diff options
-rw-r--r-- | system/easy-kernel/0000-README | 4 | ||||
-rw-r--r-- | system/easy-kernel/0100-linux-5.15.11.patch | 80405 | ||||
-rw-r--r-- | system/easy-kernel/0100-linux-5.15.28.patch | 174425 | ||||
-rw-r--r-- | system/easy-kernel/0200-x86-compile.patch | 11 | ||||
-rw-r--r-- | system/easy-kernel/0250-projectc-5.15-r1.patch | 2 | ||||
-rw-r--r-- | system/easy-kernel/1000-version.patch | 2 | ||||
-rw-r--r-- | system/easy-kernel/APKBUILD | 14 | ||||
-rw-r--r-- | system/easy-kernel/config-ppc64 | 4 |
8 files changed, 174452 insertions, 80415 deletions
diff --git a/system/easy-kernel/0000-README b/system/easy-kernel/0000-README index a59328389..07d3c4979 100644 --- a/system/easy-kernel/0000-README +++ b/system/easy-kernel/0000-README @@ -48,6 +48,10 @@ File: 0130-lrng.patch From: https://github.com/smuellerDD/lrng Desc: An ABI- and API- compatible replacement for the Linux /dev/random implementation focused on security, performance, and correctness. +File: 0200-x86-compile.patch +From: Laurent Bercot <ska-adelie@skarnet.org> +Desc: Make x86 kernels compile without glibc-specific tools. + File: 0250-projectc-5.15-r1.patch From: https://gitlab.com/alfredchen/linux-prjc Desc: "Project C", incorporating the PDQ scheduler descended from ck's Brain Fuck Scheduler diff --git a/system/easy-kernel/0100-linux-5.15.11.patch b/system/easy-kernel/0100-linux-5.15.11.patch deleted file mode 100644 index 5f2c26f1a..000000000 --- a/system/easy-kernel/0100-linux-5.15.11.patch +++ /dev/null @@ -1,80405 +0,0 @@ -diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt -index 43dc35fe5bc03..1396fd2d90319 100644 ---- a/Documentation/admin-guide/kernel-parameters.txt -+++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -6349,6 +6349,13 @@ - improve timer resolution at the expense of processing - more timer interrupts. - -+ xen.balloon_boot_timeout= [XEN] -+ The time (in seconds) to wait before giving up to boot -+ in case initial ballooning fails to free enough memory. -+ Applies only when running as HVM or PVH guest and -+ started with less memory configured than allowed at -+ max. Default is 180. -+ - xen.event_eoi_delay= [XEN] - How long to delay EOI handling in case of event - storms (jiffies). Default is 10. -diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst -index 426162009ce99..0e486f41185ef 100644 ---- a/Documentation/admin-guide/sysctl/kernel.rst -+++ b/Documentation/admin-guide/sysctl/kernel.rst -@@ -1099,7 +1099,7 @@ task_delayacct - =============== - - Enables/disables task delay accounting (see --:doc:`accounting/delay-accounting.rst`). Enabling this feature incurs -+Documentation/accounting/delay-accounting.rst. Enabling this feature incurs - a small amount of overhead in the scheduler but is useful for debugging - and performance tuning. It is required by some tools such as iotop. - -diff --git a/Documentation/dev-tools/kfence.rst b/Documentation/dev-tools/kfence.rst -index 0fbe3308bf37f..48244d32780f6 100644 ---- a/Documentation/dev-tools/kfence.rst -+++ b/Documentation/dev-tools/kfence.rst -@@ -231,10 +231,14 @@ Guarded allocations are set up based on the sample interval. After expiration - of the sample interval, the next allocation through the main allocator (SLAB or - SLUB) returns a guarded allocation from the KFENCE object pool (allocation - sizes up to PAGE_SIZE are supported). At this point, the timer is reset, and --the next allocation is set up after the expiration of the interval. To "gate" a --KFENCE allocation through the main allocator's fast-path without overhead, --KFENCE relies on static branches via the static keys infrastructure. The static --branch is toggled to redirect the allocation to KFENCE. -+the next allocation is set up after the expiration of the interval. -+ -+When using ``CONFIG_KFENCE_STATIC_KEYS=y``, KFENCE allocations are "gated" -+through the main allocator's fast-path by relying on static branches via the -+static keys infrastructure. The static branch is toggled to redirect the -+allocation to KFENCE. Depending on sample interval, target workloads, and -+system architecture, this may perform better than the simple dynamic branch. -+Careful benchmarking is recommended. - - KFENCE objects each reside on a dedicated page, at either the left or right - page boundaries selected at random. The pages to the left and right of the -diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml -index d5c54813ce872..a8f7720d1e3e2 100644 ---- a/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml -+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml -@@ -54,7 +54,7 @@ examples: - - ad5766@0 { - compatible = "adi,ad5766"; -- output-range-microvolts = <(-5000) 5000>; -+ output-range-microvolts = <(-5000000) 5000000>; - reg = <0>; - spi-cpol; - spi-max-frequency = <1000000>; -diff --git a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml -index 877183cf42787..1ef849dc74d7e 100644 ---- a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml -+++ b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml -@@ -79,6 +79,8 @@ properties: - - properties: - data-lanes: -+ description: -+ Note that 'fsl,imx7-mipi-csi2' only supports up to 2 data lines. - items: - minItems: 1 - maxItems: 4 -@@ -91,18 +93,6 @@ properties: - required: - - data-lanes - -- allOf: -- - if: -- properties: -- compatible: -- contains: -- const: fsl,imx7-mipi-csi2 -- then: -- properties: -- data-lanes: -- items: -- maxItems: 2 -- - port@1: - $ref: /schemas/graph.yaml#/properties/port - description: -diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml -index 2766fe45bb98b..ee42328a109dc 100644 ---- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml -+++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml -@@ -91,6 +91,14 @@ properties: - compensate for the board being designed with the lanes - swapped. - -+ enet-phy-lane-no-swap: -+ $ref: /schemas/types.yaml#/definitions/flag -+ description: -+ If set, indicates that PHY will disable swap of the -+ TX/RX lanes. This property allows the PHY to work correcly after -+ e.g. wrong bootstrap configuration caused by issues in PCB -+ layout design. -+ - eee-broken-100tx: - $ref: /schemas/types.yaml#/definitions/flag - description: -diff --git a/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt b/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt -index 093edda0c8dfc..6cd83d920155f 100644 ---- a/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt -+++ b/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt -@@ -13,6 +13,14 @@ common regulator binding documented in: - - - Required properties of the main device node (the parent!): -+ - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used -+ for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines. -+ -+ [1] If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional -+ property is specified, then all the eight voltage values for the -+ 's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified. -+ -+Optional properties of the main device node (the parent!): - - s5m8767,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV) - units for buck2 when changing voltage using gpio dvs. Refer to [1] below - for additional information. -@@ -25,26 +33,13 @@ Required properties of the main device node (the parent!): - units for buck4 when changing voltage using gpio dvs. Refer to [1] below - for additional information. - -- - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used -- for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines. -- -- [1] If none of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional -- property is specified, the 's5m8767,pmic-buck[2/3/4]-dvs-voltage' -- property should specify atleast one voltage level (which would be a -- safe operating voltage). -- -- If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional -- property is specified, then all the eight voltage values for the -- 's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified. -- --Optional properties of the main device node (the parent!): - - s5m8767,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs. - - s5m8767,pmic-buck3-uses-gpio-dvs: 'buck3' can be controlled by gpio dvs. - - s5m8767,pmic-buck4-uses-gpio-dvs: 'buck4' can be controlled by gpio dvs. - - Additional properties required if either of the optional properties are used: - -- - s5m8767,pmic-buck234-default-dvs-idx: Default voltage setting selected from -+ - s5m8767,pmic-buck-default-dvs-idx: Default voltage setting selected from - the possible 8 options selectable by the dvs gpios. The value of this - property should be between 0 and 7. If not specified or if out of range, the - default value of this property is set to 0. -diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst -index 0eb799d9d05a2..7940a45d39522 100644 ---- a/Documentation/filesystems/fscrypt.rst -+++ b/Documentation/filesystems/fscrypt.rst -@@ -176,11 +176,11 @@ Master Keys - - Each encrypted directory tree is protected by a *master key*. Master - keys can be up to 64 bytes long, and must be at least as long as the --greater of the key length needed by the contents and filenames --encryption modes being used. For example, if AES-256-XTS is used for --contents encryption, the master key must be 64 bytes (512 bits). Note --that the XTS mode is defined to require a key twice as long as that --required by the underlying block cipher. -+greater of the security strength of the contents and filenames -+encryption modes being used. For example, if any AES-256 mode is -+used, the master key must be at least 256 bits, i.e. 32 bytes. A -+stricter requirement applies if the key is used by a v1 encryption -+policy and AES-256-XTS is used; such keys must be 64 bytes. - - To "unlock" an encrypted directory tree, userspace must provide the - appropriate master key. There can be any number of master keys, each -diff --git a/Documentation/locking/locktypes.rst b/Documentation/locking/locktypes.rst -index ddada4a537493..4fd7b70fcde19 100644 ---- a/Documentation/locking/locktypes.rst -+++ b/Documentation/locking/locktypes.rst -@@ -439,11 +439,9 @@ preemption. The following substitution works on both kernels:: - spin_lock(&p->lock); - p->count += this_cpu_read(var2); - --On a non-PREEMPT_RT kernel migrate_disable() maps to preempt_disable() --which makes the above code fully equivalent. On a PREEMPT_RT kernel - migrate_disable() ensures that the task is pinned on the current CPU which - in turn guarantees that the per-CPU access to var1 and var2 are staying on --the same CPU. -+the same CPU while the task remains preemptible. - - The migrate_disable() substitution is not valid for the following - scenario:: -@@ -456,9 +454,8 @@ scenario:: - p = this_cpu_ptr(&var1); - p->val = func2(); - --While correct on a non-PREEMPT_RT kernel, this breaks on PREEMPT_RT because --here migrate_disable() does not protect against reentrancy from a --preempting task. A correct substitution for this case is:: -+This breaks because migrate_disable() does not protect against reentrancy from -+a preempting task. A correct substitution for this case is:: - - func() - { -diff --git a/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst b/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst -index f1d5233e5e510..0a233b17c664e 100644 ---- a/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst -+++ b/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst -@@ -440,6 +440,22 @@ NOTE: For 82599-based network connections, if you are enabling jumbo frames in - a virtual function (VF), jumbo frames must first be enabled in the physical - function (PF). The VF MTU setting cannot be larger than the PF MTU. - -+NBASE-T Support -+--------------- -+The ixgbe driver supports NBASE-T on some devices. However, the advertisement -+of NBASE-T speeds is suppressed by default, to accommodate broken network -+switches which cannot cope with advertised NBASE-T speeds. Use the ethtool -+command to enable advertising NBASE-T speeds on devices which support it:: -+ -+ ethtool -s eth? advertise 0x1800000001028 -+ -+On Linux systems with INTERFACES(5), this can be specified as a pre-up command -+in /etc/network/interfaces so that the interface is always brought up with -+NBASE-T support, e.g.:: -+ -+ iface eth? inet dhcp -+ pre-up ethtool -s eth? advertise 0x1800000001028 || true -+ - Generic Receive Offload, aka GRO - -------------------------------- - The driver supports the in-kernel software implementation of GRO. GRO has -diff --git a/Documentation/networking/ipvs-sysctl.rst b/Documentation/networking/ipvs-sysctl.rst -index 2afccc63856ee..1cfbf1add2fc9 100644 ---- a/Documentation/networking/ipvs-sysctl.rst -+++ b/Documentation/networking/ipvs-sysctl.rst -@@ -37,8 +37,7 @@ conn_reuse_mode - INTEGER - - 0: disable any special handling on port reuse. The new - connection will be delivered to the same real server that was -- servicing the previous connection. This will effectively -- disable expire_nodest_conn. -+ servicing the previous connection. - - bit 1: enable rescheduling of new connections when it is safe. - That is, whenever expire_nodest_conn and for TCP sockets, when -diff --git a/Makefile b/Makefile -index ed6e7ec60eff6..37a1144c32df7 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,7 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - VERSION = 5 - PATCHLEVEL = 15 --SUBLEVEL = 0 -+SUBLEVEL = 11 - EXTRAVERSION = - NAME = Trick or Treat - -diff --git a/arch/Kconfig b/arch/Kconfig -index 8df1c71026435..d1e69d6e8498b 100644 ---- a/arch/Kconfig -+++ b/arch/Kconfig -@@ -1234,6 +1234,9 @@ config RELR - config ARCH_HAS_MEM_ENCRYPT - bool - -+config ARCH_HAS_CC_PLATFORM -+ bool -+ - config HAVE_SPARSE_SYSCALL_NR - bool - help -diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c -index 3793876f42d9b..8e90052f6f056 100644 ---- a/arch/arc/kernel/process.c -+++ b/arch/arc/kernel/process.c -@@ -294,7 +294,7 @@ int elf_check_arch(const struct elf32_hdr *x) - eflags = x->e_flags; - if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) { - pr_err("ABI mismatch - you need newer toolchain\n"); -- force_sigsegv(SIGSEGV); -+ force_fatal_sig(SIGSEGV); - return 0; - } - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index dcf2df6da98f0..4ebd512043be5 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -1455,6 +1455,7 @@ config HIGHMEM - bool "High Memory Support" - depends on MMU - select KMAP_LOCAL -+ select KMAP_LOCAL_NON_LINEAR_PTE_ARRAY - help - The address space of ARM processors is only 4 Gigabytes large - and it has to accommodate user address space, kernel address -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 847c31e7c3687..fa45837b8065c 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -60,15 +60,15 @@ KBUILD_CFLAGS += $(call cc-option,-fno-ipa-sra) - # Note that GCC does not numerically define an architecture version - # macro, but instead defines a whole series of macros which makes - # testing for a specific architecture or later rather impossible. --arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m --arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) --arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) -+arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m -+arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -march=armv7-a -+arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 -march=armv6 - # Only override the compiler option if ARMv6. The ARMv6K extensions are - # always available in ARMv7 - ifeq ($(CONFIG_CPU_32v6),y) --arch-$(CONFIG_CPU_32v6K) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) -+arch-$(CONFIG_CPU_32v6K) =-D__LINUX_ARM_ARCH__=6 -march=armv6k - endif --arch-$(CONFIG_CPU_32v5) =-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) -+arch-$(CONFIG_CPU_32v5) =-D__LINUX_ARM_ARCH__=5 -march=armv5te - arch-$(CONFIG_CPU_32v4T) =-D__LINUX_ARM_ARCH__=4 -march=armv4t - arch-$(CONFIG_CPU_32v4) =-D__LINUX_ARM_ARCH__=4 -march=armv4 - arch-$(CONFIG_CPU_32v3) =-D__LINUX_ARM_ARCH__=3 -march=armv3m -@@ -82,7 +82,7 @@ tune-$(CONFIG_CPU_ARM720T) =-mtune=arm7tdmi - tune-$(CONFIG_CPU_ARM740T) =-mtune=arm7tdmi - tune-$(CONFIG_CPU_ARM9TDMI) =-mtune=arm9tdmi - tune-$(CONFIG_CPU_ARM940T) =-mtune=arm9tdmi --tune-$(CONFIG_CPU_ARM946E) =$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi) -+tune-$(CONFIG_CPU_ARM946E) =-mtune=arm9e - tune-$(CONFIG_CPU_ARM920T) =-mtune=arm9tdmi - tune-$(CONFIG_CPU_ARM922T) =-mtune=arm9tdmi - tune-$(CONFIG_CPU_ARM925T) =-mtune=arm9tdmi -@@ -90,11 +90,11 @@ tune-$(CONFIG_CPU_ARM926T) =-mtune=arm9tdmi - tune-$(CONFIG_CPU_FA526) =-mtune=arm9tdmi - tune-$(CONFIG_CPU_SA110) =-mtune=strongarm110 - tune-$(CONFIG_CPU_SA1100) =-mtune=strongarm1100 --tune-$(CONFIG_CPU_XSCALE) =$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale --tune-$(CONFIG_CPU_XSC3) =$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale --tune-$(CONFIG_CPU_FEROCEON) =$(call cc-option,-mtune=marvell-f,-mtune=xscale) --tune-$(CONFIG_CPU_V6) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) --tune-$(CONFIG_CPU_V6K) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) -+tune-$(CONFIG_CPU_XSCALE) =-mtune=xscale -+tune-$(CONFIG_CPU_XSC3) =-mtune=xscale -+tune-$(CONFIG_CPU_FEROCEON) =-mtune=xscale -+tune-$(CONFIG_CPU_V6) =-mtune=arm1136j-s -+tune-$(CONFIG_CPU_V6K) =-mtune=arm1136j-s - - # Evaluate tune cc-option calls now - tune-y := $(tune-y) -diff --git a/arch/arm/boot/dts/at91-tse850-3.dts b/arch/arm/boot/dts/at91-tse850-3.dts -index 3ca97b47c69ce..7e5c598e7e68f 100644 ---- a/arch/arm/boot/dts/at91-tse850-3.dts -+++ b/arch/arm/boot/dts/at91-tse850-3.dts -@@ -262,7 +262,7 @@ - &macb1 { - status = "okay"; - -- phy-mode = "rgmii"; -+ phy-mode = "rmii"; - - #address-cells = <1>; - #size-cells = <0>; -diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi -index 748df7955ae67..e96ddb2e26e2c 100644 ---- a/arch/arm/boot/dts/bcm-nsp.dtsi -+++ b/arch/arm/boot/dts/bcm-nsp.dtsi -@@ -77,7 +77,7 @@ - interrupt-affinity = <&cpu0>, <&cpu1>; - }; - -- mpcore@19000000 { -+ mpcore-bus@19000000 { - compatible = "simple-bus"; - ranges = <0x00000000 0x19000000 0x00023000>; - #address-cells = <1>; -@@ -219,7 +219,7 @@ - status = "disabled"; - }; - -- sdio: sdhci@21000 { -+ sdio: mmc@21000 { - compatible = "brcm,sdhci-iproc-cygnus"; - reg = <0x21000 0x100>; - interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>; -diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi -index 3b60297af7f60..9e01dbca4a011 100644 ---- a/arch/arm/boot/dts/bcm2711.dtsi -+++ b/arch/arm/boot/dts/bcm2711.dtsi -@@ -506,11 +506,17 @@ - #address-cells = <3>; - #interrupt-cells = <1>; - #size-cells = <2>; -- interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, -+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "pcie", "msi"; - interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 -+ IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &gicv2 GIC_SPI 144 -+ IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &gicv2 GIC_SPI 145 -+ IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &gicv2 GIC_SPI 146 - IRQ_TYPE_LEVEL_HIGH>; - msi-controller; - msi-parent = <&pcie0>; -diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -index 61c7b137607e5..7900aac4f35a9 100644 ---- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -20,7 +20,7 @@ - bootargs = "console=ttyS0,115200 earlycon"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x08000000>; -diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts -index 6c6bb7b17d27a..7546c8d07bcd7 100644 ---- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts -+++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts -@@ -19,7 +19,7 @@ - bootargs = "console=ttyS0,115200"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x08000000>; -diff --git a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts -index d29e7f80ea6aa..beae9eab9cb8c 100644 ---- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts -+++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts -@@ -19,7 +19,7 @@ - bootargs = "console=ttyS0,115200"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x18000000>; -diff --git a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts -index 9b6887d477d86..7879f7d7d9c33 100644 ---- a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts -+++ b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts -@@ -16,7 +16,7 @@ - bootargs = "console=ttyS0,115200"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x08000000>; -diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts -index 7989a53597d4f..56d309dbc6b0d 100644 ---- a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts -+++ b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts -@@ -19,7 +19,7 @@ - bootargs = "console=ttyS0,115200"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x08000000>; -diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -index 87b655be674c5..184e3039aa864 100644 ---- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -+++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -@@ -30,7 +30,7 @@ - bootargs = "console=ttyS0,115200"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x08000000>; -diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts -index f806be5da7237..c2a266a439d05 100644 ---- a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts -+++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts -@@ -15,7 +15,7 @@ - bootargs = "console=ttyS0,115200 earlycon"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>; - }; -diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts -index 05d4f2931772b..9bef6b9bfa8d9 100644 ---- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts -+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts -@@ -129,7 +129,7 @@ - }; - }; - -- mdio-bus-mux@18003000 { -+ mdio-mux@18003000 { - - /* BIT(9) = 1 => external mdio */ - mdio@200 { -diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts b/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts -index 452b8d0ab180e..b0d8a688141d3 100644 ---- a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts -+++ b/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts -@@ -16,7 +16,7 @@ - bootargs = "earlycon"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>, - <0x88000000 0x18000000>; -diff --git a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts -index 3b978dc8997a4..577a4dc604d93 100644 ---- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts -+++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts -@@ -20,7 +20,7 @@ - bootargs = " console=ttyS0,115200n8 earlycon"; - }; - -- memory { -+ memory@0 { - reg = <0x00000000 0x08000000>; - device_type = "memory"; - }; -@@ -195,3 +195,25 @@ - }; - }; - }; -+ -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ reg = <0>; -+ label = "poe"; -+ }; -+ -+ port@5 { -+ reg = <5>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ -+ fixed-link { -+ speed = <1000>; -+ duplex-full; -+ }; -+ }; -+ }; -+}; -diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi -index f92089290ccd5..f69d2af3c1fa4 100644 ---- a/arch/arm/boot/dts/bcm5301x.dtsi -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -19,7 +19,7 @@ - #size-cells = <1>; - interrupt-parent = <&gic>; - -- chipcommonA@18000000 { -+ chipcommon-a-bus@18000000 { - compatible = "simple-bus"; - ranges = <0x00000000 0x18000000 0x00001000>; - #address-cells = <1>; -@@ -44,7 +44,7 @@ - }; - }; - -- mpcore@19000000 { -+ mpcore-bus@19000000 { - compatible = "simple-bus"; - ranges = <0x00000000 0x19000000 0x00023000>; - #address-cells = <1>; -@@ -242,6 +242,8 @@ - - gpio-controller; - #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; - }; - - pcie0: pcie@12000 { -@@ -369,8 +371,8 @@ - #address-cells = <1>; - }; - -- mdio-bus-mux@18003000 { -- compatible = "mdio-mux-mmioreg"; -+ mdio-mux@18003000 { -+ compatible = "mdio-mux-mmioreg", "mdio-mux"; - mdio-parent-bus = <&mdio>; - #address-cells = <1>; - #size-cells = <0>; -@@ -408,14 +410,14 @@ - i2c0: i2c@18009000 { - compatible = "brcm,iproc-i2c"; - reg = <0x18009000 0x50>; -- interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>; -+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <0>; - clock-frequency = <100000>; - status = "disabled"; - }; - -- dmu@1800c000 { -+ dmu-bus@1800c000 { - compatible = "simple-bus"; - ranges = <0 0x1800c000 0x1000>; - #address-cells = <1>; -diff --git a/arch/arm/boot/dts/bcm94708.dts b/arch/arm/boot/dts/bcm94708.dts -index 3d13e46c69494..d9eb2040b9631 100644 ---- a/arch/arm/boot/dts/bcm94708.dts -+++ b/arch/arm/boot/dts/bcm94708.dts -@@ -38,7 +38,7 @@ - model = "NorthStar SVK (BCM94708)"; - compatible = "brcm,bcm94708", "brcm,bcm4708"; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>; - }; -diff --git a/arch/arm/boot/dts/bcm94709.dts b/arch/arm/boot/dts/bcm94709.dts -index 5017b7b259cbe..618c812eef73e 100644 ---- a/arch/arm/boot/dts/bcm94709.dts -+++ b/arch/arm/boot/dts/bcm94709.dts -@@ -38,7 +38,7 @@ - model = "NorthStar SVK (BCM94709)"; - compatible = "brcm,bcm94709", "brcm,bcm4709", "brcm,bcm4708"; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>; - }; -diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h -index eb025a9d47592..7328d4ef8559f 100644 ---- a/arch/arm/boot/dts/imx6ull-pinfunc.h -+++ b/arch/arm/boot/dts/imx6ull-pinfunc.h -@@ -82,6 +82,6 @@ - #define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS 0x01F4 0x0480 0x0000 0x9 0x0 - #define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK 0x01F8 0x0484 0x0000 0x9 0x0 - #define MX6ULL_PAD_CSI_DATA06__ESAI_TX5_RX0 0x01FC 0x0488 0x0000 0x9 0x0 --#define MX6ULL_PAD_CSI_DATA07__ESAI_T0 0x0200 0x048C 0x0000 0x9 0x0 -+#define MX6ULL_PAD_CSI_DATA07__ESAI_TX0 0x0200 0x048C 0x0000 0x9 0x0 - - #endif /* __DTS_IMX6ULL_PINFUNC_H */ -diff --git a/arch/arm/boot/dts/ls1021a-tsn.dts b/arch/arm/boot/dts/ls1021a-tsn.dts -index 9d8f0c2a8aba3..aca78b5eddf20 100644 ---- a/arch/arm/boot/dts/ls1021a-tsn.dts -+++ b/arch/arm/boot/dts/ls1021a-tsn.dts -@@ -251,7 +251,7 @@ - - flash@0 { - /* Rev. A uses 64MB flash, Rev. B & C use 32MB flash */ -- compatible = "jedec,spi-nor", "s25fl256s1", "s25fl512s"; -+ compatible = "jedec,spi-nor"; - spi-max-frequency = <20000000>; - #address-cells = <1>; - #size-cells = <1>; -diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi -index 4fce81422943b..f3b8540750b61 100644 ---- a/arch/arm/boot/dts/ls1021a.dtsi -+++ b/arch/arm/boot/dts/ls1021a.dtsi -@@ -329,39 +329,6 @@ - #thermal-sensor-cells = <1>; - }; - -- thermal-zones { -- cpu_thermal: cpu-thermal { -- polling-delay-passive = <1000>; -- polling-delay = <5000>; -- -- thermal-sensors = <&tmu 0>; -- -- trips { -- cpu_alert: cpu-alert { -- temperature = <85000>; -- hysteresis = <2000>; -- type = "passive"; -- }; -- cpu_crit: cpu-crit { -- temperature = <95000>; -- hysteresis = <2000>; -- type = "critical"; -- }; -- }; -- -- cooling-maps { -- map0 { -- trip = <&cpu_alert>; -- cooling-device = -- <&cpu0 THERMAL_NO_LIMIT -- THERMAL_NO_LIMIT>, -- <&cpu1 THERMAL_NO_LIMIT -- THERMAL_NO_LIMIT>; -- }; -- }; -- }; -- }; -- - dspi0: spi@2100000 { - compatible = "fsl,ls1021a-v1.0-dspi"; - #address-cells = <1>; -@@ -1016,4 +983,37 @@ - big-endian; - }; - }; -+ -+ thermal-zones { -+ cpu_thermal: cpu-thermal { -+ polling-delay-passive = <1000>; -+ polling-delay = <5000>; -+ -+ thermal-sensors = <&tmu 0>; -+ -+ trips { -+ cpu_alert: cpu-alert { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ cpu_crit: cpu-crit { -+ temperature = <95000>; -+ hysteresis = <2000>; -+ type = "critical"; -+ }; -+ }; -+ -+ cooling-maps { -+ map0 { -+ trip = <&cpu_alert>; -+ cooling-device = -+ <&cpu0 THERMAL_NO_LIMIT -+ THERMAL_NO_LIMIT>, -+ <&cpu1 THERMAL_NO_LIMIT -+ THERMAL_NO_LIMIT>; -+ }; -+ }; -+ }; -+ }; - }; -diff --git a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi -index 7f6aefd134514..e7534fe9c53cf 100644 ---- a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi -+++ b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi -@@ -29,7 +29,7 @@ - compatible = "smsc,lan9221","smsc,lan9115"; - bank-width = <2>; - -- gpmc,mux-add-data; -+ gpmc,mux-add-data = <0>; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <42>; - gpmc,cs-wr-off-ns = <36>; -diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi -index 938cc691bb2fe..23ab27fe4ee5d 100644 ---- a/arch/arm/boot/dts/omap3-gta04.dtsi -+++ b/arch/arm/boot/dts/omap3-gta04.dtsi -@@ -515,7 +515,7 @@ - compatible = "bosch,bma180"; - reg = <0x41>; - pinctrl-names = "default"; -- pintcrl-0 = <&bma180_pins>; -+ pinctrl-0 = <&bma180_pins>; - interrupt-parent = <&gpio4>; - interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; /* GPIO_115 */ - }; -diff --git a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi -index e5da3bc6f1050..218a10c0d8159 100644 ---- a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi -+++ b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi -@@ -22,7 +22,7 @@ - compatible = "smsc,lan9221","smsc,lan9115"; - bank-width = <2>; - -- gpmc,mux-add-data; -+ gpmc,mux-add-data = <0>; - gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <42>; - gpmc,cs-wr-off-ns = <36>; -diff --git a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts -index f7ea2e5dd1914..971d2e2292600 100644 ---- a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts -+++ b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts -@@ -19,12 +19,12 @@ - stdout-path = "serial0:115200n8"; - }; - -- memory@0 { -+ memory@42000000 { - reg = <0x42000000 0x3e000000>; - device_type = "memory"; - }; - -- mdio0: mdio@0 { -+ mdio0: mdio-0 { - status = "okay"; - compatible = "virtual,mdio-gpio"; - gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>, -@@ -91,7 +91,7 @@ - }; - }; - -- mdio1: mdio@1 { -+ mdio1: mdio-1 { - status = "okay"; - compatible = "virtual,mdio-gpio"; - gpios = <&qcom_pinmux 11 GPIO_ACTIVE_HIGH>, -diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi -index 78ec496d5bc30..2b01bc29ddf23 100644 ---- a/arch/arm/boot/dts/qcom-msm8974.dtsi -+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi -@@ -1589,8 +1589,8 @@ - #phy-cells = <0>; - qcom,dsi-phy-index = <0>; - -- clocks = <&mmcc MDSS_AHB_CLK>; -- clock-names = "iface"; -+ clocks = <&mmcc MDSS_AHB_CLK>, <&xo_board>; -+ clock-names = "iface", "ref"; - }; - }; - -diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts -index 2b645642b9352..2a745522404d6 100644 ---- a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts -+++ b/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts -@@ -12,7 +12,7 @@ - flash0: n25q00@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q00aa"; -+ compatible = "micron,mt25qu02g", "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <100000000>; - -diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/socfpga_arria5_socdk.dts -index 90e676e7019f2..1b02d46496a85 100644 ---- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts -+++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts -@@ -119,7 +119,7 @@ - flash: flash@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q256a"; -+ compatible = "micron,n25q256a", "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <100000000>; - -diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts -index 6f138b2b26163..51bb436784e24 100644 ---- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts -+++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts -@@ -124,7 +124,7 @@ - flash0: n25q00@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q00"; -+ compatible = "micron,mt25qu02g", "jedec,spi-nor"; - reg = <0>; /* chip select */ - spi-max-frequency = <100000000>; - -diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts -index c155ff02eb6e0..cae9ddd5ed38b 100644 ---- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts -+++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts -@@ -169,7 +169,7 @@ - flash: flash@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q00"; -+ compatible = "micron,mt25qu02g", "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <100000000>; - -diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts -index 8d5d3996f6f27..ca18b959e6559 100644 ---- a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts -+++ b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts -@@ -80,7 +80,7 @@ - flash: flash@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q256a"; -+ compatible = "micron,n25q256a", "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <100000000>; - m25p,fast-read; -diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts -index 99a71757cdf46..3f7aa7bf0863a 100644 ---- a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts -+++ b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts -@@ -116,7 +116,7 @@ - flash0: n25q512a@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q512a"; -+ compatible = "micron,n25q512a", "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <100000000>; - -diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts -index a060718758b67..25874e1b9c829 100644 ---- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts -+++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts -@@ -224,7 +224,7 @@ - n25q128@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q128"; -+ compatible = "micron,n25q128", "jedec,spi-nor"; - reg = <0>; /* chip select */ - spi-max-frequency = <100000000>; - m25p,fast-read; -@@ -241,7 +241,7 @@ - n25q00@1 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "n25q00"; -+ compatible = "micron,mt25qu02g", "jedec,spi-nor"; - reg = <1>; /* chip select */ - spi-max-frequency = <100000000>; - m25p,fast-read; -diff --git a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts -index 264f3e9b5fce5..86e83639fadc1 100644 ---- a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts -+++ b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts -@@ -292,10 +292,10 @@ - }; - - ab8500_ldo_aux2 { -- /* Supplies the Cypress TMA140 touchscreen only with 3.3V */ -+ /* Supplies the Cypress TMA140 touchscreen only with 3.0V */ - regulator-name = "AUX2"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -+ regulator-min-microvolt = <3000000>; -+ regulator-max-microvolt = <3000000>; - }; - - ab8500_ldo_aux3 { -@@ -314,9 +314,9 @@ - - ab8500_ldo_aux5 { - regulator-name = "AUX5"; -+ /* Intended for 1V8 for touchscreen but actually left unused */ - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <2790000>; -- regulator-always-on; - }; - - ab8500_ldo_aux6 { -diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -index 5b60ecbd718f0..2ebafe27a865b 100644 ---- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -+++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi -@@ -1179,7 +1179,7 @@ - }; - }; - -- sai2a_pins_c: sai2a-4 { -+ sai2a_pins_c: sai2a-2 { - pins { - pinmux = <STM32_PINMUX('D', 13, AF10)>, /* SAI2_SCK_A */ - <STM32_PINMUX('D', 11, AF10)>, /* SAI2_SD_A */ -@@ -1190,7 +1190,7 @@ - }; - }; - -- sai2a_sleep_pins_c: sai2a-5 { -+ sai2a_sleep_pins_c: sai2a-2 { - pins { - pinmux = <STM32_PINMUX('D', 13, ANALOG)>, /* SAI2_SCK_A */ - <STM32_PINMUX('D', 11, ANALOG)>, /* SAI2_SD_A */ -@@ -1235,14 +1235,14 @@ - }; - }; - -- sai2b_pins_c: sai2a-4 { -+ sai2b_pins_c: sai2b-2 { - pins1 { - pinmux = <STM32_PINMUX('F', 11, AF10)>; /* SAI2_SD_B */ - bias-disable; - }; - }; - -- sai2b_sleep_pins_c: sai2a-sleep-5 { -+ sai2b_sleep_pins_c: sai2b-sleep-2 { - pins { - pinmux = <STM32_PINMUX('F', 11, ANALOG)>; /* SAI2_SD_B */ - }; -diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi -index bd289bf5d2690..6992a4b0ba79b 100644 ---- a/arch/arm/boot/dts/stm32mp151.dtsi -+++ b/arch/arm/boot/dts/stm32mp151.dtsi -@@ -824,7 +824,7 @@ - #sound-dai-cells = <0>; - - compatible = "st,stm32-sai-sub-a"; -- reg = <0x4 0x1c>; -+ reg = <0x4 0x20>; - clocks = <&rcc SAI1_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 87 0x400 0x01>; -@@ -834,7 +834,7 @@ - sai1b: audio-controller@4400a024 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-b"; -- reg = <0x24 0x1c>; -+ reg = <0x24 0x20>; - clocks = <&rcc SAI1_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 88 0x400 0x01>; -@@ -855,7 +855,7 @@ - sai2a: audio-controller@4400b004 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-a"; -- reg = <0x4 0x1c>; -+ reg = <0x4 0x20>; - clocks = <&rcc SAI2_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 89 0x400 0x01>; -@@ -865,7 +865,7 @@ - sai2b: audio-controller@4400b024 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-b"; -- reg = <0x24 0x1c>; -+ reg = <0x24 0x20>; - clocks = <&rcc SAI2_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 90 0x400 0x01>; -@@ -886,7 +886,7 @@ - sai3a: audio-controller@4400c004 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-a"; -- reg = <0x04 0x1c>; -+ reg = <0x04 0x20>; - clocks = <&rcc SAI3_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 113 0x400 0x01>; -@@ -896,7 +896,7 @@ - sai3b: audio-controller@4400c024 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-b"; -- reg = <0x24 0x1c>; -+ reg = <0x24 0x20>; - clocks = <&rcc SAI3_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 114 0x400 0x01>; -@@ -1271,7 +1271,7 @@ - sai4a: audio-controller@50027004 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-a"; -- reg = <0x04 0x1c>; -+ reg = <0x04 0x20>; - clocks = <&rcc SAI4_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 99 0x400 0x01>; -@@ -1281,7 +1281,7 @@ - sai4b: audio-controller@50027024 { - #sound-dai-cells = <0>; - compatible = "st,stm32-sai-sub-b"; -- reg = <0x24 0x1c>; -+ reg = <0x24 0x20>; - clocks = <&rcc SAI4_K>; - clock-names = "sai_ck"; - dmas = <&dmamux1 100 0x400 0x01>; -diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi -index 2b0ac605549d7..44ecc47085871 100644 ---- a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi -+++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi -@@ -202,7 +202,7 @@ - compatible = "jedec,spi-nor"; - reg = <0>; - spi-rx-bus-width = <4>; -- spi-max-frequency = <108000000>; -+ spi-max-frequency = <50000000>; - #address-cells = <1>; - #size-cells = <1>; - }; -diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi -index 899bfe04aeb91..48beed0f1f30a 100644 ---- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi -+++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi -@@ -249,7 +249,7 @@ - stusb1600@28 { - compatible = "st,stusb1600"; - reg = <0x28>; -- interrupts = <11 IRQ_TYPE_EDGE_FALLING>; -+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>; - interrupt-parent = <&gpioi>; - pinctrl-names = "default"; - pinctrl-0 = <&stusb1600_pins_a>; -diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi -index 2beddbb3c5183..b3d1bdfb5118e 100644 ---- a/arch/arm/boot/dts/sun8i-a33.dtsi -+++ b/arch/arm/boot/dts/sun8i-a33.dtsi -@@ -46,7 +46,7 @@ - #include <dt-bindings/thermal/thermal.h> - - / { -- cpu0_opp_table: opp_table0 { -+ cpu0_opp_table: opp-table-cpu { - compatible = "operating-points-v2"; - opp-shared; - -@@ -164,7 +164,7 @@ - io-channels = <&ths>; - }; - -- mali_opp_table: gpu-opp-table { -+ mali_opp_table: opp-table-gpu { - compatible = "operating-points-v2"; - - opp-144000000 { -diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi -index ac97eac91349b..82fdb04122caa 100644 ---- a/arch/arm/boot/dts/sun8i-a83t.dtsi -+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi -@@ -200,7 +200,7 @@ - status = "disabled"; - }; - -- cpu0_opp_table: opp_table0 { -+ cpu0_opp_table: opp-table-cluster0 { - compatible = "operating-points-v2"; - opp-shared; - -@@ -253,7 +253,7 @@ - }; - }; - -- cpu1_opp_table: opp_table1 { -+ cpu1_opp_table: opp-table-cluster1 { - compatible = "operating-points-v2"; - opp-shared; - -diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi -index 4e89701df91f8..ae4f933abb895 100644 ---- a/arch/arm/boot/dts/sun8i-h3.dtsi -+++ b/arch/arm/boot/dts/sun8i-h3.dtsi -@@ -44,7 +44,7 @@ - #include <dt-bindings/thermal/thermal.h> - - / { -- cpu0_opp_table: opp_table0 { -+ cpu0_opp_table: opp-table-cpu { - compatible = "operating-points-v2"; - opp-shared; - -@@ -112,7 +112,7 @@ - }; - }; - -- gpu_opp_table: gpu-opp-table { -+ gpu_opp_table: opp-table-gpu { - compatible = "operating-points-v2"; - - opp-120000000 { -diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c -index 76ea4178a55cb..db798eac74315 100644 ---- a/arch/arm/kernel/stacktrace.c -+++ b/arch/arm/kernel/stacktrace.c -@@ -54,8 +54,7 @@ int notrace unwind_frame(struct stackframe *frame) - - frame->sp = frame->fp; - frame->fp = *(unsigned long *)(fp); -- frame->pc = frame->lr; -- frame->lr = *(unsigned long *)(fp + 4); -+ frame->pc = *(unsigned long *)(fp + 4); - #else - /* check current frame pointer is within bounds */ - if (fp < low + 12 || fp > high - 4) -diff --git a/arch/arm/mach-s3c/irq-s3c24xx.c b/arch/arm/mach-s3c/irq-s3c24xx.c -index 3edc5f614eefc..c1c2f041ad3b1 100644 ---- a/arch/arm/mach-s3c/irq-s3c24xx.c -+++ b/arch/arm/mach-s3c/irq-s3c24xx.c -@@ -361,11 +361,25 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, - static asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs) - { - do { -- if (likely(s3c_intc[0])) -- if (s3c24xx_handle_intc(s3c_intc[0], regs, 0)) -- continue; -+ /* -+ * For platform based machines, neither ERR nor NULL can happen here. -+ * The s3c24xx_handle_irq() will be set as IRQ handler iff this succeeds: -+ * -+ * s3c_intc[0] = s3c24xx_init_intc() -+ * -+ * If this fails, the next calls to s3c24xx_init_intc() won't be executed. -+ * -+ * For DT machine, s3c_init_intc_of() could set the IRQ handler without -+ * setting s3c_intc[0] only if it was called with num_ctrl=0. There is no -+ * such code path, so again the s3c_intc[0] will have a valid pointer if -+ * set_handle_irq() is called. -+ * -+ * Therefore in s3c24xx_handle_irq(), the s3c_intc[0] is always something. -+ */ -+ if (s3c24xx_handle_intc(s3c_intc[0], regs, 0)) -+ continue; - -- if (s3c_intc[2]) -+ if (!IS_ERR_OR_NULL(s3c_intc[2])) - if (s3c24xx_handle_intc(s3c_intc[2], regs, 64)) - continue; - -diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h -index fc2608b18a0d0..18f01190dcfd4 100644 ---- a/arch/arm/mach-socfpga/core.h -+++ b/arch/arm/mach-socfpga/core.h -@@ -33,7 +33,7 @@ extern void __iomem *sdr_ctl_base_addr; - u32 socfpga_sdram_self_refresh(u32 sdr_base); - extern unsigned int socfpga_sdram_self_refresh_sz; - --extern char secondary_trampoline, secondary_trampoline_end; -+extern char secondary_trampoline[], secondary_trampoline_end[]; - - extern unsigned long socfpga_cpu1start_addr; - -diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c -index fbb80b883e5dd..201191cf68f32 100644 ---- a/arch/arm/mach-socfpga/platsmp.c -+++ b/arch/arm/mach-socfpga/platsmp.c -@@ -20,14 +20,14 @@ - - static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) - { -- int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; -+ int trampoline_size = secondary_trampoline_end - secondary_trampoline; - - if (socfpga_cpu1start_addr) { - /* This will put CPU #1 into reset. */ - writel(RSTMGR_MPUMODRST_CPU1, - rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST); - -- memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); -+ memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size); - - writel(__pa_symbol(secondary_startup), - sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff)); -@@ -45,12 +45,12 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) - - static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle) - { -- int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; -+ int trampoline_size = secondary_trampoline_end - secondary_trampoline; - - if (socfpga_cpu1start_addr) { - writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr + - SOCFPGA_A10_RSTMGR_MODMPURST); -- memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); -+ memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size); - - writel(__pa_symbol(secondary_startup), - sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff)); -diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index 8355c38958942..82aa990c4180c 100644 ---- a/arch/arm/mm/Kconfig -+++ b/arch/arm/mm/Kconfig -@@ -750,7 +750,7 @@ config CPU_BIG_ENDIAN - config CPU_ENDIAN_BE8 - bool - depends on CPU_BIG_ENDIAN -- default CPU_V6 || CPU_V6K || CPU_V7 -+ default CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M - help - Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors. - -diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c -index 9c348042a7244..4b1619584b23c 100644 ---- a/arch/arm/mm/kasan_init.c -+++ b/arch/arm/mm/kasan_init.c -@@ -226,7 +226,7 @@ void __init kasan_init(void) - BUILD_BUG_ON(pgd_index(KASAN_SHADOW_START) != - pgd_index(KASAN_SHADOW_END)); - memcpy(tmp_pmd_table, -- pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_START)), -+ (void*)pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_START)), - sizeof(tmp_pmd_table)); - set_pgd(&tmp_pgd_table[pgd_index(KASAN_SHADOW_START)], - __pgd(__pa(tmp_pmd_table) | PMD_TYPE_TABLE | L_PGD_SWAPPER)); -diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c -index a4e0060051070..274e4f73fd33c 100644 ---- a/arch/arm/mm/mmu.c -+++ b/arch/arm/mm/mmu.c -@@ -390,9 +390,9 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) - BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) < FIXADDR_START); - BUG_ON(idx >= __end_of_fixed_addresses); - -- /* we only support device mappings until pgprot_kernel has been set */ -+ /* We support only device mappings before pgprot_kernel is set. */ - if (WARN_ON(pgprot_val(prot) != pgprot_val(FIXMAP_PAGE_IO) && -- pgprot_val(pgprot_kernel) == 0)) -+ pgprot_val(prot) && pgprot_val(pgprot_kernel) == 0)) - return; - - if (pgprot_val(prot)) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi -index cc321c04f1219..f6d7d7f7fdabe 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi -@@ -343,19 +343,19 @@ - }; - - thermal-zones { -- cpu-thermal-zone { -+ cpu-thermal { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&ths 0>; - }; - -- ddr-thermal-zone { -+ ddr-thermal { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&ths 2>; - }; - -- gpu-thermal-zone { -+ gpu-thermal { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&ths 1>; -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi -index 578c37490d901..e39db51eb4489 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi -@@ -4,7 +4,7 @@ - */ - - / { -- cpu0_opp_table: opp_table0 { -+ cpu0_opp_table: opp-table-cpu { - compatible = "operating-points-v2"; - opp-shared; - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi -index b2657201957eb..1afad8b437d72 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi -@@ -2,7 +2,7 @@ - // Copyright (C) 2020 Chen-Yu Tsai <wens@csie.org> - - / { -- cpu_opp_table: cpu-opp-table { -+ cpu_opp_table: opp-table-cpu { - compatible = "operating-points-v2"; - opp-shared; - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -index 578a63dedf466..9988e87ea7b3d 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -@@ -217,7 +217,7 @@ - }; - }; - -- gpu_thermal { -+ gpu-thermal { - polling-delay-passive = <0>; - polling-delay = <0>; - thermal-sensors = <&ths 1>; -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi -index 8c6e8536b69fa..0baf0f8e4d272 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi -@@ -3,7 +3,7 @@ - // Copyright (C) 2020 Clément Péron <peron.clem@gmail.com> - - / { -- cpu_opp_table: cpu-opp-table { -+ cpu_opp_table: opp-table-cpu { - compatible = "allwinner,sun50i-h6-operating-points"; - nvmem-cells = <&cpu_speed_grade>; - opp-shared; -diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts -index 81269ccc24968..d8838dde0f0f4 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts -+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts -@@ -139,7 +139,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&dc_in>; -+ pwm-supply = <&dc_in>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts -index a26bfe72550fe..4b5d11e56364d 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts -+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts -@@ -139,7 +139,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&main_12v>; -+ pwm-supply = <&main_12v>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts -index 579f3d02d613e..b4e86196e3468 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts -+++ b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts -@@ -139,7 +139,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&dc_in>; -+ pwm-supply = <&dc_in>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi -index f42cf4b8af2d4..16dd409051b40 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi -+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi -@@ -18,7 +18,7 @@ - regulator-min-microvolt = <690000>; - regulator-max-microvolt = <1050000>; - -- vin-supply = <&dc_in>; -+ pwm-supply = <&dc_in>; - - pwms = <&pwm_ab 0 1250 0>; - pwm-dutycycle-range = <100 0>; -@@ -37,7 +37,7 @@ - regulator-min-microvolt = <690000>; - regulator-max-microvolt = <1050000>; - -- vin-supply = <&vsys_3v3>; -+ pwm-supply = <&vsys_3v3>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi -index 344573e157a7b..4f33820aba1f1 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi -+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi -@@ -130,7 +130,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&main_12v>; -+ pwm-supply = <&main_12v>; - - pwms = <&pwm_ab 0 1250 0>; - pwm-dutycycle-range = <100 0>; -@@ -149,7 +149,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&main_12v>; -+ pwm-supply = <&main_12v>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi -index feb0885047400..b40d2c1002c92 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi -+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi -@@ -96,7 +96,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&main_12v>; -+ pwm-supply = <&main_12v>; - - pwms = <&pwm_ab 0 1250 0>; - pwm-dutycycle-range = <100 0>; -@@ -115,7 +115,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&main_12v>; -+ pwm-supply = <&main_12v>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts -index effaa138b5f98..212c6aa5a3b86 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts -+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts -@@ -173,7 +173,7 @@ - regulator-min-microvolt = <690000>; - regulator-max-microvolt = <1050000>; - -- vin-supply = <&dc_in>; -+ pwm-supply = <&dc_in>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts -index f2c0981435944..9c0b544e22098 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts -+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts -@@ -24,7 +24,7 @@ - regulator-min-microvolt = <690000>; - regulator-max-microvolt = <1050000>; - -- vin-supply = <&vsys_3v3>; -+ pwm-supply = <&vsys_3v3>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi -index fd0ad85c165ba..5779e70caccd3 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi -+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi -@@ -116,7 +116,7 @@ - regulator-min-microvolt = <721000>; - regulator-max-microvolt = <1022000>; - -- vin-supply = <&main_12v>; -+ pwm-supply = <&main_12v>; - - pwms = <&pwm_AO_cd 1 1250 0>; - pwm-dutycycle-range = <100 0>; -@@ -263,6 +263,10 @@ - reg = <0>; - max-speed = <1000>; - -+ reset-assert-us = <10000>; -+ reset-deassert-us = <80000>; -+ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; -+ - interrupt-parent = <&gpio_intc>; - /* MAC_INTR on GPIOZ_14 */ - interrupts = <26 IRQ_TYPE_LEVEL_LOW>; -diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts -index 2194a778973f1..427475846fc70 100644 ---- a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts -+++ b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts -@@ -185,7 +185,7 @@ - regulator-min-microvolt = <690000>; - regulator-max-microvolt = <1050000>; - -- vin-supply = <&dc_in>; -+ pwm-supply = <&dc_in>; - - pwms = <&pwm_AO_cd 1 1500 0>; - pwm-dutycycle-range = <100 0>; -diff --git a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi -index a5a64d17d9ea6..5118816b1ed76 100644 ---- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi -+++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi -@@ -292,7 +292,7 @@ - reg = <0x640 0x18>; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&periph_clk>; -- clock-names = "periph"; -+ clock-names = "refclk"; - status = "okay"; - }; - -@@ -326,12 +326,12 @@ - #reset-cells = <1>; - }; - }; -+ }; - -- reboot { -- compatible = "syscon-reboot"; -- regmap = <&timer>; -- offset = <0x34>; -- mask = <1>; -- }; -+ reboot { -+ compatible = "syscon-reboot"; -+ regmap = <&timer>; -+ offset = <0x34>; -+ mask = <1>; - }; - }; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -index 79f155dedb2d0..e662677a6e28f 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -@@ -15,6 +15,7 @@ - compatible = "fsl,ls1012a-rdb", "fsl,ls1012a"; - - aliases { -+ serial0 = &duart0; - mmc0 = &esdhc0; - mmc1 = &esdhc1; - }; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts -index 3063851c2fb91..d3f03dcbb8c38 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts -@@ -38,7 +38,6 @@ - powerdn { - label = "External Power Down"; - gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; -- interrupts = <&gpio1 17 IRQ_TYPE_EDGE_FALLING>; - linux,code = <KEY_POWER>; - }; - -@@ -46,7 +45,6 @@ - admin { - label = "ADMIN button"; - gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>; -- interrupts = <&gpio3 8 IRQ_TYPE_EDGE_RISING>; - linux,code = <KEY_WPS_BUTTON>; - }; - }; -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi -index f85e437f80b73..6050723172436 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi -@@ -847,7 +847,7 @@ - }; - - cluster1_core0_watchdog: wdt@c000000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc000000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -857,7 +857,7 @@ - }; - - cluster1_core1_watchdog: wdt@c010000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc010000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -867,7 +867,7 @@ - }; - - cluster1_core2_watchdog: wdt@c020000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc020000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -877,7 +877,7 @@ - }; - - cluster1_core3_watchdog: wdt@c030000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc030000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -887,7 +887,7 @@ - }; - - cluster2_core0_watchdog: wdt@c100000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc100000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -897,7 +897,7 @@ - }; - - cluster2_core1_watchdog: wdt@c110000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc110000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -907,7 +907,7 @@ - }; - - cluster2_core2_watchdog: wdt@c120000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc120000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -@@ -917,7 +917,7 @@ - }; - - cluster2_core3_watchdog: wdt@c130000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc130000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(16)>, -diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi -index 801ba9612d361..1282b61da8a55 100644 ---- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi -@@ -387,7 +387,7 @@ - }; - - cluster1_core0_watchdog: wdt@c000000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc000000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -397,7 +397,7 @@ - }; - - cluster1_core1_watchdog: wdt@c010000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc010000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -407,7 +407,7 @@ - }; - - cluster2_core0_watchdog: wdt@c100000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc100000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -417,7 +417,7 @@ - }; - - cluster2_core1_watchdog: wdt@c110000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc110000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -427,7 +427,7 @@ - }; - - cluster3_core0_watchdog: wdt@c200000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc200000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -437,7 +437,7 @@ - }; - - cluster3_core1_watchdog: wdt@c210000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc210000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -447,7 +447,7 @@ - }; - - cluster4_core0_watchdog: wdt@c300000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc300000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -@@ -457,7 +457,7 @@ - }; - - cluster4_core1_watchdog: wdt@c310000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xc310000 0x0 0x1000>; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(4)>, -diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts -index e99e7644ff392..49d7470812eef 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts -+++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts -@@ -123,8 +123,8 @@ - - ethphy: ethernet-phy@0 { - reg = <0>; -- reset-assert-us = <100>; -- reset-deassert-us = <100>; -+ reset-assert-us = <1>; -+ reset-deassert-us = <15000>; - reset-gpios = <&gpio4 27 GPIO_ACTIVE_LOW>; - }; - }; -diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -index 4066b16126552..2bc57d8f29c7f 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -@@ -524,8 +524,6 @@ - <&clk IMX8MQ_VIDEO_PLL1>, - <&clk IMX8MQ_VIDEO_PLL1_OUT>; - assigned-clock-rates = <0>, <0>, <0>, <594000000>; -- interconnects = <&noc IMX8MQ_ICM_LCDIF &noc IMX8MQ_ICS_DRAM>; -- interconnect-names = "dram"; - status = "disabled"; - - port@0 { -diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi -index 2d5c1a348716a..6eabec2602e23 100644 ---- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi -+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi -@@ -1087,7 +1087,7 @@ - }; - - watchdog0: watchdog@e8a06000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xe8a06000 0x0 0x1000>; - interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&crg_ctrl HI3660_OSC32K>, -@@ -1096,7 +1096,7 @@ - }; - - watchdog1: watchdog@e8a07000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xe8a07000 0x0 0x1000>; - interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&crg_ctrl HI3660_OSC32K>, -diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi -index dde9371dc5451..e4860b8a638ec 100644 ---- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi -+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi -@@ -840,7 +840,7 @@ - }; - - watchdog0: watchdog@f8005000 { -- compatible = "arm,sp805-wdt", "arm,primecell"; -+ compatible = "arm,sp805", "arm,primecell"; - reg = <0x0 0xf8005000 0x0 0x1000>; - interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&ao_ctrl HI6220_WDT0_PCLK>, -diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -index d2fe58e0eb7aa..7b6205c180df1 100644 ---- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi -@@ -200,7 +200,7 @@ - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <1>; -- qcom,controlled-remotely = <1>; -+ qcom,controlled-remotely; - qcom,config-pipe-trust-reg = <0>; - }; - -diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -index db333001df4d6..97f99663c132e 100644 ---- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -220,7 +220,7 @@ - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <1>; -- qcom,controlled-remotely = <1>; -+ qcom,controlled-remotely; - status = "disabled"; - }; - -diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi -index 3f85e34a8ce6f..427bb20626549 100644 ---- a/arch/arm64/boot/dts/qcom/msm8916.dtsi -+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi -@@ -445,7 +445,7 @@ - }; - }; - -- rpm_msg_ram: memory@60000 { -+ rpm_msg_ram: sram@60000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0x00060000 0x8000>; - }; -@@ -1384,11 +1384,17 @@ - lpass: audio-controller@7708000 { - status = "disabled"; - compatible = "qcom,lpass-cpu-apq8016"; -+ -+ /* -+ * Note: Unlike the name would suggest, the SEC_I2S_CLK -+ * is actually only used by Tertiary MI2S while -+ * Primary/Secondary MI2S both use the PRI_I2S_CLK. -+ */ - clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, - <&gcc GCC_ULTAUDIO_PCNOC_MPORT_CLK>, - <&gcc GCC_ULTAUDIO_PCNOC_SWAY_CLK>, - <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, -- <&gcc GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK>, -+ <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, - <&gcc GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK>, - <&gcc GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK>; - -diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi -index 986fe60dec5fb..5a9a5ed0565f6 100644 ---- a/arch/arm64/boot/dts/qcom/msm8994.dtsi -+++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi -@@ -715,7 +715,7 @@ - reg = <0xfc400000 0x2000>; - }; - -- rpm_msg_ram: memory@fc428000 { -+ rpm_msg_ram: sram@fc428000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0xfc428000 0x4000>; - }; -diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi -index 52df22ab3f6ae..f8d28dd76cfa8 100644 ---- a/arch/arm64/boot/dts/qcom/msm8996.dtsi -+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi -@@ -638,7 +638,7 @@ - }; - }; - -- rpm_msg_ram: memory@68000 { -+ rpm_msg_ram: sram@68000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0x00068000 0x6000>; - }; -diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi -index 34039b5c80175..228339f81c327 100644 ---- a/arch/arm64/boot/dts/qcom/msm8998.dtsi -+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi -@@ -308,38 +308,42 @@ - LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { - compatible = "arm,idle-state"; - idle-state-name = "little-retention"; -+ /* CPU Retention (C2D), L2 Active */ - arm,psci-suspend-param = <0x00000002>; - entry-latency-us = <81>; - exit-latency-us = <86>; -- min-residency-us = <200>; -+ min-residency-us = <504>; - }; - - LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 { - compatible = "arm,idle-state"; - idle-state-name = "little-power-collapse"; -+ /* CPU + L2 Power Collapse (C3, D4) */ - arm,psci-suspend-param = <0x40000003>; -- entry-latency-us = <273>; -- exit-latency-us = <612>; -- min-residency-us = <1000>; -+ entry-latency-us = <814>; -+ exit-latency-us = <4562>; -+ min-residency-us = <9183>; - local-timer-stop; - }; - - BIG_CPU_SLEEP_0: cpu-sleep-1-0 { - compatible = "arm,idle-state"; - idle-state-name = "big-retention"; -+ /* CPU Retention (C2D), L2 Active */ - arm,psci-suspend-param = <0x00000002>; - entry-latency-us = <79>; - exit-latency-us = <82>; -- min-residency-us = <200>; -+ min-residency-us = <1302>; - }; - - BIG_CPU_SLEEP_1: cpu-sleep-1-1 { - compatible = "arm,idle-state"; - idle-state-name = "big-power-collapse"; -+ /* CPU + L2 Power Collapse (C3, D4) */ - arm,psci-suspend-param = <0x40000003>; -- entry-latency-us = <336>; -- exit-latency-us = <525>; -- min-residency-us = <1000>; -+ entry-latency-us = <724>; -+ exit-latency-us = <2027>; -+ min-residency-us = <9419>; - local-timer-stop; - }; - }; -@@ -857,7 +861,7 @@ - reg = <0x00100000 0xb0000>; - }; - -- rpm_msg_ram: memory@778000 { -+ rpm_msg_ram: sram@778000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0x00778000 0x7000>; - }; -diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi -index f931cb0de231f..42180f1b5dbbb 100644 ---- a/arch/arm64/boot/dts/qcom/pm8916.dtsi -+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi -@@ -86,7 +86,6 @@ - rtc@6000 { - compatible = "qcom,pm8941-rtc"; - reg = <0x6000>; -- reg-names = "rtc", "alarm"; - interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; - }; - -diff --git a/arch/arm64/boot/dts/qcom/pmi8994.dtsi b/arch/arm64/boot/dts/qcom/pmi8994.dtsi -index b4ac900ab115f..a06ea9adae810 100644 ---- a/arch/arm64/boot/dts/qcom/pmi8994.dtsi -+++ b/arch/arm64/boot/dts/qcom/pmi8994.dtsi -@@ -42,7 +42,7 @@ - /* Yes, all four strings *have to* be defined or things won't work. */ - qcom,enabled-strings = <0 1 2 3>; - qcom,cabc; -- qcom,eternal-pfet; -+ qcom,external-pfet; - status = "disabled"; - }; - }; -diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi -index 339790ba585de..ca5be16479809 100644 ---- a/arch/arm64/boot/dts/qcom/qcs404.dtsi -+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi -@@ -318,7 +318,7 @@ - status = "disabled"; - }; - -- rpm_msg_ram: memory@60000 { -+ rpm_msg_ram: sram@60000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0x00060000 0x6000>; - }; -diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi -index a758e4d226122..81098aa9687ba 100644 ---- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi -+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi -@@ -33,7 +33,7 @@ ap_h1_spi: &spi0 {}; - polling-delay = <0>; - - thermal-sensors = <&pm6150_adc_tm 1>; -- sustainable-power = <814>; -+ sustainable-power = <965>; - - trips { - skin_temp_alert0: trip-point0 { -diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi -index a246dbd74cc11..b7b5264888b7c 100644 ---- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi -+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi -@@ -44,7 +44,7 @@ ap_h1_spi: &spi0 {}; - }; - - &cpu6_thermal { -- sustainable-power = <948>; -+ sustainable-power = <1124>; - }; - - &cpu7_alert0 { -@@ -56,7 +56,7 @@ ap_h1_spi: &spi0 {}; - }; - - &cpu7_thermal { -- sustainable-power = <948>; -+ sustainable-power = <1124>; - }; - - &cpu8_alert0 { -@@ -68,7 +68,7 @@ ap_h1_spi: &spi0 {}; - }; - - &cpu8_thermal { -- sustainable-power = <948>; -+ sustainable-power = <1124>; - }; - - &cpu9_alert0 { -@@ -80,7 +80,7 @@ ap_h1_spi: &spi0 {}; - }; - - &cpu9_thermal { -- sustainable-power = <948>; -+ sustainable-power = <1124>; - }; - - &gpio_keys { -diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi -index c8921e2d6480f..495c15deacb7d 100644 ---- a/arch/arm64/boot/dts/qcom/sc7180.dtsi -+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi -@@ -137,8 +137,8 @@ - cpu-idle-states = <&LITTLE_CPU_SLEEP_0 - &LITTLE_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1024>; -- dynamic-power-coefficient = <100>; -+ capacity-dmips-mhz = <415>; -+ dynamic-power-coefficient = <137>; - operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, - <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; -@@ -162,8 +162,8 @@ - cpu-idle-states = <&LITTLE_CPU_SLEEP_0 - &LITTLE_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1024>; -- dynamic-power-coefficient = <100>; -+ capacity-dmips-mhz = <415>; -+ dynamic-power-coefficient = <137>; - next-level-cache = <&L2_100>; - operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -184,8 +184,8 @@ - cpu-idle-states = <&LITTLE_CPU_SLEEP_0 - &LITTLE_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1024>; -- dynamic-power-coefficient = <100>; -+ capacity-dmips-mhz = <415>; -+ dynamic-power-coefficient = <137>; - next-level-cache = <&L2_200>; - operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -206,8 +206,8 @@ - cpu-idle-states = <&LITTLE_CPU_SLEEP_0 - &LITTLE_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1024>; -- dynamic-power-coefficient = <100>; -+ capacity-dmips-mhz = <415>; -+ dynamic-power-coefficient = <137>; - next-level-cache = <&L2_300>; - operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -228,8 +228,8 @@ - cpu-idle-states = <&LITTLE_CPU_SLEEP_0 - &LITTLE_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1024>; -- dynamic-power-coefficient = <100>; -+ capacity-dmips-mhz = <415>; -+ dynamic-power-coefficient = <137>; - next-level-cache = <&L2_400>; - operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -250,8 +250,8 @@ - cpu-idle-states = <&LITTLE_CPU_SLEEP_0 - &LITTLE_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1024>; -- dynamic-power-coefficient = <100>; -+ capacity-dmips-mhz = <415>; -+ dynamic-power-coefficient = <137>; - next-level-cache = <&L2_500>; - operating-points-v2 = <&cpu0_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -272,8 +272,8 @@ - cpu-idle-states = <&BIG_CPU_SLEEP_0 - &BIG_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1740>; -- dynamic-power-coefficient = <405>; -+ capacity-dmips-mhz = <1024>; -+ dynamic-power-coefficient = <480>; - next-level-cache = <&L2_600>; - operating-points-v2 = <&cpu6_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -294,8 +294,8 @@ - cpu-idle-states = <&BIG_CPU_SLEEP_0 - &BIG_CPU_SLEEP_1 - &CLUSTER_SLEEP_0>; -- capacity-dmips-mhz = <1740>; -- dynamic-power-coefficient = <405>; -+ capacity-dmips-mhz = <1024>; -+ dynamic-power-coefficient = <480>; - next-level-cache = <&L2_700>; - operating-points-v2 = <&cpu6_opp_table>; - interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, -@@ -3616,7 +3616,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 1>; -- sustainable-power = <768>; -+ sustainable-power = <1052>; - - trips { - cpu0_alert0: trip-point0 { -@@ -3665,7 +3665,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 2>; -- sustainable-power = <768>; -+ sustainable-power = <1052>; - - trips { - cpu1_alert0: trip-point0 { -@@ -3714,7 +3714,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 3>; -- sustainable-power = <768>; -+ sustainable-power = <1052>; - - trips { - cpu2_alert0: trip-point0 { -@@ -3763,7 +3763,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 4>; -- sustainable-power = <768>; -+ sustainable-power = <1052>; - - trips { - cpu3_alert0: trip-point0 { -@@ -3812,7 +3812,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 5>; -- sustainable-power = <768>; -+ sustainable-power = <1052>; - - trips { - cpu4_alert0: trip-point0 { -@@ -3861,7 +3861,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 6>; -- sustainable-power = <768>; -+ sustainable-power = <1052>; - - trips { - cpu5_alert0: trip-point0 { -@@ -3910,7 +3910,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 9>; -- sustainable-power = <1202>; -+ sustainable-power = <1425>; - - trips { - cpu6_alert0: trip-point0 { -@@ -3951,7 +3951,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 10>; -- sustainable-power = <1202>; -+ sustainable-power = <1425>; - - trips { - cpu7_alert0: trip-point0 { -@@ -3992,7 +3992,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 11>; -- sustainable-power = <1202>; -+ sustainable-power = <1425>; - - trips { - cpu8_alert0: trip-point0 { -@@ -4033,7 +4033,7 @@ - polling-delay = <0>; - - thermal-sensors = <&tsens0 12>; -- sustainable-power = <1202>; -+ sustainable-power = <1425>; - - trips { - cpu9_alert0: trip-point0 { -diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi -index fd78f16181ddd..f58336536a92a 100644 ---- a/arch/arm64/boot/dts/qcom/sc7280.dtsi -+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi -@@ -1258,15 +1258,11 @@ - dp_phy: dp-phy@88ea200 { - reg = <0 0x088ea200 0 0x200>, - <0 0x088ea400 0 0x200>, -- <0 0x088eac00 0 0x400>, -+ <0 0x088eaa00 0 0x200>, - <0 0x088ea600 0 0x200>, -- <0 0x088ea800 0 0x200>, -- <0 0x088eaa00 0 0x100>; -+ <0 0x088ea800 0 0x200>; - #phy-cells = <0>; - #clock-cells = <1>; -- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; -- clock-names = "pipe0"; -- clock-output-names = "usb3_phy_pipe_clk_src"; - }; - }; - -diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi -index 9c7f87e42fccd..a8724fd60645f 100644 ---- a/arch/arm64/boot/dts/qcom/sdm630.dtsi -+++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi -@@ -541,7 +541,7 @@ - <&sleep_clk>; - }; - -- rpm_msg_ram: memory@778000 { -+ rpm_msg_ram: sram@778000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0x00778000 0x7000>; - }; -diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi -index b3b9119261844..519ca9a705b4f 100644 ---- a/arch/arm64/boot/dts/qcom/sdm845.dtsi -+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi -@@ -2316,11 +2316,11 @@ - compatible = "qcom,bam-v1.7.0"; - reg = <0 0x01dc4000 0 0x24000>; - interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>; -- clocks = <&rpmhcc 15>; -+ clocks = <&rpmhcc RPMH_CE_CLK>; - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <0>; -- qcom,controlled-remotely = <1>; -+ qcom,controlled-remotely; - iommus = <&apps_smmu 0x704 0x1>, - <&apps_smmu 0x706 0x1>, - <&apps_smmu 0x714 0x1>, -@@ -2331,8 +2331,8 @@ - compatible = "qcom,crypto-v5.4"; - reg = <0 0x01dfa000 0 0x6000>; - clocks = <&gcc GCC_CE1_AHB_CLK>, -- <&gcc GCC_CE1_AHB_CLK>, -- <&rpmhcc 15>; -+ <&gcc GCC_CE1_AXI_CLK>, -+ <&rpmhcc RPMH_CE_CLK>; - clock-names = "iface", "bus", "core"; - dmas = <&cryptobam 6>, <&cryptobam 7>; - dma-names = "rx", "tx"; -diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi -index 2b37ce6a9f9c5..9f476e3d0720b 100644 ---- a/arch/arm64/boot/dts/qcom/sm6125.dtsi -+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi -@@ -380,7 +380,7 @@ - status = "disabled"; - }; - -- rpm_msg_ram: memory@45f0000 { -+ rpm_msg_ram: sram@45f0000 { - compatible = "qcom,rpm-msg-ram"; - reg = <0x045f0000 0x7000>; - }; -diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi -index 090dc9c4f57b5..937d17a426b66 100644 ---- a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi -+++ b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi -@@ -50,6 +50,7 @@ - &avb { - pinctrl-0 = <&avb_pins>; - pinctrl-names = "default"; -+ phy-mode = "rgmii-rxid"; - phy-handle = <&phy0>; - rx-internal-delay-ps = <1800>; - tx-internal-delay-ps = <2000>; -diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts -index 665b2e69455dd..ea6820902ede0 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts -@@ -97,7 +97,7 @@ - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; -- vim-supply = <&vcc_io>; -+ vin-supply = <&vcc_io>; - }; - - vdd_core: vdd-core { -diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -index 8c821acb21ffb..da84be6f4715e 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi -@@ -599,7 +599,7 @@ - - gpu: gpu@ff300000 { - compatible = "rockchip,rk3328-mali", "arm,mali-450"; -- reg = <0x0 0xff300000 0x0 0x40000>; -+ reg = <0x0 0xff300000 0x0 0x30000>; - interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>, -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi -index d5c7648c841dc..f1fcc6b5b402c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi -@@ -705,7 +705,6 @@ - &sdhci { - bus-width = <8>; - mmc-hs400-1_8v; -- mmc-hs400-enhanced-strobe; - non-removable; - status = "okay"; - }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts -index 738cfd21df3ef..354f54767bad8 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts -@@ -269,6 +269,7 @@ - clock-output-names = "xin32k", "rk808-clkout2"; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int_l>; -+ rockchip,system-power-controller; - vcc1-supply = <&vcc5v0_sys>; - vcc2-supply = <&vcc5v0_sys>; - vcc3-supply = <&vcc5v0_sys>; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts -index 7c93f840bc64f..e890166e7fd43 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts -@@ -55,7 +55,7 @@ - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; -- vim-supply = <&vcc3v3_sys>; -+ vin-supply = <&vcc3v3_sys>; - }; - - vcc3v3_sys: vcc3v3-sys { -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts -index 2b5f001ff4a61..9e5d07f5712e6 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts -@@ -385,10 +385,6 @@ - }; - }; - --&cdn_dp { -- status = "okay"; --}; -- - &cpu_b0 { - cpu-supply = <&vdd_cpu_b>; - }; -diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi -index b28888ea9262e..100a769165ef9 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi -@@ -457,7 +457,7 @@ - status = "okay"; - - bt656-supply = <&vcc_3v0>; -- audio-supply = <&vcc_3v0>; -+ audio-supply = <&vcc1v8_codec>; - sdmmc-supply = <&vcc_sdio>; - gpio1830-supply = <&vcc_3v0>; - }; -diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi -index e8a41d09b45f2..874cba75e9a5a 100644 ---- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi -+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi -@@ -606,10 +606,10 @@ - clock-names = "fck"; - #address-cells = <3>; - #size-cells = <2>; -- bus-range = <0x0 0xf>; -+ bus-range = <0x0 0xff>; - cdns,no-bar-match-nbits = <64>; -- vendor-id = /bits/ 16 <0x104c>; -- device-id = /bits/ 16 <0xb00f>; -+ vendor-id = <0x104c>; -+ device-id = <0xb00f>; - msi-map = <0x0 &gic_its 0x0 0x10000>; - dma-coherent; - ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>, -diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi -index cf3482376c1e6..08c8d1b47dcd9 100644 ---- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi -+++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi -@@ -610,7 +610,7 @@ - clock-names = "fck"; - #address-cells = <3>; - #size-cells = <2>; -- bus-range = <0x0 0xf>; -+ bus-range = <0x0 0xff>; - vendor-id = <0x104c>; - device-id = <0xb00d>; - msi-map = <0x0 &gic_its 0x0 0x10000>; -@@ -636,7 +636,7 @@ - clocks = <&k3_clks 239 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; -- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; -+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; - }; - -@@ -658,7 +658,7 @@ - clock-names = "fck"; - #address-cells = <3>; - #size-cells = <2>; -- bus-range = <0x0 0xf>; -+ bus-range = <0x0 0xff>; - vendor-id = <0x104c>; - device-id = <0xb00d>; - msi-map = <0x0 &gic_its 0x10000 0x10000>; -@@ -684,7 +684,7 @@ - clocks = <&k3_clks 240 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; -- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; -+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; - }; - -@@ -706,7 +706,7 @@ - clock-names = "fck"; - #address-cells = <3>; - #size-cells = <2>; -- bus-range = <0x0 0xf>; -+ bus-range = <0x0 0xff>; - vendor-id = <0x104c>; - device-id = <0xb00d>; - msi-map = <0x0 &gic_its 0x20000 0x10000>; -@@ -732,7 +732,7 @@ - clocks = <&k3_clks 241 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; -- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; -+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; - }; - -@@ -754,7 +754,7 @@ - clock-names = "fck"; - #address-cells = <3>; - #size-cells = <2>; -- bus-range = <0x0 0xf>; -+ bus-range = <0x0 0xff>; - vendor-id = <0x104c>; - device-id = <0xb00d>; - msi-map = <0x0 &gic_its 0x30000 0x10000>; -@@ -780,7 +780,7 @@ - clocks = <&k3_clks 242 1>; - clock-names = "fck"; - max-functions = /bits/ 8 <6>; -- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; -+ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; - dma-coherent; - #address-cells = <2>; - #size-cells = <2>; -diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts -index 4a86efa32d687..f7124e15f0ff6 100644 ---- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts -+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts -@@ -131,7 +131,7 @@ - reg = <0>; - - partition@0 { -- label = "data"; -+ label = "spi0-data"; - reg = <0x0 0x100000>; - }; - }; -@@ -149,7 +149,7 @@ - reg = <0>; - - partition@0 { -- label = "data"; -+ label = "spi1-data"; - reg = <0x0 0x84000>; - }; - }; -diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi -index 28dccb891a535..8278876ad33fa 100644 ---- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi -+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi -@@ -792,7 +792,7 @@ - }; - - uart0: serial@ff000000 { -- compatible = "cdns,uart-r1p12", "xlnx,xuartps"; -+ compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12"; - status = "disabled"; - interrupt-parent = <&gic>; - interrupts = <0 21 4>; -@@ -802,7 +802,7 @@ - }; - - uart1: serial@ff010000 { -- compatible = "cdns,uart-r1p12", "xlnx,xuartps"; -+ compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12"; - status = "disabled"; - interrupt-parent = <&gic>; - interrupts = <0 22 4>; -diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h -index 29f97eb3dad41..8f59bbeba7a7e 100644 ---- a/arch/arm64/include/asm/esr.h -+++ b/arch/arm64/include/asm/esr.h -@@ -68,6 +68,7 @@ - #define ESR_ELx_EC_MAX (0x3F) - - #define ESR_ELx_EC_SHIFT (26) -+#define ESR_ELx_EC_WIDTH (6) - #define ESR_ELx_EC_MASK (UL(0x3F) << ESR_ELx_EC_SHIFT) - #define ESR_ELx_EC(esr) (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT) - -diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h -index 327120c0089fe..f67a561e0935e 100644 ---- a/arch/arm64/include/asm/kvm_arm.h -+++ b/arch/arm64/include/asm/kvm_arm.h -@@ -91,7 +91,7 @@ - #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) - - /* TCR_EL2 Registers bits */ --#define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) -+#define TCR_EL2_RES1 ((1U << 31) | (1 << 23)) - #define TCR_EL2_TBI (1 << 20) - #define TCR_EL2_PS_SHIFT 16 - #define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT) -@@ -276,7 +276,7 @@ - #define CPTR_EL2_TFP_SHIFT 10 - - /* Hyp Coprocessor Trap Register */ --#define CPTR_EL2_TCPAC (1 << 31) -+#define CPTR_EL2_TCPAC (1U << 31) - #define CPTR_EL2_TAM (1 << 30) - #define CPTR_EL2_TTA (1 << 20) - #define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT) -diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h -index 8433a2058eb15..237224484d0f6 100644 ---- a/arch/arm64/include/asm/pgalloc.h -+++ b/arch/arm64/include/asm/pgalloc.h -@@ -76,7 +76,7 @@ static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t ptep, - static inline void - pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) - { -- VM_BUG_ON(mm != &init_mm); -+ VM_BUG_ON(mm && mm != &init_mm); - __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE | PMD_TABLE_UXN); - } - -diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h -index dfa76afa0ccff..72f95c6a70519 100644 ---- a/arch/arm64/include/asm/pgtable.h -+++ b/arch/arm64/include/asm/pgtable.h -@@ -67,9 +67,15 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; - * page table entry, taking care of 52-bit addresses. - */ - #ifdef CONFIG_ARM64_PA_BITS_52 --#define __pte_to_phys(pte) \ -- ((pte_val(pte) & PTE_ADDR_LOW) | ((pte_val(pte) & PTE_ADDR_HIGH) << 36)) --#define __phys_to_pte_val(phys) (((phys) | ((phys) >> 36)) & PTE_ADDR_MASK) -+static inline phys_addr_t __pte_to_phys(pte_t pte) -+{ -+ return (pte_val(pte) & PTE_ADDR_LOW) | -+ ((pte_val(pte) & PTE_ADDR_HIGH) << 36); -+} -+static inline pteval_t __phys_to_pte_val(phys_addr_t phys) -+{ -+ return (phys | (phys >> 36)) & PTE_ADDR_MASK; -+} - #else - #define __pte_to_phys(pte) (pte_val(pte) & PTE_ADDR_MASK) - #define __phys_to_pte_val(phys) (phys) -diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h -index 190b494e22ab9..0fd6056ba412b 100644 ---- a/arch/arm64/include/asm/uaccess.h -+++ b/arch/arm64/include/asm/uaccess.h -@@ -292,12 +292,22 @@ do { \ - (x) = (__force __typeof__(*(ptr)))__gu_val; \ - } while (0) - -+/* -+ * We must not call into the scheduler between uaccess_ttbr0_enable() and -+ * uaccess_ttbr0_disable(). As `x` and `ptr` could contain blocking functions, -+ * we must evaluate these outside of the critical section. -+ */ - #define __raw_get_user(x, ptr, err) \ - do { \ -+ __typeof__(*(ptr)) __user *__rgu_ptr = (ptr); \ -+ __typeof__(x) __rgu_val; \ - __chk_user_ptr(ptr); \ -+ \ - uaccess_ttbr0_enable(); \ -- __raw_get_mem("ldtr", x, ptr, err); \ -+ __raw_get_mem("ldtr", __rgu_val, __rgu_ptr, err); \ - uaccess_ttbr0_disable(); \ -+ \ -+ (x) = __rgu_val; \ - } while (0) - - #define __get_user_error(x, ptr, err) \ -@@ -321,14 +331,22 @@ do { \ - - #define get_user __get_user - -+/* -+ * We must not call into the scheduler between __uaccess_enable_tco_async() and -+ * __uaccess_disable_tco_async(). As `dst` and `src` may contain blocking -+ * functions, we must evaluate these outside of the critical section. -+ */ - #define __get_kernel_nofault(dst, src, type, err_label) \ - do { \ -+ __typeof__(dst) __gkn_dst = (dst); \ -+ __typeof__(src) __gkn_src = (src); \ - int __gkn_err = 0; \ - \ - __uaccess_enable_tco_async(); \ -- __raw_get_mem("ldr", *((type *)(dst)), \ -- (__force type *)(src), __gkn_err); \ -+ __raw_get_mem("ldr", *((type *)(__gkn_dst)), \ -+ (__force type *)(__gkn_src), __gkn_err); \ - __uaccess_disable_tco_async(); \ -+ \ - if (unlikely(__gkn_err)) \ - goto err_label; \ - } while (0) -@@ -367,11 +385,19 @@ do { \ - } \ - } while (0) - -+/* -+ * We must not call into the scheduler between uaccess_ttbr0_enable() and -+ * uaccess_ttbr0_disable(). As `x` and `ptr` could contain blocking functions, -+ * we must evaluate these outside of the critical section. -+ */ - #define __raw_put_user(x, ptr, err) \ - do { \ -- __chk_user_ptr(ptr); \ -+ __typeof__(*(ptr)) __user *__rpu_ptr = (ptr); \ -+ __typeof__(*(ptr)) __rpu_val = (x); \ -+ __chk_user_ptr(__rpu_ptr); \ -+ \ - uaccess_ttbr0_enable(); \ -- __raw_put_mem("sttr", x, ptr, err); \ -+ __raw_put_mem("sttr", __rpu_val, __rpu_ptr, err); \ - uaccess_ttbr0_disable(); \ - } while (0) - -@@ -396,14 +422,22 @@ do { \ - - #define put_user __put_user - -+/* -+ * We must not call into the scheduler between __uaccess_enable_tco_async() and -+ * __uaccess_disable_tco_async(). As `dst` and `src` may contain blocking -+ * functions, we must evaluate these outside of the critical section. -+ */ - #define __put_kernel_nofault(dst, src, type, err_label) \ - do { \ -+ __typeof__(dst) __pkn_dst = (dst); \ -+ __typeof__(src) __pkn_src = (src); \ - int __pkn_err = 0; \ - \ - __uaccess_enable_tco_async(); \ -- __raw_put_mem("str", *((type *)(src)), \ -- (__force type *)(dst), __pkn_err); \ -+ __raw_put_mem("str", *((type *)(__pkn_src)), \ -+ (__force type *)(__pkn_dst), __pkn_err); \ - __uaccess_disable_tco_async(); \ -+ \ - if (unlikely(__pkn_err)) \ - goto err_label; \ - } while(0) -diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c -index 6ec7036ef7e18..7553c98f379fc 100644 ---- a/arch/arm64/kernel/cpufeature.c -+++ b/arch/arm64/kernel/cpufeature.c -@@ -573,15 +573,19 @@ static const struct arm64_ftr_bits ftr_raz[] = { - ARM64_FTR_END, - }; - --#define ARM64_FTR_REG_OVERRIDE(id, table, ovr) { \ -+#define __ARM64_FTR_REG_OVERRIDE(id_str, id, table, ovr) { \ - .sys_id = id, \ - .reg = &(struct arm64_ftr_reg){ \ -- .name = #id, \ -+ .name = id_str, \ - .override = (ovr), \ - .ftr_bits = &((table)[0]), \ - }} - --#define ARM64_FTR_REG(id, table) ARM64_FTR_REG_OVERRIDE(id, table, &no_override) -+#define ARM64_FTR_REG_OVERRIDE(id, table, ovr) \ -+ __ARM64_FTR_REG_OVERRIDE(#id, id, table, ovr) -+ -+#define ARM64_FTR_REG(id, table) \ -+ __ARM64_FTR_REG_OVERRIDE(#id, id, table, &no_override) - - struct arm64_ftr_override __ro_after_init id_aa64mmfr1_override; - struct arm64_ftr_override __ro_after_init id_aa64pfr1_override; -diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S -index b3e4f9a088b1a..8cf970d219f5d 100644 ---- a/arch/arm64/kernel/entry-ftrace.S -+++ b/arch/arm64/kernel/entry-ftrace.S -@@ -77,11 +77,17 @@ - .endm - - SYM_CODE_START(ftrace_regs_caller) -+#ifdef BTI_C -+ BTI_C -+#endif - ftrace_regs_entry 1 - b ftrace_common - SYM_CODE_END(ftrace_regs_caller) - - SYM_CODE_START(ftrace_caller) -+#ifdef BTI_C -+ BTI_C -+#endif - ftrace_regs_entry 0 - b ftrace_common - SYM_CODE_END(ftrace_caller) -diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c -index 63634b4d72c15..59c648d518488 100644 ---- a/arch/arm64/kernel/machine_kexec_file.c -+++ b/arch/arm64/kernel/machine_kexec_file.c -@@ -149,6 +149,7 @@ int load_other_segments(struct kimage *image, - initrd_len, cmdline, 0); - if (!dtb) { - pr_err("Preparing for new dtb failed\n"); -+ ret = -EINVAL; - goto out_err; - } - -diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile -index 3dba0c4f8f42b..764d1900d5aab 100644 ---- a/arch/arm64/kernel/vdso32/Makefile -+++ b/arch/arm64/kernel/vdso32/Makefile -@@ -40,7 +40,8 @@ cc32-as-instr = $(call try-run,\ - # As a result we set our own flags here. - - # KBUILD_CPPFLAGS and NOSTDINC_FLAGS from top-level Makefile --VDSO_CPPFLAGS := -DBUILD_VDSO -D__KERNEL__ -nostdinc -isystem $(shell $(CC_COMPAT) -print-file-name=include) -+VDSO_CPPFLAGS := -DBUILD_VDSO -D__KERNEL__ -nostdinc -+VDSO_CPPFLAGS += -isystem $(shell $(CC_COMPAT) -print-file-name=include 2>/dev/null) - VDSO_CPPFLAGS += $(LINUXINCLUDE) - - # Common C and assembly flags -diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c -index fe102cd2e5183..9b328bb05596a 100644 ---- a/arch/arm64/kvm/arm.c -+++ b/arch/arm64/kvm/arm.c -@@ -1971,9 +1971,25 @@ out_err: - return err; - } - --static void _kvm_host_prot_finalize(void *discard) -+static void _kvm_host_prot_finalize(void *arg) - { -- WARN_ON(kvm_call_hyp_nvhe(__pkvm_prot_finalize)); -+ int *err = arg; -+ -+ if (WARN_ON(kvm_call_hyp_nvhe(__pkvm_prot_finalize))) -+ WRITE_ONCE(*err, -EINVAL); -+} -+ -+static int pkvm_drop_host_privileges(void) -+{ -+ int ret = 0; -+ -+ /* -+ * Flip the static key upfront as that may no longer be possible -+ * once the host stage 2 is installed. -+ */ -+ static_branch_enable(&kvm_protected_mode_initialized); -+ on_each_cpu(_kvm_host_prot_finalize, &ret, 1); -+ return ret; - } - - static int finalize_hyp_mode(void) -@@ -1987,15 +2003,7 @@ static int finalize_hyp_mode(void) - * None of other sections should ever be introspected. - */ - kmemleak_free_part(__hyp_bss_start, __hyp_bss_end - __hyp_bss_start); -- -- /* -- * Flip the static key upfront as that may no longer be possible -- * once the host stage 2 is installed. -- */ -- static_branch_enable(&kvm_protected_mode_initialized); -- on_each_cpu(_kvm_host_prot_finalize, NULL, 1); -- -- return 0; -+ return pkvm_drop_host_privileges(); - } - - struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) -diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S -index 9aa9b73475c95..b6b6801d96d5a 100644 ---- a/arch/arm64/kvm/hyp/hyp-entry.S -+++ b/arch/arm64/kvm/hyp/hyp-entry.S -@@ -44,7 +44,7 @@ - el1_sync: // Guest trapped into EL2 - - mrs x0, esr_el2 -- lsr x0, x0, #ESR_ELx_EC_SHIFT -+ ubfx x0, x0, #ESR_ELx_EC_SHIFT, #ESR_ELx_EC_WIDTH - cmp x0, #ESR_ELx_EC_HVC64 - ccmp x0, #ESR_ELx_EC_HVC32, #4, ne - b.ne el1_trap -diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h -index a0e78a6027be0..c75e84489f57b 100644 ---- a/arch/arm64/kvm/hyp/include/hyp/switch.h -+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h -@@ -416,6 +416,12 @@ static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) - */ - static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) - { -+ /* -+ * Save PSTATE early so that we can evaluate the vcpu mode -+ * early on. -+ */ -+ vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR); -+ - if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) - vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); - -diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h -index de7e14c862e6c..7ecca8b078519 100644 ---- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h -+++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h -@@ -70,7 +70,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) - static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) - { - ctxt->regs.pc = read_sysreg_el2(SYS_ELR); -- ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); -+ /* -+ * Guest PSTATE gets saved at guest fixup time in all -+ * cases. We still need to handle the nVHE host side here. -+ */ -+ if (!has_vhe() && ctxt->__hyp_running_vcpu) -+ ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); - - if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) - ctxt_sys_reg(ctxt, DISR_EL1) = read_sysreg_s(SYS_VDISR_EL2); -diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S -index 4b652ffb591d4..d310d2b2c8b40 100644 ---- a/arch/arm64/kvm/hyp/nvhe/host.S -+++ b/arch/arm64/kvm/hyp/nvhe/host.S -@@ -115,7 +115,7 @@ SYM_FUNC_END(__hyp_do_panic) - .L__vect_start\@: - stp x0, x1, [sp, #-16]! - mrs x0, esr_el2 -- lsr x0, x0, #ESR_ELx_EC_SHIFT -+ ubfx x0, x0, #ESR_ELx_EC_SHIFT, #ESR_ELx_EC_WIDTH - cmp x0, #ESR_ELx_EC_HVC64 - b.ne __host_exit - -diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c -index 57c27846320f4..58ad9c5ba3112 100644 ---- a/arch/arm64/kvm/hyp/nvhe/setup.c -+++ b/arch/arm64/kvm/hyp/nvhe/setup.c -@@ -177,7 +177,7 @@ static int finalize_host_mappings_walker(u64 addr, u64 end, u32 level, - - phys = kvm_pte_to_phys(pte); - if (!addr_is_memory(phys)) -- return 0; -+ return -EINVAL; - - /* - * Adjust the host stage-2 mappings to match the ownership attributes -@@ -206,8 +206,18 @@ static int finalize_host_mappings(void) - .cb = finalize_host_mappings_walker, - .flags = KVM_PGTABLE_WALK_LEAF, - }; -+ int i, ret; -+ -+ for (i = 0; i < hyp_memblock_nr; i++) { -+ struct memblock_region *reg = &hyp_memory[i]; -+ u64 start = (u64)hyp_phys_to_virt(reg->base); -+ -+ ret = kvm_pgtable_walk(&pkvm_pgtable, start, reg->size, &walker); -+ if (ret) -+ return ret; -+ } - -- return kvm_pgtable_walk(&pkvm_pgtable, 0, BIT(pkvm_pgtable.ia_bits), &walker); -+ return 0; - } - - void __noreturn __pkvm_init_finalise(void) -diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c -index cfd9deb347c38..fd85b51b9d50f 100644 ---- a/arch/arm64/mm/mmu.c -+++ b/arch/arm64/mm/mmu.c -@@ -1499,6 +1499,11 @@ int arch_add_memory(int nid, u64 start, u64 size, - if (ret) - __remove_pgd_mapping(swapper_pg_dir, - __phys_to_virt(start), size); -+ else { -+ max_pfn = PFN_UP(start + size); -+ max_low_pfn = max_pfn; -+ } -+ - return ret; - } - -diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c -index e5fbf8653a215..2020af88b6361 100644 ---- a/arch/csky/kernel/traps.c -+++ b/arch/csky/kernel/traps.c -@@ -209,7 +209,7 @@ asmlinkage void do_trap_illinsn(struct pt_regs *regs) - - asmlinkage void do_trap_fpe(struct pt_regs *regs) - { --#ifdef CONFIG_CPU_HAS_FP -+#ifdef CONFIG_CPU_HAS_FPU - return fpu_fpe(regs); - #else - do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, -@@ -219,7 +219,7 @@ asmlinkage void do_trap_fpe(struct pt_regs *regs) - - asmlinkage void do_trap_priv(struct pt_regs *regs) - { --#ifdef CONFIG_CPU_HAS_FP -+#ifdef CONFIG_CPU_HAS_FPU - if (user_mode(regs) && fpu_libc_helper(regs)) - return; - #endif -diff --git a/arch/hexagon/include/asm/timer-regs.h b/arch/hexagon/include/asm/timer-regs.h -deleted file mode 100644 -index ee6c61423a058..0000000000000 ---- a/arch/hexagon/include/asm/timer-regs.h -+++ /dev/null -@@ -1,26 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0-only */ --/* -- * Timer support for Hexagon -- * -- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. -- */ -- --#ifndef _ASM_TIMER_REGS_H --#define _ASM_TIMER_REGS_H -- --/* This stuff should go into a platform specific file */ --#define TCX0_CLK_RATE 19200 --#define TIMER_ENABLE 0 --#define TIMER_CLR_ON_MATCH 1 -- --/* -- * 8x50 HDD Specs 5-8. Simulator co-sim not fixed until -- * release 1.1, and then it's "adjustable" and probably not defaulted. -- */ --#define RTOS_TIMER_INT 3 --#ifdef CONFIG_HEXAGON_COMET --#define RTOS_TIMER_REGS_ADDR 0xAB000000UL --#endif --#define SLEEP_CLK_RATE 32000 -- --#endif -diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h -index 8d4ec76fceb45..dfe69e118b2be 100644 ---- a/arch/hexagon/include/asm/timex.h -+++ b/arch/hexagon/include/asm/timex.h -@@ -7,11 +7,10 @@ - #define _ASM_TIMEX_H - - #include <asm-generic/timex.h> --#include <asm/timer-regs.h> - #include <asm/hexagon_vm.h> - - /* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */ --#define CLOCK_TICK_RATE TCX0_CLK_RATE -+#define CLOCK_TICK_RATE 19200 - - #define ARCH_HAS_READ_CURRENT_TIMER - -diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c -index feffe527ac929..febc95714d756 100644 ---- a/arch/hexagon/kernel/time.c -+++ b/arch/hexagon/kernel/time.c -@@ -17,9 +17,10 @@ - #include <linux/of_irq.h> - #include <linux/module.h> - --#include <asm/timer-regs.h> - #include <asm/hexagon_vm.h> - -+#define TIMER_ENABLE BIT(0) -+ - /* - * For the clocksource we need: - * pcycle frequency (600MHz) -@@ -33,6 +34,13 @@ cycles_t pcycle_freq_mhz; - cycles_t thread_freq_mhz; - cycles_t sleep_clk_freq; - -+/* -+ * 8x50 HDD Specs 5-8. Simulator co-sim not fixed until -+ * release 1.1, and then it's "adjustable" and probably not defaulted. -+ */ -+#define RTOS_TIMER_INT 3 -+#define RTOS_TIMER_REGS_ADDR 0xAB000000UL -+ - static struct resource rtos_timer_resources[] = { - { - .start = RTOS_TIMER_REGS_ADDR, -@@ -80,7 +88,7 @@ static int set_next_event(unsigned long delta, struct clock_event_device *evt) - iowrite32(0, &rtos_timer->clear); - - iowrite32(delta, &rtos_timer->match); -- iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable); -+ iowrite32(TIMER_ENABLE, &rtos_timer->enable); - return 0; - } - -diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c -index d35d69d6588c4..55f75392857b0 100644 ---- a/arch/hexagon/lib/io.c -+++ b/arch/hexagon/lib/io.c -@@ -27,6 +27,7 @@ void __raw_readsw(const void __iomem *addr, void *data, int len) - *dst++ = *src; - - } -+EXPORT_SYMBOL(__raw_readsw); - - /* - * __raw_writesw - read words a short at a time -@@ -47,6 +48,7 @@ void __raw_writesw(void __iomem *addr, const void *data, int len) - - - } -+EXPORT_SYMBOL(__raw_writesw); - - /* Pretty sure len is pre-adjusted for the length of the access already */ - void __raw_readsl(const void __iomem *addr, void *data, int len) -@@ -62,6 +64,7 @@ void __raw_readsl(const void __iomem *addr, void *data, int len) - - - } -+EXPORT_SYMBOL(__raw_readsl); - - void __raw_writesl(void __iomem *addr, const void *data, int len) - { -@@ -76,3 +79,4 @@ void __raw_writesl(void __iomem *addr, const void *data, int len) - - - } -+EXPORT_SYMBOL(__raw_writesl); -diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug -index 40ca23bd228d6..2ce008e2d1644 100644 ---- a/arch/ia64/Kconfig.debug -+++ b/arch/ia64/Kconfig.debug -@@ -39,7 +39,7 @@ config DISABLE_VHPT - - config IA64_DEBUG_CMPXCHG - bool "Turn on compare-and-exchange bug checking (slow!)" -- depends on DEBUG_KERNEL -+ depends on DEBUG_KERNEL && PRINTK - help - Selecting this option turns on bug checking for the IA-64 - compare-and-exchange instructions. This is slow! Itaniums -diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c -index 441ed04b10378..d4048518a1d7d 100644 ---- a/arch/ia64/kernel/kprobes.c -+++ b/arch/ia64/kernel/kprobes.c -@@ -398,7 +398,8 @@ static void kretprobe_trampoline(void) - - int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) - { -- regs->cr_iip = __kretprobe_trampoline_handler(regs, kretprobe_trampoline, NULL); -+ regs->cr_iip = __kretprobe_trampoline_handler(regs, -+ dereference_function_descriptor(kretprobe_trampoline), NULL); - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we don't want the post_handler -@@ -414,7 +415,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, - ri->fp = NULL; - - /* Replace the return addr with trampoline addr */ -- regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip; -+ regs->b0 = (unsigned long)dereference_function_descriptor(kretprobe_trampoline); - } - - /* Check the instruction in the slot is break */ -@@ -902,14 +903,14 @@ static struct kprobe trampoline_p = { - int __init arch_init_kprobes(void) - { - trampoline_p.addr = -- (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip; -+ dereference_function_descriptor(kretprobe_trampoline); - return register_kprobe(&trampoline_p); - } - - int __kprobes arch_trampoline_kprobe(struct kprobe *p) - { - if (p->addr == -- (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip) -+ dereference_function_descriptor(kretprobe_trampoline)) - return 1; - - return 0; -diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine -index 36fa0c3ef1296..eeab4f3e6c197 100644 ---- a/arch/m68k/Kconfig.machine -+++ b/arch/m68k/Kconfig.machine -@@ -203,6 +203,7 @@ config INIT_LCD - config MEMORY_RESERVE - int "Memory reservation (MiB)" - depends on (UCSIMM || UCDIMM) -+ default 0 - help - Reserve certain memory regions on 68x328 based boards. - -diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c -index 9718ce94cc845..34d6458340b0f 100644 ---- a/arch/m68k/kernel/traps.c -+++ b/arch/m68k/kernel/traps.c -@@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long ssp) - */ - asmlinkage void fpsp040_die(void) - { -- force_sigsegv(SIGSEGV); -+ force_exit_sig(SIGSEGV); - } - - #ifdef CONFIG_M68KFPU_EMU -diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms -index 584081df89c28..6e3f36c841e5d 100644 ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -38,4 +38,4 @@ platform-$(CONFIG_MACH_TX49XX) += txx9/ - platform-$(CONFIG_MACH_VR41XX) += vr41xx/ - - # include the platform specific files --include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platform-y)) -+include $(patsubst %/, $(srctree)/arch/mips/%/Platform, $(platform-y)) -diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig -index 6b8f591c5054c..23654ccdbfb12 100644 ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -332,6 +332,9 @@ config BCM63XX - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_HAS_EARLY_PRINTK -+ select SYS_HAS_CPU_BMIPS32_3300 -+ select SYS_HAS_CPU_BMIPS4350 -+ select SYS_HAS_CPU_BMIPS4380 - select SWAP_IO_SPACE - select GPIOLIB - select MIPS_L1_CACHE_SHIFT_4 -@@ -1379,6 +1382,7 @@ config CPU_LOONGSON64 - select MIPS_ASID_BITS_VARIABLE - select MIPS_PGD_C0_CONTEXT - select MIPS_L1_CACHE_SHIFT_6 -+ select MIPS_FP_SUPPORT - select GPIOLIB - select SWIOTLB - select HAVE_KVM -@@ -3185,7 +3189,7 @@ config STACKTRACE_SUPPORT - config PGTABLE_LEVELS - int - default 4 if PAGE_SIZE_4KB && MIPS_VA_BITS_48 -- default 3 if 64BIT && !PAGE_SIZE_64KB -+ default 3 if 64BIT && (!PAGE_SIZE_64KB || MIPS_VA_BITS_48) - default 2 - - config MIPS_AUTO_PFN_OFFSET -diff --git a/arch/mips/Makefile b/arch/mips/Makefile -index ea3cd080a1c7d..f7b58da2f3889 100644 ---- a/arch/mips/Makefile -+++ b/arch/mips/Makefile -@@ -254,7 +254,9 @@ endif - # - # Board-dependent options and extra files - # -+ifdef need-compiler - include $(srctree)/arch/mips/Kbuild.platforms -+endif - - ifdef CONFIG_PHYSICAL_START - load-y = $(CONFIG_PHYSICAL_START) -diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c -index 5a3e325275d0d..1c91064cb448b 100644 ---- a/arch/mips/bcm63xx/clk.c -+++ b/arch/mips/bcm63xx/clk.c -@@ -381,6 +381,12 @@ void clk_disable(struct clk *clk) - - EXPORT_SYMBOL(clk_disable); - -+struct clk *clk_get_parent(struct clk *clk) -+{ -+ return NULL; -+} -+EXPORT_SYMBOL(clk_get_parent); -+ - unsigned long clk_get_rate(struct clk *clk) - { - if (!clk) -diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile -index 3548b3b452699..9112bdb86be45 100644 ---- a/arch/mips/boot/compressed/Makefile -+++ b/arch/mips/boot/compressed/Makefile -@@ -56,6 +56,8 @@ $(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c - - vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o - -+vmlinuzobjs-$(CONFIG_KERNEL_ZSTD) += $(obj)/bswapdi.o -+ - extra-y += ashldi3.c - $(obj)/ashldi3.c: $(obj)/%.c: $(srctree)/lib/%.c FORCE - $(call if_changed,shipped) -@@ -64,6 +66,10 @@ extra-y += bswapsi.c - $(obj)/bswapsi.c: $(obj)/%.c: $(srctree)/arch/mips/lib/%.c FORCE - $(call if_changed,shipped) - -+extra-y += bswapdi.c -+$(obj)/bswapdi.c: $(obj)/%.c: $(srctree)/arch/mips/lib/%.c FORCE -+ $(call if_changed,shipped) -+ - targets := $(notdir $(vmlinuzobjs-y)) - - targets += vmlinux.bin -diff --git a/arch/mips/generic/yamon-dt.c b/arch/mips/generic/yamon-dt.c -index a3aa22c77cadc..a07a5edbcda78 100644 ---- a/arch/mips/generic/yamon-dt.c -+++ b/arch/mips/generic/yamon-dt.c -@@ -75,7 +75,7 @@ static unsigned int __init gen_fdt_mem_array( - __init int yamon_dt_append_memory(void *fdt, - const struct yamon_mem_region *regions) - { -- unsigned long phys_memsize, memsize; -+ unsigned long phys_memsize = 0, memsize; - __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES]; - unsigned int mem_entries; - int i, err, mem_off; -diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h -index 0b983800f48b7..66a8b293fd80b 100644 ---- a/arch/mips/include/asm/cmpxchg.h -+++ b/arch/mips/include/asm/cmpxchg.h -@@ -249,6 +249,7 @@ static inline unsigned long __cmpxchg64(volatile void *ptr, - /* Load 64 bits from ptr */ - " " __SYNC(full, loongson3_war) " \n" - "1: lld %L0, %3 # __cmpxchg64 \n" -+ " .set pop \n" - /* - * Split the 64 bit value we loaded into the 2 registers that hold the - * ret variable. -@@ -276,12 +277,14 @@ static inline unsigned long __cmpxchg64(volatile void *ptr, - " or %L1, %L1, $at \n" - " .set at \n" - # endif -+ " .set push \n" -+ " .set " MIPS_ISA_ARCH_LEVEL " \n" - /* Attempt to store new at ptr */ - " scd %L1, %2 \n" - /* If we failed, loop! */ - "\t" __SC_BEQZ "%L1, 1b \n" -- " .set pop \n" - "2: " __SYNC(full, loongson3_war) " \n" -+ " .set pop \n" - : "=&r"(ret), - "=&r"(tmp), - "=" GCC_OFF_SMALL_ASM() (*(unsigned long long *)ptr) -diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h -index aeae2effa123d..23c67c0871b17 100644 ---- a/arch/mips/include/asm/mips-cm.h -+++ b/arch/mips/include/asm/mips-cm.h -@@ -11,6 +11,7 @@ - #ifndef __MIPS_ASM_MIPS_CM_H__ - #define __MIPS_ASM_MIPS_CM_H__ - -+#include <linux/bitfield.h> - #include <linux/bitops.h> - #include <linux/errno.h> - -@@ -153,8 +154,8 @@ GCR_ACCESSOR_RO(32, 0x030, rev) - #define CM_GCR_REV_MINOR GENMASK(7, 0) - - #define CM_ENCODE_REV(major, minor) \ -- (((major) << __ffs(CM_GCR_REV_MAJOR)) | \ -- ((minor) << __ffs(CM_GCR_REV_MINOR))) -+ (FIELD_PREP(CM_GCR_REV_MAJOR, major) | \ -+ FIELD_PREP(CM_GCR_REV_MINOR, minor)) - - #define CM_REV_CM2 CM_ENCODE_REV(6, 0) - #define CM_REV_CM2_5 CM_ENCODE_REV(7, 0) -@@ -362,10 +363,10 @@ static inline int mips_cm_revision(void) - static inline unsigned int mips_cm_max_vp_width(void) - { - extern int smp_num_siblings; -- uint32_t cfg; - - if (mips_cm_revision() >= CM_REV_CM3) -- return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW; -+ return FIELD_GET(CM_GCR_SYS_CONFIG2_MAXVPW, -+ read_gcr_sys_config2()); - - if (mips_cm_present()) { - /* -@@ -373,8 +374,7 @@ static inline unsigned int mips_cm_max_vp_width(void) - * number of VP(E)s, and if that ever changes then this will - * need revisiting. - */ -- cfg = read_gcr_cl_config() & CM_GCR_Cx_CONFIG_PVPE; -- return (cfg >> __ffs(CM_GCR_Cx_CONFIG_PVPE)) + 1; -+ return FIELD_GET(CM_GCR_Cx_CONFIG_PVPE, read_gcr_cl_config()) + 1; - } - - if (IS_ENABLED(CONFIG_SMP)) -diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c -index 630fcb4cb30e7..7c861e6a89529 100644 ---- a/arch/mips/kernel/cpu-probe.c -+++ b/arch/mips/kernel/cpu-probe.c -@@ -1734,8 +1734,6 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c) - - static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) - { -- decode_configs(c); -- - /* All Loongson processors covered here define ExcCode 16 as GSExc. */ - c->options |= MIPS_CPU_GSEXCEX; - -@@ -1796,6 +1794,8 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) - panic("Unknown Loongson Processor ID!"); - break; - } -+ -+ decode_configs(c); - } - #else - static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { } -diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c -index 90f1c3df1f0e4..b4f7d950c8468 100644 ---- a/arch/mips/kernel/mips-cm.c -+++ b/arch/mips/kernel/mips-cm.c -@@ -221,8 +221,7 @@ static void mips_cm_probe_l2sync(void) - phys_addr_t addr; - - /* L2-only sync was introduced with CM major revision 6 */ -- major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR) >> -- __ffs(CM_GCR_REV_MAJOR); -+ major_rev = FIELD_GET(CM_GCR_REV_MAJOR, read_gcr_rev()); - if (major_rev < 6) - return; - -@@ -306,13 +305,13 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core, - preempt_disable(); - - if (cm_rev >= CM_REV_CM3) { -- val = core << __ffs(CM3_GCR_Cx_OTHER_CORE); -- val |= vp << __ffs(CM3_GCR_Cx_OTHER_VP); -+ val = FIELD_PREP(CM3_GCR_Cx_OTHER_CORE, core) | -+ FIELD_PREP(CM3_GCR_Cx_OTHER_VP, vp); - - if (cm_rev >= CM_REV_CM3_5) { - val |= CM_GCR_Cx_OTHER_CLUSTER_EN; -- val |= cluster << __ffs(CM_GCR_Cx_OTHER_CLUSTER); -- val |= block << __ffs(CM_GCR_Cx_OTHER_BLOCK); -+ val |= FIELD_PREP(CM_GCR_Cx_OTHER_CLUSTER, cluster); -+ val |= FIELD_PREP(CM_GCR_Cx_OTHER_BLOCK, block); - } else { - WARN_ON(cluster != 0); - WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL); -@@ -342,7 +341,7 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core, - spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), - per_cpu(cm_core_lock_flags, curr_core)); - -- val = core << __ffs(CM_GCR_Cx_OTHER_CORENUM); -+ val = FIELD_PREP(CM_GCR_Cx_OTHER_CORENUM, core); - } - - write_gcr_cl_other(val); -@@ -386,8 +385,8 @@ void mips_cm_error_report(void) - cm_other = read_gcr_error_mult(); - - if (revision < CM_REV_CM3) { /* CM2 */ -- cause = cm_error >> __ffs(CM_GCR_ERROR_CAUSE_ERRTYPE); -- ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND); -+ cause = FIELD_GET(CM_GCR_ERROR_CAUSE_ERRTYPE, cm_error); -+ ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other); - - if (!cause) - return; -@@ -445,8 +444,8 @@ void mips_cm_error_report(void) - ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits; - ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit; - -- cause = cm_error >> __ffs64(CM3_GCR_ERROR_CAUSE_ERRTYPE); -- ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND); -+ cause = FIELD_GET(CM3_GCR_ERROR_CAUSE_ERRTYPE, cm_error); -+ ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other); - - if (!cause) - return; -diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S -index 12e58053544fc..cbf6db98cfb38 100644 ---- a/arch/mips/kernel/r2300_fpu.S -+++ b/arch/mips/kernel/r2300_fpu.S -@@ -29,8 +29,8 @@ - #define EX2(a,b) \ - 9: a,##b; \ - .section __ex_table,"a"; \ -- PTR 9b,bad_stack; \ -- PTR 9b+4,bad_stack; \ -+ PTR 9b,fault; \ -+ PTR 9b+4,fault; \ - .previous - - .set mips1 -diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c -index 2afa3eef486a9..5512cd586e6e8 100644 ---- a/arch/mips/kernel/syscall.c -+++ b/arch/mips/kernel/syscall.c -@@ -240,12 +240,3 @@ SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) - { - return -ENOSYS; - } -- --/* -- * If we ever come here the user sp is bad. Zap the process right away. -- * Due to the bad stack signaling wouldn't work. -- */ --asmlinkage void bad_stack(void) --{ -- do_exit(SIGSEGV); --} -diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c -index dd819e31fcbbf..4916cccf378fd 100644 ---- a/arch/mips/lantiq/clk.c -+++ b/arch/mips/lantiq/clk.c -@@ -158,6 +158,12 @@ void clk_deactivate(struct clk *clk) - } - EXPORT_SYMBOL(clk_deactivate); - -+struct clk *clk_get_parent(struct clk *clk) -+{ -+ return NULL; -+} -+EXPORT_SYMBOL(clk_get_parent); -+ - static inline u32 get_counter_resolution(void) - { - u32 res; -diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c -index 63dccb2ed08b2..53fcc672a2944 100644 ---- a/arch/mips/lantiq/xway/dma.c -+++ b/arch/mips/lantiq/xway/dma.c -@@ -11,6 +11,7 @@ - #include <linux/export.h> - #include <linux/spinlock.h> - #include <linux/clk.h> -+#include <linux/delay.h> - #include <linux/err.h> - #include <linux/of.h> - -@@ -30,6 +31,7 @@ - #define LTQ_DMA_PCTRL 0x44 - #define LTQ_DMA_IRNEN 0xf4 - -+#define DMA_ID_CHNR GENMASK(26, 20) /* channel number */ - #define DMA_DESCPT BIT(3) /* descriptor complete irq */ - #define DMA_TX BIT(8) /* TX channel direction */ - #define DMA_CHAN_ON BIT(0) /* channel on / off bit */ -@@ -39,8 +41,11 @@ - #define DMA_IRQ_ACK 0x7e /* IRQ status register */ - #define DMA_POLL BIT(31) /* turn on channel polling */ - #define DMA_CLK_DIV4 BIT(6) /* polling clock divider */ --#define DMA_2W_BURST BIT(1) /* 2 word burst length */ --#define DMA_MAX_CHANNEL 20 /* the soc has 20 channels */ -+#define DMA_PCTRL_2W_BURST 0x1 /* 2 word burst length */ -+#define DMA_PCTRL_4W_BURST 0x2 /* 4 word burst length */ -+#define DMA_PCTRL_8W_BURST 0x3 /* 8 word burst length */ -+#define DMA_TX_BURST_SHIFT 4 /* tx burst shift */ -+#define DMA_RX_BURST_SHIFT 2 /* rx burst shift */ - #define DMA_ETOP_ENDIANNESS (0xf << 8) /* endianness swap etop channels */ - #define DMA_WEIGHT (BIT(17) | BIT(16)) /* default channel wheight */ - -@@ -191,7 +196,8 @@ ltq_dma_init_port(int p) - break; - - case DMA_PORT_DEU: -- ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2), -+ ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) | -+ (DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT), - LTQ_DMA_PCTRL); - break; - -@@ -206,7 +212,7 @@ ltq_dma_init(struct platform_device *pdev) - { - struct clk *clk; - struct resource *res; -- unsigned id; -+ unsigned int id, nchannels; - int i; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -@@ -222,21 +228,24 @@ ltq_dma_init(struct platform_device *pdev) - clk_enable(clk); - ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL); - -+ usleep_range(1, 10); -+ - /* disable all interrupts */ - ltq_dma_w32(0, LTQ_DMA_IRNEN); - - /* reset/configure each channel */ -- for (i = 0; i < DMA_MAX_CHANNEL; i++) { -+ id = ltq_dma_r32(LTQ_DMA_ID); -+ nchannels = ((id & DMA_ID_CHNR) >> 20); -+ for (i = 0; i < nchannels; i++) { - ltq_dma_w32(i, LTQ_DMA_CS); - ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL); - ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); - ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); - } - -- id = ltq_dma_r32(LTQ_DMA_ID); - dev_info(&pdev->dev, - "Init done - hw rev: %X, ports: %d, channels: %d\n", -- id & 0x1f, (id >> 16) & 0xf, id >> 20); -+ id & 0x1f, (id >> 16) & 0xf, nchannels); - - return 0; - } -diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c -index 240bb68ec2478..ff3ba7e778901 100644 ---- a/arch/mips/sni/time.c -+++ b/arch/mips/sni/time.c -@@ -18,14 +18,14 @@ static int a20r_set_periodic(struct clock_event_device *evt) - { - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; - wmb(); -- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV; -+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV & 0xff; - wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8; - wmb(); - - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; - wmb(); -- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV; -+ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV & 0xff; - wmb(); - *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8; - wmb(); -diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c -index 1b16d97e7da7f..a82b2caaa560d 100644 ---- a/arch/openrisc/kernel/dma.c -+++ b/arch/openrisc/kernel/dma.c -@@ -33,7 +33,7 @@ page_set_nocache(pte_t *pte, unsigned long addr, - * Flush the page out of the TLB so that the new page flags get - * picked up next time there's an access - */ -- flush_tlb_page(NULL, addr); -+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE); - - /* Flush page out of dcache */ - for (cl = __pa(addr); cl < __pa(next); cl += cpuinfo->dcache_block_size) -@@ -56,7 +56,7 @@ page_clear_nocache(pte_t *pte, unsigned long addr, - * Flush the page out of the TLB so that the new page flags get - * picked up next time there's an access - */ -- flush_tlb_page(NULL, addr); -+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE); - - return 0; - } -diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c -index 415e209732a3d..ba78766cf00b5 100644 ---- a/arch/openrisc/kernel/smp.c -+++ b/arch/openrisc/kernel/smp.c -@@ -272,7 +272,7 @@ static inline void ipi_flush_tlb_range(void *info) - local_flush_tlb_range(NULL, fd->addr1, fd->addr2); - } - --static void smp_flush_tlb_range(struct cpumask *cmask, unsigned long start, -+static void smp_flush_tlb_range(const struct cpumask *cmask, unsigned long start, - unsigned long end) - { - unsigned int cpuid; -@@ -320,7 +320,9 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) - void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) - { -- smp_flush_tlb_range(mm_cpumask(vma->vm_mm), start, end); -+ const struct cpumask *cmask = vma ? mm_cpumask(vma->vm_mm) -+ : cpu_online_mask; -+ smp_flush_tlb_range(cmask, start, end); - } - - /* Instruction cache invalidate - performed on each cpu */ -diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile -index fcde3ffa02213..fadb098de1545 100644 ---- a/arch/parisc/Makefile -+++ b/arch/parisc/Makefile -@@ -17,7 +17,12 @@ - # Mike Shaver, Helge Deller and Martin K. Petersen - # - -+ifdef CONFIG_PARISC_SELF_EXTRACT -+boot := arch/parisc/boot -+KBUILD_IMAGE := $(boot)/bzImage -+else - KBUILD_IMAGE := vmlinuz -+endif - - NM = sh $(srctree)/arch/parisc/nm - CHECKFLAGS += -D__hppa__=1 -diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h -index 7badd872f05ac..3e7cf882639fb 100644 ---- a/arch/parisc/include/asm/pgtable.h -+++ b/arch/parisc/include/asm/pgtable.h -@@ -76,6 +76,8 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) - purge_tlb_end(flags); - } - -+extern void __update_cache(pte_t pte); -+ - /* Certain architectures need to do special things when PTEs - * within a page table are directly modified. Thus, the following - * hook is made available. -@@ -83,11 +85,14 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) - #define set_pte(pteptr, pteval) \ - do { \ - *(pteptr) = (pteval); \ -- barrier(); \ -+ mb(); \ - } while(0) - - #define set_pte_at(mm, addr, pteptr, pteval) \ - do { \ -+ if (pte_present(pteval) && \ -+ pte_user(pteval)) \ -+ __update_cache(pteval); \ - *(pteptr) = (pteval); \ - purge_tlb_entries(mm, addr); \ - } while (0) -@@ -303,6 +308,7 @@ extern unsigned long *empty_zero_page; - - #define pte_none(x) (pte_val(x) == 0) - #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) -+#define pte_user(x) (pte_val(x) & _PAGE_USER) - #define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0)) - - #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) -@@ -410,7 +416,7 @@ extern void paging_init (void); - - #define PG_dcache_dirty PG_arch_1 - --extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); -+#define update_mmu_cache(vms,addr,ptep) __update_cache(*ptep) - - /* Encode and de-code a swap entry */ - -diff --git a/arch/parisc/include/asm/rt_sigframe.h b/arch/parisc/include/asm/rt_sigframe.h -index 4b9e3d707571b..2b3010ade00e7 100644 ---- a/arch/parisc/include/asm/rt_sigframe.h -+++ b/arch/parisc/include/asm/rt_sigframe.h -@@ -2,7 +2,7 @@ - #ifndef _ASM_PARISC_RT_SIGFRAME_H - #define _ASM_PARISC_RT_SIGFRAME_H - --#define SIGRETURN_TRAMP 3 -+#define SIGRETURN_TRAMP 4 - #define SIGRESTARTBLOCK_TRAMP 5 - #define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP) - -diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh -index 056d588befdd6..70d3cffb02515 100644 ---- a/arch/parisc/install.sh -+++ b/arch/parisc/install.sh -@@ -39,6 +39,7 @@ verify "$3" - if [ -n "${INSTALLKERNEL}" ]; then - if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi - if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi -+ if [ -x /usr/sbin/${INSTALLKERNEL} ]; then exec /usr/sbin/${INSTALLKERNEL} "$@"; fi - fi - - # Default install -diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c -index 39e02227e2310..4ed4942d8312b 100644 ---- a/arch/parisc/kernel/cache.c -+++ b/arch/parisc/kernel/cache.c -@@ -83,9 +83,9 @@ EXPORT_SYMBOL(flush_cache_all_local); - #define pfn_va(pfn) __va(PFN_PHYS(pfn)) - - void --update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) -+__update_cache(pte_t pte) - { -- unsigned long pfn = pte_pfn(*ptep); -+ unsigned long pfn = pte_pfn(pte); - struct page *page; - - /* We don't have pte special. As a result, we can be called with -diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S -index 9f939afe6b88c..437c8d31f3907 100644 ---- a/arch/parisc/kernel/entry.S -+++ b/arch/parisc/kernel/entry.S -@@ -1834,8 +1834,8 @@ syscall_restore: - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 - - /* Are we being ptraced? */ -- ldw TASK_FLAGS(%r1),%r19 -- ldi _TIF_SYSCALL_TRACE_MASK,%r2 -+ LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 -+ ldi _TIF_SINGLESTEP|_TIF_BLOCKSTEP,%r2 - and,COND(=) %r19,%r2,%r0 - b,n syscall_restore_rfi - -diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c -index bbfe23c40c016..0fb06d87b3a5c 100644 ---- a/arch/parisc/kernel/signal.c -+++ b/arch/parisc/kernel/signal.c -@@ -288,21 +288,22 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, - already in userspace. The first words of tramp are used to - save the previous sigrestartblock trampoline that might be - on the stack. We start the sigreturn trampoline at -- SIGRESTARTBLOCK_TRAMP. */ -+ SIGRESTARTBLOCK_TRAMP+X. */ - err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0, - &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]); -- err |= __put_user(INSN_BLE_SR2_R0, -- &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]); - err |= __put_user(INSN_LDI_R20, -+ &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]); -+ err |= __put_user(INSN_BLE_SR2_R0, - &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]); -+ err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]); - -- start = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]; -- end = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]; -+ start = (unsigned long) &frame->tramp[0]; -+ end = (unsigned long) &frame->tramp[TRAMP_SIZE]; - flush_user_dcache_range_asm(start, end); - flush_user_icache_range_asm(start, end); - - /* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP -- * TRAMP Words 5-7, Length 3 = SIGRETURN_TRAMP -+ * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP - * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP - */ - rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP]; -diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h -index a5bdbb5678b72..f166250f2d064 100644 ---- a/arch/parisc/kernel/signal32.h -+++ b/arch/parisc/kernel/signal32.h -@@ -36,7 +36,7 @@ struct compat_regfile { - compat_int_t rf_sar; - }; - --#define COMPAT_SIGRETURN_TRAMP 3 -+#define COMPAT_SIGRETURN_TRAMP 4 - #define COMPAT_SIGRESTARTBLOCK_TRAMP 5 - #define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + \ - COMPAT_SIGRESTARTBLOCK_TRAMP) -diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c -index 1405b603b91b6..cf92ece20b757 100644 ---- a/arch/parisc/kernel/smp.c -+++ b/arch/parisc/kernel/smp.c -@@ -29,6 +29,7 @@ - #include <linux/bitops.h> - #include <linux/ftrace.h> - #include <linux/cpu.h> -+#include <linux/kgdb.h> - - #include <linux/atomic.h> - #include <asm/current.h> -@@ -69,7 +70,10 @@ enum ipi_message_type { - IPI_CALL_FUNC, - IPI_CPU_START, - IPI_CPU_STOP, -- IPI_CPU_TEST -+ IPI_CPU_TEST, -+#ifdef CONFIG_KGDB -+ IPI_ENTER_KGDB, -+#endif - }; - - -@@ -167,7 +171,12 @@ ipi_interrupt(int irq, void *dev_id) - case IPI_CPU_TEST: - smp_debug(100, KERN_DEBUG "CPU%d is alive!\n", this_cpu); - break; -- -+#ifdef CONFIG_KGDB -+ case IPI_ENTER_KGDB: -+ smp_debug(100, KERN_DEBUG "CPU%d ENTER_KGDB\n", this_cpu); -+ kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); -+ break; -+#endif - default: - printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", - this_cpu, which); -@@ -226,6 +235,12 @@ send_IPI_allbutself(enum ipi_message_type op) - } - } - -+#ifdef CONFIG_KGDB -+void kgdb_roundup_cpus(void) -+{ -+ send_IPI_allbutself(IPI_ENTER_KGDB); -+} -+#endif - - inline void - smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } -diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c -index 9fb1e794831b0..061119a56fbe8 100644 ---- a/arch/parisc/kernel/time.c -+++ b/arch/parisc/kernel/time.c -@@ -249,30 +249,16 @@ void __init time_init(void) - static int __init init_cr16_clocksource(void) - { - /* -- * The cr16 interval timers are not syncronized across CPUs on -- * different sockets, so mark them unstable and lower rating on -- * multi-socket SMP systems. -+ * The cr16 interval timers are not syncronized across CPUs, even if -+ * they share the same socket. - */ - if (num_online_cpus() > 1 && !running_on_qemu) { -- int cpu; -- unsigned long cpu0_loc; -- cpu0_loc = per_cpu(cpu_data, 0).cpu_loc; -- -- for_each_online_cpu(cpu) { -- if (cpu == 0) -- continue; -- if ((cpu0_loc != 0) && -- (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc)) -- continue; -- -- /* mark sched_clock unstable */ -- clear_sched_clock_stable(); -- -- clocksource_cr16.name = "cr16_unstable"; -- clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; -- clocksource_cr16.rating = 0; -- break; -- } -+ /* mark sched_clock unstable */ -+ clear_sched_clock_stable(); -+ -+ clocksource_cr16.name = "cr16_unstable"; -+ clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; -+ clocksource_cr16.rating = 0; - } - - /* register at clocksource framework */ -diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c -index 87ae476d1c4f5..86a57fb0e6fae 100644 ---- a/arch/parisc/kernel/unwind.c -+++ b/arch/parisc/kernel/unwind.c -@@ -21,6 +21,8 @@ - #include <asm/ptrace.h> - - #include <asm/unwind.h> -+#include <asm/switch_to.h> -+#include <asm/sections.h> - - /* #define DEBUG 1 */ - #ifdef DEBUG -@@ -203,6 +205,11 @@ int __init unwind_init(void) - return 0; - } - -+static bool pc_is_kernel_fn(unsigned long pc, void *fn) -+{ -+ return (unsigned long)dereference_kernel_function_descriptor(fn) == pc; -+} -+ - static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) - { - /* -@@ -221,7 +228,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int - extern void * const _call_on_stack; - #endif /* CONFIG_IRQSTACKS */ - -- if (pc == (unsigned long) &handle_interruption) { -+ if (pc_is_kernel_fn(pc, handle_interruption)) { - struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); - dbg("Unwinding through handle_interruption()\n"); - info->prev_sp = regs->gr[30]; -@@ -229,13 +236,13 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int - return 1; - } - -- if (pc == (unsigned long) &ret_from_kernel_thread || -- pc == (unsigned long) &syscall_exit) { -+ if (pc_is_kernel_fn(pc, ret_from_kernel_thread) || -+ pc_is_kernel_fn(pc, syscall_exit)) { - info->prev_sp = info->prev_ip = 0; - return 1; - } - -- if (pc == (unsigned long) &intr_return) { -+ if (pc_is_kernel_fn(pc, intr_return)) { - struct pt_regs *regs; - - dbg("Found intr_return()\n"); -@@ -246,20 +253,20 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int - return 1; - } - -- if (pc == (unsigned long) &_switch_to_ret) { -+ if (pc_is_kernel_fn(pc, _switch_to) || -+ pc_is_kernel_fn(pc, _switch_to_ret)) { - info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; - info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); - return 1; - } - - #ifdef CONFIG_IRQSTACKS -- if (pc == (unsigned long) &_call_on_stack) { -+ if (pc_is_kernel_fn(pc, _call_on_stack)) { - info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ); - info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET); - return 1; - } - #endif -- - return 0; - } - -diff --git a/arch/parisc/mm/fixmap.c b/arch/parisc/mm/fixmap.c -index 24426a7e1a5e5..cc15d737fda64 100644 ---- a/arch/parisc/mm/fixmap.c -+++ b/arch/parisc/mm/fixmap.c -@@ -20,12 +20,9 @@ void notrace set_fixmap(enum fixed_addresses idx, phys_addr_t phys) - pte_t *pte; - - if (pmd_none(*pmd)) -- pmd = pmd_alloc(NULL, pud, vaddr); -- -- pte = pte_offset_kernel(pmd, vaddr); -- if (pte_none(*pte)) - pte = pte_alloc_kernel(pmd, vaddr); - -+ pte = pte_offset_kernel(pmd, vaddr); - set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); - flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); - } -diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c -index 3f7d6d5b56ac8..65f50f072a87b 100644 ---- a/arch/parisc/mm/init.c -+++ b/arch/parisc/mm/init.c -@@ -842,9 +842,9 @@ void flush_tlb_all(void) - { - int do_recycle; - -- __inc_irq_stat(irq_tlb_count); - do_recycle = 0; - spin_lock(&sid_lock); -+ __inc_irq_stat(irq_tlb_count); - if (dirty_space_ids > RECYCLE_THRESHOLD) { - BUG_ON(recycle_inuse); /* FIXME: Use a semaphore/wait queue here */ - get_dirty_sids(&recycle_ndirty,recycle_dirty_array); -@@ -863,8 +863,8 @@ void flush_tlb_all(void) - #else - void flush_tlb_all(void) - { -- __inc_irq_stat(irq_tlb_count); - spin_lock(&sid_lock); -+ __inc_irq_stat(irq_tlb_count); - flush_tlb_all_local(NULL); - recycle_sids(); - spin_unlock(&sid_lock); -diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig -index ba5b661893588..6b9f523882c58 100644 ---- a/arch/powerpc/Kconfig -+++ b/arch/powerpc/Kconfig -@@ -138,7 +138,7 @@ config PPC - select ARCH_HAS_PTE_SPECIAL - select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64 - select ARCH_HAS_SET_MEMORY -- select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION) -+ select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION - select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32 - select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST - select ARCH_HAS_UACCESS_FLUSHCACHE -@@ -150,7 +150,7 @@ config PPC - select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX - select ARCH_STACKWALK - select ARCH_SUPPORTS_ATOMIC_RMW -- select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC32 || PPC_BOOK3S_64 -+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x - select ARCH_USE_BUILTIN_BSWAP - select ARCH_USE_CMPXCHG_LOCKREF if PPC64 - select ARCH_USE_MEMTEST -@@ -190,7 +190,7 @@ config PPC - select HAVE_ARCH_JUMP_LABEL_RELATIVE - select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14 - select HAVE_ARCH_KASAN_VMALLOC if PPC32 && PPC_PAGE_SHIFT <= 14 -- select HAVE_ARCH_KFENCE if PPC32 -+ select HAVE_ARCH_KFENCE if PPC_BOOK3S_32 || PPC_8xx || 40x - select HAVE_ARCH_KGDB - select HAVE_ARCH_MMAP_RND_BITS - select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT -diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts -index 408b486b13dff..cd589539f313f 100644 ---- a/arch/powerpc/boot/dts/charon.dts -+++ b/arch/powerpc/boot/dts/charon.dts -@@ -35,7 +35,7 @@ - }; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x08000000>; // 128MB - }; -diff --git a/arch/powerpc/boot/dts/digsy_mtc.dts b/arch/powerpc/boot/dts/digsy_mtc.dts -index 0e5e9d3acf79f..19a14e62e65f4 100644 ---- a/arch/powerpc/boot/dts/digsy_mtc.dts -+++ b/arch/powerpc/boot/dts/digsy_mtc.dts -@@ -16,7 +16,7 @@ - model = "intercontrol,digsy-mtc"; - compatible = "intercontrol,digsy-mtc"; - -- memory { -+ memory@0 { - reg = <0x00000000 0x02000000>; // 32MB - }; - -diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts -index cb2782dd6132c..e7b194775d783 100644 ---- a/arch/powerpc/boot/dts/lite5200.dts -+++ b/arch/powerpc/boot/dts/lite5200.dts -@@ -32,7 +32,7 @@ - }; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x04000000>; // 64MB - }; -diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts -index 2b86c81f90485..547cbe726ff23 100644 ---- a/arch/powerpc/boot/dts/lite5200b.dts -+++ b/arch/powerpc/boot/dts/lite5200b.dts -@@ -31,7 +31,7 @@ - led4 { gpios = <&gpio_simple 2 1>; }; - }; - -- memory { -+ memory@0 { - reg = <0x00000000 0x10000000>; // 256MB - }; - -diff --git a/arch/powerpc/boot/dts/media5200.dts b/arch/powerpc/boot/dts/media5200.dts -index 61cae9dcddef4..f3188018faceb 100644 ---- a/arch/powerpc/boot/dts/media5200.dts -+++ b/arch/powerpc/boot/dts/media5200.dts -@@ -32,7 +32,7 @@ - }; - }; - -- memory { -+ memory@0 { - reg = <0x00000000 0x08000000>; // 128MB RAM - }; - -diff --git a/arch/powerpc/boot/dts/mpc5200b.dtsi b/arch/powerpc/boot/dts/mpc5200b.dtsi -index 648fe31795f49..8b796f3b11da7 100644 ---- a/arch/powerpc/boot/dts/mpc5200b.dtsi -+++ b/arch/powerpc/boot/dts/mpc5200b.dtsi -@@ -33,7 +33,7 @@ - }; - }; - -- memory: memory { -+ memory: memory@0 { - device_type = "memory"; - reg = <0x00000000 0x04000000>; // 64MB - }; -diff --git a/arch/powerpc/boot/dts/o2d.dts b/arch/powerpc/boot/dts/o2d.dts -index 24a46f65e5299..e0a8d3034417f 100644 ---- a/arch/powerpc/boot/dts/o2d.dts -+++ b/arch/powerpc/boot/dts/o2d.dts -@@ -12,7 +12,7 @@ - model = "ifm,o2d"; - compatible = "ifm,o2d"; - -- memory { -+ memory@0 { - reg = <0x00000000 0x08000000>; // 128MB - }; - -diff --git a/arch/powerpc/boot/dts/o2d.dtsi b/arch/powerpc/boot/dts/o2d.dtsi -index 6661955a2be47..b55a9e5bd828c 100644 ---- a/arch/powerpc/boot/dts/o2d.dtsi -+++ b/arch/powerpc/boot/dts/o2d.dtsi -@@ -19,7 +19,7 @@ - model = "ifm,o2d"; - compatible = "ifm,o2d"; - -- memory { -+ memory@0 { - reg = <0x00000000 0x04000000>; // 64MB - }; - -diff --git a/arch/powerpc/boot/dts/o2dnt2.dts b/arch/powerpc/boot/dts/o2dnt2.dts -index eeba7f5507d5d..c2eedbd1f5fcb 100644 ---- a/arch/powerpc/boot/dts/o2dnt2.dts -+++ b/arch/powerpc/boot/dts/o2dnt2.dts -@@ -12,7 +12,7 @@ - model = "ifm,o2dnt2"; - compatible = "ifm,o2d"; - -- memory { -+ memory@0 { - reg = <0x00000000 0x08000000>; // 128MB - }; - -diff --git a/arch/powerpc/boot/dts/o3dnt.dts b/arch/powerpc/boot/dts/o3dnt.dts -index fd00396b0593e..e4c1bdd412716 100644 ---- a/arch/powerpc/boot/dts/o3dnt.dts -+++ b/arch/powerpc/boot/dts/o3dnt.dts -@@ -12,7 +12,7 @@ - model = "ifm,o3dnt"; - compatible = "ifm,o2d"; - -- memory { -+ memory@0 { - reg = <0x00000000 0x04000000>; // 64MB - }; - -diff --git a/arch/powerpc/boot/dts/pcm032.dts b/arch/powerpc/boot/dts/pcm032.dts -index 780e13d99e7b8..1895bc95900cc 100644 ---- a/arch/powerpc/boot/dts/pcm032.dts -+++ b/arch/powerpc/boot/dts/pcm032.dts -@@ -20,7 +20,7 @@ - model = "phytec,pcm032"; - compatible = "phytec,pcm032"; - -- memory { -+ memory@0 { - reg = <0x00000000 0x08000000>; // 128MB - }; - -diff --git a/arch/powerpc/boot/dts/tqm5200.dts b/arch/powerpc/boot/dts/tqm5200.dts -index 9ed0bc78967e1..5bb25a9e40a01 100644 ---- a/arch/powerpc/boot/dts/tqm5200.dts -+++ b/arch/powerpc/boot/dts/tqm5200.dts -@@ -32,7 +32,7 @@ - }; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x00000000 0x04000000>; // 64MB - }; -diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h -index f06ae00f2a65e..d6ba821a56ced 100644 ---- a/arch/powerpc/include/asm/nohash/32/pgtable.h -+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h -@@ -193,10 +193,12 @@ static inline pte_t pte_wrprotect(pte_t pte) - } - #endif - -+#ifndef pte_mkexec - static inline pte_t pte_mkexec(pte_t pte) - { - return __pte(pte_val(pte) | _PAGE_EXEC); - } -+#endif - - #define pmd_none(pmd) (!pmd_val(pmd)) - #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) -@@ -306,30 +308,29 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, - } - - #define __HAVE_ARCH_PTEP_SET_WRPROTECT -+#ifndef ptep_set_wrprotect - static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) - { -- unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0))); -- unsigned long set = pte_val(pte_wrprotect(__pte(0))); -- -- pte_update(mm, addr, ptep, clr, set, 0); -+ pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); - } -+#endif - -+#ifndef __ptep_set_access_flags - static inline void __ptep_set_access_flags(struct vm_area_struct *vma, - pte_t *ptep, pte_t entry, - unsigned long address, - int psize) - { -- pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0))))); -- pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0))))); -- unsigned long set = pte_val(entry) & pte_val(pte_set); -- unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr); -+ unsigned long set = pte_val(entry) & -+ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); - int huge = psize > mmu_virtual_psize ? 1 : 0; - -- pte_update(vma->vm_mm, address, ptep, clr, set, huge); -+ pte_update(vma->vm_mm, address, ptep, 0, set, huge); - - flush_tlb_page(vma, address); - } -+#endif - - static inline int pte_young(pte_t pte) - { -diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h -index fcc48d590d888..1a89ebdc3acc9 100644 ---- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h -+++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h -@@ -136,6 +136,28 @@ static inline pte_t pte_mkhuge(pte_t pte) - - #define pte_mkhuge pte_mkhuge - -+static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, -+ unsigned long clr, unsigned long set, int huge); -+ -+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) -+{ -+ pte_update(mm, addr, ptep, 0, _PAGE_RO, 0); -+} -+#define ptep_set_wrprotect ptep_set_wrprotect -+ -+static inline void __ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, -+ pte_t entry, unsigned long address, int psize) -+{ -+ unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_EXEC); -+ unsigned long clr = ~pte_val(entry) & _PAGE_RO; -+ int huge = psize > mmu_virtual_psize ? 1 : 0; -+ -+ pte_update(vma->vm_mm, address, ptep, clr, set, huge); -+ -+ flush_tlb_page(vma, address); -+} -+#define __ptep_set_access_flags __ptep_set_access_flags -+ - static inline unsigned long pgd_leaf_size(pgd_t pgd) - { - if (pgd_val(pgd) & _PMD_PAGE_8M) -diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h -index d081704b13fb9..9d2905a474103 100644 ---- a/arch/powerpc/include/asm/nohash/64/pgtable.h -+++ b/arch/powerpc/include/asm/nohash/64/pgtable.h -@@ -118,11 +118,6 @@ static inline pte_t pte_wrprotect(pte_t pte) - return __pte(pte_val(pte) & ~_PAGE_RW); - } - --static inline pte_t pte_mkexec(pte_t pte) --{ -- return __pte(pte_val(pte) | _PAGE_EXEC); --} -- - #define PMD_BAD_BITS (PTE_TABLE_SIZE-1) - #define PUD_BAD_BITS (PMD_TABLE_SIZE-1) - -diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h -index 813918f407653..f798640422c2d 100644 ---- a/arch/powerpc/include/asm/nohash/pte-book3e.h -+++ b/arch/powerpc/include/asm/nohash/pte-book3e.h -@@ -48,7 +48,7 @@ - #define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */ - - /* "Higher level" linux bit combinations */ --#define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */ -+#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */ - #define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ - #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY) - #define _PAGE_KERNEL_RO (_PAGE_BAP_SR) -@@ -93,11 +93,11 @@ - /* Permission masks used to generate the __P and __S table */ - #define PAGE_NONE __pgprot(_PAGE_BASE) - #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) --#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) -+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX) - #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) --#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX) - #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) --#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX) - - #ifndef __ASSEMBLY__ - static inline pte_t pte_mkprivileged(pte_t pte) -@@ -113,6 +113,16 @@ static inline pte_t pte_mkuser(pte_t pte) - } - - #define pte_mkuser pte_mkuser -+ -+static inline pte_t pte_mkexec(pte_t pte) -+{ -+ if (pte_val(pte) & _PAGE_BAP_UR) -+ return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX); -+ else -+ return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX); -+} -+#define pte_mkexec pte_mkexec -+ - #endif /* __ASSEMBLY__ */ - - #endif /* __KERNEL__ */ -diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h -index bcb7b5f917be6..b325022ffa2b0 100644 ---- a/arch/powerpc/include/asm/paravirt.h -+++ b/arch/powerpc/include/asm/paravirt.h -@@ -97,7 +97,23 @@ static inline bool vcpu_is_preempted(int cpu) - - #ifdef CONFIG_PPC_SPLPAR - if (!is_kvm_guest()) { -- int first_cpu = cpu_first_thread_sibling(smp_processor_id()); -+ int first_cpu; -+ -+ /* -+ * The result of vcpu_is_preempted() is used in a -+ * speculative way, and is always subject to invalidation -+ * by events internal and external to Linux. While we can -+ * be called in preemptable context (in the Linux sense), -+ * we're not accessing per-cpu resources in a way that can -+ * race destructively with Linux scheduler preemption and -+ * migration, and callers can tolerate the potential for -+ * error introduced by sampling the CPU index without -+ * pinning the task to it. So it is permissible to use -+ * raw_smp_processor_id() here to defeat the preempt debug -+ * warnings that can arise from using smp_processor_id() -+ * in arbitrary contexts. -+ */ -+ first_cpu = cpu_first_thread_sibling(raw_smp_processor_id()); - - /* - * Preemption can only happen at core granularity. This CPU -diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile -index 7be36c1e1db6d..86e40db2dec56 100644 ---- a/arch/powerpc/kernel/Makefile -+++ b/arch/powerpc/kernel/Makefile -@@ -196,3 +196,6 @@ clean-files := vmlinux.lds - # Force dependency (incbin is bad) - $(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg - $(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg -+ -+# for cleaning -+subdir- += vdso32 vdso64 -diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c -index c7022c41cc314..20328f72f9f2b 100644 ---- a/arch/powerpc/kernel/firmware.c -+++ b/arch/powerpc/kernel/firmware.c -@@ -31,11 +31,10 @@ int __init check_kvm_guest(void) - if (!hyper_node) - return 0; - -- if (!of_device_is_compatible(hyper_node, "linux,kvm")) -- return 0; -- -- static_branch_enable(&kvm_guest); -+ if (of_device_is_compatible(hyper_node, "linux,kvm")) -+ static_branch_enable(&kvm_guest); - -+ of_node_put(hyper_node); - return 0; - } - core_initcall(check_kvm_guest); // before kvm_guest_init() -diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h -index 6b1ec9e3541b9..349c4a820231b 100644 ---- a/arch/powerpc/kernel/head_32.h -+++ b/arch/powerpc/kernel/head_32.h -@@ -202,11 +202,11 @@ vmap_stack_overflow: - mfspr r1, SPRN_SPRG_THREAD - lwz r1, TASK_CPU - THREAD(r1) - slwi r1, r1, 3 -- addis r1, r1, emergency_ctx@ha -+ addis r1, r1, emergency_ctx-PAGE_OFFSET@ha - #else -- lis r1, emergency_ctx@ha -+ lis r1, emergency_ctx-PAGE_OFFSET@ha - #endif -- lwz r1, emergency_ctx@l(r1) -+ lwz r1, emergency_ctx-PAGE_OFFSET@l(r1) - addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE - EXCEPTION_PROLOG_2 0 vmap_stack_overflow - prepare_transfer_to_handler -diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S -index 9bdb95f5694f7..0d073b9fd52c5 100644 ---- a/arch/powerpc/kernel/head_8xx.S -+++ b/arch/powerpc/kernel/head_8xx.S -@@ -733,6 +733,7 @@ _GLOBAL(mmu_pin_tlb) - #ifdef CONFIG_PIN_TLB_DATA - LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET) - LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED) -+ li r8, 0 - #ifdef CONFIG_PIN_TLB_IMMR - li r0, 3 - #else -@@ -741,26 +742,26 @@ _GLOBAL(mmu_pin_tlb) - mtctr r0 - cmpwi r4, 0 - beq 4f -- LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT) - LOAD_REG_ADDR(r9, _sinittext) - - 2: ori r0, r6, MD_EVALID -+ ori r12, r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT - mtspr SPRN_MD_CTR, r5 - mtspr SPRN_MD_EPN, r0 - mtspr SPRN_MD_TWC, r7 -- mtspr SPRN_MD_RPN, r8 -+ mtspr SPRN_MD_RPN, r12 - addi r5, r5, 0x100 - addis r6, r6, SZ_8M@h - addis r8, r8, SZ_8M@h - cmplw r6, r9 - bdnzt lt, 2b -- --4: LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT) -+4: - 2: ori r0, r6, MD_EVALID -+ ori r12, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT - mtspr SPRN_MD_CTR, r5 - mtspr SPRN_MD_EPN, r0 - mtspr SPRN_MD_TWC, r7 -- mtspr SPRN_MD_RPN, r8 -+ mtspr SPRN_MD_RPN, r12 - addi r5, r5, 0x100 - addis r6, r6, SZ_8M@h - addis r8, r8, SZ_8M@h -@@ -781,7 +782,7 @@ _GLOBAL(mmu_pin_tlb) - #endif - #if defined(CONFIG_PIN_TLB_IMMR) || defined(CONFIG_PIN_TLB_DATA) - lis r0, (MD_RSV4I | MD_TWAM)@h -- mtspr SPRN_MI_CTR, r0 -+ mtspr SPRN_MD_CTR, r0 - #endif - mtspr SPRN_SRR1, r10 - mtspr SPRN_SRR0, r11 -diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h -index e5503420b6c6d..ef8d1b1c234e7 100644 ---- a/arch/powerpc/kernel/head_booke.h -+++ b/arch/powerpc/kernel/head_booke.h -@@ -465,12 +465,21 @@ label: - bl do_page_fault; \ - b interrupt_return - -+/* -+ * Instruction TLB Error interrupt handlers may call InstructionStorage -+ * directly without clearing ESR, so the ESR at this point may be left over -+ * from a prior interrupt. -+ * -+ * In any case, do_page_fault for BOOK3E does not use ESR and always expects -+ * dsisr to be 0. ESR_DST from a prior store in particular would confuse fault -+ * handling. -+ */ - #define INSTRUCTION_STORAGE_EXCEPTION \ - START_EXCEPTION(InstructionStorage) \ -- NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \ -- mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ -+ NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \ -+ li r5,0; /* Store 0 in regs->esr (dsisr) */ \ - stw r5,_ESR(r11); \ -- stw r12, _DEAR(r11); /* Pass SRR0 as arg2 */ \ -+ stw r12, _DEAR(r11); /* Set regs->dear (dar) to SRR0 */ \ - prepare_transfer_to_handler; \ - bl do_page_fault; \ - b interrupt_return -diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c -index de10a26972581..835b626cd4760 100644 ---- a/arch/powerpc/kernel/interrupt.c -+++ b/arch/powerpc/kernel/interrupt.c -@@ -266,7 +266,7 @@ static void check_return_regs_valid(struct pt_regs *regs) - if (trap_is_scv(regs)) - return; - -- trap = regs->trap; -+ trap = TRAP(regs); - // EE in HV mode sets HSRRs like 0xea0 - if (cpu_has_feature(CPU_FTR_HVMODE) && trap == INTERRUPT_EXTERNAL) - trap = 0xea0; -diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c -index 6baa676e7cb60..5d77d3f5fbb56 100644 ---- a/arch/powerpc/kernel/module_64.c -+++ b/arch/powerpc/kernel/module_64.c -@@ -422,11 +422,17 @@ static inline int create_stub(const Elf64_Shdr *sechdrs, - const char *name) - { - long reladdr; -+ func_desc_t desc; -+ int i; - - if (is_mprofile_ftrace_call(name)) - return create_ftrace_stub(entry, addr, me); - -- memcpy(entry->jump, ppc64_stub_insns, sizeof(ppc64_stub_insns)); -+ for (i = 0; i < sizeof(ppc64_stub_insns) / sizeof(u32); i++) { -+ if (patch_instruction(&entry->jump[i], -+ ppc_inst(ppc64_stub_insns[i]))) -+ return 0; -+ } - - /* Stub uses address relative to r2. */ - reladdr = (unsigned long)entry - my_r2(sechdrs, me); -@@ -437,10 +443,24 @@ static inline int create_stub(const Elf64_Shdr *sechdrs, - } - pr_debug("Stub %p get data from reladdr %li\n", entry, reladdr); - -- entry->jump[0] |= PPC_HA(reladdr); -- entry->jump[1] |= PPC_LO(reladdr); -- entry->funcdata = func_desc(addr); -- entry->magic = STUB_MAGIC; -+ if (patch_instruction(&entry->jump[0], -+ ppc_inst(entry->jump[0] | PPC_HA(reladdr)))) -+ return 0; -+ -+ if (patch_instruction(&entry->jump[1], -+ ppc_inst(entry->jump[1] | PPC_LO(reladdr)))) -+ return 0; -+ -+ // func_desc_t is 8 bytes if ABIv2, else 16 bytes -+ desc = func_desc(addr); -+ for (i = 0; i < sizeof(func_desc_t) / sizeof(u32); i++) { -+ if (patch_instruction(((u32 *)&entry->funcdata) + i, -+ ppc_inst(((u32 *)(&desc))[i]))) -+ return 0; -+ } -+ -+ if (patch_instruction(&entry->magic, ppc_inst(STUB_MAGIC))) -+ return 0; - - return 1; - } -@@ -495,8 +515,11 @@ static int restore_r2(const char *name, u32 *instruction, struct module *me) - me->name, *instruction, instruction); - return 0; - } -+ - /* ld r2,R2_STACK_OFFSET(r1) */ -- *instruction = PPC_INST_LD_TOC; -+ if (patch_instruction(instruction, ppc_inst(PPC_INST_LD_TOC))) -+ return 0; -+ - return 1; - } - -@@ -636,9 +659,12 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, - } - - /* Only replace bits 2 through 26 */ -- *(uint32_t *)location -- = (*(uint32_t *)location & ~0x03fffffc) -+ value = (*(uint32_t *)location & ~0x03fffffc) - | (value & 0x03fffffc); -+ -+ if (patch_instruction((u32 *)location, ppc_inst(value))) -+ return -EFAULT; -+ - break; - - case R_PPC64_REL64: -diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h -index 1f07317964e49..618aeccdf6918 100644 ---- a/arch/powerpc/kernel/signal.h -+++ b/arch/powerpc/kernel/signal.h -@@ -25,8 +25,14 @@ static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src) - - return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]); - } --#define unsafe_get_user_sigset(dst, src, label) \ -- unsafe_get_user((dst)->sig[0], (u64 __user *)&(src)->sig[0], label) -+#define unsafe_get_user_sigset(dst, src, label) do { \ -+ sigset_t *__dst = dst; \ -+ const sigset_t __user *__src = src; \ -+ int i; \ -+ \ -+ for (i = 0; i < _NSIG_WORDS; i++) \ -+ unsafe_get_user(__dst->sig[i], &__src->sig[i], label); \ -+} while (0) - - #ifdef CONFIG_VSX - extern unsigned long copy_vsx_to_user(void __user *to, -diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c -index 0608581967f09..f2da879264bcd 100644 ---- a/arch/powerpc/kernel/signal_32.c -+++ b/arch/powerpc/kernel/signal_32.c -@@ -1062,8 +1062,10 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, - * or if another thread unmaps the region containing the context. - * We kill the task with a SIGSEGV in this situation. - */ -- if (do_setcontext(new_ctx, regs, 0)) -- do_exit(SIGSEGV); -+ if (do_setcontext(new_ctx, regs, 0)) { -+ force_exit_sig(SIGSEGV); -+ return -EFAULT; -+ } - - set_thread_flag(TIF_RESTOREALL); - return 0; -diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c -index 1831bba0582e1..bb9c077ac1322 100644 ---- a/arch/powerpc/kernel/signal_64.c -+++ b/arch/powerpc/kernel/signal_64.c -@@ -703,15 +703,18 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, - * We kill the task with a SIGSEGV in this situation. - */ - -- if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) -- do_exit(SIGSEGV); -+ if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) { -+ force_exit_sig(SIGSEGV); -+ return -EFAULT; -+ } - set_current_blocked(&set); - - if (!user_read_access_begin(new_ctx, ctx_size)) - return -EFAULT; - if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) { - user_read_access_end(); -- do_exit(SIGSEGV); -+ force_exit_sig(SIGSEGV); -+ return -EFAULT; - } - user_read_access_end(); - -diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c -index f9ea0e5357f92..3fa6d240bade2 100644 ---- a/arch/powerpc/kernel/watchdog.c -+++ b/arch/powerpc/kernel/watchdog.c -@@ -187,6 +187,12 @@ static void watchdog_smp_panic(int cpu, u64 tb) - if (sysctl_hardlockup_all_cpu_backtrace) - trigger_allbutself_cpu_backtrace(); - -+ /* -+ * Force flush any remote buffers that might be stuck in IRQ context -+ * and therefore could not run their irq_work. -+ */ -+ printk_trigger_flush(); -+ - if (hardlockup_panic) - nmi_panic(NULL, "Hard LOCKUP"); - -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 2acb1c96cfafd..7b74fc0a986b8 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -3726,7 +3726,20 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) - - kvmppc_set_host_core(pcpu); - -- guest_exit_irqoff(); -+ context_tracking_guest_exit(); -+ if (!vtime_accounting_enabled_this_cpu()) { -+ local_irq_enable(); -+ /* -+ * Service IRQs here before vtime_account_guest_exit() so any -+ * ticks that occurred while running the guest are accounted to -+ * the guest. If vtime accounting is enabled, accounting uses -+ * TB rather than ticks, so it can be done without enabling -+ * interrupts here, which has the problem that it accounts -+ * interrupt processing overhead to the host. -+ */ -+ local_irq_disable(); -+ } -+ vtime_account_guest_exit(); - - local_irq_enable(); - -@@ -4510,7 +4523,20 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, - - kvmppc_set_host_core(pcpu); - -- guest_exit_irqoff(); -+ context_tracking_guest_exit(); -+ if (!vtime_accounting_enabled_this_cpu()) { -+ local_irq_enable(); -+ /* -+ * Service IRQs here before vtime_account_guest_exit() so any -+ * ticks that occurred while running the guest are accounted to -+ * the guest. If vtime accounting is enabled, accounting uses -+ * TB rather than ticks, so it can be done without enabling -+ * interrupts here, which has the problem that it accounts -+ * interrupt processing overhead to the host. -+ */ -+ local_irq_disable(); -+ } -+ vtime_account_guest_exit(); - - local_irq_enable(); - -diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c -index fcf4760a3a0ea..70b7a8f971538 100644 ---- a/arch/powerpc/kvm/book3s_hv_builtin.c -+++ b/arch/powerpc/kvm/book3s_hv_builtin.c -@@ -695,6 +695,7 @@ static void flush_guest_tlb(struct kvm *kvm) - "r" (0) : "memory"); - } - asm volatile("ptesync": : :"memory"); -+ // POWER9 congruence-class TLBIEL leaves ERAT. Flush it now. - asm volatile(PPC_RADIX_INVALIDATE_ERAT_GUEST : : :"memory"); - } else { - for (set = 0; set < kvm->arch.tlb_sets; ++set) { -@@ -705,7 +706,9 @@ static void flush_guest_tlb(struct kvm *kvm) - rb += PPC_BIT(51); /* increment set number */ - } - asm volatile("ptesync": : :"memory"); -- asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); -+ // POWER9 congruence-class TLBIEL leaves ERAT. Flush it now. -+ if (cpu_has_feature(CPU_FTR_ARCH_300)) -+ asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); - } - } - -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index eb776d0c5d8e9..32a4b4d412b92 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -2005,7 +2005,7 @@ hcall_real_table: - .globl hcall_real_table_end - hcall_real_table_end: - --_GLOBAL(kvmppc_h_set_xdabr) -+_GLOBAL_TOC(kvmppc_h_set_xdabr) - EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr) - andi. r0, r5, DABRX_USER | DABRX_KERNEL - beq 6f -@@ -2015,7 +2015,7 @@ EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr) - 6: li r3, H_PARAMETER - blr - --_GLOBAL(kvmppc_h_set_dabr) -+_GLOBAL_TOC(kvmppc_h_set_dabr) - EXPORT_SYMBOL_GPL(kvmppc_h_set_dabr) - li r5, DABRX_USER | DABRX_KERNEL - 3: -diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c -index 977801c83aff8..8c15c90dd3a97 100644 ---- a/arch/powerpc/kvm/booke.c -+++ b/arch/powerpc/kvm/booke.c -@@ -1042,7 +1042,21 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr) - } - - trace_kvm_exit(exit_nr, vcpu); -- guest_exit_irqoff(); -+ -+ context_tracking_guest_exit(); -+ if (!vtime_accounting_enabled_this_cpu()) { -+ local_irq_enable(); -+ /* -+ * Service IRQs here before vtime_account_guest_exit() so any -+ * ticks that occurred while running the guest are accounted to -+ * the guest. If vtime accounting is enabled, accounting uses -+ * TB rather than ticks, so it can be done without enabling -+ * interrupts here, which has the problem that it accounts -+ * interrupt processing overhead to the host. -+ */ -+ local_irq_disable(); -+ } -+ vtime_account_guest_exit(); - - local_irq_enable(); - -diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c -index cda17bee5afea..c3e06922468b3 100644 ---- a/arch/powerpc/lib/feature-fixups.c -+++ b/arch/powerpc/lib/feature-fixups.c -@@ -228,6 +228,7 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types) - - static bool stf_exit_reentrant = false; - static bool rfi_exit_reentrant = false; -+static DEFINE_MUTEX(exit_flush_lock); - - static int __do_stf_barrier_fixups(void *data) - { -@@ -253,6 +254,9 @@ void do_stf_barrier_fixups(enum stf_barrier_type types) - * low level interrupt exit code before patching. After the patching, - * if allowed, then flip the branch to allow fast exits. - */ -+ -+ // Prevent static key update races with do_rfi_flush_fixups() -+ mutex_lock(&exit_flush_lock); - static_branch_enable(&interrupt_exit_not_reentrant); - - stop_machine(__do_stf_barrier_fixups, &types, NULL); -@@ -264,6 +268,8 @@ void do_stf_barrier_fixups(enum stf_barrier_type types) - - if (stf_exit_reentrant && rfi_exit_reentrant) - static_branch_disable(&interrupt_exit_not_reentrant); -+ -+ mutex_unlock(&exit_flush_lock); - } - - void do_uaccess_flush_fixups(enum l1d_flush_type types) -@@ -486,6 +492,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) - * without stop_machine, so this could be achieved with a broadcast - * IPI instead, but this matches the stf sequence. - */ -+ -+ // Prevent static key update races with do_stf_barrier_fixups() -+ mutex_lock(&exit_flush_lock); - static_branch_enable(&interrupt_exit_not_reentrant); - - stop_machine(__do_rfi_flush_fixups, &types, NULL); -@@ -497,6 +506,8 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) - - if (stf_exit_reentrant && rfi_exit_reentrant) - static_branch_disable(&interrupt_exit_not_reentrant); -+ -+ mutex_unlock(&exit_flush_lock); - } - - void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) -diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c -index c3c4e31462eca..05b9c3f31456c 100644 ---- a/arch/powerpc/mm/mem.c -+++ b/arch/powerpc/mm/mem.c -@@ -20,8 +20,8 @@ - #include <asm/machdep.h> - #include <asm/rtas.h> - #include <asm/kasan.h> --#include <asm/sparsemem.h> - #include <asm/svm.h> -+#include <asm/mmzone.h> - - #include <mm/mmu_decl.h> - -diff --git a/arch/powerpc/mm/nohash/tlb_low_64e.S b/arch/powerpc/mm/nohash/tlb_low_64e.S -index bf24451f3e71f..9235e720e3572 100644 ---- a/arch/powerpc/mm/nohash/tlb_low_64e.S -+++ b/arch/powerpc/mm/nohash/tlb_low_64e.S -@@ -222,7 +222,7 @@ tlb_miss_kernel_bolted: - - tlb_miss_fault_bolted: - /* We need to check if it was an instruction miss */ -- andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX -+ andi. r10,r11,_PAGE_BAP_UX|_PAGE_BAP_SX - bne itlb_miss_fault_bolted - dtlb_miss_fault_bolted: - tlb_epilog_bolted -@@ -239,7 +239,7 @@ itlb_miss_fault_bolted: - srdi r15,r16,60 /* get region */ - bne- itlb_miss_fault_bolted - -- li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */ -+ li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */ - - /* We do the user/kernel test for the PID here along with the RW test - */ -@@ -614,7 +614,7 @@ itlb_miss_fault_e6500: - - /* We do the user/kernel test for the PID here along with the RW test - */ -- li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */ -+ li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */ - oris r11,r11,_PAGE_ACCESSED@h - - cmpldi cr0,r15,0 /* Check for user region */ -@@ -734,7 +734,7 @@ normal_tlb_miss_done: - - normal_tlb_miss_access_fault: - /* We need to check if it was an instruction miss */ -- andi. r10,r11,_PAGE_EXEC -+ andi. r10,r11,_PAGE_BAP_UX - bne 1f - ld r14,EX_TLB_DEAR(r12) - ld r15,EX_TLB_ESR(r12) -diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c -index 6f14c8fb6359d..59d3cfcd78879 100644 ---- a/arch/powerpc/mm/numa.c -+++ b/arch/powerpc/mm/numa.c -@@ -376,9 +376,9 @@ static void initialize_form2_numa_distance_lookup_table(void) - { - int i, j; - struct device_node *root; -- const __u8 *numa_dist_table; -+ const __u8 *form2_distances; - const __be32 *numa_lookup_index; -- int numa_dist_table_length; -+ int form2_distances_length; - int max_numa_index, distance_index; - - if (firmware_has_feature(FW_FEATURE_OPAL)) -@@ -392,45 +392,41 @@ static void initialize_form2_numa_distance_lookup_table(void) - max_numa_index = of_read_number(&numa_lookup_index[0], 1); - - /* first element of the array is the size and is encode-int */ -- numa_dist_table = of_get_property(root, "ibm,numa-distance-table", NULL); -- numa_dist_table_length = of_read_number((const __be32 *)&numa_dist_table[0], 1); -+ form2_distances = of_get_property(root, "ibm,numa-distance-table", NULL); -+ form2_distances_length = of_read_number((const __be32 *)&form2_distances[0], 1); - /* Skip the size which is encoded int */ -- numa_dist_table += sizeof(__be32); -+ form2_distances += sizeof(__be32); - -- pr_debug("numa_dist_table_len = %d, numa_dist_indexes_len = %d\n", -- numa_dist_table_length, max_numa_index); -+ pr_debug("form2_distances_len = %d, numa_dist_indexes_len = %d\n", -+ form2_distances_length, max_numa_index); - - for (i = 0; i < max_numa_index; i++) - /* +1 skip the max_numa_index in the property */ - numa_id_index_table[i] = of_read_number(&numa_lookup_index[i + 1], 1); - - -- if (numa_dist_table_length != max_numa_index * max_numa_index) { -+ if (form2_distances_length != max_numa_index * max_numa_index) { - WARN(1, "Wrong NUMA distance information\n"); -- /* consider everybody else just remote. */ -- for (i = 0; i < max_numa_index; i++) { -- for (j = 0; j < max_numa_index; j++) { -- int nodeA = numa_id_index_table[i]; -- int nodeB = numa_id_index_table[j]; -- -- if (nodeA == nodeB) -- numa_distance_table[nodeA][nodeB] = LOCAL_DISTANCE; -- else -- numa_distance_table[nodeA][nodeB] = REMOTE_DISTANCE; -- } -- } -+ form2_distances = NULL; // don't use it - } -- - distance_index = 0; - for (i = 0; i < max_numa_index; i++) { - for (j = 0; j < max_numa_index; j++) { - int nodeA = numa_id_index_table[i]; - int nodeB = numa_id_index_table[j]; -- -- numa_distance_table[nodeA][nodeB] = numa_dist_table[distance_index++]; -- pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, numa_distance_table[nodeA][nodeB]); -+ int dist; -+ -+ if (form2_distances) -+ dist = form2_distances[distance_index++]; -+ else if (nodeA == nodeB) -+ dist = LOCAL_DISTANCE; -+ else -+ dist = REMOTE_DISTANCE; -+ numa_distance_table[nodeA][nodeB] = dist; -+ pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, dist); - } - } -+ - of_node_put(root); - } - -diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c -index dcf5ecca19d99..fde1ed445ca46 100644 ---- a/arch/powerpc/mm/pgtable_32.c -+++ b/arch/powerpc/mm/pgtable_32.c -@@ -173,7 +173,7 @@ void mark_rodata_ro(void) - } - #endif - --#ifdef CONFIG_DEBUG_PAGEALLOC -+#if defined(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) && defined(CONFIG_DEBUG_PAGEALLOC) - void __kernel_map_pages(struct page *page, int numpages, int enable) - { - unsigned long addr = (unsigned long)page_address(page); -diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c -index fcbf7a917c566..90ce75f0f1e2a 100644 ---- a/arch/powerpc/net/bpf_jit_comp.c -+++ b/arch/powerpc/net/bpf_jit_comp.c -@@ -241,8 +241,8 @@ skip_codegen_passes: - fp->jited_len = alloclen; - - bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + (bpf_hdr->pages * PAGE_SIZE)); -- bpf_jit_binary_lock_ro(bpf_hdr); - if (!fp->is_func || extra_pass) { -+ bpf_jit_binary_lock_ro(bpf_hdr); - bpf_prog_fill_jited_linfo(fp, addrs); - out_addrs: - kfree(addrs); -diff --git a/arch/powerpc/perf/power10-events-list.h b/arch/powerpc/perf/power10-events-list.h -index 93be7197d2502..564f14097f07b 100644 ---- a/arch/powerpc/perf/power10-events-list.h -+++ b/arch/powerpc/perf/power10-events-list.h -@@ -9,10 +9,10 @@ - /* - * Power10 event codes. - */ --EVENT(PM_RUN_CYC, 0x600f4); -+EVENT(PM_CYC, 0x600f4); - EVENT(PM_DISP_STALL_CYC, 0x100f8); - EVENT(PM_EXEC_STALL, 0x30008); --EVENT(PM_RUN_INST_CMPL, 0x500fa); -+EVENT(PM_INST_CMPL, 0x500fa); - EVENT(PM_BR_CMPL, 0x4d05e); - EVENT(PM_BR_MPRED_CMPL, 0x400f6); - EVENT(PM_BR_FIN, 0x2f04a); -@@ -50,8 +50,8 @@ EVENT(PM_DTLB_MISS, 0x300fc); - /* ITLB Reloaded */ - EVENT(PM_ITLB_MISS, 0x400fc); - --EVENT(PM_RUN_CYC_ALT, 0x0001e); --EVENT(PM_RUN_INST_CMPL_ALT, 0x00002); -+EVENT(PM_CYC_ALT, 0x0001e); -+EVENT(PM_INST_CMPL_ALT, 0x00002); - - /* - * Memory Access Events -diff --git a/arch/powerpc/perf/power10-pmu.c b/arch/powerpc/perf/power10-pmu.c -index f9d64c63bb4a7..9dd75f3858372 100644 ---- a/arch/powerpc/perf/power10-pmu.c -+++ b/arch/powerpc/perf/power10-pmu.c -@@ -91,8 +91,8 @@ extern u64 PERF_REG_EXTENDED_MASK; - - /* Table of alternatives, sorted by column 0 */ - static const unsigned int power10_event_alternatives[][MAX_ALT] = { -- { PM_RUN_CYC_ALT, PM_RUN_CYC }, -- { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL }, -+ { PM_CYC_ALT, PM_CYC }, -+ { PM_INST_CMPL_ALT, PM_INST_CMPL }, - }; - - static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[]) -@@ -118,8 +118,8 @@ static int power10_check_attr_config(struct perf_event *ev) - return 0; - } - --GENERIC_EVENT_ATTR(cpu-cycles, PM_RUN_CYC); --GENERIC_EVENT_ATTR(instructions, PM_RUN_INST_CMPL); -+GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); -+GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL); - GENERIC_EVENT_ATTR(branch-instructions, PM_BR_CMPL); - GENERIC_EVENT_ATTR(branch-misses, PM_BR_MPRED_CMPL); - GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1); -@@ -148,8 +148,8 @@ CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS); - CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS); - - static struct attribute *power10_events_attr_dd1[] = { -- GENERIC_EVENT_PTR(PM_RUN_CYC), -- GENERIC_EVENT_PTR(PM_RUN_INST_CMPL), -+ GENERIC_EVENT_PTR(PM_CYC), -+ GENERIC_EVENT_PTR(PM_INST_CMPL), - GENERIC_EVENT_PTR(PM_BR_CMPL), - GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL), - GENERIC_EVENT_PTR(PM_LD_REF_L1), -@@ -173,8 +173,8 @@ static struct attribute *power10_events_attr_dd1[] = { - }; - - static struct attribute *power10_events_attr[] = { -- GENERIC_EVENT_PTR(PM_RUN_CYC), -- GENERIC_EVENT_PTR(PM_RUN_INST_CMPL), -+ GENERIC_EVENT_PTR(PM_CYC), -+ GENERIC_EVENT_PTR(PM_INST_CMPL), - GENERIC_EVENT_PTR(PM_BR_FIN), - GENERIC_EVENT_PTR(PM_MPRED_BR_FIN), - GENERIC_EVENT_PTR(PM_LD_REF_L1), -@@ -271,8 +271,8 @@ static const struct attribute_group *power10_pmu_attr_groups[] = { - }; - - static int power10_generic_events_dd1[] = { -- [PERF_COUNT_HW_CPU_CYCLES] = PM_RUN_CYC, -- [PERF_COUNT_HW_INSTRUCTIONS] = PM_RUN_INST_CMPL, -+ [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC, -+ [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_CMPL, - [PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL, - [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1, -@@ -280,8 +280,8 @@ static int power10_generic_events_dd1[] = { - }; - - static int power10_generic_events[] = { -- [PERF_COUNT_HW_CPU_CYCLES] = PM_RUN_CYC, -- [PERF_COUNT_HW_INSTRUCTIONS] = PM_RUN_INST_CMPL, -+ [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC, -+ [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_FIN, - [PERF_COUNT_HW_BRANCH_MISSES] = PM_MPRED_BR_FIN, - [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1, -@@ -548,6 +548,24 @@ static u64 power10_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { - - #undef C - -+/* -+ * Set the MMCR0[CC56RUN] bit to enable counting for -+ * PMC5 and PMC6 regardless of the state of CTRL[RUN], -+ * so that we can use counters 5 and 6 as PM_INST_CMPL and -+ * PM_CYC. -+ */ -+static int power10_compute_mmcr(u64 event[], int n_ev, -+ unsigned int hwc[], struct mmcr_regs *mmcr, -+ struct perf_event *pevents[], u32 flags) -+{ -+ int ret; -+ -+ ret = isa207_compute_mmcr(event, n_ev, hwc, mmcr, pevents, flags); -+ if (!ret) -+ mmcr->mmcr0 |= MMCR0_C56RUN; -+ return ret; -+} -+ - static struct power_pmu power10_pmu = { - .name = "POWER10", - .n_counter = MAX_PMU_COUNTERS, -@@ -555,7 +573,7 @@ static struct power_pmu power10_pmu = { - .test_adder = ISA207_TEST_ADDER, - .group_constraint_mask = CNST_CACHE_PMC4_MASK, - .group_constraint_val = CNST_CACHE_PMC4_VAL, -- .compute_mmcr = isa207_compute_mmcr, -+ .compute_mmcr = power10_compute_mmcr, - .config_bhrb = power10_config_bhrb, - .bhrb_filter_map = power10_bhrb_filter_map, - .get_constraint = isa207_get_constraint, -diff --git a/arch/powerpc/platforms/44x/fsp2.c b/arch/powerpc/platforms/44x/fsp2.c -index b299e43f5ef94..823397c802def 100644 ---- a/arch/powerpc/platforms/44x/fsp2.c -+++ b/arch/powerpc/platforms/44x/fsp2.c -@@ -208,6 +208,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler) - if (irq == NO_IRQ) { - pr_err("device tree node %pOFn is missing a interrupt", - np); -+ of_node_put(np); - return; - } - -@@ -215,6 +216,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler) - if (rc) { - pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d", - np, rc); -+ of_node_put(np); - return; - } - } -diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile -index 60e4e97a929db..260fbad7967b2 100644 ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -3,7 +3,9 @@ - # Makefile for the PowerPC 85xx linux kernel. - # - obj-$(CONFIG_SMP) += smp.o --obj-$(CONFIG_FSL_PMC) += mpc85xx_pm_ops.o -+ifneq ($(CONFIG_FSL_CORENET_RCPM),y) -+obj-$(CONFIG_SMP) += mpc85xx_pm_ops.o -+endif - - obj-y += common.o - -diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c -index 7c0133f558d02..4a8af80011a6f 100644 ---- a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c -+++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c -@@ -17,6 +17,7 @@ - - static struct ccsr_guts __iomem *guts; - -+#ifdef CONFIG_FSL_PMC - static void mpc85xx_irq_mask(int cpu) - { - -@@ -49,6 +50,7 @@ static void mpc85xx_cpu_up_prepare(int cpu) - { - - } -+#endif - - static void mpc85xx_freeze_time_base(bool freeze) - { -@@ -76,10 +78,12 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = { - - static const struct fsl_pm_ops mpc85xx_pm_ops = { - .freeze_time_base = mpc85xx_freeze_time_base, -+#ifdef CONFIG_FSL_PMC - .irq_mask = mpc85xx_irq_mask, - .irq_unmask = mpc85xx_irq_unmask, - .cpu_die = mpc85xx_cpu_die, - .cpu_up_prepare = mpc85xx_cpu_up_prepare, -+#endif - }; - - int __init mpc85xx_setup_pmc(void) -@@ -94,9 +98,8 @@ int __init mpc85xx_setup_pmc(void) - pr_err("Could not map guts node address\n"); - return -ENOMEM; - } -+ qoriq_pm_ops = &mpc85xx_pm_ops; - } - -- qoriq_pm_ops = &mpc85xx_pm_ops; -- - return 0; - } -diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c -index c6df294054fe9..d7081e9af65c7 100644 ---- a/arch/powerpc/platforms/85xx/smp.c -+++ b/arch/powerpc/platforms/85xx/smp.c -@@ -40,7 +40,6 @@ struct epapr_spin_table { - u32 pir; - }; - --#ifdef CONFIG_HOTPLUG_CPU - static u64 timebase; - static int tb_req; - static int tb_valid; -@@ -112,6 +111,7 @@ static void mpc85xx_take_timebase(void) - local_irq_restore(flags); - } - -+#ifdef CONFIG_HOTPLUG_CPU - static void smp_85xx_cpu_offline_self(void) - { - unsigned int cpu = smp_processor_id(); -@@ -220,7 +220,7 @@ static int smp_85xx_start_cpu(int cpu) - local_irq_save(flags); - hard_irq_disable(); - -- if (qoriq_pm_ops) -+ if (qoriq_pm_ops && qoriq_pm_ops->cpu_up_prepare) - qoriq_pm_ops->cpu_up_prepare(cpu); - - /* if cpu is not spinning, reset it */ -@@ -292,7 +292,7 @@ static int smp_85xx_kick_cpu(int nr) - booting_thread_hwid = cpu_thread_in_core(nr); - primary = cpu_first_thread_sibling(nr); - -- if (qoriq_pm_ops) -+ if (qoriq_pm_ops && qoriq_pm_ops->cpu_up_prepare) - qoriq_pm_ops->cpu_up_prepare(nr); - - /* -@@ -495,21 +495,21 @@ void __init mpc85xx_smp_init(void) - smp_85xx_ops.probe = NULL; - } - --#ifdef CONFIG_HOTPLUG_CPU - #ifdef CONFIG_FSL_CORENET_RCPM -+ /* Assign a value to qoriq_pm_ops on PPC_E500MC */ - fsl_rcpm_init(); --#endif -- --#ifdef CONFIG_FSL_PMC -+#else -+ /* Assign a value to qoriq_pm_ops on !PPC_E500MC */ - mpc85xx_setup_pmc(); - #endif - if (qoriq_pm_ops) { - smp_85xx_ops.give_timebase = mpc85xx_give_timebase; - smp_85xx_ops.take_timebase = mpc85xx_take_timebase; -+#ifdef CONFIG_HOTPLUG_CPU - smp_85xx_ops.cpu_offline_self = smp_85xx_cpu_offline_self; - smp_85xx_ops.cpu_die = qoriq_cpu_kill; -- } - #endif -+ } - smp_ops = &smp_85xx_ops; - - #ifdef CONFIG_KEXEC_CORE -diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c -index 30172e52e16b7..4d82c92ddd523 100644 ---- a/arch/powerpc/platforms/book3s/vas-api.c -+++ b/arch/powerpc/platforms/book3s/vas-api.c -@@ -303,7 +303,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) - return -EINVAL; - } - -- if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) { -+ if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->open_win) { - pr_err("VAS API is not registered\n"); - return -EACCES; - } -@@ -373,7 +373,7 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) - return -EINVAL; - } - -- if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->paste_addr) { -+ if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->paste_addr) { - pr_err("%s(): VAS API is not registered\n", __func__); - return -EACCES; - } -diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c -index a191f4c60ce71..113bdb151f687 100644 ---- a/arch/powerpc/platforms/powernv/opal-prd.c -+++ b/arch/powerpc/platforms/powernv/opal-prd.c -@@ -369,6 +369,12 @@ static struct notifier_block opal_prd_event_nb = { - .priority = 0, - }; - -+static struct notifier_block opal_prd_event_nb2 = { -+ .notifier_call = opal_prd_msg_notifier, -+ .next = NULL, -+ .priority = 0, -+}; -+ - static int opal_prd_probe(struct platform_device *pdev) - { - int rc; -@@ -390,9 +396,10 @@ static int opal_prd_probe(struct platform_device *pdev) - return rc; - } - -- rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb); -+ rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb2); - if (rc) { - pr_err("Couldn't register PRD2 event notifier\n"); -+ opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb); - return rc; - } - -@@ -401,6 +408,8 @@ static int opal_prd_probe(struct platform_device *pdev) - pr_err("failed to register miscdev\n"); - opal_message_notifier_unregister(OPAL_MSG_PRD, - &opal_prd_event_nb); -+ opal_message_notifier_unregister(OPAL_MSG_PRD2, -+ &opal_prd_event_nb2); - return rc; - } - -@@ -411,6 +420,7 @@ static int opal_prd_remove(struct platform_device *pdev) - { - misc_deregister(&opal_prd_dev); - opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb); -+ opal_message_notifier_unregister(OPAL_MSG_PRD2, &opal_prd_event_nb2); - return 0; - } - -diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c -index a52af8fbf5711..8322ca86d5acf 100644 ---- a/arch/powerpc/platforms/pseries/iommu.c -+++ b/arch/powerpc/platforms/pseries/iommu.c -@@ -1092,15 +1092,6 @@ static phys_addr_t ddw_memory_hotplug_max(void) - phys_addr_t max_addr = memory_hotplug_max(); - struct device_node *memory; - -- /* -- * The "ibm,pmemory" can appear anywhere in the address space. -- * Assuming it is still backed by page structs, set the upper limit -- * for the huge DMA window as MAX_PHYSMEM_BITS. -- */ -- if (of_find_node_by_type(NULL, "ibm,pmemory")) -- return (sizeof(phys_addr_t) * 8 <= MAX_PHYSMEM_BITS) ? -- (phys_addr_t) -1 : (1ULL << MAX_PHYSMEM_BITS); -- - for_each_node_by_type(memory, "memory") { - unsigned long start, size; - int n_mem_addr_cells, n_mem_size_cells, len; -@@ -1365,8 +1356,10 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) - len = order_base_2(query.largest_available_block << page_shift); - win_name = DMA64_PROPNAME; - } else { -- direct_mapping = true; -- win_name = DIRECT64_PROPNAME; -+ direct_mapping = !default_win_removed || -+ (len == MAX_PHYSMEM_BITS) || -+ (!pmem_present && (len == max_ram_len)); -+ win_name = direct_mapping ? DIRECT64_PROPNAME : DMA64_PROPNAME; - } - - ret = create_ddw(dev, ddw_avail, &create, page_shift, len); -diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c -index e83e0891272d3..210a37a065fb7 100644 ---- a/arch/powerpc/platforms/pseries/mobility.c -+++ b/arch/powerpc/platforms/pseries/mobility.c -@@ -63,6 +63,27 @@ static int mobility_rtas_call(int token, char *buf, s32 scope) - - static int delete_dt_node(struct device_node *dn) - { -+ struct device_node *pdn; -+ bool is_platfac; -+ -+ pdn = of_get_parent(dn); -+ is_platfac = of_node_is_type(dn, "ibm,platform-facilities") || -+ of_node_is_type(pdn, "ibm,platform-facilities"); -+ of_node_put(pdn); -+ -+ /* -+ * The drivers that bind to nodes in the platform-facilities -+ * hierarchy don't support node removal, and the removal directive -+ * from firmware is always followed by an add of an equivalent -+ * node. The capability (e.g. RNG, encryption, compression) -+ * represented by the node is never interrupted by the migration. -+ * So ignore changes to this part of the tree. -+ */ -+ if (is_platfac) { -+ pr_notice("ignoring remove operation for %pOFfp\n", dn); -+ return 0; -+ } -+ - pr_debug("removing node %pOFfp\n", dn); - dlpar_detach_node(dn); - return 0; -@@ -222,6 +243,19 @@ static int add_dt_node(struct device_node *parent_dn, __be32 drc_index) - if (!dn) - return -ENOENT; - -+ /* -+ * Since delete_dt_node() ignores this node type, this is the -+ * necessary counterpart. We also know that a platform-facilities -+ * node returned from dlpar_configure_connector() has children -+ * attached, and dlpar_attach_node() only adds the parent, leaking -+ * the children. So ignore these on the add side for now. -+ */ -+ if (of_node_is_type(dn, "ibm,platform-facilities")) { -+ pr_notice("ignoring add operation for %pOF\n", dn); -+ dlpar_free_cc_nodes(dn); -+ return 0; -+ } -+ - rc = dlpar_attach_node(dn, parent_dn); - if (rc) - dlpar_free_cc_nodes(dn); -diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S -index efeeb1b885a17..329b9c4ae5429 100644 ---- a/arch/powerpc/sysdev/dcr-low.S -+++ b/arch/powerpc/sysdev/dcr-low.S -@@ -11,7 +11,7 @@ - #include <asm/export.h> - - #define DCR_ACCESS_PROLOG(table) \ -- cmpli cr0,r3,1024; \ -+ cmplwi cr0,r3,1024; \ - rlwinm r3,r3,4,18,27; \ - lis r5,table@h; \ - ori r5,r5,table@l; \ -diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig -index 97796c6b63f04..785c292d104b7 100644 ---- a/arch/powerpc/sysdev/xive/Kconfig -+++ b/arch/powerpc/sysdev/xive/Kconfig -@@ -3,7 +3,6 @@ config PPC_XIVE - bool - select PPC_SMP_MUXED_IPI - select HARDIRQS_SW_RESEND -- select IRQ_DOMAIN_NOMAP - - config PPC_XIVE_NATIVE - bool -diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c -index c5d75c02ad8b5..7b69299c29123 100644 ---- a/arch/powerpc/sysdev/xive/common.c -+++ b/arch/powerpc/sysdev/xive/common.c -@@ -1443,8 +1443,7 @@ static const struct irq_domain_ops xive_irq_domain_ops = { - - static void __init xive_init_host(struct device_node *np) - { -- xive_irq_domain = irq_domain_add_nomap(np, XIVE_MAX_IRQ, -- &xive_irq_domain_ops, NULL); -+ xive_irq_domain = irq_domain_add_tree(np, &xive_irq_domain_ops, NULL); - if (WARN_ON(xive_irq_domain == NULL)) - return; - irq_set_default_host(xive_irq_domain); -diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c -index dd8241c009e53..8b28ff9d98d16 100644 ---- a/arch/powerpc/xmon/xmon.c -+++ b/arch/powerpc/xmon/xmon.c -@@ -3264,8 +3264,7 @@ static void show_task(struct task_struct *volatile tsk) - * appropriate for calling from xmon. This could be moved - * to a common, generic, routine used by both. - */ -- state = (p_state == 0) ? 'R' : -- (p_state < 0) ? 'U' : -+ state = (p_state == TASK_RUNNING) ? 'R' : - (p_state & TASK_UNINTERRUPTIBLE) ? 'D' : - (p_state & TASK_STOPPED) ? 'T' : - (p_state & TASK_TRACED) ? 'C' : -diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile -index 0eb4568fbd290..41f3a75fe2ec8 100644 ---- a/arch/riscv/Makefile -+++ b/arch/riscv/Makefile -@@ -108,11 +108,13 @@ PHONY += vdso_install - vdso_install: - $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@ - -+ifeq ($(KBUILD_EXTMOD),) - ifeq ($(CONFIG_MMU),y) - prepare: vdso_prepare - vdso_prepare: prepare0 - $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h - endif -+endif - - ifneq ($(CONFIG_XIP_KERNEL),y) - ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy) -diff --git a/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts -index b254c60589a1c..cce5eca31f257 100644 ---- a/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts -+++ b/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts -@@ -12,7 +12,7 @@ - #address-cells = <2>; - #size-cells = <2>; - model = "Microchip PolarFire-SoC Icicle Kit"; -- compatible = "microchip,mpfs-icicle-kit"; -+ compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs"; - - aliases { - ethernet0 = &emac1; -@@ -56,8 +56,17 @@ - status = "okay"; - }; - --&sdcard { -+&mmc { - status = "okay"; -+ -+ bus-width = <4>; -+ disable-wp; -+ cap-sd-highspeed; -+ card-detect-delay = <200>; -+ sd-uhs-sdr12; -+ sd-uhs-sdr25; -+ sd-uhs-sdr50; -+ sd-uhs-sdr104; - }; - - &emac0 { -diff --git a/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi b/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi -index 9d2fbbc1f7778..b12fd594e7172 100644 ---- a/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi -+++ b/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi -@@ -6,8 +6,8 @@ - / { - #address-cells = <2>; - #size-cells = <2>; -- model = "Microchip MPFS Icicle Kit"; -- compatible = "microchip,mpfs-icicle-kit"; -+ model = "Microchip PolarFire SoC"; -+ compatible = "microchip,mpfs"; - - chosen { - }; -@@ -262,39 +262,14 @@ - status = "disabled"; - }; - -- emmc: mmc@20008000 { -+ /* Common node entry for emmc/sd */ -+ mmc: mmc@20008000 { - compatible = "cdns,sd4hc"; - reg = <0x0 0x20008000 0x0 0x1000>; - interrupt-parent = <&plic>; - interrupts = <88 89>; - pinctrl-names = "default"; - clocks = <&clkcfg 6>; -- bus-width = <4>; -- cap-mmc-highspeed; -- mmc-ddr-3_3v; -- max-frequency = <200000000>; -- non-removable; -- no-sd; -- no-sdio; -- voltage-ranges = <3300 3300>; -- status = "disabled"; -- }; -- -- sdcard: sdhc@20008000 { -- compatible = "cdns,sd4hc"; -- reg = <0x0 0x20008000 0x0 0x1000>; -- interrupt-parent = <&plic>; -- interrupts = <88>; -- pinctrl-names = "default"; -- clocks = <&clkcfg 6>; -- bus-width = <4>; -- disable-wp; -- cap-sd-highspeed; -- card-detect-delay = <200>; -- sd-uhs-sdr12; -- sd-uhs-sdr25; -- sd-uhs-sdr50; -- sd-uhs-sdr104; - max-frequency = <200000000>; - status = "disabled"; - }; -diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts -index 60846e88ae4b1..22f971e971614 100644 ---- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts -+++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts -@@ -80,6 +80,7 @@ - spi-max-frequency = <20000000>; - voltage-ranges = <3300 3300>; - disable-wp; -+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; - }; - }; - -diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts -index 2e4ea84f27e77..b40990210fb50 100644 ---- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts -+++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts -@@ -2,6 +2,7 @@ - /* Copyright (c) 2020 SiFive, Inc */ - - #include "fu740-c000.dtsi" -+#include <dt-bindings/gpio/gpio.h> - #include <dt-bindings/interrupt-controller/irq.h> - - /* Clock frequency (in Hz) of the PCB crystal for rtcclk */ -@@ -228,6 +229,7 @@ - spi-max-frequency = <20000000>; - voltage-ranges = <3300 3300>; - disable-wp; -+ gpios = <&gpio 15 GPIO_ACTIVE_LOW>; - }; - }; - -diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig -index b86de61b8caa2..797041b5109a2 100644 ---- a/arch/s390/Kconfig -+++ b/arch/s390/Kconfig -@@ -47,7 +47,7 @@ config ARCH_SUPPORTS_UPROBES - config KASAN_SHADOW_OFFSET - hex - depends on KASAN -- default 0x18000000000000 -+ default 0x1C000000000000 - - config S390 - def_bool y -diff --git a/arch/s390/Makefile b/arch/s390/Makefile -index 450b351dfa8ef..d4fd1426a8226 100644 ---- a/arch/s390/Makefile -+++ b/arch/s390/Makefile -@@ -79,10 +79,12 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(aflags-y) - KBUILD_CFLAGS_DECOMPRESSOR += $(cflags-y) - - ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),) --cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE) --ifeq ($(call cc-option,-mstack-size=8192),) --cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD) --endif -+ CC_FLAGS_CHECK_STACK := -mstack-size=$(STACK_SIZE) -+ ifeq ($(call cc-option,-mstack-size=8192),) -+ CC_FLAGS_CHECK_STACK += -mstack-guard=$(CONFIG_STACK_GUARD) -+ endif -+ export CC_FLAGS_CHECK_STACK -+ cflags-$(CONFIG_CHECK_STACK) += $(CC_FLAGS_CHECK_STACK) - endif - - ifdef CONFIG_EXPOLINE -diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c -index 6dc8d0a538640..b13352dd1e1cf 100644 ---- a/arch/s390/boot/startup.c -+++ b/arch/s390/boot/startup.c -@@ -148,82 +148,56 @@ static void setup_ident_map_size(unsigned long max_physmem_end) - - static void setup_kernel_memory_layout(void) - { -- bool vmalloc_size_verified = false; -- unsigned long vmemmap_off; -- unsigned long vspace_left; -+ unsigned long vmemmap_start; - unsigned long rte_size; - unsigned long pages; -- unsigned long vmax; - - pages = ident_map_size / PAGE_SIZE; - /* vmemmap contains a multiple of PAGES_PER_SECTION struct pages */ - vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page); - - /* choose kernel address space layout: 4 or 3 levels. */ -- vmemmap_off = round_up(ident_map_size, _REGION3_SIZE); -+ vmemmap_start = round_up(ident_map_size, _REGION3_SIZE); - if (IS_ENABLED(CONFIG_KASAN) || - vmalloc_size > _REGION2_SIZE || -- vmemmap_off + vmemmap_size + vmalloc_size + MODULES_LEN > _REGION2_SIZE) -- vmax = _REGION1_SIZE; -- else -- vmax = _REGION2_SIZE; -- -- /* keep vmemmap_off aligned to a top level region table entry */ -- rte_size = vmax == _REGION1_SIZE ? _REGION2_SIZE : _REGION3_SIZE; -- MODULES_END = vmax; -- if (is_prot_virt_host()) { -- /* -- * forcing modules and vmalloc area under the ultravisor -- * secure storage limit, so that any vmalloc allocation -- * we do could be used to back secure guest storage. -- */ -- adjust_to_uv_max(&MODULES_END); -- } -- --#ifdef CONFIG_KASAN -- if (MODULES_END < vmax) { -- /* force vmalloc and modules below kasan shadow */ -- MODULES_END = min(MODULES_END, KASAN_SHADOW_START); -+ vmemmap_start + vmemmap_size + vmalloc_size + MODULES_LEN > -+ _REGION2_SIZE) { -+ MODULES_END = _REGION1_SIZE; -+ rte_size = _REGION2_SIZE; - } else { -- /* -- * leave vmalloc and modules above kasan shadow but make -- * sure they don't overlap with it -- */ -- vmalloc_size = min(vmalloc_size, vmax - KASAN_SHADOW_END - MODULES_LEN); -- vmalloc_size_verified = true; -- vspace_left = KASAN_SHADOW_START; -+ MODULES_END = _REGION2_SIZE; -+ rte_size = _REGION3_SIZE; - } -+ /* -+ * forcing modules and vmalloc area under the ultravisor -+ * secure storage limit, so that any vmalloc allocation -+ * we do could be used to back secure guest storage. -+ */ -+ adjust_to_uv_max(&MODULES_END); -+#ifdef CONFIG_KASAN -+ /* force vmalloc and modules below kasan shadow */ -+ MODULES_END = min(MODULES_END, KASAN_SHADOW_START); - #endif - MODULES_VADDR = MODULES_END - MODULES_LEN; - VMALLOC_END = MODULES_VADDR; - -- if (vmalloc_size_verified) { -- VMALLOC_START = VMALLOC_END - vmalloc_size; -- } else { -- vmemmap_off = round_up(ident_map_size, rte_size); -- -- if (vmemmap_off + vmemmap_size > VMALLOC_END || -- vmalloc_size > VMALLOC_END - vmemmap_off - vmemmap_size) { -- /* -- * allow vmalloc area to occupy up to 1/2 of -- * the rest virtual space left. -- */ -- vmalloc_size = min(vmalloc_size, VMALLOC_END / 2); -- } -- VMALLOC_START = VMALLOC_END - vmalloc_size; -- vspace_left = VMALLOC_START; -- } -+ /* allow vmalloc area to occupy up to about 1/2 of the rest virtual space left */ -+ vmalloc_size = min(vmalloc_size, round_down(VMALLOC_END / 2, _REGION3_SIZE)); -+ VMALLOC_START = VMALLOC_END - vmalloc_size; - -- pages = vspace_left / (PAGE_SIZE + sizeof(struct page)); -+ /* split remaining virtual space between 1:1 mapping & vmemmap array */ -+ pages = VMALLOC_START / (PAGE_SIZE + sizeof(struct page)); - pages = SECTION_ALIGN_UP(pages); -- vmemmap_off = round_up(vspace_left - pages * sizeof(struct page), rte_size); -- /* keep vmemmap left most starting from a fresh region table entry */ -- vmemmap_off = min(vmemmap_off, round_up(ident_map_size, rte_size)); -- /* take care that identity map is lower then vmemmap */ -- ident_map_size = min(ident_map_size, vmemmap_off); -+ /* keep vmemmap_start aligned to a top level region table entry */ -+ vmemmap_start = round_down(VMALLOC_START - pages * sizeof(struct page), rte_size); -+ /* vmemmap_start is the future VMEM_MAX_PHYS, make sure it is within MAX_PHYSMEM */ -+ vmemmap_start = min(vmemmap_start, 1UL << MAX_PHYSMEM_BITS); -+ /* make sure identity map doesn't overlay with vmemmap */ -+ ident_map_size = min(ident_map_size, vmemmap_start); - vmemmap_size = SECTION_ALIGN_UP(ident_map_size / PAGE_SIZE) * sizeof(struct page); -- VMALLOC_START = max(vmemmap_off + vmemmap_size, VMALLOC_START); -- vmemmap = (struct page *)vmemmap_off; -+ /* make sure vmemmap doesn't overlay with vmalloc area */ -+ VMALLOC_START = max(vmemmap_start + vmemmap_size, VMALLOC_START); -+ vmemmap = (struct page *)vmemmap_start; - } - - /* -diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h -index ea398a05f6432..7f3c9ac34bd8d 100644 ---- a/arch/s390/include/asm/kexec.h -+++ b/arch/s390/include/asm/kexec.h -@@ -74,6 +74,12 @@ void *kexec_file_add_components(struct kimage *image, - int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val, - unsigned long addr); - -+#define ARCH_HAS_KIMAGE_ARCH -+ -+struct kimage_arch { -+ void *ipl_buf; -+}; -+ - extern const struct kexec_file_ops s390_kexec_image_ops; - extern const struct kexec_file_ops s390_kexec_elf_ops; - -diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h -index e4dc64cc9c555..287bb88f76986 100644 ---- a/arch/s390/include/asm/pci_io.h -+++ b/arch/s390/include/asm/pci_io.h -@@ -14,12 +14,13 @@ - - /* I/O Map */ - #define ZPCI_IOMAP_SHIFT 48 --#define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000UL -+#define ZPCI_IOMAP_ADDR_SHIFT 62 -+#define ZPCI_IOMAP_ADDR_BASE (1UL << ZPCI_IOMAP_ADDR_SHIFT) - #define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1) - #define ZPCI_IOMAP_MAX_ENTRIES \ -- ((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT)) -+ (1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT)) - #define ZPCI_IOMAP_ADDR_IDX_MASK \ -- (~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE) -+ ((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK) - - struct zpci_iomap_entry { - u32 fh; -diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c -index d72a6df058d79..785d54c9350c4 100644 ---- a/arch/s390/kernel/crash_dump.c -+++ b/arch/s390/kernel/crash_dump.c -@@ -191,8 +191,8 @@ static int copy_oldmem_user(void __user *dst, void *src, size_t count) - return rc; - } else { - /* Check for swapped kdump oldmem areas */ -- if (oldmem_data.start && from - oldmem_data.size < oldmem_data.size) { -- from -= oldmem_data.size; -+ if (oldmem_data.start && from - oldmem_data.start < oldmem_data.size) { -+ from -= oldmem_data.start; - len = min(count, oldmem_data.size - from); - } else if (oldmem_data.start && from < oldmem_data.size) { - len = min(count, oldmem_data.size - from); -diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c -index e2cc35775b996..5ad1dde23dc59 100644 ---- a/arch/s390/kernel/ipl.c -+++ b/arch/s390/kernel/ipl.c -@@ -2156,7 +2156,7 @@ void *ipl_report_finish(struct ipl_report *report) - - buf = vzalloc(report->size); - if (!buf) -- return ERR_PTR(-ENOMEM); -+ goto out; - ptr = buf; - - memcpy(ptr, report->ipib, report->ipib->hdr.len); -@@ -2195,6 +2195,7 @@ void *ipl_report_finish(struct ipl_report *report) - } - - BUG_ON(ptr > buf + report->size); -+out: - return buf; - } - -diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c -index 3a3145c4a3ba4..be5d432b902e0 100644 ---- a/arch/s390/kernel/irq.c -+++ b/arch/s390/kernel/irq.c -@@ -138,7 +138,7 @@ void noinstr do_io_irq(struct pt_regs *regs) - struct pt_regs *old_regs = set_irq_regs(regs); - int from_idle; - -- irq_enter(); -+ irq_enter_rcu(); - - if (user_mode(regs)) - update_timer_sys(); -@@ -155,7 +155,8 @@ void noinstr do_io_irq(struct pt_regs *regs) - do_irq_async(regs, IO_INTERRUPT); - } while (MACHINE_IS_LPAR && irq_pending(regs)); - -- irq_exit(); -+ irq_exit_rcu(); -+ - set_irq_regs(old_regs); - irqentry_exit(regs, state); - -@@ -169,7 +170,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) - struct pt_regs *old_regs = set_irq_regs(regs); - int from_idle; - -- irq_enter(); -+ irq_enter_rcu(); - - if (user_mode(regs)) - update_timer_sys(); -@@ -184,7 +185,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) - - do_irq_async(regs, EXT_INTERRUPT); - -- irq_exit(); -+ irq_exit_rcu(); - set_irq_regs(old_regs); - irqentry_exit(regs, state); - -diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c -index f9e4baa64b675..76cd09879eaf4 100644 ---- a/arch/s390/kernel/machine_kexec_file.c -+++ b/arch/s390/kernel/machine_kexec_file.c -@@ -12,6 +12,7 @@ - #include <linux/kexec.h> - #include <linux/module_signature.h> - #include <linux/verification.h> -+#include <linux/vmalloc.h> - #include <asm/boot_data.h> - #include <asm/ipl.h> - #include <asm/setup.h> -@@ -170,6 +171,7 @@ static int kexec_file_add_ipl_report(struct kimage *image, - struct kexec_buf buf; - unsigned long addr; - void *ptr, *end; -+ int ret; - - buf.image = image; - -@@ -199,9 +201,13 @@ static int kexec_file_add_ipl_report(struct kimage *image, - ptr += len; - } - -+ ret = -ENOMEM; - buf.buffer = ipl_report_finish(data->report); -+ if (!buf.buffer) -+ goto out; - buf.bufsz = data->report->size; - buf.memsz = buf.bufsz; -+ image->arch.ipl_buf = buf.buffer; - - data->memsz += buf.memsz; - -@@ -209,7 +215,9 @@ static int kexec_file_add_ipl_report(struct kimage *image, - data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr); - *lc_ipl_parmblock_ptr = (__u32)buf.mem; - -- return kexec_add_buffer(&buf); -+ ret = kexec_add_buffer(&buf); -+out: -+ return ret; - } - - void *kexec_file_add_components(struct kimage *image, -@@ -269,6 +277,7 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, - { - Elf_Rela *relas; - int i, r_type; -+ int ret; - - relas = (void *)pi->ehdr + relsec->sh_offset; - -@@ -303,7 +312,11 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, - addr = section->sh_addr + relas[i].r_offset; - - r_type = ELF64_R_TYPE(relas[i].r_info); -- arch_kexec_do_relocs(r_type, loc, val, addr); -+ ret = arch_kexec_do_relocs(r_type, loc, val, addr); -+ if (ret) { -+ pr_err("Unknown rela relocation: %d\n", r_type); -+ return -ENOEXEC; -+ } - } - return 0; - } -@@ -321,3 +334,11 @@ int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, - - return kexec_image_probe_default(image, buf, buf_len); - } -+ -+int arch_kimage_file_post_load_cleanup(struct kimage *image) -+{ -+ vfree(image->arch.ipl_buf); -+ image->arch.ipl_buf = NULL; -+ -+ return kexec_image_post_load_cleanup_default(image); -+} -diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c -index 4a99154fe6514..cceb8ec707e4b 100644 ---- a/arch/s390/kernel/perf_cpum_cf.c -+++ b/arch/s390/kernel/perf_cpum_cf.c -@@ -687,8 +687,10 @@ static void cpumf_pmu_stop(struct perf_event *event, int flags) - false); - if (cfdiag_diffctr(cpuhw, event->hw.config_base)) - cfdiag_push_sample(event, cpuhw); -- } else -+ } else if (cpuhw->flags & PMU_F_RESERVED) { -+ /* Only update when PMU not hotplugged off */ - hw_perf_event_update(event); -+ } - hwc->state |= PERF_HES_UPTODATE; - } - } -diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c -index 67e5fff96ee06..ee67215a678a5 100644 ---- a/arch/s390/kernel/setup.c -+++ b/arch/s390/kernel/setup.c -@@ -633,14 +633,6 @@ static struct notifier_block kdump_mem_nb = { - - #endif - --/* -- * Make sure that the area above identity mapping is protected -- */ --static void __init reserve_above_ident_map(void) --{ -- memblock_reserve(ident_map_size, ULONG_MAX); --} -- - /* - * Reserve memory for kdump kernel to be loaded with kexec - */ -@@ -824,9 +816,6 @@ static void __init setup_memory(void) - storage_key_init_range(start, end); - - psw_set_key(PAGE_DEFAULT_KEY); -- -- /* Only cosmetics */ -- memblock_enforce_memory_limit(memblock_end_of_DRAM()); - } - - static void __init relocate_amode31_section(void) -@@ -1005,11 +994,11 @@ void __init setup_arch(char **cmdline_p) - setup_control_program_code(); - - /* Do some memory reservations *before* memory is added to memblock */ -- reserve_above_ident_map(); - reserve_kernel(); - reserve_initrd(); - reserve_certificate_list(); - reserve_mem_detect_info(); -+ memblock_set_current_limit(ident_map_size); - memblock_allow_resize(); - - /* Get information about *all* installed memory */ -diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c -index bcefc2173de45..12d28ff5281fa 100644 ---- a/arch/s390/kernel/traps.c -+++ b/arch/s390/kernel/traps.c -@@ -84,7 +84,7 @@ static void default_trap_handler(struct pt_regs *regs) - { - if (user_mode(regs)) { - report_user_fault(regs, SIGSEGV, 0); -- do_exit(SIGSEGV); -+ force_exit_sig(SIGSEGV); - } else - die(regs, "Unknown program exception"); - } -diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c -index 5a656c7b7a67a..f95ccbd396925 100644 ---- a/arch/s390/kernel/uv.c -+++ b/arch/s390/kernel/uv.c -@@ -212,7 +212,7 @@ again: - uaddr = __gmap_translate(gmap, gaddr); - if (IS_ERR_VALUE(uaddr)) - goto out; -- vma = find_vma(gmap->mm, uaddr); -+ vma = vma_lookup(gmap->mm, uaddr); - if (!vma) - goto out; - /* -diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile -index 6568de2367010..0dea82b87e54b 100644 ---- a/arch/s390/kernel/vdso64/Makefile -+++ b/arch/s390/kernel/vdso64/Makefile -@@ -8,8 +8,9 @@ ARCH_REL_TYPE_ABS += R_390_GOT|R_390_PLT - include $(srctree)/lib/vdso/Makefile - obj-vdso64 = vdso_user_wrapper.o note.o - obj-cvdso64 = vdso64_generic.o getcpu.o --CFLAGS_REMOVE_getcpu.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) --CFLAGS_REMOVE_vdso64_generic.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) -+VDSO_CFLAGS_REMOVE := -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) $(CC_FLAGS_CHECK_STACK) -+CFLAGS_REMOVE_getcpu.o = $(VDSO_CFLAGS_REMOVE) -+CFLAGS_REMOVE_vdso64_generic.o = $(VDSO_CFLAGS_REMOVE) - - # Build rules - -diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c -index 53da4ceb16a3a..417154b314a64 100644 ---- a/arch/s390/kvm/priv.c -+++ b/arch/s390/kvm/priv.c -@@ -397,6 +397,8 @@ static int handle_sske(struct kvm_vcpu *vcpu) - mmap_read_unlock(current->mm); - if (rc == -EFAULT) - return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); -+ if (rc == -EAGAIN) -+ continue; - if (rc < 0) - return rc; - start += PAGE_SIZE; -diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c -index c8841f476e913..00d272d134c24 100644 ---- a/arch/s390/kvm/pv.c -+++ b/arch/s390/kvm/pv.c -@@ -16,18 +16,17 @@ - - int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc) - { -- int cc = 0; -+ int cc; - -- if (kvm_s390_pv_cpu_get_handle(vcpu)) { -- cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu), -- UVC_CMD_DESTROY_SEC_CPU, rc, rrc); -+ if (!kvm_s390_pv_cpu_get_handle(vcpu)) -+ return 0; -+ -+ cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu), UVC_CMD_DESTROY_SEC_CPU, rc, rrc); -+ -+ KVM_UV_EVENT(vcpu->kvm, 3, "PROTVIRT DESTROY VCPU %d: rc %x rrc %x", -+ vcpu->vcpu_id, *rc, *rrc); -+ WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc); - -- KVM_UV_EVENT(vcpu->kvm, 3, -- "PROTVIRT DESTROY VCPU %d: rc %x rrc %x", -- vcpu->vcpu_id, *rc, *rrc); -- WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", -- *rc, *rrc); -- } - /* Intended memory leak for something that should never happen. */ - if (!cc) - free_pages(vcpu->arch.pv.stor_base, -@@ -196,7 +195,7 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) - uvcb.conf_base_stor_origin = (u64)kvm->arch.pv.stor_base; - uvcb.conf_virt_stor_origin = (u64)kvm->arch.pv.stor_var; - -- cc = uv_call(0, (u64)&uvcb); -+ cc = uv_call_sched(0, (u64)&uvcb); - *rc = uvcb.header.rc; - *rrc = uvcb.header.rrc; - KVM_UV_EVENT(kvm, 3, "PROTVIRT CREATE VM: handle %llx len %llx rc %x rrc %x", -diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c -index ecf327d743a03..c0635cf787e31 100644 ---- a/arch/s390/lib/test_unwind.c -+++ b/arch/s390/lib/test_unwind.c -@@ -171,10 +171,11 @@ static noinline int unwindme_func4(struct unwindme *u) - } - - /* -- * trigger specification exception -+ * Trigger operation exception; use insn notation to bypass -+ * llvm's integrated assembler sanity checks. - */ - asm volatile( -- " mvcl %%r1,%%r1\n" -+ " .insn e,0x0000\n" /* illegal opcode */ - "0: nopr %%r7\n" - EX_TABLE(0b, 0b) - :); -diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c -index 4d3b33ce81c62..d63c0ccc5ccda 100644 ---- a/arch/s390/mm/gmap.c -+++ b/arch/s390/mm/gmap.c -@@ -672,6 +672,7 @@ EXPORT_SYMBOL_GPL(gmap_fault); - */ - void __gmap_zap(struct gmap *gmap, unsigned long gaddr) - { -+ struct vm_area_struct *vma; - unsigned long vmaddr; - spinlock_t *ptl; - pte_t *ptep; -@@ -681,11 +682,17 @@ void __gmap_zap(struct gmap *gmap, unsigned long gaddr) - gaddr >> PMD_SHIFT); - if (vmaddr) { - vmaddr |= gaddr & ~PMD_MASK; -+ -+ vma = vma_lookup(gmap->mm, vmaddr); -+ if (!vma || is_vm_hugetlb_page(vma)) -+ return; -+ - /* Get pointer to the page table entry */ - ptep = get_locked_pte(gmap->mm, vmaddr, &ptl); -- if (likely(ptep)) -+ if (likely(ptep)) { - ptep_zap_unused(gmap->mm, vmaddr, ptep, 0); -- pte_unmap_unlock(ptep, ptl); -+ pte_unmap_unlock(ptep, ptl); -+ } - } - } - EXPORT_SYMBOL_GPL(__gmap_zap); -diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c -index 034721a68d8fd..6ad634a27d5b9 100644 ---- a/arch/s390/mm/pgtable.c -+++ b/arch/s390/mm/pgtable.c -@@ -429,22 +429,36 @@ static inline pmd_t pmdp_flush_lazy(struct mm_struct *mm, - } - - #ifdef CONFIG_PGSTE --static pmd_t *pmd_alloc_map(struct mm_struct *mm, unsigned long addr) -+static int pmd_lookup(struct mm_struct *mm, unsigned long addr, pmd_t **pmdp) - { -+ struct vm_area_struct *vma; - pgd_t *pgd; - p4d_t *p4d; - pud_t *pud; -- pmd_t *pmd; -+ -+ /* We need a valid VMA, otherwise this is clearly a fault. */ -+ vma = vma_lookup(mm, addr); -+ if (!vma) -+ return -EFAULT; - - pgd = pgd_offset(mm, addr); -- p4d = p4d_alloc(mm, pgd, addr); -- if (!p4d) -- return NULL; -- pud = pud_alloc(mm, p4d, addr); -- if (!pud) -- return NULL; -- pmd = pmd_alloc(mm, pud, addr); -- return pmd; -+ if (!pgd_present(*pgd)) -+ return -ENOENT; -+ -+ p4d = p4d_offset(pgd, addr); -+ if (!p4d_present(*p4d)) -+ return -ENOENT; -+ -+ pud = pud_offset(p4d, addr); -+ if (!pud_present(*pud)) -+ return -ENOENT; -+ -+ /* Large PUDs are not supported yet. */ -+ if (pud_large(*pud)) -+ return -EFAULT; -+ -+ *pmdp = pmd_offset(pud, addr); -+ return 0; - } - #endif - -@@ -778,8 +792,7 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, - pmd_t *pmdp; - pte_t *ptep; - -- pmdp = pmd_alloc_map(mm, addr); -- if (unlikely(!pmdp)) -+ if (pmd_lookup(mm, addr, &pmdp)) - return -EFAULT; - - ptl = pmd_lock(mm, pmdp); -@@ -881,8 +894,7 @@ int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr) - pte_t *ptep; - int cc = 0; - -- pmdp = pmd_alloc_map(mm, addr); -- if (unlikely(!pmdp)) -+ if (pmd_lookup(mm, addr, &pmdp)) - return -EFAULT; - - ptl = pmd_lock(mm, pmdp); -@@ -935,15 +947,24 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, - pmd_t *pmdp; - pte_t *ptep; - -- pmdp = pmd_alloc_map(mm, addr); -- if (unlikely(!pmdp)) -+ /* -+ * If we don't have a PTE table and if there is no huge page mapped, -+ * the storage key is 0. -+ */ -+ *key = 0; -+ -+ switch (pmd_lookup(mm, addr, &pmdp)) { -+ case -ENOENT: -+ return 0; -+ case 0: -+ break; -+ default: - return -EFAULT; -+ } - - ptl = pmd_lock(mm, pmdp); - if (!pmd_present(*pmdp)) { -- /* Not yet mapped memory has a zero key */ - spin_unlock(ptl); -- *key = 0; - return 0; - } - -@@ -988,6 +1009,7 @@ EXPORT_SYMBOL(get_guest_storage_key); - int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, - unsigned long *oldpte, unsigned long *oldpgste) - { -+ struct vm_area_struct *vma; - unsigned long pgstev; - spinlock_t *ptl; - pgste_t pgste; -@@ -997,6 +1019,10 @@ int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, - WARN_ON_ONCE(orc > ESSA_MAX); - if (unlikely(orc > ESSA_MAX)) - return -EINVAL; -+ -+ vma = vma_lookup(mm, hva); -+ if (!vma || is_vm_hugetlb_page(vma)) -+ return -EFAULT; - ptep = get_locked_pte(mm, hva, &ptl); - if (unlikely(!ptep)) - return -EFAULT; -@@ -1089,10 +1115,14 @@ EXPORT_SYMBOL(pgste_perform_essa); - int set_pgste_bits(struct mm_struct *mm, unsigned long hva, - unsigned long bits, unsigned long value) - { -+ struct vm_area_struct *vma; - spinlock_t *ptl; - pgste_t new; - pte_t *ptep; - -+ vma = vma_lookup(mm, hva); -+ if (!vma || is_vm_hugetlb_page(vma)) -+ return -EFAULT; - ptep = get_locked_pte(mm, hva, &ptl); - if (unlikely(!ptep)) - return -EFAULT; -@@ -1117,9 +1147,13 @@ EXPORT_SYMBOL(set_pgste_bits); - */ - int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep) - { -+ struct vm_area_struct *vma; - spinlock_t *ptl; - pte_t *ptep; - -+ vma = vma_lookup(mm, hva); -+ if (!vma || is_vm_hugetlb_page(vma)) -+ return -EFAULT; - ptep = get_locked_pte(mm, hva, &ptl); - if (unlikely(!ptep)) - return -EFAULT; -diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug -index 958f790273ab9..10290e5c1f438 100644 ---- a/arch/sh/Kconfig.debug -+++ b/arch/sh/Kconfig.debug -@@ -54,6 +54,7 @@ config DUMP_CODE - - config DWARF_UNWINDER - bool "Enable the DWARF unwinder for stacktraces" -+ depends on DEBUG_KERNEL - select FRAME_POINTER - default n - help -diff --git a/arch/sh/include/asm/sfp-machine.h b/arch/sh/include/asm/sfp-machine.h -index cbc7cf8c97ce6..2d2423478b71d 100644 ---- a/arch/sh/include/asm/sfp-machine.h -+++ b/arch/sh/include/asm/sfp-machine.h -@@ -13,6 +13,14 @@ - #ifndef _SFP_MACHINE_H - #define _SFP_MACHINE_H - -+#ifdef __BIG_ENDIAN__ -+#define __BYTE_ORDER __BIG_ENDIAN -+#define __LITTLE_ENDIAN 0 -+#else -+#define __BYTE_ORDER __LITTLE_ENDIAN -+#define __BIG_ENDIAN 0 -+#endif -+ - #define _FP_W_TYPE_SIZE 32 - #define _FP_W_TYPE unsigned long - #define _FP_WS_TYPE signed long -diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c -index ae354a2931e7e..fd6db0ab19288 100644 ---- a/arch/sh/kernel/cpu/fpu.c -+++ b/arch/sh/kernel/cpu/fpu.c -@@ -62,18 +62,20 @@ void fpu_state_restore(struct pt_regs *regs) - } - - if (!tsk_used_math(tsk)) { -- local_irq_enable(); -+ int ret; - /* - * does a slab alloc which can sleep - */ -- if (init_fpu(tsk)) { -+ local_irq_enable(); -+ ret = init_fpu(tsk); -+ local_irq_disable(); -+ if (ret) { - /* - * ran out of memory! - */ -- do_group_exit(SIGKILL); -+ force_sig(SIGKILL); - return; - } -- local_irq_disable(); - } - - grab_fpu(regs); -diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c -index f8a2bec0f260b..1261dc7b84e8b 100644 ---- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c -+++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c -@@ -73,8 +73,9 @@ static void shx3_prepare_cpus(unsigned int max_cpus) - BUILD_BUG_ON(SMP_MSG_NR >= 8); - - for (i = 0; i < SMP_MSG_NR; i++) -- request_irq(104 + i, ipi_interrupt_handler, -- IRQF_PERCPU, "IPI", (void *)(long)i); -+ if (request_irq(104 + i, ipi_interrupt_handler, -+ IRQF_PERCPU, "IPI", (void *)(long)i)) -+ pr_err("Failed to request irq %d\n", i); - - for (i = 0; i < max_cpus; i++) - set_cpu_present(i, true); -diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c -index e8be0eca0444a..615ba932c398e 100644 ---- a/arch/sh/math-emu/math.c -+++ b/arch/sh/math-emu/math.c -@@ -467,109 +467,6 @@ static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_reg - return id_sys(fregs, regs, code); - } - --/** -- * denormal_to_double - Given denormalized float number, -- * store double float -- * -- * @fpu: Pointer to sh_fpu_soft structure -- * @n: Index to FP register -- */ --static void denormal_to_double(struct sh_fpu_soft_struct *fpu, int n) --{ -- unsigned long du, dl; -- unsigned long x = fpu->fpul; -- int exp = 1023 - 126; -- -- if (x != 0 && (x & 0x7f800000) == 0) { -- du = (x & 0x80000000); -- while ((x & 0x00800000) == 0) { -- x <<= 1; -- exp--; -- } -- x &= 0x007fffff; -- du |= (exp << 20) | (x >> 3); -- dl = x << 29; -- -- fpu->fp_regs[n] = du; -- fpu->fp_regs[n+1] = dl; -- } --} -- --/** -- * ieee_fpe_handler - Handle denormalized number exception -- * -- * @regs: Pointer to register structure -- * -- * Returns 1 when it's handled (should not cause exception). -- */ --static int ieee_fpe_handler(struct pt_regs *regs) --{ -- unsigned short insn = *(unsigned short *)regs->pc; -- unsigned short finsn; -- unsigned long nextpc; -- int nib[4] = { -- (insn >> 12) & 0xf, -- (insn >> 8) & 0xf, -- (insn >> 4) & 0xf, -- insn & 0xf}; -- -- if (nib[0] == 0xb || -- (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ -- regs->pr = regs->pc + 4; -- -- if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ -- nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); -- finsn = *(unsigned short *) (regs->pc + 2); -- } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */ -- if (regs->sr & 1) -- nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); -- else -- nextpc = regs->pc + 4; -- finsn = *(unsigned short *) (regs->pc + 2); -- } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */ -- if (regs->sr & 1) -- nextpc = regs->pc + 4; -- else -- nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); -- finsn = *(unsigned short *) (regs->pc + 2); -- } else if (nib[0] == 0x4 && nib[3] == 0xb && -- (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */ -- nextpc = regs->regs[nib[1]]; -- finsn = *(unsigned short *) (regs->pc + 2); -- } else if (nib[0] == 0x0 && nib[3] == 0x3 && -- (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */ -- nextpc = regs->pc + 4 + regs->regs[nib[1]]; -- finsn = *(unsigned short *) (regs->pc + 2); -- } else if (insn == 0x000b) { /* rts */ -- nextpc = regs->pr; -- finsn = *(unsigned short *) (regs->pc + 2); -- } else { -- nextpc = regs->pc + 2; -- finsn = insn; -- } -- -- if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ -- struct task_struct *tsk = current; -- -- if ((tsk->thread.xstate->softfpu.fpscr & (1 << 17))) { -- /* FPU error */ -- denormal_to_double (&tsk->thread.xstate->softfpu, -- (finsn >> 8) & 0xf); -- tsk->thread.xstate->softfpu.fpscr &= -- ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); -- task_thread_info(tsk)->status |= TS_USEDFPU; -- } else { -- force_sig_fault(SIGFPE, FPE_FLTINV, -- (void __user *)regs->pc); -- } -- -- regs->pc = nextpc; -- return 1; -- } -- -- return 0; --} -- - /** - * fpu_init - Initialize FPU registers - * @fpu: Pointer to software emulated FPU registers. -diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile -index 849236d4eca48..45e5c76d449ea 100644 ---- a/arch/sparc/boot/Makefile -+++ b/arch/sparc/boot/Makefile -@@ -22,7 +22,7 @@ ifeq ($(CONFIG_SPARC64),y) - - # Actual linking - --$(obj)/zImage: $(obj)/image -+$(obj)/zImage: $(obj)/image FORCE - $(call if_changed,gzip) - @echo ' kernel: $@ is ready' - -@@ -31,7 +31,7 @@ $(obj)/vmlinux.aout: vmlinux FORCE - @echo ' kernel: $@ is ready' - else - --$(obj)/zImage: $(obj)/image -+$(obj)/zImage: $(obj)/image FORCE - $(call if_changed,strip) - @echo ' kernel: $@ is ready' - -@@ -44,7 +44,7 @@ OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment - $(obj)/image.bin: $(obj)/image FORCE - $(call if_changed,objcopy) - --$(obj)/image.gz: $(obj)/image.bin -+$(obj)/image.gz: $(obj)/image.bin FORCE - $(call if_changed,gzip) - - UIMAGE_LOADADDR = $(CONFIG_UBOOT_LOAD_ADDR) -@@ -56,7 +56,7 @@ quiet_cmd_uimage.o = UIMAGE.O $@ - -r -b binary $@ -o $@.o - - targets += uImage --$(obj)/uImage: $(obj)/image.gz -+$(obj)/uImage: $(obj)/image.gz FORCE - $(call if_changed,uimage) - $(call if_changed,uimage.o) - @echo ' Image $@ is ready' -diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c -index 02f3ad55dfe31..ffab16369beac 100644 ---- a/arch/sparc/kernel/signal_32.c -+++ b/arch/sparc/kernel/signal_32.c -@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *ksig, struct pt_regs *regs, - get_sigframe(ksig, regs, sigframe_size); - - if (invalid_frame_pointer(sf, sigframe_size)) { -- do_exit(SIGILL); -+ force_exit_sig(SIGILL); - return -EINVAL; - } - -@@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs, - sf = (struct rt_signal_frame __user *) - get_sigframe(ksig, regs, sigframe_size); - if (invalid_frame_pointer(sf, sigframe_size)) { -- do_exit(SIGILL); -+ force_exit_sig(SIGILL); - return -EINVAL; - } - -diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c -index 69a6ba6e92937..8f20862ccc83e 100644 ---- a/arch/sparc/kernel/windows.c -+++ b/arch/sparc/kernel/windows.c -@@ -121,8 +121,10 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who) - - if ((sp & 7) || - copy_to_user((char __user *) sp, &tp->reg_window[window], -- sizeof(struct reg_window32))) -- do_exit(SIGILL); -+ sizeof(struct reg_window32))) { -+ force_exit_sig(SIGILL); -+ return; -+ } - } - tp->w_saved = 0; - } -diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c -index 3198c47673879..c32efb09db214 100644 ---- a/arch/um/kernel/trap.c -+++ b/arch/um/kernel/trap.c -@@ -158,7 +158,7 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) - - void fatal_sigsegv(void) - { -- force_sigsegv(SIGSEGV); -+ force_fatal_sig(SIGSEGV); - do_signal(¤t->thread.regs); - /* - * This is to tell gcc that we're not returning - do_signal -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index d9830e7e1060f..1f96809606ac5 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -1256,7 +1256,8 @@ config TOSHIBA - - config I8K - tristate "Dell i8k legacy laptop support" -- select HWMON -+ depends on HWMON -+ depends on PROC_FS - select SENSORS_DELL_SMM - help - This option enables legacy /proc/i8k userspace interface in hwmon -@@ -1518,6 +1519,7 @@ config AMD_MEM_ENCRYPT - select ARCH_HAS_FORCE_DMA_UNENCRYPTED - select INSTRUCTION_DECODER - select ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS -+ select ARCH_HAS_CC_PLATFORM - help - Say yes to enable support for the encryption of system memory. - This requires an AMD processor that supports Secure Memory -@@ -1917,6 +1919,7 @@ config EFI - depends on ACPI - select UCS2_STRING - select EFI_RUNTIME_WRAPPERS -+ select ARCH_USE_MEMREMAP_PROT - help - This enables the kernel to use EFI runtime services that are - available (such as the EFI variable services). -diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c -index 0fc961bef299c..e09f4672dd382 100644 ---- a/arch/x86/crypto/aesni-intel_glue.c -+++ b/arch/x86/crypto/aesni-intel_glue.c -@@ -866,7 +866,7 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt) - req = &subreq; - - err = skcipher_walk_virt(&walk, req, false); -- if (err) -+ if (!walk.nbytes) - return err; - } else { - tail = 0; -diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S -index e38a4cf795d96..97b1f84bb53f8 100644 ---- a/arch/x86/entry/entry_64.S -+++ b/arch/x86/entry/entry_64.S -@@ -574,6 +574,10 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) - ud2 - 1: - #endif -+#ifdef CONFIG_XEN_PV -+ ALTERNATIVE "", "jmp xenpv_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV -+#endif -+ - POP_REGS pop_rdi=0 - - /* -@@ -890,6 +894,7 @@ SYM_CODE_START_LOCAL(paranoid_entry) - .Lparanoid_entry_checkgs: - /* EBX = 1 -> kernel GSBASE active, no restore required */ - movl $1, %ebx -+ - /* - * The kernel-enforced convention is a negative GSBASE indicates - * a kernel value. No SWAPGS needed on entry and exit. -@@ -897,21 +902,14 @@ SYM_CODE_START_LOCAL(paranoid_entry) - movl $MSR_GS_BASE, %ecx - rdmsr - testl %edx, %edx -- jns .Lparanoid_entry_swapgs -- ret -+ js .Lparanoid_kernel_gsbase - --.Lparanoid_entry_swapgs: -+ /* EBX = 0 -> SWAPGS required on exit */ -+ xorl %ebx, %ebx - swapgs -+.Lparanoid_kernel_gsbase: - -- /* -- * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an -- * unconditional CR3 write, even in the PTI case. So do an lfence -- * to prevent GS speculation, regardless of whether PTI is enabled. -- */ - FENCE_SWAPGS_KERNEL_ENTRY -- -- /* EBX = 0 -> SWAPGS required on exit */ -- xorl %ebx, %ebx - ret - SYM_CODE_END(paranoid_entry) - -@@ -993,11 +991,6 @@ SYM_CODE_START_LOCAL(error_entry) - pushq %r12 - ret - --.Lerror_entry_done_lfence: -- FENCE_SWAPGS_KERNEL_ENTRY --.Lerror_entry_done: -- ret -- - /* - * There are two places in the kernel that can potentially fault with - * usergs. Handle them here. B stepping K8s sometimes report a -@@ -1020,8 +1013,14 @@ SYM_CODE_START_LOCAL(error_entry) - * .Lgs_change's error handler with kernel gsbase. - */ - SWAPGS -- FENCE_SWAPGS_USER_ENTRY -- jmp .Lerror_entry_done -+ -+ /* -+ * Issue an LFENCE to prevent GS speculation, regardless of whether it is a -+ * kernel or user gsbase. -+ */ -+.Lerror_entry_done_lfence: -+ FENCE_SWAPGS_KERNEL_ENTRY -+ ret - - .Lbstep_iret: - /* Fix truncated RIP */ -diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c -index 1b40b92970831..fd2ee9408e914 100644 ---- a/arch/x86/entry/vsyscall/vsyscall_64.c -+++ b/arch/x86/entry/vsyscall/vsyscall_64.c -@@ -226,7 +226,8 @@ bool emulate_vsyscall(unsigned long error_code, - if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { - warn_bad_vsyscall(KERN_DEBUG, regs, - "seccomp tried to change syscall nr or ip"); -- do_exit(SIGSYS); -+ force_exit_sig(SIGSYS); -+ return true; - } - regs->orig_ax = -1; - if (tmp) -diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c -index 9a044438072ba..c7f1cc433a6aa 100644 ---- a/arch/x86/events/intel/core.c -+++ b/arch/x86/events/intel/core.c -@@ -243,7 +243,8 @@ static struct extra_reg intel_skl_extra_regs[] __read_mostly = { - - static struct event_constraint intel_icl_event_constraints[] = { - FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ -- FIXED_EVENT_CONSTRAINT(0x01c0, 0), /* INST_RETIRED.PREC_DIST */ -+ FIXED_EVENT_CONSTRAINT(0x01c0, 0), /* old INST_RETIRED.PREC_DIST */ -+ FIXED_EVENT_CONSTRAINT(0x0100, 0), /* INST_RETIRED.PREC_DIST */ - FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ - FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ - FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */ -@@ -288,7 +289,7 @@ static struct extra_reg intel_spr_extra_regs[] __read_mostly = { - - static struct event_constraint intel_spr_event_constraints[] = { - FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ -- FIXED_EVENT_CONSTRAINT(0x01c0, 0), /* INST_RETIRED.PREC_DIST */ -+ FIXED_EVENT_CONSTRAINT(0x0100, 0), /* INST_RETIRED.PREC_DIST */ - FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ - FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ - FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */ -@@ -2998,8 +2999,10 @@ intel_vlbr_constraints(struct perf_event *event) - { - struct event_constraint *c = &vlbr_constraint; - -- if (unlikely(constraint_match(c, event->hw.config))) -+ if (unlikely(constraint_match(c, event->hw.config))) { -+ event->hw.flags |= c->flags; - return c; -+ } - - return NULL; - } -diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c -index 8647713276a73..4dbb55a43dad2 100644 ---- a/arch/x86/events/intel/ds.c -+++ b/arch/x86/events/intel/ds.c -@@ -923,7 +923,8 @@ struct event_constraint intel_skl_pebs_event_constraints[] = { - }; - - struct event_constraint intel_icl_pebs_event_constraints[] = { -- INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ -+ INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x100000000ULL), /* old INST_RETIRED.PREC_DIST */ -+ INTEL_FLAGS_UEVENT_CONSTRAINT(0x0100, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ - INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), /* SLOTS */ - - INTEL_PLD_CONSTRAINT(0x1cd, 0xff), /* MEM_TRANS_RETIRED.LOAD_LATENCY */ -@@ -943,7 +944,7 @@ struct event_constraint intel_icl_pebs_event_constraints[] = { - }; - - struct event_constraint intel_spr_pebs_event_constraints[] = { -- INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL), -+ INTEL_FLAGS_UEVENT_CONSTRAINT(0x100, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ - INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), - - INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xfe), -diff --git a/arch/x86/events/intel/uncore_discovery.h b/arch/x86/events/intel/uncore_discovery.h -index 7280c8a3c8310..6d735611c281c 100644 ---- a/arch/x86/events/intel/uncore_discovery.h -+++ b/arch/x86/events/intel/uncore_discovery.h -@@ -30,7 +30,7 @@ - - - #define uncore_discovery_invalid_unit(unit) \ -- (!unit.table1 || !unit.ctl || !unit.table3 || \ -+ (!unit.table1 || !unit.ctl || \ - unit.table1 == -1ULL || unit.ctl == -1ULL || \ - unit.table3 == -1ULL) - -diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c -index 5ddc0f30db6fc..3660f698fb2aa 100644 ---- a/arch/x86/events/intel/uncore_snbep.c -+++ b/arch/x86/events/intel/uncore_snbep.c -@@ -452,7 +452,7 @@ - #define ICX_M3UPI_PCI_PMON_BOX_CTL 0xa0 - - /* ICX IMC */ --#define ICX_NUMBER_IMC_CHN 2 -+#define ICX_NUMBER_IMC_CHN 3 - #define ICX_IMC_MEM_STRIDE 0x4 - - /* SPR */ -@@ -3608,6 +3608,9 @@ static int skx_cha_hw_config(struct intel_uncore_box *box, struct perf_event *ev - struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; - struct extra_reg *er; - int idx = 0; -+ /* Any of the CHA events may be filtered by Thread/Core-ID.*/ -+ if (event->hw.config & SNBEP_CBO_PMON_CTL_TID_EN) -+ idx = SKX_CHA_MSR_PMON_BOX_FILTER_TID; - - for (er = skx_uncore_cha_extra_regs; er->msr; er++) { - if (er->event != (event->hw.config & er->config_mask)) -@@ -3675,6 +3678,7 @@ static struct event_constraint skx_uncore_iio_constraints[] = { - UNCORE_EVENT_CONSTRAINT(0xc0, 0xc), - UNCORE_EVENT_CONSTRAINT(0xc5, 0xc), - UNCORE_EVENT_CONSTRAINT(0xd4, 0xc), -+ UNCORE_EVENT_CONSTRAINT(0xd5, 0xc), - EVENT_CONSTRAINT_END - }; - -@@ -4525,6 +4529,13 @@ static void snr_iio_cleanup_mapping(struct intel_uncore_type *type) - pmu_iio_cleanup_mapping(type, &snr_iio_mapping_group); - } - -+static struct event_constraint snr_uncore_iio_constraints[] = { -+ UNCORE_EVENT_CONSTRAINT(0x83, 0x3), -+ UNCORE_EVENT_CONSTRAINT(0xc0, 0xc), -+ UNCORE_EVENT_CONSTRAINT(0xd5, 0xc), -+ EVENT_CONSTRAINT_END -+}; -+ - static struct intel_uncore_type snr_uncore_iio = { - .name = "iio", - .num_counters = 4, -@@ -4536,6 +4547,7 @@ static struct intel_uncore_type snr_uncore_iio = { - .event_mask_ext = SNR_IIO_PMON_RAW_EVENT_MASK_EXT, - .box_ctl = SNR_IIO_MSR_PMON_BOX_CTL, - .msr_offset = SNR_IIO_MSR_OFFSET, -+ .constraints = snr_uncore_iio_constraints, - .ops = &ivbep_uncore_msr_ops, - .format_group = &snr_uncore_iio_format_group, - .attr_update = snr_iio_attr_update, -@@ -5076,8 +5088,10 @@ static struct event_constraint icx_uncore_iio_constraints[] = { - UNCORE_EVENT_CONSTRAINT(0x02, 0x3), - UNCORE_EVENT_CONSTRAINT(0x03, 0x3), - UNCORE_EVENT_CONSTRAINT(0x83, 0x3), -+ UNCORE_EVENT_CONSTRAINT(0x88, 0xc), - UNCORE_EVENT_CONSTRAINT(0xc0, 0xc), - UNCORE_EVENT_CONSTRAINT(0xc5, 0xc), -+ UNCORE_EVENT_CONSTRAINT(0xd5, 0xc), - EVENT_CONSTRAINT_END - }; - -@@ -5463,7 +5477,7 @@ static struct intel_uncore_ops icx_uncore_mmio_ops = { - static struct intel_uncore_type icx_uncore_imc = { - .name = "imc", - .num_counters = 4, -- .num_boxes = 8, -+ .num_boxes = 12, - .perf_ctr_bits = 48, - .fixed_ctr_bits = 48, - .fixed_ctr = SNR_IMC_MMIO_PMON_FIXED_CTR, -@@ -5647,6 +5661,7 @@ static struct intel_uncore_type spr_uncore_chabox = { - .event_mask = SPR_CHA_PMON_EVENT_MASK, - .event_mask_ext = SPR_RAW_EVENT_MASK_EXT, - .num_shared_regs = 1, -+ .constraints = skx_uncore_chabox_constraints, - .ops = &spr_uncore_chabox_ops, - .format_group = &spr_uncore_chabox_format_group, - .attr_update = uncore_alias_groups, -@@ -5658,6 +5673,7 @@ static struct intel_uncore_type spr_uncore_iio = { - .event_mask_ext = SNR_IIO_PMON_RAW_EVENT_MASK_EXT, - .format_group = &snr_uncore_iio_format_group, - .attr_update = uncore_alias_groups, -+ .constraints = icx_uncore_iio_constraints, - }; - - static struct attribute *spr_uncore_raw_formats_attr[] = { -@@ -5686,9 +5702,16 @@ static struct intel_uncore_type spr_uncore_irp = { - - }; - -+static struct event_constraint spr_uncore_m2pcie_constraints[] = { -+ UNCORE_EVENT_CONSTRAINT(0x14, 0x3), -+ UNCORE_EVENT_CONSTRAINT(0x2d, 0x3), -+ EVENT_CONSTRAINT_END -+}; -+ - static struct intel_uncore_type spr_uncore_m2pcie = { - SPR_UNCORE_COMMON_FORMAT(), - .name = "m2pcie", -+ .constraints = spr_uncore_m2pcie_constraints, - }; - - static struct intel_uncore_type spr_uncore_pcu = { -@@ -5765,6 +5788,7 @@ static struct intel_uncore_type spr_uncore_upi = { - static struct intel_uncore_type spr_uncore_m3upi = { - SPR_UNCORE_PCI_COMMON_FORMAT(), - .name = "m3upi", -+ .constraints = icx_uncore_m3upi_constraints, - }; - - static struct intel_uncore_type spr_uncore_mdf = { -diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c -index 708a2712a516d..b6d48ca5b0f17 100644 ---- a/arch/x86/hyperv/hv_init.c -+++ b/arch/x86/hyperv/hv_init.c -@@ -139,7 +139,6 @@ void set_hv_tscchange_cb(void (*cb)(void)) - struct hv_reenlightenment_control re_ctrl = { - .vector = HYPERV_REENLIGHTENMENT_VECTOR, - .enabled = 1, -- .target_vp = hv_vp_index[smp_processor_id()] - }; - struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1}; - -@@ -148,13 +147,20 @@ void set_hv_tscchange_cb(void (*cb)(void)) - return; - } - -+ if (!hv_vp_index) -+ return; -+ - hv_reenlightenment_cb = cb; - - /* Make sure callback is registered before we write to MSRs */ - wmb(); - -+ re_ctrl.target_vp = hv_vp_index[get_cpu()]; -+ - wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl)); - wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl)); -+ -+ put_cpu(); - } - EXPORT_SYMBOL_GPL(set_hv_tscchange_cb); - -@@ -342,20 +348,13 @@ static void __init hv_get_partition_id(void) - */ - void __init hyperv_init(void) - { -- u64 guest_id, required_msrs; -+ u64 guest_id; - union hv_x64_msr_hypercall_contents hypercall_msr; - int cpuhp; - - if (x86_hyper_type != X86_HYPER_MS_HYPERV) - return; - -- /* Absolutely required MSRs */ -- required_msrs = HV_MSR_HYPERCALL_AVAILABLE | -- HV_MSR_VP_INDEX_AVAILABLE; -- -- if ((ms_hyperv.features & required_msrs) != required_msrs) -- return; -- - if (hv_common_init()) - return; - -diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h -index 3d52b094850a9..dd5ea1bdf04c5 100644 ---- a/arch/x86/include/asm/cpu_entry_area.h -+++ b/arch/x86/include/asm/cpu_entry_area.h -@@ -10,6 +10,12 @@ - - #ifdef CONFIG_X86_64 - -+#ifdef CONFIG_AMD_MEM_ENCRYPT -+#define VC_EXCEPTION_STKSZ EXCEPTION_STKSZ -+#else -+#define VC_EXCEPTION_STKSZ 0 -+#endif -+ - /* Macro to enforce the same ordering and stack sizes */ - #define ESTACKS_MEMBERS(guardsize, optional_stack_size) \ - char DF_stack_guard[guardsize]; \ -@@ -28,7 +34,7 @@ - - /* The exception stacks' physical storage. No guard pages required */ - struct exception_stacks { -- ESTACKS_MEMBERS(0, 0) -+ ESTACKS_MEMBERS(0, VC_EXCEPTION_STKSZ) - }; - - /* The effective cpu entry area mapping with guard pages. */ -diff --git a/arch/x86/include/asm/insn-eval.h b/arch/x86/include/asm/insn-eval.h -index 91d7182ad2d6e..4ec3613551e3b 100644 ---- a/arch/x86/include/asm/insn-eval.h -+++ b/arch/x86/include/asm/insn-eval.h -@@ -21,6 +21,7 @@ int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs); - int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs); - unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); - int insn_get_code_seg_params(struct pt_regs *regs); -+int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip); - int insn_fetch_from_user(struct pt_regs *regs, - unsigned char buf[MAX_INSN_SIZE]); - int insn_fetch_from_user_inatomic(struct pt_regs *regs, -diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h -index 562854c608082..8d55bd11848cb 100644 ---- a/arch/x86/include/asm/irq_stack.h -+++ b/arch/x86/include/asm/irq_stack.h -@@ -77,11 +77,11 @@ - * Function calls can clobber anything except the callee-saved - * registers. Tell the compiler. - */ --#define call_on_irqstack(func, asm_call, argconstr...) \ -+#define call_on_stack(stack, func, asm_call, argconstr...) \ - { \ - register void *tos asm("r11"); \ - \ -- tos = ((void *)__this_cpu_read(hardirq_stack_ptr)); \ -+ tos = ((void *)(stack)); \ - \ - asm_inline volatile( \ - "movq %%rsp, (%[tos]) \n" \ -@@ -98,6 +98,25 @@ - ); \ - } - -+#define ASM_CALL_ARG0 \ -+ "call %P[__func] \n" -+ -+#define ASM_CALL_ARG1 \ -+ "movq %[arg1], %%rdi \n" \ -+ ASM_CALL_ARG0 -+ -+#define ASM_CALL_ARG2 \ -+ "movq %[arg2], %%rsi \n" \ -+ ASM_CALL_ARG1 -+ -+#define ASM_CALL_ARG3 \ -+ "movq %[arg3], %%rdx \n" \ -+ ASM_CALL_ARG2 -+ -+#define call_on_irqstack(func, asm_call, argconstr...) \ -+ call_on_stack(__this_cpu_read(hardirq_stack_ptr), \ -+ func, asm_call, argconstr) -+ - /* Macros to assert type correctness for run_*_on_irqstack macros */ - #define assert_function_type(func, proto) \ - static_assert(__builtin_types_compatible_p(typeof(&func), proto)) -@@ -147,8 +166,7 @@ - */ - #define ASM_CALL_SYSVEC \ - "call irq_enter_rcu \n" \ -- "movq %[arg1], %%rdi \n" \ -- "call %P[__func] \n" \ -+ ASM_CALL_ARG1 \ - "call irq_exit_rcu \n" - - #define SYSVEC_CONSTRAINTS , [arg1] "r" (regs) -@@ -168,12 +186,10 @@ - */ - #define ASM_CALL_IRQ \ - "call irq_enter_rcu \n" \ -- "movq %[arg1], %%rdi \n" \ -- "movl %[arg2], %%esi \n" \ -- "call %P[__func] \n" \ -+ ASM_CALL_ARG2 \ - "call irq_exit_rcu \n" - --#define IRQ_CONSTRAINTS , [arg1] "r" (regs), [arg2] "r" (vector) -+#define IRQ_CONSTRAINTS , [arg1] "r" (regs), [arg2] "r" ((unsigned long)vector) - - #define run_irq_on_irqstack_cond(func, regs, vector) \ - { \ -@@ -185,9 +201,6 @@ - IRQ_CONSTRAINTS, regs, vector); \ - } - --#define ASM_CALL_SOFTIRQ \ -- "call %P[__func] \n" -- - /* - * Macro to invoke __do_softirq on the irq stack. This is only called from - * task context when bottom halves are about to be reenabled and soft -@@ -197,7 +210,7 @@ - #define do_softirq_own_stack() \ - { \ - __this_cpu_write(hardirq_stack_inuse, true); \ -- call_on_irqstack(__do_softirq, ASM_CALL_SOFTIRQ); \ -+ call_on_irqstack(__do_softirq, ASM_CALL_ARG0); \ - __this_cpu_write(hardirq_stack_inuse, false); \ - } - -diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h -index 13f64654dfff8..a11785ebf628b 100644 ---- a/arch/x86/include/asm/kvm_host.h -+++ b/arch/x86/include/asm/kvm_host.h -@@ -98,7 +98,7 @@ - KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) - #define KVM_REQ_TLB_FLUSH_CURRENT KVM_ARCH_REQ(26) - #define KVM_REQ_TLB_FLUSH_GUEST \ -- KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_NO_WAKEUP) -+ KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) - #define KVM_REQ_APF_READY KVM_ARCH_REQ(28) - #define KVM_REQ_MSR_FILTER_CHANGED KVM_ARCH_REQ(29) - #define KVM_REQ_UPDATE_CPU_DIRTY_LOGGING \ -@@ -364,6 +364,7 @@ union kvm_mmu_extended_role { - unsigned int cr4_smap:1; - unsigned int cr4_smep:1; - unsigned int cr4_la57:1; -+ unsigned int efer_lma:1; - }; - }; - -@@ -751,7 +752,7 @@ struct kvm_vcpu_arch { - u8 preempted; - u64 msr_val; - u64 last_steal; -- struct gfn_to_pfn_cache cache; -+ struct gfn_to_hva_cache cache; - } st; - - u64 l1_tsc_offset; -diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h -index 9c80c68d75b54..3fb9f5ebefa42 100644 ---- a/arch/x86/include/asm/mem_encrypt.h -+++ b/arch/x86/include/asm/mem_encrypt.h -@@ -13,6 +13,7 @@ - #ifndef __ASSEMBLY__ - - #include <linux/init.h> -+#include <linux/cc_platform.h> - - #include <asm/bootparam.h> - -diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h -index a8d4ad8565681..e9e2c3ba59239 100644 ---- a/arch/x86/include/asm/page_64_types.h -+++ b/arch/x86/include/asm/page_64_types.h -@@ -15,7 +15,7 @@ - #define THREAD_SIZE_ORDER (2 + KASAN_STACK_ORDER) - #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) - --#define EXCEPTION_STACK_ORDER (0 + KASAN_STACK_ORDER) -+#define EXCEPTION_STACK_ORDER (1 + KASAN_STACK_ORDER) - #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER) - - #define IRQ_STACK_ORDER (2 + KASAN_STACK_ORDER) -diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index 9ad2acaaae9b8..577f342dbfb27 100644 ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -518,6 +518,7 @@ struct thread_struct { - */ - unsigned long iopl_emul; - -+ unsigned int iopl_warn:1; - unsigned int sig_on_uaccess_err:1; - - /* -diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h -index f248eb2ac2d4a..3881b5333eb81 100644 ---- a/arch/x86/include/asm/stacktrace.h -+++ b/arch/x86/include/asm/stacktrace.h -@@ -38,6 +38,16 @@ int get_stack_info(unsigned long *stack, struct task_struct *task, - bool get_stack_info_noinstr(unsigned long *stack, struct task_struct *task, - struct stack_info *info); - -+static __always_inline -+bool get_stack_guard_info(unsigned long *stack, struct stack_info *info) -+{ -+ /* make sure it's not in the stack proper */ -+ if (get_stack_info_noinstr(stack, current, info)) -+ return false; -+ /* but if it is in the page below it, we hit a guard */ -+ return get_stack_info_noinstr((void *)stack + PAGE_SIZE, current, info); -+} -+ - const char *stack_type_name(enum stack_type type); - - static inline bool on_stack(struct stack_info *info, void *addr, size_t len) -diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h -index 7f7200021bd13..6221be7cafc3b 100644 ---- a/arch/x86/include/asm/traps.h -+++ b/arch/x86/include/asm/traps.h -@@ -40,9 +40,9 @@ void math_emulate(struct math_emu_info *); - bool fault_in_kernel_space(unsigned long address); - - #ifdef CONFIG_VMAP_STACK --void __noreturn handle_stack_overflow(const char *message, -- struct pt_regs *regs, -- unsigned long fault_address); -+void __noreturn handle_stack_overflow(struct pt_regs *regs, -+ unsigned long fault_address, -+ struct stack_info *info); - #endif - - #endif /* _ASM_X86_TRAPS_H */ -diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h -index ff4b52e37e60d..5adab895127e1 100644 ---- a/arch/x86/include/asm/xen/hypervisor.h -+++ b/arch/x86/include/asm/xen/hypervisor.h -@@ -62,4 +62,9 @@ void xen_arch_register_cpu(int num); - void xen_arch_unregister_cpu(int num); - #endif - -+#ifdef CONFIG_PVH -+void __init xen_pvh_init(struct boot_params *boot_params); -+void __init mem_map_via_hcall(struct boot_params *boot_params_p); -+#endif -+ - #endif /* _ASM_X86_XEN_HYPERVISOR_H */ -diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile -index 8f4e8fa6ed759..2ff3e600f4269 100644 ---- a/arch/x86/kernel/Makefile -+++ b/arch/x86/kernel/Makefile -@@ -21,6 +21,7 @@ CFLAGS_REMOVE_ftrace.o = -pg - CFLAGS_REMOVE_early_printk.o = -pg - CFLAGS_REMOVE_head64.o = -pg - CFLAGS_REMOVE_sev.o = -pg -+CFLAGS_REMOVE_cc_platform.o = -pg - endif - - KASAN_SANITIZE_head$(BITS).o := n -@@ -29,6 +30,7 @@ KASAN_SANITIZE_dumpstack_$(BITS).o := n - KASAN_SANITIZE_stacktrace.o := n - KASAN_SANITIZE_paravirt.o := n - KASAN_SANITIZE_sev.o := n -+KASAN_SANITIZE_cc_platform.o := n - - # With some compiler versions the generated code results in boot hangs, caused - # by several compilation units. To be safe, disable all instrumentation. -@@ -47,6 +49,7 @@ endif - KCOV_INSTRUMENT := n - - CFLAGS_head$(BITS).o += -fno-stack-protector -+CFLAGS_cc_platform.o += -fno-stack-protector - - CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace - -@@ -147,6 +150,9 @@ obj-$(CONFIG_UNWINDER_FRAME_POINTER) += unwind_frame.o - obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o - - obj-$(CONFIG_AMD_MEM_ENCRYPT) += sev.o -+ -+obj-$(CONFIG_ARCH_HAS_CC_PLATFORM) += cc_platform.o -+ - ### - # 64 bit specific files - ifeq ($(CONFIG_X86_64),y) -diff --git a/arch/x86/kernel/cc_platform.c b/arch/x86/kernel/cc_platform.c -new file mode 100644 -index 0000000000000..03bb2f343ddb7 ---- /dev/null -+++ b/arch/x86/kernel/cc_platform.c -@@ -0,0 +1,69 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Confidential Computing Platform Capability checks -+ * -+ * Copyright (C) 2021 Advanced Micro Devices, Inc. -+ * -+ * Author: Tom Lendacky <thomas.lendacky@amd.com> -+ */ -+ -+#include <linux/export.h> -+#include <linux/cc_platform.h> -+#include <linux/mem_encrypt.h> -+ -+#include <asm/processor.h> -+ -+static bool __maybe_unused intel_cc_platform_has(enum cc_attr attr) -+{ -+#ifdef CONFIG_INTEL_TDX_GUEST -+ return false; -+#else -+ return false; -+#endif -+} -+ -+/* -+ * SME and SEV are very similar but they are not the same, so there are -+ * times that the kernel will need to distinguish between SME and SEV. The -+ * cc_platform_has() function is used for this. When a distinction isn't -+ * needed, the CC_ATTR_MEM_ENCRYPT attribute can be used. -+ * -+ * The trampoline code is a good example for this requirement. Before -+ * paging is activated, SME will access all memory as decrypted, but SEV -+ * will access all memory as encrypted. So, when APs are being brought -+ * up under SME the trampoline area cannot be encrypted, whereas under SEV -+ * the trampoline area must be encrypted. -+ */ -+static bool amd_cc_platform_has(enum cc_attr attr) -+{ -+#ifdef CONFIG_AMD_MEM_ENCRYPT -+ switch (attr) { -+ case CC_ATTR_MEM_ENCRYPT: -+ return sme_me_mask; -+ -+ case CC_ATTR_HOST_MEM_ENCRYPT: -+ return sme_me_mask && !(sev_status & MSR_AMD64_SEV_ENABLED); -+ -+ case CC_ATTR_GUEST_MEM_ENCRYPT: -+ return sev_status & MSR_AMD64_SEV_ENABLED; -+ -+ case CC_ATTR_GUEST_STATE_ENCRYPT: -+ return sev_status & MSR_AMD64_SEV_ES_ENABLED; -+ -+ default: -+ return false; -+ } -+#else -+ return false; -+#endif -+} -+ -+ -+bool cc_platform_has(enum cc_attr attr) -+{ -+ if (sme_me_mask) -+ return amd_cc_platform_has(attr); -+ -+ return false; -+} -+EXPORT_SYMBOL_GPL(cc_platform_has); -diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c -index 2131af9f2fa23..4edb6f0f628c2 100644 ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -989,6 +989,8 @@ static void init_amd(struct cpuinfo_x86 *c) - if (cpu_has(c, X86_FEATURE_IRPERF) && - !cpu_has_amd_erratum(c, amd_erratum_1054)) - msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT); -+ -+ check_null_seg_clears_base(c); - } - - #ifdef CONFIG_X86_32 -diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c -index b3410f1ac2175..58b1416c05da4 100644 ---- a/arch/x86/kernel/cpu/common.c -+++ b/arch/x86/kernel/cpu/common.c -@@ -1396,9 +1396,8 @@ void __init early_cpu_init(void) - early_identify_cpu(&boot_cpu_data); - } - --static void detect_null_seg_behavior(struct cpuinfo_x86 *c) -+static bool detect_null_seg_behavior(void) - { --#ifdef CONFIG_X86_64 - /* - * Empirically, writing zero to a segment selector on AMD does - * not clear the base, whereas writing zero to a segment -@@ -1419,10 +1418,43 @@ static void detect_null_seg_behavior(struct cpuinfo_x86 *c) - wrmsrl(MSR_FS_BASE, 1); - loadsegment(fs, 0); - rdmsrl(MSR_FS_BASE, tmp); -- if (tmp != 0) -- set_cpu_bug(c, X86_BUG_NULL_SEG); - wrmsrl(MSR_FS_BASE, old_base); --#endif -+ return tmp == 0; -+} -+ -+void check_null_seg_clears_base(struct cpuinfo_x86 *c) -+{ -+ /* BUG_NULL_SEG is only relevant with 64bit userspace */ -+ if (!IS_ENABLED(CONFIG_X86_64)) -+ return; -+ -+ /* Zen3 CPUs advertise Null Selector Clears Base in CPUID. */ -+ if (c->extended_cpuid_level >= 0x80000021 && -+ cpuid_eax(0x80000021) & BIT(6)) -+ return; -+ -+ /* -+ * CPUID bit above wasn't set. If this kernel is still running -+ * as a HV guest, then the HV has decided not to advertize -+ * that CPUID bit for whatever reason. For example, one -+ * member of the migration pool might be vulnerable. Which -+ * means, the bug is present: set the BUG flag and return. -+ */ -+ if (cpu_has(c, X86_FEATURE_HYPERVISOR)) { -+ set_cpu_bug(c, X86_BUG_NULL_SEG); -+ return; -+ } -+ -+ /* -+ * Zen2 CPUs also have this behaviour, but no CPUID bit. -+ * 0x18 is the respective family for Hygon. -+ */ -+ if ((c->x86 == 0x17 || c->x86 == 0x18) && -+ detect_null_seg_behavior()) -+ return; -+ -+ /* All the remaining ones are affected */ -+ set_cpu_bug(c, X86_BUG_NULL_SEG); - } - - static void generic_identify(struct cpuinfo_x86 *c) -@@ -1458,8 +1490,6 @@ static void generic_identify(struct cpuinfo_x86 *c) - - get_model_name(c); /* Default name */ - -- detect_null_seg_behavior(c); -- - /* - * ESPFIX is a strange bug. All real CPUs have it. Paravirt - * systems that run Linux at CPL > 0 may or may not have the -diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h -index 95521302630d4..ee6f23f7587d4 100644 ---- a/arch/x86/kernel/cpu/cpu.h -+++ b/arch/x86/kernel/cpu/cpu.h -@@ -75,6 +75,7 @@ extern int detect_extended_topology_early(struct cpuinfo_x86 *c); - extern int detect_extended_topology(struct cpuinfo_x86 *c); - extern int detect_ht_early(struct cpuinfo_x86 *c); - extern void detect_ht(struct cpuinfo_x86 *c); -+extern void check_null_seg_clears_base(struct cpuinfo_x86 *c); - - unsigned int aperfmperf_get_khz(int cpu); - -diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c -index 6d50136f7ab98..3fcdda4c1e114 100644 ---- a/arch/x86/kernel/cpu/hygon.c -+++ b/arch/x86/kernel/cpu/hygon.c -@@ -335,6 +335,8 @@ static void init_hygon(struct cpuinfo_x86 *c) - /* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */ - if (!cpu_has(c, X86_FEATURE_XENPV)) - set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); -+ -+ check_null_seg_clears_base(c); - } - - static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c) -diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c -index acfd5d9f93c68..bb9a46a804bf2 100644 ---- a/arch/x86/kernel/cpu/mce/intel.c -+++ b/arch/x86/kernel/cpu/mce/intel.c -@@ -547,12 +547,13 @@ bool intel_filter_mce(struct mce *m) - { - struct cpuinfo_x86 *c = &boot_cpu_data; - -- /* MCE errata HSD131, HSM142, HSW131, BDM48, and HSM142 */ -+ /* MCE errata HSD131, HSM142, HSW131, BDM48, HSM142 and SKX37 */ - if ((c->x86 == 6) && - ((c->x86_model == INTEL_FAM6_HASWELL) || - (c->x86_model == INTEL_FAM6_HASWELL_L) || - (c->x86_model == INTEL_FAM6_BROADWELL) || -- (c->x86_model == INTEL_FAM6_HASWELL_G)) && -+ (c->x86_model == INTEL_FAM6_HASWELL_G) || -+ (c->x86_model == INTEL_FAM6_SKYLAKE_X)) && - (m->bank == 0) && - ((m->status & 0xa0000000ffffffff) == 0x80000000000f0005)) - return true; -diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c -index e095c28d27ae8..ef6316fef99ff 100644 ---- a/arch/x86/kernel/cpu/mshyperv.c -+++ b/arch/x86/kernel/cpu/mshyperv.c -@@ -163,12 +163,22 @@ static uint32_t __init ms_hyperv_platform(void) - cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, - &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); - -- if (eax >= HYPERV_CPUID_MIN && -- eax <= HYPERV_CPUID_MAX && -- !memcmp("Microsoft Hv", hyp_signature, 12)) -- return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS; -+ if (eax < HYPERV_CPUID_MIN || eax > HYPERV_CPUID_MAX || -+ memcmp("Microsoft Hv", hyp_signature, 12)) -+ return 0; - -- return 0; -+ /* HYPERCALL and VP_INDEX MSRs are mandatory for all features. */ -+ eax = cpuid_eax(HYPERV_CPUID_FEATURES); -+ if (!(eax & HV_MSR_HYPERCALL_AVAILABLE)) { -+ pr_warn("x86/hyperv: HYPERCALL MSR not available.\n"); -+ return 0; -+ } -+ if (!(eax & HV_MSR_VP_INDEX_AVAILABLE)) { -+ pr_warn("x86/hyperv: VP_INDEX MSR not available.\n"); -+ return 0; -+ } -+ -+ return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS; - } - - static unsigned char hv_get_nmi_reason(void) -diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c -index 63d3de02bbccb..8471a8b9b48e8 100644 ---- a/arch/x86/kernel/cpu/sgx/main.c -+++ b/arch/x86/kernel/cpu/sgx/main.c -@@ -28,8 +28,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ksgxd_waitq); - static LIST_HEAD(sgx_active_page_list); - static DEFINE_SPINLOCK(sgx_reclaimer_lock); - --/* The free page list lock protected variables prepend the lock. */ --static unsigned long sgx_nr_free_pages; -+static atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0); - - /* Nodes with one or more EPC sections. */ - static nodemask_t sgx_numa_mask; -@@ -403,14 +402,15 @@ skip: - - spin_lock(&node->lock); - list_add_tail(&epc_page->list, &node->free_page_list); -- sgx_nr_free_pages++; - spin_unlock(&node->lock); -+ atomic_long_inc(&sgx_nr_free_pages); - } - } - - static bool sgx_should_reclaim(unsigned long watermark) - { -- return sgx_nr_free_pages < watermark && !list_empty(&sgx_active_page_list); -+ return atomic_long_read(&sgx_nr_free_pages) < watermark && -+ !list_empty(&sgx_active_page_list); - } - - static int ksgxd(void *p) -@@ -471,9 +471,9 @@ static struct sgx_epc_page *__sgx_alloc_epc_page_from_node(int nid) - - page = list_first_entry(&node->free_page_list, struct sgx_epc_page, list); - list_del_init(&page->list); -- sgx_nr_free_pages--; - - spin_unlock(&node->lock); -+ atomic_long_dec(&sgx_nr_free_pages); - - return page; - } -@@ -625,9 +625,9 @@ void sgx_free_epc_page(struct sgx_epc_page *page) - spin_lock(&node->lock); - - list_add_tail(&page->list, &node->free_page_list); -- sgx_nr_free_pages++; - - spin_unlock(&node->lock); -+ atomic_long_inc(&sgx_nr_free_pages); - } - - static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, -diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c -index 5601b95944fae..6c5defd6569a3 100644 ---- a/arch/x86/kernel/dumpstack_64.c -+++ b/arch/x86/kernel/dumpstack_64.c -@@ -32,9 +32,15 @@ const char *stack_type_name(enum stack_type type) - { - BUILD_BUG_ON(N_EXCEPTION_STACKS != 6); - -+ if (type == STACK_TYPE_TASK) -+ return "TASK"; -+ - if (type == STACK_TYPE_IRQ) - return "IRQ"; - -+ if (type == STACK_TYPE_SOFTIRQ) -+ return "SOFTIRQ"; -+ - if (type == STACK_TYPE_ENTRY) { - /* - * On 64-bit, we have a generic entry stack that we -diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c -index e28f6a5d14f1b..766ffe3ba3137 100644 ---- a/arch/x86/kernel/irq.c -+++ b/arch/x86/kernel/irq.c -@@ -291,8 +291,10 @@ void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)) - { - if (handler) - kvm_posted_intr_wakeup_handler = handler; -- else -+ else { - kvm_posted_intr_wakeup_handler = dummy_handler; -+ synchronize_rcu(); -+ } - } - EXPORT_SYMBOL_GPL(kvm_set_posted_intr_wakeup_handler); - -diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c -index 1d9463e3096b6..f2f733bcb2b95 100644 ---- a/arch/x86/kernel/process.c -+++ b/arch/x86/kernel/process.c -@@ -132,6 +132,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, - frame->ret_addr = (unsigned long) ret_from_fork; - p->thread.sp = (unsigned long) fork_frame; - p->thread.io_bitmap = NULL; -+ p->thread.iopl_warn = 0; - memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); - - #ifdef CONFIG_X86_64 -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index 40ed44ead0631..d71267081153f 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -742,6 +742,28 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) - return 0; - } - -+static char *prepare_command_line(void) -+{ -+#ifdef CONFIG_CMDLINE_BOOL -+#ifdef CONFIG_CMDLINE_OVERRIDE -+ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); -+#else -+ if (builtin_cmdline[0]) { -+ /* append boot loader cmdline to builtin */ -+ strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); -+ strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); -+ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); -+ } -+#endif -+#endif -+ -+ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); -+ -+ parse_early_param(); -+ -+ return command_line; -+} -+ - /* - * Determine if we were loaded by an EFI loader. If so, then we have also been - * passed the efi memmap, systab, etc., so we should use these data structures -@@ -830,6 +852,23 @@ void __init setup_arch(char **cmdline_p) - - x86_init.oem.arch_setup(); - -+ /* -+ * x86_configure_nx() is called before parse_early_param() (called by -+ * prepare_command_line()) to detect whether hardware doesn't support -+ * NX (so that the early EHCI debug console setup can safely call -+ * set_fixmap()). It may then be called again from within noexec_setup() -+ * during parsing early parameters to honor the respective command line -+ * option. -+ */ -+ x86_configure_nx(); -+ -+ /* -+ * This parses early params and it needs to run before -+ * early_reserve_memory() because latter relies on such settings -+ * supplied as early params. -+ */ -+ *cmdline_p = prepare_command_line(); -+ - /* - * Do some memory reservations *before* memory is added to memblock, so - * memblock allocations won't overwrite it. -@@ -863,33 +902,6 @@ void __init setup_arch(char **cmdline_p) - bss_resource.start = __pa_symbol(__bss_start); - bss_resource.end = __pa_symbol(__bss_stop)-1; - --#ifdef CONFIG_CMDLINE_BOOL --#ifdef CONFIG_CMDLINE_OVERRIDE -- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); --#else -- if (builtin_cmdline[0]) { -- /* append boot loader cmdline to builtin */ -- strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); -- strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); -- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); -- } --#endif --#endif -- -- strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); -- *cmdline_p = command_line; -- -- /* -- * x86_configure_nx() is called before parse_early_param() to detect -- * whether hardware doesn't support NX (so that the early EHCI debug -- * console setup can safely call set_fixmap()). It may then be called -- * again from within noexec_setup() during parsing early parameters -- * to honor the respective command line option. -- */ -- x86_configure_nx(); -- -- parse_early_param(); -- - #ifdef CONFIG_MEMORY_HOTPLUG - /* - * Memory used by the kernel cannot be hot-removed because Linux -diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c -index a6895e440bc35..a0064cf77e562 100644 ---- a/arch/x86/kernel/sev.c -+++ b/arch/x86/kernel/sev.c -@@ -46,16 +46,6 @@ static struct ghcb __initdata *boot_ghcb; - struct sev_es_runtime_data { - struct ghcb ghcb_page; - -- /* Physical storage for the per-CPU IST stack of the #VC handler */ -- char ist_stack[EXCEPTION_STKSZ] __aligned(PAGE_SIZE); -- -- /* -- * Physical storage for the per-CPU fall-back stack of the #VC handler. -- * The fall-back stack is used when it is not safe to switch back to the -- * interrupted stack in the #VC entry code. -- */ -- char fallback_stack[EXCEPTION_STKSZ] __aligned(PAGE_SIZE); -- - /* - * Reserve one page per CPU as backup storage for the unencrypted GHCB. - * It is needed when an NMI happens while the #VC handler uses the real -@@ -99,27 +89,6 @@ DEFINE_STATIC_KEY_FALSE(sev_es_enable_key); - /* Needed in vc_early_forward_exception */ - void do_early_exception(struct pt_regs *regs, int trapnr); - --static void __init setup_vc_stacks(int cpu) --{ -- struct sev_es_runtime_data *data; -- struct cpu_entry_area *cea; -- unsigned long vaddr; -- phys_addr_t pa; -- -- data = per_cpu(runtime_data, cpu); -- cea = get_cpu_entry_area(cpu); -- -- /* Map #VC IST stack */ -- vaddr = CEA_ESTACK_BOT(&cea->estacks, VC); -- pa = __pa(data->ist_stack); -- cea_set_pte((void *)vaddr, pa, PAGE_KERNEL); -- -- /* Map VC fall-back stack */ -- vaddr = CEA_ESTACK_BOT(&cea->estacks, VC2); -- pa = __pa(data->fallback_stack); -- cea_set_pte((void *)vaddr, pa, PAGE_KERNEL); --} -- - static __always_inline bool on_vc_stack(struct pt_regs *regs) - { - unsigned long sp = regs->sp; -@@ -325,11 +294,6 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt, - char *dst, char *buf, size_t size) - { - unsigned long error_code = X86_PF_PROT | X86_PF_WRITE; -- char __user *target = (char __user *)dst; -- u64 d8; -- u32 d4; -- u16 d2; -- u8 d1; - - /* - * This function uses __put_user() independent of whether kernel or user -@@ -351,26 +315,42 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt, - * instructions here would cause infinite nesting. - */ - switch (size) { -- case 1: -+ case 1: { -+ u8 d1; -+ u8 __user *target = (u8 __user *)dst; -+ - memcpy(&d1, buf, 1); - if (__put_user(d1, target)) - goto fault; - break; -- case 2: -+ } -+ case 2: { -+ u16 d2; -+ u16 __user *target = (u16 __user *)dst; -+ - memcpy(&d2, buf, 2); - if (__put_user(d2, target)) - goto fault; - break; -- case 4: -+ } -+ case 4: { -+ u32 d4; -+ u32 __user *target = (u32 __user *)dst; -+ - memcpy(&d4, buf, 4); - if (__put_user(d4, target)) - goto fault; - break; -- case 8: -+ } -+ case 8: { -+ u64 d8; -+ u64 __user *target = (u64 __user *)dst; -+ - memcpy(&d8, buf, 8); - if (__put_user(d8, target)) - goto fault; - break; -+ } - default: - WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); - return ES_UNSUPPORTED; -@@ -393,11 +373,6 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, - char *src, char *buf, size_t size) - { - unsigned long error_code = X86_PF_PROT; -- char __user *s = (char __user *)src; -- u64 d8; -- u32 d4; -- u16 d2; -- u8 d1; - - /* - * This function uses __get_user() independent of whether kernel or user -@@ -419,26 +394,41 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, - * instructions here would cause infinite nesting. - */ - switch (size) { -- case 1: -+ case 1: { -+ u8 d1; -+ u8 __user *s = (u8 __user *)src; -+ - if (__get_user(d1, s)) - goto fault; - memcpy(buf, &d1, 1); - break; -- case 2: -+ } -+ case 2: { -+ u16 d2; -+ u16 __user *s = (u16 __user *)src; -+ - if (__get_user(d2, s)) - goto fault; - memcpy(buf, &d2, 2); - break; -- case 4: -+ } -+ case 4: { -+ u32 d4; -+ u32 __user *s = (u32 __user *)src; -+ - if (__get_user(d4, s)) - goto fault; - memcpy(buf, &d4, 4); - break; -- case 8: -+ } -+ case 8: { -+ u64 d8; -+ u64 __user *s = (u64 __user *)src; - if (__get_user(d8, s)) - goto fault; - memcpy(buf, &d8, 8); - break; -+ } - default: - WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); - return ES_UNSUPPORTED; -@@ -787,7 +777,6 @@ void __init sev_es_init_vc_handling(void) - for_each_possible_cpu(cpu) { - alloc_runtime_data(cpu); - init_ghcb(cpu); -- setup_vc_stacks(cpu); - } - - sev_es_setup_play_dead(); -diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c -index a58800973aed3..5b1984d468227 100644 ---- a/arch/x86/kernel/traps.c -+++ b/arch/x86/kernel/traps.c -@@ -313,17 +313,19 @@ out: - } - - #ifdef CONFIG_VMAP_STACK --__visible void __noreturn handle_stack_overflow(const char *message, -- struct pt_regs *regs, -- unsigned long fault_address) -+__visible void __noreturn handle_stack_overflow(struct pt_regs *regs, -+ unsigned long fault_address, -+ struct stack_info *info) - { -- printk(KERN_EMERG "BUG: stack guard page was hit at %p (stack is %p..%p)\n", -- (void *)fault_address, current->stack, -- (char *)current->stack + THREAD_SIZE - 1); -- die(message, regs, 0); -+ const char *name = stack_type_name(info->type); -+ -+ printk(KERN_EMERG "BUG: %s stack guard page was hit at %p (stack is %p..%p)\n", -+ name, (void *)fault_address, info->begin, info->end); -+ -+ die("stack guard page", regs, 0); - - /* Be absolutely certain we don't return. */ -- panic("%s", message); -+ panic("%s stack guard hit", name); - } - #endif - -@@ -353,6 +355,7 @@ DEFINE_IDTENTRY_DF(exc_double_fault) - - #ifdef CONFIG_VMAP_STACK - unsigned long address = read_cr2(); -+ struct stack_info info; - #endif - - #ifdef CONFIG_X86_ESPFIX64 -@@ -455,10 +458,8 @@ DEFINE_IDTENTRY_DF(exc_double_fault) - * stack even if the actual trigger for the double fault was - * something else. - */ -- if ((unsigned long)task_stack_page(tsk) - 1 - address < PAGE_SIZE) { -- handle_stack_overflow("kernel stack overflow (double-fault)", -- regs, address); -- } -+ if (get_stack_guard_info((void *)address, &info)) -+ handle_stack_overflow(regs, address, &info); - #endif - - pr_emerg("PANIC: double fault, error_code: 0x%lx\n", error_code); -@@ -528,6 +529,36 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs, - - #define GPFSTR "general protection fault" - -+static bool fixup_iopl_exception(struct pt_regs *regs) -+{ -+ struct thread_struct *t = ¤t->thread; -+ unsigned char byte; -+ unsigned long ip; -+ -+ if (!IS_ENABLED(CONFIG_X86_IOPL_IOPERM) || t->iopl_emul != 3) -+ return false; -+ -+ if (insn_get_effective_ip(regs, &ip)) -+ return false; -+ -+ if (get_user(byte, (const char __user *)ip)) -+ return false; -+ -+ if (byte != 0xfa && byte != 0xfb) -+ return false; -+ -+ if (!t->iopl_warn && printk_ratelimit()) { -+ pr_err("%s[%d] attempts to use CLI/STI, pretending it's a NOP, ip:%lx", -+ current->comm, task_pid_nr(current), ip); -+ print_vma_addr(KERN_CONT " in ", ip); -+ pr_cont("\n"); -+ t->iopl_warn = 1; -+ } -+ -+ regs->ip += 1; -+ return true; -+} -+ - DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) - { - char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR; -@@ -553,6 +584,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) - tsk = current; - - if (user_mode(regs)) { -+ if (fixup_iopl_exception(regs)) -+ goto exit; -+ - tsk->thread.error_code = error_code; - tsk->thread.trap_nr = X86_TRAP_GP; - -@@ -709,7 +743,7 @@ asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *r - stack = (unsigned long *)sp; - - if (!get_stack_info_noinstr(stack, current, &info) || info.type == STACK_TYPE_ENTRY || -- info.type >= STACK_TYPE_EXCEPTION_LAST) -+ info.type > STACK_TYPE_EXCEPTION_LAST) - sp = __this_cpu_ist_top_va(VC2); - - sync: -diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c -index 2e076a459a0c0..a698196377be9 100644 ---- a/arch/x86/kernel/tsc.c -+++ b/arch/x86/kernel/tsc.c -@@ -1180,6 +1180,12 @@ void mark_tsc_unstable(char *reason) - - EXPORT_SYMBOL_GPL(mark_tsc_unstable); - -+static void __init tsc_disable_clocksource_watchdog(void) -+{ -+ clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; -+ clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; -+} -+ - static void __init check_system_tsc_reliable(void) - { - #if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC) -@@ -1196,6 +1202,23 @@ static void __init check_system_tsc_reliable(void) - #endif - if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) - tsc_clocksource_reliable = 1; -+ -+ /* -+ * Disable the clocksource watchdog when the system has: -+ * - TSC running at constant frequency -+ * - TSC which does not stop in C-States -+ * - the TSC_ADJUST register which allows to detect even minimal -+ * modifications -+ * - not more than two sockets. As the number of sockets cannot be -+ * evaluated at the early boot stage where this has to be -+ * invoked, check the number of online memory nodes as a -+ * fallback solution which is an reasonable estimate. -+ */ -+ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && -+ boot_cpu_has(X86_FEATURE_NONSTOP_TSC) && -+ boot_cpu_has(X86_FEATURE_TSC_ADJUST) && -+ nr_online_nodes <= 2) -+ tsc_disable_clocksource_watchdog(); - } - - /* -@@ -1387,9 +1410,6 @@ static int __init init_tsc_clocksource(void) - if (tsc_unstable) - goto unreg; - -- if (tsc_clocksource_reliable || no_tsc_watchdog) -- clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; -- - if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) - clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; - -@@ -1527,7 +1547,7 @@ void __init tsc_init(void) - } - - if (tsc_clocksource_reliable || no_tsc_watchdog) -- clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; -+ tsc_disable_clocksource_watchdog(); - - clocksource_register_khz(&clocksource_tsc_early, tsc_khz); - detect_art(); -diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c -index 50a4515fe0ad1..9452dc9664b51 100644 ---- a/arch/x86/kernel/tsc_sync.c -+++ b/arch/x86/kernel/tsc_sync.c -@@ -30,6 +30,7 @@ struct tsc_adjust { - }; - - static DEFINE_PER_CPU(struct tsc_adjust, tsc_adjust); -+static struct timer_list tsc_sync_check_timer; - - /* - * TSC's on different sockets may be reset asynchronously. -@@ -77,6 +78,46 @@ void tsc_verify_tsc_adjust(bool resume) - } - } - -+/* -+ * Normally the tsc_sync will be checked every time system enters idle -+ * state, but there is still caveat that a system won't enter idle, -+ * either because it's too busy or configured purposely to not enter -+ * idle. -+ * -+ * So setup a periodic timer (every 10 minutes) to make sure the check -+ * is always on. -+ */ -+ -+#define SYNC_CHECK_INTERVAL (HZ * 600) -+ -+static void tsc_sync_check_timer_fn(struct timer_list *unused) -+{ -+ int next_cpu; -+ -+ tsc_verify_tsc_adjust(false); -+ -+ /* Run the check for all onlined CPUs in turn */ -+ next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask); -+ if (next_cpu >= nr_cpu_ids) -+ next_cpu = cpumask_first(cpu_online_mask); -+ -+ tsc_sync_check_timer.expires += SYNC_CHECK_INTERVAL; -+ add_timer_on(&tsc_sync_check_timer, next_cpu); -+} -+ -+static int __init start_sync_check_timer(void) -+{ -+ if (!cpu_feature_enabled(X86_FEATURE_TSC_ADJUST) || tsc_clocksource_reliable) -+ return 0; -+ -+ timer_setup(&tsc_sync_check_timer, tsc_sync_check_timer_fn, 0); -+ tsc_sync_check_timer.expires = jiffies + SYNC_CHECK_INTERVAL; -+ add_timer(&tsc_sync_check_timer); -+ -+ return 0; -+} -+late_initcall(start_sync_check_timer); -+ - static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval, - unsigned int cpu, bool bootcpu) - { -diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c -index e5a7a10a0164d..17d58740891e2 100644 ---- a/arch/x86/kernel/vm86_32.c -+++ b/arch/x86/kernel/vm86_32.c -@@ -142,6 +142,7 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval) - - user_access_end(); - -+exit_vm86: - preempt_disable(); - tsk->thread.sp0 = vm86->saved_sp0; - tsk->thread.sysenter_cs = __KERNEL_CS; -@@ -161,7 +162,8 @@ Efault_end: - user_access_end(); - Efault: - pr_alert("could not access userspace vm86 info\n"); -- do_exit(SIGSEGV); -+ force_exit_sig(SIGSEGV); -+ goto exit_vm86; - } - - static int do_vm86_irq_handling(int subfunction, int irqnumber); -diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c -index 751aa85a30012..f666fd79d8ad6 100644 ---- a/arch/x86/kvm/cpuid.c -+++ b/arch/x86/kvm/cpuid.c -@@ -232,6 +232,25 @@ u64 kvm_vcpu_reserved_gpa_bits_raw(struct kvm_vcpu *vcpu) - return rsvd_bits(cpuid_maxphyaddr(vcpu), 63); - } - -+static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2, -+ int nent) -+{ -+ int r; -+ -+ r = kvm_check_cpuid(e2, nent); -+ if (r) -+ return r; -+ -+ kvfree(vcpu->arch.cpuid_entries); -+ vcpu->arch.cpuid_entries = e2; -+ vcpu->arch.cpuid_nent = nent; -+ -+ kvm_update_cpuid_runtime(vcpu); -+ kvm_vcpu_after_set_cpuid(vcpu); -+ -+ return 0; -+} -+ - /* when an old userspace process fills a new kernel module */ - int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, - struct kvm_cpuid *cpuid, -@@ -268,18 +287,9 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, - e2[i].padding[2] = 0; - } - -- r = kvm_check_cpuid(e2, cpuid->nent); -- if (r) { -+ r = kvm_set_cpuid(vcpu, e2, cpuid->nent); -+ if (r) - kvfree(e2); -- goto out_free_cpuid; -- } -- -- kvfree(vcpu->arch.cpuid_entries); -- vcpu->arch.cpuid_entries = e2; -- vcpu->arch.cpuid_nent = cpuid->nent; -- -- kvm_update_cpuid_runtime(vcpu); -- kvm_vcpu_after_set_cpuid(vcpu); - - out_free_cpuid: - kvfree(e); -@@ -303,20 +313,11 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, - return PTR_ERR(e2); - } - -- r = kvm_check_cpuid(e2, cpuid->nent); -- if (r) { -+ r = kvm_set_cpuid(vcpu, e2, cpuid->nent); -+ if (r) - kvfree(e2); -- return r; -- } - -- kvfree(vcpu->arch.cpuid_entries); -- vcpu->arch.cpuid_entries = e2; -- vcpu->arch.cpuid_nent = cpuid->nent; -- -- kvm_update_cpuid_runtime(vcpu); -- kvm_vcpu_after_set_cpuid(vcpu); -- -- return 0; -+ return r; - } - - int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, -diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c -index d5124b520f761..2092834efba11 100644 ---- a/arch/x86/kvm/hyperv.c -+++ b/arch/x86/kvm/hyperv.c -@@ -1922,11 +1922,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool - - all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL; - -+ if (all_cpus) -+ goto check_and_send_ipi; -+ - if (!sparse_banks_len) - goto ret_success; - -- if (!all_cpus && -- kvm_read_guest(kvm, -+ if (kvm_read_guest(kvm, - hc->ingpa + offsetof(struct hv_send_ipi_ex, - vp_set.bank_contents), - sparse_banks, -@@ -1934,6 +1936,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool - return HV_STATUS_INVALID_HYPERCALL_INPUT; - } - -+check_and_send_ipi: - if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) - return HV_STATUS_INVALID_HYPERCALL_INPUT; - -@@ -2022,7 +2025,7 @@ static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result) - { - bool longmode; - -- longmode = is_64_bit_mode(vcpu); -+ longmode = is_64_bit_hypercall(vcpu); - if (longmode) - kvm_rax_write(vcpu, result); - else { -@@ -2171,7 +2174,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) - } - - #ifdef CONFIG_X86_64 -- if (is_64_bit_mode(vcpu)) { -+ if (is_64_bit_hypercall(vcpu)) { - hc.param = kvm_rcx_read(vcpu); - hc.ingpa = kvm_rdx_read(vcpu); - hc.outgpa = kvm_r8_read(vcpu); -diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c -index 8c065da73f8e5..4e0f52660842b 100644 ---- a/arch/x86/kvm/ioapic.c -+++ b/arch/x86/kvm/ioapic.c -@@ -96,7 +96,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, - static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) - { - ioapic->rtc_status.pending_eoi = 0; -- bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID + 1); -+ bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID); - } - - static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic); -diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h -index bbd4a5d18b5dc..f1b2b2a6ff4db 100644 ---- a/arch/x86/kvm/ioapic.h -+++ b/arch/x86/kvm/ioapic.h -@@ -39,13 +39,13 @@ struct kvm_vcpu; - - struct dest_map { - /* vcpu bitmap where IRQ has been sent */ -- DECLARE_BITMAP(map, KVM_MAX_VCPU_ID + 1); -+ DECLARE_BITMAP(map, KVM_MAX_VCPU_ID); - - /* - * Vector sent to a given vcpu, only valid when - * the vcpu's bit in map is set - */ -- u8 vectors[KVM_MAX_VCPU_ID + 1]; -+ u8 vectors[KVM_MAX_VCPU_ID]; - }; - - -@@ -81,7 +81,6 @@ struct kvm_ioapic { - unsigned long irq_states[IOAPIC_NUM_PINS]; - struct kvm_io_device dev; - struct kvm *kvm; -- void (*ack_notifier)(void *opaque, int irq); - spinlock_t lock; - struct rtc_status rtc_status; - struct delayed_work eoi_inject; -diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h -index 650642b18d151..c2d7cfe82d004 100644 ---- a/arch/x86/kvm/irq.h -+++ b/arch/x86/kvm/irq.h -@@ -56,7 +56,6 @@ struct kvm_pic { - struct kvm_io_device dev_master; - struct kvm_io_device dev_slave; - struct kvm_io_device dev_elcr; -- void (*ack_notifier)(void *opaque, int irq); - unsigned long irq_states[PIC_NUM_PINS]; - }; - -diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c -index d6ac32f3f650c..95f5527646e4a 100644 ---- a/arch/x86/kvm/lapic.c -+++ b/arch/x86/kvm/lapic.c -@@ -707,7 +707,7 @@ static void pv_eoi_clr_pending(struct kvm_vcpu *vcpu) - static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr) - { - int highest_irr; -- if (apic->vcpu->arch.apicv_active) -+ if (kvm_x86_ops.sync_pir_to_irr) - highest_irr = static_call(kvm_x86_sync_pir_to_irr)(apic->vcpu); - else - highest_irr = apic_find_highest_irr(apic); -diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index 0cc58901bf7a7..0a88cb4f731f4 100644 ---- a/arch/x86/kvm/mmu/mmu.c -+++ b/arch/x86/kvm/mmu/mmu.c -@@ -1592,7 +1592,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) - flush = kvm_handle_gfn_range(kvm, range, kvm_unmap_rmapp); - - if (is_tdp_mmu_enabled(kvm)) -- flush |= kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); -+ flush = kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); - - return flush; - } -@@ -2188,10 +2188,10 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato - iterator->shadow_addr = root; - iterator->level = vcpu->arch.mmu->shadow_root_level; - -- if (iterator->level == PT64_ROOT_4LEVEL && -+ if (iterator->level >= PT64_ROOT_4LEVEL && - vcpu->arch.mmu->root_level < PT64_ROOT_4LEVEL && - !vcpu->arch.mmu->direct_map) -- --iterator->level; -+ iterator->level = PT32E_ROOT_LEVEL; - - if (iterator->level == PT32E_ROOT_LEVEL) { - /* -@@ -4679,6 +4679,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu, - /* PKEY and LA57 are active iff long mode is active. */ - ext.cr4_pke = ____is_efer_lma(regs) && ____is_cr4_pke(regs); - ext.cr4_la57 = ____is_efer_lma(regs) && ____is_cr4_la57(regs); -+ ext.efer_lma = ____is_efer_lma(regs); - } - - ext.valid = 1; -@@ -4851,7 +4852,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0, - struct kvm_mmu *context = &vcpu->arch.guest_mmu; - struct kvm_mmu_role_regs regs = { - .cr0 = cr0, -- .cr4 = cr4, -+ .cr4 = cr4 & ~X86_CR4_PKE, - .efer = efer, - }; - union kvm_mmu_role new_role; -@@ -4915,7 +4916,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, - context->direct_map = false; - - update_permission_bitmask(context, true); -- update_pkru_bitmask(context); -+ context->pkru_mask = 0; - reset_rsvds_bits_mask_ept(vcpu, context, execonly); - reset_ept_shadow_zero_bits_mask(vcpu, context, execonly); - } -@@ -5368,7 +5369,7 @@ void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, - - void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva) - { -- kvm_mmu_invalidate_gva(vcpu, vcpu->arch.mmu, gva, INVALID_PAGE); -+ kvm_mmu_invalidate_gva(vcpu, vcpu->arch.walk_mmu, gva, INVALID_PAGE); - ++vcpu->stat.invlpg; - } - EXPORT_SYMBOL_GPL(kvm_mmu_invlpg); -@@ -5473,8 +5474,8 @@ slot_handle_level(struct kvm *kvm, const struct kvm_memory_slot *memslot, - } - - static __always_inline bool --slot_handle_leaf(struct kvm *kvm, const struct kvm_memory_slot *memslot, -- slot_level_handler fn, bool flush_on_yield) -+slot_handle_level_4k(struct kvm *kvm, const struct kvm_memory_slot *memslot, -+ slot_level_handler fn, bool flush_on_yield) - { - return slot_handle_level(kvm, memslot, fn, PG_LEVEL_4K, - PG_LEVEL_4K, flush_on_yield); -@@ -5758,13 +5759,11 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end) - for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) - flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, gfn_start, - gfn_end, flush); -- if (flush) -- kvm_flush_remote_tlbs_with_address(kvm, gfn_start, -- gfn_end - gfn_start); - } - - if (flush) -- kvm_flush_remote_tlbs_with_address(kvm, gfn_start, gfn_end); -+ kvm_flush_remote_tlbs_with_address(kvm, gfn_start, -+ gfn_end - gfn_start); - - kvm_dec_notifier_count(kvm, gfn_start, gfn_end); - -@@ -5856,21 +5855,21 @@ restart: - void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm, - const struct kvm_memory_slot *slot) - { -- bool flush = false; -- - if (kvm_memslots_have_rmaps(kvm)) { - write_lock(&kvm->mmu_lock); -- flush = slot_handle_leaf(kvm, slot, kvm_mmu_zap_collapsible_spte, true); -- if (flush) -+ /* -+ * Zap only 4k SPTEs since the legacy MMU only supports dirty -+ * logging at a 4k granularity and never creates collapsible -+ * 2m SPTEs during dirty logging. -+ */ -+ if (slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true)) - kvm_arch_flush_remote_tlbs_memslot(kvm, slot); - write_unlock(&kvm->mmu_lock); - } - - if (is_tdp_mmu_enabled(kvm)) { - read_lock(&kvm->mmu_lock); -- flush = kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot, flush); -- if (flush) -- kvm_arch_flush_remote_tlbs_memslot(kvm, slot); -+ kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot); - read_unlock(&kvm->mmu_lock); - } - } -@@ -5897,8 +5896,11 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm, - - if (kvm_memslots_have_rmaps(kvm)) { - write_lock(&kvm->mmu_lock); -- flush = slot_handle_leaf(kvm, memslot, __rmap_clear_dirty, -- false); -+ /* -+ * Clear dirty bits only on 4k SPTEs since the legacy MMU only -+ * support dirty logging at a 4k granularity. -+ */ -+ flush = slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false); - write_unlock(&kvm->mmu_lock); - } - -diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h -index eb7b227fc6cfe..31d6456d8ac33 100644 ---- a/arch/x86/kvm/mmu/spte.h -+++ b/arch/x86/kvm/mmu/spte.h -@@ -310,12 +310,7 @@ static inline bool __is_bad_mt_xwr(struct rsvd_bits_validate *rsvd_check, - static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check, - u64 spte, int level) - { -- /* -- * Use a bitwise-OR instead of a logical-OR to aggregate the reserved -- * bits and EPT's invalid memtype/XWR checks to avoid an extra Jcc -- * (this is extremely unlikely to be short-circuited as true). -- */ -- return __is_bad_mt_xwr(rsvd_check, spte) | -+ return __is_bad_mt_xwr(rsvd_check, spte) || - __is_rsvd_bits_set(rsvd_check, spte, level); - } - -diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c -index 64ccfc1fa5535..0e4227b59d7bb 100644 ---- a/arch/x86/kvm/mmu/tdp_mmu.c -+++ b/arch/x86/kvm/mmu/tdp_mmu.c -@@ -316,9 +316,6 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, - struct kvm_mmu_page *sp = sptep_to_sp(rcu_dereference(pt)); - int level = sp->role.level; - gfn_t base_gfn = sp->gfn; -- u64 old_child_spte; -- u64 *sptep; -- gfn_t gfn; - int i; - - trace_kvm_mmu_prepare_zap_page(sp); -@@ -326,8 +323,9 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, - tdp_mmu_unlink_page(kvm, sp, shared); - - for (i = 0; i < PT64_ENT_PER_PAGE; i++) { -- sptep = rcu_dereference(pt) + i; -- gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); -+ u64 *sptep = rcu_dereference(pt) + i; -+ gfn_t gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); -+ u64 old_child_spte; - - if (shared) { - /* -@@ -373,7 +371,7 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, - shared); - } - -- kvm_flush_remote_tlbs_with_address(kvm, gfn, -+ kvm_flush_remote_tlbs_with_address(kvm, base_gfn, - KVM_PAGES_PER_HPAGE(level + 1)); - - call_rcu(&sp->rcu_head, tdp_mmu_free_sp_rcu_callback); -@@ -1083,8 +1081,8 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range, - struct kvm_mmu_page *root; - - for_each_tdp_mmu_root(kvm, root, range->slot->as_id) -- flush |= zap_gfn_range(kvm, root, range->start, range->end, -- range->may_block, flush, false); -+ flush = zap_gfn_range(kvm, root, range->start, range->end, -+ range->may_block, flush, false); - - return flush; - } -@@ -1415,10 +1413,9 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, - * Clear leaf entries which could be replaced by large mappings, for - * GFNs within the slot. - */ --static bool zap_collapsible_spte_range(struct kvm *kvm, -+static void zap_collapsible_spte_range(struct kvm *kvm, - struct kvm_mmu_page *root, -- const struct kvm_memory_slot *slot, -- bool flush) -+ const struct kvm_memory_slot *slot) - { - gfn_t start = slot->base_gfn; - gfn_t end = start + slot->npages; -@@ -1429,10 +1426,8 @@ static bool zap_collapsible_spte_range(struct kvm *kvm, - - tdp_root_for_each_pte(iter, root, start, end) { - retry: -- if (tdp_mmu_iter_cond_resched(kvm, &iter, flush, true)) { -- flush = false; -+ if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true)) - continue; -- } - - if (!is_shadow_present_pte(iter.old_spte) || - !is_last_spte(iter.old_spte, iter.level)) -@@ -1444,6 +1439,7 @@ retry: - pfn, PG_LEVEL_NUM)) - continue; - -+ /* Note, a successful atomic zap also does a remote TLB flush. */ - if (!tdp_mmu_zap_spte_atomic(kvm, &iter)) { - /* - * The iter must explicitly re-read the SPTE because -@@ -1452,30 +1448,24 @@ retry: - iter.old_spte = READ_ONCE(*rcu_dereference(iter.sptep)); - goto retry; - } -- flush = true; - } - - rcu_read_unlock(); -- -- return flush; - } - - /* - * Clear non-leaf entries (and free associated page tables) which could - * be replaced by large mappings, for GFNs within the slot. - */ --bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, -- const struct kvm_memory_slot *slot, -- bool flush) -+void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, -+ const struct kvm_memory_slot *slot) - { - struct kvm_mmu_page *root; - - lockdep_assert_held_read(&kvm->mmu_lock); - - for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true) -- flush = zap_collapsible_spte_range(kvm, root, slot, flush); -- -- return flush; -+ zap_collapsible_spte_range(kvm, root, slot); - } - - /* -diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h -index 358f447d40120..ba3681cd38ab4 100644 ---- a/arch/x86/kvm/mmu/tdp_mmu.h -+++ b/arch/x86/kvm/mmu/tdp_mmu.h -@@ -66,9 +66,8 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, - struct kvm_memory_slot *slot, - gfn_t gfn, unsigned long mask, - bool wrprot); --bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, -- const struct kvm_memory_slot *slot, -- bool flush); -+void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, -+ const struct kvm_memory_slot *slot); - - bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm, - struct kvm_memory_slot *slot, gfn_t gfn, -diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c -index 8052d92069e01..2fb6a6f00290d 100644 ---- a/arch/x86/kvm/svm/avic.c -+++ b/arch/x86/kvm/svm/avic.c -@@ -988,16 +988,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu) - static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run) - { - struct vcpu_svm *svm = to_svm(vcpu); -+ int cpu = get_cpu(); - -+ WARN_ON(cpu != vcpu->cpu); - svm->avic_is_running = is_run; - -- if (!kvm_vcpu_apicv_active(vcpu)) -- return; -- -- if (is_run) -- avic_vcpu_load(vcpu, vcpu->cpu); -- else -- avic_vcpu_put(vcpu); -+ if (kvm_vcpu_apicv_active(vcpu)) { -+ if (is_run) -+ avic_vcpu_load(vcpu, cpu); -+ else -+ avic_vcpu_put(vcpu); -+ } -+ put_cpu(); - } - - void svm_vcpu_blocking(struct kvm_vcpu *vcpu) -diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c -index fdf587f19c5fb..e152241d1d709 100644 ---- a/arch/x86/kvm/svm/pmu.c -+++ b/arch/x86/kvm/svm/pmu.c -@@ -282,7 +282,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) - pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS; - - pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1; -- pmu->reserved_bits = 0xffffffff00200000ull; -+ pmu->reserved_bits = 0xfffffff000280000ull; - pmu->version = 1; - /* not applicable to AMD; but clean them to prevent any fall out */ - pmu->counter_bitmask[KVM_PMC_FIXED] = 0; -diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c -index 7e34d7163adab..134c4ea5e6ad8 100644 ---- a/arch/x86/kvm/svm/sev.c -+++ b/arch/x86/kvm/svm/sev.c -@@ -1787,7 +1787,12 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) - mutex_unlock(&source_kvm->lock); - mutex_lock(&kvm->lock); - -- if (sev_guest(kvm)) { -+ /* -+ * Disallow out-of-band SEV/SEV-ES init if the target is already an -+ * SEV guest, or if vCPUs have been created. KVM relies on vCPUs being -+ * created after SEV/SEV-ES initialization, e.g. to init intercepts. -+ */ -+ if (sev_guest(kvm) || kvm->created_vcpus) { - ret = -EINVAL; - goto e_mirror_unlock; - } -@@ -1800,6 +1805,7 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) - mirror_sev->fd = source_sev.fd; - mirror_sev->es_active = source_sev.es_active; - mirror_sev->handle = source_sev.handle; -+ INIT_LIST_HEAD(&mirror_sev->regions_list); - /* - * Do not copy ap_jump_table. Since the mirror does not share the same - * KVM contexts as the original, and they may have different -@@ -2311,7 +2317,7 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) - } - - #define GHCB_SCRATCH_AREA_LIMIT (16ULL * PAGE_SIZE) --static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) -+static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) - { - struct vmcb_control_area *control = &svm->vmcb->control; - struct ghcb *ghcb = svm->ghcb; -@@ -2322,14 +2328,14 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) - scratch_gpa_beg = ghcb_get_sw_scratch(ghcb); - if (!scratch_gpa_beg) { - pr_err("vmgexit: scratch gpa not provided\n"); -- return false; -+ return -EINVAL; - } - - scratch_gpa_end = scratch_gpa_beg + len; - if (scratch_gpa_end < scratch_gpa_beg) { - pr_err("vmgexit: scratch length (%#llx) not valid for scratch address (%#llx)\n", - len, scratch_gpa_beg); -- return false; -+ return -EINVAL; - } - - if ((scratch_gpa_beg & PAGE_MASK) == control->ghcb_gpa) { -@@ -2347,7 +2353,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) - scratch_gpa_end > ghcb_scratch_end) { - pr_err("vmgexit: scratch area is outside of GHCB shared buffer area (%#llx - %#llx)\n", - scratch_gpa_beg, scratch_gpa_end); -- return false; -+ return -EINVAL; - } - - scratch_va = (void *)svm->ghcb; -@@ -2360,18 +2366,18 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) - if (len > GHCB_SCRATCH_AREA_LIMIT) { - pr_err("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n", - len, GHCB_SCRATCH_AREA_LIMIT); -- return false; -+ return -EINVAL; - } - scratch_va = kzalloc(len, GFP_KERNEL_ACCOUNT); - if (!scratch_va) -- return false; -+ return -ENOMEM; - - if (kvm_read_guest(svm->vcpu.kvm, scratch_gpa_beg, scratch_va, len)) { - /* Unable to copy scratch area from guest */ - pr_err("vmgexit: kvm_read_guest for scratch area failed\n"); - - kfree(scratch_va); -- return false; -+ return -EFAULT; - } - - /* -@@ -2387,7 +2393,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) - svm->ghcb_sa = scratch_va; - svm->ghcb_sa_len = len; - -- return true; -+ return 0; - } - - static void set_ghcb_msr_bits(struct vcpu_svm *svm, u64 value, u64 mask, -@@ -2526,10 +2532,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) - ghcb_set_sw_exit_info_1(ghcb, 0); - ghcb_set_sw_exit_info_2(ghcb, 0); - -- ret = -EINVAL; - switch (exit_code) { - case SVM_VMGEXIT_MMIO_READ: -- if (!setup_vmgexit_scratch(svm, true, control->exit_info_2)) -+ ret = setup_vmgexit_scratch(svm, true, control->exit_info_2); -+ if (ret) - break; - - ret = kvm_sev_es_mmio_read(vcpu, -@@ -2538,7 +2544,8 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) - svm->ghcb_sa); - break; - case SVM_VMGEXIT_MMIO_WRITE: -- if (!setup_vmgexit_scratch(svm, false, control->exit_info_2)) -+ ret = setup_vmgexit_scratch(svm, false, control->exit_info_2); -+ if (ret) - break; - - ret = kvm_sev_es_mmio_write(vcpu, -@@ -2581,6 +2588,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) - vcpu_unimpl(vcpu, - "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n", - control->exit_info_1, control->exit_info_2); -+ ret = -EINVAL; - break; - default: - ret = svm_invoke_exit_handler(vcpu, exit_code); -@@ -2593,6 +2601,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) - { - int count; - int bytes; -+ int r; - - if (svm->vmcb->control.exit_info_2 > INT_MAX) - return -EINVAL; -@@ -2601,8 +2610,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) - if (unlikely(check_mul_overflow(count, size, &bytes))) - return -EINVAL; - -- if (!setup_vmgexit_scratch(svm, in, bytes)) -- return -EINVAL; -+ r = setup_vmgexit_scratch(svm, in, bytes); -+ if (r) -+ return r; - - return kvm_sev_es_string_io(&svm->vcpu, size, port, svm->ghcb_sa, count, in); - } -diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c -index 989685098b3ea..1fce044beebea 100644 ---- a/arch/x86/kvm/svm/svm.c -+++ b/arch/x86/kvm/svm/svm.c -@@ -4592,7 +4592,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { - .load_eoi_exitmap = svm_load_eoi_exitmap, - .hwapic_irr_update = svm_hwapic_irr_update, - .hwapic_isr_update = svm_hwapic_isr_update, -- .sync_pir_to_irr = kvm_lapic_find_highest_irr, - .apicv_post_state_restore = avic_post_state_restore, - - .set_tss_addr = svm_set_tss_addr, -diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c -index eedcebf580041..e97a11abc1d85 100644 ---- a/arch/x86/kvm/vmx/nested.c -+++ b/arch/x86/kvm/vmx/nested.c -@@ -523,29 +523,6 @@ static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu, - return 0; - } - --/* -- * Check if MSR is intercepted for L01 MSR bitmap. -- */ --static bool msr_write_intercepted_l01(struct kvm_vcpu *vcpu, u32 msr) --{ -- unsigned long *msr_bitmap; -- int f = sizeof(unsigned long); -- -- if (!cpu_has_vmx_msr_bitmap()) -- return true; -- -- msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap; -- -- if (msr <= 0x1fff) { -- return !!test_bit(msr, msr_bitmap + 0x800 / f); -- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { -- msr &= 0x1fff; -- return !!test_bit(msr, msr_bitmap + 0xc00 / f); -- } -- -- return true; --} -- - /* - * If a msr is allowed by L0, we should check whether it is allowed by L1. - * The corresponding bit will be cleared unless both of L0 and L1 allow it. -@@ -599,6 +576,34 @@ static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) - } - } - -+#define BUILD_NVMX_MSR_INTERCEPT_HELPER(rw) \ -+static inline \ -+void nested_vmx_set_msr_##rw##_intercept(struct vcpu_vmx *vmx, \ -+ unsigned long *msr_bitmap_l1, \ -+ unsigned long *msr_bitmap_l0, u32 msr) \ -+{ \ -+ if (vmx_test_msr_bitmap_##rw(vmx->vmcs01.msr_bitmap, msr) || \ -+ vmx_test_msr_bitmap_##rw(msr_bitmap_l1, msr)) \ -+ vmx_set_msr_bitmap_##rw(msr_bitmap_l0, msr); \ -+ else \ -+ vmx_clear_msr_bitmap_##rw(msr_bitmap_l0, msr); \ -+} -+BUILD_NVMX_MSR_INTERCEPT_HELPER(read) -+BUILD_NVMX_MSR_INTERCEPT_HELPER(write) -+ -+static inline void nested_vmx_set_intercept_for_msr(struct vcpu_vmx *vmx, -+ unsigned long *msr_bitmap_l1, -+ unsigned long *msr_bitmap_l0, -+ u32 msr, int types) -+{ -+ if (types & MSR_TYPE_R) -+ nested_vmx_set_msr_read_intercept(vmx, msr_bitmap_l1, -+ msr_bitmap_l0, msr); -+ if (types & MSR_TYPE_W) -+ nested_vmx_set_msr_write_intercept(vmx, msr_bitmap_l1, -+ msr_bitmap_l0, msr); -+} -+ - /* - * Merge L0's and L1's MSR bitmap, return false to indicate that - * we do not use the hardware. -@@ -606,10 +611,11 @@ static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) - static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12) - { -+ struct vcpu_vmx *vmx = to_vmx(vcpu); - int msr; - unsigned long *msr_bitmap_l1; -- unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap; -- struct kvm_host_map *map = &to_vmx(vcpu)->nested.msr_bitmap_map; -+ unsigned long *msr_bitmap_l0 = vmx->nested.vmcs02.msr_bitmap; -+ struct kvm_host_map *map = &vmx->nested.msr_bitmap_map; - - /* Nothing to do if the MSR bitmap is not in use. */ - if (!cpu_has_vmx_msr_bitmap() || -@@ -660,44 +666,27 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, - } - } - -- /* KVM unconditionally exposes the FS/GS base MSRs to L1. */ -+ /* -+ * Always check vmcs01's bitmap to honor userspace MSR filters and any -+ * other runtime changes to vmcs01's bitmap, e.g. dynamic pass-through. -+ */ - #ifdef CONFIG_X86_64 -- nested_vmx_disable_intercept_for_msr(msr_bitmap_l1, msr_bitmap_l0, -- MSR_FS_BASE, MSR_TYPE_RW); -+ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, -+ MSR_FS_BASE, MSR_TYPE_RW); - -- nested_vmx_disable_intercept_for_msr(msr_bitmap_l1, msr_bitmap_l0, -- MSR_GS_BASE, MSR_TYPE_RW); -+ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, -+ MSR_GS_BASE, MSR_TYPE_RW); - -- nested_vmx_disable_intercept_for_msr(msr_bitmap_l1, msr_bitmap_l0, -- MSR_KERNEL_GS_BASE, MSR_TYPE_RW); -+ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, -+ MSR_KERNEL_GS_BASE, MSR_TYPE_RW); - #endif -+ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, -+ MSR_IA32_SPEC_CTRL, MSR_TYPE_RW); - -- /* -- * Checking the L0->L1 bitmap is trying to verify two things: -- * -- * 1. L0 gave a permission to L1 to actually passthrough the MSR. This -- * ensures that we do not accidentally generate an L02 MSR bitmap -- * from the L12 MSR bitmap that is too permissive. -- * 2. That L1 or L2s have actually used the MSR. This avoids -- * unnecessarily merging of the bitmap if the MSR is unused. This -- * works properly because we only update the L01 MSR bitmap lazily. -- * So even if L0 should pass L1 these MSRs, the L01 bitmap is only -- * updated to reflect this when L1 (or its L2s) actually write to -- * the MSR. -- */ -- if (!msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL)) -- nested_vmx_disable_intercept_for_msr( -- msr_bitmap_l1, msr_bitmap_l0, -- MSR_IA32_SPEC_CTRL, -- MSR_TYPE_R | MSR_TYPE_W); -- -- if (!msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD)) -- nested_vmx_disable_intercept_for_msr( -- msr_bitmap_l1, msr_bitmap_l0, -- MSR_IA32_PRED_CMD, -- MSR_TYPE_W); -+ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, -+ MSR_IA32_PRED_CMD, MSR_TYPE_W); - -- kvm_vcpu_unmap(vcpu, &to_vmx(vcpu)->nested.msr_bitmap_map, false); -+ kvm_vcpu_unmap(vcpu, &vmx->nested.msr_bitmap_map, false); - - return true; - } -@@ -1191,29 +1180,26 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu, - WARN_ON(!enable_vpid); - - /* -- * If VPID is enabled and used by vmc12, but L2 does not have a unique -- * TLB tag (ASID), i.e. EPT is disabled and KVM was unable to allocate -- * a VPID for L2, flush the current context as the effective ASID is -- * common to both L1 and L2. -- * -- * Defer the flush so that it runs after vmcs02.EPTP has been set by -- * KVM_REQ_LOAD_MMU_PGD (if nested EPT is enabled) and to avoid -- * redundant flushes further down the nested pipeline. -- * -- * If a TLB flush isn't required due to any of the above, and vpid12 is -- * changing then the new "virtual" VPID (vpid12) will reuse the same -- * "real" VPID (vpid02), and so needs to be flushed. There's no direct -- * mapping between vpid02 and vpid12, vpid02 is per-vCPU and reused for -- * all nested vCPUs. Remember, a flush on VM-Enter does not invalidate -- * guest-physical mappings, so there is no need to sync the nEPT MMU. -+ * VPID is enabled and in use by vmcs12. If vpid12 is changing, then -+ * emulate a guest TLB flush as KVM does not track vpid12 history nor -+ * is the VPID incorporated into the MMU context. I.e. KVM must assume -+ * that the new vpid12 has never been used and thus represents a new -+ * guest ASID that cannot have entries in the TLB. - */ -- if (!nested_has_guest_tlb_tag(vcpu)) { -- kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); -- } else if (is_vmenter && -- vmcs12->virtual_processor_id != vmx->nested.last_vpid) { -+ if (is_vmenter && vmcs12->virtual_processor_id != vmx->nested.last_vpid) { - vmx->nested.last_vpid = vmcs12->virtual_processor_id; -- vpid_sync_context(nested_get_vpid02(vcpu)); -+ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); -+ return; - } -+ -+ /* -+ * If VPID is enabled, used by vmc12, and vpid12 is not changing but -+ * does not have a unique TLB tag (ASID), i.e. EPT is disabled and -+ * KVM was unable to allocate a VPID for L2, flush the current context -+ * as the effective ASID is common to both L1 and L2. -+ */ -+ if (!nested_has_guest_tlb_tag(vcpu)) -+ kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); - } - - static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask) -@@ -2623,8 +2609,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, - - if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && - WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, -- vmcs12->guest_ia32_perf_global_ctrl))) -+ vmcs12->guest_ia32_perf_global_ctrl))) { -+ *entry_failure_code = ENTRY_FAIL_DEFAULT; - return -EINVAL; -+ } - - kvm_rsp_write(vcpu, vmcs12->guest_rsp); - kvm_rip_write(vcpu, vmcs12->guest_rip); -@@ -2865,6 +2853,17 @@ static int nested_vmx_check_controls(struct kvm_vcpu *vcpu, - return 0; - } - -+static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu, -+ struct vmcs12 *vmcs12) -+{ -+#ifdef CONFIG_X86_64 -+ if (CC(!!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE) != -+ !!(vcpu->arch.efer & EFER_LMA))) -+ return -EINVAL; -+#endif -+ return 0; -+} -+ - static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu, - struct vmcs12 *vmcs12) - { -@@ -2889,18 +2888,16 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu, - return -EINVAL; - - #ifdef CONFIG_X86_64 -- ia32e = !!(vcpu->arch.efer & EFER_LMA); -+ ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE); - #else - ia32e = false; - #endif - - if (ia32e) { -- if (CC(!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)) || -- CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) -+ if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) - return -EINVAL; - } else { -- if (CC(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE) || -- CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) || -+ if (CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) || - CC(vmcs12->host_cr4 & X86_CR4_PCIDE) || - CC((vmcs12->host_rip) >> 32)) - return -EINVAL; -@@ -3360,8 +3357,7 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, - }; - u32 failed_index; - -- if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) -- kvm_vcpu_flush_tlb_current(vcpu); -+ kvm_service_local_tlb_flush_requests(vcpu); - - evaluate_pending_interrupts = exec_controls_get(vmx) & - (CPU_BASED_INTR_WINDOW_EXITING | CPU_BASED_NMI_WINDOW_EXITING); -@@ -3570,6 +3566,9 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) - if (nested_vmx_check_controls(vcpu, vmcs12)) - return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); - -+ if (nested_vmx_check_address_space_size(vcpu, vmcs12)) -+ return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); -+ - if (nested_vmx_check_host_state(vcpu, vmcs12)) - return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); - -@@ -4515,9 +4514,8 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, - (void)nested_get_evmcs_page(vcpu); - } - -- /* Service the TLB flush request for L2 before switching to L1. */ -- if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) -- kvm_vcpu_flush_tlb_current(vcpu); -+ /* Service pending TLB flush requests for L2 before switching to L1. */ -+ kvm_service_local_tlb_flush_requests(vcpu); - - /* - * VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between -diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c -index 5f81ef092bd43..1c94783b5a54c 100644 ---- a/arch/x86/kvm/vmx/posted_intr.c -+++ b/arch/x86/kvm/vmx/posted_intr.c -@@ -5,6 +5,7 @@ - #include <asm/cpu.h> - - #include "lapic.h" -+#include "irq.h" - #include "posted_intr.h" - #include "trace.h" - #include "vmx.h" -@@ -77,13 +78,18 @@ after_clear_sn: - pi_set_on(pi_desc); - } - -+static bool vmx_can_use_vtd_pi(struct kvm *kvm) -+{ -+ return irqchip_in_kernel(kvm) && enable_apicv && -+ kvm_arch_has_assigned_device(kvm) && -+ irq_remapping_cap(IRQ_POSTING_CAP); -+} -+ - void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu) - { - struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); - -- if (!kvm_arch_has_assigned_device(vcpu->kvm) || -- !irq_remapping_cap(IRQ_POSTING_CAP) || -- !kvm_vcpu_apicv_active(vcpu)) -+ if (!vmx_can_use_vtd_pi(vcpu->kvm)) - return; - - /* Set SN when the vCPU is preempted */ -@@ -141,9 +147,7 @@ int pi_pre_block(struct kvm_vcpu *vcpu) - struct pi_desc old, new; - struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); - -- if (!kvm_arch_has_assigned_device(vcpu->kvm) || -- !irq_remapping_cap(IRQ_POSTING_CAP) || -- !kvm_vcpu_apicv_active(vcpu)) -+ if (!vmx_can_use_vtd_pi(vcpu->kvm)) - return 0; - - WARN_ON(irqs_disabled()); -@@ -270,9 +274,7 @@ int pi_update_irte(struct kvm *kvm, unsigned int host_irq, uint32_t guest_irq, - struct vcpu_data vcpu_info; - int idx, ret = 0; - -- if (!kvm_arch_has_assigned_device(kvm) || -- !irq_remapping_cap(IRQ_POSTING_CAP) || -- !kvm_vcpu_apicv_active(kvm->vcpus[0])) -+ if (!vmx_can_use_vtd_pi(kvm)) - return 0; - - idx = srcu_read_lock(&kvm->irq_srcu); -diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c -index 7d595effb66f0..4e212f04268bb 100644 ---- a/arch/x86/kvm/vmx/vmx.c -+++ b/arch/x86/kvm/vmx/vmx.c -@@ -769,24 +769,13 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu) - /* - * Check if MSR is intercepted for currently loaded MSR bitmap. - */ --static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr) -+static bool msr_write_intercepted(struct vcpu_vmx *vmx, u32 msr) - { -- unsigned long *msr_bitmap; -- int f = sizeof(unsigned long); -- -- if (!cpu_has_vmx_msr_bitmap()) -+ if (!(exec_controls_get(vmx) & CPU_BASED_USE_MSR_BITMAPS)) - return true; - -- msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap; -- -- if (msr <= 0x1fff) { -- return !!test_bit(msr, msr_bitmap + 0x800 / f); -- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { -- msr &= 0x1fff; -- return !!test_bit(msr, msr_bitmap + 0xc00 / f); -- } -- -- return true; -+ return vmx_test_msr_bitmap_write(vmx->loaded_vmcs->msr_bitmap, -+ MSR_IA32_SPEC_CTRL); - } - - static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx, -@@ -2927,6 +2916,13 @@ static void vmx_flush_tlb_all(struct kvm_vcpu *vcpu) - } - } - -+static inline int vmx_get_current_vpid(struct kvm_vcpu *vcpu) -+{ -+ if (is_guest_mode(vcpu)) -+ return nested_get_vpid02(vcpu); -+ return to_vmx(vcpu)->vpid; -+} -+ - static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) - { - struct kvm_mmu *mmu = vcpu->arch.mmu; -@@ -2939,31 +2935,29 @@ static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) - if (enable_ept) - ept_sync_context(construct_eptp(vcpu, root_hpa, - mmu->shadow_root_level)); -- else if (!is_guest_mode(vcpu)) -- vpid_sync_context(to_vmx(vcpu)->vpid); - else -- vpid_sync_context(nested_get_vpid02(vcpu)); -+ vpid_sync_context(vmx_get_current_vpid(vcpu)); - } - - static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr) - { - /* -- * vpid_sync_vcpu_addr() is a nop if vmx->vpid==0, see the comment in -+ * vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in - * vmx_flush_tlb_guest() for an explanation of why this is ok. - */ -- vpid_sync_vcpu_addr(to_vmx(vcpu)->vpid, addr); -+ vpid_sync_vcpu_addr(vmx_get_current_vpid(vcpu), addr); - } - - static void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu) - { - /* -- * vpid_sync_context() is a nop if vmx->vpid==0, e.g. if enable_vpid==0 -- * or a vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit -- * are required to flush GVA->{G,H}PA mappings from the TLB if vpid is -+ * vpid_sync_context() is a nop if vpid==0, e.g. if enable_vpid==0 or a -+ * vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit are -+ * required to flush GVA->{G,H}PA mappings from the TLB if vpid is - * disabled (VM-Enter with vpid enabled and vpid==0 is disallowed), - * i.e. no explicit INVVPID is necessary. - */ -- vpid_sync_context(to_vmx(vcpu)->vpid); -+ vpid_sync_context(vmx_get_current_vpid(vcpu)); - } - - void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu) -@@ -3695,46 +3689,6 @@ void free_vpid(int vpid) - spin_unlock(&vmx_vpid_lock); - } - --static void vmx_clear_msr_bitmap_read(ulong *msr_bitmap, u32 msr) --{ -- int f = sizeof(unsigned long); -- -- if (msr <= 0x1fff) -- __clear_bit(msr, msr_bitmap + 0x000 / f); -- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -- __clear_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); --} -- --static void vmx_clear_msr_bitmap_write(ulong *msr_bitmap, u32 msr) --{ -- int f = sizeof(unsigned long); -- -- if (msr <= 0x1fff) -- __clear_bit(msr, msr_bitmap + 0x800 / f); -- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -- __clear_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); --} -- --static void vmx_set_msr_bitmap_read(ulong *msr_bitmap, u32 msr) --{ -- int f = sizeof(unsigned long); -- -- if (msr <= 0x1fff) -- __set_bit(msr, msr_bitmap + 0x000 / f); -- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -- __set_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); --} -- --static void vmx_set_msr_bitmap_write(ulong *msr_bitmap, u32 msr) --{ -- int f = sizeof(unsigned long); -- -- if (msr <= 0x1fff) -- __set_bit(msr, msr_bitmap + 0x800 / f); -- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -- __set_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); --} -- - void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type) - { - struct vcpu_vmx *vmx = to_vmx(vcpu); -@@ -6288,9 +6242,9 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu) - { - struct vcpu_vmx *vmx = to_vmx(vcpu); - int max_irr; -- bool max_irr_updated; -+ bool got_posted_interrupt; - -- if (KVM_BUG_ON(!vcpu->arch.apicv_active, vcpu->kvm)) -+ if (KVM_BUG_ON(!enable_apicv, vcpu->kvm)) - return -EIO; - - if (pi_test_on(&vmx->pi_desc)) { -@@ -6300,22 +6254,33 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu) - * But on x86 this is just a compiler barrier anyway. - */ - smp_mb__after_atomic(); -- max_irr_updated = -+ got_posted_interrupt = - kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr); -- -- /* -- * If we are running L2 and L1 has a new pending interrupt -- * which can be injected, this may cause a vmexit or it may -- * be injected into L2. Either way, this interrupt will be -- * processed via KVM_REQ_EVENT, not RVI, because we do not use -- * virtual interrupt delivery to inject L1 interrupts into L2. -- */ -- if (is_guest_mode(vcpu) && max_irr_updated) -- kvm_make_request(KVM_REQ_EVENT, vcpu); - } else { - max_irr = kvm_lapic_find_highest_irr(vcpu); -+ got_posted_interrupt = false; - } -- vmx_hwapic_irr_update(vcpu, max_irr); -+ -+ /* -+ * Newly recognized interrupts are injected via either virtual interrupt -+ * delivery (RVI) or KVM_REQ_EVENT. Virtual interrupt delivery is -+ * disabled in two cases: -+ * -+ * 1) If L2 is running and the vCPU has a new pending interrupt. If L1 -+ * wants to exit on interrupts, KVM_REQ_EVENT is needed to synthesize a -+ * VM-Exit to L1. If L1 doesn't want to exit, the interrupt is injected -+ * into L2, but KVM doesn't use virtual interrupt delivery to inject -+ * interrupts into L2, and so KVM_REQ_EVENT is again needed. -+ * -+ * 2) If APICv is disabled for this vCPU, assigned devices may still -+ * attempt to post interrupts. The posted interrupt vector will cause -+ * a VM-Exit and the subsequent entry will call sync_pir_to_irr. -+ */ -+ if (!is_guest_mode(vcpu) && kvm_vcpu_apicv_active(vcpu)) -+ vmx_set_rvi(max_irr); -+ else if (got_posted_interrupt) -+ kvm_make_request(KVM_REQ_EVENT, vcpu); -+ - return max_irr; - } - -@@ -6720,7 +6685,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) - * If the L02 MSR bitmap does not intercept the MSR, then we need to - * save it. - */ -- if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))) -+ if (unlikely(!msr_write_intercepted(vmx, MSR_IA32_SPEC_CTRL))) - vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL); - - x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0); -@@ -7551,6 +7516,8 @@ static void vmx_migrate_timers(struct kvm_vcpu *vcpu) - - static void hardware_unsetup(void) - { -+ kvm_set_posted_intr_wakeup_handler(NULL); -+ - if (nested) - nested_vmx_hardware_unsetup(); - -@@ -7809,10 +7776,10 @@ static __init int hardware_setup(void) - ple_window_shrink = 0; - } - -- if (!cpu_has_vmx_apicv()) { -+ if (!cpu_has_vmx_apicv()) - enable_apicv = 0; -+ if (!enable_apicv) - vmx_x86_ops.sync_pir_to_irr = NULL; -- } - - if (cpu_has_vmx_tsc_scaling()) { - kvm_has_tsc_control = true; -@@ -7879,8 +7846,6 @@ static __init int hardware_setup(void) - vmx_x86_ops.request_immediate_exit = __kvm_request_immediate_exit; - } - -- kvm_set_posted_intr_wakeup_handler(pi_wakeup_handler); -- - kvm_mce_cap_supported |= MCG_LMCE_P; - - if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST) -@@ -7904,6 +7869,9 @@ static __init int hardware_setup(void) - r = alloc_kvm_area(); - if (r) - nested_vmx_hardware_unsetup(); -+ -+ kvm_set_posted_intr_wakeup_handler(pi_wakeup_handler); -+ - return r; - } - -diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h -index 592217fd7d920..3f9c8548625d6 100644 ---- a/arch/x86/kvm/vmx/vmx.h -+++ b/arch/x86/kvm/vmx/vmx.h -@@ -400,6 +400,69 @@ static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, - - void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu); - -+static inline bool vmx_test_msr_bitmap_read(ulong *msr_bitmap, u32 msr) -+{ -+ int f = sizeof(unsigned long); -+ -+ if (msr <= 0x1fff) -+ return test_bit(msr, msr_bitmap + 0x000 / f); -+ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -+ return test_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); -+ return true; -+} -+ -+static inline bool vmx_test_msr_bitmap_write(ulong *msr_bitmap, u32 msr) -+{ -+ int f = sizeof(unsigned long); -+ -+ if (msr <= 0x1fff) -+ return test_bit(msr, msr_bitmap + 0x800 / f); -+ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -+ return test_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); -+ return true; -+} -+ -+static inline void vmx_clear_msr_bitmap_read(ulong *msr_bitmap, u32 msr) -+{ -+ int f = sizeof(unsigned long); -+ -+ if (msr <= 0x1fff) -+ __clear_bit(msr, msr_bitmap + 0x000 / f); -+ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -+ __clear_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); -+} -+ -+static inline void vmx_clear_msr_bitmap_write(ulong *msr_bitmap, u32 msr) -+{ -+ int f = sizeof(unsigned long); -+ -+ if (msr <= 0x1fff) -+ __clear_bit(msr, msr_bitmap + 0x800 / f); -+ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -+ __clear_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); -+} -+ -+static inline void vmx_set_msr_bitmap_read(ulong *msr_bitmap, u32 msr) -+{ -+ int f = sizeof(unsigned long); -+ -+ if (msr <= 0x1fff) -+ __set_bit(msr, msr_bitmap + 0x000 / f); -+ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -+ __set_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); -+} -+ -+static inline void vmx_set_msr_bitmap_write(ulong *msr_bitmap, u32 msr) -+{ -+ int f = sizeof(unsigned long); -+ -+ if (msr <= 0x1fff) -+ __set_bit(msr, msr_bitmap + 0x800 / f); -+ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) -+ __set_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); -+} -+ -+ - static inline u8 vmx_get_rvi(void) - { - return vmcs_read16(GUEST_INTR_STATUS) & 0xff; -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index bfe0de3008a60..dea578586fa4e 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -1091,6 +1091,18 @@ static void kvm_invalidate_pcid(struct kvm_vcpu *vcpu, unsigned long pcid) - unsigned long roots_to_free = 0; - int i; - -+ /* -+ * MOV CR3 and INVPCID are usually not intercepted when using TDP, but -+ * this is reachable when running EPT=1 and unrestricted_guest=0, and -+ * also via the emulator. KVM's TDP page tables are not in the scope of -+ * the invalidation, but the guest's TLB entries need to be flushed as -+ * the CPU may have cached entries in its TLB for the target PCID. -+ */ -+ if (unlikely(tdp_enabled)) { -+ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); -+ return; -+ } -+ - /* - * If neither the current CR3 nor any of the prev_roots use the given - * PCID, then nothing needs to be done here because a resync will -@@ -3193,10 +3205,36 @@ static void kvm_vcpu_flush_tlb_guest(struct kvm_vcpu *vcpu) - static_call(kvm_x86_tlb_flush_guest)(vcpu); - } - -+ -+static inline void kvm_vcpu_flush_tlb_current(struct kvm_vcpu *vcpu) -+{ -+ ++vcpu->stat.tlb_flush; -+ static_call(kvm_x86_tlb_flush_current)(vcpu); -+} -+ -+/* -+ * Service "local" TLB flush requests, which are specific to the current MMU -+ * context. In addition to the generic event handling in vcpu_enter_guest(), -+ * TLB flushes that are targeted at an MMU context also need to be serviced -+ * prior before nested VM-Enter/VM-Exit. -+ */ -+void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu) -+{ -+ if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) -+ kvm_vcpu_flush_tlb_current(vcpu); -+ -+ if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) -+ kvm_vcpu_flush_tlb_guest(vcpu); -+} -+EXPORT_SYMBOL_GPL(kvm_service_local_tlb_flush_requests); -+ - static void record_steal_time(struct kvm_vcpu *vcpu) - { -- struct kvm_host_map map; -- struct kvm_steal_time *st; -+ struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache; -+ struct kvm_steal_time __user *st; -+ struct kvm_memslots *slots; -+ u64 steal; -+ u32 version; - - if (kvm_xen_msr_enabled(vcpu->kvm)) { - kvm_xen_runstate_set_running(vcpu); -@@ -3206,47 +3244,86 @@ static void record_steal_time(struct kvm_vcpu *vcpu) - if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) - return; - -- /* -EAGAIN is returned in atomic context so we can just return. */ -- if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, -- &map, &vcpu->arch.st.cache, false)) -+ if (WARN_ON_ONCE(current->mm != vcpu->kvm->mm)) - return; - -- st = map.hva + -- offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); -+ slots = kvm_memslots(vcpu->kvm); - -+ if (unlikely(slots->generation != ghc->generation || -+ kvm_is_error_hva(ghc->hva) || !ghc->memslot)) { -+ gfn_t gfn = vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS; -+ -+ /* We rely on the fact that it fits in a single page. */ -+ BUILD_BUG_ON((sizeof(*st) - 1) & KVM_STEAL_VALID_BITS); -+ -+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, gfn, sizeof(*st)) || -+ kvm_is_error_hva(ghc->hva) || !ghc->memslot) -+ return; -+ } -+ -+ st = (struct kvm_steal_time __user *)ghc->hva; - /* - * Doing a TLB flush here, on the guest's behalf, can avoid - * expensive IPIs. - */ - if (guest_pv_has(vcpu, KVM_FEATURE_PV_TLB_FLUSH)) { -- u8 st_preempted = xchg(&st->preempted, 0); -+ u8 st_preempted = 0; -+ int err = -EFAULT; -+ -+ if (!user_access_begin(st, sizeof(*st))) -+ return; -+ -+ asm volatile("1: xchgb %0, %2\n" -+ "xor %1, %1\n" -+ "2:\n" -+ _ASM_EXTABLE_UA(1b, 2b) -+ : "+q" (st_preempted), -+ "+&r" (err), -+ "+m" (st->preempted)); -+ if (err) -+ goto out; -+ -+ user_access_end(); -+ -+ vcpu->arch.st.preempted = 0; - - trace_kvm_pv_tlb_flush(vcpu->vcpu_id, - st_preempted & KVM_VCPU_FLUSH_TLB); - if (st_preempted & KVM_VCPU_FLUSH_TLB) - kvm_vcpu_flush_tlb_guest(vcpu); -+ -+ if (!user_access_begin(st, sizeof(*st))) -+ goto dirty; - } else { -- st->preempted = 0; -- } -+ if (!user_access_begin(st, sizeof(*st))) -+ return; - -- vcpu->arch.st.preempted = 0; -+ unsafe_put_user(0, &st->preempted, out); -+ vcpu->arch.st.preempted = 0; -+ } - -- if (st->version & 1) -- st->version += 1; /* first time write, random junk */ -+ unsafe_get_user(version, &st->version, out); -+ if (version & 1) -+ version += 1; /* first time write, random junk */ - -- st->version += 1; -+ version += 1; -+ unsafe_put_user(version, &st->version, out); - - smp_wmb(); - -- st->steal += current->sched_info.run_delay - -+ unsafe_get_user(steal, &st->steal, out); -+ steal += current->sched_info.run_delay - - vcpu->arch.st.last_steal; - vcpu->arch.st.last_steal = current->sched_info.run_delay; -+ unsafe_put_user(steal, &st->steal, out); - -- smp_wmb(); -- -- st->version += 1; -+ version += 1; -+ unsafe_put_user(version, &st->version, out); - -- kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false); -+ out: -+ user_access_end(); -+ dirty: -+ mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa)); - } - - int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) -@@ -3282,7 +3359,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - - if (!msr_info->host_initiated) - return 1; -- if (guest_cpuid_has(vcpu, X86_FEATURE_PDCM) && kvm_get_msr_feature(&msr_ent)) -+ if (kvm_get_msr_feature(&msr_ent)) - return 1; - if (data & ~msr_ent.data) - return 1; -@@ -4285,8 +4362,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) - - static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) - { -- struct kvm_host_map map; -- struct kvm_steal_time *st; -+ struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache; -+ struct kvm_steal_time __user *st; -+ struct kvm_memslots *slots; -+ static const u8 preempted = KVM_VCPU_PREEMPTED; - - if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) - return; -@@ -4294,16 +4373,23 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) - if (vcpu->arch.st.preempted) - return; - -- if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, -- &vcpu->arch.st.cache, true)) -+ /* This happens on process exit */ -+ if (unlikely(current->mm != vcpu->kvm->mm)) -+ return; -+ -+ slots = kvm_memslots(vcpu->kvm); -+ -+ if (unlikely(slots->generation != ghc->generation || -+ kvm_is_error_hva(ghc->hva) || !ghc->memslot)) - return; - -- st = map.hva + -- offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); -+ st = (struct kvm_steal_time __user *)ghc->hva; -+ BUILD_BUG_ON(sizeof(st->preempted) != sizeof(preempted)); - -- st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED; -+ if (!copy_to_user_nofault(&st->preempted, &preempted, sizeof(preempted))) -+ vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED; - -- kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true); -+ mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa)); - } - - void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) -@@ -4331,8 +4417,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) - static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu, - struct kvm_lapic_state *s) - { -- if (vcpu->arch.apicv_active) -- static_call(kvm_x86_sync_pir_to_irr)(vcpu); -+ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); - - return kvm_apic_get_state(vcpu, s); - } -@@ -6948,7 +7033,13 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, - unsigned short port, void *val, unsigned int count) - { - if (vcpu->arch.pio.count) { -- /* Complete previous iteration. */ -+ /* -+ * Complete a previous iteration that required userspace I/O. -+ * Note, @count isn't guaranteed to match pio.count as userspace -+ * can modify ECX before rerunning the vCPU. Ignore any such -+ * shenanigans as KVM doesn't support modifying the rep count, -+ * and the emulator ensures @count doesn't overflow the buffer. -+ */ - } else { - int r = __emulator_pio_in(vcpu, size, port, count); - if (!r) -@@ -6957,7 +7048,6 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, - /* Results already available, fall through. */ - } - -- WARN_ON(count != vcpu->arch.pio.count); - complete_emulator_pio_in(vcpu, val); - return 1; - } -@@ -8686,7 +8776,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) - - trace_kvm_hypercall(nr, a0, a1, a2, a3); - -- op_64_bit = is_64_bit_mode(vcpu); -+ op_64_bit = is_64_bit_hypercall(vcpu); - if (!op_64_bit) { - nr &= 0xFFFFFFFF; - a0 &= 0xFFFFFFFF; -@@ -9359,8 +9449,7 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu) - if (irqchip_split(vcpu->kvm)) - kvm_scan_ioapic_routes(vcpu, vcpu->arch.ioapic_handled_vectors); - else { -- if (vcpu->arch.apicv_active) -- static_call(kvm_x86_sync_pir_to_irr)(vcpu); -+ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); - if (ioapic_in_kernel(vcpu->kvm)) - kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors); - } -@@ -9378,12 +9467,16 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu) - if (!kvm_apic_hw_enabled(vcpu->arch.apic)) - return; - -- if (to_hv_vcpu(vcpu)) -+ if (to_hv_vcpu(vcpu)) { - bitmap_or((ulong *)eoi_exit_bitmap, - vcpu->arch.ioapic_handled_vectors, - to_hv_synic(vcpu)->vec_bitmap, 256); -+ static_call(kvm_x86_load_eoi_exitmap)(vcpu, eoi_exit_bitmap); -+ return; -+ } - -- static_call(kvm_x86_load_eoi_exitmap)(vcpu, eoi_exit_bitmap); -+ static_call(kvm_x86_load_eoi_exitmap)( -+ vcpu, (u64 *)vcpu->arch.ioapic_handled_vectors); - } - - void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm, -@@ -9475,10 +9568,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) - /* Flushing all ASIDs flushes the current ASID... */ - kvm_clear_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); - } -- if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) -- kvm_vcpu_flush_tlb_current(vcpu); -- if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) -- kvm_vcpu_flush_tlb_guest(vcpu); -+ kvm_service_local_tlb_flush_requests(vcpu); - - if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) { - vcpu->run->exit_reason = KVM_EXIT_TPR_ACCESS; -@@ -9629,10 +9719,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) - - /* - * This handles the case where a posted interrupt was -- * notified with kvm_vcpu_kick. -+ * notified with kvm_vcpu_kick. Assigned devices can -+ * use the POSTED_INTR_VECTOR even if APICv is disabled, -+ * so do it even if APICv is disabled on this vCPU. - */ -- if (kvm_lapic_enabled(vcpu) && vcpu->arch.apicv_active) -- static_call(kvm_x86_sync_pir_to_irr)(vcpu); -+ if (kvm_lapic_enabled(vcpu)) -+ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); - - if (kvm_vcpu_exit_request(vcpu)) { - vcpu->mode = OUTSIDE_GUEST_MODE; -@@ -9668,8 +9760,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) - if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST)) - break; - -- if (vcpu->arch.apicv_active) -- static_call(kvm_x86_sync_pir_to_irr)(vcpu); -+ if (kvm_lapic_enabled(vcpu)) -+ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); - - if (unlikely(kvm_vcpu_exit_request(vcpu))) { - exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED; -@@ -10817,11 +10909,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) - - void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) - { -- struct gfn_to_pfn_cache *cache = &vcpu->arch.st.cache; - int idx; - -- kvm_release_pfn(cache->pfn, cache->dirty, cache); -- - kvmclock_reset(vcpu); - - static_call(kvm_x86_vcpu_free)(vcpu); -diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h -index 7d66d63dc55a6..bc7ef6820ac8f 100644 ---- a/arch/x86/kvm/x86.h -+++ b/arch/x86/kvm/x86.h -@@ -103,6 +103,7 @@ static inline unsigned int __shrink_ple_window(unsigned int val, - - #define MSR_IA32_CR_PAT_DEFAULT 0x0007040600070406ULL - -+void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu); - int kvm_check_nested_events(struct kvm_vcpu *vcpu); - - static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu) -@@ -153,12 +154,24 @@ static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu) - { - int cs_db, cs_l; - -+ WARN_ON_ONCE(vcpu->arch.guest_state_protected); -+ - if (!is_long_mode(vcpu)) - return false; - static_call(kvm_x86_get_cs_db_l_bits)(vcpu, &cs_db, &cs_l); - return cs_l; - } - -+static inline bool is_64_bit_hypercall(struct kvm_vcpu *vcpu) -+{ -+ /* -+ * If running with protected guest state, the CS register is not -+ * accessible. The hypercall register values will have had to been -+ * provided in 64-bit mode, so assume the guest is in 64-bit. -+ */ -+ return vcpu->arch.guest_state_protected || is_64_bit_mode(vcpu); -+} -+ - static inline bool x86_exception_has_error_code(unsigned int vector) - { - static u32 exception_has_error_code = BIT(DF_VECTOR) | BIT(TS_VECTOR) | -@@ -173,12 +186,6 @@ static inline bool mmu_is_nested(struct kvm_vcpu *vcpu) - return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu; - } - --static inline void kvm_vcpu_flush_tlb_current(struct kvm_vcpu *vcpu) --{ -- ++vcpu->stat.tlb_flush; -- static_call(kvm_x86_tlb_flush_current)(vcpu); --} -- - static inline int is_pae(struct kvm_vcpu *vcpu) - { - return kvm_read_cr4_bits(vcpu, X86_CR4_PAE); -diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c -index 8f62baebd0286..0787d6645573e 100644 ---- a/arch/x86/kvm/xen.c -+++ b/arch/x86/kvm/xen.c -@@ -299,7 +299,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) - break; - - case KVM_XEN_ATTR_TYPE_SHARED_INFO: -- data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_gfn); -+ data->u.shared_info.gfn = kvm->arch.xen.shinfo_gfn; - r = 0; - break; - -@@ -698,7 +698,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu) - kvm_hv_hypercall_enabled(vcpu)) - return kvm_hv_hypercall(vcpu); - -- longmode = is_64_bit_mode(vcpu); -+ longmode = is_64_bit_hypercall(vcpu); - if (!longmode) { - params[0] = (u32)kvm_rbx_read(vcpu); - params[1] = (u32)kvm_rcx_read(vcpu); -diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c -index a1d24fdc07cf0..eb3ccffb9b9dc 100644 ---- a/arch/x86/lib/insn-eval.c -+++ b/arch/x86/lib/insn-eval.c -@@ -1417,7 +1417,7 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) - } - } - --static int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip) -+int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip) - { - unsigned long seg_base = 0; - -diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c -index c565def611e24..55e371cc69fd5 100644 ---- a/arch/x86/lib/insn.c -+++ b/arch/x86/lib/insn.c -@@ -13,6 +13,7 @@ - #endif - #include <asm/inat.h> /*__ignore_sync_check__ */ - #include <asm/insn.h> /* __ignore_sync_check__ */ -+#include <asm/unaligned.h> /* __ignore_sync_check__ */ - - #include <linux/errno.h> - #include <linux/kconfig.h> -@@ -37,10 +38,10 @@ - ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr) - - #define __get_next(t, insn) \ -- ({ t r; memcpy(&r, insn->next_byte, sizeof(t)); insn->next_byte += sizeof(t); leXX_to_cpu(t, r); }) -+ ({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); }) - - #define __peek_nbyte_next(t, insn, n) \ -- ({ t r; memcpy(&r, (insn)->next_byte + n, sizeof(t)); leXX_to_cpu(t, r); }) -+ ({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); }) - - #define get_next(t, insn) \ - ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); }) -diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c -index f5e1e60c9095f..6c2f1b76a0b61 100644 ---- a/arch/x86/mm/cpu_entry_area.c -+++ b/arch/x86/mm/cpu_entry_area.c -@@ -110,6 +110,13 @@ static void __init percpu_setup_exception_stacks(unsigned int cpu) - cea_map_stack(NMI); - cea_map_stack(DB); - cea_map_stack(MCE); -+ -+ if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) { -+ if (cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) { -+ cea_map_stack(VC); -+ cea_map_stack(VC2); -+ } -+ } - } - #else - static inline void percpu_setup_exception_stacks(unsigned int cpu) -diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c -index 84a2c8c4af735..4bfed53e210ec 100644 ---- a/arch/x86/mm/fault.c -+++ b/arch/x86/mm/fault.c -@@ -32,6 +32,7 @@ - #include <asm/pgtable_areas.h> /* VMALLOC_START, ... */ - #include <asm/kvm_para.h> /* kvm_handle_async_pf */ - #include <asm/vdso.h> /* fixup_vdso_exception() */ -+#include <asm/irq_stack.h> - - #define CREATE_TRACE_POINTS - #include <asm/trace/exceptions.h> -@@ -631,6 +632,9 @@ static noinline void - page_fault_oops(struct pt_regs *regs, unsigned long error_code, - unsigned long address) - { -+#ifdef CONFIG_VMAP_STACK -+ struct stack_info info; -+#endif - unsigned long flags; - int sig; - -@@ -649,9 +653,7 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code, - * that we're in vmalloc space to avoid this. - */ - if (is_vmalloc_addr((void *)address) && -- (((unsigned long)current->stack - 1 - address < PAGE_SIZE) || -- address - ((unsigned long)current->stack + THREAD_SIZE) < PAGE_SIZE)) { -- unsigned long stack = __this_cpu_ist_top_va(DF) - sizeof(void *); -+ get_stack_guard_info((void *)address, &info)) { - /* - * We're likely to be running with very little stack space - * left. It's plausible that we'd hit this condition but -@@ -662,13 +664,11 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code, - * and then double-fault, though, because we're likely to - * break the console driver and lose most of the stack dump. - */ -- asm volatile ("movq %[stack], %%rsp\n\t" -- "call handle_stack_overflow\n\t" -- "1: jmp 1b" -- : ASM_CALL_CONSTRAINT -- : "D" ("kernel stack overflow (page fault)"), -- "S" (regs), "d" (address), -- [stack] "rm" (stack)); -+ call_on_stack(__this_cpu_ist_top_va(DF) - sizeof(void*), -+ handle_stack_overflow, -+ ASM_CALL_ARG3, -+ , [arg1] "r" (regs), [arg2] "r" (address), [arg3] "r" (&info)); -+ - unreachable(); - } - #endif -diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c -index ff08dc4636347..e29b1418d00c7 100644 ---- a/arch/x86/mm/mem_encrypt.c -+++ b/arch/x86/mm/mem_encrypt.c -@@ -20,6 +20,7 @@ - #include <linux/bitops.h> - #include <linux/dma-mapping.h> - #include <linux/virtio_config.h> -+#include <linux/cc_platform.h> - - #include <asm/tlbflush.h> - #include <asm/fixmap.h> -diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c -index 470b202084306..700ce8fdea87c 100644 ---- a/arch/x86/mm/mem_encrypt_identity.c -+++ b/arch/x86/mm/mem_encrypt_identity.c -@@ -27,6 +27,15 @@ - #undef CONFIG_PARAVIRT_XXL - #undef CONFIG_PARAVIRT_SPINLOCKS - -+/* -+ * This code runs before CPU feature bits are set. By default, the -+ * pgtable_l5_enabled() function uses bit X86_FEATURE_LA57 to determine if -+ * 5-level paging is active, so that won't work here. USE_EARLY_PGTABLE_L5 -+ * is provided to handle this situation and, instead, use a variable that -+ * has been set by the early boot code. -+ */ -+#define USE_EARLY_PGTABLE_L5 -+ - #include <linux/kernel.h> - #include <linux/mm.h> - #include <linux/mem_encrypt.h> -diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c -index 9ea57389c554b..d99434dc215c2 100644 ---- a/arch/x86/net/bpf_jit_comp.c -+++ b/arch/x86/net/bpf_jit_comp.c -@@ -721,6 +721,20 @@ static void maybe_emit_mod(u8 **pprog, u32 dst_reg, u32 src_reg, bool is64) - *pprog = prog; - } - -+/* -+ * Similar version of maybe_emit_mod() for a single register -+ */ -+static void maybe_emit_1mod(u8 **pprog, u32 reg, bool is64) -+{ -+ u8 *prog = *pprog; -+ -+ if (is64) -+ EMIT1(add_1mod(0x48, reg)); -+ else if (is_ereg(reg)) -+ EMIT1(add_1mod(0x40, reg)); -+ *pprog = prog; -+} -+ - /* LDX: dst_reg = *(u8*)(src_reg + off) */ - static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off) - { -@@ -951,10 +965,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, - /* neg dst */ - case BPF_ALU | BPF_NEG: - case BPF_ALU64 | BPF_NEG: -- if (BPF_CLASS(insn->code) == BPF_ALU64) -- EMIT1(add_1mod(0x48, dst_reg)); -- else if (is_ereg(dst_reg)) -- EMIT1(add_1mod(0x40, dst_reg)); -+ maybe_emit_1mod(&prog, dst_reg, -+ BPF_CLASS(insn->code) == BPF_ALU64); - EMIT2(0xF7, add_1reg(0xD8, dst_reg)); - break; - -@@ -968,10 +980,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, - case BPF_ALU64 | BPF_AND | BPF_K: - case BPF_ALU64 | BPF_OR | BPF_K: - case BPF_ALU64 | BPF_XOR | BPF_K: -- if (BPF_CLASS(insn->code) == BPF_ALU64) -- EMIT1(add_1mod(0x48, dst_reg)); -- else if (is_ereg(dst_reg)) -- EMIT1(add_1mod(0x40, dst_reg)); -+ maybe_emit_1mod(&prog, dst_reg, -+ BPF_CLASS(insn->code) == BPF_ALU64); - - /* - * b3 holds 'normal' opcode, b2 short form only valid -@@ -1112,10 +1122,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, - case BPF_ALU64 | BPF_LSH | BPF_K: - case BPF_ALU64 | BPF_RSH | BPF_K: - case BPF_ALU64 | BPF_ARSH | BPF_K: -- if (BPF_CLASS(insn->code) == BPF_ALU64) -- EMIT1(add_1mod(0x48, dst_reg)); -- else if (is_ereg(dst_reg)) -- EMIT1(add_1mod(0x40, dst_reg)); -+ maybe_emit_1mod(&prog, dst_reg, -+ BPF_CLASS(insn->code) == BPF_ALU64); - - b3 = simple_alu_opcodes[BPF_OP(insn->code)]; - if (imm32 == 1) -@@ -1146,10 +1154,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, - } - - /* shl %rax, %cl | shr %rax, %cl | sar %rax, %cl */ -- if (BPF_CLASS(insn->code) == BPF_ALU64) -- EMIT1(add_1mod(0x48, dst_reg)); -- else if (is_ereg(dst_reg)) -- EMIT1(add_1mod(0x40, dst_reg)); -+ maybe_emit_1mod(&prog, dst_reg, -+ BPF_CLASS(insn->code) == BPF_ALU64); - - b3 = simple_alu_opcodes[BPF_OP(insn->code)]; - EMIT2(0xD3, add_1reg(b3, dst_reg)); -@@ -1274,19 +1280,54 @@ st: if (is_imm8(insn->off)) - case BPF_LDX | BPF_MEM | BPF_DW: - case BPF_LDX | BPF_PROBE_MEM | BPF_DW: - if (BPF_MODE(insn->code) == BPF_PROBE_MEM) { -- /* test src_reg, src_reg */ -- maybe_emit_mod(&prog, src_reg, src_reg, true); /* always 1 byte */ -- EMIT2(0x85, add_2reg(0xC0, src_reg, src_reg)); -- /* jne start_of_ldx */ -- EMIT2(X86_JNE, 0); -+ /* Though the verifier prevents negative insn->off in BPF_PROBE_MEM -+ * add abs(insn->off) to the limit to make sure that negative -+ * offset won't be an issue. -+ * insn->off is s16, so it won't affect valid pointers. -+ */ -+ u64 limit = TASK_SIZE_MAX + PAGE_SIZE + abs(insn->off); -+ u8 *end_of_jmp1, *end_of_jmp2; -+ -+ /* Conservatively check that src_reg + insn->off is a kernel address: -+ * 1. src_reg + insn->off >= limit -+ * 2. src_reg + insn->off doesn't become small positive. -+ * Cannot do src_reg + insn->off >= limit in one branch, -+ * since it needs two spare registers, but JIT has only one. -+ */ -+ -+ /* movabsq r11, limit */ -+ EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG)); -+ EMIT((u32)limit, 4); -+ EMIT(limit >> 32, 4); -+ /* cmp src_reg, r11 */ -+ maybe_emit_mod(&prog, src_reg, AUX_REG, true); -+ EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG)); -+ /* if unsigned '<' goto end_of_jmp2 */ -+ EMIT2(X86_JB, 0); -+ end_of_jmp1 = prog; -+ -+ /* mov r11, src_reg */ -+ emit_mov_reg(&prog, true, AUX_REG, src_reg); -+ /* add r11, insn->off */ -+ maybe_emit_1mod(&prog, AUX_REG, true); -+ EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off); -+ /* jmp if not carry to start_of_ldx -+ * Otherwise ERR_PTR(-EINVAL) + 128 will be the user addr -+ * that has to be rejected. -+ */ -+ EMIT2(0x73 /* JNC */, 0); -+ end_of_jmp2 = prog; -+ - /* xor dst_reg, dst_reg */ - emit_mov_imm32(&prog, false, dst_reg, 0); - /* jmp byte_after_ldx */ - EMIT2(0xEB, 0); - -- /* populate jmp_offset for JNE above */ -- temp[4] = prog - temp - 5 /* sizeof(test + jne) */; -+ /* populate jmp_offset for JB above to jump to xor dst_reg */ -+ end_of_jmp1[-1] = end_of_jmp2 - end_of_jmp1; -+ /* populate jmp_offset for JNC above to jump to start_of_ldx */ - start_of_ldx = prog; -+ end_of_jmp2[-1] = start_of_ldx - end_of_jmp2; - } - emit_ldx(&prog, BPF_SIZE(insn->code), dst_reg, src_reg, insn->off); - if (BPF_MODE(insn->code) == BPF_PROBE_MEM) { -@@ -1332,7 +1373,7 @@ st: if (is_imm8(insn->off)) - * End result: x86 insn "mov rbx, qword ptr [rax+0x14]" - * of 4 bytes will be ignored and rbx will be zero inited. - */ -- ex->fixup = (prog - temp) | (reg2pt_regs[dst_reg] << 8); -+ ex->fixup = (prog - start_of_ldx) | (reg2pt_regs[dst_reg] << 8); - } - break; - -@@ -1459,10 +1500,8 @@ st: if (is_imm8(insn->off)) - case BPF_JMP | BPF_JSET | BPF_K: - case BPF_JMP32 | BPF_JSET | BPF_K: - /* test dst_reg, imm32 */ -- if (BPF_CLASS(insn->code) == BPF_JMP) -- EMIT1(add_1mod(0x48, dst_reg)); -- else if (is_ereg(dst_reg)) -- EMIT1(add_1mod(0x40, dst_reg)); -+ maybe_emit_1mod(&prog, dst_reg, -+ BPF_CLASS(insn->code) == BPF_JMP); - EMIT2_off32(0xF7, add_1reg(0xC0, dst_reg), imm32); - goto emit_cond_jmp; - -@@ -1495,10 +1534,8 @@ st: if (is_imm8(insn->off)) - } - - /* cmp dst_reg, imm8/32 */ -- if (BPF_CLASS(insn->code) == BPF_JMP) -- EMIT1(add_1mod(0x48, dst_reg)); -- else if (is_ereg(dst_reg)) -- EMIT1(add_1mod(0x40, dst_reg)); -+ maybe_emit_1mod(&prog, dst_reg, -+ BPF_CLASS(insn->code) == BPF_JMP); - - if (is_imm8(imm32)) - EMIT3(0x83, add_1reg(0xF8, dst_reg), imm32); -diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c -index b15ebfe40a73e..b0b848d6933af 100644 ---- a/arch/x86/platform/efi/quirks.c -+++ b/arch/x86/platform/efi/quirks.c -@@ -277,7 +277,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) - return; - } - -- new = early_memremap(data.phys_map, data.size); -+ new = early_memremap_prot(data.phys_map, data.size, -+ pgprot_val(pgprot_encrypted(FIXMAP_PAGE_NORMAL))); - if (!new) { - pr_err("Failed to map new boot services memmap\n"); - return; -diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c -index 31b5856010cba..d3eee1ebcf1d5 100644 ---- a/arch/x86/realmode/init.c -+++ b/arch/x86/realmode/init.c -@@ -72,6 +72,7 @@ static void __init setup_real_mode(void) - #ifdef CONFIG_X86_64 - u64 *trampoline_pgd; - u64 efer; -+ int i; - #endif - - base = (unsigned char *)real_mode_header; -@@ -128,8 +129,17 @@ static void __init setup_real_mode(void) - trampoline_header->flags = 0; - - trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); -+ -+ /* Map the real mode stub as virtual == physical */ - trampoline_pgd[0] = trampoline_pgd_entry.pgd; -- trampoline_pgd[511] = init_top_pgt[511].pgd; -+ -+ /* -+ * Include the entirety of the kernel mapping into the trampoline -+ * PGD. This way, all mappings present in the normal kernel page -+ * tables are usable while running on trampoline_pgd. -+ */ -+ for (i = pgd_index(__PAGE_OFFSET); i < PTRS_PER_PGD; i++) -+ trampoline_pgd[i] = init_top_pgt[i].pgd; - #endif - - sme_sev_setup_real_mode(trampoline_header); -diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S -index 1e626444712be..3bebf66569b48 100644 ---- a/arch/x86/xen/xen-asm.S -+++ b/arch/x86/xen/xen-asm.S -@@ -20,6 +20,7 @@ - - #include <linux/init.h> - #include <linux/linkage.h> -+#include <../entry/calling.h> - - /* - * Enable events. This clears the event mask and tests the pending -@@ -191,6 +192,25 @@ SYM_CODE_START(xen_iret) - jmp hypercall_iret - SYM_CODE_END(xen_iret) - -+/* -+ * XEN pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is -+ * also the kernel stack. Reusing swapgs_restore_regs_and_return_to_usermode() -+ * in XEN pv would cause %rsp to move up to the top of the kernel stack and -+ * leave the IRET frame below %rsp, which is dangerous to be corrupted if #NMI -+ * interrupts. And swapgs_restore_regs_and_return_to_usermode() pushing the IRET -+ * frame at the same address is useless. -+ */ -+SYM_CODE_START(xenpv_restore_regs_and_return_to_usermode) -+ UNWIND_HINT_REGS -+ POP_REGS -+ -+ /* stackleak_erase() can work safely on the kernel stack. */ -+ STACKLEAK_ERASE_NOCLOBBER -+ -+ addq $8, %rsp /* skip regs->orig_ax */ -+ jmp xen_iret -+SYM_CODE_END(xenpv_restore_regs_and_return_to_usermode) -+ - /* - * Xen handles syscall callbacks much like ordinary exceptions, which - * means we have: -diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c -index 9a1c5839dd469..0eec59e4df65c 100644 ---- a/block/blk-cgroup.c -+++ b/block/blk-cgroup.c -@@ -633,6 +633,14 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - - q = bdev->bd_disk->queue; - -+ /* -+ * blkcg_deactivate_policy() requires queue to be frozen, we can grab -+ * q_usage_counter to prevent concurrent with blkcg_deactivate_policy(). -+ */ -+ ret = blk_queue_enter(q, 0); -+ if (ret) -+ goto fail; -+ - rcu_read_lock(); - spin_lock_irq(&q->queue_lock); - -@@ -667,13 +675,13 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - new_blkg = blkg_alloc(pos, q, GFP_KERNEL); - if (unlikely(!new_blkg)) { - ret = -ENOMEM; -- goto fail; -+ goto fail_exit_queue; - } - - if (radix_tree_preload(GFP_KERNEL)) { - blkg_free(new_blkg); - ret = -ENOMEM; -- goto fail; -+ goto fail_exit_queue; - } - - rcu_read_lock(); -@@ -702,6 +710,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - goto success; - } - success: -+ blk_queue_exit(q); - ctx->bdev = bdev; - ctx->blkg = blkg; - ctx->body = input; -@@ -712,6 +721,8 @@ fail_preloaded: - fail_unlock: - spin_unlock_irq(&q->queue_lock); - rcu_read_unlock(); -+fail_exit_queue: -+ blk_queue_exit(q); - fail: - blkdev_put_no_open(bdev); - /* -diff --git a/block/blk-core.c b/block/blk-core.c -index 4d8f5fe915887..c2d912d0c976c 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -389,8 +389,10 @@ void blk_cleanup_queue(struct request_queue *q) - blk_queue_flag_set(QUEUE_FLAG_DEAD, q); - - blk_sync_queue(q); -- if (queue_is_mq(q)) -+ if (queue_is_mq(q)) { -+ blk_mq_cancel_work_sync(q); - blk_mq_exit_queue(q); -+ } - - /* - * In theory, request pool of sched_tags belongs to request queue. -@@ -887,10 +889,8 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio) - if (unlikely(!current->io_context)) - create_task_io_context(current, GFP_ATOMIC, q->node); - -- if (blk_throtl_bio(bio)) { -- blkcg_bio_issue_init(bio); -+ if (blk_throtl_bio(bio)) - return false; -- } - - blk_cgroup_bio_start(bio); - blkcg_bio_issue_init(bio); -diff --git a/block/blk-iocost.c b/block/blk-iocost.c -index b3880e4ba22a1..eb7b0d6bd11f6 100644 ---- a/block/blk-iocost.c -+++ b/block/blk-iocost.c -@@ -2311,7 +2311,14 @@ static void ioc_timer_fn(struct timer_list *timer) - hwm = current_hweight_max(iocg); - new_hwi = hweight_after_donation(iocg, old_hwi, hwm, - usage, &now); -- if (new_hwi < hwm) { -+ /* -+ * Donation calculation assumes hweight_after_donation -+ * to be positive, a condition that a donor w/ hwa < 2 -+ * can't meet. Don't bother with donation if hwa is -+ * below 2. It's not gonna make a meaningful difference -+ * anyway. -+ */ -+ if (new_hwi < hwm && hwa >= 2) { - iocg->hweight_donating = hwa; - iocg->hweight_after_donation = new_hwi; - list_add(&iocg->surplus_list, &surpluses); -diff --git a/block/blk-mq.c b/block/blk-mq.c -index 652a31fc3bb38..82de39926a9f6 100644 ---- a/block/blk-mq.c -+++ b/block/blk-mq.c -@@ -763,7 +763,6 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list) - /* this request will be re-inserted to io scheduler queue */ - blk_mq_sched_requeue_request(rq); - -- BUG_ON(!list_empty(&rq->queuelist)); - blk_mq_add_to_requeue_list(rq, true, kick_requeue_list); - } - EXPORT_SYMBOL(blk_mq_requeue_request); -@@ -2148,14 +2147,14 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq) - } - - /* -- * Allow 4x BLK_MAX_REQUEST_COUNT requests on plug queue for multiple -+ * Allow 2x BLK_MAX_REQUEST_COUNT requests on plug queue for multiple - * queues. This is important for md arrays to benefit from merging - * requests. - */ - static inline unsigned short blk_plug_max_rq_count(struct blk_plug *plug) - { - if (plug->multiple_queues) -- return BLK_MAX_REQUEST_COUNT * 4; -+ return BLK_MAX_REQUEST_COUNT * 2; - return BLK_MAX_REQUEST_COUNT; - } - -@@ -4019,6 +4018,19 @@ unsigned int blk_mq_rq_cpu(struct request *rq) - } - EXPORT_SYMBOL(blk_mq_rq_cpu); - -+void blk_mq_cancel_work_sync(struct request_queue *q) -+{ -+ if (queue_is_mq(q)) { -+ struct blk_mq_hw_ctx *hctx; -+ int i; -+ -+ cancel_delayed_work_sync(&q->requeue_work); -+ -+ queue_for_each_hw_ctx(q, hctx, i) -+ cancel_delayed_work_sync(&hctx->run_work); -+ } -+} -+ - static int __init blk_mq_init(void) - { - int i; -diff --git a/block/blk-mq.h b/block/blk-mq.h -index d08779f77a265..7cdca23b6263d 100644 ---- a/block/blk-mq.h -+++ b/block/blk-mq.h -@@ -129,6 +129,8 @@ extern int blk_mq_sysfs_register(struct request_queue *q); - extern void blk_mq_sysfs_unregister(struct request_queue *q); - extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx); - -+void blk_mq_cancel_work_sync(struct request_queue *q); -+ - void blk_mq_release(struct request_queue *q); - - static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q, -diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c -index 614d9d47de36b..4737ec024ee9b 100644 ---- a/block/blk-sysfs.c -+++ b/block/blk-sysfs.c -@@ -805,16 +805,6 @@ static void blk_release_queue(struct kobject *kobj) - - blk_free_queue_stats(q->stats); - -- if (queue_is_mq(q)) { -- struct blk_mq_hw_ctx *hctx; -- int i; -- -- cancel_delayed_work_sync(&q->requeue_work); -- -- queue_for_each_hw_ctx(q, hctx, i) -- cancel_delayed_work_sync(&hctx->run_work); -- } -- - blk_exit_queue(q); - - blk_queue_free_zone_bitmaps(q); -diff --git a/block/blk-wbt.c b/block/blk-wbt.c -index 874c1c37bf0c6..0c119be0e8133 100644 ---- a/block/blk-wbt.c -+++ b/block/blk-wbt.c -@@ -357,6 +357,9 @@ static void wb_timer_fn(struct blk_stat_callback *cb) - unsigned int inflight = wbt_inflight(rwb); - int status; - -+ if (!rwb->rqos.q->disk) -+ return; -+ - status = latency_exceeded(rwb, cb->stat); - - trace_wbt_timer(rwb->rqos.q->disk->bdi, status, rqd->scale_step, -diff --git a/block/blk-zoned.c b/block/blk-zoned.c -index 1d0c76c18fc52..774ecc598bee2 100644 ---- a/block/blk-zoned.c -+++ b/block/blk-zoned.c -@@ -429,9 +429,10 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode, - op = REQ_OP_ZONE_RESET; - - /* Invalidate the page cache, including dirty pages. */ -+ filemap_invalidate_lock(bdev->bd_inode->i_mapping); - ret = blkdev_truncate_zone_range(bdev, mode, &zrange); - if (ret) -- return ret; -+ goto fail; - break; - case BLKOPENZONE: - op = REQ_OP_ZONE_OPEN; -@@ -449,15 +450,9 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode, - ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors, - GFP_KERNEL); - -- /* -- * Invalidate the page cache again for zone reset: writes can only be -- * direct for zoned devices so concurrent writes would not add any page -- * to the page cache after/during reset. The page cache may be filled -- * again due to concurrent reads though and dropping the pages for -- * these is fine. -- */ -- if (!ret && cmd == BLKRESETZONE) -- ret = blkdev_truncate_zone_range(bdev, mode, &zrange); -+fail: -+ if (cmd == BLKRESETZONE) -+ filemap_invalidate_unlock(bdev->bd_inode->i_mapping); - - return ret; - } -diff --git a/block/blk.h b/block/blk.h -index 6c3c00a8fe19d..aab72194d2266 100644 ---- a/block/blk.h -+++ b/block/blk.h -@@ -184,6 +184,12 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list, - void blk_account_io_start(struct request *req); - void blk_account_io_done(struct request *req, u64 now); - -+/* -+ * Plug flush limits -+ */ -+#define BLK_MAX_REQUEST_COUNT 32 -+#define BLK_PLUG_FLUSH_SIZE (128 * 1024) -+ - /* - * Internal elevator interface - */ -diff --git a/block/elevator.c b/block/elevator.c -index ff45d8388f487..cd02ae332c4eb 100644 ---- a/block/elevator.c -+++ b/block/elevator.c -@@ -694,12 +694,18 @@ void elevator_init_mq(struct request_queue *q) - if (!e) - return; - -+ /* -+ * We are called before adding disk, when there isn't any FS I/O, -+ * so freezing queue plus canceling dispatch work is enough to -+ * drain any dispatch activities originated from passthrough -+ * requests, then no need to quiesce queue which may add long boot -+ * latency, especially when lots of disks are involved. -+ */ - blk_mq_freeze_queue(q); -- blk_mq_quiesce_queue(q); -+ blk_mq_cancel_work_sync(q); - - err = blk_mq_init_sched(q, e); - -- blk_mq_unquiesce_queue(q); - blk_mq_unfreeze_queue(q); - - if (err) { -diff --git a/block/genhd.c b/block/genhd.c -index ab12ae6e636e8..f091a60dcf1ea 100644 ---- a/block/genhd.c -+++ b/block/genhd.c -@@ -467,11 +467,15 @@ int device_add_disk(struct device *parent, struct gendisk *disk, - - disk->part0->bd_holder_dir = - kobject_create_and_add("holders", &ddev->kobj); -- if (!disk->part0->bd_holder_dir) -+ if (!disk->part0->bd_holder_dir) { -+ ret = -ENOMEM; - goto out_del_integrity; -+ } - disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); -- if (!disk->slave_dir) -+ if (!disk->slave_dir) { -+ ret = -ENOMEM; - goto out_put_holder_dir; -+ } - - ret = bd_register_pending_holders(disk); - if (ret < 0) -@@ -1082,6 +1086,8 @@ static void disk_release(struct device *dev) - might_sleep(); - WARN_ON_ONCE(disk_live(disk)); - -+ blk_mq_cancel_work_sync(disk->queue); -+ - disk_release_events(disk); - kfree(disk->random); - xa_destroy(&disk->part_tbl); -diff --git a/block/ioctl.c b/block/ioctl.c -index eb0491e90b9a0..a31be7fa31a51 100644 ---- a/block/ioctl.c -+++ b/block/ioctl.c -@@ -113,6 +113,7 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, - uint64_t range[2]; - uint64_t start, len; - struct request_queue *q = bdev_get_queue(bdev); -+ struct inode *inode = bdev->bd_inode; - int err; - - if (!(mode & FMODE_WRITE)) -@@ -135,12 +136,17 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, - if (start + len > i_size_read(bdev->bd_inode)) - return -EINVAL; - -+ filemap_invalidate_lock(inode->i_mapping); - err = truncate_bdev_range(bdev, mode, start, start + len - 1); - if (err) -- return err; -+ goto fail; - -- return blkdev_issue_discard(bdev, start >> 9, len >> 9, -- GFP_KERNEL, flags); -+ err = blkdev_issue_discard(bdev, start >> 9, len >> 9, -+ GFP_KERNEL, flags); -+ -+fail: -+ filemap_invalidate_unlock(inode->i_mapping); -+ return err; - } - - static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, -@@ -148,6 +154,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, - { - uint64_t range[2]; - uint64_t start, end, len; -+ struct inode *inode = bdev->bd_inode; - int err; - - if (!(mode & FMODE_WRITE)) -@@ -170,12 +177,17 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, - return -EINVAL; - - /* Invalidate the page cache, including dirty pages */ -+ filemap_invalidate_lock(inode->i_mapping); - err = truncate_bdev_range(bdev, mode, start, end); - if (err) -- return err; -+ goto fail; -+ -+ err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, -+ BLKDEV_ZERO_NOUNMAP); - -- return blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, -- BLKDEV_ZERO_NOUNMAP); -+fail: -+ filemap_invalidate_unlock(inode->i_mapping); -+ return err; - } - - static int put_ushort(unsigned short __user *argp, unsigned short val) -diff --git a/block/ioprio.c b/block/ioprio.c -index 0e4ff245f2bf2..6f01d35a5145a 100644 ---- a/block/ioprio.c -+++ b/block/ioprio.c -@@ -69,7 +69,14 @@ int ioprio_check_cap(int ioprio) - - switch (class) { - case IOPRIO_CLASS_RT: -- if (!capable(CAP_SYS_NICE) && !capable(CAP_SYS_ADMIN)) -+ /* -+ * Originally this only checked for CAP_SYS_ADMIN, -+ * which was implicitly allowed for pid 0 by security -+ * modules such as SELinux. Make sure we check -+ * CAP_SYS_ADMIN first to avoid a denial/avc for -+ * possibly missing CAP_SYS_NICE permission. -+ */ -+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_NICE)) - return -EPERM; - fallthrough; - /* rt has prio field too */ -@@ -213,6 +220,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) - pgrp = task_pgrp(current); - else - pgrp = find_vpid(who); -+ read_lock(&tasklist_lock); - do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { - tmpio = get_task_ioprio(p); - if (tmpio < 0) -@@ -222,6 +230,8 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) - else - ret = ioprio_best(ret, tmpio); - } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); -+ read_unlock(&tasklist_lock); -+ - break; - case IOPRIO_WHO_USER: - uid = make_kuid(current_user_ns(), who); -diff --git a/crypto/Kconfig b/crypto/Kconfig -index 536df4b6b825c..285f82647d2b7 100644 ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -233,12 +233,12 @@ config CRYPTO_DH - - config CRYPTO_ECC - tristate -+ select CRYPTO_RNG_DEFAULT - - config CRYPTO_ECDH - tristate "ECDH algorithm" - select CRYPTO_ECC - select CRYPTO_KPP -- select CRYPTO_RNG_DEFAULT - help - Generic implementation of the ECDH algorithm - -diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c -index d569c7ed6c800..9d10b846ccf73 100644 ---- a/crypto/pcrypt.c -+++ b/crypto/pcrypt.c -@@ -78,12 +78,14 @@ static void pcrypt_aead_enc(struct padata_priv *padata) - { - struct pcrypt_request *preq = pcrypt_padata_request(padata); - struct aead_request *req = pcrypt_request_ctx(preq); -+ int ret; - -- padata->info = crypto_aead_encrypt(req); -+ ret = crypto_aead_encrypt(req); - -- if (padata->info == -EINPROGRESS) -+ if (ret == -EINPROGRESS) - return; - -+ padata->info = ret; - padata_do_serial(padata); - } - -@@ -123,12 +125,14 @@ static void pcrypt_aead_dec(struct padata_priv *padata) - { - struct pcrypt_request *preq = pcrypt_padata_request(padata); - struct aead_request *req = pcrypt_request_ctx(preq); -+ int ret; - -- padata->info = crypto_aead_decrypt(req); -+ ret = crypto_aead_decrypt(req); - -- if (padata->info == -EINPROGRESS) -+ if (ret == -EINPROGRESS) - return; - -+ padata->info = ret; - padata_do_serial(padata); - } - -diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c -index 82b0400985a51..00149657a4bc1 100644 ---- a/crypto/tcrypt.c -+++ b/crypto/tcrypt.c -@@ -1333,7 +1333,7 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, - - if (bs > XBUFSIZE * PAGE_SIZE) { - pr_err("template (%u) too big for buffer (%lu)\n", -- *b_size, XBUFSIZE * PAGE_SIZE); -+ bs, XBUFSIZE * PAGE_SIZE); - goto out; - } - -@@ -1386,8 +1386,7 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, - memset(cur->xbuf[p], 0xff, k); - - skcipher_request_set_crypt(cur->req, cur->sg, -- cur->sg, *b_size, -- iv); -+ cur->sg, bs, iv); - } - - if (secs) { -diff --git a/drivers/Makefile b/drivers/Makefile -index be5d40ae14882..a110338c860c7 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -41,8 +41,7 @@ obj-$(CONFIG_DMADEVICES) += dma/ - # SOC specific infrastructure drivers. - obj-y += soc/ - --obj-$(CONFIG_VIRTIO) += virtio/ --obj-$(CONFIG_VIRTIO_PCI_LIB) += virtio/ -+obj-y += virtio/ - obj-$(CONFIG_VDPA) += vdpa/ - obj-$(CONFIG_XEN) += xen/ - -diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c -index b0cb662233f1a..81aff651a0d49 100644 ---- a/drivers/acpi/ac.c -+++ b/drivers/acpi/ac.c -@@ -61,6 +61,7 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); - - static int ac_sleep_before_get_state_ms; - static int ac_check_pmic = 1; -+static int ac_only; - - static struct acpi_driver acpi_ac_driver = { - .name = "ac", -@@ -93,6 +94,11 @@ static int acpi_ac_get_state(struct acpi_ac *ac) - if (!ac) - return -EINVAL; - -+ if (ac_only) { -+ ac->state = 1; -+ return 0; -+ } -+ - status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, - &ac->state); - if (ACPI_FAILURE(status)) { -@@ -200,6 +206,12 @@ static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) - return 0; - } - -+static int __init ac_only_quirk(const struct dmi_system_id *d) -+{ -+ ac_only = 1; -+ return 0; -+} -+ - /* Please keep this list alphabetically sorted */ - static const struct dmi_system_id ac_dmi_table[] __initconst = { - { -@@ -209,6 +221,13 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { - DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), - }, - }, -+ { -+ /* Kodlix GK45 returning incorrect state */ -+ .callback = ac_only_quirk, -+ .matches = { -+ DMI_MATCH(DMI_PRODUCT_NAME, "GK45"), -+ }, -+ }, - { - /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ - .callback = ac_do_not_check_pmic_quirk, -diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h -index d41b810e367c4..4366d36ef1198 100644 ---- a/drivers/acpi/acpica/acglobal.h -+++ b/drivers/acpi/acpica/acglobal.h -@@ -226,6 +226,8 @@ extern struct acpi_bit_register_info - acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; - ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a); - ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b); -+ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a_s0); -+ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b_s0); - - /***************************************************************************** - * -diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c -index 803402aefaeb6..808fdf54aeebf 100644 ---- a/drivers/acpi/acpica/hwesleep.c -+++ b/drivers/acpi/acpica/hwesleep.c -@@ -147,17 +147,13 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) - - acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) - { -- acpi_status status; - u8 sleep_type_value; - - ACPI_FUNCTION_TRACE(hw_extended_wake_prep); - -- status = acpi_get_sleep_type_data(ACPI_STATE_S0, -- &acpi_gbl_sleep_type_a, -- &acpi_gbl_sleep_type_b); -- if (ACPI_SUCCESS(status)) { -+ if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { - sleep_type_value = -- ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & -+ ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) & - ACPI_X_SLEEP_TYPE_MASK); - - (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), -diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c -index 14baa13bf8482..34a3825f25d37 100644 ---- a/drivers/acpi/acpica/hwsleep.c -+++ b/drivers/acpi/acpica/hwsleep.c -@@ -179,7 +179,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) - - acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) - { -- acpi_status status; -+ acpi_status status = AE_OK; - struct acpi_bit_register_info *sleep_type_reg_info; - struct acpi_bit_register_info *sleep_enable_reg_info; - u32 pm1a_control; -@@ -192,10 +192,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) - * This is unclear from the ACPI Spec, but it is required - * by some machines. - */ -- status = acpi_get_sleep_type_data(ACPI_STATE_S0, -- &acpi_gbl_sleep_type_a, -- &acpi_gbl_sleep_type_b); -- if (ACPI_SUCCESS(status)) { -+ if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { - sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); - sleep_enable_reg_info = -@@ -216,9 +213,9 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) - - /* Insert the SLP_TYP bits */ - -- pm1a_control |= (acpi_gbl_sleep_type_a << -+ pm1a_control |= (acpi_gbl_sleep_type_a_s0 << - sleep_type_reg_info->bit_position); -- pm1b_control |= (acpi_gbl_sleep_type_b << -+ pm1b_control |= (acpi_gbl_sleep_type_b_s0 << - sleep_type_reg_info->bit_position); - - /* Write the control registers and ignore any errors */ -diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c -index 89b12afed564e..e4cde23a29061 100644 ---- a/drivers/acpi/acpica/hwxfsleep.c -+++ b/drivers/acpi/acpica/hwxfsleep.c -@@ -217,6 +217,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) - return_ACPI_STATUS(status); - } - -+ status = acpi_get_sleep_type_data(ACPI_STATE_S0, -+ &acpi_gbl_sleep_type_a_s0, -+ &acpi_gbl_sleep_type_b_s0); -+ if (ACPI_FAILURE(status)) { -+ acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID; -+ } -+ - /* Execute the _PTS method (Prepare To Sleep) */ - - arg_list.count = 1; -diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c -index dae91f906cea9..8afa85d6eb6a7 100644 ---- a/drivers/acpi/battery.c -+++ b/drivers/acpi/battery.c -@@ -169,7 +169,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery) - return 1; - - /* fallback to using design values for broken batteries */ -- if (battery->design_capacity == battery->capacity_now) -+ if (battery->design_capacity <= battery->capacity_now) - return 1; - - /* we don't do any sort of metric based on percentages */ -diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c -index bd482108310cf..3fbb17ecce2d5 100644 ---- a/drivers/acpi/cppc_acpi.c -+++ b/drivers/acpi/cppc_acpi.c -@@ -1011,7 +1011,14 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) - static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf) - { - struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum); -- struct cpc_register_resource *reg = &cpc_desc->cpc_regs[reg_idx]; -+ struct cpc_register_resource *reg; -+ -+ if (!cpc_desc) { -+ pr_debug("No CPC descriptor for CPU:%d\n", cpunum); -+ return -ENODEV; -+ } -+ -+ reg = &cpc_desc->cpc_regs[reg_idx]; - - if (CPC_IN_PCC(reg)) { - int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); -diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c -index a371f273f99dd..9cde299eba880 100644 ---- a/drivers/acpi/pmic/intel_pmic.c -+++ b/drivers/acpi/pmic/intel_pmic.c -@@ -211,31 +211,36 @@ static acpi_status intel_pmic_regs_handler(u32 function, - void *handler_context, void *region_context) - { - struct intel_pmic_opregion *opregion = region_context; -- int result = 0; -+ int result = -EINVAL; -+ -+ if (function == ACPI_WRITE) { -+ switch (address) { -+ case 0: -+ return AE_OK; -+ case 1: -+ opregion->ctx.addr |= (*value64 & 0xff) << 8; -+ return AE_OK; -+ case 2: -+ opregion->ctx.addr |= *value64 & 0xff; -+ return AE_OK; -+ case 3: -+ opregion->ctx.val = *value64 & 0xff; -+ return AE_OK; -+ case 4: -+ if (*value64) { -+ result = regmap_write(opregion->regmap, opregion->ctx.addr, -+ opregion->ctx.val); -+ } else { -+ result = regmap_read(opregion->regmap, opregion->ctx.addr, -+ &opregion->ctx.val); -+ } -+ opregion->ctx.addr = 0; -+ } -+ } - -- switch (address) { -- case 0: -- return AE_OK; -- case 1: -- opregion->ctx.addr |= (*value64 & 0xff) << 8; -- return AE_OK; -- case 2: -- opregion->ctx.addr |= *value64 & 0xff; -+ if (function == ACPI_READ && address == 3) { -+ *value64 = opregion->ctx.val; - return AE_OK; -- case 3: -- opregion->ctx.val = *value64 & 0xff; -- return AE_OK; -- case 4: -- if (*value64) { -- result = regmap_write(opregion->regmap, opregion->ctx.addr, -- opregion->ctx.val); -- } else { -- result = regmap_read(opregion->regmap, opregion->ctx.addr, -- &opregion->ctx.val); -- if (result == 0) -- *value64 = opregion->ctx.val; -- } -- memset(&opregion->ctx, 0x00, sizeof(opregion->ctx)); - } - - if (result < 0) { -diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c -index f0ed4414edb1f..c95eedd58f5bf 100644 ---- a/drivers/acpi/power.c -+++ b/drivers/acpi/power.c -@@ -52,7 +52,6 @@ struct acpi_power_resource { - u32 order; - unsigned int ref_count; - u8 state; -- bool wakeup_enabled; - struct mutex resource_lock; - struct list_head dependents; - }; -@@ -615,20 +614,19 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) - - list_for_each_entry(entry, list, node) { - struct acpi_power_resource *resource = entry->resource; -- int result; - u8 state; - - mutex_lock(&resource->resource_lock); - -- result = acpi_power_get_state(resource, &state); -- if (result) { -- mutex_unlock(&resource->resource_lock); -- return result; -- } -- if (state == ACPI_POWER_RESOURCE_STATE_ON) { -- resource->ref_count++; -- resource->wakeup_enabled = true; -- } -+ /* -+ * Make sure that the power resource state and its reference -+ * counter value are consistent with each other. -+ */ -+ if (!resource->ref_count && -+ !acpi_power_get_state(resource, &state) && -+ state == ACPI_POWER_RESOURCE_STATE_ON) -+ __acpi_power_off(resource); -+ - if (system_level > resource->system_level) - system_level = resource->system_level; - -@@ -711,7 +709,6 @@ int acpi_device_sleep_wake(struct acpi_device *dev, - */ - int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) - { -- struct acpi_power_resource_entry *entry; - int err = 0; - - if (!dev || !dev->wakeup.flags.valid) -@@ -722,26 +719,13 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) - if (dev->wakeup.prepare_count++) - goto out; - -- list_for_each_entry(entry, &dev->wakeup.resources, node) { -- struct acpi_power_resource *resource = entry->resource; -- -- mutex_lock(&resource->resource_lock); -- -- if (!resource->wakeup_enabled) { -- err = acpi_power_on_unlocked(resource); -- if (!err) -- resource->wakeup_enabled = true; -- } -- -- mutex_unlock(&resource->resource_lock); -- -- if (err) { -- dev_err(&dev->dev, -- "Cannot turn wakeup power resources on\n"); -- dev->wakeup.flags.valid = 0; -- goto out; -- } -+ err = acpi_power_on_list(&dev->wakeup.resources); -+ if (err) { -+ dev_err(&dev->dev, "Cannot turn on wakeup power resources\n"); -+ dev->wakeup.flags.valid = 0; -+ goto out; - } -+ - /* - * Passing 3 as the third argument below means the device may be - * put into arbitrary power state afterward. -@@ -771,39 +755,31 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) - - mutex_lock(&acpi_device_lock); - -- if (--dev->wakeup.prepare_count > 0) -+ /* Do nothing if wakeup power has not been enabled for this device. */ -+ if (dev->wakeup.prepare_count <= 0) - goto out; - -- /* -- * Executing the code below even if prepare_count is already zero when -- * the function is called may be useful, for example for initialisation. -- */ -- if (dev->wakeup.prepare_count < 0) -- dev->wakeup.prepare_count = 0; -+ if (--dev->wakeup.prepare_count > 0) -+ goto out; - - err = acpi_device_sleep_wake(dev, 0, 0, 0); - if (err) - goto out; - -+ /* -+ * All of the power resources in the list need to be turned off even if -+ * there are errors. -+ */ - list_for_each_entry(entry, &dev->wakeup.resources, node) { -- struct acpi_power_resource *resource = entry->resource; -- -- mutex_lock(&resource->resource_lock); -- -- if (resource->wakeup_enabled) { -- err = acpi_power_off_unlocked(resource); -- if (!err) -- resource->wakeup_enabled = false; -- } -- -- mutex_unlock(&resource->resource_lock); -+ int ret; - -- if (err) { -- dev_err(&dev->dev, -- "Cannot turn wakeup power resources off\n"); -- dev->wakeup.flags.valid = 0; -- break; -- } -+ ret = acpi_power_off(entry->resource); -+ if (ret && !err) -+ err = ret; -+ } -+ if (err) { -+ dev_err(&dev->dev, "Cannot turn off wakeup power resources\n"); -+ dev->wakeup.flags.valid = 0; - } - - out: -diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c -index e312ebaed8db4..781e312f45342 100644 ---- a/drivers/acpi/property.c -+++ b/drivers/acpi/property.c -@@ -1090,15 +1090,10 @@ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode) - /* All data nodes have parent pointer so just return that */ - return to_acpi_data_node(fwnode)->parent; - } else if (is_acpi_device_node(fwnode)) { -- acpi_handle handle, parent_handle; -+ struct device *dev = to_acpi_device_node(fwnode)->dev.parent; - -- handle = to_acpi_device_node(fwnode)->handle; -- if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) { -- struct acpi_device *adev; -- -- if (!acpi_bus_get_device(parent_handle, &adev)) -- return acpi_fwnode_handle(adev); -- } -+ if (dev) -+ return acpi_fwnode_handle(to_acpi_device(dev)); - } - - return NULL; -diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c -index ee78a210c6068..3c25ce8c95ba1 100644 ---- a/drivers/acpi/resource.c -+++ b/drivers/acpi/resource.c -@@ -16,6 +16,7 @@ - #include <linux/ioport.h> - #include <linux/slab.h> - #include <linux/irq.h> -+#include <linux/dmi.h> - - #ifdef CONFIG_X86 - #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) -@@ -380,9 +381,58 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) - } - EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); - -+static const struct dmi_system_id medion_laptop[] = { -+ { -+ .ident = "MEDION P15651", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), -+ DMI_MATCH(DMI_BOARD_NAME, "M15T"), -+ }, -+ }, -+ { -+ .ident = "MEDION S17405", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), -+ DMI_MATCH(DMI_BOARD_NAME, "M17T"), -+ }, -+ }, -+ { } -+}; -+ -+struct irq_override_cmp { -+ const struct dmi_system_id *system; -+ unsigned char irq; -+ unsigned char triggering; -+ unsigned char polarity; -+ unsigned char shareable; -+}; -+ -+static const struct irq_override_cmp skip_override_table[] = { -+ { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 }, -+}; -+ -+static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, -+ u8 shareable) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(skip_override_table); i++) { -+ const struct irq_override_cmp *entry = &skip_override_table[i]; -+ -+ if (dmi_check_system(entry->system) && -+ entry->irq == gsi && -+ entry->triggering == triggering && -+ entry->polarity == polarity && -+ entry->shareable == shareable) -+ return false; -+ } -+ -+ return true; -+} -+ - static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, - u8 triggering, u8 polarity, u8 shareable, -- bool legacy) -+ bool check_override) - { - int irq, p, t; - -@@ -401,7 +451,9 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, - * using extended IRQ descriptors we take the IRQ configuration - * from _CRS directly. - */ -- if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { -+ if (check_override && -+ acpi_dev_irq_override(gsi, triggering, polarity, shareable) && -+ !acpi_get_override_irq(gsi, &t, &p)) { - u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; - u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; - -diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c -index 962041148482c..6c0f7f4f7d1de 100644 ---- a/drivers/amba/bus.c -+++ b/drivers/amba/bus.c -@@ -377,9 +377,6 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent) - void __iomem *tmp; - int i, ret; - -- WARN_ON(dev->irq[0] == (unsigned int)-1); -- WARN_ON(dev->irq[1] == (unsigned int)-1); -- - ret = request_resource(parent, &dev->res); - if (ret) - goto err_out; -diff --git a/drivers/android/binder.c b/drivers/android/binder.c -index 9edacc8b97688..c75fb600740cc 100644 ---- a/drivers/android/binder.c -+++ b/drivers/android/binder.c -@@ -1870,7 +1870,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, - binder_dec_node(buffer->target_node, 1, 0); - - off_start_offset = ALIGN(buffer->data_size, sizeof(void *)); -- off_end_offset = is_failure ? failed_at : -+ off_end_offset = is_failure && failed_at ? failed_at : - off_start_offset + buffer->offsets_size; - for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; - buffer_offset += sizeof(binder_size_t)) { -@@ -1956,9 +1956,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, - binder_size_t fd_buf_size; - binder_size_t num_valid; - -- if (proc->tsk != current->group_leader) { -+ if (is_failure) { - /* -- * Nothing to do if running in sender context - * The fd fixups have not been applied so no - * fds need to be closed. - */ -@@ -2056,7 +2055,7 @@ static int binder_translate_binder(struct flat_binder_object *fp, - ret = -EINVAL; - goto done; - } -- if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { -+ if (security_binder_transfer_binder(proc->cred, target_proc->cred)) { - ret = -EPERM; - goto done; - } -@@ -2102,7 +2101,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, - proc->pid, thread->pid, fp->handle); - return -EINVAL; - } -- if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { -+ if (security_binder_transfer_binder(proc->cred, target_proc->cred)) { - ret = -EPERM; - goto done; - } -@@ -2190,7 +2189,7 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset, - ret = -EBADF; - goto err_fget; - } -- ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file); -+ ret = security_binder_transfer_file(proc->cred, target_proc->cred, file); - if (ret < 0) { - ret = -EPERM; - goto err_security; -@@ -2595,8 +2594,8 @@ static void binder_transaction(struct binder_proc *proc, - return_error_line = __LINE__; - goto err_invalid_target_handle; - } -- if (security_binder_transaction(proc->tsk, -- target_proc->tsk) < 0) { -+ if (security_binder_transaction(proc->cred, -+ target_proc->cred) < 0) { - return_error = BR_FAILED_REPLY; - return_error_param = -EPERM; - return_error_line = __LINE__; -@@ -2722,16 +2721,7 @@ static void binder_transaction(struct binder_proc *proc, - u32 secid; - size_t added_size; - -- /* -- * Arguably this should be the task's subjective LSM secid but -- * we can't reliably access the subjective creds of a task -- * other than our own so we must use the objective creds, which -- * are safe to access. The downside is that if a task is -- * temporarily overriding it's creds it will not be reflected -- * here; however, it isn't clear that binder would handle that -- * case well anyway. -- */ -- security_task_getsecid_obj(proc->tsk, &secid); -+ security_cred_getsecid(proc->cred, &secid); - ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); - if (ret) { - return_error = BR_FAILED_REPLY; -@@ -3185,6 +3175,7 @@ err_invalid_target_handle: - * binder_free_buf() - free the specified buffer - * @proc: binder proc that owns buffer - * @buffer: buffer to be freed -+ * @is_failure: failed to send transaction - * - * If buffer for an async transaction, enqueue the next async - * transaction from the node. -@@ -3194,7 +3185,7 @@ err_invalid_target_handle: - static void - binder_free_buf(struct binder_proc *proc, - struct binder_thread *thread, -- struct binder_buffer *buffer) -+ struct binder_buffer *buffer, bool is_failure) - { - binder_inner_proc_lock(proc); - if (buffer->transaction) { -@@ -3222,7 +3213,7 @@ binder_free_buf(struct binder_proc *proc, - binder_node_inner_unlock(buf_node); - } - trace_binder_transaction_buffer_release(buffer); -- binder_transaction_buffer_release(proc, thread, buffer, 0, false); -+ binder_transaction_buffer_release(proc, thread, buffer, 0, is_failure); - binder_alloc_free_buf(&proc->alloc, buffer); - } - -@@ -3424,7 +3415,7 @@ static int binder_thread_write(struct binder_proc *proc, - proc->pid, thread->pid, (u64)data_ptr, - buffer->debug_id, - buffer->transaction ? "active" : "finished"); -- binder_free_buf(proc, thread, buffer); -+ binder_free_buf(proc, thread, buffer, false); - break; - } - -@@ -4117,7 +4108,7 @@ retry: - buffer->transaction = NULL; - binder_cleanup_transaction(t, "fd fixups failed", - BR_FAILED_REPLY); -- binder_free_buf(proc, thread, buffer); -+ binder_free_buf(proc, thread, buffer, true); - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d %stransaction %d fd fixups failed %d/%d, line %d\n", - proc->pid, thread->pid, -@@ -4353,6 +4344,7 @@ static void binder_free_proc(struct binder_proc *proc) - } - binder_alloc_deferred_release(&proc->alloc); - put_task_struct(proc->tsk); -+ put_cred(proc->cred); - binder_stats_deleted(BINDER_STAT_PROC); - kfree(proc); - } -@@ -4430,23 +4422,20 @@ static int binder_thread_release(struct binder_proc *proc, - __release(&t->lock); - - /* -- * If this thread used poll, make sure we remove the waitqueue -- * from any epoll data structures holding it with POLLFREE. -- * waitqueue_active() is safe to use here because we're holding -- * the inner lock. -+ * If this thread used poll, make sure we remove the waitqueue from any -+ * poll data structures holding it. - */ -- if ((thread->looper & BINDER_LOOPER_STATE_POLL) && -- waitqueue_active(&thread->wait)) { -- wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE); -- } -+ if (thread->looper & BINDER_LOOPER_STATE_POLL) -+ wake_up_pollfree(&thread->wait); - - binder_inner_proc_unlock(thread->proc); - - /* -- * This is needed to avoid races between wake_up_poll() above and -- * and ep_remove_waitqueue() called for other reasons (eg the epoll file -- * descriptor being closed); ep_remove_waitqueue() holds an RCU read -- * lock, so we can be sure it's done after calling synchronize_rcu(). -+ * This is needed to avoid races between wake_up_pollfree() above and -+ * someone else removing the last entry from the queue for other reasons -+ * (e.g. ep_remove_wait_queue() being called due to an epoll file -+ * descriptor being closed). Such other users hold an RCU read lock, so -+ * we can be sure they're done after we call synchronize_rcu(). - */ - if (thread->looper & BINDER_LOOPER_STATE_POLL) - synchronize_rcu(); -@@ -4564,7 +4553,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp, - ret = -EBUSY; - goto out; - } -- ret = security_binder_set_context_mgr(proc->tsk); -+ ret = security_binder_set_context_mgr(proc->cred); - if (ret < 0) - goto out; - if (uid_valid(context->binder_context_mgr_uid)) { -@@ -5055,6 +5044,7 @@ static int binder_open(struct inode *nodp, struct file *filp) - spin_lock_init(&proc->outer_lock); - get_task_struct(current->group_leader); - proc->tsk = current->group_leader; -+ proc->cred = get_cred(filp->f_cred); - INIT_LIST_HEAD(&proc->todo); - init_waitqueue_head(&proc->freeze_wait); - proc->default_priority = task_nice(current); -diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h -index 402c4d4362a83..d6b6b8cb73465 100644 ---- a/drivers/android/binder_internal.h -+++ b/drivers/android/binder_internal.h -@@ -364,6 +364,9 @@ struct binder_ref { - * (invariant after initialized) - * @tsk task_struct for group_leader of process - * (invariant after initialized) -+ * @cred struct cred associated with the `struct file` -+ * in binder_open() -+ * (invariant after initialized) - * @deferred_work_node: element for binder_deferred_list - * (protected by binder_deferred_lock) - * @deferred_work: bitmap of deferred work to perform -@@ -426,6 +429,7 @@ struct binder_proc { - struct list_head waiting_threads; - int pid; - struct task_struct *tsk; -+ const struct cred *cred; - struct hlist_node deferred_work_node; - int deferred_work; - int outstanding_txns; -diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c -index 186cbf90c8ead..812731e80f8e0 100644 ---- a/drivers/ata/ahci.c -+++ b/drivers/ata/ahci.c -@@ -442,6 +442,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { - /* AMD */ - { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ - { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ -+ { PCI_VDEVICE(AMD, 0x7901), board_ahci_mobile }, /* AMD Green Sardine */ - /* AMD is using RAID class only for ahci controllers */ - { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, -diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c -index 5b3fa2cbe7223..395772fa39432 100644 ---- a/drivers/ata/libahci.c -+++ b/drivers/ata/libahci.c -@@ -2305,6 +2305,18 @@ int ahci_port_resume(struct ata_port *ap) - EXPORT_SYMBOL_GPL(ahci_port_resume); - - #ifdef CONFIG_PM -+static void ahci_handle_s2idle(struct ata_port *ap) -+{ -+ void __iomem *port_mmio = ahci_port_base(ap); -+ u32 devslp; -+ -+ if (pm_suspend_via_firmware()) -+ return; -+ devslp = readl(port_mmio + PORT_DEVSLP); -+ if ((devslp & PORT_DEVSLP_ADSE)) -+ ata_msleep(ap, devslp_idle_timeout); -+} -+ - static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) - { - const char *emsg = NULL; -@@ -2318,6 +2330,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) - ata_port_freeze(ap); - } - -+ if (acpi_storage_d3(ap->host->dev)) -+ ahci_handle_s2idle(ap); -+ - ahci_rpm_put_port(ap); - return rc; - } -diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c -index eed65311b5d1d..4d848cfc406fe 100644 ---- a/drivers/ata/libata-core.c -+++ b/drivers/ata/libata-core.c -@@ -2007,7 +2007,7 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log, - - retry: - ata_tf_init(dev, &tf); -- if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) && -+ if (ata_dma_enabled(dev) && ata_id_has_read_log_dma_ext(dev->id) && - !(dev->horkage & ATA_HORKAGE_NO_DMA_LOG)) { - tf.command = ATA_CMD_READ_LOG_DMA_EXT; - tf.protocol = ATA_PROT_DMA; -@@ -2031,8 +2031,9 @@ retry: - dev->horkage |= ATA_HORKAGE_NO_DMA_LOG; - goto retry; - } -- ata_dev_err(dev, "Read log page 0x%02x failed, Emask 0x%x\n", -- (unsigned int)page, err_mask); -+ ata_dev_err(dev, -+ "Read log 0x%02x page 0x%02x failed, Emask 0x%x\n", -+ (unsigned int)log, (unsigned int)page, err_mask); - } - - return err_mask; -@@ -2166,6 +2167,9 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev) - struct ata_port *ap = dev->link->ap; - unsigned int err_mask; - -+ if (!ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS)) -+ return; -+ - err_mask = ata_read_log_page(dev, - ATA_LOG_IDENTIFY_DEVICE, - ATA_LOG_SATA_SETTINGS, -@@ -2442,7 +2446,8 @@ static void ata_dev_config_devslp(struct ata_device *dev) - * Check device sleep capability. Get DevSlp timing variables - * from SATA Settings page of Identify Device Data Log. - */ -- if (!ata_id_has_devslp(dev->id)) -+ if (!ata_id_has_devslp(dev->id) || -+ !ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS)) - return; - - err_mask = ata_read_log_page(dev, -@@ -3851,6 +3856,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { - { "VRFDFC22048UCHC-TE*", NULL, ATA_HORKAGE_NODMA }, - /* Odd clown on sil3726/4726 PMPs */ - { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, -+ /* Similar story with ASMedia 1092 */ -+ { "ASMT109x- Config", NULL, ATA_HORKAGE_DISABLE }, - - /* Weird ATAPI devices */ - { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, -diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c -index bf9c4b6c5c3d4..1d4a6f1e88cd1 100644 ---- a/drivers/ata/libata-eh.c -+++ b/drivers/ata/libata-eh.c -@@ -93,6 +93,12 @@ static const unsigned long ata_eh_identify_timeouts[] = { - ULONG_MAX, - }; - -+static const unsigned long ata_eh_revalidate_timeouts[] = { -+ 15000, /* Some drives are slow to read log pages when waking-up */ -+ 15000, /* combined time till here is enough even for media access */ -+ ULONG_MAX, -+}; -+ - static const unsigned long ata_eh_flush_timeouts[] = { - 15000, /* be generous with flush */ - 15000, /* ditto */ -@@ -129,6 +135,8 @@ static const struct ata_eh_cmd_timeout_ent - ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = { - { .commands = CMDS(ATA_CMD_ID_ATA, ATA_CMD_ID_ATAPI), - .timeouts = ata_eh_identify_timeouts, }, -+ { .commands = CMDS(ATA_CMD_READ_LOG_EXT, ATA_CMD_READ_LOG_DMA_EXT), -+ .timeouts = ata_eh_revalidate_timeouts, }, - { .commands = CMDS(ATA_CMD_READ_NATIVE_MAX, ATA_CMD_READ_NATIVE_MAX_EXT), - .timeouts = ata_eh_other_timeouts, }, - { .commands = CMDS(ATA_CMD_SET_MAX, ATA_CMD_SET_MAX_EXT), -diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c -index 1fb4611f7eeb9..10303611d17b9 100644 ---- a/drivers/ata/libata-scsi.c -+++ b/drivers/ata/libata-scsi.c -@@ -2826,8 +2826,19 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) - goto invalid_fld; - } - -- if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0) -- tf->protocol = ATA_PROT_NCQ_NODATA; -+ if ((cdb[2 + cdb_offset] & 0x3) == 0) { -+ /* -+ * When T_LENGTH is zero (No data is transferred), dir should -+ * be DMA_NONE. -+ */ -+ if (scmd->sc_data_direction != DMA_NONE) { -+ fp = 2 + cdb_offset; -+ goto invalid_fld; -+ } -+ -+ if (ata_is_ncq(tf->protocol)) -+ tf->protocol = ATA_PROT_NCQ_NODATA; -+ } - - /* enable LBA */ - tf->flags |= ATA_TFLAG_LBA; -diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c -index e5838b23c9e0a..3b31a4f596d86 100644 ---- a/drivers/ata/sata_fsl.c -+++ b/drivers/ata/sata_fsl.c -@@ -1394,6 +1394,14 @@ static int sata_fsl_init_controller(struct ata_host *host) - return 0; - } - -+static void sata_fsl_host_stop(struct ata_host *host) -+{ -+ struct sata_fsl_host_priv *host_priv = host->private_data; -+ -+ iounmap(host_priv->hcr_base); -+ kfree(host_priv); -+} -+ - /* - * scsi mid-layer and libata interface structures - */ -@@ -1426,6 +1434,8 @@ static struct ata_port_operations sata_fsl_ops = { - .port_start = sata_fsl_port_start, - .port_stop = sata_fsl_port_stop, - -+ .host_stop = sata_fsl_host_stop, -+ - .pmp_attach = sata_fsl_pmp_attach, - .pmp_detach = sata_fsl_pmp_detach, - }; -@@ -1480,9 +1490,9 @@ static int sata_fsl_probe(struct platform_device *ofdev) - host_priv->ssr_base = ssr_base; - host_priv->csr_base = csr_base; - -- irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); -- if (!irq) { -- dev_err(&ofdev->dev, "invalid irq from platform\n"); -+ irq = platform_get_irq(ofdev, 0); -+ if (irq < 0) { -+ retval = irq; - goto error_exit_with_cleanup; - } - host_priv->irq = irq; -@@ -1557,10 +1567,6 @@ static int sata_fsl_remove(struct platform_device *ofdev) - - ata_host_detach(host); - -- irq_dispose_mapping(host_priv->irq); -- iounmap(host_priv->hcr_base); -- kfree(host_priv); -- - return 0; - } - -diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c -index 1e69cc6d21a0d..ed58083499907 100644 ---- a/drivers/auxdisplay/ht16k33.c -+++ b/drivers/auxdisplay/ht16k33.c -@@ -219,6 +219,15 @@ static const struct backlight_ops ht16k33_bl_ops = { - .check_fb = ht16k33_bl_check_fb, - }; - -+/* -+ * Blank events will be passed to the actual device handling the backlight when -+ * we return zero here. -+ */ -+static int ht16k33_blank(int blank, struct fb_info *info) -+{ -+ return 0; -+} -+ - static int ht16k33_mmap(struct fb_info *info, struct vm_area_struct *vma) - { - struct ht16k33_priv *priv = info->par; -@@ -231,6 +240,7 @@ static const struct fb_ops ht16k33_fb_ops = { - .owner = THIS_MODULE, - .fb_read = fb_sys_read, - .fb_write = fb_sys_write, -+ .fb_blank = ht16k33_blank, - .fb_fillrect = sys_fillrect, - .fb_copyarea = sys_copyarea, - .fb_imageblit = sys_imageblit, -@@ -413,6 +423,33 @@ static int ht16k33_probe(struct i2c_client *client, - if (err) - return err; - -+ /* Backlight */ -+ memset(&bl_props, 0, sizeof(struct backlight_properties)); -+ bl_props.type = BACKLIGHT_RAW; -+ bl_props.max_brightness = MAX_BRIGHTNESS; -+ -+ bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl", -+ &client->dev, priv, -+ &ht16k33_bl_ops, &bl_props); -+ if (IS_ERR(bl)) { -+ dev_err(&client->dev, "failed to register backlight\n"); -+ return PTR_ERR(bl); -+ } -+ -+ err = of_property_read_u32(node, "default-brightness-level", -+ &dft_brightness); -+ if (err) { -+ dft_brightness = MAX_BRIGHTNESS; -+ } else if (dft_brightness > MAX_BRIGHTNESS) { -+ dev_warn(&client->dev, -+ "invalid default brightness level: %u, using %u\n", -+ dft_brightness, MAX_BRIGHTNESS); -+ dft_brightness = MAX_BRIGHTNESS; -+ } -+ -+ bl->props.brightness = dft_brightness; -+ ht16k33_bl_update_status(bl); -+ - /* Framebuffer (2 bytes per column) */ - BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE); - fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL); -@@ -445,6 +482,7 @@ static int ht16k33_probe(struct i2c_client *client, - fbdev->info->screen_size = HT16K33_FB_SIZE; - fbdev->info->fix = ht16k33_fb_fix; - fbdev->info->var = ht16k33_fb_var; -+ fbdev->info->bl_dev = bl; - fbdev->info->pseudo_palette = NULL; - fbdev->info->flags = FBINFO_FLAG_DEFAULT; - fbdev->info->par = priv; -@@ -460,34 +498,6 @@ static int ht16k33_probe(struct i2c_client *client, - goto err_fbdev_unregister; - } - -- /* Backlight */ -- memset(&bl_props, 0, sizeof(struct backlight_properties)); -- bl_props.type = BACKLIGHT_RAW; -- bl_props.max_brightness = MAX_BRIGHTNESS; -- -- bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl", -- &client->dev, priv, -- &ht16k33_bl_ops, &bl_props); -- if (IS_ERR(bl)) { -- dev_err(&client->dev, "failed to register backlight\n"); -- err = PTR_ERR(bl); -- goto err_fbdev_unregister; -- } -- -- err = of_property_read_u32(node, "default-brightness-level", -- &dft_brightness); -- if (err) { -- dft_brightness = MAX_BRIGHTNESS; -- } else if (dft_brightness > MAX_BRIGHTNESS) { -- dev_warn(&client->dev, -- "invalid default brightness level: %u, using %u\n", -- dft_brightness, MAX_BRIGHTNESS); -- dft_brightness = MAX_BRIGHTNESS; -- } -- -- bl->props.brightness = dft_brightness; -- ht16k33_bl_update_status(bl); -- - ht16k33_fb_queue(priv); - return 0; - -diff --git a/drivers/auxdisplay/img-ascii-lcd.c b/drivers/auxdisplay/img-ascii-lcd.c -index 1cce409ce5cac..e33ce0151cdfd 100644 ---- a/drivers/auxdisplay/img-ascii-lcd.c -+++ b/drivers/auxdisplay/img-ascii-lcd.c -@@ -280,6 +280,16 @@ static int img_ascii_lcd_display(struct img_ascii_lcd_ctx *ctx, - if (msg[count - 1] == '\n') - count--; - -+ if (!count) { -+ /* clear the LCD */ -+ devm_kfree(&ctx->pdev->dev, ctx->message); -+ ctx->message = NULL; -+ ctx->message_len = 0; -+ memset(ctx->curr, ' ', ctx->cfg->num_chars); -+ ctx->cfg->update(ctx); -+ return 0; -+ } -+ - new_msg = devm_kmalloc(&ctx->pdev->dev, count + 1, GFP_KERNEL); - if (!new_msg) - return -ENOMEM; -diff --git a/drivers/base/component.c b/drivers/base/component.c -index 5e79299f6c3ff..870485cbbb87c 100644 ---- a/drivers/base/component.c -+++ b/drivers/base/component.c -@@ -246,7 +246,7 @@ static int try_to_bring_up_master(struct master *master, - return 0; - } - -- if (!devres_open_group(master->parent, NULL, GFP_KERNEL)) -+ if (!devres_open_group(master->parent, master, GFP_KERNEL)) - return -ENOMEM; - - /* Found all components */ -@@ -258,6 +258,7 @@ static int try_to_bring_up_master(struct master *master, - return ret; - } - -+ devres_close_group(master->parent, NULL); - master->bound = true; - return 1; - } -@@ -282,7 +283,7 @@ static void take_down_master(struct master *master) - { - if (master->bound) { - master->ops->unbind(master->parent); -- devres_release_group(master->parent, NULL); -+ devres_release_group(master->parent, master); - master->bound = false; - } - } -diff --git a/drivers/base/core.c b/drivers/base/core.c -index 249da496581a0..63577de268565 100644 ---- a/drivers/base/core.c -+++ b/drivers/base/core.c -@@ -821,9 +821,7 @@ struct device_link *device_link_add(struct device *consumer, - dev_bus_name(supplier), dev_name(supplier), - dev_bus_name(consumer), dev_name(consumer)); - if (device_register(&link->link_dev)) { -- put_device(consumer); -- put_device(supplier); -- kfree(link); -+ put_device(&link->link_dev); - link = NULL; - goto out; - } -diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c -index bdbedc6660a87..ef904b8b112e6 100644 ---- a/drivers/base/firmware_loader/main.c -+++ b/drivers/base/firmware_loader/main.c -@@ -100,12 +100,15 @@ static struct firmware_cache fw_cache; - extern struct builtin_fw __start_builtin_fw[]; - extern struct builtin_fw __end_builtin_fw[]; - --static void fw_copy_to_prealloc_buf(struct firmware *fw, -+static bool fw_copy_to_prealloc_buf(struct firmware *fw, - void *buf, size_t size) - { -- if (!buf || size < fw->size) -- return; -+ if (!buf) -+ return true; -+ if (size < fw->size) -+ return false; - memcpy(buf, fw->data, fw->size); -+ return true; - } - - static bool fw_get_builtin_firmware(struct firmware *fw, const char *name, -@@ -117,9 +120,7 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name, - if (strcmp(name, b_fw->name) == 0) { - fw->size = b_fw->size; - fw->data = b_fw->data; -- fw_copy_to_prealloc_buf(fw, buf, size); -- -- return true; -+ return fw_copy_to_prealloc_buf(fw, buf, size); - } - } - -diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c -index cbea78e79f3df..a7fdd86fad057 100644 ---- a/drivers/base/power/main.c -+++ b/drivers/base/power/main.c -@@ -711,6 +711,7 @@ static void dpm_noirq_resume_devices(pm_message_t state) - dev = to_device(dpm_noirq_list.next); - get_device(dev); - list_move_tail(&dev->power.entry, &dpm_late_early_list); -+ - mutex_unlock(&dpm_list_mtx); - - if (!is_async(dev)) { -@@ -725,8 +726,9 @@ static void dpm_noirq_resume_devices(pm_message_t state) - } - } - -- mutex_lock(&dpm_list_mtx); - put_device(dev); -+ -+ mutex_lock(&dpm_list_mtx); - } - mutex_unlock(&dpm_list_mtx); - async_synchronize_full(); -@@ -852,6 +854,7 @@ void dpm_resume_early(pm_message_t state) - dev = to_device(dpm_late_early_list.next); - get_device(dev); - list_move_tail(&dev->power.entry, &dpm_suspended_list); -+ - mutex_unlock(&dpm_list_mtx); - - if (!is_async(dev)) { -@@ -865,8 +868,10 @@ void dpm_resume_early(pm_message_t state) - pm_dev_err(dev, state, " early", error); - } - } -- mutex_lock(&dpm_list_mtx); -+ - put_device(dev); -+ -+ mutex_lock(&dpm_list_mtx); - } - mutex_unlock(&dpm_list_mtx); - async_synchronize_full(); -@@ -1029,7 +1034,12 @@ void dpm_resume(pm_message_t state) - } - if (!list_empty(&dev->power.entry)) - list_move_tail(&dev->power.entry, &dpm_prepared_list); -+ -+ mutex_unlock(&dpm_list_mtx); -+ - put_device(dev); -+ -+ mutex_lock(&dpm_list_mtx); - } - mutex_unlock(&dpm_list_mtx); - async_synchronize_full(); -@@ -1051,7 +1061,7 @@ static void device_complete(struct device *dev, pm_message_t state) - const char *info = NULL; - - if (dev->power.syscore) -- return; -+ goto out; - - device_lock(dev); - -@@ -1081,6 +1091,7 @@ static void device_complete(struct device *dev, pm_message_t state) - - device_unlock(dev); - -+out: - pm_runtime_put(dev); - } - -@@ -1106,14 +1117,16 @@ void dpm_complete(pm_message_t state) - get_device(dev); - dev->power.is_prepared = false; - list_move(&dev->power.entry, &list); -+ - mutex_unlock(&dpm_list_mtx); - - trace_device_pm_callback_start(dev, "", state.event); - device_complete(dev, state); - trace_device_pm_callback_end(dev, 0); - -- mutex_lock(&dpm_list_mtx); - put_device(dev); -+ -+ mutex_lock(&dpm_list_mtx); - } - list_splice(&list, &dpm_list); - mutex_unlock(&dpm_list_mtx); -@@ -1298,17 +1311,21 @@ static int dpm_noirq_suspend_devices(pm_message_t state) - error = device_suspend_noirq(dev); - - mutex_lock(&dpm_list_mtx); -+ - if (error) { - pm_dev_err(dev, state, " noirq", error); - dpm_save_failed_dev(dev_name(dev)); -- put_device(dev); -- break; -- } -- if (!list_empty(&dev->power.entry)) -+ } else if (!list_empty(&dev->power.entry)) { - list_move(&dev->power.entry, &dpm_noirq_list); -+ } -+ -+ mutex_unlock(&dpm_list_mtx); -+ - put_device(dev); - -- if (async_error) -+ mutex_lock(&dpm_list_mtx); -+ -+ if (error || async_error) - break; - } - mutex_unlock(&dpm_list_mtx); -@@ -1475,23 +1492,28 @@ int dpm_suspend_late(pm_message_t state) - struct device *dev = to_device(dpm_suspended_list.prev); - - get_device(dev); -+ - mutex_unlock(&dpm_list_mtx); - - error = device_suspend_late(dev); - - mutex_lock(&dpm_list_mtx); -+ - if (!list_empty(&dev->power.entry)) - list_move(&dev->power.entry, &dpm_late_early_list); - - if (error) { - pm_dev_err(dev, state, " late", error); - dpm_save_failed_dev(dev_name(dev)); -- put_device(dev); -- break; - } -+ -+ mutex_unlock(&dpm_list_mtx); -+ - put_device(dev); - -- if (async_error) -+ mutex_lock(&dpm_list_mtx); -+ -+ if (error || async_error) - break; - } - mutex_unlock(&dpm_list_mtx); -@@ -1751,21 +1773,27 @@ int dpm_suspend(pm_message_t state) - struct device *dev = to_device(dpm_prepared_list.prev); - - get_device(dev); -+ - mutex_unlock(&dpm_list_mtx); - - error = device_suspend(dev); - - mutex_lock(&dpm_list_mtx); -+ - if (error) { - pm_dev_err(dev, state, "", error); - dpm_save_failed_dev(dev_name(dev)); -- put_device(dev); -- break; -- } -- if (!list_empty(&dev->power.entry)) -+ } else if (!list_empty(&dev->power.entry)) { - list_move(&dev->power.entry, &dpm_suspended_list); -+ } -+ -+ mutex_unlock(&dpm_list_mtx); -+ - put_device(dev); -- if (async_error) -+ -+ mutex_lock(&dpm_list_mtx); -+ -+ if (error || async_error) - break; - } - mutex_unlock(&dpm_list_mtx); -@@ -1794,9 +1822,6 @@ static int device_prepare(struct device *dev, pm_message_t state) - int (*callback)(struct device *) = NULL; - int ret = 0; - -- if (dev->power.syscore) -- return 0; -- - /* - * If a device's parent goes into runtime suspend at the wrong time, - * it won't be possible to resume the device. To prevent this we -@@ -1805,6 +1830,9 @@ static int device_prepare(struct device *dev, pm_message_t state) - */ - pm_runtime_get_noresume(dev); - -+ if (dev->power.syscore) -+ return 0; -+ - device_lock(dev); - - dev->power.wakeup_path = false; -@@ -1882,6 +1910,7 @@ int dpm_prepare(pm_message_t state) - struct device *dev = to_device(dpm_list.next); - - get_device(dev); -+ - mutex_unlock(&dpm_list_mtx); - - trace_device_pm_callback_start(dev, "", state.event); -@@ -1889,21 +1918,23 @@ int dpm_prepare(pm_message_t state) - trace_device_pm_callback_end(dev, error); - - mutex_lock(&dpm_list_mtx); -- if (error) { -- if (error == -EAGAIN) { -- put_device(dev); -- error = 0; -- continue; -- } -+ -+ if (!error) { -+ dev->power.is_prepared = true; -+ if (!list_empty(&dev->power.entry)) -+ list_move_tail(&dev->power.entry, &dpm_prepared_list); -+ } else if (error == -EAGAIN) { -+ error = 0; -+ } else { - dev_info(dev, "not prepared for power transition: code %d\n", - error); -- put_device(dev); -- break; - } -- dev->power.is_prepared = true; -- if (!list_empty(&dev->power.entry)) -- list_move_tail(&dev->power.entry, &dpm_prepared_list); -+ -+ mutex_unlock(&dpm_list_mtx); -+ - put_device(dev); -+ -+ mutex_lock(&dpm_list_mtx); - } - mutex_unlock(&dpm_list_mtx); - trace_suspend_resume(TPS("dpm_prepare"), state.event, false); -diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c -index a093644ac39fb..aab48b292a3bb 100644 ---- a/drivers/block/ataflop.c -+++ b/drivers/block/ataflop.c -@@ -298,6 +298,7 @@ static struct atari_floppy_struct { - disk change detection) */ - int flags; /* flags */ - struct gendisk *disk[NUM_DISK_MINORS]; -+ bool registered[NUM_DISK_MINORS]; - int ref; - int type; - struct blk_mq_tag_set tag_set; -@@ -456,10 +457,20 @@ static DEFINE_TIMER(fd_timer, check_change); - - static void fd_end_request_cur(blk_status_t err) - { -+ DPRINT(("fd_end_request_cur(), bytes %d of %d\n", -+ blk_rq_cur_bytes(fd_request), -+ blk_rq_bytes(fd_request))); -+ - if (!blk_update_request(fd_request, err, - blk_rq_cur_bytes(fd_request))) { -+ DPRINT(("calling __blk_mq_end_request()\n")); - __blk_mq_end_request(fd_request, err); - fd_request = NULL; -+ } else { -+ /* requeue rest of request */ -+ DPRINT(("calling blk_mq_requeue_request()\n")); -+ blk_mq_requeue_request(fd_request, true); -+ fd_request = NULL; - } - } - -@@ -653,9 +664,6 @@ static inline void copy_buffer(void *from, void *to) - *p2++ = *p1++; - } - -- -- -- - /* General Interrupt Handling */ - - static void (*FloppyIRQHandler)( int status ) = NULL; -@@ -700,12 +708,21 @@ static void fd_error( void ) - if (fd_request->error_count >= MAX_ERRORS) { - printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); - fd_end_request_cur(BLK_STS_IOERR); -+ finish_fdc(); -+ return; - } - else if (fd_request->error_count == RECALIBRATE_ERRORS) { - printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); - if (SelectedDrive != -1) - SUD.track = -1; - } -+ /* need to re-run request to recalibrate */ -+ atari_disable_irq( IRQ_MFP_FDC ); -+ -+ setup_req_params( SelectedDrive ); -+ do_fd_action( SelectedDrive ); -+ -+ atari_enable_irq( IRQ_MFP_FDC ); - } - - -@@ -732,8 +749,10 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) - if (type) { - type--; - if (type >= NUM_DISK_MINORS || -- minor2disktype[type].drive_types > DriveType) -+ minor2disktype[type].drive_types > DriveType) { -+ finish_fdc(); - return -EINVAL; -+ } - } - - q = unit[drive].disk[type]->queue; -@@ -751,6 +770,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) - } - - if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { -+ finish_fdc(); - ret = -EINVAL; - goto out; - } -@@ -791,6 +811,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) - - wait_for_completion(&format_wait); - -+ finish_fdc(); - ret = FormatError ? -EIO : 0; - out: - blk_mq_unquiesce_queue(q); -@@ -825,6 +846,7 @@ static void do_fd_action( int drive ) - else { - /* all sectors finished */ - fd_end_request_cur(BLK_STS_OK); -+ finish_fdc(); - return; - } - } -@@ -1229,6 +1251,7 @@ static void fd_rwsec_done1(int status) - else { - /* all sectors finished */ - fd_end_request_cur(BLK_STS_OK); -+ finish_fdc(); - } - return; - -@@ -1350,7 +1373,7 @@ static void fd_times_out(struct timer_list *unused) - - static void finish_fdc( void ) - { -- if (!NeedSeek) { -+ if (!NeedSeek || !stdma_is_locked_by(floppy_irq)) { - finish_fdc_done( 0 ); - } - else { -@@ -1385,7 +1408,8 @@ static void finish_fdc_done( int dummy ) - start_motor_off_timer(); - - local_irq_save(flags); -- stdma_release(); -+ if (stdma_is_locked_by(floppy_irq)) -+ stdma_release(); - local_irq_restore(flags); - - DPRINT(("finish_fdc() finished\n")); -@@ -1475,15 +1499,6 @@ static void setup_req_params( int drive ) - ReqTrack, ReqSector, (unsigned long)ReqData )); - } - --static void ataflop_commit_rqs(struct blk_mq_hw_ctx *hctx) --{ -- spin_lock_irq(&ataflop_lock); -- atari_disable_irq(IRQ_MFP_FDC); -- finish_fdc(); -- atari_enable_irq(IRQ_MFP_FDC); -- spin_unlock_irq(&ataflop_lock); --} -- - static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) - { -@@ -1491,6 +1506,10 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, - int drive = floppy - unit; - int type = floppy->type; - -+ DPRINT(("Queue request: drive %d type %d sectors %d of %d last %d\n", -+ drive, type, blk_rq_cur_sectors(bd->rq), -+ blk_rq_sectors(bd->rq), bd->last)); -+ - spin_lock_irq(&ataflop_lock); - if (fd_request) { - spin_unlock_irq(&ataflop_lock); -@@ -1511,6 +1530,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, - /* drive not connected */ - printk(KERN_ERR "Unknown Device: fd%d\n", drive ); - fd_end_request_cur(BLK_STS_IOERR); -+ stdma_release(); - goto out; - } - -@@ -1527,11 +1547,13 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, - if (--type >= NUM_DISK_MINORS) { - printk(KERN_WARNING "fd%d: invalid disk format", drive ); - fd_end_request_cur(BLK_STS_IOERR); -+ stdma_release(); - goto out; - } - if (minor2disktype[type].drive_types > DriveType) { - printk(KERN_WARNING "fd%d: unsupported disk format", drive ); - fd_end_request_cur(BLK_STS_IOERR); -+ stdma_release(); - goto out; - } - type = minor2disktype[type].index; -@@ -1550,8 +1572,6 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, - setup_req_params( drive ); - do_fd_action( drive ); - -- if (bd->last) -- finish_fdc(); - atari_enable_irq( IRQ_MFP_FDC ); - - out: -@@ -1634,6 +1654,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, - /* what if type > 0 here? Overwrite specified entry ? */ - if (type) { - /* refuse to re-set a predefined type for now */ -+ finish_fdc(); - return -EINVAL; - } - -@@ -1701,8 +1722,10 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, - - /* sanity check */ - if (setprm.track != dtp->blocks/dtp->spt/2 || -- setprm.head != 2) -+ setprm.head != 2) { -+ finish_fdc(); - return -EINVAL; -+ } - - UDT = dtp; - set_capacity(disk, UDT->blocks); -@@ -1962,7 +1985,6 @@ static const struct block_device_operations floppy_fops = { - - static const struct blk_mq_ops ataflop_mq_ops = { - .queue_rq = ataflop_queue_rq, -- .commit_rqs = ataflop_commit_rqs, - }; - - static int ataflop_alloc_disk(unsigned int drive, unsigned int type) -@@ -1986,8 +2008,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type) - return 0; - } - --static DEFINE_MUTEX(ataflop_probe_lock); -- - static void ataflop_probe(dev_t dev) - { - int drive = MINOR(dev) & 3; -@@ -1998,12 +2018,46 @@ static void ataflop_probe(dev_t dev) - - if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS) - return; -- mutex_lock(&ataflop_probe_lock); - if (!unit[drive].disk[type]) { -- if (ataflop_alloc_disk(drive, type) == 0) -+ if (ataflop_alloc_disk(drive, type) == 0) { - add_disk(unit[drive].disk[type]); -+ unit[drive].registered[type] = true; -+ } -+ } -+} -+ -+static void atari_floppy_cleanup(void) -+{ -+ int i; -+ int type; -+ -+ for (i = 0; i < FD_MAX_UNITS; i++) { -+ for (type = 0; type < NUM_DISK_MINORS; type++) { -+ if (!unit[i].disk[type]) -+ continue; -+ del_gendisk(unit[i].disk[type]); -+ blk_cleanup_queue(unit[i].disk[type]->queue); -+ put_disk(unit[i].disk[type]); -+ } -+ blk_mq_free_tag_set(&unit[i].tag_set); -+ } -+ -+ del_timer_sync(&fd_timer); -+ atari_stram_free(DMABuffer); -+} -+ -+static void atari_cleanup_floppy_disk(struct atari_floppy_struct *fs) -+{ -+ int type; -+ -+ for (type = 0; type < NUM_DISK_MINORS; type++) { -+ if (!fs->disk[type]) -+ continue; -+ if (fs->registered[type]) -+ del_gendisk(fs->disk[type]); -+ blk_cleanup_disk(fs->disk[type]); - } -- mutex_unlock(&ataflop_probe_lock); -+ blk_mq_free_tag_set(&fs->tag_set); - } - - static int __init atari_floppy_init (void) -@@ -2015,11 +2069,6 @@ static int __init atari_floppy_init (void) - /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */ - return -ENODEV; - -- mutex_lock(&ataflop_probe_lock); -- ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe); -- if (ret) -- goto out_unlock; -- - for (i = 0; i < FD_MAX_UNITS; i++) { - memset(&unit[i].tag_set, 0, sizeof(unit[i].tag_set)); - unit[i].tag_set.ops = &ataflop_mq_ops; -@@ -2065,6 +2114,7 @@ static int __init atari_floppy_init (void) - unit[i].track = -1; - unit[i].flags = 0; - add_disk(unit[i].disk[0]); -+ unit[i].registered[0] = true; - } - - printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n", -@@ -2072,18 +2122,17 @@ static int __init atari_floppy_init (void) - UseTrackbuffer ? "" : "no "); - config_types(); - -- return 0; -+ ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe); -+ if (ret) { -+ printk(KERN_ERR "atari_floppy_init: cannot register block device\n"); -+ atari_floppy_cleanup(); -+ } -+ return ret; - - err: -- while (--i >= 0) { -- blk_cleanup_queue(unit[i].disk[0]->queue); -- put_disk(unit[i].disk[0]); -- blk_mq_free_tag_set(&unit[i].tag_set); -- } -+ while (--i >= 0) -+ atari_cleanup_floppy_disk(&unit[i]); - -- unregister_blkdev(FLOPPY_MAJOR, "fd"); --out_unlock: -- mutex_unlock(&ataflop_probe_lock); - return ret; - } - -@@ -2128,22 +2177,8 @@ __setup("floppy=", atari_floppy_setup); - - static void __exit atari_floppy_exit(void) - { -- int i, type; -- -- for (i = 0; i < FD_MAX_UNITS; i++) { -- for (type = 0; type < NUM_DISK_MINORS; type++) { -- if (!unit[i].disk[type]) -- continue; -- del_gendisk(unit[i].disk[type]); -- blk_cleanup_queue(unit[i].disk[type]->queue); -- put_disk(unit[i].disk[type]); -- } -- blk_mq_free_tag_set(&unit[i].tag_set); -- } - unregister_blkdev(FLOPPY_MAJOR, "fd"); -- -- del_timer_sync(&fd_timer); -- atari_stram_free( DMABuffer ); -+ atari_floppy_cleanup(); - } - - module_init(atari_floppy_init) -diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c -index fef79ea52e3ed..fb2aafabfebc1 100644 ---- a/drivers/block/floppy.c -+++ b/drivers/block/floppy.c -@@ -4478,6 +4478,7 @@ static const struct blk_mq_ops floppy_mq_ops = { - }; - - static struct platform_device floppy_device[N_DRIVE]; -+static bool registered[N_DRIVE]; - - static bool floppy_available(int drive) - { -@@ -4693,6 +4694,8 @@ static int __init do_floppy_init(void) - if (err) - goto out_remove_drives; - -+ registered[drive] = true; -+ - device_add_disk(&floppy_device[drive].dev, disks[drive][0], - NULL); - } -@@ -4703,7 +4706,8 @@ out_remove_drives: - while (drive--) { - if (floppy_available(drive)) { - del_gendisk(disks[drive][0]); -- platform_device_unregister(&floppy_device[drive]); -+ if (registered[drive]) -+ platform_device_unregister(&floppy_device[drive]); - } - } - out_release_dma: -@@ -4946,7 +4950,8 @@ static void __exit floppy_module_exit(void) - if (disks[drive][i]) - del_gendisk(disks[drive][i]); - } -- platform_device_unregister(&floppy_device[drive]); -+ if (registered[drive]) -+ platform_device_unregister(&floppy_device[drive]); - } - for (i = 0; i < ARRAY_SIZE(floppy_type); i++) { - if (disks[drive][i]) -diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 7bf4686af774e..c00ae30fde89e 100644 ---- a/drivers/block/loop.c -+++ b/drivers/block/loop.c -@@ -272,19 +272,6 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) - blk_mq_unfreeze_queue(lo->lo_queue); - } - --/** -- * loop_validate_block_size() - validates the passed in block size -- * @bsize: size to validate -- */ --static int --loop_validate_block_size(unsigned short bsize) --{ -- if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) -- return -EINVAL; -- -- return 0; --} -- - /** - * loop_set_size() - sets device size and notifies userspace - * @lo: struct loop_device to set the size for -@@ -1236,7 +1223,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, - } - - if (config->block_size) { -- error = loop_validate_block_size(config->block_size); -+ error = blk_validate_block_size(config->block_size); - if (error) - goto out_unlock; - } -@@ -1759,7 +1746,7 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) - if (lo->lo_state != Lo_bound) - return -ENXIO; - -- err = loop_validate_block_size(arg); -+ err = blk_validate_block_size(arg); - if (err) - return err; - -@@ -2442,7 +2429,7 @@ static int loop_control_remove(int idx) - int ret; - - if (idx < 0) { -- pr_warn("deleting an unspecified loop device is not supported.\n"); -+ pr_warn_once("deleting an unspecified loop device is not supported.\n"); - return -EINVAL; - } - -diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c -index 1183f7872b713..577c7dba5d78d 100644 ---- a/drivers/block/nbd.c -+++ b/drivers/block/nbd.c -@@ -122,10 +122,10 @@ struct nbd_device { - struct work_struct remove_work; - - struct list_head list; -- struct task_struct *task_recv; - struct task_struct *task_setup; - - unsigned long flags; -+ pid_t pid; /* pid of nbd-client, if attached */ - - char *backend; - }; -@@ -217,7 +217,7 @@ static ssize_t pid_show(struct device *dev, - struct gendisk *disk = dev_to_disk(dev); - struct nbd_device *nbd = (struct nbd_device *)disk->private_data; - -- return sprintf(buf, "%d\n", task_pid_nr(nbd->task_recv)); -+ return sprintf(buf, "%d\n", nbd->pid); - } - - static const struct device_attribute pid_attr = { -@@ -329,7 +329,7 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, - nbd->config->bytesize = bytesize; - nbd->config->blksize_bits = __ffs(blksize); - -- if (!nbd->task_recv) -+ if (!nbd->pid) - return 0; - - if (nbd->config->flags & NBD_FLAG_SEND_TRIM) { -@@ -1241,7 +1241,7 @@ static void nbd_config_put(struct nbd_device *nbd) - if (test_and_clear_bit(NBD_RT_HAS_PID_FILE, - &config->runtime_flags)) - device_remove_file(disk_to_dev(nbd->disk), &pid_attr); -- nbd->task_recv = NULL; -+ nbd->pid = 0; - if (test_and_clear_bit(NBD_RT_HAS_BACKEND_FILE, - &config->runtime_flags)) { - device_remove_file(disk_to_dev(nbd->disk), &backend_attr); -@@ -1282,7 +1282,7 @@ static int nbd_start_device(struct nbd_device *nbd) - int num_connections = config->num_connections; - int error = 0, i; - -- if (nbd->task_recv) -+ if (nbd->pid) - return -EBUSY; - if (!config->socks) - return -EINVAL; -@@ -1301,7 +1301,7 @@ static int nbd_start_device(struct nbd_device *nbd) - } - - blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections); -- nbd->task_recv = current; -+ nbd->pid = task_pid_nr(current); - - nbd_parse_flags(nbd); - -@@ -1557,8 +1557,8 @@ static int nbd_dbg_tasks_show(struct seq_file *s, void *unused) - { - struct nbd_device *nbd = s->private; - -- if (nbd->task_recv) -- seq_printf(s, "recv: %d\n", task_pid_nr(nbd->task_recv)); -+ if (nbd->pid) -+ seq_printf(s, "recv: %d\n", nbd->pid); - - return 0; - } -@@ -1749,11 +1749,11 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) - disk->major = NBD_MAJOR; - - /* Too big first_minor can cause duplicate creation of -- * sysfs files/links, since first_minor will be truncated to -- * byte in __device_add_disk(). -+ * sysfs files/links, since index << part_shift might overflow, or -+ * MKDEV() expect that the max bits of first_minor is 20. - */ - disk->first_minor = index << part_shift; -- if (disk->first_minor > 0xff) { -+ if (disk->first_minor < index || disk->first_minor > MINORMASK) { - err = -EINVAL; - goto out_free_idr; - } -@@ -2135,7 +2135,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) - mutex_lock(&nbd->config_lock); - config = nbd->config; - if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) || -- !nbd->task_recv) { -+ !nbd->pid) { - dev_err(nbd_to_dev(nbd), - "not configured, cannot reconfigure\n"); - ret = -EINVAL; -diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c -index 72902104f1112..4dbb71230d6e7 100644 ---- a/drivers/block/xen-blkfront.c -+++ b/drivers/block/xen-blkfront.c -@@ -1511,9 +1511,12 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) - unsigned long flags; - struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id; - struct blkfront_info *info = rinfo->dev_info; -+ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; - -- if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) -+ if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { -+ xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS); - return IRQ_HANDLED; -+ } - - spin_lock_irqsave(&rinfo->ring_lock, flags); - again: -@@ -1529,6 +1532,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) - unsigned long id; - unsigned int op; - -+ eoiflag = 0; -+ - RING_COPY_RESPONSE(&rinfo->ring, i, &bret); - id = bret.id; - -@@ -1645,6 +1650,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) - - spin_unlock_irqrestore(&rinfo->ring_lock, flags); - -+ xen_irq_lateeoi(irq, eoiflag); -+ - return IRQ_HANDLED; - - err: -@@ -1652,6 +1659,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) - - spin_unlock_irqrestore(&rinfo->ring_lock, flags); - -+ /* No EOI in order to avoid further interrupts. */ -+ - pr_alert("%s disabled for further use\n", info->gd->disk_name); - return IRQ_HANDLED; - } -@@ -1691,8 +1700,8 @@ static int setup_blkring(struct xenbus_device *dev, - if (err) - goto fail; - -- err = bind_evtchn_to_irqhandler(rinfo->evtchn, blkif_interrupt, 0, -- "blkif", rinfo); -+ err = bind_evtchn_to_irqhandler_lateeoi(rinfo->evtchn, blkif_interrupt, -+ 0, "blkif", rinfo); - if (err <= 0) { - xenbus_dev_fatal(dev, err, - "bind_evtchn_to_irqhandler failed"); -diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c -index fcaf2750f68f7..6383c81ac5b37 100644 ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -910,7 +910,7 @@ static ssize_t read_block_state(struct file *file, char __user *buf, - zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.', - zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.'); - -- if (count < copied) { -+ if (count <= copied) { - zram_slot_unlock(zram, index); - break; - } -diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c -index e9d91d7c0db48..9ba22b13b4fa0 100644 ---- a/drivers/bluetooth/btmtkuart.c -+++ b/drivers/bluetooth/btmtkuart.c -@@ -158,8 +158,10 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, - int err; - - hlen = sizeof(*hdr) + wmt_params->dlen; -- if (hlen > 255) -- return -EINVAL; -+ if (hlen > 255) { -+ err = -EINVAL; -+ goto err_free_skb; -+ } - - hdr = (struct mtk_wmt_hdr *)&wc; - hdr->dir = 1; -@@ -173,7 +175,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, - err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc); - if (err < 0) { - clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); -- return err; -+ goto err_free_skb; - } - - /* The vendor specific WMT commands are all answered by a vendor -@@ -190,13 +192,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, - if (err == -EINTR) { - bt_dev_err(hdev, "Execution of wmt command interrupted"); - clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); -- return err; -+ goto err_free_skb; - } - - if (err) { - bt_dev_err(hdev, "Execution of wmt command timed out"); - clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); -- return -ETIMEDOUT; -+ err = -ETIMEDOUT; -+ goto err_free_skb; - } - - /* Parse and handle the return WMT event */ -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 60d2fce59a71d..79d0db542da3b 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -433,6 +433,10 @@ static const struct usb_device_id blacklist_table[] = { - { USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK }, - { USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK }, - -+ /* Additional Realtek 8761B Bluetooth devices */ -+ { USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK | -+ BTUSB_WIDEBAND_SPEECH }, -+ - /* Additional Realtek 8761BU Bluetooth devices */ - { USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK | - BTUSB_WIDEBAND_SPEECH }, -diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c -index 0c0dedece59c5..d49a39d17d7dc 100644 ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -587,9 +587,11 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count) - count -= processed; - } - -- pm_runtime_get(&hu->serdev->dev); -- pm_runtime_mark_last_busy(&hu->serdev->dev); -- pm_runtime_put_autosuspend(&hu->serdev->dev); -+ if (hu->serdev) { -+ pm_runtime_get(&hu->serdev->dev); -+ pm_runtime_mark_last_busy(&hu->serdev->dev); -+ pm_runtime_put_autosuspend(&hu->serdev->dev); -+ } - - return 0; - } -@@ -846,6 +848,8 @@ static int h5_serdev_probe(struct serdev_device *serdev) - h5->vnd = data->vnd; - } - -+ if (data->driver_info & H5_INFO_WAKEUP_DISABLE) -+ set_bit(H5_WAKEUP_DISABLE, &h5->flags); - - h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(h5->enable_gpio)) -@@ -860,9 +864,6 @@ static int h5_serdev_probe(struct serdev_device *serdev) - if (err) - return err; - -- if (data->driver_info & H5_INFO_WAKEUP_DISABLE) -- set_bit(H5_WAKEUP_DISABLE, &h5->flags); -- - return 0; - } - -@@ -962,11 +963,13 @@ static void h5_btrtl_open(struct h5 *h5) - serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN); - serdev_device_set_baudrate(h5->hu->serdev, 115200); - -- pm_runtime_set_active(&h5->hu->serdev->dev); -- pm_runtime_use_autosuspend(&h5->hu->serdev->dev); -- pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev, -- SUSPEND_TIMEOUT_MS); -- pm_runtime_enable(&h5->hu->serdev->dev); -+ if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) { -+ pm_runtime_set_active(&h5->hu->serdev->dev); -+ pm_runtime_use_autosuspend(&h5->hu->serdev->dev); -+ pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev, -+ SUSPEND_TIMEOUT_MS); -+ pm_runtime_enable(&h5->hu->serdev->dev); -+ } - - /* The controller needs up to 500ms to wakeup */ - gpiod_set_value_cansleep(h5->enable_gpio, 1); -@@ -976,7 +979,8 @@ static void h5_btrtl_open(struct h5 *h5) - - static void h5_btrtl_close(struct h5 *h5) - { -- pm_runtime_disable(&h5->hu->serdev->dev); -+ if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) -+ pm_runtime_disable(&h5->hu->serdev->dev); - - gpiod_set_value_cansleep(h5->device_wake_gpio, 0); - gpiod_set_value_cansleep(h5->enable_gpio, 0); -diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c -index fb99e3727155b..547e6e769546a 100644 ---- a/drivers/bus/mhi/core/pm.c -+++ b/drivers/bus/mhi/core/pm.c -@@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) - } - EXPORT_SYMBOL_GPL(mhi_pm_suspend); - --int mhi_pm_resume(struct mhi_controller *mhi_cntrl) -+static int __mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force) - { - struct mhi_chan *itr, *tmp; - struct device *dev = &mhi_cntrl->mhi_dev->dev; -@@ -898,8 +898,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - -- if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) -- return -EINVAL; -+ if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) { -+ dev_warn(dev, "Resuming from non M3 state (%s)\n", -+ TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); -+ if (!force) -+ return -EINVAL; -+ } - - /* Notify clients about exiting LPM */ - list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { -@@ -940,8 +944,19 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) - - return 0; - } -+ -+int mhi_pm_resume(struct mhi_controller *mhi_cntrl) -+{ -+ return __mhi_pm_resume(mhi_cntrl, false); -+} - EXPORT_SYMBOL_GPL(mhi_pm_resume); - -+int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl) -+{ -+ return __mhi_pm_resume(mhi_cntrl, true); -+} -+EXPORT_SYMBOL_GPL(mhi_pm_resume_force); -+ - int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) - { - int ret; -diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c -index 59a4896a80309..4c577a7317091 100644 ---- a/drivers/bus/mhi/pci_generic.c -+++ b/drivers/bus/mhi/pci_generic.c -@@ -20,7 +20,7 @@ - - #define MHI_PCI_DEFAULT_BAR_NUM 0 - --#define MHI_POST_RESET_DELAY_MS 500 -+#define MHI_POST_RESET_DELAY_MS 2000 - - #define HEALTH_CHECK_PERIOD (HZ * 2) - -diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c -index 6a8b7fb5be58d..ebf22929ff328 100644 ---- a/drivers/bus/ti-sysc.c -+++ b/drivers/bus/ti-sysc.c -@@ -6,6 +6,7 @@ - #include <linux/io.h> - #include <linux/clk.h> - #include <linux/clkdev.h> -+#include <linux/cpu_pm.h> - #include <linux/delay.h> - #include <linux/list.h> - #include <linux/module.h> -@@ -17,6 +18,7 @@ - #include <linux/of_platform.h> - #include <linux/slab.h> - #include <linux/sys_soc.h> -+#include <linux/timekeeping.h> - #include <linux/iopoll.h> - - #include <linux/platform_data/ti-sysc.h> -@@ -51,11 +53,18 @@ struct sysc_address { - struct list_head node; - }; - -+struct sysc_module { -+ struct sysc *ddata; -+ struct list_head node; -+}; -+ - struct sysc_soc_info { - unsigned long general_purpose:1; - enum sysc_soc soc; -- struct mutex list_lock; /* disabled modules list lock */ -+ struct mutex list_lock; /* disabled and restored modules list lock */ - struct list_head disabled_modules; -+ struct list_head restored_modules; -+ struct notifier_block nb; - }; - - enum sysc_clocks { -@@ -223,37 +232,77 @@ static u32 sysc_read_sysstatus(struct sysc *ddata) - return sysc_read(ddata, offset); - } - --/* Poll on reset status */ --static int sysc_wait_softreset(struct sysc *ddata) -+static int sysc_poll_reset_sysstatus(struct sysc *ddata) - { -- u32 sysc_mask, syss_done, rstval; -- int syss_offset, error = 0; -- -- if (ddata->cap->regbits->srst_shift < 0) -- return 0; -- -- syss_offset = ddata->offsets[SYSC_SYSSTATUS]; -- sysc_mask = BIT(ddata->cap->regbits->srst_shift); -+ int error, retries; -+ u32 syss_done, rstval; - - if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED) - syss_done = 0; - else - syss_done = ddata->cfg.syss_mask; - -- if (syss_offset >= 0) { -+ if (likely(!timekeeping_suspended)) { - error = readx_poll_timeout_atomic(sysc_read_sysstatus, ddata, - rstval, (rstval & ddata->cfg.syss_mask) == - syss_done, 100, MAX_MODULE_SOFTRESET_WAIT); -+ } else { -+ retries = MAX_MODULE_SOFTRESET_WAIT; -+ while (retries--) { -+ rstval = sysc_read_sysstatus(ddata); -+ if ((rstval & ddata->cfg.syss_mask) == syss_done) -+ return 0; -+ udelay(2); /* Account for udelay flakeyness */ -+ } -+ error = -ETIMEDOUT; -+ } -+ -+ return error; -+} -+ -+static int sysc_poll_reset_sysconfig(struct sysc *ddata) -+{ -+ int error, retries; -+ u32 sysc_mask, rstval; -+ -+ sysc_mask = BIT(ddata->cap->regbits->srst_shift); - -- } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) { -+ if (likely(!timekeeping_suspended)) { - error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata, - rstval, !(rstval & sysc_mask), - 100, MAX_MODULE_SOFTRESET_WAIT); -+ } else { -+ retries = MAX_MODULE_SOFTRESET_WAIT; -+ while (retries--) { -+ rstval = sysc_read_sysconfig(ddata); -+ if (!(rstval & sysc_mask)) -+ return 0; -+ udelay(2); /* Account for udelay flakeyness */ -+ } -+ error = -ETIMEDOUT; - } - - return error; - } - -+/* Poll on reset status */ -+static int sysc_wait_softreset(struct sysc *ddata) -+{ -+ int syss_offset, error = 0; -+ -+ if (ddata->cap->regbits->srst_shift < 0) -+ return 0; -+ -+ syss_offset = ddata->offsets[SYSC_SYSSTATUS]; -+ -+ if (syss_offset >= 0) -+ error = sysc_poll_reset_sysstatus(ddata); -+ else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) -+ error = sysc_poll_reset_sysconfig(ddata); -+ -+ return error; -+} -+ - static int sysc_add_named_clock_from_child(struct sysc *ddata, - const char *name, - const char *optfck_name) -@@ -1518,7 +1567,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { - 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), - SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, - SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | -- SYSC_QUIRK_REINIT_ON_RESUME), -+ SYSC_QUIRK_REINIT_ON_CTX_LOST), - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, - SYSC_MODULE_QUIRK_WDT), - /* PRUSS on am3, am4 and am5 */ -@@ -2401,6 +2450,78 @@ static struct dev_pm_domain sysc_child_pm_domain = { - } - }; - -+/* Caller needs to take list_lock if ever used outside of cpu_pm */ -+static void sysc_reinit_modules(struct sysc_soc_info *soc) -+{ -+ struct sysc_module *module; -+ struct list_head *pos; -+ struct sysc *ddata; -+ -+ list_for_each(pos, &sysc_soc->restored_modules) { -+ module = list_entry(pos, struct sysc_module, node); -+ ddata = module->ddata; -+ sysc_reinit_module(ddata, ddata->enabled); -+ } -+} -+ -+/** -+ * sysc_context_notifier - optionally reset and restore module after idle -+ * @nb: notifier block -+ * @cmd: unused -+ * @v: unused -+ * -+ * Some interconnect target modules need to be restored, or reset and restored -+ * on CPU_PM CPU_PM_CLUSTER_EXIT notifier. This is needed at least for am335x -+ * OTG and GPMC target modules even if the modules are unused. -+ */ -+static int sysc_context_notifier(struct notifier_block *nb, unsigned long cmd, -+ void *v) -+{ -+ struct sysc_soc_info *soc; -+ -+ soc = container_of(nb, struct sysc_soc_info, nb); -+ -+ switch (cmd) { -+ case CPU_CLUSTER_PM_ENTER: -+ break; -+ case CPU_CLUSTER_PM_ENTER_FAILED: /* No need to restore context */ -+ break; -+ case CPU_CLUSTER_PM_EXIT: -+ sysc_reinit_modules(soc); -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+/** -+ * sysc_add_restored - optionally add reset and restore quirk hanlling -+ * @ddata: device data -+ */ -+static void sysc_add_restored(struct sysc *ddata) -+{ -+ struct sysc_module *restored_module; -+ -+ restored_module = kzalloc(sizeof(*restored_module), GFP_KERNEL); -+ if (!restored_module) -+ return; -+ -+ restored_module->ddata = ddata; -+ -+ mutex_lock(&sysc_soc->list_lock); -+ -+ list_add(&restored_module->node, &sysc_soc->restored_modules); -+ -+ if (sysc_soc->nb.notifier_call) -+ goto out_unlock; -+ -+ sysc_soc->nb.notifier_call = sysc_context_notifier; -+ cpu_pm_register_notifier(&sysc_soc->nb); -+ -+out_unlock: -+ mutex_unlock(&sysc_soc->list_lock); -+} -+ - /** - * sysc_legacy_idle_quirk - handle children in omap_device compatible way - * @ddata: device driver data -@@ -2900,12 +3021,14 @@ static int sysc_add_disabled(unsigned long base) - } - - /* -- * One time init to detect the booted SoC and disable unavailable features. -+ * One time init to detect the booted SoC, disable unavailable features -+ * and initialize list for optional cpu_pm notifier. -+ * - * Note that we initialize static data shared across all ti-sysc instances - * so ddata is only used for SoC type. This can be called from module_init - * once we no longer need to rely on platform data. - */ --static int sysc_init_soc(struct sysc *ddata) -+static int sysc_init_static_data(struct sysc *ddata) - { - const struct soc_device_attribute *match; - struct ti_sysc_platform_data *pdata; -@@ -2921,6 +3044,7 @@ static int sysc_init_soc(struct sysc *ddata) - - mutex_init(&sysc_soc->list_lock); - INIT_LIST_HEAD(&sysc_soc->disabled_modules); -+ INIT_LIST_HEAD(&sysc_soc->restored_modules); - sysc_soc->general_purpose = true; - - pdata = dev_get_platdata(ddata->dev); -@@ -2985,15 +3109,24 @@ static int sysc_init_soc(struct sysc *ddata) - return 0; - } - --static void sysc_cleanup_soc(void) -+static void sysc_cleanup_static_data(void) - { -+ struct sysc_module *restored_module; - struct sysc_address *disabled_module; - struct list_head *pos, *tmp; - - if (!sysc_soc) - return; - -+ if (sysc_soc->nb.notifier_call) -+ cpu_pm_unregister_notifier(&sysc_soc->nb); -+ - mutex_lock(&sysc_soc->list_lock); -+ list_for_each_safe(pos, tmp, &sysc_soc->restored_modules) { -+ restored_module = list_entry(pos, struct sysc_module, node); -+ list_del(pos); -+ kfree(restored_module); -+ } - list_for_each_safe(pos, tmp, &sysc_soc->disabled_modules) { - disabled_module = list_entry(pos, struct sysc_address, node); - list_del(pos); -@@ -3061,7 +3194,7 @@ static int sysc_probe(struct platform_device *pdev) - ddata->dev = &pdev->dev; - platform_set_drvdata(pdev, ddata); - -- error = sysc_init_soc(ddata); -+ error = sysc_init_static_data(ddata); - if (error) - return error; - -@@ -3159,6 +3292,9 @@ static int sysc_probe(struct platform_device *pdev) - pm_runtime_put(&pdev->dev); - } - -+ if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_CTX_LOST) -+ sysc_add_restored(ddata); -+ - return 0; - - err: -@@ -3240,7 +3376,7 @@ static void __exit sysc_exit(void) - { - bus_unregister_notifier(&platform_bus_type, &sysc_nb); - platform_driver_unregister(&sysc_driver); -- sysc_cleanup_soc(); -+ sysc_cleanup_static_data(); - } - module_exit(sysc_exit); - -diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c -index ed3c4c42fc23b..d68d05d5d3838 100644 ---- a/drivers/char/agp/parisc-agp.c -+++ b/drivers/char/agp/parisc-agp.c -@@ -281,7 +281,7 @@ agp_ioc_init(void __iomem *ioc_regs) - return 0; - } - --static int -+static int __init - lba_find_capability(int cap) - { - struct _parisc_agp_info *info = &parisc_agp_info; -@@ -366,7 +366,7 @@ fail: - return error; - } - --static int -+static int __init - find_quicksilver(struct device *dev, void *data) - { - struct parisc_device **lba = data; -@@ -378,7 +378,7 @@ find_quicksilver(struct device *dev, void *data) - return 0; - } - --static int -+static int __init - parisc_agp_init(void) - { - extern struct sba_device *sba_list; -diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c -index 8ad7b515a51b8..6c00ea0085553 100644 ---- a/drivers/char/hw_random/mtk-rng.c -+++ b/drivers/char/hw_random/mtk-rng.c -@@ -166,8 +166,13 @@ static int mtk_rng_runtime_resume(struct device *dev) - return mtk_rng_init(&priv->rng); - } - --static UNIVERSAL_DEV_PM_OPS(mtk_rng_pm_ops, mtk_rng_runtime_suspend, -- mtk_rng_runtime_resume, NULL); -+static const struct dev_pm_ops mtk_rng_pm_ops = { -+ SET_RUNTIME_PM_OPS(mtk_rng_runtime_suspend, -+ mtk_rng_runtime_resume, NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, -+ pm_runtime_force_resume) -+}; -+ - #define MTK_RNG_PM_OPS (&mtk_rng_pm_ops) - #else /* CONFIG_PM */ - #define MTK_RNG_PM_OPS NULL -diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c -index e96cb5c4f97a3..b404cc46cbda7 100644 ---- a/drivers/char/ipmi/ipmi_msghandler.c -+++ b/drivers/char/ipmi/ipmi_msghandler.c -@@ -191,6 +191,8 @@ struct ipmi_user { - struct work_struct remove_work; - }; - -+static struct workqueue_struct *remove_work_wq; -+ - static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user, int *index) - __acquires(user->release_barrier) - { -@@ -1261,7 +1263,7 @@ static void free_user(struct kref *ref) - struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount); - - /* SRCU cleanup must happen in task context. */ -- schedule_work(&user->remove_work); -+ queue_work(remove_work_wq, &user->remove_work); - } - - static void _ipmi_destroy_user(struct ipmi_user *user) -@@ -4789,7 +4791,9 @@ static atomic_t recv_msg_inuse_count = ATOMIC_INIT(0); - static void free_smi_msg(struct ipmi_smi_msg *msg) - { - atomic_dec(&smi_msg_inuse_count); -- kfree(msg); -+ /* Try to keep as much stuff out of the panic path as possible. */ -+ if (!oops_in_progress) -+ kfree(msg); - } - - struct ipmi_smi_msg *ipmi_alloc_smi_msg(void) -@@ -4808,7 +4812,9 @@ EXPORT_SYMBOL(ipmi_alloc_smi_msg); - static void free_recv_msg(struct ipmi_recv_msg *msg) - { - atomic_dec(&recv_msg_inuse_count); -- kfree(msg); -+ /* Try to keep as much stuff out of the panic path as possible. */ -+ if (!oops_in_progress) -+ kfree(msg); - } - - static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) -@@ -4826,7 +4832,7 @@ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) - - void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) - { -- if (msg->user) -+ if (msg->user && !oops_in_progress) - kref_put(&msg->user->refcount, free_user); - msg->done(msg); - } -@@ -5149,6 +5155,13 @@ static int ipmi_init_msghandler(void) - - atomic_notifier_chain_register(&panic_notifier_list, &panic_block); - -+ remove_work_wq = create_singlethread_workqueue("ipmi-msghandler-remove-wq"); -+ if (!remove_work_wq) { -+ pr_err("unable to create ipmi-msghandler-remove-wq workqueue"); -+ rv = -ENOMEM; -+ goto out; -+ } -+ - initialized = true; - - out: -@@ -5174,6 +5187,8 @@ static void __exit cleanup_ipmi(void) - int count; - - if (initialized) { -+ destroy_workqueue(remove_work_wq); -+ - atomic_notifier_chain_unregister(&panic_notifier_list, - &panic_block); - -diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c -index e4ff3b50de7f3..883b4a3410122 100644 ---- a/drivers/char/ipmi/ipmi_watchdog.c -+++ b/drivers/char/ipmi/ipmi_watchdog.c -@@ -342,13 +342,17 @@ static atomic_t msg_tofree = ATOMIC_INIT(0); - static DECLARE_COMPLETION(msg_wait); - static void msg_free_smi(struct ipmi_smi_msg *msg) - { -- if (atomic_dec_and_test(&msg_tofree)) -- complete(&msg_wait); -+ if (atomic_dec_and_test(&msg_tofree)) { -+ if (!oops_in_progress) -+ complete(&msg_wait); -+ } - } - static void msg_free_recv(struct ipmi_recv_msg *msg) - { -- if (atomic_dec_and_test(&msg_tofree)) -- complete(&msg_wait); -+ if (atomic_dec_and_test(&msg_tofree)) { -+ if (!oops_in_progress) -+ complete(&msg_wait); -+ } - } - static struct ipmi_smi_msg smi_msg = { - .done = msg_free_smi -@@ -434,8 +438,10 @@ static int _ipmi_set_timeout(int do_heartbeat) - rv = __ipmi_set_timeout(&smi_msg, - &recv_msg, - &send_heartbeat_now); -- if (rv) -+ if (rv) { -+ atomic_set(&msg_tofree, 0); - return rv; -+ } - - wait_for_completion(&msg_wait); - -@@ -497,7 +503,7 @@ static void panic_halt_ipmi_heartbeat(void) - msg.cmd = IPMI_WDOG_RESET_TIMER; - msg.data = NULL; - msg.data_len = 0; -- atomic_inc(&panic_done_count); -+ atomic_add(2, &panic_done_count); - rv = ipmi_request_supply_msgs(watchdog_user, - (struct ipmi_addr *) &addr, - 0, -@@ -507,7 +513,7 @@ static void panic_halt_ipmi_heartbeat(void) - &panic_halt_heartbeat_recv_msg, - 1); - if (rv) -- atomic_dec(&panic_done_count); -+ atomic_sub(2, &panic_done_count); - } - - static struct ipmi_smi_msg panic_halt_smi_msg = { -@@ -531,12 +537,12 @@ static void panic_halt_ipmi_set_timeout(void) - /* Wait for the messages to be free. */ - while (atomic_read(&panic_done_count) != 0) - ipmi_poll_interface(watchdog_user); -- atomic_inc(&panic_done_count); -+ atomic_add(2, &panic_done_count); - rv = __ipmi_set_timeout(&panic_halt_smi_msg, - &panic_halt_recv_msg, - &send_heartbeat_now); - if (rv) { -- atomic_dec(&panic_done_count); -+ atomic_sub(2, &panic_done_count); - pr_warn("Unable to extend the watchdog timeout\n"); - } else { - if (send_heartbeat_now) -@@ -580,6 +586,7 @@ restart: - &recv_msg, - 1); - if (rv) { -+ atomic_set(&msg_tofree, 0); - pr_warn("heartbeat send failure: %d\n", rv); - return rv; - } -diff --git a/drivers/char/ipmi/kcs_bmc_serio.c b/drivers/char/ipmi/kcs_bmc_serio.c -index 7948cabde50b4..7e2067628a6ce 100644 ---- a/drivers/char/ipmi/kcs_bmc_serio.c -+++ b/drivers/char/ipmi/kcs_bmc_serio.c -@@ -73,10 +73,12 @@ static int kcs_bmc_serio_add_device(struct kcs_bmc_device *kcs_bmc) - struct serio *port; - - priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; - - /* Use kzalloc() as the allocation is cleaned up with kfree() via serio_unregister_port() */ - port = kzalloc(sizeof(*port), GFP_KERNEL); -- if (!(priv && port)) -+ if (!port) - return -ENOMEM; - - port->id.type = SERIO_8042; -diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c -index 784b8b3cb903f..97e916856cf3e 100644 ---- a/drivers/char/tpm/tpm2-space.c -+++ b/drivers/char/tpm/tpm2-space.c -@@ -455,6 +455,9 @@ static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp, - if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES) - return 0; - -+ if (be32_to_cpu(data->count) > (UINT_MAX - TPM_HEADER_SIZE - 9) / 4) -+ return -EFAULT; -+ - if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count)) - return -EFAULT; - -diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c -index 69579efb247b3..b2659a4c40168 100644 ---- a/drivers/char/tpm/tpm_tis_core.c -+++ b/drivers/char/tpm/tpm_tis_core.c -@@ -48,6 +48,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, - unsigned long timeout, wait_queue_head_t *queue, - bool check_cancel) - { -+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - unsigned long stop; - long rc; - u8 status; -@@ -80,8 +81,8 @@ again: - } - } else { - do { -- usleep_range(TPM_TIMEOUT_USECS_MIN, -- TPM_TIMEOUT_USECS_MAX); -+ usleep_range(priv->timeout_min, -+ priv->timeout_max); - status = chip->ops->status(chip); - if ((status & mask) == mask) - return 0; -@@ -945,7 +946,22 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, - chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); - chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); - chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); -+ priv->timeout_min = TPM_TIMEOUT_USECS_MIN; -+ priv->timeout_max = TPM_TIMEOUT_USECS_MAX; - priv->phy_ops = phy_ops; -+ -+ rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); -+ if (rc < 0) -+ goto out_err; -+ -+ priv->manufacturer_id = vendor; -+ -+ if (priv->manufacturer_id == TPM_VID_ATML && -+ !(chip->flags & TPM_CHIP_FLAG_TPM2)) { -+ priv->timeout_min = TIS_TIMEOUT_MIN_ATML; -+ priv->timeout_max = TIS_TIMEOUT_MAX_ATML; -+ } -+ - dev_set_drvdata(&chip->dev, priv); - - if (is_bsw()) { -@@ -988,12 +1004,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, - if (rc) - goto out_err; - -- rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); -- if (rc < 0) -- goto out_err; -- -- priv->manufacturer_id = vendor; -- - rc = tpm_tis_read8(priv, TPM_RID(0), &rid); - if (rc < 0) - goto out_err; -diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h -index b2a3c6c72882d..3be24f221e32a 100644 ---- a/drivers/char/tpm/tpm_tis_core.h -+++ b/drivers/char/tpm/tpm_tis_core.h -@@ -54,6 +54,8 @@ enum tis_defaults { - TIS_MEM_LEN = 0x5000, - TIS_SHORT_TIMEOUT = 750, /* ms */ - TIS_LONG_TIMEOUT = 2000, /* 2 sec */ -+ TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ -+ TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ - }; - - /* Some timeout values are needed before it is known whether the chip is -@@ -98,6 +100,8 @@ struct tpm_tis_data { - wait_queue_head_t read_queue; - const struct tpm_tis_phy_ops *phy_ops; - unsigned short rng_quality; -+ unsigned int timeout_min; /* usecs */ -+ unsigned int timeout_max; /* usecs */ - }; - - struct tpm_tis_phy_ops { -diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c -index 54584b4b00d19..aaa59a00eeaef 100644 ---- a/drivers/char/tpm/tpm_tis_spi_main.c -+++ b/drivers/char/tpm/tpm_tis_spi_main.c -@@ -267,6 +267,7 @@ static const struct spi_device_id tpm_tis_spi_id[] = { - { "st33htpm-spi", (unsigned long)tpm_tis_spi_probe }, - { "slb9670", (unsigned long)tpm_tis_spi_probe }, - { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe }, -+ { "tpm_tis-spi", (unsigned long)tpm_tis_spi_probe }, - { "cr50", (unsigned long)cr50_spi_probe }, - {} - }; -diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c -index e7f88f35c7028..dc3551796e5ed 100644 ---- a/drivers/char/xillybus/xillyusb.c -+++ b/drivers/char/xillybus/xillyusb.c -@@ -1912,6 +1912,7 @@ static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev) - - dealloc: - endpoint_dealloc(xdev->msg_ep); /* Also frees FIFO mem if allocated */ -+ xdev->msg_ep = NULL; - return -ENOMEM; - } - -diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c -index a80427980bf73..04d0dd8385945 100644 ---- a/drivers/clk/at91/clk-master.c -+++ b/drivers/clk/at91/clk-master.c -@@ -280,7 +280,7 @@ static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate, - - else if (pres == 3) - pres = MASTER_PRES_MAX; -- else -+ else if (pres) - pres = ffs(pres) - 1; - - spin_lock_irqsave(master->lock, flags); -@@ -309,7 +309,7 @@ static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw, - spin_unlock_irqrestore(master->lock, flags); - - pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK; -- if (pres == 3 && characteristics->have_div3_pres) -+ if (pres == MASTER_PRES_MAX && characteristics->have_div3_pres) - pres = 3; - else - pres = (1 << pres); -@@ -610,7 +610,7 @@ static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate, - - if (div == 3) - div = MASTER_PRES_MAX; -- else -+ else if (div) - div = ffs(div) - 1; - - spin_lock_irqsave(master->lock, flags); -diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c -index 34e3ab13741ac..1f52409475e9c 100644 ---- a/drivers/clk/at91/clk-sam9x60-pll.c -+++ b/drivers/clk/at91/clk-sam9x60-pll.c -@@ -71,8 +71,8 @@ static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw, - struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw); - struct sam9x60_frac *frac = to_sam9x60_frac(core); - -- return (parent_rate * (frac->mul + 1) + -- ((u64)parent_rate * frac->frac >> 22)); -+ return parent_rate * (frac->mul + 1) + -+ DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22)); - } - - static int sam9x60_frac_pll_prepare(struct clk_hw *hw) -diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c -index 20ee9dccee787..b40035b011d0a 100644 ---- a/drivers/clk/at91/pmc.c -+++ b/drivers/clk/at91/pmc.c -@@ -267,6 +267,11 @@ static int __init pmc_register_ops(void) - if (!np) - return -ENODEV; - -+ if (!of_device_is_available(np)) { -+ of_node_put(np); -+ return -ENODEV; -+ } -+ - pmcreg = device_node_to_regmap(np); - of_node_put(np); - if (IS_ERR(pmcreg)) -diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c -index cf8c079aa086a..019e712f90d6f 100644 ---- a/drivers/clk/at91/sama7g5.c -+++ b/drivers/clk/at91/sama7g5.c -@@ -982,16 +982,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np) - } - - parent_names[0] = "cpupll_divpmcck"; -- hw = at91_clk_register_master_pres(regmap, "cpuck", 1, parent_names, -- &mck0_layout, &mck0_characteristics, -- &pmc_mck0_lock, -- CLK_SET_RATE_PARENT, 0); -- if (IS_ERR(hw)) -- goto err_free; -- -- sama7g5_pmc->chws[PMC_CPU] = hw; -- -- hw = at91_clk_register_master_div(regmap, "mck0", "cpuck", -+ hw = at91_clk_register_master_div(regmap, "mck0", "cpupll_divpmcck", - &mck0_layout, &mck0_characteristics, - &pmc_mck0_lock, 0); - if (IS_ERR(hw)) -diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c -index bc3be5f3eae15..24dab2312bc6f 100644 ---- a/drivers/clk/clk-ast2600.c -+++ b/drivers/clk/clk-ast2600.c -@@ -51,6 +51,8 @@ static DEFINE_SPINLOCK(aspeed_g6_clk_lock); - static struct clk_hw_onecell_data *aspeed_g6_clk_data; - - static void __iomem *scu_g6_base; -+/* AST2600 revision: A0, A1, A2, etc */ -+static u8 soc_rev; - - /* - * Clocks marked with CLK_IS_CRITICAL: -@@ -191,9 +193,8 @@ static struct clk_hw *ast2600_calc_pll(const char *name, u32 val) - static struct clk_hw *ast2600_calc_apll(const char *name, u32 val) - { - unsigned int mult, div; -- u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV); - -- if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) { -+ if (soc_rev >= 2) { - if (val & BIT(24)) { - /* Pass through mode */ - mult = div = 1; -@@ -707,7 +708,7 @@ static const u32 ast2600_a1_axi_ahb200_tbl[] = { - static void __init aspeed_g6_cc(struct regmap *map) - { - struct clk_hw *hw; -- u32 val, div, divbits, chip_id, axi_div, ahb_div; -+ u32 val, div, divbits, axi_div, ahb_div; - - clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, 25000000); - -@@ -738,8 +739,7 @@ static void __init aspeed_g6_cc(struct regmap *map) - axi_div = 2; - - divbits = (val >> 11) & 0x3; -- regmap_read(map, ASPEED_G6_SILICON_REV, &chip_id); -- if (chip_id & BIT(16)) { -+ if (soc_rev >= 1) { - if (!divbits) { - ahb_div = ast2600_a1_axi_ahb200_tbl[(val >> 8) & 0x3]; - if (val & BIT(16)) -@@ -784,6 +784,8 @@ static void __init aspeed_g6_cc_init(struct device_node *np) - if (!scu_g6_base) - return; - -+ soc_rev = (readl(scu_g6_base + ASPEED_G6_SILICON_REV) & CHIP_REVISION_ID) >> 16; -+ - aspeed_g6_clk_data = kzalloc(struct_size(aspeed_g6_clk_data, hws, - ASPEED_G6_NUM_CLKS), GFP_KERNEL); - if (!aspeed_g6_clk_data) -diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -index 65508eb89ec99..a277fd4f2f0a6 100644 ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -3415,6 +3415,14 @@ static int __clk_core_init(struct clk_core *core) - - clk_prepare_lock(); - -+ /* -+ * Set hw->core after grabbing the prepare_lock to synchronize with -+ * callers of clk_core_fill_parent_index() where we treat hw->core -+ * being NULL as the clk not being registered yet. This is crucial so -+ * that clks aren't parented until their parent is fully registered. -+ */ -+ core->hw->core = core; -+ - ret = clk_pm_runtime_get(core); - if (ret) - goto unlock; -@@ -3579,8 +3587,10 @@ static int __clk_core_init(struct clk_core *core) - out: - clk_pm_runtime_put(core); - unlock: -- if (ret) -+ if (ret) { - hlist_del_init(&core->child_node); -+ core->hw->core = NULL; -+ } - - clk_prepare_unlock(); - -@@ -3844,7 +3854,6 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) - core->num_parents = init->num_parents; - core->min_rate = 0; - core->max_rate = ULONG_MAX; -- hw->core = core; - - ret = clk_core_populate_parent_map(core, init); - if (ret) -@@ -3862,7 +3871,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) - goto fail_create_clk; - } - -- clk_core_link_consumer(hw->core, hw->clk); -+ clk_core_link_consumer(core, hw->clk); - - ret = __clk_core_init(core); - if (!ret) -diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c -index 5dbb6a9377324..206e4c43f68f8 100644 ---- a/drivers/clk/imx/clk-imx6ul.c -+++ b/drivers/clk/imx/clk-imx6ul.c -@@ -161,7 +161,6 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) - hws[IMX6UL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); - hws[IMX6UL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); - hws[IMX6UL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); -- hws[IMX6UL_CLK_CSI_SEL] = imx_clk_hw_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT); - - /* Do not bypass PLLs initially */ - clk_set_parent(hws[IMX6UL_PLL1_BYPASS]->clk, hws[IMX6UL_CLK_PLL1]->clk); -@@ -270,6 +269,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) - hws[IMX6UL_CLK_ECSPI_SEL] = imx_clk_hw_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); - hws[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_hw_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT); - hws[IMX6UL_CLK_LCDIF_SEL] = imx_clk_hw_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels)); -+ hws[IMX6UL_CLK_CSI_SEL] = imx_clk_hw_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); - - hws[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels)); - hws[IMX6UL_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels)); -diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c -index d3e905cf867d7..b23758083ce52 100644 ---- a/drivers/clk/imx/clk-imx8qxp-lpcg.c -+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c -@@ -370,7 +370,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { - .probe = imx8qxp_lpcg_clk_probe, - }; - --builtin_platform_driver(imx8qxp_lpcg_clk_driver); -+module_platform_driver(imx8qxp_lpcg_clk_driver); - - MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); - MODULE_DESCRIPTION("NXP i.MX8QXP LPCG clock driver"); -diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c -index c53a688d8ccca..40a2efb1329be 100644 ---- a/drivers/clk/imx/clk-imx8qxp.c -+++ b/drivers/clk/imx/clk-imx8qxp.c -@@ -308,7 +308,7 @@ static struct platform_driver imx8qxp_clk_driver = { - }, - .probe = imx8qxp_clk_probe, - }; --builtin_platform_driver(imx8qxp_clk_driver); -+module_platform_driver(imx8qxp_clk_driver); - - MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); - MODULE_DESCRIPTION("NXP i.MX8QXP clock driver"); -diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c -index 266c7595d3302..af31633a8862e 100644 ---- a/drivers/clk/ingenic/cgu.c -+++ b/drivers/clk/ingenic/cgu.c -@@ -453,15 +453,15 @@ ingenic_clk_calc_div(struct clk_hw *hw, - } - - /* Impose hardware constraints */ -- div = min_t(unsigned, div, 1 << clk_info->div.bits); -- div = max_t(unsigned, div, 1); -+ div = clamp_t(unsigned int, div, clk_info->div.div, -+ clk_info->div.div << clk_info->div.bits); - - /* - * If the divider value itself must be divided before being written to - * the divider register, we must ensure we don't have any bits set that - * would be lost as a result of doing so. - */ -- div /= clk_info->div.div; -+ div = DIV_ROUND_UP(div, clk_info->div.div); - div *= clk_info->div.div; - - return div; -diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c -index 08ba59ec3fb17..71bdd7c3ff034 100644 ---- a/drivers/clk/mvebu/ap-cpu-clk.c -+++ b/drivers/clk/mvebu/ap-cpu-clk.c -@@ -256,12 +256,15 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) - int cpu, err; - - err = of_property_read_u32(dn, "reg", &cpu); -- if (WARN_ON(err)) -+ if (WARN_ON(err)) { -+ of_node_put(dn); - return err; -+ } - - /* If cpu2 or cpu3 is enabled */ - if (cpu & APN806_CLUSTER_NUM_MASK) { - nclusters = 2; -+ of_node_put(dn); - break; - } - } -@@ -288,8 +291,10 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) - int cpu, err; - - err = of_property_read_u32(dn, "reg", &cpu); -- if (WARN_ON(err)) -+ if (WARN_ON(err)) { -+ of_node_put(dn); - return err; -+ } - - cluster_index = cpu & APN806_CLUSTER_NUM_MASK; - cluster_index >>= APN806_CLUSTER_NUM_OFFSET; -@@ -301,6 +306,7 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) - parent = of_clk_get(np, cluster_index); - if (IS_ERR(parent)) { - dev_err(dev, "Could not get the clock parent\n"); -+ of_node_put(dn); - return -EINVAL; - } - parent_name = __clk_get_name(parent); -@@ -319,8 +325,10 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) - init.parent_names = &parent_name; - - ret = devm_clk_hw_register(dev, &ap_cpu_clk[cluster_index].hw); -- if (ret) -+ if (ret) { -+ of_node_put(dn); - return ret; -+ } - ap_cpu_data->hws[cluster_index] = &ap_cpu_clk[cluster_index].hw; - } - -diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c -index eaedcceb766f9..8f65b9bdafce4 100644 ---- a/drivers/clk/qcom/clk-alpha-pll.c -+++ b/drivers/clk/qcom/clk-alpha-pll.c -@@ -1429,6 +1429,15 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); - void clk_trion_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("Trion 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); -diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c -index b2d00b4519634..45d9cca28064f 100644 ---- a/drivers/clk/qcom/clk-regmap-mux.c -+++ b/drivers/clk/qcom/clk-regmap-mux.c -@@ -28,7 +28,7 @@ static u8 mux_get_parent(struct clk_hw *hw) - val &= mask; - - if (mux->parent_map) -- return qcom_find_src_index(hw, mux->parent_map, val); -+ return qcom_find_cfg_index(hw, mux->parent_map, val); - - return val; - } -diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c -index 60d2a78d13950..2af04fc4abfa9 100644 ---- a/drivers/clk/qcom/common.c -+++ b/drivers/clk/qcom/common.c -@@ -69,6 +69,18 @@ int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src) - } - EXPORT_SYMBOL_GPL(qcom_find_src_index); - -+int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, u8 cfg) -+{ -+ int i, num_parents = clk_hw_get_num_parents(hw); -+ -+ for (i = 0; i < num_parents; i++) -+ if (cfg == map[i].cfg) -+ return i; -+ -+ return -ENOENT; -+} -+EXPORT_SYMBOL_GPL(qcom_find_cfg_index); -+ - struct regmap * - qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) - { -diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h -index bb39a7e106d8a..9c8f7b798d9fc 100644 ---- a/drivers/clk/qcom/common.h -+++ b/drivers/clk/qcom/common.h -@@ -49,6 +49,8 @@ extern void - qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count); - extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, - u8 src); -+extern int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, -+ u8 cfg); - - extern int qcom_cc_register_board_clk(struct device *dev, const char *path, - const char *name, unsigned long rate); -diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c -index 3c3a7ff045621..9b1674b28d45d 100644 ---- a/drivers/clk/qcom/gcc-msm8996.c -+++ b/drivers/clk/qcom/gcc-msm8996.c -@@ -2937,20 +2937,6 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = { - }, - }; - --static struct clk_branch gcc_aggre1_pnoc_ahb_clk = { -- .halt_reg = 0x82014, -- .clkr = { -- .enable_reg = 0x82014, -- .enable_mask = BIT(0), -- .hw.init = &(struct clk_init_data){ -- .name = "gcc_aggre1_pnoc_ahb_clk", -- .parent_names = (const char *[]){ "periph_noc_clk_src" }, -- .num_parents = 1, -- .ops = &clk_branch2_ops, -- }, -- }, --}; -- - static struct clk_branch gcc_aggre2_ufs_axi_clk = { - .halt_reg = 0x83014, - .clkr = { -@@ -3474,7 +3460,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { - [GCC_AGGRE0_CNOC_AHB_CLK] = &gcc_aggre0_cnoc_ahb_clk.clkr, - [GCC_SMMU_AGGRE0_AXI_CLK] = &gcc_smmu_aggre0_axi_clk.clkr, - [GCC_SMMU_AGGRE0_AHB_CLK] = &gcc_smmu_aggre0_ahb_clk.clkr, -- [GCC_AGGRE1_PNOC_AHB_CLK] = &gcc_aggre1_pnoc_ahb_clk.clkr, - [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr, - [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr, - [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr, -diff --git a/drivers/clk/qcom/gcc-sm6125.c b/drivers/clk/qcom/gcc-sm6125.c -index 543cfab7561f9..431b55bb0d2f7 100644 ---- a/drivers/clk/qcom/gcc-sm6125.c -+++ b/drivers/clk/qcom/gcc-sm6125.c -@@ -1121,7 +1121,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { - .name = "gcc_sdcc1_apps_clk_src", - .parent_data = gcc_parent_data_1, - .num_parents = ARRAY_SIZE(gcc_parent_data_1), -- .ops = &clk_rcg2_ops, -+ .ops = &clk_rcg2_floor_ops, - }, - }; - -@@ -1143,7 +1143,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { - .name = "gcc_sdcc1_ice_core_clk_src", - .parent_data = gcc_parent_data_0, - .num_parents = ARRAY_SIZE(gcc_parent_data_0), -- .ops = &clk_rcg2_floor_ops, -+ .ops = &clk_rcg2_ops, - }, - }; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c -index f32366d9336e7..bd9a8782fec3d 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c -+++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c -@@ -1464,7 +1464,7 @@ static void __init sun4i_ccu_init(struct device_node *node, - val &= ~GENMASK(7, 6); - writel(val | (2 << 6), reg + SUN4I_AHB_REG); - -- sunxi_ccu_probe(node, reg, desc); -+ of_sunxi_ccu_probe(node, reg, desc); - } - - static void __init sun4i_a10_ccu_setup(struct device_node *node) -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c -index a56142b909938..6f2a589705561 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c -@@ -196,7 +196,7 @@ static int sun50i_a100_r_ccu_probe(struct platform_device *pdev) - if (IS_ERR(reg)) - return PTR_ERR(reg); - -- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc); -+ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_r_ccu_desc); - } - - static const struct of_device_id sun50i_a100_r_ccu_ids[] = { -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c -index 81b48c73d389f..913bb08e6dee8 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c -@@ -1247,7 +1247,7 @@ static int sun50i_a100_ccu_probe(struct platform_device *pdev) - writel(val, reg + sun50i_a100_usb2_clk_regs[i]); - } - -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc); - if (ret) - return ret; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -index 149cfde817cba..54f25c624f020 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -@@ -955,7 +955,7 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev) - - writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); - -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc); - if (ret) - return ret; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c -index f8909a7ed5539..f30d7eb5424d8 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c -@@ -232,7 +232,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, - return; - } - -- sunxi_ccu_probe(node, reg, desc); -+ of_sunxi_ccu_probe(node, reg, desc); - } - - static void __init sun50i_h6_r_ccu_setup(struct device_node *node) -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c -index bff446b782907..c0800da2fa3d7 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c -@@ -1240,7 +1240,7 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) - val |= BIT(24); - writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); - -- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc); -+ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); - } - - static const struct of_device_id sun50i_h6_ccu_ids[] = { -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c -index 225307305880e..22eb18079a154 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c -@@ -1141,9 +1141,7 @@ static void __init sun50i_h616_ccu_setup(struct device_node *node) - val |= BIT(24); - writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); - -- i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); -- if (i) -- pr_err("%pOF: probing clocks fails: %d\n", node, i); -+ of_sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); - } - - CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu", -diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c -index b78e9b507c1c6..1f4bc0e773a7e 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun5i.c -+++ b/drivers/clk/sunxi-ng/ccu-sun5i.c -@@ -1012,7 +1012,7 @@ static void __init sun5i_ccu_init(struct device_node *node, - val &= ~GENMASK(7, 6); - writel(val | (2 << 6), reg + SUN5I_AHB_REG); - -- sunxi_ccu_probe(node, reg, desc); -+ of_sunxi_ccu_probe(node, reg, desc); - } - - static void __init sun5i_a10s_ccu_setup(struct device_node *node) -diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c -index 9b40d53266a3f..3df5c0b415804 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c -+++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c -@@ -1257,7 +1257,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) - val |= 0x3 << 12; - writel(val, reg + SUN6I_A31_AHB1_REG); - -- sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); -+ of_sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); - - ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, - &sun6i_a31_cpu_nb); -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c -index 103aa504f6c8a..577bb235d6584 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c -@@ -745,7 +745,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) - val &= ~BIT(16); - writel(val, reg + SUN8I_A23_PLL_MIPI_REG); - -- sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); -+ of_sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); - } - CLK_OF_DECLARE(sun8i_a23_ccu, "allwinner,sun8i-a23-ccu", - sun8i_a23_ccu_setup); -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c -index 91838cd110377..8f65cd03f5acc 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c -@@ -805,7 +805,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node) - val &= ~BIT(16); - writel(val, reg + SUN8I_A33_PLL_MIPI_REG); - -- sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); -+ of_sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); - - /* Gate then ungate PLL CPU after any rate changes */ - ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb); -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c -index 2b434521c5ccf..c2ddcd2ddab4e 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c -@@ -906,7 +906,7 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev) - sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG); - sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG); - -- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_a83t_ccu_desc); -+ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc); - } - - static const struct of_device_id sun8i_a83t_ccu_ids[] = { -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c -index 524f33275bc73..4b94b6041b271 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c -@@ -342,7 +342,7 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev) - goto err_disable_mod_clk; - } - -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc); - if (ret) - goto err_assert_reset; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c -index 7e629a4493afd..d2fc2903787d8 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c -@@ -1154,7 +1154,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, - val &= ~GENMASK(19, 16); - writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); - -- sunxi_ccu_probe(node, reg, desc); -+ of_sunxi_ccu_probe(node, reg, desc); - - /* Gate then ungate PLL CPU after any rate changes */ - ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb); -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c -index 4c8c491b87c27..9e754d1f754a1 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c -@@ -265,7 +265,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, - return; - } - -- sunxi_ccu_probe(node, reg, desc); -+ of_sunxi_ccu_probe(node, reg, desc); - } - - static void __init sun8i_a83t_r_ccu_setup(struct device_node *node) -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c -index 84153418453f4..002e0c3a04dbe 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c -@@ -1346,7 +1346,7 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) - if (IS_ERR(regmap)) - return PTR_ERR(regmap); - -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_r40_ccu_desc); - if (ret) - return ret; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c -index f49724a22540e..ce150f83ab54e 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c -+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c -@@ -822,7 +822,7 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node, - val &= ~GENMASK(19, 16); - writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG); - -- sunxi_ccu_probe(node, reg, ccu_desc); -+ of_sunxi_ccu_probe(node, reg, ccu_desc); - } - - static void __init sun8i_v3s_ccu_setup(struct device_node *node) -diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c -index 6616e8114f623..261e64416f26a 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c -+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c -@@ -246,8 +246,7 @@ static int sun9i_a80_de_clk_probe(struct platform_device *pdev) - goto err_disable_clk; - } - -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, -- &sun9i_a80_de_clk_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc); - if (ret) - goto err_assert_reset; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c -index 4b4a507d04edf..596243b3e0fa3 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c -+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c -@@ -117,8 +117,7 @@ static int sun9i_a80_usb_clk_probe(struct platform_device *pdev) - return ret; - } - -- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, -- &sun9i_a80_usb_clk_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_usb_clk_desc); - if (ret) - goto err_disable_clk; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c -index ef29582676f6e..97aaed0e68500 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c -+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c -@@ -1231,7 +1231,7 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev) - sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG); - sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG); - -- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc); -+ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc); - } - - static const struct of_device_id sun9i_a80_ccu_ids[] = { -diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c -index 7ecc3a5a5b5e1..61ad7ee91c114 100644 ---- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c -+++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c -@@ -538,7 +538,7 @@ static void __init suniv_f1c100s_ccu_setup(struct device_node *node) - val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG); - -- sunxi_ccu_probe(node, reg, &suniv_ccu_desc); -+ of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc); - - /* Gate then ungate PLL CPU after any rate changes */ - ccu_pll_notifier_register(&suniv_pll_cpu_nb); -diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c -index 2e20e650b6c01..88cb569e58358 100644 ---- a/drivers/clk/sunxi-ng/ccu_common.c -+++ b/drivers/clk/sunxi-ng/ccu_common.c -@@ -7,6 +7,7 @@ - - #include <linux/clk.h> - #include <linux/clk-provider.h> -+#include <linux/device.h> - #include <linux/iopoll.h> - #include <linux/slab.h> - -@@ -14,6 +15,11 @@ - #include "ccu_gate.h" - #include "ccu_reset.h" - -+struct sunxi_ccu { -+ const struct sunxi_ccu_desc *desc; -+ struct ccu_reset reset; -+}; -+ - static DEFINE_SPINLOCK(ccu_lock); - - void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) -@@ -79,12 +85,15 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb) - &pll_nb->clk_nb); - } - --int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, -- const struct sunxi_ccu_desc *desc) -+static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, -+ struct device_node *node, void __iomem *reg, -+ const struct sunxi_ccu_desc *desc) - { - struct ccu_reset *reset; - int i, ret; - -+ ccu->desc = desc; -+ - for (i = 0; i < desc->num_ccu_clks; i++) { - struct ccu_common *cclk = desc->ccu_clks[i]; - -@@ -103,7 +112,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, - continue; - - name = hw->init->name; -- ret = of_clk_hw_register(node, hw); -+ if (dev) -+ ret = clk_hw_register(dev, hw); -+ else -+ ret = of_clk_hw_register(node, hw); - if (ret) { - pr_err("Couldn't register clock %d - %s\n", i, name); - goto err_clk_unreg; -@@ -115,15 +127,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, - if (ret) - goto err_clk_unreg; - -- reset = kzalloc(sizeof(*reset), GFP_KERNEL); -- if (!reset) { -- ret = -ENOMEM; -- goto err_alloc_reset; -- } -- -+ reset = &ccu->reset; - reset->rcdev.of_node = node; - reset->rcdev.ops = &ccu_reset_ops; -- reset->rcdev.owner = THIS_MODULE; -+ reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE; - reset->rcdev.nr_resets = desc->num_resets; - reset->base = reg; - reset->lock = &ccu_lock; -@@ -131,13 +138,11 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, - - ret = reset_controller_register(&reset->rcdev); - if (ret) -- goto err_of_clk_unreg; -+ goto err_del_provider; - - return 0; - --err_of_clk_unreg: -- kfree(reset); --err_alloc_reset: -+err_del_provider: - of_clk_del_provider(node); - err_clk_unreg: - while (--i >= 0) { -@@ -149,3 +154,59 @@ err_clk_unreg: - } - return ret; - } -+ -+static void devm_sunxi_ccu_release(struct device *dev, void *res) -+{ -+ struct sunxi_ccu *ccu = res; -+ const struct sunxi_ccu_desc *desc = ccu->desc; -+ int i; -+ -+ reset_controller_unregister(&ccu->reset.rcdev); -+ of_clk_del_provider(dev->of_node); -+ -+ for (i = 0; i < desc->hw_clks->num; i++) { -+ struct clk_hw *hw = desc->hw_clks->hws[i]; -+ -+ if (!hw) -+ continue; -+ clk_hw_unregister(hw); -+ } -+} -+ -+int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, -+ const struct sunxi_ccu_desc *desc) -+{ -+ struct sunxi_ccu *ccu; -+ int ret; -+ -+ ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL); -+ if (!ccu) -+ return -ENOMEM; -+ -+ ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc); -+ if (ret) { -+ devres_free(ccu); -+ return ret; -+ } -+ -+ devres_add(dev, ccu); -+ -+ return 0; -+} -+ -+void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, -+ const struct sunxi_ccu_desc *desc) -+{ -+ struct sunxi_ccu *ccu; -+ int ret; -+ -+ ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); -+ if (!ccu) -+ return; -+ -+ ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc); -+ if (ret) { -+ pr_err("%pOF: probing clocks failed: %d\n", node, ret); -+ kfree(ccu); -+ } -+} -diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h -index 04e7a12200a21..98a1834b58bb4 100644 ---- a/drivers/clk/sunxi-ng/ccu_common.h -+++ b/drivers/clk/sunxi-ng/ccu_common.h -@@ -63,7 +63,9 @@ struct ccu_pll_nb { - - int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb); - --int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, -- const struct sunxi_ccu_desc *desc); -+int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, -+ const struct sunxi_ccu_desc *desc); -+void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, -+ const struct sunxi_ccu_desc *desc); - - #endif /* _COMMON_H_ */ -diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig -index 0f5e3983951a8..08f8cb944a2ac 100644 ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -24,6 +24,7 @@ config I8253_LOCK - - config OMAP_DM_TIMER - bool -+ select TIMER_OF - - config CLKBLD_I8253 - def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK -diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c -index 3819ef5b70989..3245eb0c602d2 100644 ---- a/drivers/clocksource/dw_apb_timer_of.c -+++ b/drivers/clocksource/dw_apb_timer_of.c -@@ -47,7 +47,7 @@ static int __init timer_get_base_and_rate(struct device_node *np, - pr_warn("pclk for %pOFn is present, but could not be activated\n", - np); - -- if (!of_property_read_u32(np, "clock-freq", rate) && -+ if (!of_property_read_u32(np, "clock-freq", rate) || - !of_property_read_u32(np, "clock-frequency", rate)) - return 0; - -diff --git a/drivers/comedi/drivers/dt9812.c b/drivers/comedi/drivers/dt9812.c -index 634f57730c1e0..704b04d2980d3 100644 ---- a/drivers/comedi/drivers/dt9812.c -+++ b/drivers/comedi/drivers/dt9812.c -@@ -32,6 +32,7 @@ - #include <linux/kernel.h> - #include <linux/module.h> - #include <linux/errno.h> -+#include <linux/slab.h> - #include <linux/uaccess.h> - - #include "../comedi_usb.h" -@@ -237,22 +238,42 @@ static int dt9812_read_info(struct comedi_device *dev, - { - struct usb_device *usb = comedi_to_usb_dev(dev); - struct dt9812_private *devpriv = dev->private; -- struct dt9812_usb_cmd cmd; -+ struct dt9812_usb_cmd *cmd; -+ size_t tbuf_size; - int count, ret; -+ void *tbuf; - -- cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA); -- cmd.u.flash_data_info.address = -+ tbuf_size = max(sizeof(*cmd), buf_size); -+ -+ tbuf = kzalloc(tbuf_size, GFP_KERNEL); -+ if (!tbuf) -+ return -ENOMEM; -+ -+ cmd = tbuf; -+ -+ cmd->cmd = cpu_to_le32(DT9812_R_FLASH_DATA); -+ cmd->u.flash_data_info.address = - cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset); -- cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size); -+ cmd->u.flash_data_info.numbytes = cpu_to_le16(buf_size); - - /* DT9812 only responds to 32 byte writes!! */ - ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), -- &cmd, 32, &count, DT9812_USB_TIMEOUT); -+ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); - if (ret) -- return ret; -+ goto out; -+ -+ ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), -+ tbuf, buf_size, &count, DT9812_USB_TIMEOUT); -+ if (!ret) { -+ if (count == buf_size) -+ memcpy(buf, tbuf, buf_size); -+ else -+ ret = -EREMOTEIO; -+ } -+out: -+ kfree(tbuf); - -- return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), -- buf, buf_size, &count, DT9812_USB_TIMEOUT); -+ return ret; - } - - static int dt9812_read_multiple_registers(struct comedi_device *dev, -@@ -261,22 +282,42 @@ static int dt9812_read_multiple_registers(struct comedi_device *dev, - { - struct usb_device *usb = comedi_to_usb_dev(dev); - struct dt9812_private *devpriv = dev->private; -- struct dt9812_usb_cmd cmd; -+ struct dt9812_usb_cmd *cmd; - int i, count, ret; -+ size_t buf_size; -+ void *buf; - -- cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG); -- cmd.u.read_multi_info.count = reg_count; -+ buf_size = max_t(size_t, sizeof(*cmd), reg_count); -+ -+ buf = kzalloc(buf_size, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ cmd = buf; -+ -+ cmd->cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG); -+ cmd->u.read_multi_info.count = reg_count; - for (i = 0; i < reg_count; i++) -- cmd.u.read_multi_info.address[i] = address[i]; -+ cmd->u.read_multi_info.address[i] = address[i]; - - /* DT9812 only responds to 32 byte writes!! */ - ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), -- &cmd, 32, &count, DT9812_USB_TIMEOUT); -+ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); - if (ret) -- return ret; -+ goto out; -+ -+ ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), -+ buf, reg_count, &count, DT9812_USB_TIMEOUT); -+ if (!ret) { -+ if (count == reg_count) -+ memcpy(value, buf, reg_count); -+ else -+ ret = -EREMOTEIO; -+ } -+out: -+ kfree(buf); - -- return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), -- value, reg_count, &count, DT9812_USB_TIMEOUT); -+ return ret; - } - - static int dt9812_write_multiple_registers(struct comedi_device *dev, -@@ -285,19 +326,27 @@ static int dt9812_write_multiple_registers(struct comedi_device *dev, - { - struct usb_device *usb = comedi_to_usb_dev(dev); - struct dt9812_private *devpriv = dev->private; -- struct dt9812_usb_cmd cmd; -+ struct dt9812_usb_cmd *cmd; - int i, count; -+ int ret; -+ -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (!cmd) -+ return -ENOMEM; - -- cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG); -- cmd.u.read_multi_info.count = reg_count; -+ cmd->cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG); -+ cmd->u.read_multi_info.count = reg_count; - for (i = 0; i < reg_count; i++) { -- cmd.u.write_multi_info.write[i].address = address[i]; -- cmd.u.write_multi_info.write[i].value = value[i]; -+ cmd->u.write_multi_info.write[i].address = address[i]; -+ cmd->u.write_multi_info.write[i].value = value[i]; - } - - /* DT9812 only responds to 32 byte writes!! */ -- return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), -- &cmd, 32, &count, DT9812_USB_TIMEOUT); -+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), -+ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); -+ kfree(cmd); -+ -+ return ret; - } - - static int dt9812_rmw_multiple_registers(struct comedi_device *dev, -@@ -306,17 +355,25 @@ static int dt9812_rmw_multiple_registers(struct comedi_device *dev, - { - struct usb_device *usb = comedi_to_usb_dev(dev); - struct dt9812_private *devpriv = dev->private; -- struct dt9812_usb_cmd cmd; -+ struct dt9812_usb_cmd *cmd; - int i, count; -+ int ret; -+ -+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); -+ if (!cmd) -+ return -ENOMEM; - -- cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG); -- cmd.u.rmw_multi_info.count = reg_count; -+ cmd->cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG); -+ cmd->u.rmw_multi_info.count = reg_count; - for (i = 0; i < reg_count; i++) -- cmd.u.rmw_multi_info.rmw[i] = rmw[i]; -+ cmd->u.rmw_multi_info.rmw[i] = rmw[i]; - - /* DT9812 only responds to 32 byte writes!! */ -- return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), -- &cmd, 32, &count, DT9812_USB_TIMEOUT); -+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), -+ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); -+ kfree(cmd); -+ -+ return ret; - } - - static int dt9812_digital_in(struct comedi_device *dev, u8 *bits) -diff --git a/drivers/comedi/drivers/ni_usb6501.c b/drivers/comedi/drivers/ni_usb6501.c -index 5b6d9d783b2f7..c42987b74b1dc 100644 ---- a/drivers/comedi/drivers/ni_usb6501.c -+++ b/drivers/comedi/drivers/ni_usb6501.c -@@ -144,6 +144,10 @@ static const u8 READ_COUNTER_RESPONSE[] = {0x00, 0x01, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00}; - -+/* Largest supported packets */ -+static const size_t TX_MAX_SIZE = sizeof(SET_PORT_DIR_REQUEST); -+static const size_t RX_MAX_SIZE = sizeof(READ_PORT_RESPONSE); -+ - enum commands { - READ_PORT, - WRITE_PORT, -@@ -501,6 +505,12 @@ static int ni6501_find_endpoints(struct comedi_device *dev) - if (!devpriv->ep_rx || !devpriv->ep_tx) - return -ENODEV; - -+ if (usb_endpoint_maxp(devpriv->ep_rx) < RX_MAX_SIZE) -+ return -ENODEV; -+ -+ if (usb_endpoint_maxp(devpriv->ep_tx) < TX_MAX_SIZE) -+ return -ENODEV; -+ - return 0; - } - -diff --git a/drivers/comedi/drivers/vmk80xx.c b/drivers/comedi/drivers/vmk80xx.c -index 9f920819cd742..4b00a9ea611ab 100644 ---- a/drivers/comedi/drivers/vmk80xx.c -+++ b/drivers/comedi/drivers/vmk80xx.c -@@ -90,6 +90,9 @@ enum { - #define IC3_VERSION BIT(0) - #define IC6_VERSION BIT(1) - -+#define MIN_BUF_SIZE 64 -+#define PACKET_TIMEOUT 10000 /* ms */ -+ - enum vmk80xx_model { - VMK8055_MODEL, - VMK8061_MODEL -@@ -157,22 +160,21 @@ static void vmk80xx_do_bulk_msg(struct comedi_device *dev) - __u8 rx_addr; - unsigned int tx_pipe; - unsigned int rx_pipe; -- size_t size; -+ size_t tx_size; -+ size_t rx_size; - - tx_addr = devpriv->ep_tx->bEndpointAddress; - rx_addr = devpriv->ep_rx->bEndpointAddress; - tx_pipe = usb_sndbulkpipe(usb, tx_addr); - rx_pipe = usb_rcvbulkpipe(usb, rx_addr); -+ tx_size = usb_endpoint_maxp(devpriv->ep_tx); -+ rx_size = usb_endpoint_maxp(devpriv->ep_rx); - -- /* -- * The max packet size attributes of the K8061 -- * input/output endpoints are identical -- */ -- size = usb_endpoint_maxp(devpriv->ep_tx); -+ usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, tx_size, NULL, -+ PACKET_TIMEOUT); - -- usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, -- size, NULL, devpriv->ep_tx->bInterval); -- usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, size, NULL, HZ * 10); -+ usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, rx_size, NULL, -+ PACKET_TIMEOUT); - } - - static int vmk80xx_read_packet(struct comedi_device *dev) -@@ -191,7 +193,7 @@ static int vmk80xx_read_packet(struct comedi_device *dev) - pipe = usb_rcvintpipe(usb, ep->bEndpointAddress); - return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf, - usb_endpoint_maxp(ep), NULL, -- HZ * 10); -+ PACKET_TIMEOUT); - } - - static int vmk80xx_write_packet(struct comedi_device *dev, int cmd) -@@ -212,7 +214,7 @@ static int vmk80xx_write_packet(struct comedi_device *dev, int cmd) - pipe = usb_sndintpipe(usb, ep->bEndpointAddress); - return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf, - usb_endpoint_maxp(ep), NULL, -- HZ * 10); -+ PACKET_TIMEOUT); - } - - static int vmk80xx_reset_device(struct comedi_device *dev) -@@ -678,12 +680,12 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev) - struct vmk80xx_private *devpriv = dev->private; - size_t size; - -- size = usb_endpoint_maxp(devpriv->ep_rx); -+ size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE); - devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL); - if (!devpriv->usb_rx_buf) - return -ENOMEM; - -- size = usb_endpoint_maxp(devpriv->ep_tx); -+ size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE); - devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL); - if (!devpriv->usb_tx_buf) - return -ENOMEM; -diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index 5782b15a8caad..fcb44352623ee 100644 ---- a/drivers/cpufreq/cpufreq.c -+++ b/drivers/cpufreq/cpufreq.c -@@ -1004,10 +1004,9 @@ static struct kobj_type ktype_cpufreq = { - .release = cpufreq_sysfs_release, - }; - --static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu) -+static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu, -+ struct device *dev) - { -- struct device *dev = get_cpu_device(cpu); -- - if (unlikely(!dev)) - return; - -@@ -1391,7 +1390,7 @@ static int cpufreq_online(unsigned int cpu) - if (new_policy) { - for_each_cpu(j, policy->related_cpus) { - per_cpu(cpufreq_cpu_data, j) = policy; -- add_cpu_dev_symlink(policy, j); -+ add_cpu_dev_symlink(policy, j, get_cpu_device(j)); - } - - policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req), -@@ -1565,7 +1564,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) - /* Create sysfs link on CPU registration */ - policy = per_cpu(cpufreq_cpu_data, cpu); - if (policy) -- add_cpu_dev_symlink(policy, cpu); -+ add_cpu_dev_symlink(policy, cpu, dev); - - return 0; - } -@@ -2523,8 +2522,15 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, - if (ret) - return ret; - -+ /* -+ * Resolve policy min/max to available frequencies. It ensures -+ * no frequency resolution will neither overshoot the requested maximum -+ * nor undershoot the requested minimum. -+ */ - policy->min = new_data.min; - policy->max = new_data.max; -+ policy->min = __resolve_freq(policy, policy->min, CPUFREQ_RELATION_L); -+ policy->max = __resolve_freq(policy, policy->max, CPUFREQ_RELATION_H); - trace_cpu_frequency_limits(policy); - - policy->cached_target_freq = UINT_MAX; -diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c -index 8c176b7dae415..e15c3bc17a55c 100644 ---- a/drivers/cpufreq/intel_pstate.c -+++ b/drivers/cpufreq/intel_pstate.c -@@ -537,7 +537,8 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) - * scaling factor is too high, so recompute it to make the HWP_CAP - * highest performance correspond to the maximum turbo frequency. - */ -- if (turbo_freq < cpu->pstate.turbo_pstate * scaling) { -+ cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling; -+ if (turbo_freq < cpu->pstate.turbo_freq) { - cpu->pstate.turbo_freq = turbo_freq; - scaling = DIV_ROUND_UP(turbo_freq, cpu->pstate.turbo_pstate); - cpu->pstate.scaling = scaling; -@@ -998,9 +999,22 @@ static void intel_pstate_hwp_offline(struct cpudata *cpu) - */ - value &= ~GENMASK_ULL(31, 24); - value |= HWP_ENERGY_PERF_PREFERENCE(cpu->epp_cached); -- WRITE_ONCE(cpu->hwp_req_cached, value); -+ /* -+ * However, make sure that EPP will be set to "performance" when -+ * the CPU is brought back online again and the "performance" -+ * scaling algorithm is still in effect. -+ */ -+ cpu->epp_policy = CPUFREQ_POLICY_UNKNOWN; - } - -+ /* -+ * Clear the desired perf field in the cached HWP request value to -+ * prevent nonzero desired values from being leaked into the active -+ * mode. -+ */ -+ value &= ~HWP_DESIRED_PERF(~0L); -+ WRITE_ONCE(cpu->hwp_req_cached, value); -+ - value &= ~GENMASK_ULL(31, 0); - min_perf = HWP_LOWEST_PERF(READ_ONCE(cpu->hwp_cap_cached)); - -@@ -2241,6 +2255,7 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = { - X86_MATCH(BROADWELL_D, core_funcs), - X86_MATCH(BROADWELL_X, core_funcs), - X86_MATCH(SKYLAKE_X, core_funcs), -+ X86_MATCH(ICELAKE_X, core_funcs), - {} - }; - -@@ -2902,6 +2917,27 @@ static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy) - return intel_pstate_cpu_exit(policy); - } - -+static int intel_cpufreq_suspend(struct cpufreq_policy *policy) -+{ -+ intel_pstate_suspend(policy); -+ -+ if (hwp_active) { -+ struct cpudata *cpu = all_cpu_data[policy->cpu]; -+ u64 value = READ_ONCE(cpu->hwp_req_cached); -+ -+ /* -+ * Clear the desired perf field in MSR_HWP_REQUEST in case -+ * intel_cpufreq_adjust_perf() is in use and the last value -+ * written by it may not be suitable. -+ */ -+ value &= ~HWP_DESIRED_PERF(~0L); -+ wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, value); -+ WRITE_ONCE(cpu->hwp_req_cached, value); -+ } -+ -+ return 0; -+} -+ - static struct cpufreq_driver intel_cpufreq = { - .flags = CPUFREQ_CONST_LOOPS, - .verify = intel_cpufreq_verify_policy, -@@ -2911,7 +2947,7 @@ static struct cpufreq_driver intel_cpufreq = { - .exit = intel_cpufreq_cpu_exit, - .offline = intel_cpufreq_cpu_offline, - .online = intel_pstate_cpu_online, -- .suspend = intel_pstate_suspend, -+ .suspend = intel_cpufreq_suspend, - .resume = intel_pstate_resume, - .update_limits = intel_pstate_update_limits, - .name = "intel_cpufreq", -diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c -index 53ec9585ccd44..469e18547d06c 100644 ---- a/drivers/cpuidle/sysfs.c -+++ b/drivers/cpuidle/sysfs.c -@@ -488,6 +488,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) - &kdev->kobj, "state%d", i); - if (ret) { - kobject_put(&kobj->kobj); -+ kfree(kobj); - goto error_state; - } - cpuidle_add_s2idle_attr_group(kobj); -@@ -619,6 +620,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) - &kdev->kobj, "driver"); - if (ret) { - kobject_put(&kdrv->kobj); -+ kfree(kdrv); - return ret; - } - -@@ -705,7 +707,6 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev) - if (!kdev) - return -ENOMEM; - kdev->dev = dev; -- dev->kobj_dev = kdev; - - init_completion(&kdev->kobj_unregister); - -@@ -713,9 +714,11 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev) - "cpuidle"); - if (error) { - kobject_put(&kdev->kobj); -+ kfree(kdev); - return error; - } - -+ dev->kobj_dev = kdev; - kobject_uevent(&kdev->kobj, KOBJ_ADD); - - return 0; -diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c -index e313233ec6de7..bf6275ffc4aad 100644 ---- a/drivers/crypto/caam/caampkc.c -+++ b/drivers/crypto/caam/caampkc.c -@@ -1153,16 +1153,27 @@ static struct caam_akcipher_alg caam_rsa = { - int caam_pkc_init(struct device *ctrldev) - { - struct caam_drv_private *priv = dev_get_drvdata(ctrldev); -- u32 pk_inst; -+ u32 pk_inst, pkha; - int err; - init_done = false; - - /* Determine public key hardware accelerator presence. */ -- if (priv->era < 10) -+ if (priv->era < 10) { - pk_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & - CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT; -- else -- pk_inst = rd_reg32(&priv->ctrl->vreg.pkha) & CHA_VER_NUM_MASK; -+ } else { -+ pkha = rd_reg32(&priv->ctrl->vreg.pkha); -+ pk_inst = pkha & CHA_VER_NUM_MASK; -+ -+ /* -+ * Newer CAAMs support partially disabled functionality. If this is the -+ * case, the number is non-zero, but this bit is set to indicate that -+ * no encryption or decryption is supported. Only signing and verifying -+ * is supported. -+ */ -+ if (pkha & CHA_VER_MISC_PKHA_NO_CRYPT) -+ pk_inst = 0; -+ } - - /* Do not register algorithms if PKHA is not present. */ - if (!pk_inst) -diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h -index af61f3a2c0d46..3738625c02509 100644 ---- a/drivers/crypto/caam/regs.h -+++ b/drivers/crypto/caam/regs.h -@@ -322,6 +322,9 @@ struct version_regs { - /* CHA Miscellaneous Information - AESA_MISC specific */ - #define CHA_VER_MISC_AES_GCM BIT(1 + CHA_VER_MISC_SHIFT) - -+/* CHA Miscellaneous Information - PKHA_MISC specific */ -+#define CHA_VER_MISC_PKHA_NO_CRYPT BIT(7 + CHA_VER_MISC_SHIFT) -+ - /* - * caam_perfmon - Performance Monitor/Secure Memory Status/ - * CAAM Global Status/Component Version IDs -diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c -index e599ac6dc162a..790fa9058a36d 100644 ---- a/drivers/crypto/ccree/cc_driver.c -+++ b/drivers/crypto/ccree/cc_driver.c -@@ -103,7 +103,8 @@ MODULE_DEVICE_TABLE(of, arm_ccree_dev_of_match); - static void init_cc_cache_params(struct cc_drvdata *drvdata) - { - struct device *dev = drvdata_to_dev(drvdata); -- u32 cache_params, ace_const, val, mask; -+ u32 cache_params, ace_const, val; -+ u64 mask; - - /* compute CC_AXIM_CACHE_PARAMS */ - cache_params = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS)); -diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c -index a72723455df72..877a948469bd1 100644 ---- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c -+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c -@@ -1274,6 +1274,7 @@ static int aead_do_fallback(struct aead_request *req, bool is_enc) - req->base.complete, req->base.data); - aead_request_set_crypt(&rctx->fbk_req, req->src, - req->dst, req->cryptlen, req->iv); -+ aead_request_set_ad(&rctx->fbk_req, req->assoclen); - ret = is_enc ? crypto_aead_encrypt(&rctx->fbk_req) : - crypto_aead_decrypt(&rctx->fbk_req); - } else { -diff --git a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c -index 33d8e50dcbdac..88c0ded411f15 100644 ---- a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c -+++ b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) - /* Copyright(c) 2020 Intel Corporation */ -+#include <linux/iopoll.h> - #include <adf_accel_devices.h> - #include <adf_common_drv.h> - #include <adf_pf2vf_msg.h> -@@ -161,6 +162,35 @@ static void adf_enable_ints(struct adf_accel_dev *accel_dev) - ADF_CSR_WR(addr, ADF_4XXX_SMIAPF_MASK_OFFSET, 0); - } - -+static int adf_init_device(struct adf_accel_dev *accel_dev) -+{ -+ void __iomem *addr; -+ u32 status; -+ u32 csr; -+ int ret; -+ -+ addr = (&GET_BARS(accel_dev)[ADF_4XXX_PMISC_BAR])->virt_addr; -+ -+ /* Temporarily mask PM interrupt */ -+ csr = ADF_CSR_RD(addr, ADF_4XXX_ERRMSK2); -+ csr |= ADF_4XXX_PM_SOU; -+ ADF_CSR_WR(addr, ADF_4XXX_ERRMSK2, csr); -+ -+ /* Set DRV_ACTIVE bit to power up the device */ -+ ADF_CSR_WR(addr, ADF_4XXX_PM_INTERRUPT, ADF_4XXX_PM_DRV_ACTIVE); -+ -+ /* Poll status register to make sure the device is powered up */ -+ ret = read_poll_timeout(ADF_CSR_RD, status, -+ status & ADF_4XXX_PM_INIT_STATE, -+ ADF_4XXX_PM_POLL_DELAY_US, -+ ADF_4XXX_PM_POLL_TIMEOUT_US, true, addr, -+ ADF_4XXX_PM_STATUS); -+ if (ret) -+ dev_err(&GET_DEV(accel_dev), "Failed to power up the device\n"); -+ -+ return ret; -+} -+ - static int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev) - { - return 0; -@@ -215,6 +245,7 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data) - hw_data->exit_arb = adf_exit_arb; - hw_data->get_arb_mapping = adf_get_arbiter_mapping; - hw_data->enable_ints = adf_enable_ints; -+ hw_data->init_device = adf_init_device; - hw_data->reset_device = adf_reset_flr; - hw_data->admin_ae_mask = ADF_4XXX_ADMIN_AE_MASK; - hw_data->uof_get_num_objs = uof_get_num_objs; -diff --git a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h -index 4fe2a776293c2..924bac6feb372 100644 ---- a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h -+++ b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h -@@ -62,6 +62,16 @@ - #define ADF_4XXX_ADMINMSGLR_OFFSET (0x500578) - #define ADF_4XXX_MAILBOX_BASE_OFFSET (0x600970) - -+/* Power management */ -+#define ADF_4XXX_PM_POLL_DELAY_US 20 -+#define ADF_4XXX_PM_POLL_TIMEOUT_US USEC_PER_SEC -+#define ADF_4XXX_PM_STATUS (0x50A00C) -+#define ADF_4XXX_PM_INTERRUPT (0x50A028) -+#define ADF_4XXX_PM_DRV_ACTIVE BIT(20) -+#define ADF_4XXX_PM_INIT_STATE BIT(21) -+/* Power management source in ERRSOU2 and ERRMSK2 */ -+#define ADF_4XXX_PM_SOU BIT(18) -+ - /* Firmware Binaries */ - #define ADF_4XXX_FW "qat_4xxx.bin" - #define ADF_4XXX_MMP "qat_4xxx_mmp.bin" -diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h -index 38c0af6d4e43e..580566cfcb04c 100644 ---- a/drivers/crypto/qat/qat_common/adf_accel_devices.h -+++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h -@@ -166,6 +166,7 @@ struct adf_hw_device_data { - int (*init_arb)(struct adf_accel_dev *accel_dev); - void (*exit_arb)(struct adf_accel_dev *accel_dev); - const u32 *(*get_arb_mapping)(void); -+ int (*init_device)(struct adf_accel_dev *accel_dev); - void (*disable_iov)(struct adf_accel_dev *accel_dev); - void (*configure_iov_threads)(struct adf_accel_dev *accel_dev, - bool enable); -diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c -index 60bc7b991d351..e3749e5817d94 100644 ---- a/drivers/crypto/qat/qat_common/adf_init.c -+++ b/drivers/crypto/qat/qat_common/adf_init.c -@@ -79,6 +79,11 @@ int adf_dev_init(struct adf_accel_dev *accel_dev) - return -EFAULT; - } - -+ if (hw_data->init_device && hw_data->init_device(accel_dev)) { -+ dev_err(&GET_DEV(accel_dev), "Failed to initialize device\n"); -+ return -EFAULT; -+ } -+ - if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) { - dev_err(&GET_DEV(accel_dev), "Failed initialize admin comms\n"); - return -EFAULT; -diff --git a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c -index 976b9ab7617cd..5a41beb8f20f6 100644 ---- a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c -+++ b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c -@@ -156,6 +156,13 @@ static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr) - val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset); - } while ((val & int_bit) && (count++ < ADF_IOV_MSG_ACK_MAX_RETRY)); - -+ if (val != msg) { -+ dev_dbg(&GET_DEV(accel_dev), -+ "Collision - PFVF CSR overwritten by remote function\n"); -+ ret = -EIO; -+ goto out; -+ } -+ - if (val & int_bit) { - dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n"); - val &= ~int_bit; -@@ -204,6 +211,11 @@ void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info) - - /* Read message from the VF */ - msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr)); -+ if (!(msg & ADF_VF2PF_INT)) { -+ dev_info(&GET_DEV(accel_dev), -+ "Spurious VF2PF interrupt, msg %X. Ignored\n", msg); -+ goto out; -+ } - - /* To ACK, clear the VF2PFINT bit */ - msg &= ~ADF_VF2PF_INT; -@@ -287,6 +299,7 @@ void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info) - if (resp && adf_iov_putmsg(accel_dev, resp, vf_nr)) - dev_err(&GET_DEV(accel_dev), "Failed to send response to VF\n"); - -+out: - /* re-enable interrupt on PF from this VF */ - adf_enable_vf2pf_interrupts(accel_dev, (1 << vf_nr)); - -diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c -index 7828a6573f3e2..2e300c255ab94 100644 ---- a/drivers/crypto/qat/qat_common/adf_vf_isr.c -+++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c -@@ -101,6 +101,11 @@ static void adf_pf2vf_bh_handler(void *data) - - /* Read the message from PF */ - msg = ADF_CSR_RD(pmisc_bar_addr, hw_data->get_pf2vf_offset(0)); -+ if (!(msg & ADF_PF2VF_INT)) { -+ dev_info(&GET_DEV(accel_dev), -+ "Spurious PF2VF interrupt, msg %X. Ignored\n", msg); -+ goto out; -+ } - - if (!(msg & ADF_PF2VF_MSGORIGIN_SYSTEM)) - /* Ignore legacy non-system (non-kernel) PF2VF messages */ -@@ -149,6 +154,7 @@ static void adf_pf2vf_bh_handler(void *data) - msg &= ~ADF_PF2VF_INT; - ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg); - -+out: - /* Re-enable PF2VF interrupts */ - adf_enable_pf2vf_interrupts(accel_dev); - return; -diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c -index 55aa3a71169b0..7717e9e5977bb 100644 ---- a/drivers/crypto/s5p-sss.c -+++ b/drivers/crypto/s5p-sss.c -@@ -2171,6 +2171,8 @@ static int s5p_aes_probe(struct platform_device *pdev) - - variant = find_s5p_sss_version(pdev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -EINVAL; - - /* - * Note: HASH and PRNG uses the same registers in secss, avoid -diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c -index 8e45aa07d662f..5444b5a7fd3c4 100644 ---- a/drivers/cxl/pci.c -+++ b/drivers/cxl/pci.c -@@ -972,7 +972,7 @@ static void __iomem *cxl_mem_map_regblock(struct cxl_mem *cxlm, - if (pci_resource_len(pdev, bar) < offset) { - dev_err(dev, "BAR%d: %pr: too small (offset: %#llx)\n", bar, - &pdev->resource[bar], (unsigned long long)offset); -- return IOMEM_ERR_PTR(-ENXIO); -+ return NULL; - } - - addr = pci_iomap(pdev, bar, 0); -diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c -index 63d32261b63ff..61e20ae7b08b7 100644 ---- a/drivers/dma-buf/dma-buf.c -+++ b/drivers/dma-buf/dma-buf.c -@@ -74,7 +74,7 @@ static void dma_buf_release(struct dentry *dentry) - * If you hit this BUG() it means someone dropped their ref to the - * dma-buf while still having pending operation to the buffer. - */ -- BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active); -+ BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active); - - dma_buf_stats_teardown(dmabuf); - dmabuf->ops->release(dmabuf); -@@ -82,6 +82,7 @@ static void dma_buf_release(struct dentry *dentry) - if (dmabuf->resv == (struct dma_resv *)&dmabuf[1]) - dma_resv_fini(dmabuf->resv); - -+ WARN_ON(!list_empty(&dmabuf->attachments)); - module_put(dmabuf->owner); - kfree(dmabuf->name); - kfree(dmabuf); -@@ -205,16 +206,55 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb) - wake_up_locked_poll(dcb->poll, dcb->active); - dcb->active = 0; - spin_unlock_irqrestore(&dcb->poll->lock, flags); -+ dma_fence_put(fence); -+} -+ -+static bool dma_buf_poll_shared(struct dma_resv *resv, -+ struct dma_buf_poll_cb_t *dcb) -+{ -+ struct dma_resv_list *fobj = dma_resv_shared_list(resv); -+ struct dma_fence *fence; -+ int i, r; -+ -+ if (!fobj) -+ return false; -+ -+ for (i = 0; i < fobj->shared_count; ++i) { -+ fence = rcu_dereference_protected(fobj->shared[i], -+ dma_resv_held(resv)); -+ dma_fence_get(fence); -+ r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb); -+ if (!r) -+ return true; -+ dma_fence_put(fence); -+ } -+ -+ return false; -+} -+ -+static bool dma_buf_poll_excl(struct dma_resv *resv, -+ struct dma_buf_poll_cb_t *dcb) -+{ -+ struct dma_fence *fence = dma_resv_excl_fence(resv); -+ int r; -+ -+ if (!fence) -+ return false; -+ -+ dma_fence_get(fence); -+ r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb); -+ if (!r) -+ return true; -+ dma_fence_put(fence); -+ -+ return false; - } - - static __poll_t dma_buf_poll(struct file *file, poll_table *poll) - { - struct dma_buf *dmabuf; - struct dma_resv *resv; -- struct dma_resv_list *fobj; -- struct dma_fence *fence_excl; - __poll_t events; -- unsigned shared_count, seq; - - dmabuf = file->private_data; - if (!dmabuf || !dmabuf->resv) -@@ -228,101 +268,50 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) - if (!events) - return 0; - --retry: -- seq = read_seqcount_begin(&resv->seq); -- rcu_read_lock(); -- -- fobj = rcu_dereference(resv->fence); -- if (fobj) -- shared_count = fobj->shared_count; -- else -- shared_count = 0; -- fence_excl = dma_resv_excl_fence(resv); -- if (read_seqcount_retry(&resv->seq, seq)) { -- rcu_read_unlock(); -- goto retry; -- } -- -- if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) { -- struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl; -- __poll_t pevents = EPOLLIN; -+ dma_resv_lock(resv, NULL); - -- if (shared_count == 0) -- pevents |= EPOLLOUT; -+ if (events & EPOLLOUT) { -+ struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_out; - -+ /* Check that callback isn't busy */ - spin_lock_irq(&dmabuf->poll.lock); -- if (dcb->active) { -- dcb->active |= pevents; -- events &= ~pevents; -- } else -- dcb->active = pevents; -+ if (dcb->active) -+ events &= ~EPOLLOUT; -+ else -+ dcb->active = EPOLLOUT; - spin_unlock_irq(&dmabuf->poll.lock); - -- if (events & pevents) { -- if (!dma_fence_get_rcu(fence_excl)) { -- /* force a recheck */ -- events &= ~pevents; -- dma_buf_poll_cb(NULL, &dcb->cb); -- } else if (!dma_fence_add_callback(fence_excl, &dcb->cb, -- dma_buf_poll_cb)) { -- events &= ~pevents; -- dma_fence_put(fence_excl); -- } else { -- /* -- * No callback queued, wake up any additional -- * waiters. -- */ -- dma_fence_put(fence_excl); -+ if (events & EPOLLOUT) { -+ if (!dma_buf_poll_shared(resv, dcb) && -+ !dma_buf_poll_excl(resv, dcb)) -+ /* No callback queued, wake up any other waiters */ - dma_buf_poll_cb(NULL, &dcb->cb); -- } -+ else -+ events &= ~EPOLLOUT; - } - } - -- if ((events & EPOLLOUT) && shared_count > 0) { -- struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared; -- int i; -+ if (events & EPOLLIN) { -+ struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_in; - -- /* Only queue a new callback if no event has fired yet */ -+ /* Check that callback isn't busy */ - spin_lock_irq(&dmabuf->poll.lock); - if (dcb->active) -- events &= ~EPOLLOUT; -+ events &= ~EPOLLIN; - else -- dcb->active = EPOLLOUT; -+ dcb->active = EPOLLIN; - spin_unlock_irq(&dmabuf->poll.lock); - -- if (!(events & EPOLLOUT)) -- goto out; -- -- for (i = 0; i < shared_count; ++i) { -- struct dma_fence *fence = rcu_dereference(fobj->shared[i]); -- -- if (!dma_fence_get_rcu(fence)) { -- /* -- * fence refcount dropped to zero, this means -- * that fobj has been freed -- * -- * call dma_buf_poll_cb and force a recheck! -- */ -- events &= ~EPOLLOUT; -+ if (events & EPOLLIN) { -+ if (!dma_buf_poll_excl(resv, dcb)) -+ /* No callback queued, wake up any other waiters */ - dma_buf_poll_cb(NULL, &dcb->cb); -- break; -- } -- if (!dma_fence_add_callback(fence, &dcb->cb, -- dma_buf_poll_cb)) { -- dma_fence_put(fence); -- events &= ~EPOLLOUT; -- break; -- } -- dma_fence_put(fence); -+ else -+ events &= ~EPOLLIN; - } -- -- /* No callback queued, wake up any additional waiters. */ -- if (i == shared_count) -- dma_buf_poll_cb(NULL, &dcb->cb); - } - --out: -- rcu_read_unlock(); -+ dma_resv_unlock(resv); - return events; - } - -@@ -565,8 +554,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) - dmabuf->owner = exp_info->owner; - spin_lock_init(&dmabuf->name_lock); - init_waitqueue_head(&dmabuf->poll); -- dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll; -- dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0; -+ dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll; -+ dmabuf->cb_in.active = dmabuf->cb_out.active = 0; - - if (!resv) { - resv = (struct dma_resv *)&dmabuf[1]; -diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c -index 23a7e74ef9666..8660508f3684f 100644 ---- a/drivers/dma-buf/heaps/system_heap.c -+++ b/drivers/dma-buf/heaps/system_heap.c -@@ -289,7 +289,7 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) - int i; - - table = &buffer->sg_table; -- for_each_sg(table->sgl, sg, table->nents, i) { -+ for_each_sgtable_sg(table, sg, i) { - struct page *page = sg_page(sg); - - __free_pages(page, compound_order(page)); -diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c -index ab78e0f6afd70..e18abbd56fb51 100644 ---- a/drivers/dma/at_xdmac.c -+++ b/drivers/dma/at_xdmac.c -@@ -155,7 +155,7 @@ - #define AT_XDMAC_CC_WRIP (0x1 << 23) /* Write in Progress (read only) */ - #define AT_XDMAC_CC_WRIP_DONE (0x0 << 23) - #define AT_XDMAC_CC_WRIP_IN_PROGRESS (0x1 << 23) --#define AT_XDMAC_CC_PERID(i) (0x7f & (i) << 24) /* Channel Peripheral Identifier */ -+#define AT_XDMAC_CC_PERID(i) ((0x7f & (i)) << 24) /* Channel Peripheral Identifier */ - #define AT_XDMAC_CDS_MSP 0x2C /* Channel Data Stride Memory Set Pattern */ - #define AT_XDMAC_CSUS 0x30 /* Channel Source Microblock Stride */ - #define AT_XDMAC_CDUS 0x34 /* Channel Destination Microblock Stride */ -@@ -1926,6 +1926,30 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan) - return; - } - -+static void at_xdmac_axi_config(struct platform_device *pdev) -+{ -+ struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev); -+ bool dev_m2m = false; -+ u32 dma_requests; -+ -+ if (!atxdmac->layout->axi_config) -+ return; /* Not supported */ -+ -+ if (!of_property_read_u32(pdev->dev.of_node, "dma-requests", -+ &dma_requests)) { -+ dev_info(&pdev->dev, "controller in mem2mem mode.\n"); -+ dev_m2m = true; -+ } -+ -+ if (dev_m2m) { -+ at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M); -+ at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M); -+ } else { -+ at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M); -+ at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M); -+ } -+} -+ - #ifdef CONFIG_PM - static int atmel_xdmac_prepare(struct device *dev) - { -@@ -1975,6 +1999,7 @@ static int atmel_xdmac_resume(struct device *dev) - struct at_xdmac *atxdmac = dev_get_drvdata(dev); - struct at_xdmac_chan *atchan; - struct dma_chan *chan, *_chan; -+ struct platform_device *pdev = container_of(dev, struct platform_device, dev); - int i; - int ret; - -@@ -1982,6 +2007,8 @@ static int atmel_xdmac_resume(struct device *dev) - if (ret) - return ret; - -+ at_xdmac_axi_config(pdev); -+ - /* Clear pending interrupts. */ - for (i = 0; i < atxdmac->dma.chancnt; i++) { - atchan = &atxdmac->chan[i]; -@@ -2007,30 +2034,6 @@ static int atmel_xdmac_resume(struct device *dev) - } - #endif /* CONFIG_PM_SLEEP */ - --static void at_xdmac_axi_config(struct platform_device *pdev) --{ -- struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev); -- bool dev_m2m = false; -- u32 dma_requests; -- -- if (!atxdmac->layout->axi_config) -- return; /* Not supported */ -- -- if (!of_property_read_u32(pdev->dev.of_node, "dma-requests", -- &dma_requests)) { -- dev_info(&pdev->dev, "controller in mem2mem mode.\n"); -- dev_m2m = true; -- } -- -- if (dev_m2m) { -- at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M); -- at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M); -- } else { -- at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M); -- at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M); -- } --} -- - static int at_xdmac_probe(struct platform_device *pdev) - { - struct at_xdmac *atxdmac; -diff --git a/drivers/dma/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c -index 2fd87f83cf90b..e169f18da551f 100644 ---- a/drivers/dma/bestcomm/ata.c -+++ b/drivers/dma/bestcomm/ata.c -@@ -133,7 +133,7 @@ void bcom_ata_reset_bd(struct bcom_task *tsk) - struct bcom_ata_var *var; - - /* Reset all BD */ -- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); -+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); - - tsk->index = 0; - tsk->outdex = 0; -diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c -index d91cbbe7a48fb..8c42e5ca00a99 100644 ---- a/drivers/dma/bestcomm/bestcomm.c -+++ b/drivers/dma/bestcomm/bestcomm.c -@@ -95,7 +95,7 @@ bcom_task_alloc(int bd_count, int bd_size, int priv_size) - tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa); - if (!tsk->bd) - goto error; -- memset(tsk->bd, 0x00, bd_count * bd_size); -+ memset_io(tsk->bd, 0x00, bd_count * bd_size); - - tsk->num_bd = bd_count; - tsk->bd_size = bd_size; -@@ -186,16 +186,16 @@ bcom_load_image(int task, u32 *task_image) - inc = bcom_task_inc(task); - - /* Clear & copy */ -- memset(var, 0x00, BCOM_VAR_SIZE); -- memset(inc, 0x00, BCOM_INC_SIZE); -+ memset_io(var, 0x00, BCOM_VAR_SIZE); -+ memset_io(inc, 0x00, BCOM_INC_SIZE); - - desc_src = (u32 *)(hdr + 1); - var_src = desc_src + hdr->desc_size; - inc_src = var_src + hdr->var_size; - -- memcpy(desc, desc_src, hdr->desc_size * sizeof(u32)); -- memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32)); -- memcpy(inc, inc_src, hdr->inc_size * sizeof(u32)); -+ memcpy_toio(desc, desc_src, hdr->desc_size * sizeof(u32)); -+ memcpy_toio(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32)); -+ memcpy_toio(inc, inc_src, hdr->inc_size * sizeof(u32)); - - return 0; - } -@@ -302,13 +302,13 @@ static int bcom_engine_init(void) - return -ENOMEM; - } - -- memset(bcom_eng->tdt, 0x00, tdt_size); -- memset(bcom_eng->ctx, 0x00, ctx_size); -- memset(bcom_eng->var, 0x00, var_size); -- memset(bcom_eng->fdt, 0x00, fdt_size); -+ memset_io(bcom_eng->tdt, 0x00, tdt_size); -+ memset_io(bcom_eng->ctx, 0x00, ctx_size); -+ memset_io(bcom_eng->var, 0x00, var_size); -+ memset_io(bcom_eng->fdt, 0x00, fdt_size); - - /* Copy the FDT for the EU#3 */ -- memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops)); -+ memcpy_toio(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops)); - - /* Initialize Task base structure */ - for (task=0; task<BCOM_MAX_TASKS; task++) -diff --git a/drivers/dma/bestcomm/fec.c b/drivers/dma/bestcomm/fec.c -index 7f1fb1c999e43..d203618ac11fe 100644 ---- a/drivers/dma/bestcomm/fec.c -+++ b/drivers/dma/bestcomm/fec.c -@@ -140,7 +140,7 @@ bcom_fec_rx_reset(struct bcom_task *tsk) - tsk->index = 0; - tsk->outdex = 0; - -- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); -+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); - - /* Configure some stuff */ - bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA); -@@ -241,7 +241,7 @@ bcom_fec_tx_reset(struct bcom_task *tsk) - tsk->index = 0; - tsk->outdex = 0; - -- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); -+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); - - /* Configure some stuff */ - bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA); -diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c -index 906ddba6a6f5d..8a24a5cbc2633 100644 ---- a/drivers/dma/bestcomm/gen_bd.c -+++ b/drivers/dma/bestcomm/gen_bd.c -@@ -142,7 +142,7 @@ bcom_gen_bd_rx_reset(struct bcom_task *tsk) - tsk->index = 0; - tsk->outdex = 0; - -- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); -+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); - - /* Configure some stuff */ - bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA); -@@ -226,7 +226,7 @@ bcom_gen_bd_tx_reset(struct bcom_task *tsk) - tsk->index = 0; - tsk->outdex = 0; - -- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); -+ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); - - /* Configure some stuff */ - bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA); -diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h -index 1bfbd64b13717..53f16d3f00294 100644 ---- a/drivers/dma/dmaengine.h -+++ b/drivers/dma/dmaengine.h -@@ -176,7 +176,7 @@ dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, - static inline bool - dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) - { -- return (cb->callback) ? true : false; -+ return cb->callback || cb->callback_result; - } - - struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); -diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c -index 83a5ff2ecf2a0..419b206f8a42d 100644 ---- a/drivers/dma/idxd/device.c -+++ b/drivers/dma/idxd/device.c -@@ -427,7 +427,6 @@ void idxd_wq_quiesce(struct idxd_wq *wq) - { - percpu_ref_kill(&wq->wq_active); - wait_for_completion(&wq->wq_dead); -- percpu_ref_exit(&wq->wq_active); - } - - /* Device control bits */ -@@ -584,6 +583,8 @@ void idxd_device_reset(struct idxd_device *idxd) - spin_lock(&idxd->dev_lock); - idxd_device_clear_state(idxd); - idxd->state = IDXD_DEV_DISABLED; -+ idxd_unmask_error_interrupts(idxd); -+ idxd_msix_perm_setup(idxd); - spin_unlock(&idxd->dev_lock); - } - -diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c -index e0f056c1d1f56..c39e9483206ad 100644 ---- a/drivers/dma/idxd/dma.c -+++ b/drivers/dma/idxd/dma.c -@@ -311,6 +311,7 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev) - - err_dma: - idxd_wq_quiesce(wq); -+ percpu_ref_exit(&wq->wq_active); - err_ref: - idxd_wq_free_resources(wq); - err_res_alloc: -@@ -328,9 +329,9 @@ static void idxd_dmaengine_drv_remove(struct idxd_dev *idxd_dev) - mutex_lock(&wq->wq_lock); - idxd_wq_quiesce(wq); - idxd_unregister_dma_channel(wq); -- __drv_disable_wq(wq); - idxd_wq_free_resources(wq); -- wq->type = IDXD_WQT_NONE; -+ __drv_disable_wq(wq); -+ percpu_ref_exit(&wq->wq_active); - mutex_unlock(&wq->wq_lock); - } - -diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c -index eb09bc591c316..7bf03f371ce19 100644 ---- a/drivers/dma/idxd/init.c -+++ b/drivers/dma/idxd/init.c -@@ -797,11 +797,19 @@ static void idxd_remove(struct pci_dev *pdev) - int msixcnt = pci_msix_vec_count(pdev); - int i; - -- dev_dbg(&pdev->dev, "%s called\n", __func__); -+ idxd_unregister_devices(idxd); -+ /* -+ * When ->release() is called for the idxd->conf_dev, it frees all the memory related -+ * to the idxd context. The driver still needs those bits in order to do the rest of -+ * the cleanup. However, we do need to unbound the idxd sub-driver. So take a ref -+ * on the device here to hold off the freeing while allowing the idxd sub-driver -+ * to unbind. -+ */ -+ get_device(idxd_confdev(idxd)); -+ device_unregister(idxd_confdev(idxd)); - idxd_shutdown(pdev); - if (device_pasid_enabled(idxd)) - idxd_disable_system_pasid(idxd); -- idxd_unregister_devices(idxd); - - for (i = 0; i < msixcnt; i++) { - irq_entry = &idxd->irq_entries[i]; -@@ -815,7 +823,7 @@ static void idxd_remove(struct pci_dev *pdev) - pci_disable_device(pdev); - destroy_workqueue(idxd->wq); - perfmon_pmu_remove(idxd); -- device_unregister(idxd_confdev(idxd)); -+ put_device(idxd_confdev(idxd)); - } - - static struct pci_driver idxd_pci_driver = { -diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c -index ca88fa7a328e7..6d6af0dc3c0ec 100644 ---- a/drivers/dma/idxd/irq.c -+++ b/drivers/dma/idxd/irq.c -@@ -63,6 +63,9 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) - int i; - bool err = false; - -+ if (cause & IDXD_INTC_HALT_STATE) -+ goto halt; -+ - if (cause & IDXD_INTC_ERR) { - spin_lock(&idxd->dev_lock); - for (i = 0; i < 4; i++) -@@ -121,6 +124,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) - if (!err) - return 0; - -+halt: - gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET); - if (gensts.state == IDXD_DEVICE_STATE_HALT) { - idxd->state = IDXD_DEV_HALTED; -@@ -133,9 +137,10 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) - INIT_WORK(&idxd->work, idxd_device_reinit); - queue_work(idxd->wq, &idxd->work); - } else { -- spin_lock(&idxd->dev_lock); -+ idxd->state = IDXD_DEV_HALTED; - idxd_wqs_quiesce(idxd); - idxd_wqs_unmap_portal(idxd); -+ spin_lock(&idxd->dev_lock); - idxd_device_clear_state(idxd); - dev_err(&idxd->pdev->dev, - "idxd halted, need %s.\n", -diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h -index ffc7550a77eeb..97ffb06de9b0d 100644 ---- a/drivers/dma/idxd/registers.h -+++ b/drivers/dma/idxd/registers.h -@@ -158,6 +158,7 @@ enum idxd_device_reset_type { - #define IDXD_INTC_CMD 0x02 - #define IDXD_INTC_OCCUPY 0x04 - #define IDXD_INTC_PERFMON_OVFL 0x08 -+#define IDXD_INTC_HALT_STATE 0x10 - - #define IDXD_CMD_OFFSET 0xa0 - union idxd_command_reg { -diff --git a/drivers/dma/idxd/submit.c b/drivers/dma/idxd/submit.c -index de76fb4abac24..83452fbbb168b 100644 ---- a/drivers/dma/idxd/submit.c -+++ b/drivers/dma/idxd/submit.c -@@ -106,6 +106,7 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, - { - struct idxd_desc *d, *t, *found = NULL; - struct llist_node *head; -+ LIST_HEAD(flist); - - desc->completion->status = IDXD_COMP_DESC_ABORT; - /* -@@ -120,7 +121,11 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, - found = desc; - continue; - } -- list_add_tail(&desc->list, &ie->work_list); -+ -+ if (d->completion->status) -+ list_add_tail(&d->list, &flist); -+ else -+ list_add_tail(&d->list, &ie->work_list); - } - } - -@@ -130,6 +135,17 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, - - if (found) - complete_desc(found, IDXD_COMPLETE_ABORT); -+ -+ /* -+ * complete_desc() will return desc to allocator and the desc can be -+ * acquired by a different process and the desc->list can be modified. -+ * Delete desc from list so the list trasversing does not get corrupted -+ * by the other process. -+ */ -+ list_for_each_entry_safe(d, t, &flist, list) { -+ list_del_init(&d->list); -+ complete_desc(d, IDXD_COMPLETE_NORMAL); -+ } - } - - int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc) -diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c -index 962b6e05287b5..d95c421877fb7 100644 ---- a/drivers/dma/st_fdma.c -+++ b/drivers/dma/st_fdma.c -@@ -874,4 +874,4 @@ MODULE_LICENSE("GPL v2"); - MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver"); - MODULE_AUTHOR("Ludovic.barre <Ludovic.barre@st.com>"); - MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>"); --MODULE_ALIAS("platform: " DRIVER_NAME); -+MODULE_ALIAS("platform:" DRIVER_NAME); -diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c -index 9063c727962ed..7dfc743ac4338 100644 ---- a/drivers/dma/stm32-dma.c -+++ b/drivers/dma/stm32-dma.c -@@ -270,7 +270,6 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, - u32 threshold) - { - enum dma_slave_buswidth max_width; -- u64 addr = buf_addr; - - if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL) - max_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -@@ -281,7 +280,7 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, - max_width > DMA_SLAVE_BUSWIDTH_1_BYTE) - max_width = max_width >> 1; - -- if (do_div(addr, max_width)) -+ if (buf_addr & (max_width - 1)) - max_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - - return max_width; -@@ -753,8 +752,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - if (src_bus_width < 0) - return src_bus_width; - -- /* Set memory burst size */ -- src_maxburst = STM32_DMA_MAX_BURST; -+ /* -+ * Set memory burst size - burst not possible if address is not aligned on -+ * the address boundary equal to the size of the transfer -+ */ -+ if (buf_addr & (buf_len - 1)) -+ src_maxburst = 1; -+ else -+ src_maxburst = STM32_DMA_MAX_BURST; - src_best_burst = stm32_dma_get_best_burst(buf_len, - src_maxburst, - fifoth, -@@ -803,8 +808,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, - if (dst_bus_width < 0) - return dst_bus_width; - -- /* Set memory burst size */ -- dst_maxburst = STM32_DMA_MAX_BURST; -+ /* -+ * Set memory burst size - burst not possible if address is not aligned on -+ * the address boundary equal to the size of the transfer -+ */ -+ if (buf_addr & (buf_len - 1)) -+ dst_maxburst = 1; -+ else -+ dst_maxburst = STM32_DMA_MAX_BURST; - dst_best_burst = stm32_dma_get_best_burst(buf_len, - dst_maxburst, - fifoth, -diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c -index b1115a6d1935c..d1dff3a29db59 100644 ---- a/drivers/dma/tegra210-adma.c -+++ b/drivers/dma/tegra210-adma.c -@@ -867,7 +867,7 @@ static int tegra_adma_probe(struct platform_device *pdev) - - pm_runtime_enable(&pdev->dev); - -- ret = pm_runtime_get_sync(&pdev->dev); -+ ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret < 0) - goto rpm_disable; - -diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c -index a35858610780c..041d8e32d6300 100644 ---- a/drivers/dma/ti/k3-udma.c -+++ b/drivers/dma/ti/k3-udma.c -@@ -1348,6 +1348,7 @@ static int bcdma_get_bchan(struct udma_chan *uc) - { - struct udma_dev *ud = uc->ud; - enum udma_tp_level tpl; -+ int ret; - - if (uc->bchan) { - dev_dbg(ud->dev, "chan%d: already have bchan%d allocated\n", -@@ -1365,8 +1366,11 @@ static int bcdma_get_bchan(struct udma_chan *uc) - tpl = ud->bchan_tpl.levels - 1; - - uc->bchan = __udma_reserve_bchan(ud, tpl, -1); -- if (IS_ERR(uc->bchan)) -- return PTR_ERR(uc->bchan); -+ if (IS_ERR(uc->bchan)) { -+ ret = PTR_ERR(uc->bchan); -+ uc->bchan = NULL; -+ return ret; -+ } - - uc->tchan = uc->bchan; - -@@ -1376,6 +1380,7 @@ static int bcdma_get_bchan(struct udma_chan *uc) - static int udma_get_tchan(struct udma_chan *uc) - { - struct udma_dev *ud = uc->ud; -+ int ret; - - if (uc->tchan) { - dev_dbg(ud->dev, "chan%d: already have tchan%d allocated\n", -@@ -1390,8 +1395,11 @@ static int udma_get_tchan(struct udma_chan *uc) - */ - uc->tchan = __udma_reserve_tchan(ud, uc->config.channel_tpl, - uc->config.mapped_channel_id); -- if (IS_ERR(uc->tchan)) -- return PTR_ERR(uc->tchan); -+ if (IS_ERR(uc->tchan)) { -+ ret = PTR_ERR(uc->tchan); -+ uc->tchan = NULL; -+ return ret; -+ } - - if (ud->tflow_cnt) { - int tflow_id; -@@ -1421,6 +1429,7 @@ static int udma_get_tchan(struct udma_chan *uc) - static int udma_get_rchan(struct udma_chan *uc) - { - struct udma_dev *ud = uc->ud; -+ int ret; - - if (uc->rchan) { - dev_dbg(ud->dev, "chan%d: already have rchan%d allocated\n", -@@ -1435,8 +1444,13 @@ static int udma_get_rchan(struct udma_chan *uc) - */ - uc->rchan = __udma_reserve_rchan(ud, uc->config.channel_tpl, - uc->config.mapped_channel_id); -+ if (IS_ERR(uc->rchan)) { -+ ret = PTR_ERR(uc->rchan); -+ uc->rchan = NULL; -+ return ret; -+ } - -- return PTR_ERR_OR_ZERO(uc->rchan); -+ return 0; - } - - static int udma_get_chan_pair(struct udma_chan *uc) -@@ -1490,6 +1504,7 @@ static int udma_get_chan_pair(struct udma_chan *uc) - static int udma_get_rflow(struct udma_chan *uc, int flow_id) - { - struct udma_dev *ud = uc->ud; -+ int ret; - - if (!uc->rchan) { - dev_err(ud->dev, "chan%d: does not have rchan??\n", uc->id); -@@ -1503,8 +1518,13 @@ static int udma_get_rflow(struct udma_chan *uc, int flow_id) - } - - uc->rflow = __udma_get_rflow(ud, flow_id); -+ if (IS_ERR(uc->rflow)) { -+ ret = PTR_ERR(uc->rflow); -+ uc->rflow = NULL; -+ return ret; -+ } - -- return PTR_ERR_OR_ZERO(uc->rflow); -+ return 0; - } - - static void bcdma_put_bchan(struct udma_chan *uc) -diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c -index b280a53e8570a..ce5c66e6897d2 100644 ---- a/drivers/dma/xilinx/xilinx_dpdma.c -+++ b/drivers/dma/xilinx/xilinx_dpdma.c -@@ -271,9 +271,6 @@ struct xilinx_dpdma_device { - /* ----------------------------------------------------------------------------- - * DebugFS - */ -- --#ifdef CONFIG_DEBUG_FS -- - #define XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE 32 - #define XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR "65535" - -@@ -299,7 +296,7 @@ struct xilinx_dpdma_debugfs_request { - - static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan) - { -- if (chan->id == dpdma_debugfs.chan_id) -+ if (IS_ENABLED(CONFIG_DEBUG_FS) && chan->id == dpdma_debugfs.chan_id) - dpdma_debugfs.xilinx_dpdma_irq_done_count++; - } - -@@ -462,16 +459,6 @@ static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev) - dev_err(xdev->dev, "Failed to create debugfs testcase file\n"); - } - --#else --static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev) --{ --} -- --static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan) --{ --} --#endif /* CONFIG_DEBUG_FS */ -- - /* ----------------------------------------------------------------------------- - * I/O Accessors - */ -diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c -index 99b06a3e8fb12..4fce75013674f 100644 ---- a/drivers/edac/amd64_edac.c -+++ b/drivers/edac/amd64_edac.c -@@ -1065,12 +1065,14 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) - #define CS_ODD_PRIMARY BIT(1) - #define CS_EVEN_SECONDARY BIT(2) - #define CS_ODD_SECONDARY BIT(3) -+#define CS_3R_INTERLEAVE BIT(4) - - #define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY) - #define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY) - - static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) - { -+ u8 base, count = 0; - int cs_mode = 0; - - if (csrow_enabled(2 * dimm, ctrl, pvt)) -@@ -1083,6 +1085,20 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) - if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt)) - cs_mode |= CS_ODD_SECONDARY; - -+ /* -+ * 3 Rank inteleaving support. -+ * There should be only three bases enabled and their two masks should -+ * be equal. -+ */ -+ for_each_chip_select(base, ctrl, pvt) -+ count += csrow_enabled(base, ctrl, pvt); -+ -+ if (count == 3 && -+ pvt->csels[ctrl].csmasks[0] == pvt->csels[ctrl].csmasks[1]) { -+ edac_dbg(1, "3R interleaving in use.\n"); -+ cs_mode |= CS_3R_INTERLEAVE; -+ } -+ - return cs_mode; - } - -@@ -1891,10 +1907,14 @@ static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, - * - * The MSB is the number of bits in the full mask because BIT[0] is - * always 0. -+ * -+ * In the special 3 Rank interleaving case, a single bit is flipped -+ * without swapping with the most significant bit. This can be handled -+ * by keeping the MSB where it is and ignoring the single zero bit. - */ - msb = fls(addr_mask_orig) - 1; - weight = hweight_long(addr_mask_orig); -- num_zero_bits = msb - weight; -+ num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE); - - /* Take the number of zero bits off from the top of the mask. */ - addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); -diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c -index 4c626fcd4dcbb..1522d4aa2ca62 100644 ---- a/drivers/edac/sb_edac.c -+++ b/drivers/edac/sb_edac.c -@@ -1052,7 +1052,7 @@ static u64 haswell_get_tohm(struct sbridge_pvt *pvt) - pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, ®); - rc = ((reg << 6) | rc) << 26; - -- return rc | 0x1ffffff; -+ return rc | 0x3ffffff; - } - - static u64 knl_get_tolm(struct sbridge_pvt *pvt) -diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c -index de416f9e79213..f5219334fd3a5 100644 ---- a/drivers/firmware/arm_scmi/base.c -+++ b/drivers/firmware/arm_scmi/base.c -@@ -34,6 +34,12 @@ struct scmi_msg_resp_base_attributes { - __le16 reserved; - }; - -+struct scmi_msg_resp_base_discover_agent { -+ __le32 agent_id; -+ u8 name[SCMI_MAX_STR_SIZE]; -+}; -+ -+ - struct scmi_msg_base_error_notify { - __le32 event_control; - #define BASE_TP_NOTIFY_ALL BIT(0) -@@ -225,18 +231,21 @@ static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph, - int id, char *name) - { - int ret; -+ struct scmi_msg_resp_base_discover_agent *agent_info; - struct scmi_xfer *t; - - ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT, -- sizeof(__le32), SCMI_MAX_STR_SIZE, &t); -+ sizeof(__le32), sizeof(*agent_info), &t); - if (ret) - return ret; - - put_unaligned_le32(id, t->tx.buf); - - ret = ph->xops->do_xfer(ph, t); -- if (!ret) -- strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE); -+ if (!ret) { -+ agent_info = t->rx.buf; -+ strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE); -+ } - - ph->xops->xfer_put(ph, t); - -diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c -index 4371fdcd5a73f..581d34c957695 100644 ---- a/drivers/firmware/arm_scmi/scmi_pm_domain.c -+++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c -@@ -138,9 +138,7 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev) - scmi_pd_data->domains = domains; - scmi_pd_data->num_domains = num_domains; - -- of_genpd_add_provider_onecell(np, scmi_pd_data); -- -- return 0; -+ return of_genpd_add_provider_onecell(np, scmi_pd_data); - } - - static const struct scmi_device_id scmi_id_table[] = { -diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c -index 308471586381f..cdbb287bd8bcd 100644 ---- a/drivers/firmware/arm_scmi/sensors.c -+++ b/drivers/firmware/arm_scmi/sensors.c -@@ -637,7 +637,7 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph, - if (ret) - return ret; - -- put_unaligned_le32(cpu_to_le32(sensor_id), t->tx.buf); -+ put_unaligned_le32(sensor_id, t->tx.buf); - ret = ph->xops->do_xfer(ph, t); - if (!ret) { - struct sensors_info *si = ph->get_priv(ph); -diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c -index 11e8efb713751..87039c5c03fdb 100644 ---- a/drivers/firmware/arm_scmi/virtio.c -+++ b/drivers/firmware/arm_scmi/virtio.c -@@ -82,7 +82,8 @@ static bool scmi_vio_have_vq_rx(struct virtio_device *vdev) - } - - static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, -- struct scmi_vio_msg *msg) -+ struct scmi_vio_msg *msg, -+ struct device *dev) - { - struct scatterlist sg_in; - int rc; -@@ -94,8 +95,7 @@ static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, - - rc = virtqueue_add_inbuf(vioch->vqueue, &sg_in, 1, msg, GFP_ATOMIC); - if (rc) -- dev_err_once(vioch->cinfo->dev, -- "failed to add to virtqueue (%d)\n", rc); -+ dev_err_once(dev, "failed to add to virtqueue (%d)\n", rc); - else - virtqueue_kick(vioch->vqueue); - -@@ -108,7 +108,7 @@ static void scmi_finalize_message(struct scmi_vio_channel *vioch, - struct scmi_vio_msg *msg) - { - if (vioch->is_rx) { -- scmi_vio_feed_vq_rx(vioch, msg); -+ scmi_vio_feed_vq_rx(vioch, msg, vioch->cinfo->dev); - } else { - /* Here IRQs are assumed to be already disabled by the caller */ - spin_lock(&vioch->lock); -@@ -269,7 +269,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, - list_add_tail(&msg->list, &vioch->free_list); - spin_unlock_irqrestore(&vioch->lock, flags); - } else { -- scmi_vio_feed_vq_rx(vioch, msg); -+ scmi_vio_feed_vq_rx(vioch, msg, cinfo->dev); - } - } - -diff --git a/drivers/firmware/arm_scmi/voltage.c b/drivers/firmware/arm_scmi/voltage.c -index a5048956a0be9..ac08e819088bb 100644 ---- a/drivers/firmware/arm_scmi/voltage.c -+++ b/drivers/firmware/arm_scmi/voltage.c -@@ -156,7 +156,7 @@ static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph, - int cnt; - - cmd->domain_id = cpu_to_le32(v->id); -- cmd->level_index = desc_index; -+ cmd->level_index = cpu_to_le32(desc_index); - ret = ph->xops->do_xfer(ph, tl); - if (ret) - break; -diff --git a/drivers/firmware/psci/psci_checker.c b/drivers/firmware/psci/psci_checker.c -index 9a369a2eda71d..116eb465cdb42 100644 ---- a/drivers/firmware/psci/psci_checker.c -+++ b/drivers/firmware/psci/psci_checker.c -@@ -155,7 +155,7 @@ static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups) - if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) - return -ENOMEM; - -- cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups), -+ cpu_groups = kcalloc(nb_available_cpus, sizeof(*cpu_groups), - GFP_KERNEL); - if (!cpu_groups) { - free_cpumask_var(tmp); -diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c -index 2ee97bab74409..27a64de919817 100644 ---- a/drivers/firmware/qcom_scm.c -+++ b/drivers/firmware/qcom_scm.c -@@ -252,7 +252,7 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id, - break; - default: - pr_err("Unknown SMC convention being used\n"); -- return -EINVAL; -+ return false; - } - - ret = qcom_scm_call(dev, &desc, &res); -diff --git a/drivers/firmware/scpi_pm_domain.c b/drivers/firmware/scpi_pm_domain.c -index 51201600d789b..800673910b511 100644 ---- a/drivers/firmware/scpi_pm_domain.c -+++ b/drivers/firmware/scpi_pm_domain.c -@@ -16,7 +16,6 @@ struct scpi_pm_domain { - struct generic_pm_domain genpd; - struct scpi_ops *ops; - u32 domain; -- char name[30]; - }; - - /* -@@ -110,8 +109,13 @@ static int scpi_pm_domain_probe(struct platform_device *pdev) - - scpi_pd->domain = i; - scpi_pd->ops = scpi_ops; -- sprintf(scpi_pd->name, "%pOFn.%d", np, i); -- scpi_pd->genpd.name = scpi_pd->name; -+ scpi_pd->genpd.name = devm_kasprintf(dev, GFP_KERNEL, -+ "%pOFn.%d", np, i); -+ if (!scpi_pd->genpd.name) { -+ dev_err(dev, "Failed to allocate genpd name:%pOFn.%d\n", -+ np, i); -+ continue; -+ } - scpi_pd->genpd.power_off = scpi_pd_power_off; - scpi_pd->genpd.power_on = scpi_pd_power_on; - -diff --git a/drivers/firmware/smccc/soc_id.c b/drivers/firmware/smccc/soc_id.c -index 581aa5e9b0778..dd7c3d5e8b0bb 100644 ---- a/drivers/firmware/smccc/soc_id.c -+++ b/drivers/firmware/smccc/soc_id.c -@@ -50,7 +50,7 @@ static int __init smccc_soc_init(void) - arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, - ARM_SMCCC_ARCH_SOC_ID, &res); - -- if (res.a0 == SMCCC_RET_NOT_SUPPORTED) { -+ if ((int)res.a0 == SMCCC_RET_NOT_SUPPORTED) { - pr_info("ARCH_SOC_ID not implemented, skipping ....\n"); - return 0; - } -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index fae5141251e5d..947474f6abb45 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -523,6 +523,7 @@ config GPIO_REG - config GPIO_ROCKCHIP - tristate "Rockchip GPIO support" - depends on ARCH_ROCKCHIP || COMPILE_TEST -+ select GENERIC_IRQ_CHIP - select GPIOLIB_IRQCHIP - default ARCH_ROCKCHIP - help -diff --git a/drivers/gpio/gpio-realtek-otto.c b/drivers/gpio/gpio-realtek-otto.c -index eeeb39bc171dc..bd75401b549d1 100644 ---- a/drivers/gpio/gpio-realtek-otto.c -+++ b/drivers/gpio/gpio-realtek-otto.c -@@ -205,7 +205,7 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc) - status = realtek_gpio_read_isr(ctrl, lines_done / 8); - port_pin_count = min(gc->ngpio - lines_done, 8U); - for_each_set_bit(offset, &status, port_pin_count) -- generic_handle_domain_irq(gc->irq.domain, offset); -+ generic_handle_domain_irq(gc->irq.domain, offset + lines_done); - } - - chained_irq_exit(irq_chip, desc); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h -index 269437b013280..289c7dc053634 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h -@@ -1078,8 +1078,6 @@ struct amdgpu_device { - char product_name[32]; - char serial[20]; - -- struct amdgpu_autodump autodump; -- - atomic_t throttling_logging_enabled; - struct ratelimit_state throttling_logging_rs; - uint32_t ras_hw_enabled; -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c -index 054c1a224defb..ab36cce59d2e4 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c -@@ -1393,7 +1393,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( - struct sg_table *sg = NULL; - uint64_t user_addr = 0; - struct amdgpu_bo *bo; -- struct drm_gem_object *gobj; -+ struct drm_gem_object *gobj = NULL; - u32 domain, alloc_domain; - u64 alloc_flags; - int ret; -@@ -1503,14 +1503,16 @@ allocate_init_user_pages_failed: - remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info); - drm_vma_node_revoke(&gobj->vma_node, drm_priv); - err_node_allow: -- amdgpu_bo_unref(&bo); - /* Don't unreserve system mem limit twice */ - goto err_reserve_limit; - err_bo_create: - unreserve_mem_limit(adev, size, alloc_domain, !!sg); - err_reserve_limit: - mutex_destroy(&(*mem)->lock); -- kfree(*mem); -+ if (gobj) -+ drm_gem_object_put(gobj); -+ else -+ kfree(*mem); - err: - if (sg) { - sg_free_table(sg); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c -index 15c45b2a39835..714178f1b6c6e 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c -@@ -61,7 +61,7 @@ static void amdgpu_bo_list_free(struct kref *ref) - - int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, - struct drm_amdgpu_bo_list_entry *info, -- unsigned num_entries, struct amdgpu_bo_list **result) -+ size_t num_entries, struct amdgpu_bo_list **result) - { - unsigned last_entry = 0, first_userptr = num_entries; - struct amdgpu_bo_list_entry *array; -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h -index c905a4cfc173d..044b41f0bfd9c 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h -@@ -61,7 +61,7 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, - int amdgpu_bo_list_create(struct amdgpu_device *adev, - struct drm_file *filp, - struct drm_amdgpu_bo_list_entry *info, -- unsigned num_entries, -+ size_t num_entries, - struct amdgpu_bo_list **list); - - static inline struct amdgpu_bo_list_entry * -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c -index b9c11c2b2885a..0de66f59adb8a 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c -@@ -827,6 +827,7 @@ static int amdgpu_connector_vga_get_modes(struct drm_connector *connector) - - amdgpu_connector_get_edid(connector); - ret = amdgpu_connector_ddc_get_modes(connector); -+ amdgpu_get_native_mode(connector); - - return ret; - } -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c -index 463b9c0283f7e..ec30d81586a79 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c -@@ -27,7 +27,6 @@ - #include <linux/pci.h> - #include <linux/uaccess.h> - #include <linux/pm_runtime.h> --#include <linux/poll.h> - - #include "amdgpu.h" - #include "amdgpu_pm.h" -@@ -37,85 +36,7 @@ - #include "amdgpu_securedisplay.h" - #include "amdgpu_fw_attestation.h" - --int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev) --{ - #if defined(CONFIG_DEBUG_FS) -- unsigned long timeout = 600 * HZ; -- int ret; -- -- wake_up_interruptible(&adev->autodump.gpu_hang); -- -- ret = wait_for_completion_interruptible_timeout(&adev->autodump.dumping, timeout); -- if (ret == 0) { -- pr_err("autodump: timeout, move on to gpu recovery\n"); -- return -ETIMEDOUT; -- } --#endif -- return 0; --} -- --#if defined(CONFIG_DEBUG_FS) -- --static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) --{ -- struct amdgpu_device *adev = inode->i_private; -- int ret; -- -- file->private_data = adev; -- -- ret = down_read_killable(&adev->reset_sem); -- if (ret) -- return ret; -- -- if (adev->autodump.dumping.done) { -- reinit_completion(&adev->autodump.dumping); -- ret = 0; -- } else { -- ret = -EBUSY; -- } -- -- up_read(&adev->reset_sem); -- -- return ret; --} -- --static int amdgpu_debugfs_autodump_release(struct inode *inode, struct file *file) --{ -- struct amdgpu_device *adev = file->private_data; -- -- complete_all(&adev->autodump.dumping); -- return 0; --} -- --static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_table_struct *poll_table) --{ -- struct amdgpu_device *adev = file->private_data; -- -- poll_wait(file, &adev->autodump.gpu_hang, poll_table); -- -- if (amdgpu_in_reset(adev)) -- return POLLIN | POLLRDNORM | POLLWRNORM; -- -- return 0; --} -- --static const struct file_operations autodump_debug_fops = { -- .owner = THIS_MODULE, -- .open = amdgpu_debugfs_autodump_open, -- .poll = amdgpu_debugfs_autodump_poll, -- .release = amdgpu_debugfs_autodump_release, --}; -- --static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev) --{ -- init_completion(&adev->autodump.dumping); -- complete_all(&adev->autodump.dumping); -- init_waitqueue_head(&adev->autodump.gpu_hang); -- -- debugfs_create_file("amdgpu_autodump", 0600, -- adev_to_drm(adev)->primary->debugfs_root, -- adev, &autodump_debug_fops); --} - - /** - * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes -@@ -1588,7 +1509,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) - } - - amdgpu_ras_debugfs_create_all(adev); -- amdgpu_debugfs_autodump_init(adev); - amdgpu_rap_debugfs_init(adev); - amdgpu_securedisplay_debugfs_init(adev); - amdgpu_fw_attestation_debugfs_init(adev); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h -index 141a8474e24f2..8b641f40fdf66 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h -@@ -26,10 +26,6 @@ - /* - * Debugfs - */ --struct amdgpu_autodump { -- struct completion dumping; -- struct wait_queue_head gpu_hang; --}; - - int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); - int amdgpu_debugfs_init(struct amdgpu_device *adev); -@@ -37,4 +33,3 @@ void amdgpu_debugfs_fini(struct amdgpu_device *adev); - void amdgpu_debugfs_fence_init(struct amdgpu_device *adev); - void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev); - void amdgpu_debugfs_gem_init(struct amdgpu_device *adev); --int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c -index af9bdf16eefd4..1545884dc703e 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c -@@ -2394,6 +2394,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) - if (r) - goto init_failed; - -+ r = amdgpu_amdkfd_resume_iommu(adev); -+ if (r) -+ goto init_failed; -+ - r = amdgpu_device_ip_hw_init_phase1(adev); - if (r) - goto init_failed; -@@ -2432,10 +2436,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) - if (!adev->gmc.xgmi.pending_reset) - amdgpu_amdkfd_device_init(adev); - -- r = amdgpu_amdkfd_resume_iommu(adev); -- if (r) -- goto init_failed; -- - amdgpu_fru_get_product_info(adev); - - init_failed: -@@ -2745,6 +2745,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev) - adev->ip_blocks[i].status.hw = false; - } - -+ if (amdgpu_sriov_vf(adev)) { -+ if (amdgpu_virt_release_full_gpu(adev, false)) -+ DRM_ERROR("failed to release exclusive mode on fini\n"); -+ } -+ - return 0; - } - -@@ -2805,10 +2810,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) - - amdgpu_ras_fini(adev); - -- if (amdgpu_sriov_vf(adev)) -- if (amdgpu_virt_release_full_gpu(adev, false)) -- DRM_ERROR("failed to release exclusive mode on fini\n"); -- - return 0; - } - -@@ -3531,6 +3532,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, - adev->rmmio_size = pci_resource_len(adev->pdev, 2); - } - -+ for (i = 0; i < AMD_IP_BLOCK_TYPE_NUM; i++) -+ atomic_set(&adev->pm.pwr_state[i], POWER_STATE_UNKNOWN); -+ - adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); - if (adev->rmmio == NULL) { - return -ENOMEM; -@@ -3850,7 +3854,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) - /* disable all interrupts */ - amdgpu_irq_disable_all(adev); - if (adev->mode_info.mode_config_initialized){ -- if (!amdgpu_device_has_dc_support(adev)) -+ if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev))) - drm_helper_force_disable_all(adev_to_drm(adev)); - else - drm_atomic_helper_shutdown(adev_to_drm(adev)); -@@ -3876,8 +3880,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) - - void amdgpu_device_fini_sw(struct amdgpu_device *adev) - { -- amdgpu_device_ip_fini(adev); - amdgpu_fence_driver_sw_fini(adev); -+ amdgpu_device_ip_fini(adev); - release_firmware(adev->firmware.gpu_info_fw); - adev->firmware.gpu_info_fw = NULL; - adev->accel_working = false; -@@ -4466,10 +4470,6 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, - if (reset_context->reset_req_dev == adev) - job = reset_context->job; - -- /* no need to dump if device is not in good state during probe period */ -- if (!adev->gmc.xgmi.pending_reset) -- amdgpu_debugfs_wait_dump(adev); -- - if (amdgpu_sriov_vf(adev)) { - /* stop the data exchange thread */ - amdgpu_virt_fini_data_exchange(adev); -@@ -5130,7 +5130,7 @@ skip_hw_reset: - drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); - } - -- if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { -+ if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { - drm_helper_resume_force_mode(adev_to_drm(tmp_adev)); - } - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c -index d6aa032890ee8..a1e63ba4c54a5 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c -@@ -61,7 +61,7 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf) - } - - ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, -- TTM_BO_VM_NUM_PREFAULT, 1); -+ TTM_BO_VM_NUM_PREFAULT); - - drm_dev_exit(idx); - } else { -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c -index f3d62e196901a..0c7963dfacad1 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c -@@ -223,7 +223,7 @@ int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev, - */ - int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih) - { -- unsigned int count = AMDGPU_IH_MAX_NUM_IVS; -+ unsigned int count; - u32 wptr; - - if (!ih->enabled || adev->shutdown) -@@ -232,6 +232,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih) - wptr = amdgpu_ih_get_wptr(adev, ih); - - restart_ih: -+ count = AMDGPU_IH_MAX_NUM_IVS; - DRM_DEBUG("%s: rptr %d, wptr %d\n", __func__, ih->rptr, wptr); - - /* Order reading of wptr vs. reading of IH ring data */ -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c -index ce982afeff913..ac9a8cd21c4b6 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c -@@ -504,8 +504,8 @@ static int amdgpu_vkms_sw_fini(void *handle) - int i = 0; - - for (i = 0; i < adev->mode_info.num_crtc; i++) -- if (adev->mode_info.crtcs[i]) -- hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); -+ if (adev->amdgpu_vkms_output[i].vblank_hrtimer.function) -+ hrtimer_cancel(&adev->amdgpu_vkms_output[i].vblank_hrtimer); - - kfree(adev->mode_info.bios_hardcoded_edid); - kfree(adev->amdgpu_vkms_output); -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c -index 978ac927ac11d..a799e0b1ff736 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c -@@ -386,6 +386,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) - "%s", "xgmi_hive_info"); - if (ret) { - dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi hive\n"); -+ kobject_put(&hive->kobj); - kfree(hive); - hive = NULL; - goto pro_end; -diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c -index 16dbe593cba2e..970d59a21005a 100644 ---- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c -@@ -7729,8 +7729,19 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev) - switch (adev->asic_type) { - case CHIP_VANGOGH: - case CHIP_YELLOW_CARP: -- clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh) | -- ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL); -+ preempt_disable(); -+ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh); -+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh); -+ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh); -+ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over -+ * roughly every 42 seconds. -+ */ -+ if (hi_check != clock_hi) { -+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh); -+ clock_hi = hi_check; -+ } -+ preempt_enable(); -+ clock = clock_lo | (clock_hi << 32ULL); - break; - default: - preempt_disable(); -diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c -index 025184a556ee6..c39e53a41f13a 100644 ---- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c -@@ -140,6 +140,11 @@ MODULE_FIRMWARE("amdgpu/aldebaran_rlc.bin"); - #define mmTCP_CHAN_STEER_5_ARCT 0x0b0c - #define mmTCP_CHAN_STEER_5_ARCT_BASE_IDX 0 - -+#define mmGOLDEN_TSC_COUNT_UPPER_Renoir 0x0025 -+#define mmGOLDEN_TSC_COUNT_UPPER_Renoir_BASE_IDX 1 -+#define mmGOLDEN_TSC_COUNT_LOWER_Renoir 0x0026 -+#define mmGOLDEN_TSC_COUNT_LOWER_Renoir_BASE_IDX 1 -+ - enum ta_ras_gfx_subblock { - /*CPC*/ - TA_RAS_BLOCK__GFX_CPC_INDEX_START = 0, -@@ -3056,8 +3061,8 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev) - AMD_PG_SUPPORT_CP | - AMD_PG_SUPPORT_GDS | - AMD_PG_SUPPORT_RLC_SMU_HS)) { -- WREG32(mmRLC_JUMP_TABLE_RESTORE, -- adev->gfx.rlc.cp_table_gpu_addr >> 8); -+ WREG32_SOC15(GC, 0, mmRLC_JUMP_TABLE_RESTORE, -+ adev->gfx.rlc.cp_table_gpu_addr >> 8); - gfx_v9_0_init_gfx_power_gating(adev); - } - } -@@ -4228,19 +4233,38 @@ failed_kiq_read: - - static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev) - { -- uint64_t clock; -+ uint64_t clock, clock_lo, clock_hi, hi_check; - -- amdgpu_gfx_off_ctrl(adev, false); -- mutex_lock(&adev->gfx.gpu_clock_mutex); -- if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) { -- clock = gfx_v9_0_kiq_read_clock(adev); -- } else { -- WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1); -- clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) | -- ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL); -+ switch (adev->asic_type) { -+ case CHIP_RENOIR: -+ preempt_disable(); -+ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir); -+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Renoir); -+ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir); -+ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over -+ * roughly every 42 seconds. -+ */ -+ if (hi_check != clock_hi) { -+ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Renoir); -+ clock_hi = hi_check; -+ } -+ preempt_enable(); -+ clock = clock_lo | (clock_hi << 32ULL); -+ break; -+ default: -+ amdgpu_gfx_off_ctrl(adev, false); -+ mutex_lock(&adev->gfx.gpu_clock_mutex); -+ if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) { -+ clock = gfx_v9_0_kiq_read_clock(adev); -+ } else { -+ WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1); -+ clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) | -+ ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL); -+ } -+ mutex_unlock(&adev->gfx.gpu_clock_mutex); -+ amdgpu_gfx_off_ctrl(adev, true); -+ break; - } -- mutex_unlock(&adev->gfx.gpu_clock_mutex); -- amdgpu_gfx_off_ctrl(adev, true); - return clock; - } - -diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c -index bda1542ef1ddf..f51fd0688eca7 100644 ---- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c -@@ -162,7 +162,6 @@ static void gfxhub_v1_0_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC);/* XXX for emulation. */ - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1); -diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c -index 14c1c1a297dd3..6e0ace2fbfab1 100644 ---- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c -@@ -196,7 +196,6 @@ static void gfxhub_v2_0_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC); /* UC, uncached */ - -diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c -index 1a374ec0514a5..9328991e8807f 100644 ---- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c -+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c -@@ -197,7 +197,6 @@ static void gfxhub_v2_1_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC); /* UC, uncached */ - -diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c -index 0e81e03e9b498..0fe714f54cca9 100644 ---- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c -@@ -841,12 +841,12 @@ static int gmc_v6_0_sw_init(void *handle) - - adev->gmc.mc_mask = 0xffffffffffULL; - -- r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44)); -+ r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40)); - if (r) { - dev_warn(adev->dev, "No suitable DMA available.\n"); - return r; - } -- adev->need_swiotlb = drm_need_swiotlb(44); -+ adev->need_swiotlb = drm_need_swiotlb(40); - - r = gmc_v6_0_init_microcode(adev); - if (r) { -diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c -index a99953833820e..b3bede1dc41da 100644 ---- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c -@@ -145,7 +145,6 @@ static void mmhub_v1_0_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC);/* XXX for emulation. */ - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1); -diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c -index f80a14a1b82dc..f5f7181f9af5f 100644 ---- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c -+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c -@@ -165,7 +165,6 @@ static void mmhub_v1_7_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC);/* XXX for emulation. */ - tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1); -diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c -index 7ded6b2f058ef..2e58ed2caa485 100644 ---- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c -@@ -269,7 +269,6 @@ static void mmhub_v2_0_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC); /* UC, uncached */ - -diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c -index 88e457a150e02..c63b6b9349350 100644 ---- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c -+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c -@@ -194,7 +194,6 @@ static void mmhub_v2_3_init_tlb_regs(struct amdgpu_device *adev) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC); /* UC, uncached */ - -diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c -index c4ef822bbe8c5..ff49eeaf78824 100644 ---- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c -+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c -@@ -189,8 +189,6 @@ static void mmhub_v9_4_init_tlb_regs(struct amdgpu_device *adev, int hubid) - ENABLE_ADVANCED_DRIVER_MODEL, 1); - tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, - SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); -- tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, -- ECO_BITS, 0); - tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, - MTYPE, MTYPE_UC);/* XXX for emulation. */ - tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, -diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c -index 7232241e3bfb2..0fef925b66024 100644 ---- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c -+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c -@@ -698,6 +698,19 @@ static int uvd_v3_1_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->uvd.idle_work); -+ -+ if (RREG32(mmUVD_STATUS) != 0) -+ uvd_v3_1_stop(adev); -+ -+ return 0; -+} -+ -+static int uvd_v3_1_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -722,17 +735,6 @@ static int uvd_v3_1_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- if (RREG32(mmUVD_STATUS) != 0) -- uvd_v3_1_stop(adev); -- -- return 0; --} -- --static int uvd_v3_1_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = uvd_v3_1_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c -index 52d6de969f462..c108b83817951 100644 ---- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c -+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c -@@ -212,6 +212,19 @@ static int uvd_v4_2_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->uvd.idle_work); -+ -+ if (RREG32(mmUVD_STATUS) != 0) -+ uvd_v4_2_stop(adev); -+ -+ return 0; -+} -+ -+static int uvd_v4_2_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -236,17 +249,6 @@ static int uvd_v4_2_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- if (RREG32(mmUVD_STATUS) != 0) -- uvd_v4_2_stop(adev); -- -- return 0; --} -- --static int uvd_v4_2_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = uvd_v4_2_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c -index db6d06758e4d4..563493d1f8306 100644 ---- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c -@@ -210,6 +210,19 @@ static int uvd_v5_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->uvd.idle_work); -+ -+ if (RREG32(mmUVD_STATUS) != 0) -+ uvd_v5_0_stop(adev); -+ -+ return 0; -+} -+ -+static int uvd_v5_0_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -234,17 +247,6 @@ static int uvd_v5_0_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- if (RREG32(mmUVD_STATUS) != 0) -- uvd_v5_0_stop(adev); -- -- return 0; --} -- --static int uvd_v5_0_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = uvd_v5_0_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c -index bc571833632ea..72f8762907681 100644 ---- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c -@@ -543,6 +543,19 @@ static int uvd_v6_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->uvd.idle_work); -+ -+ if (RREG32(mmUVD_STATUS) != 0) -+ uvd_v6_0_stop(adev); -+ -+ return 0; -+} -+ -+static int uvd_v6_0_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -567,17 +580,6 @@ static int uvd_v6_0_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- if (RREG32(mmUVD_STATUS) != 0) -- uvd_v6_0_stop(adev); -- -- return 0; --} -- --static int uvd_v6_0_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = uvd_v6_0_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c -index b6e82d75561f6..1fd9ca21a091b 100644 ---- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c -@@ -606,6 +606,23 @@ static int uvd_v7_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->uvd.idle_work); -+ -+ if (!amdgpu_sriov_vf(adev)) -+ uvd_v7_0_stop(adev); -+ else { -+ /* full access mode, so don't touch any UVD register */ -+ DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); -+ } -+ -+ return 0; -+} -+ -+static int uvd_v7_0_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -630,21 +647,6 @@ static int uvd_v7_0_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- if (!amdgpu_sriov_vf(adev)) -- uvd_v7_0_stop(adev); -- else { -- /* full access mode, so don't touch any UVD register */ -- DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); -- } -- -- return 0; --} -- --static int uvd_v7_0_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = uvd_v7_0_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c -index b70c17f0c52e8..98952fd387e73 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c -@@ -479,6 +479,17 @@ static int vce_v2_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->vce.idle_work); -+ -+ return 0; -+} -+ -+static int vce_v2_0_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -502,14 +513,6 @@ static int vce_v2_0_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- return 0; --} -- --static int vce_v2_0_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = vce_v2_0_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c -index 9de66893ccd6d..8fb5df7181e09 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c -@@ -490,6 +490,21 @@ static int vce_v3_0_hw_fini(void *handle) - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -+ cancel_delayed_work_sync(&adev->vce.idle_work); -+ -+ r = vce_v3_0_wait_for_idle(handle); -+ if (r) -+ return r; -+ -+ vce_v3_0_stop(adev); -+ return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); -+} -+ -+static int vce_v3_0_suspend(void *handle) -+{ -+ int r; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work -@@ -513,19 +528,6 @@ static int vce_v3_0_hw_fini(void *handle) - AMD_CG_STATE_GATE); - } - -- r = vce_v3_0_wait_for_idle(handle); -- if (r) -- return r; -- -- vce_v3_0_stop(adev); -- return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); --} -- --static int vce_v3_0_suspend(void *handle) --{ -- int r; -- struct amdgpu_device *adev = (struct amdgpu_device *)handle; -- - r = vce_v3_0_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c -index fec902b800c28..70b8c88d30513 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c -@@ -542,29 +542,8 @@ static int vce_v4_0_hw_fini(void *handle) - { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -- /* -- * Proper cleanups before halting the HW engine: -- * - cancel the delayed idle work -- * - enable powergating -- * - enable clockgating -- * - disable dpm -- * -- * TODO: to align with the VCN implementation, move the -- * jobs for clockgating/powergating/dpm setting to -- * ->set_powergating_state(). -- */ - cancel_delayed_work_sync(&adev->vce.idle_work); - -- if (adev->pm.dpm_enabled) { -- amdgpu_dpm_enable_vce(adev, false); -- } else { -- amdgpu_asic_set_vce_clocks(adev, 0, 0); -- amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -- AMD_PG_STATE_GATE); -- amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -- AMD_CG_STATE_GATE); -- } -- - if (!amdgpu_sriov_vf(adev)) { - /* vce_v4_0_wait_for_idle(handle); */ - vce_v4_0_stop(adev); -@@ -594,6 +573,29 @@ static int vce_v4_0_suspend(void *handle) - drm_dev_exit(idx); - } - -+ /* -+ * Proper cleanups before halting the HW engine: -+ * - cancel the delayed idle work -+ * - enable powergating -+ * - enable clockgating -+ * - disable dpm -+ * -+ * TODO: to align with the VCN implementation, move the -+ * jobs for clockgating/powergating/dpm setting to -+ * ->set_powergating_state(). -+ */ -+ cancel_delayed_work_sync(&adev->vce.idle_work); -+ -+ if (adev->pm.dpm_enabled) { -+ amdgpu_dpm_enable_vce(adev, false); -+ } else { -+ amdgpu_asic_set_vce_clocks(adev, 0, 0); -+ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -+ AMD_PG_STATE_GATE); -+ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -+ AMD_CG_STATE_GATE); -+ } -+ - r = vce_v4_0_hw_fini(adev); - if (r) - return r; -diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c -index f4686e918e0d1..c405075a572c1 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c -@@ -22,6 +22,7 @@ - */ - - #include <linux/firmware.h> -+#include <drm/drm_drv.h> - - #include "amdgpu.h" - #include "amdgpu_vcn.h" -@@ -192,11 +193,14 @@ static int vcn_v2_0_sw_init(void *handle) - */ - static int vcn_v2_0_sw_fini(void *handle) - { -- int r; -+ int r, idx; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared_cpu_addr; - -- fw_shared->present_flag_0 = 0; -+ if (drm_dev_enter(&adev->ddev, &idx)) { -+ fw_shared->present_flag_0 = 0; -+ drm_dev_exit(idx); -+ } - - amdgpu_virt_free_mm_table(adev); - -diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c -index e0c0c3734432e..a0956d8623770 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c -+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c -@@ -22,6 +22,7 @@ - */ - - #include <linux/firmware.h> -+#include <drm/drm_drv.h> - - #include "amdgpu.h" - #include "amdgpu_vcn.h" -@@ -233,17 +234,21 @@ static int vcn_v2_5_sw_init(void *handle) - */ - static int vcn_v2_5_sw_fini(void *handle) - { -- int i, r; -+ int i, r, idx; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - volatile struct amdgpu_fw_shared *fw_shared; - -- for (i = 0; i < adev->vcn.num_vcn_inst; i++) { -- if (adev->vcn.harvest_config & (1 << i)) -- continue; -- fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr; -- fw_shared->present_flag_0 = 0; -+ if (drm_dev_enter(&adev->ddev, &idx)) { -+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) { -+ if (adev->vcn.harvest_config & (1 << i)) -+ continue; -+ fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr; -+ fw_shared->present_flag_0 = 0; -+ } -+ drm_dev_exit(idx); - } - -+ - if (amdgpu_sriov_vf(adev)) - amdgpu_virt_free_mm_table(adev); - -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c -index 4a416231b24c8..88c483f699894 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c -@@ -916,6 +916,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, - kfd_double_confirm_iommu_support(kfd); - - if (kfd_iommu_device_init(kfd)) { -+ kfd->use_iommu_v2 = false; - dev_err(kfd_device, "Error initializing iommuv2\n"); - goto device_iommu_error; - } -@@ -924,6 +925,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, - - svm_migrate_init((struct amdgpu_device *)kfd->kgd); - -+ if(kgd2kfd_resume_iommu(kfd)) -+ goto device_iommu_error; -+ - if (kfd_resume(kfd)) - goto kfd_resume_error; - -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c -index f8fce9d05f50c..4f2e0cc8a51a8 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c -@@ -1225,6 +1225,11 @@ static int stop_cpsch(struct device_queue_manager *dqm) - bool hanging; - - dqm_lock(dqm); -+ if (!dqm->sched_running) { -+ dqm_unlock(dqm); -+ return 0; -+ } -+ - if (!dqm->is_hws_hang) - unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); - hanging = dqm->is_hws_hang || dqm->is_resetting; -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c -index 9d0f65a90002d..5a674235ae41a 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c -@@ -1307,7 +1307,7 @@ struct svm_validate_context { - struct svm_range *prange; - bool intr; - unsigned long bitmap[MAX_GPU_INSTANCE]; -- struct ttm_validate_buffer tv[MAX_GPU_INSTANCE+1]; -+ struct ttm_validate_buffer tv[MAX_GPU_INSTANCE]; - struct list_head validate_list; - struct ww_acquire_ctx ticket; - }; -@@ -1334,11 +1334,6 @@ static int svm_range_reserve_bos(struct svm_validate_context *ctx) - ctx->tv[gpuidx].num_shared = 4; - list_add(&ctx->tv[gpuidx].head, &ctx->validate_list); - } -- if (ctx->prange->svm_bo && ctx->prange->ttm_res) { -- ctx->tv[MAX_GPU_INSTANCE].bo = &ctx->prange->svm_bo->bo->tbo; -- ctx->tv[MAX_GPU_INSTANCE].num_shared = 1; -- list_add(&ctx->tv[MAX_GPU_INSTANCE].head, &ctx->validate_list); -- } - - r = ttm_eu_reserve_buffers(&ctx->ticket, &ctx->validate_list, - ctx->intr, NULL); -@@ -1570,7 +1565,6 @@ retry_flush_work: - static void svm_range_restore_work(struct work_struct *work) - { - struct delayed_work *dwork = to_delayed_work(work); -- struct amdkfd_process_info *process_info; - struct svm_range_list *svms; - struct svm_range *prange; - struct kfd_process *p; -@@ -1590,12 +1584,10 @@ static void svm_range_restore_work(struct work_struct *work) - * the lifetime of this thread, kfd_process and mm will be valid. - */ - p = container_of(svms, struct kfd_process, svms); -- process_info = p->kgd_process_info; - mm = p->mm; - if (!mm) - return; - -- mutex_lock(&process_info->lock); - svm_range_list_lock_and_flush_work(svms, mm); - mutex_lock(&svms->lock); - -@@ -1648,7 +1640,6 @@ static void svm_range_restore_work(struct work_struct *work) - out_reschedule: - mutex_unlock(&svms->lock); - mmap_write_unlock(mm); -- mutex_unlock(&process_info->lock); - - /* If validation failed, reschedule another attempt */ - if (evicted_ranges) { -@@ -2979,7 +2970,6 @@ static int - svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, - uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) - { -- struct amdkfd_process_info *process_info = p->kgd_process_info; - struct mm_struct *mm = current->mm; - struct list_head update_list; - struct list_head insert_list; -@@ -2998,8 +2988,6 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, - - svms = &p->svms; - -- mutex_lock(&process_info->lock); -- - svm_range_list_lock_and_flush_work(svms, mm); - - if (!svm_range_is_valid(mm, start, size)) { -@@ -3075,8 +3063,6 @@ out_unlock_range: - mutex_unlock(&svms->lock); - mmap_read_unlock(mm); - out: -- mutex_unlock(&process_info->lock); -- - pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] done, r=%d\n", p->pasid, - &p->svms, start, start + size - 1, r); - -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 1ea31dcc7a8b0..fef13e93a99fd 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -1141,8 +1141,15 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) - case CHIP_RAVEN: - case CHIP_RENOIR: - init_data.flags.gpu_vm_support = true; -- if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id)) -+ switch (adev->dm.dmcub_fw_version) { -+ case 0: /* development */ -+ case 0x1: /* linux-firmware.git hash 6d9f399 */ -+ case 0x01000000: /* linux-firmware.git hash 9a0b0f4 */ -+ init_data.flags.disable_dmcu = false; -+ break; -+ default: - init_data.flags.disable_dmcu = true; -+ } - break; - case CHIP_VANGOGH: - case CHIP_YELLOW_CARP: -@@ -2206,6 +2213,9 @@ static int dm_resume(void *handle) - if (amdgpu_in_reset(adev)) { - dc_state = dm->cached_dc_state; - -+ if (dc_enable_dmub_notifications(adev->dm.dc)) -+ amdgpu_dm_outbox_init(adev); -+ - r = dm_dmub_hw_init(adev); - if (r) - DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); -@@ -2217,8 +2227,8 @@ static int dm_resume(void *handle) - - for (i = 0; i < dc_state->stream_count; i++) { - dc_state->streams[i]->mode_changed = true; -- for (j = 0; j < dc_state->stream_status->plane_count; j++) { -- dc_state->stream_status->plane_states[j]->update_flags.raw -+ for (j = 0; j < dc_state->stream_status[i].plane_count; j++) { -+ dc_state->stream_status[i].plane_states[j]->update_flags.raw - = 0xffffffff; - } - } -@@ -2253,6 +2263,10 @@ static int dm_resume(void *handle) - /* TODO: Remove dc_state->dccg, use dc->dccg directly. */ - dc_resource_state_construct(dm->dc, dm_state->context); - -+ /* Re-enable outbox interrupts for DPIA. */ -+ if (dc_enable_dmub_notifications(adev->dm.dc)) -+ amdgpu_dm_outbox_init(adev); -+ - /* Before powering on DC we need to re-initialize DMUB. */ - r = dm_dmub_hw_init(adev); - if (r) -@@ -3839,6 +3853,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) - } else if (dc_link_detect(link, DETECT_REASON_BOOT)) { - amdgpu_dm_update_connector_after_detect(aconnector); - register_backlight_device(dm, link); -+ -+ if (dm->num_of_edps) -+ update_connector_ext_caps(aconnector); - if (amdgpu_dc_feature_mask & DC_PSR_MASK) - amdgpu_dm_set_psr_caps(link); - } -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c -index cce062adc4391..8a441a22c46ec 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c -@@ -314,6 +314,14 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) - ret = -EINVAL; - goto cleanup; - } -+ -+ if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) && -+ (aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) { -+ DRM_DEBUG_DRIVER("No DP connector available for CRC source\n"); -+ ret = -EINVAL; -+ goto cleanup; -+ } -+ - } - - #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c -index 8080bba5b7a76..de9ec5ddb6c72 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c -@@ -247,6 +247,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, - { - struct amdgpu_dm_connector *connector = file_inode(f)->i_private; - struct dc_link *link = connector->dc_link; -+ struct dc *dc = (struct dc *)link->dc; - struct dc_link_settings prefer_link_settings; - char *wr_buf = NULL; - const uint32_t wr_buf_size = 40; -@@ -313,7 +314,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, - prefer_link_settings.lane_count = param[0]; - prefer_link_settings.link_rate = param[1]; - -- dp_retrain_link_dp_test(link, &prefer_link_settings, false); -+ dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true); - - kfree(wr_buf); - return size; -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c -index 6fee12c91ef59..d793eec69d61e 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c -@@ -40,6 +40,39 @@ - - #include "dm_helpers.h" - -+struct monitor_patch_info { -+ unsigned int manufacturer_id; -+ unsigned int product_id; -+ void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param); -+ unsigned int patch_param; -+}; -+static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param); -+ -+static const struct monitor_patch_info monitor_patch_table[] = { -+{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15}, -+{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15}, -+}; -+ -+static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param) -+{ -+ if (edid_caps) -+ edid_caps->panel_patch.max_dsc_target_bpp_limit = param; -+} -+ -+static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps) -+{ -+ int i, ret = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++) -+ if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id) -+ && (edid_caps->product_id == monitor_patch_table[i].product_id)) { -+ monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param); -+ ret++; -+ } -+ -+ return ret; -+} -+ - /* dm_helpers_parse_edid_caps - * - * Parse edid caps -@@ -125,6 +158,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps( - kfree(sads); - kfree(sadb); - -+ amdgpu_dm_patch_edid_caps(edid_caps); -+ - return result; - } - -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 7af0d58c231b6..74885ff77f96a 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 -@@ -36,6 +36,8 @@ - #include "dm_helpers.h" - - #include "dc_link_ddc.h" -+#include "ddc_service_types.h" -+#include "dpcd_defs.h" - - #include "i2caux_interface.h" - #include "dmub_cmd.h" -@@ -155,6 +157,16 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { - }; - - #if defined(CONFIG_DRM_AMD_DC_DCN) -+static bool needs_dsc_aux_workaround(struct dc_link *link) -+{ -+ if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && -+ (link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) && -+ link->dpcd_caps.sink_count.bits.SINK_COUNT >= 2) -+ return true; -+ -+ return false; -+} -+ - static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector) - { - struct dc_sink *dc_sink = aconnector->dc_sink; -@@ -164,7 +176,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto - u8 *dsc_branch_dec_caps = NULL; - - aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port); --#if defined(CONFIG_HP_HOOK_WORKAROUND) -+ - /* - * drm_dp_mst_dsc_aux_for_port() will return NULL for certain configs - * because it only check the dsc/fec caps of the "port variable" and not the dock -@@ -174,10 +186,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto - * Workaround: explicitly check the use case above and use the mst dock's aux as dsc_aux - * - */ -- -- if (!aconnector->dsc_aux && !port->parent->port_parent) -+ if (!aconnector->dsc_aux && !port->parent->port_parent && -+ needs_dsc_aux_workaround(aconnector->dc_link)) - aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; --#endif -+ - if (!aconnector->dsc_aux) - return false; - -diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c -index 6d655e158267a..61c18637f84dc 100644 ---- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c -+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c -@@ -4690,7 +4690,7 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready) - link_enc->funcs->fec_set_ready(link_enc, true); - link->fec_state = dc_link_fec_ready; - } else { -- link_enc->funcs->fec_set_ready(link->link_enc, false); -+ link_enc->funcs->fec_set_ready(link_enc, false); - link->fec_state = dc_link_fec_not_ready; - dm_error("dpcd write failed to set fec_ready"); - } -diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c -index a60396d5be445..e94546187cf15 100644 ---- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c -@@ -1623,6 +1623,10 @@ bool dc_is_stream_unchanged( - if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) - return false; - -+ // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks -+ if (old_stream->audio_info.mode_count != stream->audio_info.mode_count) -+ return false; -+ - return true; - } - -diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c -index df8a7718a85fc..3af49cdf89ebd 100644 ---- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c -+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c -@@ -1522,7 +1522,7 @@ void dcn10_power_down_on_boot(struct dc *dc) - for (i = 0; i < dc->link_count; i++) { - struct dc_link *link = dc->links[i]; - -- if (link->link_enc->funcs->is_dig_enabled && -+ if (link->link_enc && link->link_enc->funcs->is_dig_enabled && - link->link_enc->funcs->is_dig_enabled(link->link_enc) && - dc->hwss.power_down) { - dc->hwss.power_down(dc); -diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c -index e3e01b17c164e..ede11eb120d4f 100644 ---- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c -+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c -@@ -1854,7 +1854,9 @@ static void swizzle_to_dml_params( - case DC_SW_VAR_D_X: - *sw_mode = dm_sw_var_d_x; - break; -- -+ case DC_SW_VAR_R_X: -+ *sw_mode = dm_sw_var_r_x; -+ break; - default: - ASSERT(0); /* Not supported */ - break; -@@ -3152,7 +3154,7 @@ void dcn20_calculate_dlg_params( - - context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml, - &context->res_ctx.pipe_ctx[i].rq_regs, -- pipes[pipe_idx].pipe); -+ &pipes[pipe_idx].pipe); - pipe_idx++; - } - } -@@ -3668,16 +3670,22 @@ static bool init_soc_bounding_box(struct dc *dc, - clock_limits_available = (status == PP_SMU_RESULT_OK); - } - -- if (clock_limits_available && uclk_states_available && num_states) -+ if (clock_limits_available && uclk_states_available && num_states) { -+ DC_FP_START(); - dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states); -- else if (clock_limits_available) -+ DC_FP_END(); -+ } else if (clock_limits_available) { -+ DC_FP_START(); - dcn20_cap_soc_clocks(loaded_bb, max_clocks); -+ DC_FP_END(); -+ } - } - - loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; - loaded_ip->max_num_dpp = pool->base.pipe_count; -+ DC_FP_START(); - dcn20_patch_bounding_box(dc, loaded_bb); -- -+ DC_FP_END(); - return true; - } - -@@ -3697,8 +3705,6 @@ static bool dcn20_resource_construct( - enum dml_project dml_project_version = - get_dml_project_version(ctx->asic_id.hw_internal_rev); - -- DC_FP_START(); -- - ctx->dc_bios->regs = &bios_regs; - pool->base.funcs = &dcn20_res_pool_funcs; - -@@ -4047,12 +4053,10 @@ static bool dcn20_resource_construct( - pool->base.oem_device = NULL; - } - -- DC_FP_END(); - return true; - - create_fail: - -- DC_FP_END(); - dcn20_resource_destruct(pool); - - return false; -diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c -index fafed1e4a998d..0950784bafa49 100644 ---- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c -+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c -@@ -1002,7 +1002,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc, - /* turning off DPG */ - pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false); - for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) -- mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false); -+ if (mpcc_pipe->plane_res.hubp) -+ mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false); - - stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space, - color_depth, solid_color, width, height, offset); -diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c -index 40011cd3c8ef0..ac8fb202fd5ee 100644 ---- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c -+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c -@@ -100,6 +100,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = { - .z10_save_init = dcn31_z10_save_init, - .is_abm_supported = dcn31_is_abm_supported, - .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, -+ .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, - .update_visual_confirm_color = dcn20_update_visual_confirm_color, - }; - -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c -index 2091dd8c252da..8c168f348a27f 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c -@@ -768,12 +768,12 @@ static void dml20_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, - - void dml20_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param) -+ const display_pipe_params_st *pipe_param) - { - display_rq_params_st rq_param = {0}; - - memset(rq_regs, 0, sizeof(*rq_regs)); -- dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param.src); -+ dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); - extract_rq_regs(mode_lib, rq_regs, rq_param); - - print__rq_regs_st(mode_lib, *rq_regs); -@@ -1549,7 +1549,7 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, - void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h -index d0b90947f5409..8b23867e97c18 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h -@@ -43,7 +43,7 @@ struct display_mode_lib; - void dml20_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param); -+ const display_pipe_params_st *pipe_param); - - - // Function: dml_rq_dlg_get_dlg_reg -@@ -61,7 +61,7 @@ void dml20_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c -index 1a0c14e465faa..26ececfd40cdc 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c -@@ -768,12 +768,12 @@ static void dml20v2_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, - - void dml20v2_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param) -+ const display_pipe_params_st *pipe_param) - { - display_rq_params_st rq_param = {0}; - - memset(rq_regs, 0, sizeof(*rq_regs)); -- dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param.src); -+ dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); - extract_rq_regs(mode_lib, rq_regs, rq_param); - - print__rq_regs_st(mode_lib, *rq_regs); -@@ -1550,7 +1550,7 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, - void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h -index 27cf8bed9376f..2b4e46ea1c3df 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h -@@ -43,7 +43,7 @@ struct display_mode_lib; - void dml20v2_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param); -+ const display_pipe_params_st *pipe_param); - - - // Function: dml_rq_dlg_get_dlg_reg -@@ -61,7 +61,7 @@ void dml20v2_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c -index 287e31052b307..736978c4d40a1 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c -@@ -694,7 +694,7 @@ static void get_surf_rq_param( - display_data_rq_sizing_params_st *rq_sizing_param, - display_data_rq_dlg_params_st *rq_dlg_param, - display_data_rq_misc_params_st *rq_misc_param, -- const display_pipe_params_st pipe_param, -+ const display_pipe_params_st *pipe_param, - bool is_chroma) - { - bool mode_422 = false; -@@ -706,30 +706,30 @@ static void get_surf_rq_param( - - // FIXME check if ppe apply for both luma and chroma in 422 case - if (is_chroma) { -- vp_width = pipe_param.src.viewport_width_c / ppe; -- vp_height = pipe_param.src.viewport_height_c; -- data_pitch = pipe_param.src.data_pitch_c; -- meta_pitch = pipe_param.src.meta_pitch_c; -+ vp_width = pipe_param->src.viewport_width_c / ppe; -+ vp_height = pipe_param->src.viewport_height_c; -+ data_pitch = pipe_param->src.data_pitch_c; -+ meta_pitch = pipe_param->src.meta_pitch_c; - } else { -- vp_width = pipe_param.src.viewport_width / ppe; -- vp_height = pipe_param.src.viewport_height; -- data_pitch = pipe_param.src.data_pitch; -- meta_pitch = pipe_param.src.meta_pitch; -+ vp_width = pipe_param->src.viewport_width / ppe; -+ vp_height = pipe_param->src.viewport_height; -+ data_pitch = pipe_param->src.data_pitch; -+ meta_pitch = pipe_param->src.meta_pitch; - } - -- if (pipe_param.dest.odm_combine) { -+ if (pipe_param->dest.odm_combine) { - unsigned int access_dir; - unsigned int full_src_vp_width; - unsigned int hactive_half; - unsigned int src_hactive_half; -- access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed -- hactive_half = pipe_param.dest.hactive / 2; -+ access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed -+ hactive_half = pipe_param->dest.hactive / 2; - if (is_chroma) { -- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; -- src_hactive_half = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_half; -+ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; -+ src_hactive_half = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_half; - } else { -- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; -- src_hactive_half = pipe_param.scale_ratio_depth.hscl_ratio * hactive_half; -+ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; -+ src_hactive_half = pipe_param->scale_ratio_depth.hscl_ratio * hactive_half; - } - - if (access_dir == 0) { -@@ -754,7 +754,7 @@ static void get_surf_rq_param( - rq_sizing_param->meta_chunk_bytes = 2048; - rq_sizing_param->min_meta_chunk_bytes = 256; - -- if (pipe_param.src.hostvm) -+ if (pipe_param->src.hostvm) - rq_sizing_param->mpte_group_bytes = 512; - else - rq_sizing_param->mpte_group_bytes = 2048; -@@ -768,23 +768,23 @@ static void get_surf_rq_param( - vp_height, - data_pitch, - meta_pitch, -- pipe_param.src.source_format, -- pipe_param.src.sw_mode, -- pipe_param.src.macro_tile_size, -- pipe_param.src.source_scan, -- pipe_param.src.hostvm, -+ pipe_param->src.source_format, -+ pipe_param->src.sw_mode, -+ pipe_param->src.macro_tile_size, -+ pipe_param->src.source_scan, -+ pipe_param->src.hostvm, - is_chroma); - } - - static void dml_rq_dlg_get_rq_params( - struct display_mode_lib *mode_lib, - display_rq_params_st *rq_param, -- const display_pipe_params_st pipe_param) -+ const display_pipe_params_st *pipe_param) - { - // get param for luma surface -- rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 -- || pipe_param.src.source_format == dm_420_10; -- rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; -+ rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 -+ || pipe_param->src.source_format == dm_420_10; -+ rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; - - get_surf_rq_param( - mode_lib, -@@ -794,7 +794,7 @@ static void dml_rq_dlg_get_rq_params( - pipe_param, - 0); - -- if (is_dual_plane((enum source_format_class) (pipe_param.src.source_format))) { -+ if (is_dual_plane((enum source_format_class) (pipe_param->src.source_format))) { - // get param for chroma surface - get_surf_rq_param( - mode_lib, -@@ -806,14 +806,14 @@ static void dml_rq_dlg_get_rq_params( - } - - // calculate how to split the det buffer space between luma and chroma -- handle_det_buf_split(mode_lib, rq_param, pipe_param.src); -+ handle_det_buf_split(mode_lib, rq_param, pipe_param->src); - print__rq_params_st(mode_lib, *rq_param); - } - - void dml21_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param) -+ const display_pipe_params_st *pipe_param) - { - display_rq_params_st rq_param = {0}; - -@@ -1658,7 +1658,7 @@ void dml21_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -@@ -1696,7 +1696,7 @@ void dml21_rq_dlg_get_dlg_reg( - // system parameter calculation done - - dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); -- dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); -+ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); - dml_rq_dlg_get_dlg_params( - mode_lib, - e2e_pipe_param, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h -index e8f7785e3fc63..af6ad0ca9cf8a 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h -@@ -44,7 +44,7 @@ struct display_mode_lib; - void dml21_rq_dlg_get_rq_reg( - struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param); -+ const display_pipe_params_st *pipe_param); - - // Function: dml_rq_dlg_get_dlg_reg - // Calculate and return DLG and TTU register struct given the system setting -@@ -61,7 +61,7 @@ void dml21_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c -index 0d934fae1c3a6..2120e0941a095 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c -@@ -747,7 +747,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, - display_data_rq_sizing_params_st *rq_sizing_param, - display_data_rq_dlg_params_st *rq_dlg_param, - display_data_rq_misc_params_st *rq_misc_param, -- const display_pipe_params_st pipe_param, -+ const display_pipe_params_st *pipe_param, - bool is_chroma, - bool is_alpha) - { -@@ -761,32 +761,32 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, - - // FIXME check if ppe apply for both luma and chroma in 422 case - if (is_chroma | is_alpha) { -- vp_width = pipe_param.src.viewport_width_c / ppe; -- vp_height = pipe_param.src.viewport_height_c; -- data_pitch = pipe_param.src.data_pitch_c; -- meta_pitch = pipe_param.src.meta_pitch_c; -- surface_height = pipe_param.src.surface_height_y / 2.0; -+ vp_width = pipe_param->src.viewport_width_c / ppe; -+ vp_height = pipe_param->src.viewport_height_c; -+ data_pitch = pipe_param->src.data_pitch_c; -+ meta_pitch = pipe_param->src.meta_pitch_c; -+ surface_height = pipe_param->src.surface_height_y / 2.0; - } else { -- vp_width = pipe_param.src.viewport_width / ppe; -- vp_height = pipe_param.src.viewport_height; -- data_pitch = pipe_param.src.data_pitch; -- meta_pitch = pipe_param.src.meta_pitch; -- surface_height = pipe_param.src.surface_height_y; -+ vp_width = pipe_param->src.viewport_width / ppe; -+ vp_height = pipe_param->src.viewport_height; -+ data_pitch = pipe_param->src.data_pitch; -+ meta_pitch = pipe_param->src.meta_pitch; -+ surface_height = pipe_param->src.surface_height_y; - } - -- if (pipe_param.dest.odm_combine) { -+ if (pipe_param->dest.odm_combine) { - unsigned int access_dir = 0; - unsigned int full_src_vp_width = 0; - unsigned int hactive_odm = 0; - unsigned int src_hactive_odm = 0; -- access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed -- hactive_odm = pipe_param.dest.hactive / ((unsigned int)pipe_param.dest.odm_combine*2); -+ access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed -+ hactive_odm = pipe_param->dest.hactive / ((unsigned int) pipe_param->dest.odm_combine*2); - if (is_chroma) { -- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; -- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_odm; -+ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; -+ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_odm; - } else { -- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; -- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio * hactive_odm; -+ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; -+ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio * hactive_odm; - } - - if (access_dir == 0) { -@@ -815,7 +815,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, - rq_sizing_param->meta_chunk_bytes = 2048; - rq_sizing_param->min_meta_chunk_bytes = 256; - -- if (pipe_param.src.hostvm) -+ if (pipe_param->src.hostvm) - rq_sizing_param->mpte_group_bytes = 512; - else - rq_sizing_param->mpte_group_bytes = 2048; -@@ -828,28 +828,28 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, - vp_height, - data_pitch, - meta_pitch, -- pipe_param.src.source_format, -- pipe_param.src.sw_mode, -- pipe_param.src.macro_tile_size, -- pipe_param.src.source_scan, -- pipe_param.src.hostvm, -+ pipe_param->src.source_format, -+ pipe_param->src.sw_mode, -+ pipe_param->src.macro_tile_size, -+ pipe_param->src.source_scan, -+ pipe_param->src.hostvm, - is_chroma, - surface_height); - } - - static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, - display_rq_params_st *rq_param, -- const display_pipe_params_st pipe_param) -+ const display_pipe_params_st *pipe_param) - { - // get param for luma surface -- rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 -- || pipe_param.src.source_format == dm_420_10 -- || pipe_param.src.source_format == dm_rgbe_alpha -- || pipe_param.src.source_format == dm_420_12; -+ rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 -+ || pipe_param->src.source_format == dm_420_10 -+ || pipe_param->src.source_format == dm_rgbe_alpha -+ || pipe_param->src.source_format == dm_420_12; - -- rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; -+ rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; - -- rq_param->rgbe_alpha = (pipe_param.src.source_format == dm_rgbe_alpha)?1:0; -+ rq_param->rgbe_alpha = (pipe_param->src.source_format == dm_rgbe_alpha)?1:0; - - get_surf_rq_param(mode_lib, - &(rq_param->sizing.rq_l), -@@ -859,7 +859,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, - 0, - 0); - -- if (is_dual_plane((enum source_format_class)(pipe_param.src.source_format))) { -+ if (is_dual_plane((enum source_format_class)(pipe_param->src.source_format))) { - // get param for chroma surface - get_surf_rq_param(mode_lib, - &(rq_param->sizing.rq_c), -@@ -871,13 +871,13 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, - } - - // calculate how to split the det buffer space between luma and chroma -- handle_det_buf_split(mode_lib, rq_param, pipe_param.src); -+ handle_det_buf_split(mode_lib, rq_param, pipe_param->src); - print__rq_params_st(mode_lib, *rq_param); - } - - void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param) -+ const display_pipe_params_st *pipe_param) - { - display_rq_params_st rq_param = { 0 }; - -@@ -1831,7 +1831,7 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, - void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -@@ -1866,7 +1866,7 @@ void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, - // system parameter calculation done - - dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); -- dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); -+ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); - dml_rq_dlg_get_dlg_params(mode_lib, - e2e_pipe_param, - num_pipes, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h -index c04965cceff35..625e41f8d5751 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h -@@ -41,7 +41,7 @@ struct display_mode_lib; - // See also: <display_rq_regs_st> - void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param); -+ const display_pipe_params_st *pipe_param); - - // Function: dml_rq_dlg_get_dlg_reg - // Calculate and return DLG and TTU register struct given the system setting -@@ -57,7 +57,7 @@ void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c -index c23905bc733ae..57bd4e3f8a823 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c -@@ -738,7 +738,7 @@ static void get_surf_rq_param( - display_data_rq_sizing_params_st *rq_sizing_param, - display_data_rq_dlg_params_st *rq_dlg_param, - display_data_rq_misc_params_st *rq_misc_param, -- const display_pipe_params_st pipe_param, -+ const display_pipe_params_st *pipe_param, - bool is_chroma, - bool is_alpha) - { -@@ -752,33 +752,33 @@ static void get_surf_rq_param( - - // FIXME check if ppe apply for both luma and chroma in 422 case - if (is_chroma | is_alpha) { -- vp_width = pipe_param.src.viewport_width_c / ppe; -- vp_height = pipe_param.src.viewport_height_c; -- data_pitch = pipe_param.src.data_pitch_c; -- meta_pitch = pipe_param.src.meta_pitch_c; -- surface_height = pipe_param.src.surface_height_y / 2.0; -+ vp_width = pipe_param->src.viewport_width_c / ppe; -+ vp_height = pipe_param->src.viewport_height_c; -+ data_pitch = pipe_param->src.data_pitch_c; -+ meta_pitch = pipe_param->src.meta_pitch_c; -+ surface_height = pipe_param->src.surface_height_y / 2.0; - } else { -- vp_width = pipe_param.src.viewport_width / ppe; -- vp_height = pipe_param.src.viewport_height; -- data_pitch = pipe_param.src.data_pitch; -- meta_pitch = pipe_param.src.meta_pitch; -- surface_height = pipe_param.src.surface_height_y; -+ vp_width = pipe_param->src.viewport_width / ppe; -+ vp_height = pipe_param->src.viewport_height; -+ data_pitch = pipe_param->src.data_pitch; -+ meta_pitch = pipe_param->src.meta_pitch; -+ surface_height = pipe_param->src.surface_height_y; - } - -- if (pipe_param.dest.odm_combine) { -+ if (pipe_param->dest.odm_combine) { - unsigned int access_dir; - unsigned int full_src_vp_width; - unsigned int hactive_odm; - unsigned int src_hactive_odm; - -- access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed -- hactive_odm = pipe_param.dest.hactive / ((unsigned int) pipe_param.dest.odm_combine * 2); -+ access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed -+ hactive_odm = pipe_param->dest.hactive / ((unsigned int) pipe_param->dest.odm_combine * 2); - if (is_chroma) { -- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; -- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_odm; -+ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; -+ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_odm; - } else { -- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; -- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio * hactive_odm; -+ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; -+ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio * hactive_odm; - } - - if (access_dir == 0) { -@@ -808,7 +808,7 @@ static void get_surf_rq_param( - rq_sizing_param->meta_chunk_bytes = 2048; - rq_sizing_param->min_meta_chunk_bytes = 256; - -- if (pipe_param.src.hostvm) -+ if (pipe_param->src.hostvm) - rq_sizing_param->mpte_group_bytes = 512; - else - rq_sizing_param->mpte_group_bytes = 2048; -@@ -822,38 +822,38 @@ static void get_surf_rq_param( - vp_height, - data_pitch, - meta_pitch, -- pipe_param.src.source_format, -- pipe_param.src.sw_mode, -- pipe_param.src.macro_tile_size, -- pipe_param.src.source_scan, -- pipe_param.src.hostvm, -+ pipe_param->src.source_format, -+ pipe_param->src.sw_mode, -+ pipe_param->src.macro_tile_size, -+ pipe_param->src.source_scan, -+ pipe_param->src.hostvm, - is_chroma, - surface_height); - } - --static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_params_st pipe_param) -+static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_params_st *pipe_param) - { - // get param for luma surface -- rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 || pipe_param.src.source_format == dm_420_10 || pipe_param.src.source_format == dm_rgbe_alpha -- || pipe_param.src.source_format == dm_420_12; -+ rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 || pipe_param->src.source_format == dm_420_10 || pipe_param->src.source_format == dm_rgbe_alpha -+ || pipe_param->src.source_format == dm_420_12; - -- rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; -+ rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; - -- rq_param->rgbe_alpha = (pipe_param.src.source_format == dm_rgbe_alpha) ? 1 : 0; -+ rq_param->rgbe_alpha = (pipe_param->src.source_format == dm_rgbe_alpha) ? 1 : 0; - - get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), &(rq_param->dlg.rq_l), &(rq_param->misc.rq_l), pipe_param, 0, 0); - -- if (is_dual_plane((enum source_format_class) (pipe_param.src.source_format))) { -+ if (is_dual_plane((enum source_format_class) (pipe_param->src.source_format))) { - // get param for chroma surface - get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), &(rq_param->dlg.rq_c), &(rq_param->misc.rq_c), pipe_param, 1, rq_param->rgbe_alpha); - } - - // calculate how to split the det buffer space between luma and chroma -- handle_det_buf_split(mode_lib, rq_param, pipe_param.src); -+ handle_det_buf_split(mode_lib, rq_param, pipe_param->src); - print__rq_params_st(mode_lib, *rq_param); - } - --void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st pipe_param) -+void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st *pipe_param) - { - display_rq_params_st rq_param = {0}; - -@@ -1677,7 +1677,7 @@ void dml31_rq_dlg_get_dlg_reg( - struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -@@ -1704,7 +1704,7 @@ void dml31_rq_dlg_get_dlg_reg( - // system parameter calculation done - - dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); -- dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); -+ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); - dml_rq_dlg_get_dlg_params( - mode_lib, - e2e_pipe_param, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h -index adf8518f761f9..8ee991351699d 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h -@@ -41,7 +41,7 @@ struct display_mode_lib; - // See also: <display_rq_regs_st> - void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param); -+ const display_pipe_params_st *pipe_param); - - // Function: dml_rq_dlg_get_dlg_reg - // Calculate and return DLG and TTU register struct given the system setting -@@ -57,7 +57,7 @@ void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, - void dml31_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h -index 1051ca1a23b8a..edb9f7567d6d9 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h -@@ -80,11 +80,11 @@ enum dm_swizzle_mode { - dm_sw_SPARE_13 = 24, - dm_sw_64kb_s_x = 25, - dm_sw_64kb_d_x = 26, -- dm_sw_SPARE_14 = 27, -+ dm_sw_64kb_r_x = 27, - dm_sw_SPARE_15 = 28, - dm_sw_var_s_x = 29, - dm_sw_var_d_x = 30, -- dm_sw_64kb_r_x, -+ dm_sw_var_r_x = 31, - dm_sw_gfx7_2d_thin_l_vp, - dm_sw_gfx7_2d_thin_gl, - }; -diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h -index d42a0aeca6be2..72b1957022aa2 100644 ---- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h -+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h -@@ -49,7 +49,7 @@ struct dml_funcs { - struct display_mode_lib *mode_lib, - display_dlg_regs_st *dlg_regs, - display_ttu_regs_st *ttu_regs, -- display_e2e_pipe_params_st *e2e_pipe_param, -+ const display_e2e_pipe_params_st *e2e_pipe_param, - const unsigned int num_pipes, - const unsigned int pipe_idx, - const bool cstate_en, -@@ -60,7 +60,7 @@ struct dml_funcs { - void (*rq_dlg_get_rq_reg)( - struct display_mode_lib *mode_lib, - display_rq_regs_st *rq_regs, -- const display_pipe_params_st pipe_param); -+ const display_pipe_params_st *pipe_param); - void (*recalculate)(struct display_mode_lib *mode_lib); - void (*validate)(struct display_mode_lib *mode_lib); - }; -diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h -index 257f280d3d53f..bd077ea224a40 100644 ---- a/drivers/gpu/drm/amd/include/amd_shared.h -+++ b/drivers/gpu/drm/amd/include/amd_shared.h -@@ -98,7 +98,8 @@ enum amd_ip_block_type { - AMD_IP_BLOCK_TYPE_ACP, - AMD_IP_BLOCK_TYPE_VCN, - AMD_IP_BLOCK_TYPE_MES, -- AMD_IP_BLOCK_TYPE_JPEG -+ AMD_IP_BLOCK_TYPE_JPEG, -+ AMD_IP_BLOCK_TYPE_NUM, - }; - - enum amd_clockgating_state { -diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c -index 03581d5b18360..08362d506534b 100644 ---- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c -+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c -@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block - { - int ret = 0; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; -+ enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; -+ -+ if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) { -+ dev_dbg(adev->dev, "IP block%d already in the target %s state!", -+ block_type, gate ? "gate" : "ungate"); -+ return 0; -+ } - - switch (block_type) { - case AMD_IP_BLOCK_TYPE_UVD: -@@ -979,6 +986,9 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block - break; - } - -+ if (!ret) -+ atomic_set(&adev->pm.pwr_state[block_type], pwr_state); -+ - return ret; - } - -diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h -index 98f1b3d8c1d59..16e3f72d31b9f 100644 ---- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h -+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h -@@ -417,6 +417,12 @@ struct amdgpu_dpm { - enum amd_dpm_forced_level forced_level; - }; - -+enum ip_power_state { -+ POWER_STATE_UNKNOWN, -+ POWER_STATE_ON, -+ POWER_STATE_OFF, -+}; -+ - struct amdgpu_pm { - struct mutex mutex; - u32 current_sclk; -@@ -452,6 +458,8 @@ struct amdgpu_pm { - struct i2c_adapter smu_i2c; - struct mutex smu_i2c_mutex; - struct list_head pm_attr_list; -+ -+ atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM]; - }; - - #define R600_SSTU_DFLT 0 -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c -index 1de3ae77e03ed..1f406f21b452f 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c -@@ -1036,13 +1036,13 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, - else - i = 1; - -- size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", -+ size += sprintf(buf + size, "0: %uMhz %s\n", - data->gfx_min_freq_limit/100, - i == 0 ? "*" : ""); -- size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", -+ size += sprintf(buf + size, "1: %uMhz %s\n", - i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK, - i == 1 ? "*" : ""); -- size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", -+ size += sprintf(buf + size, "2: %uMhz %s\n", - data->gfx_max_freq_limit/100, - i == 2 ? "*" : ""); - break; -@@ -1050,7 +1050,7 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now); - - for (i = 0; i < mclk_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, - mclk_table->entries[i].clk / 100, - ((mclk_table->entries[i].clk / 100) -@@ -1065,10 +1065,10 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, - if (ret) - return ret; - -- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); -- size += sysfs_emit_at(buf, size, "0: %10uMhz\n", -+ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); -+ size += sprintf(buf + size, "0: %10uMhz\n", - (data->gfx_actual_soft_min_freq > 0) ? data->gfx_actual_soft_min_freq : min_freq); -- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -+ size += sprintf(buf + size, "1: %10uMhz\n", - (data->gfx_actual_soft_max_freq > 0) ? data->gfx_actual_soft_max_freq : max_freq); - } - break; -@@ -1081,8 +1081,8 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, - if (ret) - return ret; - -- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); -- size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n", -+ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); -+ size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", - min_freq, max_freq); - } - break; -@@ -1456,6 +1456,8 @@ static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) - if (!buf) - return -EINVAL; - -+ phm_get_sysfs_buf(&buf, &size); -+ - size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n",title[0], - title[1], title[2], title[3], title[4], title[5]); - -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c -index e7803ce8f67aa..611969bf45207 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c -@@ -4926,7 +4926,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, - now = i; - - for (i = 0; i < sclk_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, sclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; -@@ -4941,7 +4941,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, - now = i; - - for (i = 0; i < mclk_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, mclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; -@@ -4955,7 +4955,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, - now = i; - - for (i = 0; i < pcie_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %s %s\n", i, -+ size += sprintf(buf + size, "%d: %s %s\n", i, - (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" : - (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" : - (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "", -@@ -4963,32 +4963,32 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, - break; - case OD_SCLK: - if (hwmgr->od_enabled) { -- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); -+ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); - for (i = 0; i < odn_sclk_table->num_of_pl; i++) -- size += sysfs_emit_at(buf, size, "%d: %10uMHz %10umV\n", -+ size += sprintf(buf + size, "%d: %10uMHz %10umV\n", - i, odn_sclk_table->entries[i].clock/100, - odn_sclk_table->entries[i].vddc); - } - break; - case OD_MCLK: - if (hwmgr->od_enabled) { -- size = sysfs_emit(buf, "%s:\n", "OD_MCLK"); -+ size += sprintf(buf + size, "%s:\n", "OD_MCLK"); - for (i = 0; i < odn_mclk_table->num_of_pl; i++) -- size += sysfs_emit_at(buf, size, "%d: %10uMHz %10umV\n", -+ size += sprintf(buf + size, "%d: %10uMHz %10umV\n", - i, odn_mclk_table->entries[i].clock/100, - odn_mclk_table->entries[i].vddc); - } - break; - case OD_RANGE: - if (hwmgr->od_enabled) { -- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); -- size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n", -+ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); -+ size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.engineClock/100); -- size += sysfs_emit_at(buf, size, "MCLK: %7uMHz %10uMHz\n", -+ size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); -- size += sysfs_emit_at(buf, size, "VDDC: %7umV %11umV\n", -+ size += sprintf(buf + size, "VDDC: %7umV %11umV\n", - data->odn_dpm_table.min_vddc, - data->odn_dpm_table.max_vddc); - } -@@ -5518,6 +5518,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) - if (!buf) - return -EINVAL; - -+ phm_get_sysfs_buf(&buf, &size); -+ - size += sysfs_emit_at(buf, size, "%s %16s %16s %16s %16s %16s %16s %16s\n", - title[0], title[1], title[2], title[3], - title[4], title[5], title[6], title[7]); -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c -index b94a77e4e7147..03bf8f0692228 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c -@@ -1559,7 +1559,7 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, - CURR_SCLK_INDEX); - - for (i = 0; i < sclk_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, sclk_table->entries[i].clk / 100, - (i == now) ? "*" : ""); - break; -@@ -1571,7 +1571,7 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, - CURR_MCLK_INDEX); - - for (i = SMU8_NUM_NBPMEMORYCLOCK; i > 0; i--) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - SMU8_NUM_NBPMEMORYCLOCK-i, data->sys_info.nbp_memory_clock[i-1] / 100, - (SMU8_NUM_NBPMEMORYCLOCK-i == now) ? "*" : ""); - break; -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h -index ad33983a8064e..2a75da1e9f035 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h -@@ -109,6 +109,19 @@ int phm_irq_process(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); - -+/* -+ * Helper function to make sysfs_emit_at() happy. Align buf to -+ * the current page boundary and record the offset. -+ */ -+static inline void phm_get_sysfs_buf(char **buf, int *offset) -+{ -+ if (!*buf || !offset) -+ return; -+ -+ *offset = offset_in_page(*buf); -+ *buf -= *offset; -+} -+ - int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr); - - void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size, -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c -index c152a61ddd2c9..e6336654c5655 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c -@@ -4548,6 +4548,8 @@ static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) - int ret = 0; - int size = 0; - -+ phm_get_sysfs_buf(&buf, &size); -+ - ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", -@@ -4650,7 +4652,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - else - count = sclk_table->count; - for (i = 0; i < count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, sclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; -@@ -4661,7 +4663,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); - - for (i = 0; i < mclk_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, mclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; -@@ -4672,7 +4674,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); - - for (i = 0; i < soc_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, soc_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; -@@ -4684,7 +4686,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now); - - for (i = 0; i < dcef_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, dcef_table->dpm_levels[i].value / 100, - (dcef_table->dpm_levels[i].value / 100 == now) ? - "*" : ""); -@@ -4698,7 +4700,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - gen_speed = pptable->PcieGenSpeed[i]; - lane_width = pptable->PcieLaneCount[i]; - -- size += sysfs_emit_at(buf, size, "%d: %s %s %s\n", i, -+ size += sprintf(buf + size, "%d: %s %s %s\n", i, - (gen_speed == 0) ? "2.5GT/s," : - (gen_speed == 1) ? "5.0GT/s," : - (gen_speed == 2) ? "8.0GT/s," : -@@ -4717,34 +4719,34 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - - case OD_SCLK: - if (hwmgr->od_enabled) { -- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); -+ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); - podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; - for (i = 0; i < podn_vdd_dep->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %10uMhz %10umV\n", -+ size += sprintf(buf + size, "%d: %10uMhz %10umV\n", - i, podn_vdd_dep->entries[i].clk / 100, - podn_vdd_dep->entries[i].vddc); - } - break; - case OD_MCLK: - if (hwmgr->od_enabled) { -- size = sysfs_emit(buf, "%s:\n", "OD_MCLK"); -+ size += sprintf(buf + size, "%s:\n", "OD_MCLK"); - podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; - for (i = 0; i < podn_vdd_dep->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %10uMhz %10umV\n", -+ size += sprintf(buf + size, "%d: %10uMhz %10umV\n", - i, podn_vdd_dep->entries[i].clk/100, - podn_vdd_dep->entries[i].vddc); - } - break; - case OD_RANGE: - if (hwmgr->od_enabled) { -- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); -- size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n", -+ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); -+ size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.engineClock/100); -- size += sysfs_emit_at(buf, size, "MCLK: %7uMHz %10uMHz\n", -+ size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.mem_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); -- size += sysfs_emit_at(buf, size, "VDDC: %7umV %11umV\n", -+ size += sprintf(buf + size, "VDDC: %7umV %11umV\n", - data->odn_dpm_table.min_vddc, - data->odn_dpm_table.max_vddc); - } -@@ -5112,6 +5114,8 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) - if (!buf) - return -EINVAL; - -+ phm_get_sysfs_buf(&buf, &size); -+ - size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n",title[0], - title[1], title[2], title[3], title[4], title[5]); - -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c -index 8558718e15a8f..a2f4d6773d458 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c -@@ -2141,6 +2141,8 @@ static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) - int ret = 0; - int size = 0; - -+ phm_get_sysfs_buf(&buf, &size); -+ - ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", -@@ -2256,7 +2258,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, - "Attempt to get gfx clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); - break; -@@ -2272,7 +2274,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, - "Attempt to get memory clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); - break; -@@ -2290,7 +2292,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, - "Attempt to get soc clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); - break; -@@ -2308,7 +2310,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, - "Attempt to get dcef clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); - break; -diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c -index 0cf39c1244b1c..85d55ab4e369f 100644 ---- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c -+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c -@@ -3238,6 +3238,8 @@ static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) - int ret = 0; - int size = 0; - -+ phm_get_sysfs_buf(&buf, &size); -+ - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", -@@ -3372,13 +3374,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - return ret); - - if (vega20_get_sclks(hwmgr, &clocks)) { -- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", -+ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; -@@ -3390,13 +3392,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - return ret); - - if (vega20_get_memclocks(hwmgr, &clocks)) { -- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", -+ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; -@@ -3408,13 +3410,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - return ret); - - if (vega20_get_socclocks(hwmgr, &clocks)) { -- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", -+ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; -@@ -3426,7 +3428,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - return ret); - - for (i = 0; i < fclk_dpm_table->count; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, fclk_dpm_table->dpm_levels[i].value, - fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : ""); - break; -@@ -3438,13 +3440,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - return ret); - - if (vega20_get_dcefclocks(hwmgr, &clocks)) { -- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", -+ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) -- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", -+ size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; -@@ -3458,7 +3460,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - gen_speed = pptable->PcieGenSpeed[i]; - lane_width = pptable->PcieLaneCount[i]; - -- size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i, -+ size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, - (gen_speed == 0) ? "2.5GT/s," : - (gen_speed == 1) ? "5.0GT/s," : - (gen_speed == 2) ? "8.0GT/s," : -@@ -3479,18 +3481,18 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - case OD_SCLK: - if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { -- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); -- size += sysfs_emit_at(buf, size, "0: %10uMhz\n", -+ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); -+ size += sprintf(buf + size, "0: %10uMhz\n", - od_table->GfxclkFmin); -- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -+ size += sprintf(buf + size, "1: %10uMhz\n", - od_table->GfxclkFmax); - } - break; - - case OD_MCLK: - if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { -- size = sysfs_emit(buf, "%s:\n", "OD_MCLK"); -- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -+ size += sprintf(buf + size, "%s:\n", "OD_MCLK"); -+ size += sprintf(buf + size, "1: %10uMhz\n", - od_table->UclkFmax); - } - -@@ -3503,14 +3505,14 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { -- size = sysfs_emit(buf, "%s:\n", "OD_VDDC_CURVE"); -- size += sysfs_emit_at(buf, size, "0: %10uMhz %10dmV\n", -+ size += sprintf(buf + size, "%s:\n", "OD_VDDC_CURVE"); -+ size += sprintf(buf + size, "0: %10uMhz %10dmV\n", - od_table->GfxclkFreq1, - od_table->GfxclkVolt1 / VOLTAGE_SCALE); -- size += sysfs_emit_at(buf, size, "1: %10uMhz %10dmV\n", -+ size += sprintf(buf + size, "1: %10uMhz %10dmV\n", - od_table->GfxclkFreq2, - od_table->GfxclkVolt2 / VOLTAGE_SCALE); -- size += sysfs_emit_at(buf, size, "2: %10uMhz %10dmV\n", -+ size += sprintf(buf + size, "2: %10uMhz %10dmV\n", - od_table->GfxclkFreq3, - od_table->GfxclkVolt3 / VOLTAGE_SCALE); - } -@@ -3518,17 +3520,17 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - break; - - case OD_RANGE: -- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); -+ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); - - if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { -- size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", -+ size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, - od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); - } - - if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { -- size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n", -+ size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_UCLK_FMAX].min_value, - od8_settings[OD8_SETTING_UCLK_FMAX].max_value); - } -@@ -3539,22 +3541,22 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { -- size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", -+ size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, - od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value); -- size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", -+ size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); -- size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", -+ size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, - od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value); -- size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", -+ size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); -- size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", -+ size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, - od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value); -- size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", -+ size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); - } -@@ -4003,6 +4005,8 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) - if (!buf) - return -EINVAL; - -+ phm_get_sysfs_buf(&buf, &size); -+ - size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n", - title[0], title[1], title[2], title[3], title[4], title[5], - title[6], title[7], title[8], title[9], title[10]); -diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c -index b1ad451af06bd..dfba0bc732073 100644 ---- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c -+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c -@@ -1265,7 +1265,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, char *buf) - { - uint16_t *curve_settings; -- int i, size = 0, ret = 0; -+ int i, levels, size = 0, ret = 0; - uint32_t cur_value = 0, value = 0, count = 0; - uint32_t freq_values[3] = {0}; - uint32_t mark_index = 0; -@@ -1319,14 +1319,17 @@ static int navi10_print_clk_levels(struct smu_context *smu, - freq_values[1] = cur_value; - mark_index = cur_value == freq_values[0] ? 0 : - cur_value == freq_values[2] ? 2 : 1; -- if (mark_index != 1) -- freq_values[1] = (freq_values[0] + freq_values[2]) / 2; - -- for (i = 0; i < 3; i++) { -+ levels = 3; -+ if (mark_index != 1) { -+ levels = 2; -+ freq_values[1] = freq_values[2]; -+ } -+ -+ for (i = 0; i < levels; i++) { - size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, freq_values[i], - i == mark_index ? "*" : ""); - } -- - } - break; - case SMU_PCIE: -diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c -index f6ef0ce6e9e2c..a9dceef4a7011 100644 ---- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c -+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c -@@ -1386,52 +1386,38 @@ static int vangogh_set_performance_level(struct smu_context *smu, - uint32_t soc_mask, mclk_mask, fclk_mask; - uint32_t vclk_mask = 0, dclk_mask = 0; - -+ smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -+ smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -+ - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: -- smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; -+ smu->gfx_actual_hard_min_freq = smu->gfx_default_soft_max_freq; - smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; - -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; - - ret = vangogh_force_dpm_limit_value(smu, true); -+ if (ret) -+ return ret; - break; - case AMD_DPM_FORCED_LEVEL_LOW: - smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; -- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; -- -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -+ smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq; - - ret = vangogh_force_dpm_limit_value(smu, false); -+ if (ret) -+ return ret; - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; - smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; - -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -- - ret = vangogh_unforce_dpm_levels(smu); -- break; -- case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: -- smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; -- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; -- -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -- -- ret = smu_cmn_send_smc_msg_with_param(smu, -- SMU_MSG_SetHardMinGfxClk, -- VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL); -- if (ret) -- return ret; -- -- ret = smu_cmn_send_smc_msg_with_param(smu, -- SMU_MSG_SetSoftMaxGfxClk, -- VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL); - if (ret) - return ret; -+ break; -+ case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: -+ smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK; -+ smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK; - - ret = vangogh_get_profiling_clk_mask(smu, level, - &vclk_mask, -@@ -1446,32 +1432,15 @@ static int vangogh_set_performance_level(struct smu_context *smu, - vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); - vangogh_force_clk_levels(smu, SMU_VCLK, 1 << vclk_mask); - vangogh_force_clk_levels(smu, SMU_DCLK, 1 << dclk_mask); -- - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; -- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; -- -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -- -- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, -- VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL); -- if (ret) -- return ret; -- -- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, -- VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL); -- if (ret) -- return ret; -+ smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq; - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; - smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; - -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -- - ret = vangogh_get_profiling_clk_mask(smu, level, - NULL, - NULL, -@@ -1484,29 +1453,29 @@ static int vangogh_set_performance_level(struct smu_context *smu, - vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: -- smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; -- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; -- -- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; -- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; -- -- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, -- VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL); -- if (ret) -- return ret; -+ smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK; -+ smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK; - -- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, -- VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL); -+ ret = vangogh_set_peak_clock_by_device(smu); - if (ret) - return ret; -- -- ret = vangogh_set_peak_clock_by_device(smu); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: -- break; -+ return 0; - } -+ -+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, -+ smu->gfx_actual_hard_min_freq, NULL); -+ if (ret) -+ return ret; -+ -+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, -+ smu->gfx_actual_soft_max_freq, NULL); -+ if (ret) -+ return ret; -+ - return ret; - } - -diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c -index d60b8c5e87157..43028f2cd28b5 100644 ---- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c -+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c -@@ -191,6 +191,9 @@ int smu_v12_0_fini_smc_tables(struct smu_context *smu) - kfree(smu_table->watermarks_table); - smu_table->watermarks_table = NULL; - -+ kfree(smu_table->gpu_metrics_table); -+ smu_table->gpu_metrics_table = NULL; -+ - return 0; - } - -diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c -index a0e50f23b1dd7..8d4aa16b2ae7c 100644 ---- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c -+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c -@@ -197,6 +197,7 @@ int smu_v13_0_check_fw_status(struct smu_context *smu) - - int smu_v13_0_check_fw_version(struct smu_context *smu) - { -+ struct amdgpu_device *adev = smu->adev; - uint32_t if_version = 0xff, smu_version = 0xff; - uint16_t smu_major; - uint8_t smu_minor, smu_debug; -@@ -209,6 +210,8 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) - smu_major = (smu_version >> 16) & 0xffff; - smu_minor = (smu_version >> 8) & 0xff; - smu_debug = (smu_version >> 0) & 0xff; -+ if (smu->is_apu) -+ adev->pm.fw_version = smu_version; - - switch (smu->adev->asic_type) { - case CHIP_ALDEBARAN: -diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c -index b53fee6f1c170..65f172807a0d5 100644 ---- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c -+++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c -@@ -291,7 +291,7 @@ vga_pw_show(struct device *dev, struct device_attribute *attr, char *buf) - if (rc) - return rc; - -- return sprintf(buf, "%u\n", reg & 1); -+ return sprintf(buf, "%u\n", reg); - } - static DEVICE_ATTR_RO(vga_pw); - -diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c -index 1e30eaeb0e1b3..d5c98f79d58d3 100644 ---- a/drivers/gpu/drm/ast/ast_mode.c -+++ b/drivers/gpu/drm/ast/ast_mode.c -@@ -1121,7 +1121,10 @@ static void ast_crtc_reset(struct drm_crtc *crtc) - if (crtc->state) - crtc->funcs->atomic_destroy_state(crtc, crtc->state); - -- __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); -+ if (ast_state) -+ __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); -+ else -+ __drm_atomic_helper_crtc_reset(crtc, NULL); - } - - static struct drm_crtc_state * -diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c -index 14d73fb1dd15b..ea414cd349b5c 100644 ---- a/drivers/gpu/drm/bridge/analogix/anx7625.c -+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c -@@ -720,7 +720,7 @@ static int edid_read(struct anx7625_data *ctx, - ret = sp_tx_aux_rd(ctx, 0xf1); - - if (ret) { -- sp_tx_rst_aux(ctx); -+ ret = sp_tx_rst_aux(ctx); - DRM_DEV_DEBUG_DRIVER(dev, "edid read fail, reset!\n"); - } else { - ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client, -@@ -735,7 +735,7 @@ static int edid_read(struct anx7625_data *ctx, - if (cnt > EDID_TRY_CNT) - return -EIO; - -- return 0; -+ return ret; - } - - static int segments_edid_read(struct anx7625_data *ctx, -@@ -785,7 +785,7 @@ static int segments_edid_read(struct anx7625_data *ctx, - if (cnt > EDID_TRY_CNT) - return -EIO; - -- return 0; -+ return ret; - } - - static int sp_tx_edid_read(struct anx7625_data *ctx, -@@ -887,7 +887,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx, - } - - /* Reset aux channel */ -- sp_tx_rst_aux(ctx); -+ ret = sp_tx_rst_aux(ctx); -+ if (ret < 0) { -+ DRM_DEV_ERROR(dev, "Failed to reset aux channel!\n"); -+ return ret; -+ } - - return (blocks_num + 1); - } -diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c -index 2f2a09adb4bc8..06b59b422c696 100644 ---- a/drivers/gpu/drm/bridge/ite-it66121.c -+++ b/drivers/gpu/drm/bridge/ite-it66121.c -@@ -889,7 +889,7 @@ unlock: - static int it66121_probe(struct i2c_client *client, - const struct i2c_device_id *id) - { -- u32 vendor_ids[2], device_ids[2], revision_id; -+ u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; - struct device_node *ep; - int ret; - struct it66121_ctx *ctx; -@@ -918,11 +918,26 @@ static int it66121_probe(struct i2c_client *client, - return -EINVAL; - - ep = of_graph_get_remote_node(dev->of_node, 1, -1); -- if (!ep) -- return -EPROBE_DEFER; -+ if (!ep) { -+ dev_err(ctx->dev, "The endpoint is unconnected\n"); -+ return -EINVAL; -+ } -+ -+ if (!of_device_is_available(ep)) { -+ of_node_put(ep); -+ dev_err(ctx->dev, "The remote device is disabled\n"); -+ return -ENODEV; -+ } - - ctx->next_bridge = of_drm_find_bridge(ep); - of_node_put(ep); -+ if (!ctx->next_bridge) { -+ dev_dbg(ctx->dev, "Next bridge not found, deferring probe\n"); -+ return -EPROBE_DEFER; -+ } -+ -+ if (!ctx->next_bridge) -+ return -EPROBE_DEFER; - - i2c_set_clientdata(client, ctx); - mutex_init(&ctx->lock); -diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c -index 3cac16db970f0..010657ea7af78 100644 ---- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c -+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c -@@ -167,9 +167,10 @@ static void lt9611uxc_hpd_work(struct work_struct *work) - struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work); - bool connected; - -- if (lt9611uxc->connector.dev) -- drm_kms_helper_hotplug_event(lt9611uxc->connector.dev); -- else { -+ if (lt9611uxc->connector.dev) { -+ if (lt9611uxc->connector.dev->mode_config.funcs) -+ drm_kms_helper_hotplug_event(lt9611uxc->connector.dev); -+ } else { - - mutex_lock(<9611uxc->ocm_lock); - connected = lt9611uxc->hdmi_connected; -@@ -339,6 +340,8 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc - return -ENODEV; - } - -+ lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD; -+ - drm_connector_helper_add(<9611uxc->connector, - <9611uxc_bridge_connector_helper_funcs); - ret = drm_connector_init(bridge->dev, <9611uxc->connector, -diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c -index ed8ac5059cd26..a7389a0facfb4 100644 ---- a/drivers/gpu/drm/bridge/nwl-dsi.c -+++ b/drivers/gpu/drm/bridge/nwl-dsi.c -@@ -939,6 +939,40 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge) - drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0); - } - -+static u32 *nwl_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, -+ struct drm_bridge_state *bridge_state, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state, -+ u32 output_fmt, -+ unsigned int *num_input_fmts) -+{ -+ u32 *input_fmts, input_fmt; -+ -+ *num_input_fmts = 0; -+ -+ switch (output_fmt) { -+ /* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */ -+ case MEDIA_BUS_FMT_FIXED: -+ input_fmt = MEDIA_BUS_FMT_RGB888_1X24; -+ break; -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ case MEDIA_BUS_FMT_RGB666_1X18: -+ case MEDIA_BUS_FMT_RGB565_1X16: -+ input_fmt = output_fmt; -+ break; -+ default: -+ return NULL; -+ } -+ -+ input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL); -+ if (!input_fmts) -+ return NULL; -+ input_fmts[0] = input_fmt; -+ *num_input_fmts = 1; -+ -+ return input_fmts; -+} -+ - static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { - .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, -@@ -946,6 +980,7 @@ static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { - .atomic_check = nwl_dsi_bridge_atomic_check, - .atomic_enable = nwl_dsi_bridge_atomic_enable, - .atomic_disable = nwl_dsi_bridge_atomic_disable, -+ .atomic_get_input_bus_fmts = nwl_bridge_atomic_get_input_bus_fmts, - .mode_set = nwl_dsi_bridge_mode_set, - .mode_valid = nwl_dsi_bridge_mode_valid, - .attach = nwl_dsi_bridge_attach, -diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c -index 8e7a124d6c5a3..22bf690910b25 100644 ---- a/drivers/gpu/drm/drm_fb_helper.c -+++ b/drivers/gpu/drm/drm_fb_helper.c -@@ -1743,7 +1743,13 @@ void drm_fb_helper_fill_info(struct fb_info *info, - sizes->fb_width, sizes->fb_height); - - info->par = fb_helper; -- snprintf(info->fix.id, sizeof(info->fix.id), "%s", -+ /* -+ * The DRM drivers fbdev emulation device name can be confusing if the -+ * driver name also has a "drm" suffix on it. Leading to names such as -+ * "simpledrmdrmfb" in /proc/fb. Unfortunately, it's an uAPI and can't -+ * be changed due user-space tools (e.g: pm-utils) matching against it. -+ */ -+ snprintf(info->fix.id, sizeof(info->fix.id), "%sdrmfb", - fb_helper->dev->driver->name); - - } -diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c -index d53388199f34c..9d05674550a4f 100644 ---- a/drivers/gpu/drm/drm_gem_cma_helper.c -+++ b/drivers/gpu/drm/drm_gem_cma_helper.c -@@ -210,8 +210,13 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) - dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map); - drm_prime_gem_destroy(gem_obj, cma_obj->sgt); - } else if (cma_obj->vaddr) { -- dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, -- cma_obj->vaddr, cma_obj->paddr); -+ if (cma_obj->map_noncoherent) -+ dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size, -+ cma_obj->vaddr, cma_obj->paddr, -+ DMA_TO_DEVICE); -+ else -+ dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, -+ cma_obj->vaddr, cma_obj->paddr); - } - - drm_gem_object_release(gem_obj); -diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c -index e1b2ce4921ae7..a950d5db211c5 100644 ---- a/drivers/gpu/drm/drm_panel_orientation_quirks.c -+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c -@@ -109,6 +109,12 @@ static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { - .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, - }; - -+static const struct drm_dmi_panel_orientation_data lcd1280x1920_rightside_up = { -+ .width = 1280, -+ .height = 1920, -+ .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, -+}; -+ - static const struct dmi_system_id orientation_data[] = { - { /* Acer One 10 (S1003) */ - .matches = { -@@ -205,6 +211,13 @@ static const struct dmi_system_id orientation_data[] = { - DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), - }, - .driver_data = (void *)&itworks_tw891, -+ }, { /* KD Kurio Smart C15200 2-in-1 */ -+ .matches = { -+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "KD Interactive"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Kurio Smart"), -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "KDM960BCP"), -+ }, -+ .driver_data = (void *)&lcd800x1280_rightside_up, - }, { /* - * Lenovo Ideapad Miix 310 laptop, only some production batches - * have a portrait screen, the resolution checks makes the quirk -@@ -223,10 +236,15 @@ static const struct dmi_system_id orientation_data[] = { - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), - }, - .driver_data = (void *)&lcd800x1280_rightside_up, -- }, { /* Lenovo Ideapad D330 */ -+ }, { /* Lenovo Ideapad D330-10IGM (HD) */ -+ .matches = { -+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"), -+ }, -+ .driver_data = (void *)&lcd800x1280_rightside_up, -+ }, { /* Lenovo Ideapad D330-10IGM (FHD) */ - .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), -- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81H3"), - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"), - }, - .driver_data = (void *)&lcd1200x1920_rightside_up, -@@ -237,6 +255,19 @@ static const struct dmi_system_id orientation_data[] = { - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"), - }, - .driver_data = (void *)&onegx1_pro, -+ }, { /* Samsung GalaxyBook 10.6 */ -+ .matches = { -+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), -+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"), -+ }, -+ .driver_data = (void *)&lcd1280x1920_rightside_up, -+ }, { /* Valve Steam Deck */ -+ .matches = { -+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"), -+ }, -+ .driver_data = (void *)&lcd800x1280_rightside_up, - }, { /* VIOS LTH17 */ - .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), -diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c -index 5b2d0ca03705c..838b32b70bce6 100644 ---- a/drivers/gpu/drm/drm_plane_helper.c -+++ b/drivers/gpu/drm/drm_plane_helper.c -@@ -123,7 +123,6 @@ static int drm_plane_helper_check_update(struct drm_plane *plane, - .crtc_w = drm_rect_width(dst), - .crtc_h = drm_rect_height(dst), - .rotation = rotation, -- .visible = *visible, - }; - struct drm_crtc_state crtc_state = { - .crtc = crtc, -diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c -index deb23dbec8b52..d6c7f4f9a7a29 100644 ---- a/drivers/gpu/drm/drm_prime.c -+++ b/drivers/gpu/drm/drm_prime.c -@@ -719,11 +719,13 @@ int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) - if (obj->funcs && obj->funcs->mmap) { - vma->vm_ops = obj->funcs->vm_ops; - -+ drm_gem_object_get(obj); - ret = obj->funcs->mmap(obj, vma); -- if (ret) -+ if (ret) { -+ drm_gem_object_put(obj); - return ret; -+ } - vma->vm_private_data = obj; -- drm_gem_object_get(obj); - return 0; - } - -diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c -index c9a9d74f338c1..c313a5b4549c4 100644 ---- a/drivers/gpu/drm/drm_syncobj.c -+++ b/drivers/gpu/drm/drm_syncobj.c -@@ -404,8 +404,17 @@ int drm_syncobj_find_fence(struct drm_file *file_private, - - if (*fence) { - ret = dma_fence_chain_find_seqno(fence, point); -- if (!ret) -+ if (!ret) { -+ /* If the requested seqno is already signaled -+ * drm_syncobj_find_fence may return a NULL -+ * fence. To make sure the recipient gets -+ * signalled, use a new fence instead. -+ */ -+ if (!*fence) -+ *fence = dma_fence_get_stub(); -+ - goto out; -+ } - dma_fence_put(*fence); - } else { - ret = -EINVAL; -diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c -index cd818a6291835..00e53de4812bb 100644 ---- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c -+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c -@@ -225,12 +225,29 @@ static int hyperv_vmbus_remove(struct hv_device *hdev) - { - struct drm_device *dev = hv_get_drvdata(hdev); - struct hyperv_drm_device *hv = to_hv(dev); -+ struct pci_dev *pdev; - - drm_dev_unplug(dev); - drm_atomic_helper_shutdown(dev); - vmbus_close(hdev->channel); - hv_set_drvdata(hdev, NULL); -- vmbus_free_mmio(hv->mem->start, hv->fb_size); -+ -+ /* -+ * Free allocated MMIO memory only on Gen2 VMs. -+ * On Gen1 VMs, release the PCI device -+ */ -+ if (efi_enabled(EFI_BOOT)) { -+ vmbus_free_mmio(hv->mem->start, hv->fb_size); -+ } else { -+ pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, -+ PCI_DEVICE_ID_HYPERV_VIDEO, NULL); -+ if (!pdev) { -+ drm_err(dev, "Unable to find PCI Hyper-V video\n"); -+ return -ENODEV; -+ } -+ pci_release_region(pdev, 0); -+ pci_dev_put(pdev); -+ } - - return 0; - } -diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c -index be352e9f0afc1..63baaf6988ade 100644 ---- a/drivers/gpu/drm/i915/display/g4x_hdmi.c -+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c -@@ -584,6 +584,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, - else - intel_encoder->enable = g4x_enable_hdmi; - } -+ intel_encoder->shutdown = intel_hdmi_encoder_shutdown; - - intel_encoder->type = INTEL_OUTPUT_HDMI; - intel_encoder->power_domain = intel_port_to_power_domain(port); -diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c -index a3eae3f3eadce..638a00b2dc2d2 100644 ---- a/drivers/gpu/drm/i915/display/icl_dsi.c -+++ b/drivers/gpu/drm/i915/display/icl_dsi.c -@@ -711,10 +711,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, - intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); - - for_each_dsi_phy(phy, intel_dsi->phys) { -- if (DISPLAY_VER(dev_priv) >= 12) -- val |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); -- else -- val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); -+ val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); - } - intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); - -@@ -1150,8 +1147,6 @@ static void - gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) - { -- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); -- - /* step 4a: power up all lanes of the DDI used by DSI */ - gen11_dsi_power_up_lanes(encoder); - -@@ -1177,8 +1172,7 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, - gen11_dsi_configure_transcoder(encoder, crtc_state); - - /* Step 4l: Gate DDI clocks */ -- if (DISPLAY_VER(dev_priv) == 11) -- gen11_dsi_gate_clocks(encoder); -+ gen11_dsi_gate_clocks(encoder); - } - - static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) -diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c -index fd71346aac7bc..32d5a556b7eac 100644 ---- a/drivers/gpu/drm/i915/display/intel_bios.c -+++ b/drivers/gpu/drm/i915/display/intel_bios.c -@@ -1692,6 +1692,39 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) - return 0; - } - -+static u8 dvo_port_type(u8 dvo_port) -+{ -+ switch (dvo_port) { -+ case DVO_PORT_HDMIA: -+ case DVO_PORT_HDMIB: -+ case DVO_PORT_HDMIC: -+ case DVO_PORT_HDMID: -+ case DVO_PORT_HDMIE: -+ case DVO_PORT_HDMIF: -+ case DVO_PORT_HDMIG: -+ case DVO_PORT_HDMIH: -+ case DVO_PORT_HDMII: -+ return DVO_PORT_HDMIA; -+ case DVO_PORT_DPA: -+ case DVO_PORT_DPB: -+ case DVO_PORT_DPC: -+ case DVO_PORT_DPD: -+ case DVO_PORT_DPE: -+ case DVO_PORT_DPF: -+ case DVO_PORT_DPG: -+ case DVO_PORT_DPH: -+ case DVO_PORT_DPI: -+ return DVO_PORT_DPA; -+ case DVO_PORT_MIPIA: -+ case DVO_PORT_MIPIB: -+ case DVO_PORT_MIPIC: -+ case DVO_PORT_MIPID: -+ return DVO_PORT_MIPIA; -+ default: -+ return dvo_port; -+ } -+} -+ - static enum port __dvo_port_to_port(int n_ports, int n_dvo, - const int port_mapping[][3], u8 dvo_port) - { -@@ -2622,35 +2655,17 @@ bool intel_bios_is_port_edp(struct drm_i915_private *i915, enum port port) - return false; - } - --static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, -- enum port port) -+static bool child_dev_is_dp_dual_mode(const struct child_device_config *child) - { -- static const struct { -- u16 dp, hdmi; -- } port_mapping[] = { -- /* -- * Buggy VBTs may declare DP ports as having -- * HDMI type dvo_port :( So let's check both. -- */ -- [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, }, -- [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, }, -- [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, -- [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, -- [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, -- }; -- -- if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) -- return false; -- - if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != - (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) - return false; - -- if (child->dvo_port == port_mapping[port].dp) -+ if (dvo_port_type(child->dvo_port) == DVO_PORT_DPA) - return true; - - /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ -- if (child->dvo_port == port_mapping[port].hdmi && -+ if (dvo_port_type(child->dvo_port) == DVO_PORT_HDMIA && - child->aux_channel != 0) - return true; - -@@ -2660,10 +2675,36 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, - bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915, - enum port port) - { -+ static const struct { -+ u16 dp, hdmi; -+ } port_mapping[] = { -+ /* -+ * Buggy VBTs may declare DP ports as having -+ * HDMI type dvo_port :( So let's check both. -+ */ -+ [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, }, -+ [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, }, -+ [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, -+ [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, -+ [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, -+ }; - const struct intel_bios_encoder_data *devdata; - -+ if (HAS_DDI(i915)) { -+ const struct intel_bios_encoder_data *devdata; -+ -+ devdata = intel_bios_encoder_data_lookup(i915, port); -+ -+ return devdata && child_dev_is_dp_dual_mode(&devdata->child); -+ } -+ -+ if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) -+ return false; -+ - list_for_each_entry(devdata, &i915->vbt.display_devices, node) { -- if (child_dev_is_dp_dual_mode(&devdata->child, port)) -+ if ((devdata->child.dvo_port == port_mapping[port].dp || -+ devdata->child.dvo_port == port_mapping[port].hdmi) && -+ child_dev_is_dp_dual_mode(&devdata->child)) - return true; - } - -diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c -index bd184325d0c75..82e5064b4ce7b 100644 ---- a/drivers/gpu/drm/i915/display/intel_ddi.c -+++ b/drivers/gpu/drm/i915/display/intel_ddi.c -@@ -4432,6 +4432,7 @@ static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) - enum phy phy = intel_port_to_phy(i915, encoder->port); - - intel_dp_encoder_shutdown(encoder); -+ intel_hdmi_encoder_shutdown(encoder); - - if (!intel_phy_is_tc(i915, phy)) - return; -diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h -index 6beeeeba1bed2..b56850d964919 100644 ---- a/drivers/gpu/drm/i915/display/intel_display_types.h -+++ b/drivers/gpu/drm/i915/display/intel_display_types.h -@@ -1639,6 +1639,9 @@ struct intel_dp { - struct intel_dp_pcon_frl frl; - - struct intel_psr psr; -+ -+ /* When we last wrote the OUI for eDP */ -+ unsigned long last_oui_write; - }; - - enum lspcon_vendor { -diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c -index b3c8e1c450efb..73076737add75 100644 ---- a/drivers/gpu/drm/i915/display/intel_dmc.c -+++ b/drivers/gpu/drm/i915/display/intel_dmc.c -@@ -606,7 +606,7 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv, - continue; - - offset = readcount + dmc->dmc_info[id].dmc_offset * 4; -- if (fw->size - offset < 0) { -+ if (offset > fw->size) { - drm_err(&dev_priv->drm, "Reading beyond the fw_size\n"); - continue; - } -diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c -index 5cf152be44877..d55363f1fa102 100644 ---- a/drivers/gpu/drm/i915/display/intel_dp.c -+++ b/drivers/gpu/drm/i915/display/intel_dp.c -@@ -29,6 +29,7 @@ - #include <linux/i2c.h> - #include <linux/notifier.h> - #include <linux/slab.h> -+#include <linux/timekeeping.h> - #include <linux/types.h> - - #include <asm/byteorder.h> -@@ -111,6 +112,12 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) - static void intel_dp_unset_edid(struct intel_dp *intel_dp); - static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc); - -+static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp) -+{ -+ intel_dp->sink_rates[0] = 162000; -+ intel_dp->num_sink_rates = 1; -+} -+ - /* update sink rates from dpcd */ - static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) - { -@@ -1767,6 +1774,12 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, - intel_dp->lane_count = lane_count; - } - -+static void intel_dp_reset_max_link_params(struct intel_dp *intel_dp) -+{ -+ intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); -+ intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); -+} -+ - /* Enable backlight PWM and backlight PP control. */ - void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) -@@ -1852,6 +1865,16 @@ intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful) - - if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) - drm_err(&i915->drm, "Failed to write source OUI\n"); -+ -+ intel_dp->last_oui_write = jiffies; -+} -+ -+void intel_dp_wait_source_oui(struct intel_dp *intel_dp) -+{ -+ struct drm_i915_private *i915 = dp_to_i915(intel_dp); -+ -+ drm_dbg_kms(&i915->drm, "Performing OUI wait\n"); -+ wait_remaining_ms_from_jiffies(intel_dp->last_oui_write, 30); - } - - /* If the device supports it, try to set the power state appropriately */ -@@ -1926,8 +1949,7 @@ void intel_dp_sync_state(struct intel_encoder *encoder, - if (intel_dp->dpcd[DP_DPCD_REV] == 0) - intel_dp_get_dpcd(intel_dp); - -- intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); -- intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); -+ intel_dp_reset_max_link_params(intel_dp); - } - - bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, -@@ -2462,6 +2484,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) - */ - intel_psr_init_dpcd(intel_dp); - -+ /* Clear the default sink rates */ -+ intel_dp->num_sink_rates = 0; -+ - /* Read the eDP 1.4+ supported link rates. */ - if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { - __le16 sink_rates[DP_MAX_SUPPORTED_RATES]; -@@ -2497,6 +2522,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) - intel_dp_set_sink_rates(intel_dp); - - intel_dp_set_common_rates(intel_dp); -+ intel_dp_reset_max_link_params(intel_dp); - - /* Read the eDP DSC DPCD registers */ - if (DISPLAY_VER(dev_priv) >= 10) -@@ -4240,12 +4266,7 @@ intel_dp_detect(struct drm_connector *connector, - * supports link training fallback params. - */ - if (intel_dp->reset_link_params || intel_dp->is_mst) { -- /* Initial max link lane count */ -- intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); -- -- /* Initial max link rate */ -- intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); -- -+ intel_dp_reset_max_link_params(intel_dp); - intel_dp->reset_link_params = false; - } - -@@ -5296,6 +5317,9 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, - return false; - - intel_dp_set_source_rates(intel_dp); -+ intel_dp_set_default_sink_rates(intel_dp); -+ intel_dp_set_common_rates(intel_dp); -+ intel_dp_reset_max_link_params(intel_dp); - - intel_dp->reset_link_params = true; - intel_dp->pps.pps_pipe = INVALID_PIPE; -diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h -index 680631b5b4378..2121aaa9b8db0 100644 ---- a/drivers/gpu/drm/i915/display/intel_dp.h -+++ b/drivers/gpu/drm/i915/display/intel_dp.h -@@ -129,4 +129,6 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); - void intel_dp_phy_test(struct intel_encoder *encoder); - -+void intel_dp_wait_source_oui(struct intel_dp *intel_dp); -+ - #endif /* __INTEL_DP_H__ */ -diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c -index 6ac568617ef37..c82f8febe7303 100644 ---- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c -+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c -@@ -35,6 +35,7 @@ - */ - - #include "intel_display_types.h" -+#include "intel_dp.h" - #include "intel_dp_aux_backlight.h" - #include "intel_panel.h" - -@@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) - int ret; - u8 tcon_cap[4]; - -+ intel_dp_wait_source_oui(intel_dp); -+ - ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); - if (ret != sizeof(tcon_cap)) - return false; -@@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, - int ret; - u8 old_ctrl, ctrl; - -+ intel_dp_wait_source_oui(intel_dp); -+ - ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); - if (ret != 1) { - drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret); -diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c -index c60a81a81c09c..c6413c5409420 100644 ---- a/drivers/gpu/drm/i915/display/intel_fb.c -+++ b/drivers/gpu/drm/i915/display/intel_fb.c -@@ -172,8 +172,9 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl - - intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane); - intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane); -- *w = fb->base.width / main_hsub / hsub; -- *h = fb->base.height / main_vsub / vsub; -+ -+ *w = DIV_ROUND_UP(fb->base.width, main_hsub * hsub); -+ *h = DIV_ROUND_UP(fb->base.height, main_vsub * vsub); - } - - static u32 intel_adjust_tile_offset(int *x, int *y, -diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c -index b04685bb6439c..c3787512295dd 100644 ---- a/drivers/gpu/drm/i915/display/intel_hdmi.c -+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c -@@ -53,21 +53,20 @@ - #include "intel_panel.h" - #include "intel_snps_phy.h" - --static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi) -+static struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi *intel_hdmi) - { -- return hdmi_to_dig_port(intel_hdmi)->base.base.dev; -+ return to_i915(hdmi_to_dig_port(intel_hdmi)->base.base.dev); - } - - static void - assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) - { -- struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi); -- struct drm_i915_private *dev_priv = to_i915(dev); -+ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(intel_hdmi); - u32 enabled_bits; - - enabled_bits = HAS_DDI(dev_priv) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; - -- drm_WARN(dev, -+ drm_WARN(&dev_priv->drm, - intel_de_read(dev_priv, intel_hdmi->hdmi_reg) & enabled_bits, - "HDMI port enabled, expecting disabled\n"); - } -@@ -1246,13 +1245,14 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, - - void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) - { -- struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); -- struct i2c_adapter *adapter = -- intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); -+ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); -+ struct i2c_adapter *adapter; - - if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) - return; - -+ adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); -+ - drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n", - enable ? "Enabling" : "Disabling"); - -@@ -1830,7 +1830,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, - int clock, bool respect_downstream_limits, - bool has_hdmi_sink) - { -- struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); -+ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); - - if (clock < 25000) - return MODE_CLOCK_LOW; -@@ -1946,8 +1946,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { - struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); -- struct drm_device *dev = intel_hdmi_to_dev(hdmi); -- struct drm_i915_private *dev_priv = to_i915(dev); -+ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); - enum drm_mode_status status; - int clock = mode->clock; - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; -@@ -2260,6 +2259,17 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, - return 0; - } - -+void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder) -+{ -+ struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); -+ -+ /* -+ * Give a hand to buggy BIOSen which forget to turn -+ * the TMDS output buffers back on after a reboot. -+ */ -+ intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); -+} -+ - static void - intel_hdmi_unset_edid(struct drm_connector *connector) - { -diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h -index b43a180d007e0..2bf440eb400ab 100644 ---- a/drivers/gpu/drm/i915/display/intel_hdmi.h -+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h -@@ -28,6 +28,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, - int intel_hdmi_compute_config(struct intel_encoder *encoder, - struct intel_crtc_state *pipe_config, - struct drm_connector_state *conn_state); -+void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder); - bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, - struct drm_connector *connector, - bool high_tmds_clock_ratio, -diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -index de5f9c86b9a44..cafb0608ffb46 100644 ---- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -@@ -2140,10 +2140,6 @@ static void __execlists_unhold(struct i915_request *rq) - if (p->flags & I915_DEPENDENCY_WEAK) - continue; - -- /* Propagate any change in error status */ -- if (rq->fence.error) -- i915_request_set_error_once(w, rq->fence.error); -- - if (w->engine != rq->engine) - continue; - -diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c -index aae609d7d85dd..6b5ab19a2ada9 100644 ---- a/drivers/gpu/drm/i915/gt/intel_workarounds.c -+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c -@@ -621,13 +621,6 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, - FF_MODE2_GS_TIMER_MASK, - FF_MODE2_GS_TIMER_224, - 0, false); -- -- /* -- * Wa_14012131227:dg1 -- * Wa_1508744258:tgl,rkl,dg1,adl-s,adl-p -- */ -- wa_masked_en(wal, GEN7_COMMON_SLICE_CHICKEN1, -- GEN9_RHWO_OPTIMIZATION_DISABLE); - } - - static void dg1_ctx_workarounds_init(struct intel_engine_cs *engine, -diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c -index 87d8dc8f51b96..93c9de8f43e8e 100644 ---- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c -+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c -@@ -148,11 +148,12 @@ static inline void clr_context_registered(struct intel_context *ce) - #define SCHED_STATE_BLOCKED_SHIFT 4 - #define SCHED_STATE_BLOCKED BIT(SCHED_STATE_BLOCKED_SHIFT) - #define SCHED_STATE_BLOCKED_MASK (0xfff << SCHED_STATE_BLOCKED_SHIFT) -+ - static inline void init_sched_state(struct intel_context *ce) - { - /* Only should be called from guc_lrc_desc_pin() */ - atomic_set(&ce->guc_sched_state_no_lock, 0); -- ce->guc_state.sched_state = 0; -+ ce->guc_state.sched_state &= SCHED_STATE_BLOCKED_MASK; - } - - static inline bool -@@ -352,20 +353,29 @@ static inline void set_lrc_desc_registered(struct intel_guc *guc, u32 id, - xa_unlock_irqrestore(&guc->context_lookup, flags); - } - -+static void decr_outstanding_submission_g2h(struct intel_guc *guc) -+{ -+ if (atomic_dec_and_test(&guc->outstanding_submission_g2h)) -+ wake_up_all(&guc->ct.wq); -+} -+ - static int guc_submission_send_busy_loop(struct intel_guc *guc, - const u32 *action, - u32 len, - u32 g2h_len_dw, - bool loop) - { -- int err; -- -- err = intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); -+ /* -+ * We always loop when a send requires a reply (i.e. g2h_len_dw > 0), -+ * so we don't handle the case where we don't get a reply because we -+ * aborted the send due to the channel being busy. -+ */ -+ GEM_BUG_ON(g2h_len_dw && !loop); - -- if (!err && g2h_len_dw) -+ if (g2h_len_dw) - atomic_inc(&guc->outstanding_submission_g2h); - -- return err; -+ return intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); - } - - int intel_guc_wait_for_pending_msg(struct intel_guc *guc, -@@ -616,7 +626,7 @@ static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc) - init_sched_state(ce); - - if (pending_enable || destroyed || deregister) { -- atomic_dec(&guc->outstanding_submission_g2h); -+ decr_outstanding_submission_g2h(guc); - if (deregister) - guc_signal_context_fence(ce); - if (destroyed) { -@@ -635,7 +645,7 @@ static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc) - intel_engine_signal_breadcrumbs(ce->engine); - } - intel_context_sched_disable_unpin(ce); -- atomic_dec(&guc->outstanding_submission_g2h); -+ decr_outstanding_submission_g2h(guc); - spin_lock_irqsave(&ce->guc_state.lock, flags); - guc_blocked_fence_complete(ce); - spin_unlock_irqrestore(&ce->guc_state.lock, flags); -@@ -797,15 +807,13 @@ __unwind_incomplete_requests(struct intel_context *ce) - - spin_lock_irqsave(&sched_engine->lock, flags); - spin_lock(&ce->guc_active.lock); -- list_for_each_entry_safe(rq, rn, -- &ce->guc_active.requests, -- sched.link) { -+ list_for_each_entry_safe_reverse(rq, rn, -+ &ce->guc_active.requests, -+ sched.link) { - if (i915_request_completed(rq)) - continue; - - list_del_init(&rq->sched.link); -- spin_unlock(&ce->guc_active.lock); -- - __i915_request_unsubmit(rq); - - /* Push the request back into the queue for later resubmission. */ -@@ -816,10 +824,8 @@ __unwind_incomplete_requests(struct intel_context *ce) - } - GEM_BUG_ON(i915_sched_engine_is_empty(sched_engine)); - -- list_add_tail(&rq->sched.link, pl); -+ list_add(&rq->sched.link, pl); - set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags); -- -- spin_lock(&ce->guc_active.lock); - } - spin_unlock(&ce->guc_active.lock); - spin_unlock_irqrestore(&sched_engine->lock, flags); -@@ -828,17 +834,33 @@ __unwind_incomplete_requests(struct intel_context *ce) - static void __guc_reset_context(struct intel_context *ce, bool stalled) - { - struct i915_request *rq; -+ unsigned long flags; - u32 head; -+ bool skip = false; - - intel_context_get(ce); - - /* -- * GuC will implicitly mark the context as non-schedulable -- * when it sends the reset notification. Make sure our state -- * reflects this change. The context will be marked enabled -- * on resubmission. -+ * GuC will implicitly mark the context as non-schedulable when it sends -+ * the reset notification. Make sure our state reflects this change. The -+ * context will be marked enabled on resubmission. -+ * -+ * XXX: If the context is reset as a result of the request cancellation -+ * this G2H is received after the schedule disable complete G2H which is -+ * wrong as this creates a race between the request cancellation code -+ * re-submitting the context and this G2H handler. This is a bug in the -+ * GuC but can be worked around in the meantime but converting this to a -+ * NOP if a pending enable is in flight as this indicates that a request -+ * cancellation has occurred. - */ -- clr_context_enabled(ce); -+ spin_lock_irqsave(&ce->guc_state.lock, flags); -+ if (likely(!context_pending_enable(ce))) -+ clr_context_enabled(ce); -+ else -+ skip = true; -+ spin_unlock_irqrestore(&ce->guc_state.lock, flags); -+ if (unlikely(skip)) -+ goto out_put; - - rq = intel_context_find_active_request(ce); - if (!rq) { -@@ -857,6 +879,7 @@ static void __guc_reset_context(struct intel_context *ce, bool stalled) - out_replay: - guc_reset_state(ce, head, stalled); - __unwind_incomplete_requests(ce); -+out_put: - intel_context_put(ce); - } - -@@ -1233,8 +1256,7 @@ static int register_context(struct intel_context *ce, bool loop) - } - - static int __guc_action_deregister_context(struct intel_guc *guc, -- u32 guc_id, -- bool loop) -+ u32 guc_id) - { - u32 action[] = { - INTEL_GUC_ACTION_DEREGISTER_CONTEXT, -@@ -1243,16 +1265,16 @@ static int __guc_action_deregister_context(struct intel_guc *guc, - - return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), - G2H_LEN_DW_DEREGISTER_CONTEXT, -- loop); -+ true); - } - --static int deregister_context(struct intel_context *ce, u32 guc_id, bool loop) -+static int deregister_context(struct intel_context *ce, u32 guc_id) - { - struct intel_guc *guc = ce_to_guc(ce); - - trace_intel_context_deregister(ce); - -- return __guc_action_deregister_context(guc, guc_id, loop); -+ return __guc_action_deregister_context(guc, guc_id); - } - - static intel_engine_mask_t adjust_engine_mask(u8 class, intel_engine_mask_t mask) -@@ -1340,26 +1362,23 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) - * registering this context. - */ - if (context_registered) { -+ bool disabled; -+ unsigned long flags; -+ - trace_intel_context_steal_guc_id(ce); -- if (!loop) { -+ GEM_BUG_ON(!loop); -+ -+ /* Seal race with Reset */ -+ spin_lock_irqsave(&ce->guc_state.lock, flags); -+ disabled = submission_disabled(guc); -+ if (likely(!disabled)) { - set_context_wait_for_deregister_to_register(ce); - intel_context_get(ce); -- } else { -- bool disabled; -- unsigned long flags; -- -- /* Seal race with Reset */ -- spin_lock_irqsave(&ce->guc_state.lock, flags); -- disabled = submission_disabled(guc); -- if (likely(!disabled)) { -- set_context_wait_for_deregister_to_register(ce); -- intel_context_get(ce); -- } -- spin_unlock_irqrestore(&ce->guc_state.lock, flags); -- if (unlikely(disabled)) { -- reset_lrc_desc(guc, desc_idx); -- return 0; /* Will get registered later */ -- } -+ } -+ spin_unlock_irqrestore(&ce->guc_state.lock, flags); -+ if (unlikely(disabled)) { -+ reset_lrc_desc(guc, desc_idx); -+ return 0; /* Will get registered later */ - } - - /* -@@ -1367,13 +1386,9 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) - * context whose guc_id was stolen. - */ - with_intel_runtime_pm(runtime_pm, wakeref) -- ret = deregister_context(ce, ce->guc_id, loop); -- if (unlikely(ret == -EBUSY)) { -- clr_context_wait_for_deregister_to_register(ce); -- intel_context_put(ce); -- } else if (unlikely(ret == -ENODEV)) { -+ ret = deregister_context(ce, ce->guc_id); -+ if (unlikely(ret == -ENODEV)) - ret = 0; /* Will get registered later */ -- } - } else { - with_intel_runtime_pm(runtime_pm, wakeref) - ret = register_context(ce, loop); -@@ -1548,6 +1563,23 @@ static struct i915_sw_fence *guc_context_block(struct intel_context *ce) - return &ce->guc_blocked; - } - -+#define SCHED_STATE_MULTI_BLOCKED_MASK \ -+ (SCHED_STATE_BLOCKED_MASK & ~SCHED_STATE_BLOCKED) -+#define SCHED_STATE_NO_UNBLOCK \ -+ (SCHED_STATE_MULTI_BLOCKED_MASK | \ -+ SCHED_STATE_PENDING_DISABLE | \ -+ SCHED_STATE_BANNED) -+ -+static bool context_cant_unblock(struct intel_context *ce) -+{ -+ lockdep_assert_held(&ce->guc_state.lock); -+ -+ return (ce->guc_state.sched_state & SCHED_STATE_NO_UNBLOCK) || -+ context_guc_id_invalid(ce) || -+ !lrc_desc_registered(ce_to_guc(ce), ce->guc_id) || -+ !intel_context_is_pinned(ce); -+} -+ - static void guc_context_unblock(struct intel_context *ce) - { - struct intel_guc *guc = ce_to_guc(ce); -@@ -1562,9 +1594,7 @@ static void guc_context_unblock(struct intel_context *ce) - spin_lock_irqsave(&ce->guc_state.lock, flags); - - if (unlikely(submission_disabled(guc) || -- !intel_context_is_pinned(ce) || -- context_pending_disable(ce) || -- context_blocked(ce) > 1)) { -+ context_cant_unblock(ce))) { - enable = false; - } else { - enable = true; -@@ -1601,6 +1631,13 @@ static void guc_context_cancel_request(struct intel_context *ce, - guc_reset_state(ce, intel_ring_wrap(ce->ring, rq->head), - true); - } -+ -+ /* -+ * XXX: Racey if context is reset, see comment in -+ * __guc_reset_context(). -+ */ -+ flush_work(&ce_to_guc(ce)->ct.requests.worker); -+ - guc_context_unblock(ce); - } - } -@@ -1730,7 +1767,7 @@ static inline void guc_lrc_desc_unpin(struct intel_context *ce) - GEM_BUG_ON(context_enabled(ce)); - - clr_context_registered(ce); -- deregister_context(ce, ce->guc_id, true); -+ deregister_context(ce, ce->guc_id); - } - - static void __guc_context_destroy(struct intel_context *ce) -@@ -2583,12 +2620,6 @@ g2h_context_lookup(struct intel_guc *guc, u32 desc_idx) - return ce; - } - --static void decr_outstanding_submission_g2h(struct intel_guc *guc) --{ -- if (atomic_dec_and_test(&guc->outstanding_submission_g2h)) -- wake_up_all(&guc->ct.wq); --} -- - int intel_guc_deregister_done_process_msg(struct intel_guc *guc, - const u32 *msg, - u32 len) -@@ -2721,7 +2752,12 @@ static void guc_handle_context_reset(struct intel_guc *guc, - { - trace_intel_context_reset(ce); - -- if (likely(!intel_context_is_banned(ce))) { -+ /* -+ * XXX: Racey if request cancellation has occurred, see comment in -+ * __guc_reset_context(). -+ */ -+ if (likely(!intel_context_is_banned(ce) && -+ !context_blocked(ce))) { - capture_error_state(guc, ce); - guc_context_replay(ce); - } -diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c -index 9558e9e1b431b..cb685fe2039b4 100644 ---- a/drivers/gpu/drm/imx/imx-drm-core.c -+++ b/drivers/gpu/drm/imx/imx-drm-core.c -@@ -81,7 +81,6 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) - struct drm_plane_state *old_plane_state, *new_plane_state; - bool plane_disabling = false; - int i; -- bool fence_cookie = dma_fence_begin_signalling(); - - drm_atomic_helper_commit_modeset_disables(dev, state); - -@@ -112,7 +111,6 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) - } - - drm_atomic_helper_commit_hw_done(state); -- dma_fence_end_signalling(fence_cookie); - } - - static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { -diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c -index 8b73f70766a47..4347a104755a9 100644 ---- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c -+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c -@@ -516,11 +516,11 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) - struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; - struct platform_device *pdev = to_platform_device(gmu->dev); - void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc"); -- void __iomem *seqptr; -+ void __iomem *seqptr = NULL; - uint32_t pdc_address_offset; - bool pdc_in_aop = false; - -- if (!pdcptr) -+ if (IS_ERR(pdcptr)) - goto err; - - if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu)) -@@ -532,7 +532,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) - - if (!pdc_in_aop) { - seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq"); -- if (!seqptr) -+ if (IS_ERR(seqptr)) - goto err; - } - -diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c -index 267a880811d65..723074aae5b63 100644 ---- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c -+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c -@@ -1424,17 +1424,24 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) - { - struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; - struct msm_gpu *gpu = &adreno_gpu->base; -- u32 gpu_scid, cntl1_regval = 0; -+ u32 cntl1_regval = 0; - - if (IS_ERR(a6xx_gpu->llc_mmio)) - return; - - if (!llcc_slice_activate(a6xx_gpu->llc_slice)) { -- gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); -+ u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); - - gpu_scid &= 0x1f; - cntl1_regval = (gpu_scid << 0) | (gpu_scid << 5) | (gpu_scid << 10) | - (gpu_scid << 15) | (gpu_scid << 20); -+ -+ /* On A660, the SCID programming for UCHE traffic is done in -+ * A6XX_GBIF_SCACHE_CNTL0[14:10] -+ */ -+ if (adreno_is_a660_family(adreno_gpu)) -+ gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | -+ (1 << 8), (gpu_scid << 10) | (1 << 8)); - } - - /* -@@ -1471,13 +1478,6 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) - } - - gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval); -- -- /* On A660, the SCID programming for UCHE traffic is done in -- * A6XX_GBIF_SCACHE_CNTL0[14:10] -- */ -- if (adreno_is_a660_family(adreno_gpu)) -- gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | -- (1 << 8), (gpu_scid << 10) | (1 << 8)); - } - - static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) -diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c -index e8f65cd8eca6e..bfac7e47cb396 100644 ---- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c -+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c -@@ -777,12 +777,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, - struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); - - a6xx_state->gmu_registers = state_kcalloc(a6xx_state, -- 2, sizeof(*a6xx_state->gmu_registers)); -+ 3, sizeof(*a6xx_state->gmu_registers)); - - if (!a6xx_state->gmu_registers) - return; - -- a6xx_state->nr_gmu_registers = 2; -+ a6xx_state->nr_gmu_registers = 3; - - /* Get the CX GMU registers from AHB */ - _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], -diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c -index 69eed79324865..f9460672176aa 100644 ---- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c -+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c -@@ -138,11 +138,13 @@ static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx, - u32 *idx) - { - int rc = 0; -- const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk; -+ const struct dpu_sspp_sub_blks *sblk; - -- if (!ctx) -+ if (!ctx || !ctx->cap || !ctx->cap->sblk) - return -EINVAL; - -+ sblk = ctx->cap->sblk; -+ - switch (s_id) { - case DPU_SSPP_SRC: - *idx = sblk->src_blk.base; -@@ -419,7 +421,7 @@ static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx, - - (void)pe; - if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp -- || !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk) -+ || !scaler3_cfg) - return; - - dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx, -diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c -index ae48f41821cfe..ad247c06e198f 100644 ---- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c -+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c -@@ -908,6 +908,10 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) - return 0; - - mmu = msm_iommu_new(dpu_kms->dev->dev, domain); -+ if (IS_ERR(mmu)) { -+ iommu_domain_free(domain); -+ return PTR_ERR(mmu); -+ } - aspace = msm_gem_address_space_create(mmu, "dpu1", - 0x1000, 0x100000000 - 0x1000); - -diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c -index eb40d8413bca9..6d36f63c33388 100644 ---- a/drivers/gpu/drm/msm/dp/dp_aux.c -+++ b/drivers/gpu/drm/msm/dp/dp_aux.c -@@ -33,6 +33,7 @@ struct dp_aux_private { - bool read; - bool no_send_addr; - bool no_send_stop; -+ bool initted; - u32 offset; - u32 segment; - -@@ -331,6 +332,10 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, - } - - mutex_lock(&aux->mutex); -+ if (!aux->initted) { -+ ret = -EIO; -+ goto exit; -+ } - - dp_aux_update_offset_and_segment(aux, msg); - dp_aux_transfer_helper(aux, msg, true); -@@ -380,6 +385,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, - } - - aux->cmd_busy = false; -+ -+exit: - mutex_unlock(&aux->mutex); - - return ret; -@@ -431,8 +438,13 @@ void dp_aux_init(struct drm_dp_aux *dp_aux) - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - -+ mutex_lock(&aux->mutex); -+ - dp_catalog_aux_enable(aux->catalog, true); - aux->retry_cnt = 0; -+ aux->initted = true; -+ -+ mutex_unlock(&aux->mutex); - } - - void dp_aux_deinit(struct drm_dp_aux *dp_aux) -@@ -441,7 +453,12 @@ void dp_aux_deinit(struct drm_dp_aux *dp_aux) - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - -+ mutex_lock(&aux->mutex); -+ -+ aux->initted = false; - dp_catalog_aux_enable(aux->catalog, false); -+ -+ mutex_unlock(&aux->mutex); - } - - int dp_aux_register(struct drm_dp_aux *dp_aux) -diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h -index b50db91cb8a7e..569c8ff062ba4 100644 ---- a/drivers/gpu/drm/msm/dsi/dsi.h -+++ b/drivers/gpu/drm/msm/dsi/dsi.h -@@ -107,6 +107,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, - u32 dma_base, u32 len); - int msm_dsi_host_enable(struct mipi_dsi_host *host); - int msm_dsi_host_disable(struct mipi_dsi_host *host); -+void msm_dsi_host_enable_irq(struct mipi_dsi_host *host); -+void msm_dsi_host_disable_irq(struct mipi_dsi_host *host); - int msm_dsi_host_power_on(struct mipi_dsi_host *host, - struct msm_dsi_phy_shared_timings *phy_shared_timings, - bool is_bonded_dsi, struct msm_dsi_phy *phy); -diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c -index c86b5090fae60..dc85974c78975 100644 ---- a/drivers/gpu/drm/msm/dsi/dsi_host.c -+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c -@@ -115,16 +115,16 @@ struct msm_dsi_host { - struct clk *pixel_clk_src; - struct clk *byte_intf_clk; - -- u32 byte_clk_rate; -- u32 pixel_clk_rate; -- u32 esc_clk_rate; -+ unsigned long byte_clk_rate; -+ unsigned long pixel_clk_rate; -+ unsigned long esc_clk_rate; - - /* DSI v2 specific clocks */ - struct clk *src_clk; - struct clk *esc_clk_src; - struct clk *dsi_clk_src; - -- u32 src_clk_rate; -+ unsigned long src_clk_rate; - - struct gpio_desc *disp_en_gpio; - struct gpio_desc *te_gpio; -@@ -498,10 +498,10 @@ int msm_dsi_runtime_resume(struct device *dev) - - int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) - { -- u32 byte_intf_rate; -+ unsigned long byte_intf_rate; - int ret; - -- DBG("Set clk rates: pclk=%d, byteclk=%d", -+ DBG("Set clk rates: pclk=%d, byteclk=%lu", - msm_host->mode->clock, msm_host->byte_clk_rate); - - ret = dev_pm_opp_set_rate(&msm_host->pdev->dev, -@@ -583,7 +583,7 @@ int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host) - { - int ret; - -- DBG("Set clk rates: pclk=%d, byteclk=%d, esc_clk=%d, dsi_src_clk=%d", -+ DBG("Set clk rates: pclk=%d, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", - msm_host->mode->clock, msm_host->byte_clk_rate, - msm_host->esc_clk_rate, msm_host->src_clk_rate); - -@@ -673,10 +673,10 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) - clk_disable_unprepare(msm_host->byte_clk); - } - --static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bonded_dsi) -+static unsigned long dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bonded_dsi) - { - struct drm_display_mode *mode = msm_host->mode; -- u32 pclk_rate; -+ unsigned long pclk_rate; - - pclk_rate = mode->clock * 1000; - -@@ -696,7 +696,7 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) - { - u8 lanes = msm_host->lanes; - u32 bpp = dsi_get_bpp(msm_host->format); -- u32 pclk_rate = dsi_get_pclk_rate(msm_host, is_bonded_dsi); -+ unsigned long pclk_rate = dsi_get_pclk_rate(msm_host, is_bonded_dsi); - u64 pclk_bpp = (u64)pclk_rate * bpp; - - if (lanes == 0) { -@@ -713,7 +713,7 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) - msm_host->pixel_clk_rate = pclk_rate; - msm_host->byte_clk_rate = pclk_bpp; - -- DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, -+ DBG("pclk=%lu, bclk=%lu", msm_host->pixel_clk_rate, - msm_host->byte_clk_rate); - - } -@@ -772,7 +772,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi) - - msm_host->esc_clk_rate = msm_host->byte_clk_rate / esc_div; - -- DBG("esc=%d, src=%d", msm_host->esc_clk_rate, -+ DBG("esc=%lu, src=%lu", msm_host->esc_clk_rate, - msm_host->src_clk_rate); - - return 0; -@@ -1696,6 +1696,8 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, - if (!prop) { - DRM_DEV_DEBUG(dev, - "failed to find data lane mapping, using default\n"); -+ /* Set the number of date lanes to 4 by default. */ -+ msm_host->num_data_lanes = 4; - return 0; - } - -@@ -1898,6 +1900,23 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) - return ret; - } - -+ msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); -+ if (msm_host->irq < 0) { -+ ret = msm_host->irq; -+ dev_err(&pdev->dev, "failed to get irq: %d\n", ret); -+ return ret; -+ } -+ -+ /* do not autoenable, will be enabled later */ -+ ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, -+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, -+ "dsi_isr", msm_host); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", -+ msm_host->irq, ret); -+ return ret; -+ } -+ - init_completion(&msm_host->dma_comp); - init_completion(&msm_host->video_comp); - mutex_init(&msm_host->dev_mutex); -@@ -1941,25 +1960,8 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, - { - struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; -- struct platform_device *pdev = msm_host->pdev; - int ret; - -- msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); -- if (msm_host->irq < 0) { -- ret = msm_host->irq; -- DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret); -- return ret; -- } -- -- ret = devm_request_irq(&pdev->dev, msm_host->irq, -- dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, -- "dsi_isr", msm_host); -- if (ret < 0) { -- DRM_DEV_ERROR(&pdev->dev, "failed to request IRQ%u: %d\n", -- msm_host->irq, ret); -- return ret; -- } -- - msm_host->dev = dev; - ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); - if (ret) { -@@ -2315,6 +2317,20 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, - clk_req->escclk_rate = msm_host->esc_clk_rate; - } - -+void msm_dsi_host_enable_irq(struct mipi_dsi_host *host) -+{ -+ struct msm_dsi_host *msm_host = to_msm_dsi_host(host); -+ -+ enable_irq(msm_host->irq); -+} -+ -+void msm_dsi_host_disable_irq(struct mipi_dsi_host *host) -+{ -+ struct msm_dsi_host *msm_host = to_msm_dsi_host(host); -+ -+ disable_irq(msm_host->irq); -+} -+ - int msm_dsi_host_enable(struct mipi_dsi_host *host) - { - struct msm_dsi_host *msm_host = to_msm_dsi_host(host); -diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c -index c41d39f5b7cf4..fb4ccffdcfe13 100644 ---- a/drivers/gpu/drm/msm/dsi/dsi_manager.c -+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c -@@ -377,6 +377,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) - } - } - -+ /* -+ * Enable before preparing the panel, disable after unpreparing, so -+ * that the panel can communicate over the DSI link. -+ */ -+ msm_dsi_host_enable_irq(host); -+ if (is_bonded_dsi && msm_dsi1) -+ msm_dsi_host_enable_irq(msm_dsi1->host); -+ - /* Always call panel functions once, because even for dual panels, - * there is only one drm_panel instance. - */ -@@ -411,6 +419,10 @@ host_en_fail: - if (panel) - drm_panel_unprepare(panel); - panel_prep_fail: -+ msm_dsi_host_disable_irq(host); -+ if (is_bonded_dsi && msm_dsi1) -+ msm_dsi_host_disable_irq(msm_dsi1->host); -+ - if (is_bonded_dsi && msm_dsi1) - msm_dsi_host_power_off(msm_dsi1->host); - host1_on_fail: -@@ -523,6 +535,10 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) - id, ret); - } - -+ msm_dsi_host_disable_irq(host); -+ if (is_bonded_dsi && msm_dsi1) -+ msm_dsi_host_disable_irq(msm_dsi1->host); -+ - /* Save PHY status if it is a clock source */ - msm_dsi_phy_pll_save_state(msm_dsi->phy); - -diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c -index 09d2d279c30ae..dee13fedee3b5 100644 ---- a/drivers/gpu/drm/msm/msm_debugfs.c -+++ b/drivers/gpu/drm/msm/msm_debugfs.c -@@ -77,6 +77,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file) - goto free_priv; - - pm_runtime_get_sync(&gpu->pdev->dev); -+ msm_gpu_hw_init(gpu); - show_priv->state = gpu->funcs->gpu_state_get(gpu); - pm_runtime_put_sync(&gpu->pdev->dev); - -diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c -index d4e09703a87db..27f737a253c77 100644 ---- a/drivers/gpu/drm/msm/msm_drv.c -+++ b/drivers/gpu/drm/msm/msm_drv.c -@@ -938,29 +938,18 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, - return ret; - } - --static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, -- struct drm_file *file) -+static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, -+ ktime_t timeout) - { -- struct msm_drm_private *priv = dev->dev_private; -- struct drm_msm_wait_fence *args = data; -- ktime_t timeout = to_ktime(args->timeout); -- struct msm_gpu_submitqueue *queue; -- struct msm_gpu *gpu = priv->gpu; - struct dma_fence *fence; - int ret; - -- if (args->pad) { -- DRM_ERROR("invalid pad: %08x\n", args->pad); -+ if (fence_id > queue->last_fence) { -+ DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n", -+ fence_id, queue->last_fence); - return -EINVAL; - } - -- if (!gpu) -- return 0; -- -- queue = msm_submitqueue_get(file->driver_priv, args->queueid); -- if (!queue) -- return -ENOENT; -- - /* - * Map submitqueue scoped "seqno" (which is actually an idr key) - * back to underlying dma-fence -@@ -972,7 +961,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, - ret = mutex_lock_interruptible(&queue->lock); - if (ret) - return ret; -- fence = idr_find(&queue->fence_idr, args->fence); -+ fence = idr_find(&queue->fence_idr, fence_id); - if (fence) - fence = dma_fence_get_rcu(fence); - mutex_unlock(&queue->lock); -@@ -988,6 +977,32 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, - } - - dma_fence_put(fence); -+ -+ return ret; -+} -+ -+static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, -+ struct drm_file *file) -+{ -+ struct msm_drm_private *priv = dev->dev_private; -+ struct drm_msm_wait_fence *args = data; -+ struct msm_gpu_submitqueue *queue; -+ int ret; -+ -+ if (args->pad) { -+ DRM_ERROR("invalid pad: %08x\n", args->pad); -+ return -EINVAL; -+ } -+ -+ if (!priv->gpu) -+ return 0; -+ -+ queue = msm_submitqueue_get(file->driver_priv, args->queueid); -+ if (!queue) -+ return -ENOENT; -+ -+ ret = wait_fence(queue, args->fence, to_ktime(args->timeout)); -+ - msm_submitqueue_put(queue); - - return ret; -diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c -index 22308a1b66fc3..cb52ac01e5122 100644 ---- a/drivers/gpu/drm/msm/msm_gem.c -+++ b/drivers/gpu/drm/msm/msm_gem.c -@@ -1055,8 +1055,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct - { - struct msm_gem_object *msm_obj = to_msm_bo(obj); - -- vma->vm_flags &= ~VM_PFNMAP; -- vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND; -+ vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP; - vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags)); - - return 0; -@@ -1132,6 +1131,7 @@ static int msm_gem_new_impl(struct drm_device *dev, - msm_obj->flags = flags; - msm_obj->madv = MSM_MADV_WILLNEED; - -+ INIT_LIST_HEAD(&msm_obj->node); - INIT_LIST_HEAD(&msm_obj->vmas); - - *obj = &msm_obj->base; -@@ -1166,7 +1166,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32 - - ret = msm_gem_new_impl(dev, size, flags, &obj); - if (ret) -- goto fail; -+ return ERR_PTR(ret); - - msm_obj = to_msm_bo(obj); - -@@ -1250,7 +1250,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, - - ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); - if (ret) -- goto fail; -+ return ERR_PTR(ret); - - drm_gem_private_object_init(dev, obj, size); - -diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c -index 151d19e4453cd..d9aef97eb93ad 100644 ---- a/drivers/gpu/drm/msm/msm_gem_submit.c -+++ b/drivers/gpu/drm/msm/msm_gem_submit.c -@@ -780,6 +780,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, - args->nr_cmds); - if (IS_ERR(submit)) { - ret = PTR_ERR(submit); -+ submit = NULL; - goto out_unlock; - } - -@@ -911,6 +912,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, - drm_sched_entity_push_job(&submit->base, queue->entity); - - args->fence = submit->fence_id; -+ queue->last_fence = submit->fence_id; - - msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs); - msm_process_post_deps(post_deps, args->nr_out_syncobjs, -diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c -index 8a3a592da3a4d..2c46cd968ac4c 100644 ---- a/drivers/gpu/drm/msm/msm_gpu.c -+++ b/drivers/gpu/drm/msm/msm_gpu.c -@@ -296,7 +296,7 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, - state->bos = kcalloc(nr, - sizeof(struct msm_gpu_state_bo), GFP_KERNEL); - -- for (i = 0; i < submit->nr_bos; i++) { -+ for (i = 0; state->bos && i < submit->nr_bos; i++) { - if (should_dump(submit, i)) { - msm_gpu_crashstate_get_bo(state, submit->bos[i].obj, - submit->bos[i].iova, submit->bos[i].flags); -diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h -index ee25d556c8a10..2e2424066e701 100644 ---- a/drivers/gpu/drm/msm/msm_gpu.h -+++ b/drivers/gpu/drm/msm/msm_gpu.h -@@ -352,6 +352,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, - * @ring_nr: the ringbuffer used by this submitqueue, which is determined - * by the submitqueue's priority - * @faults: the number of GPU hangs associated with this submitqueue -+ * @last_fence: the sequence number of the last allocated fence (for error -+ * checking) - * @ctx: the per-drm_file context associated with the submitqueue (ie. - * which set of pgtables do submits jobs associated with the - * submitqueue use) -@@ -367,6 +369,7 @@ struct msm_gpu_submitqueue { - u32 flags; - u32 ring_nr; - int faults; -+ uint32_t last_fence; - struct msm_file_private *ctx; - struct list_head node; - struct idr fence_idr; -diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c -index 20006d060b5b5..4ac2a4eb984d8 100644 ---- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c -+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c -@@ -20,6 +20,10 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, - struct msm_gpu *gpu = dev_to_gpu(dev); - struct dev_pm_opp *opp; - -+ /* -+ * Note that devfreq_recommended_opp() can modify the freq -+ * to something that actually is in the opp table: -+ */ - opp = devfreq_recommended_opp(dev, freq, flags); - - /* -@@ -28,6 +32,7 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, - */ - if (gpu->devfreq.idle_freq) { - gpu->devfreq.idle_freq = *freq; -+ dev_pm_opp_put(opp); - return 0; - } - -diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c -index b8621c6e05546..7cb158bcbcf67 100644 ---- a/drivers/gpu/drm/msm/msm_submitqueue.c -+++ b/drivers/gpu/drm/msm/msm_submitqueue.c -@@ -101,6 +101,7 @@ get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, - - ret = drm_sched_entity_init(entity, sched_prio, &sched, 1, NULL); - if (ret) { -+ mutex_unlock(&entity_lock); - kfree(entity); - return ERR_PTR(ret); - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c -index 6109cd9e33991..e7efd9ede8e4b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c -@@ -562,6 +562,7 @@ nouveau_drm_device_init(struct drm_device *dev) - nvkm_dbgopt(nouveau_debug, "DRM"); - - INIT_LIST_HEAD(&drm->clients); -+ mutex_init(&drm->clients_lock); - spin_lock_init(&drm->tile.lock); - - /* workaround an odd issue on nvc1 by disabling the device's -@@ -632,6 +633,7 @@ fail_alloc: - static void - nouveau_drm_device_fini(struct drm_device *dev) - { -+ struct nouveau_cli *cli, *temp_cli; - struct nouveau_drm *drm = nouveau_drm(dev); - - if (nouveau_pmops_runtime()) { -@@ -656,9 +658,28 @@ nouveau_drm_device_fini(struct drm_device *dev) - nouveau_ttm_fini(drm); - nouveau_vga_fini(drm); - -+ /* -+ * There may be existing clients from as-yet unclosed files. For now, -+ * clean them up here rather than deferring until the file is closed, -+ * but this likely not correct if we want to support hot-unplugging -+ * properly. -+ */ -+ mutex_lock(&drm->clients_lock); -+ list_for_each_entry_safe(cli, temp_cli, &drm->clients, head) { -+ list_del(&cli->head); -+ mutex_lock(&cli->mutex); -+ if (cli->abi16) -+ nouveau_abi16_fini(cli->abi16); -+ mutex_unlock(&cli->mutex); -+ nouveau_cli_fini(cli); -+ kfree(cli); -+ } -+ mutex_unlock(&drm->clients_lock); -+ - nouveau_cli_fini(&drm->client); - nouveau_cli_fini(&drm->master); - nvif_parent_dtor(&drm->parent); -+ mutex_destroy(&drm->clients_lock); - kfree(drm); - } - -@@ -796,7 +817,7 @@ nouveau_drm_device_remove(struct drm_device *dev) - struct nvkm_client *client; - struct nvkm_device *device; - -- drm_dev_unregister(dev); -+ drm_dev_unplug(dev); - - client = nvxx_client(&drm->client.base); - device = nvkm_device_find(client->device); -@@ -1090,9 +1111,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) - - fpriv->driver_priv = cli; - -- mutex_lock(&drm->client.mutex); -+ mutex_lock(&drm->clients_lock); - list_add(&cli->head, &drm->clients); -- mutex_unlock(&drm->client.mutex); -+ mutex_unlock(&drm->clients_lock); - - done: - if (ret && cli) { -@@ -1110,6 +1131,16 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) - { - struct nouveau_cli *cli = nouveau_cli(fpriv); - struct nouveau_drm *drm = nouveau_drm(dev); -+ int dev_index; -+ -+ /* -+ * The device is gone, and as it currently stands all clients are -+ * cleaned up in the removal codepath. In the future this may change -+ * so that we can support hot-unplugging, but for now we immediately -+ * return to avoid a double-free situation. -+ */ -+ if (!drm_dev_enter(dev, &dev_index)) -+ return; - - pm_runtime_get_sync(dev->dev); - -@@ -1118,14 +1149,15 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) - nouveau_abi16_fini(cli->abi16); - mutex_unlock(&cli->mutex); - -- mutex_lock(&drm->client.mutex); -+ mutex_lock(&drm->clients_lock); - list_del(&cli->head); -- mutex_unlock(&drm->client.mutex); -+ mutex_unlock(&drm->clients_lock); - - nouveau_cli_fini(cli); - kfree(cli); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); -+ drm_dev_exit(dev_index); - } - - static const struct drm_ioctl_desc -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index ba65f136cf481..b2a970aa9bf4b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.h -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -139,6 +139,11 @@ struct nouveau_drm { - - struct list_head clients; - -+ /** -+ * @clients_lock: Protects access to the @clients list of &struct nouveau_cli. -+ */ -+ struct mutex clients_lock; -+ - u8 old_pm_cap; - - struct { -diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c -index 8c2ecc2827232..c89d5964148fd 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_gem.c -+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c -@@ -56,7 +56,7 @@ static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) - - nouveau_bo_del_io_reserve_lru(bo); - prot = vm_get_page_prot(vma->vm_flags); -- ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); -+ ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT); - nouveau_bo_add_io_reserve_lru(bo); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret; -diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c -index b0c3422cb01fa..9985bfde015a6 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_svm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c -@@ -162,10 +162,14 @@ nouveau_svmm_bind(struct drm_device *dev, void *data, - */ - - mm = get_task_mm(current); -+ if (!mm) { -+ return -EINVAL; -+ } - mmap_read_lock(mm); - - if (!cli->svm.svmm) { - mmap_read_unlock(mm); -+ mmput(mm); - return -EINVAL; - } - -diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c -index 704df0f2d1f16..09a112af2f893 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c -+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c -@@ -78,6 +78,6 @@ int - gt215_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, - struct nvkm_engine **pengine) - { -- return nvkm_falcon_new_(>215_ce, device, type, inst, -+ return nvkm_falcon_new_(>215_ce, device, type, -1, - (device->chipset != 0xaf), 0x104000, pengine); - } -diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c -index ca75c5f6ecaf8..88d262ba648cf 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c -+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c -@@ -2626,6 +2626,27 @@ nv174_chipset = { - .fifo = { 0x00000001, ga102_fifo_new }, - }; - -+static const struct nvkm_device_chip -+nv176_chipset = { -+ .name = "GA106", -+ .bar = { 0x00000001, tu102_bar_new }, -+ .bios = { 0x00000001, nvkm_bios_new }, -+ .devinit = { 0x00000001, ga100_devinit_new }, -+ .fb = { 0x00000001, ga102_fb_new }, -+ .gpio = { 0x00000001, ga102_gpio_new }, -+ .i2c = { 0x00000001, gm200_i2c_new }, -+ .imem = { 0x00000001, nv50_instmem_new }, -+ .mc = { 0x00000001, ga100_mc_new }, -+ .mmu = { 0x00000001, tu102_mmu_new }, -+ .pci = { 0x00000001, gp100_pci_new }, -+ .privring = { 0x00000001, gm200_privring_new }, -+ .timer = { 0x00000001, gk20a_timer_new }, -+ .top = { 0x00000001, ga100_top_new }, -+ .disp = { 0x00000001, ga102_disp_new }, -+ .dma = { 0x00000001, gv100_dma_new }, -+ .fifo = { 0x00000001, ga102_fifo_new }, -+}; -+ - static const struct nvkm_device_chip - nv177_chipset = { - .name = "GA107", -@@ -3072,6 +3093,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, - case 0x168: device->chip = &nv168_chipset; break; - case 0x172: device->chip = &nv172_chipset; break; - case 0x174: device->chip = &nv174_chipset; break; -+ case 0x176: device->chip = &nv176_chipset; break; - case 0x177: device->chip = &nv177_chipset; break; - default: - if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) { -@@ -3147,8 +3169,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, - WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1)); \ - for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) { \ - if ((device->chip->ptr.inst & BIT(j)) && (subdev_mask & BIT_ULL(type))) { \ -- int inst = (device->chip->ptr.inst == 1) ? -1 : (j); \ -- ret = device->chip->ptr.ctor(device, (type), inst, &device->ptr[j]); \ -+ ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]); \ - subdev = nvkm_device_subdev(device, (type), (j)); \ - if (ret) { \ - nvkm_subdev_del(&subdev); \ -diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c -index 6e3c450eaacef..3ff49344abc77 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c -+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c -@@ -62,7 +62,6 @@ gv100_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); -- nvkm_wr32(device, 0x6f0110 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c -index cdb1ead26d84f..82b4c8e1457c2 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c -@@ -207,11 +207,13 @@ int - gm200_acr_wpr_parse(struct nvkm_acr *acr) - { - const struct wpr_header *hdr = (void *)acr->wpr_fw->data; -+ struct nvkm_acr_lsfw *lsfw; - - while (hdr->falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID) { - wpr_header_dump(&acr->subdev, hdr); -- if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) -- return -ENOMEM; -+ lsfw = nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id); -+ if (IS_ERR(lsfw)) -+ return PTR_ERR(lsfw); - } - - return 0; -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c -index fb9132a39bb1a..fd97a935a380e 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c -@@ -161,11 +161,13 @@ int - gp102_acr_wpr_parse(struct nvkm_acr *acr) - { - const struct wpr_header_v1 *hdr = (void *)acr->wpr_fw->data; -+ struct nvkm_acr_lsfw *lsfw; - - while (hdr->falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) { - wpr_header_v1_dump(&acr->subdev, hdr); -- if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) -- return -ENOMEM; -+ lsfw = nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id); -+ if (IS_ERR(lsfw)) -+ return PTR_ERR(lsfw); - } - - return 0; -diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c -index 458f92a708879..a36a4f2c76b09 100644 ---- a/drivers/gpu/drm/radeon/radeon_gem.c -+++ b/drivers/gpu/drm/radeon/radeon_gem.c -@@ -61,7 +61,7 @@ static vm_fault_t radeon_gem_fault(struct vm_fault *vmf) - goto unlock_resv; - - ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, -- TTM_BO_VM_NUM_PREFAULT, 1); -+ TTM_BO_VM_NUM_PREFAULT); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - goto unlock_mclk; - -diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig -index 5755f0432e774..8c796de53222c 100644 ---- a/drivers/gpu/drm/sun4i/Kconfig -+++ b/drivers/gpu/drm/sun4i/Kconfig -@@ -46,6 +46,7 @@ config DRM_SUN6I_DSI - default MACH_SUN8I - select CRC_CCITT - select DRM_MIPI_DSI -+ select RESET_CONTROLLER - select PHY_SUN6I_MIPI_DPHY - help - Choose this option if you want have an Allwinner SoC with -diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h -index a55a38ad849c1..022cafa6c06cb 100644 ---- a/drivers/gpu/drm/sun4i/sun8i_csc.h -+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h -@@ -16,8 +16,8 @@ struct sun8i_mixer; - #define CCSC10_OFFSET 0xA0000 - #define CCSC11_OFFSET 0xF0000 - --#define SUN8I_CSC_CTRL(base) (base + 0x0) --#define SUN8I_CSC_COEFF(base, i) (base + 0x10 + 4 * i) -+#define SUN8I_CSC_CTRL(base) ((base) + 0x0) -+#define SUN8I_CSC_COEFF(base, i) ((base) + 0x10 + 4 * (i)) - - #define SUN8I_CSC_CTRL_EN BIT(0) - -diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c -index 481b48bde0473..5a6e89825bc2f 100644 ---- a/drivers/gpu/drm/tiny/simpledrm.c -+++ b/drivers/gpu/drm/tiny/simpledrm.c -@@ -458,7 +458,7 @@ static struct drm_display_mode simpledrm_mode(unsigned int width, - { - struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) }; - -- mode.clock = 60 /* Hz */ * mode.hdisplay * mode.vdisplay; -+ mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */; - drm_mode_set_name(&mode); - - return mode; -diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c -index f56be5bc0861e..4a655ab23c89d 100644 ---- a/drivers/gpu/drm/ttm/ttm_bo_vm.c -+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c -@@ -171,89 +171,6 @@ vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, - } - EXPORT_SYMBOL(ttm_bo_vm_reserve); - --#ifdef CONFIG_TRANSPARENT_HUGEPAGE --/** -- * ttm_bo_vm_insert_huge - Insert a pfn for PUD or PMD faults -- * @vmf: Fault data -- * @bo: The buffer object -- * @page_offset: Page offset from bo start -- * @fault_page_size: The size of the fault in pages. -- * @pgprot: The page protections. -- * Does additional checking whether it's possible to insert a PUD or PMD -- * pfn and performs the insertion. -- * -- * Return: VM_FAULT_NOPAGE on successful insertion, VM_FAULT_FALLBACK if -- * a huge fault was not possible, or on insertion error. -- */ --static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, -- struct ttm_buffer_object *bo, -- pgoff_t page_offset, -- pgoff_t fault_page_size, -- pgprot_t pgprot) --{ -- pgoff_t i; -- vm_fault_t ret; -- unsigned long pfn; -- pfn_t pfnt; -- struct ttm_tt *ttm = bo->ttm; -- bool write = vmf->flags & FAULT_FLAG_WRITE; -- -- /* Fault should not cross bo boundary. */ -- page_offset &= ~(fault_page_size - 1); -- if (page_offset + fault_page_size > bo->resource->num_pages) -- goto out_fallback; -- -- if (bo->resource->bus.is_iomem) -- pfn = ttm_bo_io_mem_pfn(bo, page_offset); -- else -- pfn = page_to_pfn(ttm->pages[page_offset]); -- -- /* pfn must be fault_page_size aligned. */ -- if ((pfn & (fault_page_size - 1)) != 0) -- goto out_fallback; -- -- /* Check that memory is contiguous. */ -- if (!bo->resource->bus.is_iomem) { -- for (i = 1; i < fault_page_size; ++i) { -- if (page_to_pfn(ttm->pages[page_offset + i]) != pfn + i) -- goto out_fallback; -- } -- } else if (bo->bdev->funcs->io_mem_pfn) { -- for (i = 1; i < fault_page_size; ++i) { -- if (ttm_bo_io_mem_pfn(bo, page_offset + i) != pfn + i) -- goto out_fallback; -- } -- } -- -- pfnt = __pfn_to_pfn_t(pfn, PFN_DEV); -- if (fault_page_size == (HPAGE_PMD_SIZE >> PAGE_SHIFT)) -- ret = vmf_insert_pfn_pmd_prot(vmf, pfnt, pgprot, write); --#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD -- else if (fault_page_size == (HPAGE_PUD_SIZE >> PAGE_SHIFT)) -- ret = vmf_insert_pfn_pud_prot(vmf, pfnt, pgprot, write); --#endif -- else -- WARN_ON_ONCE(ret = VM_FAULT_FALLBACK); -- -- if (ret != VM_FAULT_NOPAGE) -- goto out_fallback; -- -- return VM_FAULT_NOPAGE; --out_fallback: -- count_vm_event(THP_FAULT_FALLBACK); -- return VM_FAULT_FALLBACK; --} --#else --static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, -- struct ttm_buffer_object *bo, -- pgoff_t page_offset, -- pgoff_t fault_page_size, -- pgprot_t pgprot) --{ -- return VM_FAULT_FALLBACK; --} --#endif -- - /** - * ttm_bo_vm_fault_reserved - TTM fault helper - * @vmf: The struct vm_fault given as argument to the fault callback -@@ -261,7 +178,6 @@ static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, - * @num_prefault: Maximum number of prefault pages. The caller may want to - * specify this based on madvice settings and the size of the GPU object - * backed by the memory. -- * @fault_page_size: The size of the fault in pages. - * - * This function inserts one or more page table entries pointing to the - * memory backing the buffer object, and then returns a return code -@@ -275,8 +191,7 @@ static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, - */ - vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, - pgprot_t prot, -- pgoff_t num_prefault, -- pgoff_t fault_page_size) -+ pgoff_t num_prefault) - { - struct vm_area_struct *vma = vmf->vma; - struct ttm_buffer_object *bo = vma->vm_private_data; -@@ -327,11 +242,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, - prot = pgprot_decrypted(prot); - } - -- /* We don't prefault on huge faults. Yet. */ -- if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && fault_page_size != 1) -- return ttm_bo_vm_insert_huge(vmf, bo, page_offset, -- fault_page_size, prot); -- - /* - * Speculatively prefault a number of pages. Only error on - * first page. -@@ -429,7 +339,7 @@ vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) - - prot = vma->vm_page_prot; - if (drm_dev_enter(ddev, &idx)) { -- ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); -+ ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT); - drm_dev_exit(idx); - } else { - ret = ttm_bo_vm_dummy_page(vmf, prot); -@@ -519,11 +429,6 @@ int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, - - switch (bo->resource->mem_type) { - case TTM_PL_SYSTEM: -- if (unlikely(bo->ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { -- ret = ttm_tt_swapin(bo->ttm); -- if (unlikely(ret != 0)) -- return ret; -- } - fallthrough; - case TTM_PL_TT: - ret = ttm_bo_vm_access_kmap(bo, offset, buf, len, write); -diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c -index 3750fd2161317..930574ad2bca9 100644 ---- a/drivers/gpu/drm/udl/udl_connector.c -+++ b/drivers/gpu/drm/udl/udl_connector.c -@@ -30,7 +30,7 @@ static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, - int bval = (i + block * EDID_LENGTH) << 8; - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - 0x02, (0x80 | (0x02 << 5)), bval, -- 0xA1, read_buff, 2, HZ); -+ 0xA1, read_buff, 2, 1000); - if (ret < 1) { - DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); - kfree(read_buff); -diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c -index 5689da118197e..772b5831bcc6f 100644 ---- a/drivers/gpu/drm/v3d/v3d_gem.c -+++ b/drivers/gpu/drm/v3d/v3d_gem.c -@@ -197,8 +197,8 @@ v3d_clean_caches(struct v3d_dev *v3d) - - V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF); - if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & -- V3D_L2TCACTL_L2TFLS), 100)) { -- DRM_ERROR("Timeout waiting for L1T write combiner flush\n"); -+ V3D_L2TCACTL_TMUWCF), 100)) { -+ DRM_ERROR("Timeout waiting for TMU write combiner flush\n"); - } - - mutex_lock(&v3d->cache_clean_lock); -diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c -index fddaeb0b09c11..f642bd6e71ff4 100644 ---- a/drivers/gpu/drm/vc4/vc4_bo.c -+++ b/drivers/gpu/drm/vc4/vc4_bo.c -@@ -391,7 +391,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) - - bo = kzalloc(sizeof(*bo), GFP_KERNEL); - if (!bo) -- return ERR_PTR(-ENOMEM); -+ return NULL; - - bo->madv = VC4_MADV_WILLNEED; - refcount_set(&bo->usecnt, 0); -diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c -index f0b3e4cf5bceb..b61792d2aa657 100644 ---- a/drivers/gpu/drm/vc4/vc4_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_kms.c -@@ -337,10 +337,10 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - struct drm_device *dev = state->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hvs *hvs = vc4->hvs; -- struct drm_crtc_state *old_crtc_state; - struct drm_crtc_state *new_crtc_state; - struct drm_crtc *crtc; - struct vc4_hvs_state *old_hvs_state; -+ unsigned int channel; - int i; - - for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { -@@ -353,30 +353,32 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) - vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); - } - -- if (vc4->hvs->hvs5) -- clk_set_min_rate(hvs->core_clk, 500000000); -- - old_hvs_state = vc4_hvs_get_old_global_state(state); -- if (!old_hvs_state) -+ if (IS_ERR(old_hvs_state)) - return; - -- for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { -- struct vc4_crtc_state *vc4_crtc_state = -- to_vc4_crtc_state(old_crtc_state); -- unsigned int channel = vc4_crtc_state->assigned_channel; -+ for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { -+ struct drm_crtc_commit *commit; - int ret; - -- if (channel == VC4_HVS_CHANNEL_DISABLED) -+ if (!old_hvs_state->fifo_state[channel].in_use) - continue; - -- if (!old_hvs_state->fifo_state[channel].in_use) -+ commit = old_hvs_state->fifo_state[channel].pending_commit; -+ if (!commit) - continue; - -- ret = drm_crtc_commit_wait(old_hvs_state->fifo_state[channel].pending_commit); -+ ret = drm_crtc_commit_wait(commit); - if (ret) - drm_err(dev, "Timed out waiting for commit\n"); -+ -+ drm_crtc_commit_put(commit); -+ old_hvs_state->fifo_state[channel].pending_commit = NULL; - } - -+ if (vc4->hvs->hvs5) -+ clk_set_min_rate(hvs->core_clk, 500000000); -+ - drm_atomic_helper_commit_modeset_disables(dev, state); - - vc4_ctm_commit(vc4, state); -@@ -410,8 +412,8 @@ static int vc4_atomic_commit_setup(struct drm_atomic_state *state) - unsigned int i; - - hvs_state = vc4_hvs_get_new_global_state(state); -- if (!hvs_state) -- return -EINVAL; -+ if (WARN_ON(IS_ERR(hvs_state))) -+ return PTR_ERR(hvs_state); - - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = -@@ -668,12 +670,6 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) - - for (i = 0; i < HVS_NUM_CHANNELS; i++) { - state->fifo_state[i].in_use = old_state->fifo_state[i].in_use; -- -- if (!old_state->fifo_state[i].pending_commit) -- continue; -- -- state->fifo_state[i].pending_commit = -- drm_crtc_commit_get(old_state->fifo_state[i].pending_commit); - } - - return &state->base; -@@ -762,8 +758,8 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, - unsigned int i; - - hvs_new_state = vc4_hvs_get_global_state(state); -- if (!hvs_new_state) -- return -EINVAL; -+ if (IS_ERR(hvs_new_state)) -+ return PTR_ERR(hvs_new_state); - - for (i = 0; i < ARRAY_SIZE(hvs_new_state->fifo_state); i++) - if (!hvs_new_state->fifo_state[i].in_use) -diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c -index 2e71e91278b45..93a41d018dca6 100644 ---- a/drivers/gpu/drm/virtio/virtgpu_vq.c -+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c -@@ -91,9 +91,7 @@ virtio_gpu_get_vbuf(struct virtio_gpu_device *vgdev, - { - struct virtio_gpu_vbuffer *vbuf; - -- vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL); -- if (!vbuf) -- return ERR_PTR(-ENOMEM); -+ vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL | __GFP_NOFAIL); - - BUG_ON(size > MAX_INLINE_CMD_SIZE || - size < sizeof(struct virtio_gpu_ctrl_hdr)); -@@ -147,10 +145,6 @@ static void *virtio_gpu_alloc_cmd_resp(struct virtio_gpu_device *vgdev, - - vbuf = virtio_gpu_get_vbuf(vgdev, cmd_size, - resp_size, resp_buf, cb); -- if (IS_ERR(vbuf)) { -- *vbuffer_p = NULL; -- return ERR_CAST(vbuf); -- } - *vbuffer_p = vbuf; - return (struct virtio_gpu_command *)vbuf->buf; - } -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h -index a833751099b55..858aff99a3fe5 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h -@@ -1550,10 +1550,6 @@ void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, - pgoff_t start, pgoff_t end); - vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf); - vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf); --#ifdef CONFIG_TRANSPARENT_HUGEPAGE --vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf, -- enum page_entry_size pe_size); --#endif - - /* Transparent hugepage support - vmwgfx_thp.c */ - #ifdef CONFIG_TRANSPARENT_HUGEPAGE -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c -index e5a9a5cbd01a7..922317d1acc8a 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c -@@ -477,7 +477,7 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf) - else - prot = vm_get_page_prot(vma->vm_flags); - -- ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault, 1); -+ ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault); - if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) - return ret; - -@@ -486,73 +486,3 @@ out_unlock: - - return ret; - } -- --#ifdef CONFIG_TRANSPARENT_HUGEPAGE --vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf, -- enum page_entry_size pe_size) --{ -- struct vm_area_struct *vma = vmf->vma; -- struct ttm_buffer_object *bo = (struct ttm_buffer_object *) -- vma->vm_private_data; -- struct vmw_buffer_object *vbo = -- container_of(bo, struct vmw_buffer_object, base); -- pgprot_t prot; -- vm_fault_t ret; -- pgoff_t fault_page_size; -- bool write = vmf->flags & FAULT_FLAG_WRITE; -- -- switch (pe_size) { -- case PE_SIZE_PMD: -- fault_page_size = HPAGE_PMD_SIZE >> PAGE_SHIFT; -- break; --#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD -- case PE_SIZE_PUD: -- fault_page_size = HPAGE_PUD_SIZE >> PAGE_SHIFT; -- break; --#endif -- default: -- WARN_ON_ONCE(1); -- return VM_FAULT_FALLBACK; -- } -- -- /* Always do write dirty-tracking and COW on PTE level. */ -- if (write && (READ_ONCE(vbo->dirty) || is_cow_mapping(vma->vm_flags))) -- return VM_FAULT_FALLBACK; -- -- ret = ttm_bo_vm_reserve(bo, vmf); -- if (ret) -- return ret; -- -- if (vbo->dirty) { -- pgoff_t allowed_prefault; -- unsigned long page_offset; -- -- page_offset = vmf->pgoff - -- drm_vma_node_start(&bo->base.vma_node); -- if (page_offset >= bo->resource->num_pages || -- vmw_resources_clean(vbo, page_offset, -- page_offset + PAGE_SIZE, -- &allowed_prefault)) { -- ret = VM_FAULT_SIGBUS; -- goto out_unlock; -- } -- -- /* -- * Write protect, so we get a new fault on write, and can -- * split. -- */ -- prot = vm_get_page_prot(vma->vm_flags & ~VM_SHARED); -- } else { -- prot = vm_get_page_prot(vma->vm_flags); -- } -- -- ret = ttm_bo_vm_fault_reserved(vmf, prot, 1, fault_page_size); -- if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) -- return ret; -- --out_unlock: -- dma_resv_unlock(bo->base.resv); -- -- return ret; --} --#endif -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c -index e6b1f98ec99f0..0a4c340252ec4 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c -@@ -61,9 +61,6 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) - .fault = vmw_bo_vm_fault, - .open = ttm_bo_vm_open, - .close = ttm_bo_vm_close, --#ifdef CONFIG_TRANSPARENT_HUGEPAGE -- .huge_fault = vmw_bo_vm_huge_fault, --#endif - }; - struct drm_file *file_priv = filp->private_data; - struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); -diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig -index 3c33bf572d6d3..9235ab7161e3a 100644 ---- a/drivers/hid/Kconfig -+++ b/drivers/hid/Kconfig -@@ -207,14 +207,14 @@ config HID_CHERRY - - config HID_CHICONY - tristate "Chicony devices" -- depends on HID -+ depends on USB_HID - default !EXPERT - help - Support for Chicony Tactical pad and special keys on Chicony keyboards. - - config HID_CORSAIR - tristate "Corsair devices" -- depends on HID && USB && LEDS_CLASS -+ depends on USB_HID && LEDS_CLASS - help - Support for Corsair devices that are not fully compliant with the - HID standard. -@@ -245,7 +245,7 @@ config HID_MACALLY - - config HID_PRODIKEYS - tristate "Prodikeys PC-MIDI Keyboard support" -- depends on HID && SND -+ depends on USB_HID && SND - select SND_RAWMIDI - help - Support for Prodikeys PC-MIDI Keyboard device support. -@@ -553,7 +553,7 @@ config HID_LENOVO - - config HID_LOGITECH - tristate "Logitech devices" -- depends on HID -+ depends on USB_HID - depends on LEDS_CLASS - default !EXPERT - help -@@ -919,7 +919,7 @@ config HID_SAITEK - - config HID_SAMSUNG - tristate "Samsung InfraRed remote control or keyboards" -- depends on HID -+ depends on USB_HID - help - Support for Samsung InfraRed remote control or keyboards. - -diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c -index f3ecddc519ee8..08c9a9a60ae47 100644 ---- a/drivers/hid/hid-asus.c -+++ b/drivers/hid/hid-asus.c -@@ -1028,8 +1028,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) - if (drvdata->quirks & QUIRK_IS_MULTITOUCH) - drvdata->tp = &asus_i2c_tp; - -- if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && -- hid_is_using_ll_driver(hdev, &usb_hid_driver)) { -+ if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) { - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - - if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { -@@ -1057,8 +1056,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) - drvdata->tp = &asus_t100chi_tp; - } - -- if ((drvdata->quirks & QUIRK_MEDION_E1239T) && -- hid_is_using_ll_driver(hdev, &usb_hid_driver)) { -+ if ((drvdata->quirks & QUIRK_MEDION_E1239T) && hid_is_usb(hdev)) { - struct usb_host_interface *alt = - to_usb_interface(hdev->dev.parent)->altsetting; - -diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c -index db6da21ade063..74ad8bf98bfd5 100644 ---- a/drivers/hid/hid-bigbenff.c -+++ b/drivers/hid/hid-bigbenff.c -@@ -191,7 +191,7 @@ static void bigben_worker(struct work_struct *work) - struct bigben_device, worker); - struct hid_field *report_field = bigben->report->field[0]; - -- if (bigben->removed) -+ if (bigben->removed || !report_field) - return; - - if (bigben->work_led) { -diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c -index ca556d39da2ae..f04d2aa23efe4 100644 ---- a/drivers/hid/hid-chicony.c -+++ b/drivers/hid/hid-chicony.c -@@ -114,6 +114,9 @@ static int ch_probe(struct hid_device *hdev, const struct hid_device_id *id) - { - int ret; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - hdev->quirks |= HID_QUIRK_INPUT_PER_APP; - ret = hid_parse(hdev); - if (ret) { -diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c -index 902a60e249ed2..8c895c820b672 100644 ---- a/drivers/hid/hid-corsair.c -+++ b/drivers/hid/hid-corsair.c -@@ -553,7 +553,12 @@ static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id) - int ret; - unsigned long quirks = id->driver_data; - struct corsair_drvdata *drvdata; -- struct usb_interface *usbif = to_usb_interface(dev->dev.parent); -+ struct usb_interface *usbif; -+ -+ if (!hid_is_usb(dev)) -+ return -EINVAL; -+ -+ usbif = to_usb_interface(dev->dev.parent); - - drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata), - GFP_KERNEL); -diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c -index 021049805bb71..3091355d48df6 100644 ---- a/drivers/hid/hid-elan.c -+++ b/drivers/hid/hid-elan.c -@@ -50,7 +50,7 @@ struct elan_drvdata { - - static int is_not_elan_touchpad(struct hid_device *hdev) - { -- if (hdev->bus == BUS_USB) { -+ if (hid_is_usb(hdev)) { - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); - - return (intf->altsetting->desc.bInterfaceNumber != -diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c -index 383dfda8c12fc..8e960d7b233b3 100644 ---- a/drivers/hid/hid-elo.c -+++ b/drivers/hid/hid-elo.c -@@ -230,6 +230,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) - int ret; - struct usb_device *udev; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; -diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c -index 4ef1c3b8094ea..183eeb3863b38 100644 ---- a/drivers/hid/hid-ft260.c -+++ b/drivers/hid/hid-ft260.c -@@ -915,6 +915,9 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id) - struct ft260_get_chip_version_report version; - int ret; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; -diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c -index 8123b871a3ebf..0403beb3104b9 100644 ---- a/drivers/hid/hid-google-hammer.c -+++ b/drivers/hid/hid-google-hammer.c -@@ -585,6 +585,8 @@ static void hammer_remove(struct hid_device *hdev) - static const struct hid_device_id hammer_devices[] = { - { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, - USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) }, -+ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, -+ USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) }, - { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, - USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, - { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, -diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c -index 0a38e8e9bc783..403506b9697e7 100644 ---- a/drivers/hid/hid-holtek-kbd.c -+++ b/drivers/hid/hid-holtek-kbd.c -@@ -140,12 +140,17 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, - static int holtek_kbd_probe(struct hid_device *hdev, - const struct hid_device_id *id) - { -- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); -- int ret = hid_parse(hdev); -+ struct usb_interface *intf; -+ int ret; -+ -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; - -+ ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - -+ intf = to_usb_interface(hdev->dev.parent); - if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) { - struct hid_input *hidinput; - list_for_each_entry(hidinput, &hdev->inputs, list) { -diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c -index 195b735b001d0..b7172c48ef9f0 100644 ---- a/drivers/hid/hid-holtek-mouse.c -+++ b/drivers/hid/hid-holtek-mouse.c -@@ -62,6 +62,14 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, - return rdesc; - } - -+static int holtek_mouse_probe(struct hid_device *hdev, -+ const struct hid_device_id *id) -+{ -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ return 0; -+} -+ - static const struct hid_device_id holtek_mouse_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, - USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, -@@ -83,6 +91,7 @@ static struct hid_driver holtek_mouse_driver = { - .name = "holtek_mouse", - .id_table = holtek_mouse_devices, - .report_fixup = holtek_mouse_report_fixup, -+ .probe = holtek_mouse_probe, - }; - - module_hid_driver(holtek_mouse_driver); -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 29564b370341e..70e65eb1b868d 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -394,6 +394,7 @@ - #define USB_DEVICE_ID_HP_X2 0x074d - #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 - #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 -+#define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 - #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 - #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A - -@@ -496,6 +497,7 @@ - #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d - #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 - #define USB_DEVICE_ID_GOOGLE_DON 0x5050 -+#define USB_DEVICE_ID_GOOGLE_EEL 0x5057 - - #define USB_VENDOR_ID_GOTOP 0x08f2 - #define USB_DEVICE_ID_SUPER_Q2 0x007f -@@ -881,6 +883,7 @@ - #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 - #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 - #define USB_DEVICE_ID_MS_POWER_COVER 0x07da -+#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de - #define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd - #define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb - #define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0 -@@ -1276,6 +1279,9 @@ - #define USB_DEVICE_ID_WEIDA_8752 0xC300 - #define USB_DEVICE_ID_WEIDA_8755 0xC301 - -+#define USB_VENDOR_ID_WINBOND 0x0416 -+#define USB_DEVICE_ID_TSTP_MTOUCH 0xc168 -+ - #define USB_VENDOR_ID_WISEGROUP 0x0925 - #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 - #define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888 -diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c -index 4b5ebeacd2836..55017db98d896 100644 ---- a/drivers/hid/hid-input.c -+++ b/drivers/hid/hid-input.c -@@ -160,6 +160,7 @@ static int hidinput_setkeycode(struct input_dev *dev, - if (usage) { - *old_keycode = usage->type == EV_KEY ? - usage->code : KEY_RESERVED; -+ usage->type = EV_KEY; - usage->code = ke->keycode; - - clear_bit(*old_keycode, dev->keybit); -@@ -324,6 +325,8 @@ static const struct hid_device_id hid_battery_quirks[] = { - HID_BATTERY_QUIRK_IGNORE }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), -+ HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), -@@ -650,10 +653,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - code += KEY_MACRO1; - else - code += BTN_TRIGGER_HAPPY - 0x1e; -- } else { -- goto ignore; -+ break; - } -- break; -+ fallthrough; - default: - switch (field->physical) { - case HID_GD_MOUSE: -diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c -index d40af911df635..fb3f7258009c2 100644 ---- a/drivers/hid/hid-lg.c -+++ b/drivers/hid/hid-lg.c -@@ -749,12 +749,18 @@ static int lg_raw_event(struct hid_device *hdev, struct hid_report *report, - - static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) - { -- struct usb_interface *iface = to_usb_interface(hdev->dev.parent); -- __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; -+ struct usb_interface *iface; -+ __u8 iface_num; - unsigned int connect_mask = HID_CONNECT_DEFAULT; - struct lg_drv_data *drv_data; - int ret; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ -+ iface = to_usb_interface(hdev->dev.parent); -+ iface_num = iface->cur_altsetting->desc.bInterfaceNumber; -+ - /* G29 only work with the 1st interface */ - if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) && - (iface_num != 0)) { -diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c -index a0017b010c342..7106b921b53cf 100644 ---- a/drivers/hid/hid-logitech-dj.c -+++ b/drivers/hid/hid-logitech-dj.c -@@ -1777,7 +1777,7 @@ static int logi_dj_probe(struct hid_device *hdev, - case recvr_type_bluetooth: no_dj_interfaces = 2; break; - case recvr_type_dinovo: no_dj_interfaces = 2; break; - } -- if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { -+ if (hid_is_usb(hdev)) { - intf = to_usb_interface(hdev->dev.parent); - if (intf && intf->altsetting->desc.bInterfaceNumber >= - no_dj_interfaces) { -diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c -index 686788ebf3e1e..d7687ce706144 100644 ---- a/drivers/hid/hid-magicmouse.c -+++ b/drivers/hid/hid-magicmouse.c -@@ -256,8 +256,11 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda - unsigned long now = jiffies; - int step_x = msc->touches[id].scroll_x - x; - int step_y = msc->touches[id].scroll_y - y; -- int step_hr = ((64 - (int)scroll_speed) * msc->scroll_accel) / -- SCROLL_HR_STEPS; -+ int step_hr = -+ max_t(int, -+ ((64 - (int)scroll_speed) * msc->scroll_accel) / -+ SCROLL_HR_STEPS, -+ 1); - int step_x_hr = msc->touches[id].scroll_x_hr - x; - int step_y_hr = msc->touches[id].scroll_y_hr - y; - -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index 3ea7cb1cda84c..e1afddb7b33d8 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -193,6 +193,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); - /* reserved 0x0014 */ - #define MT_CLS_WIN_8_FORCE_MULTI_INPUT 0x0015 - #define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016 -+#define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017 - - /* vendor specific classes */ - #define MT_CLS_3M 0x0101 -@@ -294,6 +295,13 @@ static const struct mt_class mt_classes[] = { - MT_QUIRK_WIN8_PTP_BUTTONS | - MT_QUIRK_DISABLE_WAKEUP, - .export_all_inputs = true }, -+ { .name = MT_CLS_WIN_8_NO_STICKY_FINGERS, -+ .quirks = MT_QUIRK_ALWAYS_VALID | -+ MT_QUIRK_IGNORE_DUPLICATES | -+ MT_QUIRK_HOVERING | -+ MT_QUIRK_CONTACT_CNT_ACCURATE | -+ MT_QUIRK_WIN8_PTP_BUTTONS, -+ .export_all_inputs = true }, - - /* - * vendor specific classes -@@ -2120,6 +2128,11 @@ static const struct hid_device_id mt_devices[] = { - MT_USB_DEVICE(USB_VENDOR_ID_VTL, - USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) }, - -+ /* Winbond Electronics Corp. */ -+ { .driver_data = MT_CLS_WIN_8_NO_STICKY_FINGERS, -+ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8, -+ USB_VENDOR_ID_WINBOND, USB_DEVICE_ID_TSTP_MTOUCH) }, -+ - /* Wistron panels */ - { .driver_data = MT_CLS_NSMU, - MT_USB_DEVICE(USB_VENDOR_ID_WISTRON, -diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c -index 2666af02d5c1a..e4e9471d0f1e9 100644 ---- a/drivers/hid/hid-prodikeys.c -+++ b/drivers/hid/hid-prodikeys.c -@@ -798,12 +798,18 @@ static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, - static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) - { - int ret; -- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); -- unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -+ struct usb_interface *intf; -+ unsigned short ifnum; - unsigned long quirks = id->driver_data; - struct pk_device *pk; - struct pcmidi_snd *pm = NULL; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ -+ intf = to_usb_interface(hdev->dev.parent); -+ ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -+ - pk = kzalloc(sizeof(*pk), GFP_KERNEL); - if (pk == NULL) { - hid_err(hdev, "can't alloc descriptor\n"); -diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c -index 2e104682c22b9..65b7114761749 100644 ---- a/drivers/hid/hid-quirks.c -+++ b/drivers/hid/hid-quirks.c -@@ -124,6 +124,7 @@ static const struct hid_device_id hid_quirks[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER), HID_QUIRK_NO_INIT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, -diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c -index 4556d2a50f754..d94ee0539421e 100644 ---- a/drivers/hid/hid-roccat-arvo.c -+++ b/drivers/hid/hid-roccat-arvo.c -@@ -344,6 +344,9 @@ static int arvo_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c -index ce5f22519956a..e95d59cd8d075 100644 ---- a/drivers/hid/hid-roccat-isku.c -+++ b/drivers/hid/hid-roccat-isku.c -@@ -324,6 +324,9 @@ static int isku_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c -index 1ca64481145ee..e8522eacf7973 100644 ---- a/drivers/hid/hid-roccat-kone.c -+++ b/drivers/hid/hid-roccat-kone.c -@@ -749,6 +749,9 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c -index 0316edf8c5bb4..1896c69ea512f 100644 ---- a/drivers/hid/hid-roccat-koneplus.c -+++ b/drivers/hid/hid-roccat-koneplus.c -@@ -431,6 +431,9 @@ static int koneplus_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c -index 5248b3c7cf785..cf8eeb33a1257 100644 ---- a/drivers/hid/hid-roccat-konepure.c -+++ b/drivers/hid/hid-roccat-konepure.c -@@ -133,6 +133,9 @@ static int konepure_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c -index 9600128815705..6fb9b9563769d 100644 ---- a/drivers/hid/hid-roccat-kovaplus.c -+++ b/drivers/hid/hid-roccat-kovaplus.c -@@ -501,6 +501,9 @@ static int kovaplus_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c -index 4a88a76d5c622..d5ddf0d68346b 100644 ---- a/drivers/hid/hid-roccat-lua.c -+++ b/drivers/hid/hid-roccat-lua.c -@@ -160,6 +160,9 @@ static int lua_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c -index 989927defe8db..4fcc8e7d276f2 100644 ---- a/drivers/hid/hid-roccat-pyra.c -+++ b/drivers/hid/hid-roccat-pyra.c -@@ -449,6 +449,9 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-ryos.c b/drivers/hid/hid-roccat-ryos.c -index 3956a6c9c5217..5bf1971a2b14d 100644 ---- a/drivers/hid/hid-roccat-ryos.c -+++ b/drivers/hid/hid-roccat-ryos.c -@@ -141,6 +141,9 @@ static int ryos_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c -index 818701f7a0281..a784bb4ee6512 100644 ---- a/drivers/hid/hid-roccat-savu.c -+++ b/drivers/hid/hid-roccat-savu.c -@@ -113,6 +113,9 @@ static int savu_probe(struct hid_device *hdev, - { - int retval; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - retval = hid_parse(hdev); - if (retval) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c -index 2e1c31156eca0..cf5992e970940 100644 ---- a/drivers/hid/hid-samsung.c -+++ b/drivers/hid/hid-samsung.c -@@ -152,6 +152,9 @@ static int samsung_probe(struct hid_device *hdev, - int ret; - unsigned int cmask = HID_CONNECT_DEFAULT; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed\n"); -diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c -index d1b107d547f54..60ec2b29d54de 100644 ---- a/drivers/hid/hid-sony.c -+++ b/drivers/hid/hid-sony.c -@@ -3000,7 +3000,6 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) - sc->quirks = quirks; - hid_set_drvdata(hdev, sc); - sc->hdev = hdev; -- usbdev = to_usb_device(sc->hdev->dev.parent->parent); - - ret = hid_parse(hdev); - if (ret) { -@@ -3038,14 +3037,23 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) - */ - if (!(hdev->claimed & HID_CLAIMED_INPUT)) { - hid_err(hdev, "failed to claim input\n"); -- hid_hw_stop(hdev); -- return -ENODEV; -+ ret = -ENODEV; -+ goto err; - } - - if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { -+ if (!hid_is_usb(hdev)) { -+ ret = -EINVAL; -+ goto err; -+ } -+ -+ usbdev = to_usb_device(sc->hdev->dev.parent->parent); -+ - sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC); -- if (!sc->ghl_urb) -- return -ENOMEM; -+ if (!sc->ghl_urb) { -+ ret = -ENOMEM; -+ goto err; -+ } - - if (sc->quirks & GHL_GUITAR_PS3WIIU) - ret = ghl_init_urb(sc, usbdev, ghl_ps3wiiu_magic_data, -@@ -3055,7 +3063,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) - ARRAY_SIZE(ghl_ps4_magic_data)); - if (ret) { - hid_err(hdev, "error preparing URB\n"); -- return ret; -+ goto err; - } - - timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0); -@@ -3064,6 +3072,10 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) - } - - return ret; -+ -+err: -+ hid_hw_stop(hdev); -+ return ret; - } - - static void sony_remove(struct hid_device *hdev) -diff --git a/drivers/hid/hid-thrustmaster.c b/drivers/hid/hid-thrustmaster.c -index d44550aa88057..0c92b7f9b8b81 100644 ---- a/drivers/hid/hid-thrustmaster.c -+++ b/drivers/hid/hid-thrustmaster.c -@@ -274,6 +274,9 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i - int ret = 0; - struct tm_wheel *tm_wheel = 0; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - ret = hid_parse(hdev); - if (ret) { - hid_err(hdev, "parse failed with error %d\n", ret); -diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c -index d70cd3d7f583b..ac3fd870673d2 100644 ---- a/drivers/hid/hid-u2fzero.c -+++ b/drivers/hid/hid-u2fzero.c -@@ -132,7 +132,7 @@ static int u2fzero_recv(struct u2fzero_device *dev, - - ret = (wait_for_completion_timeout( - &ctx.done, msecs_to_jiffies(USB_CTRL_SET_TIMEOUT))); -- if (ret < 0) { -+ if (ret == 0) { - usb_kill_urb(dev->urb); - hid_err(hdev, "urb submission timed out"); - } else { -@@ -191,6 +191,8 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data, - struct u2f_hid_msg resp; - int ret; - size_t actual_length; -+ /* valid packets must have a correct header */ -+ int min_length = offsetof(struct u2f_hid_msg, init.data); - - if (!dev->present) { - hid_dbg(dev->hdev, "device not present"); -@@ -200,12 +202,12 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data, - ret = u2fzero_recv(dev, &req, &resp); - - /* ignore errors or packets without data */ -- if (ret < offsetof(struct u2f_hid_msg, init.data)) -+ if (ret < min_length) - return 0; - - /* only take the minimum amount of data it is safe to take */ -- actual_length = min3((size_t)ret - offsetof(struct u2f_hid_msg, -- init.data), U2F_HID_MSG_LEN(resp), max); -+ actual_length = min3((size_t)ret - min_length, -+ U2F_HID_MSG_LEN(resp), max); - - memcpy(data, resp.init.data, actual_length); - -@@ -288,7 +290,7 @@ static int u2fzero_probe(struct hid_device *hdev, - unsigned int minor; - int ret; - -- if (!hid_is_using_ll_driver(hdev, &usb_hid_driver)) -+ if (!hid_is_usb(hdev)) - return -EINVAL; - - dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); -diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c -index 6a9865dd703c0..d8ab0139e5cda 100644 ---- a/drivers/hid/hid-uclogic-core.c -+++ b/drivers/hid/hid-uclogic-core.c -@@ -164,6 +164,9 @@ static int uclogic_probe(struct hid_device *hdev, - struct uclogic_drvdata *drvdata = NULL; - bool params_initialized = false; - -+ if (!hid_is_usb(hdev)) -+ return -EINVAL; -+ - /* - * libinput requires the pad interface to be on a different node - * than the pen, so use QUIRK_MULTI_INPUT for all tablets. -diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c -index 3d67b748a3b95..adff1bd68d9f8 100644 ---- a/drivers/hid/hid-uclogic-params.c -+++ b/drivers/hid/hid-uclogic-params.c -@@ -843,8 +843,7 @@ int uclogic_params_init(struct uclogic_params *params, - struct uclogic_params p = {0, }; - - /* Check arguments */ -- if (params == NULL || hdev == NULL || -- !hid_is_using_ll_driver(hdev, &usb_hid_driver)) { -+ if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { - rc = -EINVAL; - goto cleanup; - } -diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c -index 1c5039081db27..8e9d9450cb835 100644 ---- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c -+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c -@@ -266,7 +266,8 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work) - - if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag - && IPC_IS_ISH_ILUP(fwsts)) { -- disable_irq_wake(pdev->irq); -+ if (device_may_wakeup(&pdev->dev)) -+ disable_irq_wake(pdev->irq); - - ish_set_host_ready(dev); - -@@ -337,7 +338,8 @@ static int __maybe_unused ish_suspend(struct device *device) - */ - pci_save_state(pdev); - -- enable_irq_wake(pdev->irq); -+ if (device_may_wakeup(&pdev->dev)) -+ enable_irq_wake(pdev->irq); - } - } else { - /* -diff --git a/drivers/hid/surface-hid/surface_hid.c b/drivers/hid/surface-hid/surface_hid.c -index a3a70e4f3f6c9..d4aa8c81903ae 100644 ---- a/drivers/hid/surface-hid/surface_hid.c -+++ b/drivers/hid/surface-hid/surface_hid.c -@@ -209,7 +209,7 @@ static int surface_hid_probe(struct ssam_device *sdev) - - shid->notif.base.priority = 1; - shid->notif.base.fn = ssam_hid_event_fn; -- shid->notif.event.reg = SSAM_EVENT_REGISTRY_REG; -+ shid->notif.event.reg = SSAM_EVENT_REGISTRY_REG(sdev->uid.target); - shid->notif.event.id.target_category = sdev->uid.category; - shid->notif.event.id.instance = sdev->uid.instance; - shid->notif.event.mask = SSAM_EVENT_MASK_STRICT; -@@ -230,7 +230,7 @@ static void surface_hid_remove(struct ssam_device *sdev) - } - - static const struct ssam_device_id surface_hid_match[] = { -- { SSAM_SDEV(HID, 0x02, SSAM_ANY_IID, 0x00) }, -+ { SSAM_SDEV(HID, SSAM_ANY_TID, SSAM_ANY_IID, 0x00) }, - { }, - }; - MODULE_DEVICE_TABLE(ssam, surface_hid_match); -diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c -index 93f49b766376e..b1bbf297f66b0 100644 ---- a/drivers/hid/wacom_sys.c -+++ b/drivers/hid/wacom_sys.c -@@ -726,7 +726,7 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, - * Skip the query for this type and modify defaults based on - * interface number. - */ -- if (features->type == WIRELESS) { -+ if (features->type == WIRELESS && intf) { - if (intf->cur_altsetting->desc.bInterfaceNumber == 0) - features->device_type = WACOM_DEVICETYPE_WL_MONITOR; - else -@@ -2217,7 +2217,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) - if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) { - char *product_name = wacom->hdev->name; - -- if (hid_is_using_ll_driver(wacom->hdev, &usb_hid_driver)) { -+ if (hid_is_usb(wacom->hdev)) { - struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent); - struct usb_device *dev = interface_to_usbdev(intf); - product_name = dev->product; -@@ -2454,6 +2454,9 @@ static void wacom_wireless_work(struct work_struct *work) - - wacom_destroy_battery(wacom); - -+ if (!usbdev) -+ return; -+ - /* Stylus interface */ - hdev1 = usb_get_intfdata(usbdev->config->interface[1]); - wacom1 = hid_get_drvdata(hdev1); -@@ -2733,8 +2736,6 @@ static void wacom_mode_change_work(struct work_struct *work) - static int wacom_probe(struct hid_device *hdev, - const struct hid_device_id *id) - { -- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); -- struct usb_device *dev = interface_to_usbdev(intf); - struct wacom *wacom; - struct wacom_wac *wacom_wac; - struct wacom_features *features; -@@ -2769,8 +2770,14 @@ static int wacom_probe(struct hid_device *hdev, - wacom_wac->hid_data.inputmode = -1; - wacom_wac->mode_report = -1; - -- wacom->usbdev = dev; -- wacom->intf = intf; -+ if (hid_is_usb(hdev)) { -+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent); -+ struct usb_device *dev = interface_to_usbdev(intf); -+ -+ wacom->usbdev = dev; -+ wacom->intf = intf; -+ } -+ - mutex_init(&wacom->lock); - INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work); - INIT_WORK(&wacom->wireless_work, wacom_wireless_work); -diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c -index 33a6908995b1b..2a4cc39962e76 100644 ---- a/drivers/hid/wacom_wac.c -+++ b/drivers/hid/wacom_wac.c -@@ -2603,6 +2603,9 @@ static void wacom_wac_finger_event(struct hid_device *hdev, - return; - - switch (equivalent_usage) { -+ case HID_DG_CONFIDENCE: -+ wacom_wac->hid_data.confidence = value; -+ break; - case HID_GD_X: - wacom_wac->hid_data.x = value; - break; -@@ -2635,7 +2638,8 @@ static void wacom_wac_finger_event(struct hid_device *hdev, - } - - if (usage->usage_index + 1 == field->report_count) { -- if (equivalent_usage == wacom_wac->hid_data.last_slot_field) -+ if (equivalent_usage == wacom_wac->hid_data.last_slot_field && -+ wacom_wac->hid_data.confidence) - wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); - } - } -@@ -2653,6 +2657,8 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, - - wacom_wac->is_invalid_bt_frame = false; - -+ hid_data->confidence = true; -+ - for (i = 0; i < report->maxfield; i++) { - struct hid_field *field = report->field[i]; - int j; -diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h -index 8b2d4e5b2303c..466b62cc16dc1 100644 ---- a/drivers/hid/wacom_wac.h -+++ b/drivers/hid/wacom_wac.h -@@ -301,6 +301,7 @@ struct hid_data { - bool barrelswitch; - bool barrelswitch2; - bool serialhi; -+ bool confidence; - int x; - int y; - int pressure; -diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c -index 7f11ea07d698f..ca873a3b98dbe 100644 ---- a/drivers/hv/hv_balloon.c -+++ b/drivers/hv/hv_balloon.c -@@ -480,7 +480,7 @@ module_param(pressure_report_delay, uint, (S_IRUGO | S_IWUSR)); - MODULE_PARM_DESC(pressure_report_delay, "Delay in secs in reporting pressure"); - static atomic_t trans_id = ATOMIC_INIT(0); - --static int dm_ring_size = 20 * 1024; -+static int dm_ring_size = VMBUS_RING_SIZE(16 * 1024); - - /* - * Driver specific state. -diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c -index 731d5117f9f10..14389fd7afb89 100644 ---- a/drivers/hwmon/corsair-psu.c -+++ b/drivers/hwmon/corsair-psu.c -@@ -729,7 +729,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id - corsairpsu_check_cmd_support(priv); - - priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsairpsu", priv, -- &corsairpsu_chip_info, 0); -+ &corsairpsu_chip_info, NULL); - - if (IS_ERR(priv->hwmon_dev)) { - ret = PTR_ERR(priv->hwmon_dev); -diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c -index 774c1b0715d91..47fce97996de2 100644 ---- a/drivers/hwmon/dell-smm-hwmon.c -+++ b/drivers/hwmon/dell-smm-hwmon.c -@@ -623,10 +623,9 @@ static void __init i8k_init_procfs(struct device *dev) - { - struct dell_smm_data *data = dev_get_drvdata(dev); - -- /* Register the proc entry */ -- proc_create_data("i8k", 0, NULL, &i8k_proc_ops, data); -- -- devm_add_action_or_reset(dev, i8k_exit_procfs, NULL); -+ /* Only register exit function if creation was successful */ -+ if (proc_create_data("i8k", 0, NULL, &i8k_proc_ops, data)) -+ devm_add_action_or_reset(dev, i8k_exit_procfs, NULL); - } - - #else -diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c -index 8d3b1dae31df1..3501a3ead4ba6 100644 ---- a/drivers/hwmon/hwmon.c -+++ b/drivers/hwmon/hwmon.c -@@ -796,8 +796,10 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, - dev_set_drvdata(hdev, drvdata); - dev_set_name(hdev, HWMON_ID_FORMAT, id); - err = device_register(hdev); -- if (err) -- goto free_hwmon; -+ if (err) { -+ put_device(hdev); -+ goto ida_remove; -+ } - - INIT_LIST_HEAD(&hwdev->tzdata); - -diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c -index d209e0afc2caa..66d3e88b54172 100644 ---- a/drivers/hwmon/pmbus/lm25066.c -+++ b/drivers/hwmon/pmbus/lm25066.c -@@ -51,26 +51,31 @@ struct __coeff { - #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) - #define PSC_POWER_L (PSC_NUM_CLASSES + 1) - --static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { -+static struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = { - [lm25056] = { - [PSC_VOLTAGE_IN] = { - .m = 16296, -+ .b = 1343, - .R = -2, - }, - [PSC_CURRENT_IN] = { - .m = 13797, -+ .b = -1833, - .R = -2, - }, - [PSC_CURRENT_IN_L] = { - .m = 6726, -+ .b = -537, - .R = -2, - }, - [PSC_POWER] = { - .m = 5501, -+ .b = -2908, - .R = -3, - }, - [PSC_POWER_L] = { - .m = 26882, -+ .b = -5646, - .R = -4, - }, - [PSC_TEMPERATURE] = { -@@ -82,26 +87,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { - [lm25066] = { - [PSC_VOLTAGE_IN] = { - .m = 22070, -+ .b = -1800, - .R = -2, - }, - [PSC_VOLTAGE_OUT] = { - .m = 22070, -+ .b = -1800, - .R = -2, - }, - [PSC_CURRENT_IN] = { - .m = 13661, -+ .b = -5200, - .R = -2, - }, - [PSC_CURRENT_IN_L] = { - .m = 6852, -+ .b = -3100, - .R = -2, - }, - [PSC_POWER] = { - .m = 736, -+ .b = -3300, - .R = -2, - }, - [PSC_POWER_L] = { - .m = 369, -+ .b = -1900, - .R = -2, - }, - [PSC_TEMPERATURE] = { -@@ -111,26 +122,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { - [lm5064] = { - [PSC_VOLTAGE_IN] = { - .m = 4611, -+ .b = -642, - .R = -2, - }, - [PSC_VOLTAGE_OUT] = { - .m = 4621, -+ .b = 423, - .R = -2, - }, - [PSC_CURRENT_IN] = { - .m = 10742, -+ .b = 1552, - .R = -2, - }, - [PSC_CURRENT_IN_L] = { - .m = 5456, -+ .b = 2118, - .R = -2, - }, - [PSC_POWER] = { - .m = 1204, -+ .b = 8524, - .R = -3, - }, - [PSC_POWER_L] = { - .m = 612, -+ .b = 11202, - .R = -3, - }, - [PSC_TEMPERATURE] = { -@@ -140,26 +157,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { - [lm5066] = { - [PSC_VOLTAGE_IN] = { - .m = 4587, -+ .b = -1200, - .R = -2, - }, - [PSC_VOLTAGE_OUT] = { - .m = 4587, -+ .b = -2400, - .R = -2, - }, - [PSC_CURRENT_IN] = { - .m = 10753, -+ .b = -1200, - .R = -2, - }, - [PSC_CURRENT_IN_L] = { - .m = 5405, -+ .b = -600, - .R = -2, - }, - [PSC_POWER] = { - .m = 1204, -+ .b = -6000, - .R = -3, - }, - [PSC_POWER_L] = { - .m = 605, -+ .b = -8000, - .R = -3, - }, - [PSC_TEMPERATURE] = { -diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c -index 17518b4cab1b0..f12b9a28a232d 100644 ---- a/drivers/hwmon/pwm-fan.c -+++ b/drivers/hwmon/pwm-fan.c -@@ -336,8 +336,6 @@ static int pwm_fan_probe(struct platform_device *pdev) - return ret; - } - -- ctx->pwm_value = MAX_PWM; -- - pwm_init_state(ctx->pwm, &ctx->pwm_state); - - /* -diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c -index e2a3620cbf489..8988b2ed2ea6f 100644 ---- a/drivers/hwtracing/coresight/coresight-cti-core.c -+++ b/drivers/hwtracing/coresight/coresight-cti-core.c -@@ -175,7 +175,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) - coresight_disclaim_device_unlocked(csdev); - CS_LOCK(drvdata->base); - spin_unlock(&drvdata->spinlock); -- pm_runtime_put(dev); -+ pm_runtime_put(dev->parent); - return 0; - - /* not disabled this call */ -diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c -index 1768684968797..7dddb85b90591 100644 ---- a/drivers/hwtracing/coresight/coresight-trbe.c -+++ b/drivers/hwtracing/coresight/coresight-trbe.c -@@ -366,7 +366,7 @@ static unsigned long __trbe_normal_offset(struct perf_output_handle *handle) - - static unsigned long trbe_normal_offset(struct perf_output_handle *handle) - { -- struct trbe_buf *buf = perf_get_aux(handle); -+ struct trbe_buf *buf = etm_perf_sink_config(handle); - u64 limit = __trbe_normal_offset(handle); - u64 head = PERF_IDX2OFF(handle->head, buf); - -@@ -869,6 +869,10 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp - if (WARN_ON(trbe_csdev)) - return; - -+ /* If the TRBE was not probed on the CPU, we shouldn't be here */ -+ if (WARN_ON(!cpudata->drvdata)) -+ return; -+ - dev = &cpudata->drvdata->pdev->dev; - desc.name = devm_kasprintf(dev, GFP_KERNEL, "trbe%d", cpu); - if (!desc.name) -@@ -950,7 +954,9 @@ static int arm_trbe_probe_coresight(struct trbe_drvdata *drvdata) - return -ENOMEM; - - for_each_cpu(cpu, &drvdata->supported_cpus) { -- smp_call_function_single(cpu, arm_trbe_probe_cpu, drvdata, 1); -+ /* If we fail to probe the CPU, let us defer it to hotplug callbacks */ -+ if (smp_call_function_single(cpu, arm_trbe_probe_cpu, drvdata, 1)) -+ continue; - if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) - arm_trbe_register_coresight_cpu(drvdata, cpu); - if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) -diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c -index 72df563477b1c..f8639a4457d23 100644 ---- a/drivers/i2c/busses/i2c-cbus-gpio.c -+++ b/drivers/i2c/busses/i2c-cbus-gpio.c -@@ -195,8 +195,9 @@ static u32 cbus_i2c_func(struct i2c_adapter *adapter) - } - - static const struct i2c_algorithm cbus_i2c_algo = { -- .smbus_xfer = cbus_i2c_smbus_xfer, -- .functionality = cbus_i2c_func, -+ .smbus_xfer = cbus_i2c_smbus_xfer, -+ .smbus_xfer_atomic = cbus_i2c_smbus_xfer, -+ .functionality = cbus_i2c_func, - }; - - static int cbus_i2c_remove(struct platform_device *pdev) -diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c -index 89ae78ef1a1cc..1f929e6c30bea 100644 ---- a/drivers/i2c/busses/i2c-i801.c -+++ b/drivers/i2c/busses/i2c-i801.c -@@ -1493,7 +1493,6 @@ static struct platform_device * - i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, - struct resource *tco_res) - { -- static DEFINE_MUTEX(p2sb_mutex); - struct resource *res; - unsigned int devfn; - u64 base64_addr; -@@ -1506,7 +1505,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, - * enumerated by the PCI subsystem, so we need to unhide/hide it - * to lookup the P2SB BAR. - */ -- mutex_lock(&p2sb_mutex); -+ pci_lock_rescan_remove(); - - devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1); - -@@ -1524,7 +1523,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, - /* Hide the P2SB device, if it was hidden before */ - if (hidden) - pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden); -- mutex_unlock(&p2sb_mutex); -+ pci_unlock_rescan_remove(); - - res = &tco_res[1]; - if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) -diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c -index a6ea1eb1394e1..53b8da6dbb23f 100644 ---- a/drivers/i2c/busses/i2c-mpc.c -+++ b/drivers/i2c/busses/i2c-mpc.c -@@ -636,7 +636,7 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) - status = readb(i2c->base + MPC_I2C_SR); - if (status & CSR_MIF) { - /* Wait up to 100us for transfer to properly complete */ -- readb_poll_timeout(i2c->base + MPC_I2C_SR, status, !(status & CSR_MCF), 0, 100); -+ readb_poll_timeout_atomic(i2c->base + MPC_I2C_SR, status, status & CSR_MCF, 0, 100); - writeb(0, i2c->base + MPC_I2C_SR); - mpc_i2c_do_intr(i2c, status); - return IRQ_HANDLED; -diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c -index 7d4b3eb7077ad..72acda59eb399 100644 ---- a/drivers/i2c/busses/i2c-mt65xx.c -+++ b/drivers/i2c/busses/i2c-mt65xx.c -@@ -195,7 +195,7 @@ static const u16 mt_i2c_regs_v2[] = { - [OFFSET_CLOCK_DIV] = 0x48, - [OFFSET_SOFTRESET] = 0x50, - [OFFSET_SCL_MIS_COMP_POINT] = 0x90, -- [OFFSET_DEBUGSTAT] = 0xe0, -+ [OFFSET_DEBUGSTAT] = 0xe4, - [OFFSET_DEBUGCTRL] = 0xe8, - [OFFSET_FIFO_STAT] = 0xf4, - [OFFSET_FIFO_THRESH] = 0xf8, -diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c -index 819ab4ee517e1..02ddb237f69af 100644 ---- a/drivers/i2c/busses/i2c-rk3x.c -+++ b/drivers/i2c/busses/i2c-rk3x.c -@@ -423,8 +423,8 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) - if (!(ipd & REG_INT_MBRF)) - return; - -- /* ack interrupt */ -- i2c_writel(i2c, REG_INT_MBRF, REG_IPD); -+ /* ack interrupt (read also produces a spurious START flag, clear it too) */ -+ i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD); - - /* Can only handle a maximum of 32 bytes at a time */ - if (len > 32) -diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c -index b9b19a2a2ffa0..50d5ae81d2271 100644 ---- a/drivers/i2c/busses/i2c-stm32f7.c -+++ b/drivers/i2c/busses/i2c-stm32f7.c -@@ -1493,6 +1493,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) - { - struct stm32f7_i2c_dev *i2c_dev = data; - struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; -+ struct stm32_i2c_dma *dma = i2c_dev->dma; - void __iomem *base = i2c_dev->base; - u32 status, mask; - int ret = IRQ_HANDLED; -@@ -1518,6 +1519,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) - dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", - __func__, f7_msg->addr); - writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); -+ if (i2c_dev->use_dma) { -+ stm32f7_i2c_disable_dma_req(i2c_dev); -+ dmaengine_terminate_all(dma->chan_using); -+ } - f7_msg->result = -ENXIO; - } - -@@ -1533,7 +1538,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) - /* Clear STOP flag */ - writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); - -- if (i2c_dev->use_dma) { -+ if (i2c_dev->use_dma && !f7_msg->result) { - ret = IRQ_WAKE_THREAD; - } else { - i2c_dev->master_mode = false; -@@ -1546,7 +1551,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) - if (f7_msg->stop) { - mask = STM32F7_I2C_CR2_STOP; - stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask); -- } else if (i2c_dev->use_dma) { -+ } else if (i2c_dev->use_dma && !f7_msg->result) { - ret = IRQ_WAKE_THREAD; - } else if (f7_msg->smbus) { - stm32f7_i2c_smbus_rep_start(i2c_dev); -@@ -1696,12 +1701,23 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, - time_left = wait_for_completion_timeout(&i2c_dev->complete, - i2c_dev->adap.timeout); - ret = f7_msg->result; -+ if (ret) { -+ /* -+ * It is possible that some unsent data have already been -+ * written into TXDR. To avoid sending old data in a -+ * further transfer, flush TXDR in case of any error -+ */ -+ writel_relaxed(STM32F7_I2C_ISR_TXE, -+ i2c_dev->base + STM32F7_I2C_ISR); -+ goto pm_free; -+ } - - if (!time_left) { - dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n", - i2c_dev->msg->addr); - if (i2c_dev->use_dma) - dmaengine_terminate_all(dma->chan_using); -+ stm32f7_i2c_wait_free_bus(i2c_dev); - ret = -ETIMEDOUT; - } - -@@ -1744,13 +1760,22 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - timeout = wait_for_completion_timeout(&i2c_dev->complete, - i2c_dev->adap.timeout); - ret = f7_msg->result; -- if (ret) -+ if (ret) { -+ /* -+ * It is possible that some unsent data have already been -+ * written into TXDR. To avoid sending old data in a -+ * further transfer, flush TXDR in case of any error -+ */ -+ writel_relaxed(STM32F7_I2C_ISR_TXE, -+ i2c_dev->base + STM32F7_I2C_ISR); - goto pm_free; -+ } - - if (!timeout) { - dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr); - if (i2c_dev->use_dma) - dmaengine_terminate_all(dma->chan_using); -+ stm32f7_i2c_wait_free_bus(i2c_dev); - ret = -ETIMEDOUT; - goto pm_free; - } -diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c -index f10a603b13fb0..5cb21d7da05b6 100644 ---- a/drivers/i2c/busses/i2c-virtio.c -+++ b/drivers/i2c/busses/i2c-virtio.c -@@ -22,24 +22,24 @@ - /** - * struct virtio_i2c - virtio I2C data - * @vdev: virtio device for this controller -- * @completion: completion of virtio I2C message - * @adap: I2C adapter for this controller - * @vq: the virtio virtqueue for communication - */ - struct virtio_i2c { - struct virtio_device *vdev; -- struct completion completion; - struct i2c_adapter adap; - struct virtqueue *vq; - }; - - /** - * struct virtio_i2c_req - the virtio I2C request structure -+ * @completion: completion of virtio I2C message - * @out_hdr: the OUT header of the virtio I2C message - * @buf: the buffer into which data is read, or from which it's written - * @in_hdr: the IN header of the virtio I2C message - */ - struct virtio_i2c_req { -+ struct completion completion; - struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned; - uint8_t *buf ____cacheline_aligned; - struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned; -@@ -47,9 +47,11 @@ struct virtio_i2c_req { - - static void virtio_i2c_msg_done(struct virtqueue *vq) - { -- struct virtio_i2c *vi = vq->vdev->priv; -+ struct virtio_i2c_req *req; -+ unsigned int len; - -- complete(&vi->completion); -+ while ((req = virtqueue_get_buf(vq, &len))) -+ complete(&req->completion); - } - - static int virtio_i2c_prepare_reqs(struct virtqueue *vq, -@@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, - for (i = 0; i < num; i++) { - int outcnt = 0, incnt = 0; - -+ init_completion(&reqs[i].completion); -+ - /* - * We don't support 0 length messages and so filter out - * 0 length transfers by using i2c_adapter_quirks. -@@ -106,24 +110,17 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, - - static int virtio_i2c_complete_reqs(struct virtqueue *vq, - struct virtio_i2c_req *reqs, -- struct i2c_msg *msgs, int num, -- bool timedout) -+ struct i2c_msg *msgs, int num) - { -- struct virtio_i2c_req *req; -- bool failed = timedout; -- unsigned int len; -+ bool failed = false; - int i, j = 0; - - for (i = 0; i < num; i++) { -- /* Detach the ith request from the vq */ -- req = virtqueue_get_buf(vq, &len); -+ struct virtio_i2c_req *req = &reqs[i]; - -- /* -- * Condition req == &reqs[i] should always meet since we have -- * total num requests in the vq. reqs[i] can never be NULL here. -- */ -- if (!failed && (WARN_ON(req != &reqs[i]) || -- req->in_hdr.status != VIRTIO_I2C_MSG_OK)) -+ wait_for_completion(&req->completion); -+ -+ if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) - failed = true; - - i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); -@@ -132,7 +129,7 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, - j++; - } - -- return timedout ? -ETIMEDOUT : j; -+ return j; - } - - static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, -@@ -141,7 +138,6 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - struct virtio_i2c *vi = i2c_get_adapdata(adap); - struct virtqueue *vq = vi->vq; - struct virtio_i2c_req *reqs; -- unsigned long time_left; - int count; - - reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL); -@@ -160,15 +156,9 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - * remote here to clear the virtqueue, so we can try another set of - * messages later on. - */ -- -- reinit_completion(&vi->completion); - virtqueue_kick(vq); - -- time_left = wait_for_completion_timeout(&vi->completion, adap->timeout); -- if (!time_left) -- dev_err(&adap->dev, "virtio i2c backend timeout.\n"); -- -- count = virtio_i2c_complete_reqs(vq, reqs, msgs, count, !time_left); -+ count = virtio_i2c_complete_reqs(vq, reqs, msgs, count); - - err_free: - kfree(reqs); -@@ -215,8 +205,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev) - vdev->priv = vi; - vi->vdev = vdev; - -- init_completion(&vi->completion); -- - ret = virtio_i2c_setup_vqs(vi); - if (ret) - return ret; -diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c -index 126d1393e548b..9ce20652d4942 100644 ---- a/drivers/i2c/busses/i2c-xlr.c -+++ b/drivers/i2c/busses/i2c-xlr.c -@@ -431,11 +431,15 @@ static int xlr_i2c_probe(struct platform_device *pdev) - i2c_set_adapdata(&priv->adap, priv); - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret < 0) -- return ret; -+ goto err_unprepare_clk; - - platform_set_drvdata(pdev, priv); - dev_info(&priv->adap.dev, "Added I2C Bus.\n"); - return 0; -+ -+err_unprepare_clk: -+ clk_unprepare(clk); -+ return ret; - } - - static int xlr_i2c_remove(struct platform_device *pdev) -diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c -index a51fdd3c9b5b5..24c9387c29687 100644 ---- a/drivers/iio/accel/kxcjk-1013.c -+++ b/drivers/iio/accel/kxcjk-1013.c -@@ -1595,8 +1595,7 @@ static int kxcjk1013_probe(struct i2c_client *client, - return 0; - - err_buffer_cleanup: -- if (data->dready_trig) -- iio_triggered_buffer_cleanup(indio_dev); -+ iio_triggered_buffer_cleanup(indio_dev); - err_trigger_unregister: - if (data->dready_trig) - iio_trigger_unregister(data->dready_trig); -@@ -1618,8 +1617,8 @@ static int kxcjk1013_remove(struct i2c_client *client) - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - -+ iio_triggered_buffer_cleanup(indio_dev); - if (data->dready_trig) { -- iio_triggered_buffer_cleanup(indio_dev); - iio_trigger_unregister(data->dready_trig); - iio_trigger_unregister(data->motion_trig); - } -diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c -index bf7ed9e7d00f4..e56ecc075014e 100644 ---- a/drivers/iio/accel/kxsd9.c -+++ b/drivers/iio/accel/kxsd9.c -@@ -224,14 +224,14 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) - hw_values.chan, - sizeof(hw_values.chan)); - if (ret) { -- dev_err(st->dev, -- "error reading data\n"); -- return ret; -+ dev_err(st->dev, "error reading data: %d\n", ret); -+ goto out; - } - - iio_push_to_buffers_with_timestamp(indio_dev, - &hw_values, - iio_get_time_ns(indio_dev)); -+out: - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c -index 715b8138fb715..09c7f10fefb6e 100644 ---- a/drivers/iio/accel/mma8452.c -+++ b/drivers/iio/accel/mma8452.c -@@ -1470,7 +1470,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev) - if (ret) - return ret; - -- indio_dev->trig = trig; -+ indio_dev->trig = iio_trigger_get(trig); - - return 0; - } -diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c -index f711756e41e3d..cba57459e90ab 100644 ---- a/drivers/iio/accel/st_accel_i2c.c -+++ b/drivers/iio/accel/st_accel_i2c.c -@@ -193,10 +193,10 @@ static int st_accel_i2c_remove(struct i2c_client *client) - { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - -- st_sensors_power_disable(indio_dev); -- - st_accel_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c -index bb45d9ff95b85..5167fae1ee8ec 100644 ---- a/drivers/iio/accel/st_accel_spi.c -+++ b/drivers/iio/accel/st_accel_spi.c -@@ -143,10 +143,10 @@ static int st_accel_spi_remove(struct spi_device *spi) - { - struct iio_dev *indio_dev = spi_get_drvdata(spi); - -- st_sensors_power_disable(indio_dev); -- - st_accel_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c -index 2c5c8a3672b2d..aa42ba759fa1a 100644 ---- a/drivers/iio/adc/ad7768-1.c -+++ b/drivers/iio/adc/ad7768-1.c -@@ -480,8 +480,8 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p) - iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan, - iio_get_time_ns(indio_dev)); - -- iio_trigger_notify_done(indio_dev->trig); - err_unlock: -+ iio_trigger_notify_done(indio_dev->trig); - mutex_unlock(&st->lock); - - return IRQ_HANDLED; -diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c -index ea5ca163d8796..c4de706012e51 100644 ---- a/drivers/iio/adc/at91-sama5d2_adc.c -+++ b/drivers/iio/adc/at91-sama5d2_adc.c -@@ -1377,7 +1377,8 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, - *val = st->conversion_value; - ret = at91_adc_adjust_val_osr(st, val); - if (chan->scan_type.sign == 's') -- *val = sign_extend32(*val, 11); -+ *val = sign_extend32(*val, -+ chan->scan_type.realbits - 1); - st->conversion_done = false; - } - -diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c -index 3e0c0233b4315..df99f1365c398 100644 ---- a/drivers/iio/adc/axp20x_adc.c -+++ b/drivers/iio/adc/axp20x_adc.c -@@ -251,19 +251,8 @@ static int axp22x_adc_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val) - { - struct axp20x_adc_iio *info = iio_priv(indio_dev); -- int size; - -- /* -- * N.B.: Unlike the Chinese datasheets tell, the charging current is -- * stored on 12 bits, not 13 bits. Only discharging current is on 13 -- * bits. -- */ -- if (chan->type == IIO_CURRENT && chan->channel == AXP22X_BATT_DISCHRG_I) -- size = 13; -- else -- size = 12; -- -- *val = axp20x_read_variable_width(info->regmap, chan->address, size); -+ *val = axp20x_read_variable_width(info->regmap, chan->address, 12); - if (*val < 0) - return *val; - -@@ -386,9 +375,8 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val, - return IIO_VAL_INT_PLUS_MICRO; - - case IIO_CURRENT: -- *val = 0; -- *val2 = 500000; -- return IIO_VAL_INT_PLUS_MICRO; -+ *val = 1; -+ return IIO_VAL_INT; - - case IIO_TEMP: - *val = 100; -diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c -index 16407664182ce..97d162a3cba4e 100644 ---- a/drivers/iio/adc/dln2-adc.c -+++ b/drivers/iio/adc/dln2-adc.c -@@ -248,7 +248,6 @@ static int dln2_adc_set_chan_period(struct dln2_adc *dln2, - static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) - { - int ret, i; -- struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); - u16 conflict; - __le16 value; - int olen = sizeof(value); -@@ -257,13 +256,9 @@ static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) - .chan = channel, - }; - -- ret = iio_device_claim_direct_mode(indio_dev); -- if (ret < 0) -- return ret; -- - ret = dln2_adc_set_chan_enabled(dln2, channel, true); - if (ret < 0) -- goto release_direct; -+ return ret; - - ret = dln2_adc_set_port_enabled(dln2, true, &conflict); - if (ret < 0) { -@@ -300,8 +295,6 @@ disable_port: - dln2_adc_set_port_enabled(dln2, false, NULL); - disable_chan: - dln2_adc_set_chan_enabled(dln2, channel, false); --release_direct: -- iio_device_release_direct_mode(indio_dev); - - return ret; - } -@@ -337,10 +330,16 @@ static int dln2_adc_read_raw(struct iio_dev *indio_dev, - - switch (mask) { - case IIO_CHAN_INFO_RAW: -+ ret = iio_device_claim_direct_mode(indio_dev); -+ if (ret < 0) -+ return ret; -+ - mutex_lock(&dln2->mutex); - ret = dln2_adc_read(dln2, chan->channel); - mutex_unlock(&dln2->mutex); - -+ iio_device_release_direct_mode(indio_dev); -+ - if (ret < 0) - return ret; - -@@ -656,7 +655,11 @@ static int dln2_adc_probe(struct platform_device *pdev) - return -ENOMEM; - } - iio_trigger_set_drvdata(dln2->trig, dln2); -- devm_iio_trigger_register(dev, dln2->trig); -+ ret = devm_iio_trigger_register(dev, dln2->trig); -+ if (ret) { -+ dev_err(dev, "failed to register trigger: %d\n", ret); -+ return ret; -+ } - iio_trigger_set_immutable(indio_dev, dln2->trig); - - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, -diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c -index 5088de835bb15..e3e75413b49e7 100644 ---- a/drivers/iio/adc/stm32-adc.c -+++ b/drivers/iio/adc/stm32-adc.c -@@ -975,6 +975,7 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) - { - struct stm32_adc *adc = iio_priv(indio_dev); - -+ stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0); - stm32h7_adc_disable(indio_dev); - stm32h7_adc_enter_pwr_down(adc); - } -diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c -index 170950d5dd499..d84ae6b008c1b 100644 ---- a/drivers/iio/adc/ti-tsc2046.c -+++ b/drivers/iio/adc/ti-tsc2046.c -@@ -398,7 +398,7 @@ static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, - priv->xfer.len = size; - priv->time_per_scan_us = size * 8 * priv->time_per_bit_ns / NSEC_PER_USEC; - -- if (priv->scan_interval_us > priv->time_per_scan_us) -+ if (priv->scan_interval_us < priv->time_per_scan_us) - dev_warn(&priv->spi->dev, "The scan interval (%d) is less then calculated scan time (%d)\n", - priv->scan_interval_us, priv->time_per_scan_us); - -diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c -index 488ec69967d67..e50718422411d 100644 ---- a/drivers/iio/dac/ad5446.c -+++ b/drivers/iio/dac/ad5446.c -@@ -531,8 +531,15 @@ static int ad5622_write(struct ad5446_state *st, unsigned val) - { - struct i2c_client *client = to_i2c_client(st->dev); - __be16 data = cpu_to_be16(val); -+ int ret; -+ -+ ret = i2c_master_send(client, (char *)&data, sizeof(data)); -+ if (ret < 0) -+ return ret; -+ if (ret != sizeof(data)) -+ return -EIO; - -- return i2c_master_send(client, (char *)&data, sizeof(data)); -+ return 0; - } - - /* -diff --git a/drivers/iio/dac/ad5766.c b/drivers/iio/dac/ad5766.c -index 3104ec32dfaca..dafda84fdea35 100644 ---- a/drivers/iio/dac/ad5766.c -+++ b/drivers/iio/dac/ad5766.c -@@ -503,13 +503,13 @@ static int ad5766_get_output_range(struct ad5766_state *st) - int i, ret, min, max, tmp[2]; - - ret = device_property_read_u32_array(&st->spi->dev, -- "output-range-voltage", -+ "output-range-microvolts", - tmp, 2); - if (ret) - return ret; - -- min = tmp[0] / 1000; -- max = tmp[1] / 1000; -+ min = tmp[0] / 1000000; -+ max = tmp[1] / 1000000; - for (i = 0; i < ARRAY_SIZE(ad5766_span_tbl); i++) { - if (ad5766_span_tbl[i].min != min || - ad5766_span_tbl[i].max != max) -diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c -index 8107f7bbbe3c5..7e2fd32e993a6 100644 ---- a/drivers/iio/dac/ad5770r.c -+++ b/drivers/iio/dac/ad5770r.c -@@ -522,7 +522,7 @@ static int ad5770r_channel_config(struct ad5770r_state *st) - return -EINVAL; - - device_for_each_child_node(&st->spi->dev, child) { -- ret = fwnode_property_read_u32(child, "num", &num); -+ ret = fwnode_property_read_u32(child, "reg", &num); - if (ret) - goto err_child_out; - if (num >= AD5770R_MAX_CHANNELS) { -diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c -index 3e0734ddafe36..600e9725da788 100644 ---- a/drivers/iio/gyro/adxrs290.c -+++ b/drivers/iio/gyro/adxrs290.c -@@ -7,6 +7,7 @@ - */ - - #include <linux/bitfield.h> -+#include <linux/bitops.h> - #include <linux/delay.h> - #include <linux/device.h> - #include <linux/kernel.h> -@@ -124,7 +125,7 @@ static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int * - goto err_unlock; - } - -- *val = temp; -+ *val = sign_extend32(temp, 15); - - err_unlock: - mutex_unlock(&st->lock); -@@ -146,7 +147,7 @@ static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) - } - - /* extract lower 12 bits temperature reading */ -- *val = temp & 0x0FFF; -+ *val = sign_extend32(temp, 11); - - err_unlock: - mutex_unlock(&st->lock); -diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c -index 04dd6a7969ea7..4cfa0d4395605 100644 ---- a/drivers/iio/gyro/itg3200_buffer.c -+++ b/drivers/iio/gyro/itg3200_buffer.c -@@ -61,9 +61,9 @@ static irqreturn_t itg3200_trigger_handler(int irq, void *p) - - iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); - -+error_ret: - iio_trigger_notify_done(indio_dev->trig); - --error_ret: - return IRQ_HANDLED; - } - -diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c -index 3ef86e16ee656..a8164fe48b857 100644 ---- a/drivers/iio/gyro/st_gyro_i2c.c -+++ b/drivers/iio/gyro/st_gyro_i2c.c -@@ -106,10 +106,10 @@ static int st_gyro_i2c_remove(struct i2c_client *client) - { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - -- st_sensors_power_disable(indio_dev); -- - st_gyro_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c -index 41d835493347c..9d8916871b4bf 100644 ---- a/drivers/iio/gyro/st_gyro_spi.c -+++ b/drivers/iio/gyro/st_gyro_spi.c -@@ -110,10 +110,10 @@ static int st_gyro_spi_remove(struct spi_device *spi) - { - struct iio_dev *indio_dev = spi_get_drvdata(spi); - -- st_sensors_power_disable(indio_dev); -- - st_gyro_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c -index b9a06ca29beec..d4e692b187cda 100644 ---- a/drivers/iio/imu/adis.c -+++ b/drivers/iio/imu/adis.c -@@ -430,6 +430,8 @@ int __adis_initial_startup(struct adis *adis) - if (ret) - return ret; - -+ adis_enable_irq(adis, false); -+ - if (!adis->data->prod_id_reg) - return 0; - -@@ -526,7 +528,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, - adis->current_page = 0; - } - -- return adis_enable_irq(adis, false); -+ return 0; - } - EXPORT_SYMBOL_GPL(adis_init); - -diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c -index db45f1fc0b817..8dbf744c5651f 100644 ---- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c -+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c -@@ -1279,6 +1279,8 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr) - int err; - - switch (sensor->id) { -+ case ST_LSM6DSX_ID_GYRO: -+ break; - case ST_LSM6DSX_ID_EXT0: - case ST_LSM6DSX_ID_EXT1: - case ST_LSM6DSX_ID_EXT2: -@@ -1304,8 +1306,8 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr) - } - break; - } -- default: -- break; -+ default: /* should never occur */ -+ return -EINVAL; - } - - if (req_odr > 0) { -diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c -index a95cc2da56be6..2f98ba70e3d78 100644 ---- a/drivers/iio/industrialio-buffer.c -+++ b/drivers/iio/industrialio-buffer.c -@@ -1312,6 +1312,11 @@ static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer, - iio_attr->buffer = buffer; - memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr)); - iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL); -+ if (!iio_attr->dev_attr.attr.name) { -+ kfree(iio_attr); -+ return NULL; -+ } -+ - sysfs_attr_init(&iio_attr->dev_attr.attr); - - list_add(&iio_attr->l, &buffer->buffer_attr_list); -@@ -1362,10 +1367,10 @@ static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev, - - return 0; - --error_free_buffer_attrs: -- kfree(iio_dev_opaque->legacy_buffer_group.attrs); - error_free_scan_el_attrs: - kfree(iio_dev_opaque->legacy_scan_el_group.attrs); -+error_free_buffer_attrs: -+ kfree(iio_dev_opaque->legacy_buffer_group.attrs); - - return ret; - } -@@ -1531,6 +1536,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, - sizeof(struct attribute *) * buffer_attrcount); - - buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs); -+ buffer->buffer_group.attrs = attr; - - for (i = 0; i < buffer_attrcount; i++) { - struct attribute *wrapped; -@@ -1538,7 +1544,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, - wrapped = iio_buffer_wrap_attr(buffer, attr[i]); - if (!wrapped) { - ret = -ENOMEM; -- goto error_free_scan_mask; -+ goto error_free_buffer_attrs; - } - attr[i] = wrapped; - } -@@ -1553,8 +1559,6 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, - goto error_free_buffer_attrs; - } - -- buffer->buffer_group.attrs = attr; -- - ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group); - if (ret) - goto error_free_buffer_attr_group_name; -@@ -1583,8 +1587,12 @@ error_cleanup_dynamic: - return ret; - } - --static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer) -+static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer, -+ struct iio_dev *indio_dev, -+ int index) - { -+ if (index == 0) -+ iio_buffer_unregister_legacy_sysfs_groups(indio_dev); - bitmap_free(buffer->scan_mask); - kfree(buffer->buffer_group.name); - kfree(buffer->buffer_group.attrs); -@@ -1616,7 +1624,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) - buffer = iio_dev_opaque->attached_buffers[i]; - ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, i); - if (ret) { -- unwind_idx = i; -+ unwind_idx = i - 1; - goto error_unwind_sysfs_and_mask; - } - } -@@ -1638,7 +1646,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) - error_unwind_sysfs_and_mask: - for (; unwind_idx >= 0; unwind_idx--) { - buffer = iio_dev_opaque->attached_buffers[unwind_idx]; -- __iio_buffer_free_sysfs_and_mask(buffer); -+ __iio_buffer_free_sysfs_and_mask(buffer, indio_dev, unwind_idx); - } - return ret; - } -@@ -1655,11 +1663,9 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) - iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler); - kfree(iio_dev_opaque->buffer_ioctl_handler); - -- iio_buffer_unregister_legacy_sysfs_groups(indio_dev); -- - for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) { - buffer = iio_dev_opaque->attached_buffers[i]; -- __iio_buffer_free_sysfs_and_mask(buffer); -+ __iio_buffer_free_sysfs_and_mask(buffer, indio_dev, i); - } - } - -diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c -index 2dbb37e09b8cf..3e1e86d987cc2 100644 ---- a/drivers/iio/industrialio-core.c -+++ b/drivers/iio/industrialio-core.c -@@ -1600,6 +1600,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) - kfree(iio_dev_opaque->chan_attr_group.attrs); - iio_dev_opaque->chan_attr_group.attrs = NULL; - kfree(iio_dev_opaque->groups); -+ iio_dev_opaque->groups = NULL; - } - - static void iio_dev_release(struct device *device) -@@ -1664,7 +1665,13 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) - kfree(iio_dev_opaque); - return NULL; - } -- dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id); -+ -+ if (dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id)) { -+ ida_simple_remove(&iio_ida, iio_dev_opaque->id); -+ kfree(iio_dev_opaque); -+ return NULL; -+ } -+ - INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); - INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); - -diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c -index b23caa2f2aa1f..93990ff1dfe39 100644 ---- a/drivers/iio/industrialio-trigger.c -+++ b/drivers/iio/industrialio-trigger.c -@@ -556,7 +556,6 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent, - irq_modify_status(trig->subirq_base + i, - IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); - } -- get_device(&trig->dev); - - return trig; - -diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c -index 1830221da48d2..f0bd0ad34f222 100644 ---- a/drivers/iio/light/ltr501.c -+++ b/drivers/iio/light/ltr501.c -@@ -1273,7 +1273,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) - ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, - als_buf, sizeof(als_buf)); - if (ret < 0) -- return ret; -+ goto done; - if (test_bit(0, indio_dev->active_scan_mask)) - scan.channels[j++] = le16_to_cpu(als_buf[1]); - if (test_bit(1, indio_dev->active_scan_mask)) -diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c -index 07e91846307c7..fc63856ed54de 100644 ---- a/drivers/iio/light/stk3310.c -+++ b/drivers/iio/light/stk3310.c -@@ -546,9 +546,8 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) - mutex_lock(&data->lock); - ret = regmap_field_read(data->reg_flag_nf, &dir); - if (ret < 0) { -- dev_err(&data->client->dev, "register read failed\n"); -- mutex_unlock(&data->lock); -- return ret; -+ dev_err(&data->client->dev, "register read failed: %d\n", ret); -+ goto out; - } - event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, - IIO_EV_TYPE_THRESH, -@@ -560,6 +559,7 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) - ret = regmap_field_write(data->reg_flag_psint, 0); - if (ret < 0) - dev_err(&data->client->dev, "failed to reset interrupts\n"); -+out: - mutex_unlock(&data->lock); - - return IRQ_HANDLED; -diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c -index 2dfe4ee99591b..fa78f0a3b53ea 100644 ---- a/drivers/iio/magnetometer/st_magn_i2c.c -+++ b/drivers/iio/magnetometer/st_magn_i2c.c -@@ -102,10 +102,10 @@ static int st_magn_i2c_remove(struct i2c_client *client) - { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - -- st_sensors_power_disable(indio_dev); -- - st_magn_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c -index fba9787963952..ff43cbf61b056 100644 ---- a/drivers/iio/magnetometer/st_magn_spi.c -+++ b/drivers/iio/magnetometer/st_magn_spi.c -@@ -96,10 +96,10 @@ static int st_magn_spi_remove(struct spi_device *spi) - { - struct iio_dev *indio_dev = spi_get_drvdata(spi); - -- st_sensors_power_disable(indio_dev); -- - st_magn_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c -index 52fa98f24478d..6215de677017e 100644 ---- a/drivers/iio/pressure/st_pressure_i2c.c -+++ b/drivers/iio/pressure/st_pressure_i2c.c -@@ -119,10 +119,10 @@ static int st_press_i2c_remove(struct i2c_client *client) - { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - -- st_sensors_power_disable(indio_dev); -- - st_press_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c -index ee393df54cee8..e220cf0b125f1 100644 ---- a/drivers/iio/pressure/st_pressure_spi.c -+++ b/drivers/iio/pressure/st_pressure_spi.c -@@ -102,10 +102,10 @@ static int st_press_spi_remove(struct spi_device *spi) - { - struct iio_dev *indio_dev = spi_get_drvdata(spi); - -- st_sensors_power_disable(indio_dev); -- - st_press_common_remove(indio_dev); - -+ st_sensors_power_disable(indio_dev); -+ - return 0; - } - -@@ -117,6 +117,10 @@ static const struct spi_device_id st_press_id_table[] = { - { LPS33HW_PRESS_DEV_NAME }, - { LPS35HW_PRESS_DEV_NAME }, - { LPS22HH_PRESS_DEV_NAME }, -+ { "lps001wp-press" }, -+ { "lps25h-press", }, -+ { "lps331ap-press" }, -+ { "lps22hb-press" }, - {}, - }; - MODULE_DEVICE_TABLE(spi, st_press_id_table); -diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c -index 33083877cd19d..4353b749ecef2 100644 ---- a/drivers/iio/trigger/stm32-timer-trigger.c -+++ b/drivers/iio/trigger/stm32-timer-trigger.c -@@ -912,6 +912,6 @@ static struct platform_driver stm32_timer_trigger_driver = { - }; - module_platform_driver(stm32_timer_trigger_driver); - --MODULE_ALIAS("platform: stm32-timer-trigger"); -+MODULE_ALIAS("platform:stm32-timer-trigger"); - MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); - MODULE_LICENSE("GPL v2"); -diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c -index 6146c3c1cbe5c..8d709986b88c7 100644 ---- a/drivers/infiniband/core/sysfs.c -+++ b/drivers/infiniband/core/sysfs.c -@@ -757,7 +757,7 @@ static void ib_port_release(struct kobject *kobj) - if (port->hw_stats_data) - kfree(port->hw_stats_data->stats); - kfree(port->hw_stats_data); -- kfree(port); -+ kvfree(port); - } - - static void ib_port_gid_attr_release(struct kobject *kobj) -@@ -1189,7 +1189,7 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, - struct ib_port *p; - int ret; - -- p = kzalloc(struct_size(p, attrs_list, -+ p = kvzalloc(struct_size(p, attrs_list, - attr->gid_tbl_len + attr->pkey_tbl_len), - GFP_KERNEL); - if (!p) -diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c -index 740e6b2efe0e7..d1345d76d9b12 100644 ---- a/drivers/infiniband/core/uverbs_cmd.c -+++ b/drivers/infiniband/core/uverbs_cmd.c -@@ -837,11 +837,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) - new_mr->device = new_pd->device; - new_mr->pd = new_pd; - new_mr->type = IB_MR_TYPE_USER; -- new_mr->dm = NULL; -- new_mr->sig_attrs = NULL; - new_mr->uobject = uobj; - atomic_inc(&new_pd->usecnt); -- new_mr->iova = cmd.hca_va; - new_uobj->object = new_mr; - - rdma_restrack_new(&new_mr->res, RDMA_RESTRACK_MR); -diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c -index 89a2b21976d63..20a46d8731455 100644 ---- a/drivers/infiniband/core/verbs.c -+++ b/drivers/infiniband/core/verbs.c -@@ -1232,6 +1232,9 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd, - INIT_LIST_HEAD(&qp->rdma_mrs); - INIT_LIST_HEAD(&qp->sig_mrs); - -+ qp->send_cq = attr->send_cq; -+ qp->recv_cq = attr->recv_cq; -+ - rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP); - WARN_ONCE(!udata && !caller, "Missing kernel QP owner"); - rdma_restrack_set_name(&qp->res, udata ? NULL : caller); -diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c -index 408dfbcc47b5e..b7ec3a3926785 100644 ---- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c -+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c -@@ -3354,8 +3354,11 @@ static void bnxt_re_process_res_ud_wc(struct bnxt_re_qp *qp, - struct ib_wc *wc, - struct bnxt_qplib_cqe *cqe) - { -+ struct bnxt_re_dev *rdev; -+ u16 vlan_id = 0; - u8 nw_type; - -+ rdev = qp->rdev; - wc->opcode = IB_WC_RECV; - wc->status = __rc_to_ib_wc_status(cqe->status); - -@@ -3367,9 +3370,12 @@ static void bnxt_re_process_res_ud_wc(struct bnxt_re_qp *qp, - memcpy(wc->smac, cqe->smac, ETH_ALEN); - wc->wc_flags |= IB_WC_WITH_SMAC; - if (cqe->flags & CQ_RES_UD_FLAGS_META_FORMAT_VLAN) { -- wc->vlan_id = (cqe->cfa_meta & 0xFFF); -- if (wc->vlan_id < 0x1000) -- wc->wc_flags |= IB_WC_WITH_VLAN; -+ vlan_id = (cqe->cfa_meta & 0xFFF); -+ } -+ /* Mark only if vlan_id is non zero */ -+ if (vlan_id && bnxt_re_check_if_vlan_valid(rdev, vlan_id)) { -+ wc->vlan_id = vlan_id; -+ wc->wc_flags |= IB_WC_WITH_VLAN; - } - nw_type = (cqe->flags & CQ_RES_UD_FLAGS_ROCE_IP_VER_MASK) >> - CQ_RES_UD_FLAGS_ROCE_IP_VER_SFT; -diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c -index d4d4959c2434c..bd153aa7e9ab3 100644 ---- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c -+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c -@@ -707,12 +707,13 @@ int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, - int rc = 0; - - RCFW_CMD_PREP(req, QUERY_SRQ, cmd_flags); -- req.srq_cid = cpu_to_le32(srq->id); - - /* Configure the request */ - sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); - if (!sbuf) - return -ENOMEM; -+ req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; -+ req.srq_cid = cpu_to_le32(srq->id); - sb = sbuf->sb; - rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, - (void *)sbuf, 0); -diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c -index 37273dc0c03ca..b0d587254fe66 100644 ---- a/drivers/infiniband/hw/hfi1/chip.c -+++ b/drivers/infiniband/hw/hfi1/chip.c -@@ -8414,6 +8414,8 @@ static void receive_interrupt_common(struct hfi1_ctxtdata *rcd) - */ - static void __hfi1_rcd_eoi_intr(struct hfi1_ctxtdata *rcd) - { -+ if (!rcd->rcvhdrq) -+ return; - clear_recv_intr(rcd); - if (check_packet_present(rcd)) - force_recv_intr(rcd); -diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c -index de411884386bf..385e6cff0d279 100644 ---- a/drivers/infiniband/hw/hfi1/driver.c -+++ b/drivers/infiniband/hw/hfi1/driver.c -@@ -1011,6 +1011,8 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread) - struct hfi1_packet packet; - int skip_pkt = 0; - -+ if (!rcd->rcvhdrq) -+ return RCV_PKT_OK; - /* Control context will always use the slow path interrupt handler */ - needset = (rcd->ctxt == HFI1_CTRL_CTXT) ? 0 : 1; - -diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c -index e3679d076eaaf..ec2a45c5cf575 100644 ---- a/drivers/infiniband/hw/hfi1/init.c -+++ b/drivers/infiniband/hw/hfi1/init.c -@@ -112,7 +112,6 @@ static int hfi1_create_kctxt(struct hfi1_devdata *dd, - rcd->fast_handler = get_dma_rtail_setting(rcd) ? - handle_receive_interrupt_dma_rtail : - handle_receive_interrupt_nodma_rtail; -- rcd->slow_handler = handle_receive_interrupt; - - hfi1_set_seq_cnt(rcd, 1); - -@@ -333,6 +332,8 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa, - rcd->numa_id = numa; - rcd->rcv_array_groups = dd->rcv_entries.ngroups; - rcd->rhf_rcv_function_map = normal_rhf_rcv_functions; -+ rcd->slow_handler = handle_receive_interrupt; -+ rcd->do_interrupt = rcd->slow_handler; - rcd->msix_intr = CCE_NUM_MSIX_VECTORS; - - mutex_init(&rcd->exp_mutex); -@@ -873,18 +874,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) - if (ret) - goto done; - -- /* allocate dummy tail memory for all receive contexts */ -- dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev, -- sizeof(u64), -- &dd->rcvhdrtail_dummy_dma, -- GFP_KERNEL); -- -- if (!dd->rcvhdrtail_dummy_kvaddr) { -- dd_dev_err(dd, "cannot allocate dummy tail memory\n"); -- ret = -ENOMEM; -- goto done; -- } -- - /* dd->rcd can be NULL if early initialization failed */ - for (i = 0; dd->rcd && i < dd->first_dyn_alloc_ctxt; ++i) { - /* -@@ -897,8 +886,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) - if (!rcd) - continue; - -- rcd->do_interrupt = &handle_receive_interrupt; -- - lastfail = hfi1_create_rcvhdrq(dd, rcd); - if (!lastfail) - lastfail = hfi1_setup_eagerbufs(rcd); -@@ -1119,7 +1106,7 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) - rcd->egrbufs.rcvtids = NULL; - - for (e = 0; e < rcd->egrbufs.alloced; e++) { -- if (rcd->egrbufs.buffers[e].dma) -+ if (rcd->egrbufs.buffers[e].addr) - dma_free_coherent(&dd->pcidev->dev, - rcd->egrbufs.buffers[e].len, - rcd->egrbufs.buffers[e].addr, -@@ -1200,6 +1187,11 @@ void hfi1_free_devdata(struct hfi1_devdata *dd) - dd->tx_opstats = NULL; - kfree(dd->comp_vect); - dd->comp_vect = NULL; -+ if (dd->rcvhdrtail_dummy_kvaddr) -+ dma_free_coherent(&dd->pcidev->dev, sizeof(u64), -+ (void *)dd->rcvhdrtail_dummy_kvaddr, -+ dd->rcvhdrtail_dummy_dma); -+ dd->rcvhdrtail_dummy_kvaddr = NULL; - sdma_clean(dd, dd->num_sdma); - rvt_dealloc_device(&dd->verbs_dev.rdi); - } -@@ -1297,6 +1289,15 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, - goto bail; - } - -+ /* allocate dummy tail memory for all receive contexts */ -+ dd->rcvhdrtail_dummy_kvaddr = -+ dma_alloc_coherent(&dd->pcidev->dev, sizeof(u64), -+ &dd->rcvhdrtail_dummy_dma, GFP_KERNEL); -+ if (!dd->rcvhdrtail_dummy_kvaddr) { -+ ret = -ENOMEM; -+ goto bail; -+ } -+ - atomic_set(&dd->ipoib_rsm_usr_num, 0); - return dd; - -@@ -1504,13 +1505,6 @@ static void cleanup_device_data(struct hfi1_devdata *dd) - - free_credit_return(dd); - -- if (dd->rcvhdrtail_dummy_kvaddr) { -- dma_free_coherent(&dd->pcidev->dev, sizeof(u64), -- (void *)dd->rcvhdrtail_dummy_kvaddr, -- dd->rcvhdrtail_dummy_dma); -- dd->rcvhdrtail_dummy_kvaddr = NULL; -- } -- - /* - * Free any resources still in use (usually just kernel contexts) - * at unload; we do for ctxtcnt, because that's what we allocate. -diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c -index 2b6c24b7b5865..f07d328689d3d 100644 ---- a/drivers/infiniband/hw/hfi1/sdma.c -+++ b/drivers/infiniband/hw/hfi1/sdma.c -@@ -838,8 +838,8 @@ struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd, - if (current->nr_cpus_allowed != 1) - goto out; - -- cpu_id = smp_processor_id(); - rcu_read_lock(); -+ cpu_id = smp_processor_id(); - rht_node = rhashtable_lookup(dd->sdma_rht, &cpu_id, - sdma_rht_params); - -diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c -index d5f3faa1627a4..51dd134952e77 100644 ---- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c -+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c -@@ -33,6 +33,7 @@ - #include <linux/acpi.h> - #include <linux/etherdevice.h> - #include <linux/interrupt.h> -+#include <linux/iopoll.h> - #include <linux/kernel.h> - #include <linux/types.h> - #include <net/addrconf.h> -@@ -1050,9 +1051,14 @@ static u32 hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, - unsigned long instance_stage, - unsigned long reset_stage) - { -+#define HW_RESET_TIMEOUT_US 1000000 -+#define HW_RESET_SLEEP_US 1000 -+ - struct hns_roce_v2_priv *priv = hr_dev->priv; - struct hnae3_handle *handle = priv->handle; - const struct hnae3_ae_ops *ops = handle->ae_algo->ops; -+ unsigned long val; -+ int ret; - - /* When hardware reset is detected, we should stop sending mailbox&cmq& - * doorbell to hardware. If now in .init_instance() function, we should -@@ -1064,7 +1070,11 @@ static u32 hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, - * again. - */ - hr_dev->dis_db = true; -- if (!ops->get_hw_reset_stat(handle)) -+ -+ ret = read_poll_timeout(ops->ae_dev_reset_cnt, val, -+ val > hr_dev->reset_cnt, HW_RESET_SLEEP_US, -+ HW_RESET_TIMEOUT_US, false, handle); -+ if (!ret) - hr_dev->is_reset = true; - - if (!hr_dev->is_reset || reset_stage == HNS_ROCE_STATE_RST_INIT || -@@ -3328,7 +3338,7 @@ static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev, - memset(cq_context, 0, sizeof(*cq_context)); - - hr_reg_write(cq_context, CQC_CQ_ST, V2_CQ_STATE_VALID); -- hr_reg_write(cq_context, CQC_ARM_ST, REG_NXT_CEQE); -+ hr_reg_write(cq_context, CQC_ARM_ST, NO_ARMED); - hr_reg_write(cq_context, CQC_SHIFT, ilog2(hr_cq->cq_depth)); - hr_reg_write(cq_context, CQC_CEQN, hr_cq->vector); - hr_reg_write(cq_context, CQC_CQN, hr_cq->cqn); -@@ -4399,8 +4409,8 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, - mtu = ib_mtu_enum_to_int(ib_mtu); - if (WARN_ON(mtu <= 0)) - return -EINVAL; --#define MAX_LP_MSG_LEN 65536 -- /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 64KB */ -+#define MAX_LP_MSG_LEN 16384 -+ /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 16KB */ - lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu); - if (WARN_ON(lp_pktn_ini >= 0xF)) - return -EINVAL; -@@ -6397,10 +6407,8 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) - if (!hr_dev) - return 0; - -- hr_dev->is_reset = true; - hr_dev->active = false; - hr_dev->dis_db = true; -- - hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN; - - return 0; -diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c -index 7de525a5ccf8c..aa119441eb45c 100644 ---- a/drivers/infiniband/hw/irdma/hw.c -+++ b/drivers/infiniband/hw/irdma/hw.c -@@ -60,6 +60,8 @@ static void irdma_iwarp_ce_handler(struct irdma_sc_cq *iwcq) - { - struct irdma_cq *cq = iwcq->back_cq; - -+ if (!cq->user_mode) -+ cq->armed = false; - if (cq->ibcq.comp_handler) - cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); - } -@@ -146,6 +148,7 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, - qp->flush_code = FLUSH_PROT_ERR; - break; - case IRDMA_AE_AMP_BAD_QP: -+ case IRDMA_AE_WQE_UNEXPECTED_OPCODE: - qp->flush_code = FLUSH_LOC_QP_OP_ERR; - break; - case IRDMA_AE_AMP_BAD_STAG_KEY: -@@ -156,7 +159,6 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, - case IRDMA_AE_PRIV_OPERATION_DENIED: - case IRDMA_AE_IB_INVALID_REQUEST: - case IRDMA_AE_IB_REMOTE_ACCESS_ERROR: -- case IRDMA_AE_IB_REMOTE_OP_ERROR: - qp->flush_code = FLUSH_REM_ACCESS_ERR; - qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; - break; -@@ -184,6 +186,9 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, - case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS: - qp->flush_code = FLUSH_MW_BIND_ERR; - break; -+ case IRDMA_AE_IB_REMOTE_OP_ERROR: -+ qp->flush_code = FLUSH_REM_OP_ERR; -+ break; - default: - qp->flush_code = FLUSH_FATAL_ERR; - break; -diff --git a/drivers/infiniband/hw/irdma/main.h b/drivers/infiniband/hw/irdma/main.h -index b678fe712447e..8b215f3cee891 100644 ---- a/drivers/infiniband/hw/irdma/main.h -+++ b/drivers/infiniband/hw/irdma/main.h -@@ -541,6 +541,7 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, - void (*callback_fcn)(struct irdma_cqp_request *cqp_request), - void *cb_param); - void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request); -+bool irdma_cq_empty(struct irdma_cq *iwcq); - int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event, - void *ptr); - int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, -diff --git a/drivers/infiniband/hw/irdma/pble.c b/drivers/infiniband/hw/irdma/pble.c -index aeeb1c310965d..fed49da770f3b 100644 ---- a/drivers/infiniband/hw/irdma/pble.c -+++ b/drivers/infiniband/hw/irdma/pble.c -@@ -25,8 +25,7 @@ void irdma_destroy_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) - list_del(&chunk->list); - if (chunk->type == PBLE_SD_PAGED) - irdma_pble_free_paged_mem(chunk); -- if (chunk->bitmapbuf) -- kfree(chunk->bitmapmem.va); -+ bitmap_free(chunk->bitmapbuf); - kfree(chunk->chunkmem.va); - } - } -@@ -283,7 +282,6 @@ add_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) - "PBLE: next_fpm_addr = %llx chunk_size[%llu] = 0x%llx\n", - pble_rsrc->next_fpm_addr, chunk->size, chunk->size); - pble_rsrc->unallocated_pble -= (u32)(chunk->size >> 3); -- list_add(&chunk->list, &pble_rsrc->pinfo.clist); - sd_reg_val = (sd_entry_type == IRDMA_SD_TYPE_PAGED) ? - sd_entry->u.pd_table.pd_page_addr.pa : - sd_entry->u.bp.addr.pa; -@@ -295,12 +293,12 @@ add_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) - goto error; - } - -+ list_add(&chunk->list, &pble_rsrc->pinfo.clist); - sd_entry->valid = true; - return 0; - - error: -- if (chunk->bitmapbuf) -- kfree(chunk->bitmapmem.va); -+ bitmap_free(chunk->bitmapbuf); - kfree(chunk->chunkmem.va); - - return ret_code; -diff --git a/drivers/infiniband/hw/irdma/pble.h b/drivers/infiniband/hw/irdma/pble.h -index e1b3b8118a2ca..aa20827dcc9de 100644 ---- a/drivers/infiniband/hw/irdma/pble.h -+++ b/drivers/infiniband/hw/irdma/pble.h -@@ -78,7 +78,6 @@ struct irdma_chunk { - u32 pg_cnt; - enum irdma_alloc_type type; - struct irdma_sc_dev *dev; -- struct irdma_virt_mem bitmapmem; - struct irdma_virt_mem chunkmem; - }; - -diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c -index ac91ea5296db9..feebfe6bf31ad 100644 ---- a/drivers/infiniband/hw/irdma/utils.c -+++ b/drivers/infiniband/hw/irdma/utils.c -@@ -2284,15 +2284,10 @@ enum irdma_status_code irdma_prm_add_pble_mem(struct irdma_pble_prm *pprm, - - sizeofbitmap = (u64)pchunk->size >> pprm->pble_shift; - -- pchunk->bitmapmem.size = sizeofbitmap >> 3; -- pchunk->bitmapmem.va = kzalloc(pchunk->bitmapmem.size, GFP_KERNEL); -- -- if (!pchunk->bitmapmem.va) -+ pchunk->bitmapbuf = bitmap_zalloc(sizeofbitmap, GFP_KERNEL); -+ if (!pchunk->bitmapbuf) - return IRDMA_ERR_NO_MEMORY; - -- pchunk->bitmapbuf = pchunk->bitmapmem.va; -- bitmap_zero(pchunk->bitmapbuf, sizeofbitmap); -- - pchunk->sizeofbitmap = sizeofbitmap; - /* each pble is 8 bytes hence shift by 3 */ - pprm->total_pble_alloc += pchunk->size >> 3; -@@ -2536,3 +2531,18 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event) - ibevent.element.qp = &iwqp->ibqp; - iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context); - } -+ -+bool irdma_cq_empty(struct irdma_cq *iwcq) -+{ -+ struct irdma_cq_uk *ukcq; -+ u64 qword3; -+ __le64 *cqe; -+ u8 polarity; -+ -+ ukcq = &iwcq->sc_cq.cq_uk; -+ cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq); -+ get_64bit_val(cqe, 24, &qword3); -+ polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); -+ -+ return polarity != ukcq->polarity; -+} -diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c -index 102dc9342f2a2..8bbc4620a97a2 100644 ---- a/drivers/infiniband/hw/irdma/verbs.c -+++ b/drivers/infiniband/hw/irdma/verbs.c -@@ -3604,18 +3604,31 @@ static int irdma_req_notify_cq(struct ib_cq *ibcq, - struct irdma_cq *iwcq; - struct irdma_cq_uk *ukcq; - unsigned long flags; -- enum irdma_cmpl_notify cq_notify = IRDMA_CQ_COMPL_EVENT; -+ enum irdma_cmpl_notify cq_notify; -+ bool promo_event = false; -+ int ret = 0; - -+ cq_notify = notify_flags == IB_CQ_SOLICITED ? -+ IRDMA_CQ_COMPL_SOLICITED : IRDMA_CQ_COMPL_EVENT; - iwcq = to_iwcq(ibcq); - ukcq = &iwcq->sc_cq.cq_uk; -- if (notify_flags == IB_CQ_SOLICITED) -- cq_notify = IRDMA_CQ_COMPL_SOLICITED; - - spin_lock_irqsave(&iwcq->lock, flags); -- irdma_uk_cq_request_notification(ukcq, cq_notify); -+ /* Only promote to arm the CQ for any event if the last arm event was solicited. */ -+ if (iwcq->last_notify == IRDMA_CQ_COMPL_SOLICITED && notify_flags != IB_CQ_SOLICITED) -+ promo_event = true; -+ -+ if (!iwcq->armed || promo_event) { -+ iwcq->armed = true; -+ iwcq->last_notify = cq_notify; -+ irdma_uk_cq_request_notification(ukcq, cq_notify); -+ } -+ -+ if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && !irdma_cq_empty(iwcq)) -+ ret = 1; - spin_unlock_irqrestore(&iwcq->lock, flags); - -- return 0; -+ return ret; - } - - static int irdma_roce_port_immutable(struct ib_device *ibdev, u32 port_num, -diff --git a/drivers/infiniband/hw/irdma/verbs.h b/drivers/infiniband/hw/irdma/verbs.h -index 5c244cd321a3a..d0fdef8d09ead 100644 ---- a/drivers/infiniband/hw/irdma/verbs.h -+++ b/drivers/infiniband/hw/irdma/verbs.h -@@ -110,6 +110,8 @@ struct irdma_cq { - u16 cq_size; - u16 cq_num; - bool user_mode; -+ bool armed; -+ enum irdma_cmpl_notify last_notify; - u32 polled_cmpls; - u32 cq_mem_size; - struct irdma_dma_mem kmem; -diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c -index f367f4a4abffc..aec2e1851fa70 100644 ---- a/drivers/infiniband/hw/mlx4/main.c -+++ b/drivers/infiniband/hw/mlx4/main.c -@@ -2217,6 +2217,11 @@ static const struct ib_device_ops mlx4_ib_hw_stats_ops = { - .get_hw_stats = mlx4_ib_get_hw_stats, - }; - -+static const struct ib_device_ops mlx4_ib_hw_stats_ops1 = { -+ .alloc_hw_device_stats = mlx4_ib_alloc_hw_device_stats, -+ .get_hw_stats = mlx4_ib_get_hw_stats, -+}; -+ - static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev) - { - struct mlx4_ib_diag_counters *diag = ibdev->diag_counters; -@@ -2229,9 +2234,16 @@ static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev) - return 0; - - for (i = 0; i < MLX4_DIAG_COUNTERS_TYPES; i++) { -- /* i == 1 means we are building port counters */ -- if (i && !per_port) -- continue; -+ /* -+ * i == 1 means we are building port counters, set a different -+ * stats ops without port stats callback. -+ */ -+ if (i && !per_port) { -+ ib_set_device_ops(&ibdev->ib_dev, -+ &mlx4_ib_hw_stats_ops1); -+ -+ return 0; -+ } - - ret = __mlx4_ib_alloc_diag_counters(ibdev, &diag[i].name, - &diag[i].offset, -diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c -index 8662f462e2a5f..3a1a4ac9dd33d 100644 ---- a/drivers/infiniband/hw/mlx4/qp.c -+++ b/drivers/infiniband/hw/mlx4/qp.c -@@ -1099,8 +1099,10 @@ static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr, - if (dev->steering_support == - MLX4_STEERING_MODE_DEVICE_MANAGED) - qp->flags |= MLX4_IB_QP_NETIF; -- else -+ else { -+ err = -EINVAL; - goto err; -+ } - } - - err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp); -diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h -index bf20a388eabe1..6204ae2caef58 100644 ---- a/drivers/infiniband/hw/mlx5/mlx5_ib.h -+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h -@@ -641,7 +641,6 @@ struct mlx5_ib_mr { - - /* User MR data */ - struct mlx5_cache_ent *cache_ent; -- struct ib_umem *umem; - - /* This is zero'd when the MR is allocated */ - union { -@@ -653,7 +652,7 @@ struct mlx5_ib_mr { - struct list_head list; - }; - -- /* Used only by kernel MRs (umem == NULL) */ -+ /* Used only by kernel MRs */ - struct { - void *descs; - void *descs_alloc; -@@ -675,8 +674,9 @@ struct mlx5_ib_mr { - int data_length; - }; - -- /* Used only by User MRs (umem != NULL) */ -+ /* Used only by User MRs */ - struct { -+ struct ib_umem *umem; - unsigned int page_shift; - /* Current access_flags */ - int access_flags; -diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c -index 22e2f4d79743d..69b2ce4c292ae 100644 ---- a/drivers/infiniband/hw/mlx5/mr.c -+++ b/drivers/infiniband/hw/mlx5/mr.c -@@ -1911,19 +1911,18 @@ err: - return ret; - } - --static void --mlx5_free_priv_descs(struct mlx5_ib_mr *mr) -+static void mlx5_free_priv_descs(struct mlx5_ib_mr *mr) - { -- if (!mr->umem && mr->descs) { -- struct ib_device *device = mr->ibmr.device; -- int size = mr->max_descs * mr->desc_size; -- struct mlx5_ib_dev *dev = to_mdev(device); -+ struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device); -+ int size = mr->max_descs * mr->desc_size; - -- dma_unmap_single(&dev->mdev->pdev->dev, mr->desc_map, size, -- DMA_TO_DEVICE); -- kfree(mr->descs_alloc); -- mr->descs = NULL; -- } -+ if (!mr->descs) -+ return; -+ -+ dma_unmap_single(&dev->mdev->pdev->dev, mr->desc_map, size, -+ DMA_TO_DEVICE); -+ kfree(mr->descs_alloc); -+ mr->descs = NULL; - } - - int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) -@@ -1999,7 +1998,8 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) - if (mr->cache_ent) { - mlx5_mr_cache_free(dev, mr); - } else { -- mlx5_free_priv_descs(mr); -+ if (!udata) -+ mlx5_free_priv_descs(mr); - kfree(mr); - } - return 0; -@@ -2086,7 +2086,6 @@ static struct mlx5_ib_mr *mlx5_ib_alloc_pi_mr(struct ib_pd *pd, - if (err) - goto err_free_in; - -- mr->umem = NULL; - kfree(in); - - return mr; -@@ -2213,7 +2212,6 @@ static struct ib_mr *__mlx5_ib_alloc_mr(struct ib_pd *pd, - } - - mr->ibmr.device = pd->device; -- mr->umem = NULL; - - switch (mr_type) { - case IB_MR_TYPE_MEM_REG: -diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c -index dcb3653db72d7..3d4e4a766574a 100644 ---- a/drivers/infiniband/hw/qedr/verbs.c -+++ b/drivers/infiniband/hw/qedr/verbs.c -@@ -2744,15 +2744,18 @@ int qedr_query_qp(struct ib_qp *ibqp, - int rc = 0; - - memset(¶ms, 0, sizeof(params)); -- -- rc = dev->ops->rdma_query_qp(dev->rdma_ctx, qp->qed_qp, ¶ms); -- if (rc) -- goto err; -- - memset(qp_attr, 0, sizeof(*qp_attr)); - memset(qp_init_attr, 0, sizeof(*qp_init_attr)); - -- qp_attr->qp_state = qedr_get_ibqp_state(params.state); -+ if (qp->qp_type != IB_QPT_GSI) { -+ rc = dev->ops->rdma_query_qp(dev->rdma_ctx, qp->qed_qp, ¶ms); -+ if (rc) -+ goto err; -+ qp_attr->qp_state = qedr_get_ibqp_state(params.state); -+ } else { -+ qp_attr->qp_state = qedr_get_ibqp_state(QED_ROCE_QP_STATE_RTS); -+ } -+ - qp_attr->cur_qp_state = qedr_get_ibqp_state(params.state); - qp_attr->path_mtu = ib_mtu_int_to_enum(params.mtu); - qp_attr->path_mig_state = IB_MIG_MIGRATED; -diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h -index f0c954575bdec..4fd73b51fabf2 100644 ---- a/drivers/infiniband/sw/rxe/rxe_loc.h -+++ b/drivers/infiniband/sw/rxe/rxe_loc.h -@@ -86,6 +86,7 @@ struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key, - int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length); - int advance_dma_data(struct rxe_dma_info *dma, unsigned int length); - int rxe_invalidate_mr(struct rxe_qp *qp, u32 rkey); -+int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe); - int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); - void rxe_mr_cleanup(struct rxe_pool_entry *arg); - -diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c -index 5890a82462161..bedcf15aaea75 100644 ---- a/drivers/infiniband/sw/rxe/rxe_mr.c -+++ b/drivers/infiniband/sw/rxe/rxe_mr.c -@@ -48,8 +48,14 @@ static void rxe_mr_init(int access, struct rxe_mr *mr) - u32 lkey = mr->pelem.index << 8 | rxe_get_next_key(-1); - u32 rkey = (access & IB_ACCESS_REMOTE) ? lkey : 0; - -- mr->ibmr.lkey = lkey; -- mr->ibmr.rkey = rkey; -+ /* set ibmr->l/rkey and also copy into private l/rkey -+ * for user MRs these will always be the same -+ * for cases where caller 'owns' the key portion -+ * they may be different until REG_MR WQE is executed. -+ */ -+ mr->lkey = mr->ibmr.lkey = lkey; -+ mr->rkey = mr->ibmr.rkey = rkey; -+ - mr->state = RXE_MR_STATE_INVALID; - mr->type = RXE_MR_TYPE_NONE; - mr->map_shift = ilog2(RXE_BUF_PER_MAP); -@@ -191,10 +197,8 @@ int rxe_mr_init_fast(struct rxe_pd *pd, int max_pages, struct rxe_mr *mr) - { - int err; - -- rxe_mr_init(0, mr); -- -- /* In fastreg, we also set the rkey */ -- mr->ibmr.rkey = mr->ibmr.lkey; -+ /* always allow remote access for FMRs */ -+ rxe_mr_init(IB_ACCESS_REMOTE, mr); - - err = rxe_mr_alloc(mr, max_pages); - if (err) -@@ -507,8 +511,8 @@ struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key, - if (!mr) - return NULL; - -- if (unlikely((type == RXE_LOOKUP_LOCAL && mr_lkey(mr) != key) || -- (type == RXE_LOOKUP_REMOTE && mr_rkey(mr) != key) || -+ if (unlikely((type == RXE_LOOKUP_LOCAL && mr->lkey != key) || -+ (type == RXE_LOOKUP_REMOTE && mr->rkey != key) || - mr_pd(mr) != pd || (access && !(access & mr->access)) || - mr->state != RXE_MR_STATE_VALID)) { - rxe_drop_ref(mr); -@@ -531,9 +535,9 @@ int rxe_invalidate_mr(struct rxe_qp *qp, u32 rkey) - goto err; - } - -- if (rkey != mr->ibmr.rkey) { -- pr_err("%s: rkey (%#x) doesn't match mr->ibmr.rkey (%#x)\n", -- __func__, rkey, mr->ibmr.rkey); -+ if (rkey != mr->rkey) { -+ pr_err("%s: rkey (%#x) doesn't match mr->rkey (%#x)\n", -+ __func__, rkey, mr->rkey); - ret = -EINVAL; - goto err_drop_ref; - } -@@ -554,6 +558,49 @@ err: - return ret; - } - -+/* user can (re)register fast MR by executing a REG_MR WQE. -+ * user is expected to hold a reference on the ib mr until the -+ * WQE completes. -+ * Once a fast MR is created this is the only way to change the -+ * private keys. It is the responsibility of the user to maintain -+ * the ib mr keys in sync with rxe mr keys. -+ */ -+int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe) -+{ -+ struct rxe_mr *mr = to_rmr(wqe->wr.wr.reg.mr); -+ u32 key = wqe->wr.wr.reg.key; -+ u32 access = wqe->wr.wr.reg.access; -+ -+ /* user can only register MR in free state */ -+ if (unlikely(mr->state != RXE_MR_STATE_FREE)) { -+ pr_warn("%s: mr->lkey = 0x%x not free\n", -+ __func__, mr->lkey); -+ return -EINVAL; -+ } -+ -+ /* user can only register mr with qp in same protection domain */ -+ if (unlikely(qp->ibqp.pd != mr->ibmr.pd)) { -+ pr_warn("%s: qp->pd and mr->pd don't match\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ /* user is only allowed to change key portion of l/rkey */ -+ if (unlikely((mr->lkey & ~0xff) != (key & ~0xff))) { -+ pr_warn("%s: key = 0x%x has wrong index mr->lkey = 0x%x\n", -+ __func__, key, mr->lkey); -+ return -EINVAL; -+ } -+ -+ mr->access = access; -+ mr->lkey = key; -+ mr->rkey = (access & IB_ACCESS_REMOTE) ? key : 0; -+ mr->iova = wqe->wr.wr.reg.mr->iova; -+ mr->state = RXE_MR_STATE_VALID; -+ -+ return 0; -+} -+ - int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) - { - struct rxe_mr *mr = to_rmr(ibmr); -diff --git a/drivers/infiniband/sw/rxe/rxe_mw.c b/drivers/infiniband/sw/rxe/rxe_mw.c -index 5ba77df7598ed..a5e2ea7d80f02 100644 ---- a/drivers/infiniband/sw/rxe/rxe_mw.c -+++ b/drivers/infiniband/sw/rxe/rxe_mw.c -@@ -21,7 +21,7 @@ int rxe_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata) - } - - rxe_add_index(mw); -- ibmw->rkey = (mw->pelem.index << 8) | rxe_get_next_key(-1); -+ mw->rkey = ibmw->rkey = (mw->pelem.index << 8) | rxe_get_next_key(-1); - mw->state = (mw->ibmw.type == IB_MW_TYPE_2) ? - RXE_MW_STATE_FREE : RXE_MW_STATE_VALID; - spin_lock_init(&mw->lock); -@@ -71,6 +71,8 @@ int rxe_dealloc_mw(struct ib_mw *ibmw) - static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - struct rxe_mw *mw, struct rxe_mr *mr) - { -+ u32 key = wqe->wr.wr.mw.rkey & 0xff; -+ - if (mw->ibmw.type == IB_MW_TYPE_1) { - if (unlikely(mw->state != RXE_MW_STATE_VALID)) { - pr_err_once( -@@ -108,7 +110,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - } - } - -- if (unlikely((wqe->wr.wr.mw.rkey & 0xff) == (mw->ibmw.rkey & 0xff))) { -+ if (unlikely(key == (mw->rkey & 0xff))) { - pr_err_once("attempt to bind MW with same key\n"); - return -EINVAL; - } -@@ -161,13 +163,9 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - static void rxe_do_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - struct rxe_mw *mw, struct rxe_mr *mr) - { -- u32 rkey; -- u32 new_rkey; -- -- rkey = mw->ibmw.rkey; -- new_rkey = (rkey & 0xffffff00) | (wqe->wr.wr.mw.rkey & 0x000000ff); -+ u32 key = wqe->wr.wr.mw.rkey & 0xff; - -- mw->ibmw.rkey = new_rkey; -+ mw->rkey = (mw->rkey & ~0xff) | key; - mw->access = wqe->wr.wr.mw.access; - mw->state = RXE_MW_STATE_VALID; - mw->addr = wqe->wr.wr.mw.addr; -@@ -197,29 +195,29 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe) - struct rxe_mw *mw; - struct rxe_mr *mr; - struct rxe_dev *rxe = to_rdev(qp->ibqp.device); -+ u32 mw_rkey = wqe->wr.wr.mw.mw_rkey; -+ u32 mr_lkey = wqe->wr.wr.mw.mr_lkey; - unsigned long flags; - -- mw = rxe_pool_get_index(&rxe->mw_pool, -- wqe->wr.wr.mw.mw_rkey >> 8); -+ mw = rxe_pool_get_index(&rxe->mw_pool, mw_rkey >> 8); - if (unlikely(!mw)) { - ret = -EINVAL; - goto err; - } - -- if (unlikely(mw->ibmw.rkey != wqe->wr.wr.mw.mw_rkey)) { -+ if (unlikely(mw->rkey != mw_rkey)) { - ret = -EINVAL; - goto err_drop_mw; - } - - if (likely(wqe->wr.wr.mw.length)) { -- mr = rxe_pool_get_index(&rxe->mr_pool, -- wqe->wr.wr.mw.mr_lkey >> 8); -+ mr = rxe_pool_get_index(&rxe->mr_pool, mr_lkey >> 8); - if (unlikely(!mr)) { - ret = -EINVAL; - goto err_drop_mw; - } - -- if (unlikely(mr->ibmr.lkey != wqe->wr.wr.mw.mr_lkey)) { -+ if (unlikely(mr->lkey != mr_lkey)) { - ret = -EINVAL; - goto err_drop_mr; - } -@@ -292,7 +290,7 @@ int rxe_invalidate_mw(struct rxe_qp *qp, u32 rkey) - goto err; - } - -- if (rkey != mw->ibmw.rkey) { -+ if (rkey != mw->rkey) { - ret = -EINVAL; - goto err_drop_ref; - } -@@ -323,7 +321,7 @@ struct rxe_mw *rxe_lookup_mw(struct rxe_qp *qp, int access, u32 rkey) - if (!mw) - return NULL; - -- if (unlikely((rxe_mw_rkey(mw) != rkey) || rxe_mw_pd(mw) != pd || -+ if (unlikely((mw->rkey != rkey) || rxe_mw_pd(mw) != pd || - (mw->ibmw.type == IB_MW_TYPE_2 && mw->qp != qp) || - (mw->length == 0) || - (access && !(access & mw->access)) || -diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h -index 742e6ec93686c..b5a70cbe94aac 100644 ---- a/drivers/infiniband/sw/rxe/rxe_param.h -+++ b/drivers/infiniband/sw/rxe/rxe_param.h -@@ -113,7 +113,7 @@ enum rxe_device_param { - /* default/initial rxe port parameters */ - enum rxe_port_param { - RXE_PORT_GID_TBL_LEN = 1024, -- RXE_PORT_PORT_CAP_FLAGS = RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP, -+ RXE_PORT_PORT_CAP_FLAGS = IB_PORT_CM_SUP, - RXE_PORT_MAX_MSG_SZ = 0x800000, - RXE_PORT_BAD_PKEY_CNTR = 0, - RXE_PORT_QKEY_VIOL_CNTR = 0, -diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c -index 1ab6af7ddb254..ed326d82725cd 100644 ---- a/drivers/infiniband/sw/rxe/rxe_qp.c -+++ b/drivers/infiniband/sw/rxe/rxe_qp.c -@@ -367,6 +367,7 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd, - - err2: - rxe_queue_cleanup(qp->sq.queue); -+ qp->sq.queue = NULL; - err1: - qp->pd = NULL; - qp->rcq = NULL; -diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c -index 3894197a82f62..fc996fd31e589 100644 ---- a/drivers/infiniband/sw/rxe/rxe_req.c -+++ b/drivers/infiniband/sw/rxe/rxe_req.c -@@ -572,7 +572,6 @@ static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe, - static int rxe_do_local_ops(struct rxe_qp *qp, struct rxe_send_wqe *wqe) - { - u8 opcode = wqe->wr.opcode; -- struct rxe_mr *mr; - u32 rkey; - int ret; - -@@ -590,14 +589,11 @@ static int rxe_do_local_ops(struct rxe_qp *qp, struct rxe_send_wqe *wqe) - } - break; - case IB_WR_REG_MR: -- mr = to_rmr(wqe->wr.wr.reg.mr); -- rxe_add_ref(mr); -- mr->state = RXE_MR_STATE_VALID; -- mr->access = wqe->wr.wr.reg.access; -- mr->ibmr.lkey = wqe->wr.wr.reg.key; -- mr->ibmr.rkey = wqe->wr.wr.reg.key; -- mr->iova = wqe->wr.wr.reg.mr->iova; -- rxe_drop_ref(mr); -+ ret = rxe_reg_fast_mr(qp, wqe); -+ if (unlikely(ret)) { -+ wqe->status = IB_WC_LOC_QP_OP_ERR; -+ return ret; -+ } - break; - case IB_WR_BIND_MW: - ret = rxe_bind_mw(qp, wqe); -diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h -index ac2a2148027f4..d90b1d77de347 100644 ---- a/drivers/infiniband/sw/rxe/rxe_verbs.h -+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h -@@ -313,6 +313,8 @@ struct rxe_mr { - - struct ib_umem *umem; - -+ u32 lkey; -+ u32 rkey; - enum rxe_mr_state state; - enum rxe_mr_type type; - u64 va; -@@ -350,6 +352,7 @@ struct rxe_mw { - enum rxe_mw_state state; - struct rxe_qp *qp; /* Type 2 only */ - struct rxe_mr *mr; -+ u32 rkey; - int access; - u64 addr; - u64 length; -@@ -474,26 +477,11 @@ static inline struct rxe_pd *mr_pd(struct rxe_mr *mr) - return to_rpd(mr->ibmr.pd); - } - --static inline u32 mr_lkey(struct rxe_mr *mr) --{ -- return mr->ibmr.lkey; --} -- --static inline u32 mr_rkey(struct rxe_mr *mr) --{ -- return mr->ibmr.rkey; --} -- - static inline struct rxe_pd *rxe_mw_pd(struct rxe_mw *mw) - { - return to_rpd(mw->ibmw.pd); - } - --static inline u32 rxe_mw_rkey(struct rxe_mw *mw) --{ -- return mw->ibmw.rkey; --} -- - int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name); - - void rxe_mc_cleanup(struct rxe_pool_entry *arg); -diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c -index 6c554c11a7ac3..ea58805c480fa 100644 ---- a/drivers/input/joystick/iforce/iforce-usb.c -+++ b/drivers/input/joystick/iforce/iforce-usb.c -@@ -92,7 +92,7 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 id, - id, - USB_TYPE_VENDOR | USB_DIR_IN | - USB_RECIP_INTERFACE, -- 0, 0, buf, IFORCE_MAX_LENGTH, HZ); -+ 0, 0, buf, IFORCE_MAX_LENGTH, 1000); - if (status < 0) { - dev_err(&iforce_usb->intf->dev, - "usb_submit_urb failed: %d\n", status); -diff --git a/drivers/input/misc/ariel-pwrbutton.c b/drivers/input/misc/ariel-pwrbutton.c -index 17bbaac8b80c8..cdc80715b5fd6 100644 ---- a/drivers/input/misc/ariel-pwrbutton.c -+++ b/drivers/input/misc/ariel-pwrbutton.c -@@ -149,12 +149,19 @@ static const struct of_device_id ariel_pwrbutton_of_match[] = { - }; - MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match); - -+static const struct spi_device_id ariel_pwrbutton_spi_ids[] = { -+ { .name = "wyse-ariel-ec-input" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(spi, ariel_pwrbutton_spi_ids); -+ - static struct spi_driver ariel_pwrbutton_driver = { - .driver = { - .name = "dell-wyse-ariel-ec-input", - .of_match_table = ariel_pwrbutton_of_match, - }, - .probe = ariel_pwrbutton_probe, -+ .id_table = ariel_pwrbutton_spi_ids, - }; - module_spi_driver(ariel_pwrbutton_driver); - -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 2d0bc029619ff..956d9cd347964 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -517,6 +517,19 @@ static void elantech_report_trackpoint(struct psmouse *psmouse, - case 0x16008020U: - case 0x26800010U: - case 0x36808000U: -+ -+ /* -+ * This firmware misreport coordinates for trackpoint -+ * occasionally. Discard packets outside of [-127, 127] range -+ * to prevent cursor jumps. -+ */ -+ if (packet[4] == 0x80 || packet[5] == 0x80 || -+ packet[1] >> 7 == packet[4] >> 7 || -+ packet[2] >> 7 == packet[5] >> 7) { -+ elantech_debug("discarding packet [%6ph]\n", packet); -+ break; -+ -+ } - x = packet[4] - (int)((packet[1]^0x80) << 1); - y = (int)((packet[2]^0x80) << 1) - packet[5]; - -diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h -index a5a0035536462..aedd055410443 100644 ---- a/drivers/input/serio/i8042-x86ia64io.h -+++ b/drivers/input/serio/i8042-x86ia64io.h -@@ -272,6 +272,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), - }, - }, -+ { -+ /* Fujitsu Lifebook T725 laptop */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"), -+ }, -+ }, - { - /* Fujitsu Lifebook U745 */ - .matches = { -@@ -840,6 +847,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"), - }, - }, -+ { -+ /* Fujitsu Lifebook T725 laptop */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"), -+ }, -+ }, - { - /* Fujitsu U574 laptop */ - /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ -diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c -index 6abae665ca71d..9d1dea6996a22 100644 ---- a/drivers/input/touchscreen/st1232.c -+++ b/drivers/input/touchscreen/st1232.c -@@ -92,7 +92,7 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts) - unsigned int retries; - int error; - -- for (retries = 10; retries; retries--) { -+ for (retries = 100; retries; retries--) { - error = st1232_ts_read_data(ts, REG_STATUS, 1); - if (!error) { - switch (ts->read_buf[0]) { -diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c -index a9e568276c99f..a45c5536d2506 100644 ---- a/drivers/iommu/amd/iommu_v2.c -+++ b/drivers/iommu/amd/iommu_v2.c -@@ -928,10 +928,8 @@ static int __init amd_iommu_v2_init(void) - { - int ret; - -- pr_info("AMD IOMMUv2 driver by Joerg Roedel <jroedel@suse.de>\n"); -- - if (!amd_iommu_v2_supported()) { -- pr_info("AMD IOMMUv2 functionality not available on this system\n"); -+ pr_info("AMD IOMMUv2 functionality not available on this system - This is not a bug.\n"); - /* - * Load anyway to provide the symbols to other modules - * which may use AMD IOMMUv2 optionally. -@@ -946,6 +944,8 @@ static int __init amd_iommu_v2_init(void) - - amd_iommu_register_ppr_notifier(&ppr_nb); - -+ pr_info("AMD IOMMUv2 loaded and initialized\n"); -+ - return 0; - - out: -diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c -index fdfa39ec2a4d4..ad69eeb5ac5ba 100644 ---- a/drivers/iommu/apple-dart.c -+++ b/drivers/iommu/apple-dart.c -@@ -70,6 +70,8 @@ - #define DART_ERROR_ADDR_HI 0x54 - #define DART_ERROR_ADDR_LO 0x50 - -+#define DART_STREAMS_ENABLE 0xfc -+ - #define DART_TCR(sid) (0x100 + 4 * (sid)) - #define DART_TCR_TRANSLATE_ENABLE BIT(7) - #define DART_TCR_BYPASS0_ENABLE BIT(8) -@@ -301,6 +303,9 @@ static int apple_dart_hw_reset(struct apple_dart *dart) - apple_dart_hw_disable_dma(&stream_map); - apple_dart_hw_clear_all_ttbrs(&stream_map); - -+ /* enable all streams globally since TCR is used to control isolation */ -+ writel(DART_STREAM_ALL, dart->regs + DART_STREAMS_ENABLE); -+ - /* clear any pending errors before the interrupt is unmasked */ - writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR); - -diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c -index 896bea04c347e..2d60216440009 100644 ---- a/drivers/iommu/dma-iommu.c -+++ b/drivers/iommu/dma-iommu.c -@@ -593,6 +593,9 @@ static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys, - memset(padding_start, 0, padding_size); - } - -+ if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) -+ arch_sync_dma_for_device(phys, org_size, dir); -+ - iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask); - if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys)) - swiotlb_tbl_unmap_single(dev, phys, org_size, dir, attrs); -@@ -828,17 +831,13 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg; - int i; - -- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) -- return; -- -- for_each_sg(sgl, sg, nelems, i) { -- if (!dev_is_dma_coherent(dev)) -+ if (dev_is_untrusted(dev)) -+ for_each_sg(sgl, sg, nelems, i) -+ iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg), -+ sg->length, dir); -+ else if (!dev_is_dma_coherent(dev)) -+ for_each_sg(sgl, sg, nelems, i) - arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir); -- -- if (is_swiotlb_buffer(dev, sg_phys(sg))) -- swiotlb_sync_single_for_cpu(dev, sg_phys(sg), -- sg->length, dir); -- } - } - - static void iommu_dma_sync_sg_for_device(struct device *dev, -@@ -848,17 +847,14 @@ static void iommu_dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg; - int i; - -- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) -- return; -- -- for_each_sg(sgl, sg, nelems, i) { -- if (is_swiotlb_buffer(dev, sg_phys(sg))) -- swiotlb_sync_single_for_device(dev, sg_phys(sg), -- sg->length, dir); -- -- if (!dev_is_dma_coherent(dev)) -+ if (dev_is_untrusted(dev)) -+ for_each_sg(sgl, sg, nelems, i) -+ iommu_dma_sync_single_for_device(dev, -+ sg_dma_address(sg), -+ sg->length, dir); -+ else if (!dev_is_dma_coherent(dev)) -+ for_each_sg(sgl, sg, nelems, i) - arch_sync_dma_for_device(sg_phys(sg), sg->length, dir); -- } - } - - static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, -@@ -867,14 +863,9 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, - { - phys_addr_t phys = page_to_phys(page) + offset; - bool coherent = dev_is_dma_coherent(dev); -- dma_addr_t dma_handle; - -- dma_handle = __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev), -+ return __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev), - coherent, dir, attrs); -- if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) && -- dma_handle != DMA_MAPPING_ERROR) -- arch_sync_dma_for_device(phys, size, dir); -- return dma_handle; - } - - static void iommu_dma_unmap_page(struct device *dev, dma_addr_t dma_handle, -@@ -1016,15 +1007,16 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, - - if (static_branch_unlikely(&iommu_deferred_attach_enabled)) { - ret = iommu_deferred_attach(dev, domain); -- goto out; -+ if (ret) -+ goto out; - } - -- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) -- iommu_dma_sync_sg_for_device(dev, sg, nents, dir); -- - if (dev_is_untrusted(dev)) - return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs); - -+ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) -+ iommu_dma_sync_sg_for_device(dev, sg, nents, dir); -+ - /* - * Work out how much IOVA space we need, and align the segments to - * IOVA granules for the IOMMU driver to handle. With some clever -diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c -index d75f59ae28e6e..78f8c8e6803e9 100644 ---- a/drivers/iommu/intel/iommu.c -+++ b/drivers/iommu/intel/iommu.c -@@ -412,6 +412,7 @@ static int __init intel_iommu_setup(char *str) - { - if (!str) - return -EINVAL; -+ - while (*str) { - if (!strncmp(str, "on", 2)) { - dmar_disabled = 0; -@@ -441,13 +442,16 @@ static int __init intel_iommu_setup(char *str) - } else if (!strncmp(str, "tboot_noforce", 13)) { - pr_info("Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n"); - intel_iommu_tboot_noforce = 1; -+ } else { -+ pr_notice("Unknown option - '%s'\n", str); - } - - str += strcspn(str, ","); - while (*str == ',') - str++; - } -- return 0; -+ -+ return 1; - } - __setup("intel_iommu=", intel_iommu_setup); - -@@ -1222,13 +1226,11 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level, - pte = &pte[pfn_level_offset(pfn, level)]; - - do { -- unsigned long level_pfn; -+ unsigned long level_pfn = pfn & level_mask(level); - - if (!dma_pte_present(pte)) - goto next; - -- level_pfn = pfn & level_mask(level); -- - /* If range covers entire pagetable, free it */ - if (start_pfn <= level_pfn && - last_pfn >= level_pfn + level_size(level) - 1) { -@@ -1249,7 +1251,7 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level, - freelist); - } - next: -- pfn += level_size(level); -+ pfn = level_pfn + level_size(level); - } while (!first_pte_in_page(++pte) && pfn <= last_pfn); - - if (first_pte) -diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c -index d837adfd1da55..25b834104790c 100644 ---- a/drivers/iommu/mtk_iommu.c -+++ b/drivers/iommu/mtk_iommu.c -@@ -550,7 +550,9 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, - phys_addr_t pa; - - pa = dom->iop->iova_to_phys(dom->iop, iova); -- if (dom->data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE) -+ if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) && -+ dom->data->enable_4GB && -+ pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE) - pa &= ~BIT_ULL(32); - - return pa; -diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c -index 5cb260820eda6..7f23ad61c094f 100644 ---- a/drivers/iommu/rockchip-iommu.c -+++ b/drivers/iommu/rockchip-iommu.c -@@ -200,8 +200,8 @@ static inline phys_addr_t rk_dte_pt_address(u32 dte) - #define DTE_HI_MASK2 GENMASK(7, 4) - #define DTE_HI_SHIFT1 24 /* shift bit 8 to bit 32 */ - #define DTE_HI_SHIFT2 32 /* shift bit 4 to bit 36 */ --#define PAGE_DESC_HI_MASK1 GENMASK_ULL(39, 36) --#define PAGE_DESC_HI_MASK2 GENMASK_ULL(35, 32) -+#define PAGE_DESC_HI_MASK1 GENMASK_ULL(35, 32) -+#define PAGE_DESC_HI_MASK2 GENMASK_ULL(39, 36) - - static inline phys_addr_t rk_dte_pt_address_v2(u32 dte) - { -diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c -index 53e0fb0562c11..c91ddb0cf1448 100644 ---- a/drivers/irqchip/irq-armada-370-xp.c -+++ b/drivers/irqchip/irq-armada-370-xp.c -@@ -232,16 +232,12 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, - int hwirq, i; - - mutex_lock(&msi_used_lock); -+ hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR, -+ order_base_2(nr_irqs)); -+ mutex_unlock(&msi_used_lock); - -- hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR, -- 0, nr_irqs, 0); -- if (hwirq >= PCI_MSI_DOORBELL_NR) { -- mutex_unlock(&msi_used_lock); -+ if (hwirq < 0) - return -ENOSPC; -- } -- -- bitmap_set(msi_used, hwirq, nr_irqs); -- mutex_unlock(&msi_used_lock); - - for (i = 0; i < nr_irqs; i++) { - irq_domain_set_info(domain, virq + i, hwirq + i, -@@ -250,7 +246,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, - NULL, NULL); - } - -- return hwirq; -+ return 0; - } - - static void armada_370_xp_msi_free(struct irq_domain *domain, -@@ -259,7 +255,7 @@ static void armada_370_xp_msi_free(struct irq_domain *domain, - struct irq_data *d = irq_domain_get_irq_data(domain, virq); - - mutex_lock(&msi_used_lock); -- bitmap_clear(msi_used, d->hwirq, nr_irqs); -+ bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs)); - mutex_unlock(&msi_used_lock); - } - -diff --git a/drivers/irqchip/irq-aspeed-scu-ic.c b/drivers/irqchip/irq-aspeed-scu-ic.c -index f3c6855a4cefb..18b77c3e6db4b 100644 ---- a/drivers/irqchip/irq-aspeed-scu-ic.c -+++ b/drivers/irqchip/irq-aspeed-scu-ic.c -@@ -76,8 +76,8 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc) - generic_handle_domain_irq(scu_ic->irq_domain, - bit - scu_ic->irq_shift); - -- regmap_update_bits(scu_ic->scu, scu_ic->reg, mask, -- BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); -+ regmap_write_bits(scu_ic->scu, scu_ic->reg, mask, -+ BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); - } - - chained_irq_exit(chip, desc); -diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c -index e3483789f4df3..1bd0621c4ce2a 100644 ---- a/drivers/irqchip/irq-bcm6345-l1.c -+++ b/drivers/irqchip/irq-bcm6345-l1.c -@@ -140,7 +140,7 @@ static void bcm6345_l1_irq_handle(struct irq_desc *desc) - for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { - irq = irq_linear_revmap(intc->domain, base + hwirq); - if (irq) -- do_IRQ(irq); -+ generic_handle_irq(irq); - else - spurious_interrupt(); - } -diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c -index eb0882d153666..0cb584d9815b9 100644 ---- a/drivers/irqchip/irq-gic-v3-its.c -+++ b/drivers/irqchip/irq-gic-v3-its.c -@@ -742,7 +742,7 @@ static struct its_collection *its_build_invall_cmd(struct its_node *its, - - its_fixup_cmd(cmd); - -- return NULL; -+ return desc->its_invall_cmd.col; - } - - static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, -diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c -index b31c4cff4d3a5..599bb6fc5f0a2 100644 ---- a/drivers/irqchip/irq-nvic.c -+++ b/drivers/irqchip/irq-nvic.c -@@ -26,7 +26,7 @@ - - #define NVIC_ISER 0x000 - #define NVIC_ICER 0x080 --#define NVIC_IPR 0x300 -+#define NVIC_IPR 0x400 - - #define NVIC_MAX_BANKS 16 - /* -diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c -index cf74cfa820453..259065d271ef0 100644 ---- a/drivers/irqchip/irq-sifive-plic.c -+++ b/drivers/irqchip/irq-sifive-plic.c -@@ -163,7 +163,13 @@ static void plic_irq_eoi(struct irq_data *d) - { - struct plic_handler *handler = this_cpu_ptr(&plic_handlers); - -- writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); -+ if (irqd_irq_masked(d)) { -+ plic_irq_unmask(d); -+ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); -+ plic_irq_mask(d); -+ } else { -+ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); -+ } - } - - static struct irq_chip plic_chip = { -diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c -index 64175a893312e..bb4793c7b38fd 100644 ---- a/drivers/mailbox/mtk-cmdq-mailbox.c -+++ b/drivers/mailbox/mtk-cmdq-mailbox.c -@@ -195,7 +195,6 @@ static void cmdq_task_exec_done(struct cmdq_task *task, int sta) - struct cmdq_task_cb *cb = &task->pkt->async_cb; - struct cmdq_cb_data data; - -- WARN_ON(cb->cb == (cmdq_async_flush_cb)NULL); - data.sta = sta; - data.data = cb->data; - data.pkt = task->pkt; -@@ -532,7 +531,8 @@ static int cmdq_probe(struct platform_device *pdev) - struct device_node *phandle = dev->of_node; - struct device_node *node; - int alias_id = 0; -- char clk_name[4] = "gce"; -+ static const char * const clk_name = "gce"; -+ static const char * const clk_names[] = { "gce0", "gce1" }; - - cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); - if (!cmdq) -@@ -570,12 +570,9 @@ static int cmdq_probe(struct platform_device *pdev) - - if (cmdq->gce_num > 1) { - for_each_child_of_node(phandle->parent, node) { -- char clk_id[8]; -- - alias_id = of_alias_get_id(node, clk_name); -- if (alias_id < cmdq->gce_num) { -- snprintf(clk_id, sizeof(clk_id), "%s%d", clk_name, alias_id); -- cmdq->clocks[alias_id].id = clk_id; -+ if (alias_id >= 0 && alias_id < cmdq->gce_num) { -+ cmdq->clocks[alias_id].id = clk_names[alias_id]; - cmdq->clocks[alias_id].clk = of_clk_get(node, 0); - if (IS_ERR(cmdq->clocks[alias_id].clk)) { - dev_err(dev, "failed to get gce clk: %d\n", alias_id); -diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c -index 0595559de174a..183a58c893774 100644 ---- a/drivers/md/bcache/btree.c -+++ b/drivers/md/bcache/btree.c -@@ -378,7 +378,7 @@ static void do_btree_node_write(struct btree *b) - struct bvec_iter_all iter_all; - - bio_for_each_segment_all(bv, b->bio, iter_all) { -- memcpy(bvec_virt(bv), addr, PAGE_SIZE); -+ memcpy(page_address(bv->bv_page), addr, PAGE_SIZE); - addr += PAGE_SIZE; - } - -diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c -index f2874c77ff797..3f72c0f40613d 100644 ---- a/drivers/md/bcache/super.c -+++ b/drivers/md/bcache/super.c -@@ -885,9 +885,9 @@ static void bcache_device_free(struct bcache_device *d) - bcache_device_detach(d); - - if (disk) { -- blk_cleanup_disk(disk); - ida_simple_remove(&bcache_device_idx, - first_minor_to_idx(disk->first_minor)); -+ blk_cleanup_disk(disk); - } - - bioset_exit(&d->bio_split); -diff --git a/drivers/md/md.c b/drivers/md/md.c -index 6c0c3d0d905aa..44006b860d0a5 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -2193,6 +2193,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) - - if (!num_sectors || num_sectors > max_sectors) - num_sectors = max_sectors; -+ rdev->sb_start = sb_start; - } - sb = page_address(rdev->sb_page); - sb->data_size = cpu_to_le64(num_sectors); -@@ -2976,7 +2977,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) - * -write_error - clears WriteErrorSeen - * {,-}failfast - set/clear FailFast - */ -+ -+ struct mddev *mddev = rdev->mddev; - int err = -EINVAL; -+ bool need_update_sb = false; -+ - if (cmd_match(buf, "faulty") && rdev->mddev->pers) { - md_error(rdev->mddev, rdev); - if (test_bit(Faulty, &rdev->flags)) -@@ -2991,7 +2996,6 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) - if (rdev->raid_disk >= 0) - err = -EBUSY; - else { -- struct mddev *mddev = rdev->mddev; - err = 0; - if (mddev_is_clustered(mddev)) - err = md_cluster_ops->remove_disk(mddev, rdev); -@@ -3008,10 +3012,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) - } else if (cmd_match(buf, "writemostly")) { - set_bit(WriteMostly, &rdev->flags); - mddev_create_serial_pool(rdev->mddev, rdev, false); -+ need_update_sb = true; - err = 0; - } else if (cmd_match(buf, "-writemostly")) { - mddev_destroy_serial_pool(rdev->mddev, rdev, false); - clear_bit(WriteMostly, &rdev->flags); -+ need_update_sb = true; - err = 0; - } else if (cmd_match(buf, "blocked")) { - set_bit(Blocked, &rdev->flags); -@@ -3037,9 +3043,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) - err = 0; - } else if (cmd_match(buf, "failfast")) { - set_bit(FailFast, &rdev->flags); -+ need_update_sb = true; - err = 0; - } else if (cmd_match(buf, "-failfast")) { - clear_bit(FailFast, &rdev->flags); -+ need_update_sb = true; - err = 0; - } else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0 && - !test_bit(Journal, &rdev->flags)) { -@@ -3118,6 +3126,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) - clear_bit(ExternalBbl, &rdev->flags); - err = 0; - } -+ if (need_update_sb) -+ md_update_sb(mddev, 1); - if (!err) - sysfs_notify_dirent_safe(rdev->sysfs_state); - return err ? err : len; -diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c -index 70532335c7c7e..cb670f16e98e9 100644 ---- a/drivers/md/persistent-data/dm-btree-remove.c -+++ b/drivers/md/persistent-data/dm-btree-remove.c -@@ -423,9 +423,9 @@ static int rebalance_children(struct shadow_spine *s, - - memcpy(n, dm_block_data(child), - dm_bm_block_size(dm_tm_get_bm(info->tm))); -- dm_tm_unlock(info->tm, child); - - dm_tm_dec(info->tm, dm_block_location(child)); -+ dm_tm_unlock(info->tm, child); - return 0; - } - -diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c -index 19598bd38939d..6ba12f0f0f036 100644 ---- a/drivers/md/raid1.c -+++ b/drivers/md/raid1.c -@@ -1496,7 +1496,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, - if (!r1_bio->bios[i]) - continue; - -- if (first_clone) { -+ if (first_clone && test_bit(WriteMostly, &rdev->flags)) { - /* do behind I/O ? - * Not if there are too many, or cannot - * allocate memory, or a reader on WriteMostly -diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c -index 79fa36de8a04a..cd9cb354dc2c7 100644 ---- a/drivers/media/cec/core/cec-adap.c -+++ b/drivers/media/cec/core/cec-adap.c -@@ -1199,6 +1199,7 @@ void cec_received_msg_ts(struct cec_adapter *adap, - if (abort) - dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT; - msg->flags = dst->flags; -+ msg->sequence = dst->sequence; - /* Remove it from the wait_queue */ - list_del_init(&data->list); - -diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c -index 508ac295eb06e..033b0c83272fe 100644 ---- a/drivers/media/common/videobuf2/videobuf2-core.c -+++ b/drivers/media/common/videobuf2/videobuf2-core.c -@@ -68,13 +68,13 @@ module_param(debug, int, 0644); - err; \ - }) - --#define call_ptr_memop(vb, op, args...) \ -+#define call_ptr_memop(op, vb, args...) \ - ({ \ - struct vb2_queue *_q = (vb)->vb2_queue; \ - void *ptr; \ - \ - log_memop(vb, op); \ -- ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \ -+ ptr = _q->mem_ops->op ? _q->mem_ops->op(vb, args) : NULL; \ - if (!IS_ERR_OR_NULL(ptr)) \ - (vb)->cnt_mem_ ## op++; \ - ptr; \ -@@ -144,9 +144,9 @@ module_param(debug, int, 0644); - ((vb)->vb2_queue->mem_ops->op ? \ - (vb)->vb2_queue->mem_ops->op(args) : 0) - --#define call_ptr_memop(vb, op, args...) \ -+#define call_ptr_memop(op, vb, args...) \ - ((vb)->vb2_queue->mem_ops->op ? \ -- (vb)->vb2_queue->mem_ops->op(args) : NULL) -+ (vb)->vb2_queue->mem_ops->op(vb, args) : NULL) - - #define call_void_memop(vb, op, args...) \ - do { \ -@@ -230,9 +230,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) - if (size < vb->planes[plane].length) - goto free; - -- mem_priv = call_ptr_memop(vb, alloc, -- q->alloc_devs[plane] ? : q->dev, -- q->dma_attrs, size, q->dma_dir, q->gfp_flags); -+ mem_priv = call_ptr_memop(alloc, -+ vb, -+ q->alloc_devs[plane] ? : q->dev, -+ size); - if (IS_ERR_OR_NULL(mem_priv)) { - if (mem_priv) - ret = PTR_ERR(mem_priv); -@@ -975,7 +976,7 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) - if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) - return NULL; - -- return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv); -+ return call_ptr_memop(vaddr, vb, vb->planes[plane_no].mem_priv); - - } - EXPORT_SYMBOL_GPL(vb2_plane_vaddr); -@@ -985,7 +986,7 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) - if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) - return NULL; - -- return call_ptr_memop(vb, cookie, vb->planes[plane_no].mem_priv); -+ return call_ptr_memop(cookie, vb, vb->planes[plane_no].mem_priv); - } - EXPORT_SYMBOL_GPL(vb2_plane_cookie); - -@@ -1125,10 +1126,11 @@ static int __prepare_userptr(struct vb2_buffer *vb) - vb->planes[plane].data_offset = 0; - - /* Acquire each plane's memory */ -- mem_priv = call_ptr_memop(vb, get_userptr, -- q->alloc_devs[plane] ? : q->dev, -- planes[plane].m.userptr, -- planes[plane].length, q->dma_dir); -+ mem_priv = call_ptr_memop(get_userptr, -+ vb, -+ q->alloc_devs[plane] ? : q->dev, -+ planes[plane].m.userptr, -+ planes[plane].length); - if (IS_ERR(mem_priv)) { - dprintk(q, 1, "failed acquiring userspace memory for plane %d\n", - plane); -@@ -1249,9 +1251,11 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) - vb->planes[plane].data_offset = 0; - - /* Acquire each plane's memory */ -- mem_priv = call_ptr_memop(vb, attach_dmabuf, -- q->alloc_devs[plane] ? : q->dev, -- dbuf, planes[plane].length, q->dma_dir); -+ mem_priv = call_ptr_memop(attach_dmabuf, -+ vb, -+ q->alloc_devs[plane] ? : q->dev, -+ dbuf, -+ planes[plane].length); - if (IS_ERR(mem_priv)) { - dprintk(q, 1, "failed to attach dmabuf\n"); - ret = PTR_ERR(mem_priv); -@@ -2187,8 +2191,10 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type, - - vb_plane = &vb->planes[plane]; - -- dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, -- flags & O_ACCMODE); -+ dbuf = call_ptr_memop(get_dmabuf, -+ vb, -+ vb_plane->mem_priv, -+ flags & O_ACCMODE); - if (IS_ERR_OR_NULL(dbuf)) { - dprintk(q, 1, "failed to export buffer %d, plane %d\n", - index, plane); -diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c -index a7f61ba854405..be376f3011b68 100644 ---- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c -+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c -@@ -40,6 +40,8 @@ struct vb2_dc_buf { - - /* DMABUF related */ - struct dma_buf_attachment *db_attach; -+ -+ struct vb2_buffer *vb; - }; - - /*********************************************/ -@@ -66,14 +68,14 @@ static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt) - /* callbacks for all buffers */ - /*********************************************/ - --static void *vb2_dc_cookie(void *buf_priv) -+static void *vb2_dc_cookie(struct vb2_buffer *vb, void *buf_priv) - { - struct vb2_dc_buf *buf = buf_priv; - - return &buf->dma_addr; - } - --static void *vb2_dc_vaddr(void *buf_priv) -+static void *vb2_dc_vaddr(struct vb2_buffer *vb, void *buf_priv) - { - struct vb2_dc_buf *buf = buf_priv; - struct dma_buf_map map; -@@ -137,9 +139,9 @@ static void vb2_dc_put(void *buf_priv) - kfree(buf); - } - --static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, -- unsigned long size, enum dma_data_direction dma_dir, -- gfp_t gfp_flags) -+static void *vb2_dc_alloc(struct vb2_buffer *vb, -+ struct device *dev, -+ unsigned long size) - { - struct vb2_dc_buf *buf; - -@@ -150,9 +152,10 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, - if (!buf) - return ERR_PTR(-ENOMEM); - -- buf->attrs = attrs; -+ buf->attrs = vb->vb2_queue->dma_attrs; - buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, -- GFP_KERNEL | gfp_flags, buf->attrs); -+ GFP_KERNEL | vb->vb2_queue->gfp_flags, -+ buf->attrs); - if (!buf->cookie) { - dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); - kfree(buf); -@@ -165,11 +168,12 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, - /* Prevent the device from being released while the buffer is used */ - buf->dev = get_device(dev); - buf->size = size; -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - - buf->handler.refcount = &buf->refcount; - buf->handler.put = vb2_dc_put; - buf->handler.arg = buf; -+ buf->vb = vb; - - refcount_set(&buf->refcount, 1); - -@@ -397,7 +401,9 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) - return sgt; - } - --static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) -+static struct dma_buf *vb2_dc_get_dmabuf(struct vb2_buffer *vb, -+ void *buf_priv, -+ unsigned long flags) - { - struct vb2_dc_buf *buf = buf_priv; - struct dma_buf *dbuf; -@@ -459,8 +465,8 @@ static void vb2_dc_put_userptr(void *buf_priv) - kfree(buf); - } - --static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, -- unsigned long size, enum dma_data_direction dma_dir) -+static void *vb2_dc_get_userptr(struct vb2_buffer *vb, struct device *dev, -+ unsigned long vaddr, unsigned long size) - { - struct vb2_dc_buf *buf; - struct frame_vector *vec; -@@ -490,7 +496,8 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, - return ERR_PTR(-ENOMEM); - - buf->dev = dev; -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; -+ buf->vb = vb; - - offset = lower_32_bits(offset_in_page(vaddr)); - vec = vb2_create_framevec(vaddr, size); -@@ -660,8 +667,8 @@ static void vb2_dc_detach_dmabuf(void *mem_priv) - kfree(buf); - } - --static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, -- unsigned long size, enum dma_data_direction dma_dir) -+static void *vb2_dc_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, -+ struct dma_buf *dbuf, unsigned long size) - { - struct vb2_dc_buf *buf; - struct dma_buf_attachment *dba; -@@ -677,6 +684,8 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, - return ERR_PTR(-ENOMEM); - - buf->dev = dev; -+ buf->vb = vb; -+ - /* create attachment for the dmabuf with the user device */ - dba = dma_buf_attach(dbuf, buf->dev); - if (IS_ERR(dba)) { -@@ -685,7 +694,7 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, - return dba; - } - -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - buf->size = size; - buf->db_attach = dba; - -diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c -index c5b06a5095661..0d6389dd9b0c6 100644 ---- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c -+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c -@@ -51,6 +51,8 @@ struct vb2_dma_sg_buf { - struct vb2_vmarea_handler handler; - - struct dma_buf_attachment *db_attach; -+ -+ struct vb2_buffer *vb; - }; - - static void vb2_dma_sg_put(void *buf_priv); -@@ -96,9 +98,8 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf, - return 0; - } - --static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, -- unsigned long size, enum dma_data_direction dma_dir, -- gfp_t gfp_flags) -+static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev, -+ unsigned long size) - { - struct vb2_dma_sg_buf *buf; - struct sg_table *sgt; -@@ -113,7 +114,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, - return ERR_PTR(-ENOMEM); - - buf->vaddr = NULL; -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - buf->offset = 0; - buf->size = size; - /* size is already page aligned */ -@@ -130,7 +131,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, - if (!buf->pages) - goto fail_pages_array_alloc; - -- ret = vb2_dma_sg_alloc_compacted(buf, gfp_flags); -+ ret = vb2_dma_sg_alloc_compacted(buf, vb->vb2_queue->gfp_flags); - if (ret) - goto fail_pages_alloc; - -@@ -154,6 +155,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, - buf->handler.refcount = &buf->refcount; - buf->handler.put = vb2_dma_sg_put; - buf->handler.arg = buf; -+ buf->vb = vb; - - refcount_set(&buf->refcount, 1); - -@@ -213,9 +215,8 @@ static void vb2_dma_sg_finish(void *buf_priv) - dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir); - } - --static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, -- unsigned long size, -- enum dma_data_direction dma_dir) -+static void *vb2_dma_sg_get_userptr(struct vb2_buffer *vb, struct device *dev, -+ unsigned long vaddr, unsigned long size) - { - struct vb2_dma_sg_buf *buf; - struct sg_table *sgt; -@@ -230,10 +231,11 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, - - buf->vaddr = NULL; - buf->dev = dev; -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - buf->offset = vaddr & ~PAGE_MASK; - buf->size = size; - buf->dma_sgt = &buf->sg_table; -+ buf->vb = vb; - vec = vb2_create_framevec(vaddr, size); - if (IS_ERR(vec)) - goto userptr_fail_pfnvec; -@@ -292,7 +294,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv) - kfree(buf); - } - --static void *vb2_dma_sg_vaddr(void *buf_priv) -+static void *vb2_dma_sg_vaddr(struct vb2_buffer *vb, void *buf_priv) - { - struct vb2_dma_sg_buf *buf = buf_priv; - struct dma_buf_map map; -@@ -511,7 +513,9 @@ static const struct dma_buf_ops vb2_dma_sg_dmabuf_ops = { - .release = vb2_dma_sg_dmabuf_ops_release, - }; - --static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags) -+static struct dma_buf *vb2_dma_sg_get_dmabuf(struct vb2_buffer *vb, -+ void *buf_priv, -+ unsigned long flags) - { - struct vb2_dma_sg_buf *buf = buf_priv; - struct dma_buf *dbuf; -@@ -605,8 +609,8 @@ static void vb2_dma_sg_detach_dmabuf(void *mem_priv) - kfree(buf); - } - --static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, -- unsigned long size, enum dma_data_direction dma_dir) -+static void *vb2_dma_sg_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, -+ struct dma_buf *dbuf, unsigned long size) - { - struct vb2_dma_sg_buf *buf; - struct dma_buf_attachment *dba; -@@ -630,14 +634,15 @@ static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, - return dba; - } - -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - buf->size = size; - buf->db_attach = dba; -+ buf->vb = vb; - - return buf; - } - --static void *vb2_dma_sg_cookie(void *buf_priv) -+static void *vb2_dma_sg_cookie(struct vb2_buffer *vb, void *buf_priv) - { - struct vb2_dma_sg_buf *buf = buf_priv; - -diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c -index 83f95258ec8c6..ef36abd912dcc 100644 ---- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c -+++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c -@@ -34,13 +34,12 @@ struct vb2_vmalloc_buf { - - static void vb2_vmalloc_put(void *buf_priv); - --static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, -- unsigned long size, enum dma_data_direction dma_dir, -- gfp_t gfp_flags) -+static void *vb2_vmalloc_alloc(struct vb2_buffer *vb, struct device *dev, -+ unsigned long size) - { - struct vb2_vmalloc_buf *buf; - -- buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags); -+ buf = kzalloc(sizeof(*buf), GFP_KERNEL | vb->vb2_queue->gfp_flags); - if (!buf) - return ERR_PTR(-ENOMEM); - -@@ -52,7 +51,7 @@ static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, - return ERR_PTR(-ENOMEM); - } - -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - buf->handler.refcount = &buf->refcount; - buf->handler.put = vb2_vmalloc_put; - buf->handler.arg = buf; -@@ -71,9 +70,8 @@ static void vb2_vmalloc_put(void *buf_priv) - } - } - --static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, -- unsigned long size, -- enum dma_data_direction dma_dir) -+static void *vb2_vmalloc_get_userptr(struct vb2_buffer *vb, struct device *dev, -+ unsigned long vaddr, unsigned long size) - { - struct vb2_vmalloc_buf *buf; - struct frame_vector *vec; -@@ -84,7 +82,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, - if (!buf) - return ERR_PTR(-ENOMEM); - -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - offset = vaddr & ~PAGE_MASK; - buf->size = size; - vec = vb2_create_framevec(vaddr, size); -@@ -147,7 +145,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) - kfree(buf); - } - --static void *vb2_vmalloc_vaddr(void *buf_priv) -+static void *vb2_vmalloc_vaddr(struct vb2_buffer *vb, void *buf_priv) - { - struct vb2_vmalloc_buf *buf = buf_priv; - -@@ -339,7 +337,9 @@ static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = { - .release = vb2_vmalloc_dmabuf_ops_release, - }; - --static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags) -+static struct dma_buf *vb2_vmalloc_get_dmabuf(struct vb2_buffer *vb, -+ void *buf_priv, -+ unsigned long flags) - { - struct vb2_vmalloc_buf *buf = buf_priv; - struct dma_buf *dbuf; -@@ -403,8 +403,10 @@ static void vb2_vmalloc_detach_dmabuf(void *mem_priv) - kfree(buf); - } - --static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, -- unsigned long size, enum dma_data_direction dma_dir) -+static void *vb2_vmalloc_attach_dmabuf(struct vb2_buffer *vb, -+ struct device *dev, -+ struct dma_buf *dbuf, -+ unsigned long size) - { - struct vb2_vmalloc_buf *buf; - -@@ -416,7 +418,7 @@ static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, - return ERR_PTR(-ENOMEM); - - buf->dbuf = dbuf; -- buf->dma_dir = dma_dir; -+ buf->dma_dir = vb->vb2_queue->dma_dir; - buf->size = size; - - return buf; -diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c -index e4528784f8477..fff212c0bf3b5 100644 ---- a/drivers/media/dvb-frontends/mn88443x.c -+++ b/drivers/media/dvb-frontends/mn88443x.c -@@ -204,11 +204,18 @@ struct mn88443x_priv { - struct regmap *regmap_t; - }; - --static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) -+static int mn88443x_cmn_power_on(struct mn88443x_priv *chip) - { -+ struct device *dev = &chip->client_s->dev; - struct regmap *r_t = chip->regmap_t; -+ int ret; - -- clk_prepare_enable(chip->mclk); -+ ret = clk_prepare_enable(chip->mclk); -+ if (ret) { -+ dev_err(dev, "Failed to prepare and enable mclk: %d\n", -+ ret); -+ return ret; -+ } - - gpiod_set_value_cansleep(chip->reset_gpio, 1); - usleep_range(100, 1000); -@@ -222,6 +229,8 @@ static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) - } else { - regmap_write(r_t, HIZSET3, 0x8f); - } -+ -+ return 0; - } - - static void mn88443x_cmn_power_off(struct mn88443x_priv *chip) -@@ -738,7 +747,10 @@ static int mn88443x_probe(struct i2c_client *client, - chip->fe.demodulator_priv = chip; - i2c_set_clientdata(client, chip); - -- mn88443x_cmn_power_on(chip); -+ ret = mn88443x_cmn_power_on(chip); -+ if (ret) -+ goto err_i2c_t; -+ - mn88443x_s_sleep(chip); - mn88443x_t_sleep(chip); - -diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c -index 2bf9467b917d1..71991f8638e6b 100644 ---- a/drivers/media/firewire/firedtv-avc.c -+++ b/drivers/media/firewire/firedtv-avc.c -@@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) - read_pos += program_info_length; - write_pos += program_info_length; - } -- while (read_pos < length) { -+ while (read_pos + 4 < length) { -+ if (write_pos + 4 >= sizeof(c->operand) - 4) { -+ ret = -EINVAL; -+ goto out; -+ } - c->operand[write_pos++] = msg[read_pos++]; - c->operand[write_pos++] = msg[read_pos++]; - c->operand[write_pos++] = msg[read_pos++]; -@@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) - c->operand[write_pos++] = es_info_length >> 8; - c->operand[write_pos++] = es_info_length & 0xff; - if (es_info_length > 0) { -+ if (read_pos >= length) { -+ ret = -EINVAL; -+ goto out; -+ } - pmt_cmd_id = msg[read_pos++]; - if (pmt_cmd_id != 1 && pmt_cmd_id != 4) - dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n", - pmt_cmd_id); - -- if (es_info_length > sizeof(c->operand) - 4 - -- write_pos) { -+ if (es_info_length > sizeof(c->operand) - 4 - write_pos || -+ es_info_length > length - read_pos) { - ret = -EINVAL; - goto out; - } -diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c -index 9363d005e2b61..e0d57e09dab0c 100644 ---- a/drivers/media/firewire/firedtv-ci.c -+++ b/drivers/media/firewire/firedtv-ci.c -@@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) - } else { - data_length = msg->msg[3]; - } -+ if (data_length > sizeof(msg->msg) - data_pos) -+ return -EINVAL; - - return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length); - } -diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig -index 08feb3e8c1bf6..6157e73eef24e 100644 ---- a/drivers/media/i2c/Kconfig -+++ b/drivers/media/i2c/Kconfig -@@ -597,6 +597,7 @@ config VIDEO_AK881X - config VIDEO_THS8200 - tristate "Texas Instruments THS8200 video encoder" - depends on VIDEO_V4L2 && I2C -+ select V4L2_ASYNC - help - Support for the Texas Instruments THS8200 video encoder. - -diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c -index 81cdf37216ca7..c249507aa2dbc 100644 ---- a/drivers/media/i2c/imx258.c -+++ b/drivers/media/i2c/imx258.c -@@ -1260,18 +1260,18 @@ static int imx258_probe(struct i2c_client *client) - return -ENOMEM; - - imx258->clk = devm_clk_get_optional(&client->dev, NULL); -+ if (IS_ERR(imx258->clk)) -+ return dev_err_probe(&client->dev, PTR_ERR(imx258->clk), -+ "error getting clock\n"); - if (!imx258->clk) { - dev_dbg(&client->dev, - "no clock provided, using clock-frequency property\n"); - - device_property_read_u32(&client->dev, "clock-frequency", &val); -- if (val != IMX258_INPUT_CLOCK_FREQ) -- return -EINVAL; -- } else if (IS_ERR(imx258->clk)) { -- return dev_err_probe(&client->dev, PTR_ERR(imx258->clk), -- "error getting clock\n"); -+ } else { -+ val = clk_get_rate(imx258->clk); - } -- if (clk_get_rate(imx258->clk) != IMX258_INPUT_CLOCK_FREQ) { -+ if (val != IMX258_INPUT_CLOCK_FREQ) { - dev_err(&client->dev, "input clock frequency not supported\n"); - return -EINVAL; - } -diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c -index 92376592455ee..56674173524fd 100644 ---- a/drivers/media/i2c/ir-kbd-i2c.c -+++ b/drivers/media/i2c/ir-kbd-i2c.c -@@ -791,6 +791,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) - rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | - RC_PROTO_BIT_RC6_6A_32; - ir_codes = RC_MAP_HAUPPAUGE; -+ ir->polling_interval = 125; - probe_tx = true; - break; - } -diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c -index 6eb88ef997836..3ae1b28c8351b 100644 ---- a/drivers/media/i2c/mt9p031.c -+++ b/drivers/media/i2c/mt9p031.c -@@ -78,7 +78,9 @@ - #define MT9P031_PIXEL_CLOCK_INVERT (1 << 15) - #define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8) - #define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0) --#define MT9P031_FRAME_RESTART 0x0b -+#define MT9P031_RESTART 0x0b -+#define MT9P031_FRAME_PAUSE_RESTART (1 << 1) -+#define MT9P031_FRAME_RESTART (1 << 0) - #define MT9P031_SHUTTER_DELAY 0x0c - #define MT9P031_RST 0x0d - #define MT9P031_RST_ENABLE 1 -@@ -444,9 +446,23 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031) - static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) - { - struct mt9p031 *mt9p031 = to_mt9p031(subdev); -+ struct i2c_client *client = v4l2_get_subdevdata(subdev); -+ int val; - int ret; - - if (!enable) { -+ /* enable pause restart */ -+ val = MT9P031_FRAME_PAUSE_RESTART; -+ ret = mt9p031_write(client, MT9P031_RESTART, val); -+ if (ret < 0) -+ return ret; -+ -+ /* enable restart + keep pause restart set */ -+ val |= MT9P031_FRAME_RESTART; -+ ret = mt9p031_write(client, MT9P031_RESTART, val); -+ if (ret < 0) -+ return ret; -+ - /* Stop sensor readout */ - ret = mt9p031_set_output_control(mt9p031, - MT9P031_OUTPUT_CONTROL_CEN, 0); -@@ -466,6 +482,16 @@ static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) - if (ret < 0) - return ret; - -+ /* -+ * - clear pause restart -+ * - don't clear restart as clearing restart manually can cause -+ * undefined behavior -+ */ -+ val = MT9P031_FRAME_RESTART; -+ ret = mt9p031_write(client, MT9P031_RESTART, val); -+ if (ret < 0) -+ return ret; -+ - return mt9p031_pll_enable(mt9p031); - } - -diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c -index 6070aaf0b32ea..4dafa9f1cf522 100644 ---- a/drivers/media/i2c/tda1997x.c -+++ b/drivers/media/i2c/tda1997x.c -@@ -1248,13 +1248,13 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr) - { - struct v4l2_subdev *sd = &state->sd; - union hdmi_infoframe frame; -- u8 buffer[40]; -+ u8 buffer[40] = { 0 }; - u8 reg; - int len, err; - - /* read data */ - len = io_readn(sd, addr, sizeof(buffer), buffer); -- err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); -+ err = hdmi_infoframe_unpack(&frame, buffer, len); - if (err) { - v4l_err(state->client, - "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", -@@ -1928,13 +1928,13 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr) - { - struct tda1997x_state *state = to_state(sd); - union hdmi_infoframe frame; -- u8 buffer[40]; -+ u8 buffer[40] = { 0 }; - int len, err; - - /* read data */ - len = io_readn(sd, addr, sizeof(buffer), buffer); - v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); -- err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); -+ err = hdmi_infoframe_unpack(&frame, buffer, len); - if (err) { - v4l_err(state->client, - "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", -diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c -index ab14d35214aa8..25dc8d4dc5b73 100644 ---- a/drivers/media/pci/cx23885/cx23885-alsa.c -+++ b/drivers/media/pci/cx23885/cx23885-alsa.c -@@ -550,7 +550,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) - SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct cx23885_audio_dev), &card); - if (err < 0) -- goto error; -+ goto error_msg; - - chip = (struct cx23885_audio_dev *) card->private_data; - chip->dev = dev; -@@ -576,6 +576,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) - - error: - snd_card_free(card); -+error_msg: - pr_err("%s(): Failed to register analog audio adapter\n", - __func__); - -diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c -index e2d56dca5be40..5ad03b2a50bdb 100644 ---- a/drivers/media/pci/ivtv/ivtvfb.c -+++ b/drivers/media/pci/ivtv/ivtvfb.c -@@ -36,7 +36,7 @@ - #include <linux/fb.h> - #include <linux/ivtvfb.h> - --#ifdef CONFIG_X86_64 -+#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) - #include <asm/memtype.h> - #endif - -@@ -1157,7 +1157,7 @@ static int ivtvfb_init_card(struct ivtv *itv) - { - int rc; - --#ifdef CONFIG_X86_64 -+#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) - if (pat_enabled()) { - if (ivtvfb_force_pat) { - pr_info("PAT is enabled. Write-combined framebuffer caching will be disabled.\n"); -diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c -index 6f3125c2d0976..77bae14685513 100644 ---- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c -+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c -@@ -258,19 +258,24 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id) - if ((reg40 & AVL_IRQ_ASSERTED) != 0) { - /* IRQ is being signaled */ - reg_isr = readw(ndev->bmmio0 + REG_ISR); -- if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) { -- iret = netup_i2c_interrupt(&ndev->i2c[0]); -- } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) { -- iret = netup_i2c_interrupt(&ndev->i2c[1]); -- } else if (reg_isr & NETUP_UNIDVB_IRQ_SPI) { -+ if (reg_isr & NETUP_UNIDVB_IRQ_SPI) - iret = netup_spi_interrupt(ndev->spi); -- } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) { -- iret = netup_dma_interrupt(&ndev->dma[0]); -- } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) { -- iret = netup_dma_interrupt(&ndev->dma[1]); -- } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) { -- iret = netup_ci_interrupt(ndev); -+ else if (!ndev->old_fw) { -+ if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) { -+ iret = netup_i2c_interrupt(&ndev->i2c[0]); -+ } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) { -+ iret = netup_i2c_interrupt(&ndev->i2c[1]); -+ } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) { -+ iret = netup_dma_interrupt(&ndev->dma[0]); -+ } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) { -+ iret = netup_dma_interrupt(&ndev->dma[1]); -+ } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) { -+ iret = netup_ci_interrupt(ndev); -+ } else { -+ goto err; -+ } - } else { -+err: - dev_err(&pci_dev->dev, - "%s(): unknown interrupt 0x%x\n", - __func__, reg_isr); -diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c -index 887b492e4ad1c..14a119b43bca0 100644 ---- a/drivers/media/platform/allegro-dvt/allegro-core.c -+++ b/drivers/media/platform/allegro-dvt/allegro-core.c -@@ -2185,6 +2185,15 @@ static irqreturn_t allegro_irq_thread(int irq, void *data) - { - struct allegro_dev *dev = data; - -+ /* -+ * The firmware is initialized after the mailbox is setup. We further -+ * check the AL5_ITC_CPU_IRQ_STA register, if the firmware actually -+ * triggered the interrupt. Although this should not happen, make sure -+ * that we ignore interrupts, if the mailbox is not initialized. -+ */ -+ if (!dev->mbox_status) -+ return IRQ_NONE; -+ - allegro_mbox_notify(dev->mbox_status); - - return IRQ_HANDLED; -diff --git a/drivers/media/platform/atmel/atmel-isc-base.c b/drivers/media/platform/atmel/atmel-isc-base.c -index 136ab7cf36edc..ebf264b980f91 100644 ---- a/drivers/media/platform/atmel/atmel-isc-base.c -+++ b/drivers/media/platform/atmel/atmel-isc-base.c -@@ -123,11 +123,9 @@ static int isc_clk_prepare(struct clk_hw *hw) - struct isc_clk *isc_clk = to_isc_clk(hw); - int ret; - -- if (isc_clk->id == ISC_ISPCK) { -- ret = pm_runtime_resume_and_get(isc_clk->dev); -- if (ret < 0) -- return ret; -- } -+ ret = pm_runtime_resume_and_get(isc_clk->dev); -+ if (ret < 0) -+ return ret; - - return isc_wait_clk_stable(hw); - } -@@ -138,8 +136,7 @@ static void isc_clk_unprepare(struct clk_hw *hw) - - isc_wait_clk_stable(hw); - -- if (isc_clk->id == ISC_ISPCK) -- pm_runtime_put_sync(isc_clk->dev); -+ pm_runtime_put_sync(isc_clk->dev); - } - - static int isc_clk_enable(struct clk_hw *hw) -@@ -186,16 +183,13 @@ static int isc_clk_is_enabled(struct clk_hw *hw) - u32 status; - int ret; - -- if (isc_clk->id == ISC_ISPCK) { -- ret = pm_runtime_resume_and_get(isc_clk->dev); -- if (ret < 0) -- return 0; -- } -+ ret = pm_runtime_resume_and_get(isc_clk->dev); -+ if (ret < 0) -+ return 0; - - regmap_read(isc_clk->regmap, ISC_CLKSR, &status); - -- if (isc_clk->id == ISC_ISPCK) -- pm_runtime_put_sync(isc_clk->dev); -+ pm_runtime_put_sync(isc_clk->dev); - - return status & ISC_CLK(isc_clk->id) ? 1 : 0; - } -@@ -325,6 +319,9 @@ static int isc_clk_register(struct isc_device *isc, unsigned int id) - const char *parent_names[3]; - int num_parents; - -+ if (id == ISC_ISPCK && !isc->ispck_required) -+ return 0; -+ - num_parents = of_clk_get_parent_count(np); - if (num_parents < 1 || num_parents > 3) - return -EINVAL; -diff --git a/drivers/media/platform/atmel/atmel-isc.h b/drivers/media/platform/atmel/atmel-isc.h -index 19cc60dfcbe0f..2bfcb135ef13b 100644 ---- a/drivers/media/platform/atmel/atmel-isc.h -+++ b/drivers/media/platform/atmel/atmel-isc.h -@@ -178,6 +178,7 @@ struct isc_reg_offsets { - * @hclock: Hclock clock input (refer datasheet) - * @ispck: iscpck clock (refer datasheet) - * @isc_clks: ISC clocks -+ * @ispck_required: ISC requires ISP Clock initialization - * @dcfg: DMA master configuration, architecture dependent - * - * @dev: Registered device driver -@@ -252,6 +253,7 @@ struct isc_device { - struct clk *hclock; - struct clk *ispck; - struct isc_clk isc_clks[2]; -+ bool ispck_required; - u32 dcfg; - - struct device *dev; -diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c -index b66f1d174e9d7..e29a9193bac81 100644 ---- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c -+++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c -@@ -454,6 +454,9 @@ static int atmel_isc_probe(struct platform_device *pdev) - /* sama5d2-isc - 8 bits per beat */ - isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8; - -+ /* sama5d2-isc : ISPCK is required and mandatory */ -+ isc->ispck_required = true; -+ - ret = isc_pipeline_init(isc); - if (ret) - return ret; -@@ -476,22 +479,6 @@ static int atmel_isc_probe(struct platform_device *pdev) - dev_err(dev, "failed to init isc clock: %d\n", ret); - goto unprepare_hclk; - } -- -- isc->ispck = isc->isc_clks[ISC_ISPCK].clk; -- -- ret = clk_prepare_enable(isc->ispck); -- if (ret) { -- dev_err(dev, "failed to enable ispck: %d\n", ret); -- goto unprepare_hclk; -- } -- -- /* ispck should be greater or equal to hclock */ -- ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); -- if (ret) { -- dev_err(dev, "failed to set ispck rate: %d\n", ret); -- goto unprepare_clk; -- } -- - ret = v4l2_device_register(dev, &isc->v4l2_dev); - if (ret) { - dev_err(dev, "unable to register v4l2 device.\n"); -@@ -545,19 +532,35 @@ static int atmel_isc_probe(struct platform_device *pdev) - pm_runtime_enable(dev); - pm_request_idle(dev); - -+ isc->ispck = isc->isc_clks[ISC_ISPCK].clk; -+ -+ ret = clk_prepare_enable(isc->ispck); -+ if (ret) { -+ dev_err(dev, "failed to enable ispck: %d\n", ret); -+ goto cleanup_subdev; -+ } -+ -+ /* ispck should be greater or equal to hclock */ -+ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); -+ if (ret) { -+ dev_err(dev, "failed to set ispck rate: %d\n", ret); -+ goto unprepare_clk; -+ } -+ - regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver); - dev_info(dev, "Microchip ISC version %x\n", ver); - - return 0; - -+unprepare_clk: -+ clk_disable_unprepare(isc->ispck); -+ - cleanup_subdev: - isc_subdev_cleanup(isc); - - unregister_v4l2_device: - v4l2_device_unregister(&isc->v4l2_dev); - --unprepare_clk: -- clk_disable_unprepare(isc->ispck); - unprepare_hclk: - clk_disable_unprepare(isc->hclock); - -diff --git a/drivers/media/platform/atmel/atmel-sama7g5-isc.c b/drivers/media/platform/atmel/atmel-sama7g5-isc.c -index f2785131ff569..9c05acafd0724 100644 ---- a/drivers/media/platform/atmel/atmel-sama7g5-isc.c -+++ b/drivers/media/platform/atmel/atmel-sama7g5-isc.c -@@ -447,6 +447,9 @@ static int microchip_xisc_probe(struct platform_device *pdev) - /* sama7g5-isc RAM access port is full AXI4 - 32 bits per beat */ - isc->dcfg = ISC_DCFG_YMBSIZE_BEATS32 | ISC_DCFG_CMBSIZE_BEATS32; - -+ /* sama7g5-isc : ISPCK does not exist, ISC is clocked by MCK */ -+ isc->ispck_required = false; -+ - ret = isc_pipeline_init(isc); - if (ret) - return ret; -@@ -470,25 +473,10 @@ static int microchip_xisc_probe(struct platform_device *pdev) - goto unprepare_hclk; - } - -- isc->ispck = isc->isc_clks[ISC_ISPCK].clk; -- -- ret = clk_prepare_enable(isc->ispck); -- if (ret) { -- dev_err(dev, "failed to enable ispck: %d\n", ret); -- goto unprepare_hclk; -- } -- -- /* ispck should be greater or equal to hclock */ -- ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); -- if (ret) { -- dev_err(dev, "failed to set ispck rate: %d\n", ret); -- goto unprepare_clk; -- } -- - ret = v4l2_device_register(dev, &isc->v4l2_dev); - if (ret) { - dev_err(dev, "unable to register v4l2 device.\n"); -- goto unprepare_clk; -+ goto unprepare_hclk; - } - - ret = xisc_parse_dt(dev, isc); -@@ -549,8 +537,6 @@ cleanup_subdev: - unregister_v4l2_device: - v4l2_device_unregister(&isc->v4l2_dev); - --unprepare_clk: -- clk_disable_unprepare(isc->ispck); - unprepare_hclk: - clk_disable_unprepare(isc->hclock); - -diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c -index 755138063ee61..fc905ea78b175 100644 ---- a/drivers/media/platform/imx-jpeg/mxc-jpeg.c -+++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.c -@@ -575,6 +575,10 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) - - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); -+ if (!dst_buf || !src_buf) { -+ dev_err(dev, "No source or destination buffer.\n"); -+ goto job_unlock; -+ } - jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf); - - if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) { -@@ -2088,6 +2092,8 @@ err_m2m: - v4l2_device_unregister(&jpeg->v4l2_dev); - - err_register: -+ mxc_jpeg_detach_pm_domains(jpeg); -+ - err_irq: - return ret; - } -diff --git a/drivers/media/platform/meson/ge2d/ge2d.c b/drivers/media/platform/meson/ge2d/ge2d.c -index a1393fefa8aea..9b1e973e78da3 100644 ---- a/drivers/media/platform/meson/ge2d/ge2d.c -+++ b/drivers/media/platform/meson/ge2d/ge2d.c -@@ -779,11 +779,7 @@ static int ge2d_s_ctrl(struct v4l2_ctrl *ctrl) - * If the rotation parameter changes the OUTPUT frames - * parameters, take them in account - */ -- if (fmt.width != ctx->out.pix_fmt.width || -- fmt.height != ctx->out.pix_fmt.width || -- fmt.bytesperline > ctx->out.pix_fmt.bytesperline || -- fmt.sizeimage > ctx->out.pix_fmt.sizeimage) -- ctx->out.pix_fmt = fmt; -+ ctx->out.pix_fmt = fmt; - - break; - } -diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c -index 416f356af363d..d97a6765693f1 100644 ---- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c -+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c -@@ -793,7 +793,7 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) - { - struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q); - struct venc_enc_param param; -- int ret; -+ int ret, pm_ret; - int i; - - /* Once state turn into MTK_STATE_ABORT, we need stop_streaming -@@ -845,9 +845,9 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) - return 0; - - err_set_param: -- ret = pm_runtime_put(&ctx->dev->plat_dev->dev); -- if (ret < 0) -- mtk_v4l2_err("pm_runtime_put fail %d", ret); -+ pm_ret = pm_runtime_put(&ctx->dev->plat_dev->dev); -+ if (pm_ret < 0) -+ mtk_v4l2_err("pm_runtime_put fail %d", pm_ret); - - err_start_stream: - for (i = 0; i < q->num_buffers; ++i) { -diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c -index ec290dde59cfd..7f1647da0ade0 100644 ---- a/drivers/media/platform/mtk-vpu/mtk_vpu.c -+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c -@@ -848,7 +848,8 @@ static int mtk_vpu_probe(struct platform_device *pdev) - vpu->wdt.wq = create_singlethread_workqueue("vpu_wdt"); - if (!vpu->wdt.wq) { - dev_err(dev, "initialize wdt workqueue failed\n"); -- return -ENOMEM; -+ ret = -ENOMEM; -+ goto clk_unprepare; - } - INIT_WORK(&vpu->wdt.ws, vpu_wdt_reset_func); - mutex_init(&vpu->vpu_mutex); -@@ -942,6 +943,8 @@ disable_vpu_clk: - vpu_clock_disable(vpu); - workqueue_destroy: - destroy_workqueue(vpu->wdt.wq); -+clk_unprepare: -+ clk_unprepare(vpu->clk); - - return ret; - } -diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c -index 3e2345eb47f7c..e031fd17f4e75 100644 ---- a/drivers/media/platform/qcom/venus/pm_helpers.c -+++ b/drivers/media/platform/qcom/venus/pm_helpers.c -@@ -1085,12 +1085,16 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst, - if (inst->state != INST_START) - return 0; - -- if (inst->session_type == VIDC_SESSION_TYPE_ENC) -+ if (inst->session_type == VIDC_SESSION_TYPE_ENC) { - vpp_freq_per_mb = inst->flags & VENUS_LOW_POWER ? - inst->clk_data.low_power_freq : - inst->clk_data.vpp_freq; - -- vpp_freq = mbs_per_sec * vpp_freq_per_mb; -+ vpp_freq = mbs_per_sec * vpp_freq_per_mb; -+ } else { -+ vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq; -+ } -+ - /* 21 / 20 is overhead factor */ - vpp_freq += vpp_freq / 20; - vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq; -diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c -index e28eff0396888..ba4a380016cc4 100644 ---- a/drivers/media/platform/rcar-vin/rcar-csi2.c -+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c -@@ -553,6 +553,8 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) - - /* Code is validated in set_fmt. */ - format = rcsi2_code_to_fmt(priv->mf.code); -+ if (!format) -+ return -EINVAL; - - /* - * Enable all supported CSI-2 channels with virtual channel and -diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c -index f5f722ab1d4e8..520d044bfb8d5 100644 ---- a/drivers/media/platform/rcar-vin/rcar-dma.c -+++ b/drivers/media/platform/rcar-vin/rcar-dma.c -@@ -904,7 +904,8 @@ static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot) - vin->format.sizeimage / 2; - break; - } -- } else if (vin->state != RUNNING || list_empty(&vin->buf_list)) { -+ } else if ((vin->state != STOPPED && vin->state != RUNNING) || -+ list_empty(&vin->buf_list)) { - vin->buf_hw[slot].buffer = NULL; - vin->buf_hw[slot].type = FULL; - phys_addr = vin->scratch_phys; -diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c -index eba2b9f040df0..f336a95432732 100644 ---- a/drivers/media/platform/s5p-mfc/s5p_mfc.c -+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c -@@ -1283,11 +1283,15 @@ static int s5p_mfc_probe(struct platform_device *pdev) - spin_lock_init(&dev->condlock); - dev->plat_dev = pdev; - if (!dev->plat_dev) { -- dev_err(&pdev->dev, "No platform data specified\n"); -+ mfc_err("No platform data specified\n"); - return -ENODEV; - } - - dev->variant = of_device_get_match_data(&pdev->dev); -+ if (!dev->variant) { -+ dev_err(&pdev->dev, "Failed to get device MFC hardware variant information\n"); -+ return -ENOENT; -+ } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->regs_base = devm_ioremap_resource(&pdev->dev, res); -diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c -index d914ccef98317..6110718645a4f 100644 ---- a/drivers/media/platform/stm32/stm32-dcmi.c -+++ b/drivers/media/platform/stm32/stm32-dcmi.c -@@ -128,6 +128,7 @@ struct stm32_dcmi { - int sequence; - struct list_head buffers; - struct dcmi_buf *active; -+ int irq; - - struct v4l2_device v4l2_dev; - struct video_device *vdev; -@@ -1759,6 +1760,14 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) - return ret; - } - -+ ret = devm_request_threaded_irq(dcmi->dev, dcmi->irq, dcmi_irq_callback, -+ dcmi_irq_thread, IRQF_ONESHOT, -+ dev_name(dcmi->dev), dcmi); -+ if (ret) { -+ dev_err(dcmi->dev, "Unable to request irq %d\n", dcmi->irq); -+ return ret; -+ } -+ - return 0; - } - -@@ -1914,6 +1923,8 @@ static int dcmi_probe(struct platform_device *pdev) - if (irq <= 0) - return irq ? irq : -ENXIO; - -+ dcmi->irq = irq; -+ - dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!dcmi->res) { - dev_err(&pdev->dev, "Could not get resource\n"); -@@ -1926,14 +1937,6 @@ static int dcmi_probe(struct platform_device *pdev) - return PTR_ERR(dcmi->regs); - } - -- ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback, -- dcmi_irq_thread, IRQF_ONESHOT, -- dev_name(&pdev->dev), dcmi); -- if (ret) { -- dev_err(&pdev->dev, "Unable to request irq %d\n", irq); -- return ret; -- } -- - mclk = devm_clk_get(&pdev->dev, "mclk"); - if (IS_ERR(mclk)) { - if (PTR_ERR(mclk) != -EPROBE_DEFER) -diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c -index 07b2161392d21..5ba3e29f794fd 100644 ---- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c -+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c -@@ -467,7 +467,7 @@ static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = { - static int sun6i_video_open(struct file *file) - { - struct sun6i_video *video = video_drvdata(file); -- int ret; -+ int ret = 0; - - if (mutex_lock_interruptible(&video->lock)) - return -ERESTARTSYS; -@@ -481,10 +481,8 @@ static int sun6i_video_open(struct file *file) - goto fh_release; - - /* check if already powered */ -- if (!v4l2_fh_is_singular_file(file)) { -- ret = -EBUSY; -+ if (!v4l2_fh_is_singular_file(file)) - goto unlock; -- } - - ret = sun6i_csi_set_power(video->csi, true); - if (ret < 0) -diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c -index 1123768731676..484046471c03f 100644 ---- a/drivers/media/radio/radio-wl1273.c -+++ b/drivers/media/radio/radio-wl1273.c -@@ -1279,7 +1279,7 @@ static int wl1273_fm_vidioc_querycap(struct file *file, void *priv, - - strscpy(capability->driver, WL1273_FM_DRIVER_NAME, - sizeof(capability->driver)); -- strscpy(capability->card, "Texas Instruments Wl1273 FM Radio", -+ strscpy(capability->card, "TI Wl1273 FM Radio", - sizeof(capability->card)); - strscpy(capability->bus_info, radio->bus_type, - sizeof(capability->bus_info)); -diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c -index f491420d7b538..a972c0705ac79 100644 ---- a/drivers/media/radio/si470x/radio-si470x-i2c.c -+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c -@@ -11,7 +11,7 @@ - - /* driver definitions */ - #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>"; --#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" -+#define DRIVER_CARD "Silicon Labs Si470x FM Radio" - #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" - #define DRIVER_VERSION "1.0.2" - -diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c -index fedff68d8c496..3f8634a465730 100644 ---- a/drivers/media/radio/si470x/radio-si470x-usb.c -+++ b/drivers/media/radio/si470x/radio-si470x-usb.c -@@ -16,7 +16,7 @@ - - /* driver definitions */ - #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" --#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" -+#define DRIVER_CARD "Silicon Labs Si470x FM Radio" - #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" - #define DRIVER_VERSION "1.0.10" - -diff --git a/drivers/media/rc/ir_toy.c b/drivers/media/rc/ir_toy.c -index 48d52baec1a1c..1aa7989e756cc 100644 ---- a/drivers/media/rc/ir_toy.c -+++ b/drivers/media/rc/ir_toy.c -@@ -310,7 +310,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count) - buf[i] = cpu_to_be16(v); - } - -- buf[count] = 0xffff; -+ buf[count] = cpu_to_be16(0xffff); - - irtoy->tx_buf = buf; - irtoy->tx_len = size; -diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c -index 5bc23e8c6d91d..4f77d4ebacdc5 100644 ---- a/drivers/media/rc/ite-cir.c -+++ b/drivers/media/rc/ite-cir.c -@@ -242,7 +242,7 @@ static irqreturn_t ite_cir_isr(int irq, void *data) - } - - /* check for the receive interrupt */ -- if (iflags & ITE_IRQ_RX_FIFO) { -+ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { - /* read the FIFO bytes */ - rx_bytes = dev->params->get_rx_bytes(dev, rx_buf, - ITE_RX_FIFO_LEN); -diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c -index e03dd1f0144f0..137a71954aabf 100644 ---- a/drivers/media/rc/mceusb.c -+++ b/drivers/media/rc/mceusb.c -@@ -1386,6 +1386,7 @@ static void mceusb_dev_recv(struct urb *urb) - case -ECONNRESET: - case -ENOENT: - case -EILSEQ: -+ case -EPROTO: - case -ESHUTDOWN: - usb_unlink_urb(urb); - return; -diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c -index b91a1e845b972..506f52c1af101 100644 ---- a/drivers/media/spi/cxd2880-spi.c -+++ b/drivers/media/spi/cxd2880-spi.c -@@ -618,7 +618,7 @@ fail_frontend: - fail_attach: - dvb_unregister_adapter(&dvb_spi->adapter); - fail_adapter: -- if (!dvb_spi->vcc_supply) -+ if (dvb_spi->vcc_supply) - regulator_disable(dvb_spi->vcc_supply); - fail_regulator: - kfree(dvb_spi); -diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c -index 75617709c8ce2..82620613d56b8 100644 ---- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c -+++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c -@@ -564,6 +564,10 @@ static int vidtv_bridge_remove(struct platform_device *pdev) - - static void vidtv_bridge_dev_release(struct device *dev) - { -+ struct vidtv_dvb *dvb; -+ -+ dvb = dev_get_drvdata(dev); -+ kfree(dvb); - } - - static struct platform_device vidtv_bridge_dev = { -diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c -index 7865fa0a82957..cd5861a30b6f8 100644 ---- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c -+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c -@@ -931,8 +931,6 @@ static int mxl111sf_init(struct dvb_usb_device *d) - .len = sizeof(eeprom), .buf = eeprom }, - }; - -- mutex_init(&state->msg_lock); -- - ret = get_chip_info(state); - if (mxl_fail(ret)) - pr_err("failed to get chip info during probe"); -@@ -1074,6 +1072,14 @@ static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, - return 0; - } - -+static int mxl111sf_probe(struct dvb_usb_device *dev) -+{ -+ struct mxl111sf_state *state = d_to_priv(dev); -+ -+ mutex_init(&state->msg_lock); -+ return 0; -+} -+ - static struct dvb_usb_device_properties mxl111sf_props_dvbt = { - .driver_name = KBUILD_MODNAME, - .owner = THIS_MODULE, -@@ -1083,6 +1089,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = { - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - -+ .probe = mxl111sf_probe, - .i2c_algo = &mxl111sf_i2c_algo, - .frontend_attach = mxl111sf_frontend_attach_dvbt, - .tuner_attach = mxl111sf_attach_tuner, -@@ -1124,6 +1131,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = { - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - -+ .probe = mxl111sf_probe, - .i2c_algo = &mxl111sf_i2c_algo, - .frontend_attach = mxl111sf_frontend_attach_atsc, - .tuner_attach = mxl111sf_attach_tuner, -@@ -1165,6 +1173,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = { - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - -+ .probe = mxl111sf_probe, - .i2c_algo = &mxl111sf_i2c_algo, - .frontend_attach = mxl111sf_frontend_attach_mh, - .tuner_attach = mxl111sf_attach_tuner, -@@ -1233,6 +1242,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - -+ .probe = mxl111sf_probe, - .i2c_algo = &mxl111sf_i2c_algo, - .frontend_attach = mxl111sf_frontend_attach_atsc_mh, - .tuner_attach = mxl111sf_attach_tuner, -@@ -1311,6 +1321,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = { - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - -+ .probe = mxl111sf_probe, - .i2c_algo = &mxl111sf_i2c_algo, - .frontend_attach = mxl111sf_frontend_attach_mercury, - .tuner_attach = mxl111sf_attach_tuner, -@@ -1381,6 +1392,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = { - .generic_bulk_ctrl_endpoint = 0x02, - .generic_bulk_ctrl_endpoint_response = 0x81, - -+ .probe = mxl111sf_probe, - .i2c_algo = &mxl111sf_i2c_algo, - .frontend_attach = mxl111sf_frontend_attach_mercury_mh, - .tuner_attach = mxl111sf_attach_tuner, -diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c -index 1c39b61cde29b..86788771175b7 100644 ---- a/drivers/media/usb/dvb-usb/az6027.c -+++ b/drivers/media/usb/dvb-usb/az6027.c -@@ -391,6 +391,7 @@ static struct rc_map_table rc_map_az6027_table[] = { - /* remote control stuff (does not work with my box) */ - static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state) - { -+ *state = REMOTE_NO_KEY_PRESSED; - return 0; - } - -diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c -index 02b51d1a1b67c..aff60c10cb0b2 100644 ---- a/drivers/media/usb/dvb-usb/dibusb-common.c -+++ b/drivers/media/usb/dvb-usb/dibusb-common.c -@@ -223,7 +223,7 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) - u8 *buf; - int rc; - -- buf = kmalloc(2, GFP_KERNEL); -+ buf = kzalloc(2, GFP_KERNEL); - if (!buf) - return -ENOMEM; - -diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c -index c1e0dccb74088..948e22e29b42a 100644 ---- a/drivers/media/usb/em28xx/em28xx-cards.c -+++ b/drivers/media/usb/em28xx/em28xx-cards.c -@@ -4139,8 +4139,11 @@ static void em28xx_usb_disconnect(struct usb_interface *intf) - - em28xx_close_extension(dev); - -- if (dev->dev_next) -+ if (dev->dev_next) { -+ em28xx_close_extension(dev->dev_next); - em28xx_release_resources(dev->dev_next); -+ } -+ - em28xx_release_resources(dev); - - if (dev->dev_next) { -diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c -index 584fa400cd7d8..acc0bf7dbe2b1 100644 ---- a/drivers/media/usb/em28xx/em28xx-core.c -+++ b/drivers/media/usb/em28xx/em28xx-core.c -@@ -1154,8 +1154,9 @@ int em28xx_suspend_extension(struct em28xx *dev) - dev_info(&dev->intf->dev, "Suspending extensions\n"); - mutex_lock(&em28xx_devlist_mutex); - list_for_each_entry(ops, &em28xx_extension_devlist, next) { -- if (ops->suspend) -- ops->suspend(dev); -+ if (!ops->suspend) -+ continue; -+ ops->suspend(dev); - if (dev->dev_next) - ops->suspend(dev->dev_next); - } -diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c -index 3f650ede0c3dc..e293f6f3d1bc9 100644 ---- a/drivers/media/usb/tm6000/tm6000-video.c -+++ b/drivers/media/usb/tm6000/tm6000-video.c -@@ -852,8 +852,7 @@ static int vidioc_querycap(struct file *file, void *priv, - struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; - - strscpy(cap->driver, "tm6000", sizeof(cap->driver)); -- strscpy(cap->card, "Trident TVMaster TM5600/6000/6010", -- sizeof(cap->card)); -+ strscpy(cap->card, "Trident TM5600/6000/6010", sizeof(cap->card)); - usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | - V4L2_CAP_DEVICE_CAPS; -diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c -index bfda46a36dc50..38822cedd93a9 100644 ---- a/drivers/media/usb/ttusb-dec/ttusb_dec.c -+++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c -@@ -327,7 +327,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, - result = mutex_lock_interruptible(&dec->usb_mutex); - if (result) { - printk("%s: Failed to lock usb mutex.\n", __func__); -- goto err; -+ goto err_free; - } - - b[0] = 0xaa; -@@ -349,7 +349,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, - if (result) { - printk("%s: command bulk message failed: error %d\n", - __func__, result); -- goto err; -+ goto err_mutex_unlock; - } - - result = usb_bulk_msg(dec->udev, dec->result_pipe, b, -@@ -358,7 +358,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, - if (result) { - printk("%s: result bulk message failed: error %d\n", - __func__, result); -- goto err; -+ goto err_mutex_unlock; - } else { - if (debug) { - printk(KERN_DEBUG "%s: result: %*ph\n", -@@ -371,9 +371,9 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, - memcpy(cmd_result, &b[4], b[3]); - } - --err: -+err_mutex_unlock: - mutex_unlock(&dec->usb_mutex); -- -+err_free: - kfree(b); - return result; - } -diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c -index 9a791d8ef200d..c4bc67024534a 100644 ---- a/drivers/media/usb/uvc/uvc_driver.c -+++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -2194,6 +2194,7 @@ int uvc_register_video_device(struct uvc_device *dev, - const struct v4l2_file_operations *fops, - const struct v4l2_ioctl_ops *ioctl_ops) - { -+ const char *name; - int ret; - - /* Initialize the video buffers queue. */ -@@ -2222,16 +2223,20 @@ int uvc_register_video_device(struct uvc_device *dev, - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - default: - vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; -+ name = "Video Capture"; - break; - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; -+ name = "Video Output"; - break; - case V4L2_BUF_TYPE_META_CAPTURE: - vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; -+ name = "Metadata"; - break; - } - -- strscpy(vdev->name, dev->name, sizeof(vdev->name)); -+ snprintf(vdev->name, sizeof(vdev->name), "%s %u", name, -+ stream->header.bTerminalLink); - - /* - * Set the driver data before calling video_register_device, otherwise -diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c -index 6acb8013de08b..c9d208677bcd8 100644 ---- a/drivers/media/usb/uvc/uvc_v4l2.c -+++ b/drivers/media/usb/uvc/uvc_v4l2.c -@@ -472,10 +472,13 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, - uvc_simplify_fraction(&timeperframe.numerator, - &timeperframe.denominator, 8, 333); - -- if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - parm->parm.capture.timeperframe = timeperframe; -- else -+ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; -+ } else { - parm->parm.output.timeperframe = timeperframe; -+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; -+ } - - return 0; - } -diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c -index e16464606b140..9f37eaf28ce7e 100644 ---- a/drivers/media/usb/uvc/uvc_video.c -+++ b/drivers/media/usb/uvc/uvc_video.c -@@ -115,6 +115,11 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, - case 5: /* Invalid unit */ - case 6: /* Invalid control */ - case 7: /* Invalid Request */ -+ /* -+ * The firmware has not properly implemented -+ * the control or there has been a HW error. -+ */ -+ return -EIO; - case 8: /* Invalid value within range */ - return -EINVAL; - default: /* reserved or unknown */ -diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -index 47aff3b197426..80aaf07b16f28 100644 ---- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -@@ -744,10 +744,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64, - /* - * x86 is the only compat architecture with different struct alignment - * between 32-bit and 64-bit tasks. -- * -- * On all other architectures, v4l2_event32 and v4l2_event32_time32 are -- * the same as v4l2_event and v4l2_event_time32, so we can use the native -- * handlers, converting v4l2_event to v4l2_event_time32 if necessary. - */ - struct v4l2_event32 { - __u32 type; -@@ -765,21 +761,6 @@ struct v4l2_event32 { - __u32 reserved[8]; - }; - --#ifdef CONFIG_COMPAT_32BIT_TIME --struct v4l2_event32_time32 { -- __u32 type; -- union { -- compat_s64 value64; -- __u8 data[64]; -- } u; -- __u32 pending; -- __u32 sequence; -- struct old_timespec32 timestamp; -- __u32 id; -- __u32 reserved[8]; --}; --#endif -- - static int put_v4l2_event32(struct v4l2_event *p64, - struct v4l2_event32 __user *p32) - { -@@ -795,7 +776,22 @@ static int put_v4l2_event32(struct v4l2_event *p64, - return 0; - } - -+#endif -+ - #ifdef CONFIG_COMPAT_32BIT_TIME -+struct v4l2_event32_time32 { -+ __u32 type; -+ union { -+ compat_s64 value64; -+ __u8 data[64]; -+ } u; -+ __u32 pending; -+ __u32 sequence; -+ struct old_timespec32 timestamp; -+ __u32 id; -+ __u32 reserved[8]; -+}; -+ - static int put_v4l2_event32_time32(struct v4l2_event *p64, - struct v4l2_event32_time32 __user *p32) - { -@@ -811,7 +807,6 @@ static int put_v4l2_event32_time32(struct v4l2_event *p64, - return 0; - } - #endif --#endif - - struct v4l2_edid32 { - __u32 pad; -@@ -873,9 +868,7 @@ static int put_v4l2_edid32(struct v4l2_edid *p64, - #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) - #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) - #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) --#ifdef CONFIG_X86_64 - #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) --#endif - #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) - #endif - -@@ -929,10 +922,10 @@ unsigned int v4l2_compat_translate_cmd(unsigned int cmd) - #ifdef CONFIG_X86_64 - case VIDIOC_DQEVENT32: - return VIDIOC_DQEVENT; -+#endif - #ifdef CONFIG_COMPAT_32BIT_TIME - case VIDIOC_DQEVENT32_TIME32: - return VIDIOC_DQEVENT; --#endif - #endif - } - return cmd; -@@ -1025,10 +1018,10 @@ int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd) - #ifdef CONFIG_X86_64 - case VIDIOC_DQEVENT32: - return put_v4l2_event32(parg, arg); -+#endif - #ifdef CONFIG_COMPAT_32BIT_TIME - case VIDIOC_DQEVENT32_TIME32: - return put_v4l2_event32_time32(parg, arg); --#endif - #endif - } - return 0; -diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c -index 05d5db3d85e58..f4f67b385d00a 100644 ---- a/drivers/media/v4l2-core/v4l2-ioctl.c -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c -@@ -869,7 +869,7 @@ static void v4l_print_default(const void *arg, bool write_only) - pr_cont("driver-specific ioctl\n"); - } - --static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) -+static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl) - { - __u32 i; - -@@ -878,23 +878,41 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) - for (i = 0; i < c->count; i++) - c->controls[i].reserved2[0] = 0; - -- /* V4L2_CID_PRIVATE_BASE cannot be used as control class -- when using extended controls. -- Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL -- is it allowed for backwards compatibility. -- */ -- if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE) -- return 0; -- if (!c->which) -- return 1; -+ switch (c->which) { -+ case V4L2_CID_PRIVATE_BASE: -+ /* -+ * V4L2_CID_PRIVATE_BASE cannot be used as control class -+ * when using extended controls. -+ * Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL -+ * is it allowed for backwards compatibility. -+ */ -+ if (ioctl == VIDIOC_G_CTRL || ioctl == VIDIOC_S_CTRL) -+ return false; -+ break; -+ case V4L2_CTRL_WHICH_DEF_VAL: -+ /* Default value cannot be changed */ -+ if (ioctl == VIDIOC_S_EXT_CTRLS || -+ ioctl == VIDIOC_TRY_EXT_CTRLS) { -+ c->error_idx = c->count; -+ return false; -+ } -+ return true; -+ case V4L2_CTRL_WHICH_CUR_VAL: -+ return true; -+ case V4L2_CTRL_WHICH_REQUEST_VAL: -+ c->error_idx = c->count; -+ return false; -+ } -+ - /* Check that all controls are from the same control class. */ - for (i = 0; i < c->count; i++) { - if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) { -- c->error_idx = i; -- return 0; -+ c->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i : -+ c->count; -+ return false; - } - } -- return 1; -+ return true; - } - - static int check_fmt(struct file *file, enum v4l2_buf_type type) -@@ -2187,7 +2205,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, - ctrls.controls = &ctrl; - ctrl.id = p->id; - ctrl.value = p->value; -- if (check_ext_ctrls(&ctrls, 1)) { -+ if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) { - int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); - - if (ret == 0) -@@ -2206,6 +2224,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, - test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; - struct v4l2_ext_controls ctrls; - struct v4l2_ext_control ctrl; -+ int ret; - - if (vfh && vfh->ctrl_handler) - return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); -@@ -2221,9 +2240,11 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, - ctrls.controls = &ctrl; - ctrl.id = p->id; - ctrl.value = p->value; -- if (check_ext_ctrls(&ctrls, 1)) -- return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); -- return -EINVAL; -+ if (!check_ext_ctrls(&ctrls, VIDIOC_S_CTRL)) -+ return -EINVAL; -+ ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); -+ p->value = ctrl.value; -+ return ret; - } - - static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, -@@ -2243,8 +2264,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, - vfd, vfd->v4l2_dev->mdev, p); - if (ops->vidioc_g_ext_ctrls == NULL) - return -ENOTTY; -- return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : -- -EINVAL; -+ return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ? -+ ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL; - } - - static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, -@@ -2264,8 +2285,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, - vfd, vfd->v4l2_dev->mdev, p); - if (ops->vidioc_s_ext_ctrls == NULL) - return -ENOTTY; -- return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : -- -EINVAL; -+ return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ? -+ ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL; - } - - static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, -@@ -2285,8 +2306,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, - vfd, vfd->v4l2_dev->mdev, p); - if (ops->vidioc_try_ext_ctrls == NULL) - return -ENOTTY; -- return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : -- -EINVAL; -+ return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ? -+ ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL; - } - - /* -diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c -index d062c2f8250f4..75a8c38df9394 100644 ---- a/drivers/memory/fsl_ifc.c -+++ b/drivers/memory/fsl_ifc.c -@@ -263,7 +263,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) - - ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev); - if (ret < 0) -- goto err; -+ goto err_unmap_nandirq; - - init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait); - -@@ -272,7 +272,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) - if (ret != 0) { - dev_err(&dev->dev, "failed to install irq (%d)\n", - fsl_ifc_ctrl_dev->irq); -- goto err_irq; -+ goto err_unmap_nandirq; - } - - if (fsl_ifc_ctrl_dev->nand_irq) { -@@ -281,17 +281,16 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) - if (ret != 0) { - dev_err(&dev->dev, "failed to install irq (%d)\n", - fsl_ifc_ctrl_dev->nand_irq); -- goto err_nandirq; -+ goto err_free_irq; - } - } - - return 0; - --err_nandirq: -- free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev); -- irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq); --err_irq: -+err_free_irq: - free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev); -+err_unmap_nandirq: -+ irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq); - irq_dispose_mapping(fsl_ifc_ctrl_dev->irq); - err: - iounmap(fsl_ifc_ctrl_dev->gregs); -diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c -index 45eed659b0c6d..77a011d5ff8c1 100644 ---- a/drivers/memory/renesas-rpc-if.c -+++ b/drivers/memory/renesas-rpc-if.c -@@ -160,10 +160,62 @@ static const struct regmap_access_table rpcif_volatile_table = { - .n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges), - }; - -+ -+/* -+ * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed -+ * with proper width. Requires SMENR_SPIDE to be correctly set before! -+ */ -+static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) -+{ -+ struct rpcif *rpc = context; -+ -+ if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { -+ u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); -+ -+ if (spide == 0x8) { -+ *val = readb(rpc->base + reg); -+ return 0; -+ } else if (spide == 0xC) { -+ *val = readw(rpc->base + reg); -+ return 0; -+ } else if (spide != 0xF) { -+ return -EILSEQ; -+ } -+ } -+ -+ *val = readl(rpc->base + reg); -+ return 0; -+ -+} -+ -+static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val) -+{ -+ struct rpcif *rpc = context; -+ -+ if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { -+ u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); -+ -+ if (spide == 0x8) { -+ writeb(val, rpc->base + reg); -+ return 0; -+ } else if (spide == 0xC) { -+ writew(val, rpc->base + reg); -+ return 0; -+ } else if (spide != 0xF) { -+ return -EILSEQ; -+ } -+ } -+ -+ writel(val, rpc->base + reg); -+ return 0; -+} -+ - static const struct regmap_config rpcif_regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, -+ .reg_read = rpcif_reg_read, -+ .reg_write = rpcif_reg_write, - .fast_io = true, - .max_register = RPCIF_PHYINT, - .volatile_table = &rpcif_volatile_table, -@@ -173,17 +225,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); - struct resource *res; -- void __iomem *base; - - rpc->dev = dev; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); -- base = devm_ioremap_resource(&pdev->dev, res); -- if (IS_ERR(base)) -- return PTR_ERR(base); -+ rpc->base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(rpc->base)) -+ return PTR_ERR(rpc->base); - -- rpc->regmap = devm_regmap_init_mmio(&pdev->dev, base, -- &rpcif_regmap_config); -+ rpc->regmap = devm_regmap_init(&pdev->dev, NULL, rpc, &rpcif_regmap_config); - if (IS_ERR(rpc->regmap)) { - dev_err(&pdev->dev, - "failed to init regmap for rpcif, error %ld\n", -@@ -354,20 +404,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, - nbytes = op->data.nbytes; - rpc->xferlen = nbytes; - -- rpc->enable |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)) | -- RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); -+ rpc->enable |= RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); - } - } - EXPORT_SYMBOL(rpcif_prepare); - - int rpcif_manual_xfer(struct rpcif *rpc) - { -- u32 smenr, smcr, pos = 0, max = 4; -+ u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4; - int ret = 0; - -- if (rpc->bus_size == 2) -- max = 8; -- - pm_runtime_get_sync(rpc->dev); - - regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, -@@ -378,37 +424,36 @@ int rpcif_manual_xfer(struct rpcif *rpc) - regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option); - regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy); - regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr); -+ regmap_write(rpc->regmap, RPCIF_SMADR, rpc->smadr); - smenr = rpc->enable; - - switch (rpc->dir) { - case RPCIF_DATA_OUT: - while (pos < rpc->xferlen) { -- u32 nbytes = rpc->xferlen - pos; -- u32 data[2]; -+ u32 bytes_left = rpc->xferlen - pos; -+ u32 nbytes, data[2]; - - smcr = rpc->smcr | RPCIF_SMCR_SPIE; -- if (nbytes > max) { -- nbytes = max; -+ -+ /* nbytes may only be 1, 2, 4, or 8 */ -+ nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); -+ if (bytes_left > nbytes) - smcr |= RPCIF_SMCR_SSLKP; -- } -+ -+ smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); -+ regmap_write(rpc->regmap, RPCIF_SMENR, smenr); - - memcpy(data, rpc->buffer + pos, nbytes); -- if (nbytes > 4) { -+ if (nbytes == 8) { - regmap_write(rpc->regmap, RPCIF_SMWDR1, - data[0]); - regmap_write(rpc->regmap, RPCIF_SMWDR0, - data[1]); -- } else if (nbytes > 2) { -+ } else { - regmap_write(rpc->regmap, RPCIF_SMWDR0, - data[0]); -- } else { -- regmap_write(rpc->regmap, RPCIF_SMWDR0, -- data[0] << 16); - } - -- regmap_write(rpc->regmap, RPCIF_SMADR, -- rpc->smadr + pos); -- regmap_write(rpc->regmap, RPCIF_SMENR, smenr); - regmap_write(rpc->regmap, RPCIF_SMCR, smcr); - ret = wait_msg_xfer_end(rpc); - if (ret) -@@ -448,14 +493,16 @@ int rpcif_manual_xfer(struct rpcif *rpc) - break; - } - while (pos < rpc->xferlen) { -- u32 nbytes = rpc->xferlen - pos; -- u32 data[2]; -+ u32 bytes_left = rpc->xferlen - pos; -+ u32 nbytes, data[2]; - -- if (nbytes > max) -- nbytes = max; -+ /* nbytes may only be 1, 2, 4, or 8 */ -+ nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); - - regmap_write(rpc->regmap, RPCIF_SMADR, - rpc->smadr + pos); -+ smenr &= ~RPCIF_SMENR_SPIDE(0xF); -+ smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); - regmap_write(rpc->regmap, RPCIF_SMENR, smenr); - regmap_write(rpc->regmap, RPCIF_SMCR, - rpc->smcr | RPCIF_SMCR_SPIE); -@@ -463,18 +510,14 @@ int rpcif_manual_xfer(struct rpcif *rpc) - if (ret) - goto err_out; - -- if (nbytes > 4) { -+ if (nbytes == 8) { - regmap_read(rpc->regmap, RPCIF_SMRDR1, - &data[0]); - regmap_read(rpc->regmap, RPCIF_SMRDR0, - &data[1]); -- } else if (nbytes > 2) { -- regmap_read(rpc->regmap, RPCIF_SMRDR0, -- &data[0]); -- } else { -+ } else { - regmap_read(rpc->regmap, RPCIF_SMRDR0, - &data[0]); -- data[0] >>= 16; - } - memcpy(rpc->buffer + pos, data, nbytes); - -diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c -index c3462dbc8c22b..6fc90f2160e93 100644 ---- a/drivers/memory/tegra/tegra20-emc.c -+++ b/drivers/memory/tegra/tegra20-emc.c -@@ -1117,4 +1117,5 @@ module_platform_driver(tegra_emc_driver); - - MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>"); - MODULE_DESCRIPTION("NVIDIA Tegra20 EMC driver"); -+MODULE_SOFTDEP("pre: governor_simpleondemand"); - MODULE_LICENSE("GPL v2"); -diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c -index acf36676e388d..487e4cc2951e0 100644 ---- a/drivers/memstick/core/ms_block.c -+++ b/drivers/memstick/core/ms_block.c -@@ -1736,7 +1736,7 @@ static int msb_init_card(struct memstick_dev *card) - msb->pages_in_block = boot_block->attr.block_size * 2; - msb->block_size = msb->page_size * msb->pages_in_block; - -- if (msb->page_size > PAGE_SIZE) { -+ if ((size_t)msb->page_size > PAGE_SIZE) { - /* this isn't supported by linux at all, anyway*/ - dbg("device page %d size isn't supported", msb->page_size); - return -EINVAL; -diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c -index f9a93b0565e15..435d4c058b20e 100644 ---- a/drivers/memstick/host/jmb38x_ms.c -+++ b/drivers/memstick/host/jmb38x_ms.c -@@ -882,7 +882,7 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) - - iounmap(host->addr); - err_out_free: -- kfree(msh); -+ memstick_free_host(msh); - return NULL; - } - -diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c -index e79a0218c492e..1d35d147552d4 100644 ---- a/drivers/memstick/host/r592.c -+++ b/drivers/memstick/host/r592.c -@@ -838,15 +838,15 @@ static void r592_remove(struct pci_dev *pdev) - } - memstick_remove_host(dev->host); - -+ if (dev->dummy_dma_page) -+ dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->dummy_dma_page, -+ dev->dummy_dma_page_physical_address); -+ - free_irq(dev->irq, dev); - iounmap(dev->mmio); - pci_release_regions(pdev); - pci_disable_device(pdev); - memstick_free_host(dev->host); -- -- if (dev->dummy_dma_page) -- dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->dummy_dma_page, -- dev->dummy_dma_page_physical_address); - } - - #ifdef CONFIG_PM_SLEEP -diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index ca0edab91aeb6..d2f3452455389 100644 ---- a/drivers/mfd/Kconfig -+++ b/drivers/mfd/Kconfig -@@ -1194,6 +1194,7 @@ config MFD_SI476X_CORE - config MFD_SIMPLE_MFD_I2C - tristate - depends on I2C -+ select MFD_CORE - select REGMAP_I2C - help - This driver creates a single register map with the intention for it -diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c -index 20cb294c75122..5d3715a28b28e 100644 ---- a/drivers/mfd/altera-sysmgr.c -+++ b/drivers/mfd/altera-sysmgr.c -@@ -153,7 +153,7 @@ static int sysmgr_probe(struct platform_device *pdev) - if (!base) - return -ENOMEM; - -- sysmgr_config.max_register = resource_size(res) - 3; -+ sysmgr_config.max_register = resource_size(res) - 4; - regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config); - } - -diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c -index 83e676a096dc1..852129ea07666 100644 ---- a/drivers/mfd/dln2.c -+++ b/drivers/mfd/dln2.c -@@ -50,6 +50,7 @@ enum dln2_handle { - DLN2_HANDLE_GPIO, - DLN2_HANDLE_I2C, - DLN2_HANDLE_SPI, -+ DLN2_HANDLE_ADC, - DLN2_HANDLES - }; - -@@ -653,6 +654,7 @@ enum { - DLN2_ACPI_MATCH_GPIO = 0, - DLN2_ACPI_MATCH_I2C = 1, - DLN2_ACPI_MATCH_SPI = 2, -+ DLN2_ACPI_MATCH_ADC = 3, - }; - - static struct dln2_platform_data dln2_pdata_gpio = { -@@ -683,6 +685,16 @@ static struct mfd_cell_acpi_match dln2_acpi_match_spi = { - .adr = DLN2_ACPI_MATCH_SPI, - }; - -+/* Only one ADC port supported */ -+static struct dln2_platform_data dln2_pdata_adc = { -+ .handle = DLN2_HANDLE_ADC, -+ .port = 0, -+}; -+ -+static struct mfd_cell_acpi_match dln2_acpi_match_adc = { -+ .adr = DLN2_ACPI_MATCH_ADC, -+}; -+ - static const struct mfd_cell dln2_devs[] = { - { - .name = "dln2-gpio", -@@ -702,6 +714,12 @@ static const struct mfd_cell dln2_devs[] = { - .platform_data = &dln2_pdata_spi, - .pdata_size = sizeof(struct dln2_platform_data), - }, -+ { -+ .name = "dln2-adc", -+ .acpi_match = &dln2_acpi_match_adc, -+ .platform_data = &dln2_pdata_adc, -+ .pdata_size = sizeof(struct dln2_platform_data), -+ }, - }; - - static void dln2_stop(struct dln2_dev *dln2) -diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c -index 79f5c6a18815a..684a011a63968 100644 ---- a/drivers/mfd/mfd-core.c -+++ b/drivers/mfd/mfd-core.c -@@ -198,6 +198,7 @@ static int mfd_add_device(struct device *parent, int id, - if (of_device_is_compatible(np, cell->of_compatible)) { - /* Ignore 'disabled' devices error free */ - if (!of_device_is_available(np)) { -+ of_node_put(np); - ret = 0; - goto fail_alias; - } -@@ -205,6 +206,7 @@ static int mfd_add_device(struct device *parent, int id, - ret = mfd_match_of_node_to_dev(pdev, np, cell); - if (ret == -EAGAIN) - continue; -+ of_node_put(np); - if (ret) - goto fail_alias; - -diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c -index 6fb206da27298..265464b5d7cc5 100644 ---- a/drivers/mfd/motorola-cpcap.c -+++ b/drivers/mfd/motorola-cpcap.c -@@ -202,6 +202,13 @@ static const struct of_device_id cpcap_of_match[] = { - }; - MODULE_DEVICE_TABLE(of, cpcap_of_match); - -+static const struct spi_device_id cpcap_spi_ids[] = { -+ { .name = "cpcap", }, -+ { .name = "6556002", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(spi, cpcap_spi_ids); -+ - static const struct regmap_config cpcap_regmap_config = { - .reg_bits = 16, - .reg_stride = 4, -@@ -342,6 +349,7 @@ static struct spi_driver cpcap_driver = { - .pm = &cpcap_pm, - }, - .probe = cpcap_probe, -+ .id_table = cpcap_spi_ids, - }; - module_spi_driver(cpcap_driver); - -diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c -index 6b7956604a0f0..9890882db1ed3 100644 ---- a/drivers/mfd/sprd-sc27xx-spi.c -+++ b/drivers/mfd/sprd-sc27xx-spi.c -@@ -236,6 +236,12 @@ static const struct of_device_id sprd_pmic_match[] = { - }; - MODULE_DEVICE_TABLE(of, sprd_pmic_match); - -+static const struct spi_device_id sprd_pmic_spi_ids[] = { -+ { .name = "sc2731", .driver_data = (unsigned long)&sc2731_data }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(spi, sprd_pmic_spi_ids); -+ - static struct spi_driver sprd_pmic_driver = { - .driver = { - .name = "sc27xx-pmic", -@@ -243,6 +249,7 @@ static struct spi_driver sprd_pmic_driver = { - .pm = &sprd_pmic_pm_ops, - }, - .probe = sprd_pmic_probe, -+ .id_table = sprd_pmic_spi_ids, - }; - - static int __init sprd_pmic_init(void) -diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c -index baf83594a01d3..5121edb0d9eff 100644 ---- a/drivers/misc/cardreader/rtsx_pcr.c -+++ b/drivers/misc/cardreader/rtsx_pcr.c -@@ -1803,8 +1803,6 @@ static int rtsx_pci_runtime_suspend(struct device *device) - mutex_lock(&pcr->pcr_mutex); - rtsx_pci_power_off(pcr, HOST_ENTER_S3); - -- free_irq(pcr->irq, (void *)pcr); -- - mutex_unlock(&pcr->pcr_mutex); - - pcr->is_runtime_suspended = true; -@@ -1825,8 +1823,6 @@ static int rtsx_pci_runtime_resume(struct device *device) - mutex_lock(&pcr->pcr_mutex); - - rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00); -- rtsx_pci_acquire_irq(pcr); -- synchronize_irq(pcr->irq); - - if (pcr->ops->fetch_vendor_settings) - pcr->ops->fetch_vendor_settings(pcr); -diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c -index 632325474233a..b38978a3b3ffa 100644 ---- a/drivers/misc/eeprom/at25.c -+++ b/drivers/misc/eeprom/at25.c -@@ -376,7 +376,6 @@ MODULE_DEVICE_TABLE(spi, at25_spi_ids); - static int at25_probe(struct spi_device *spi) - { - struct at25_data *at25 = NULL; -- struct spi_eeprom chip; - int err; - int sr; - u8 id[FM25_ID_LEN]; -@@ -389,15 +388,18 @@ static int at25_probe(struct spi_device *spi) - if (match && !strcmp(match->compatible, "cypress,fm25")) - is_fram = 1; - -+ at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL); -+ if (!at25) -+ return -ENOMEM; -+ - /* Chip description */ -- if (!spi->dev.platform_data) { -- if (!is_fram) { -- err = at25_fw_to_chip(&spi->dev, &chip); -- if (err) -- return err; -- } -- } else -- chip = *(struct spi_eeprom *)spi->dev.platform_data; -+ if (spi->dev.platform_data) { -+ memcpy(&at25->chip, spi->dev.platform_data, sizeof(at25->chip)); -+ } else if (!is_fram) { -+ err = at25_fw_to_chip(&spi->dev, &at25->chip); -+ if (err) -+ return err; -+ } - - /* Ping the chip ... the status register is pretty portable, - * unlike probing manufacturer IDs. We do expect that system -@@ -409,12 +411,7 @@ static int at25_probe(struct spi_device *spi) - return -ENXIO; - } - -- at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL); -- if (!at25) -- return -ENOMEM; -- - mutex_init(&at25->lock); -- at25->chip = chip; - at25->spi = spi; - spi_set_drvdata(spi, at25); - -@@ -431,7 +428,7 @@ static int at25_probe(struct spi_device *spi) - dev_err(&spi->dev, "Error: unsupported size (id %02x)\n", id[7]); - return -ENODEV; - } -- chip.byte_len = int_pow(2, id[7] - 0x21 + 4) * 1024; -+ at25->chip.byte_len = int_pow(2, id[7] - 0x21 + 4) * 1024; - - if (at25->chip.byte_len > 64 * 1024) - at25->chip.flags |= EE_ADDR3; -@@ -464,7 +461,7 @@ static int at25_probe(struct spi_device *spi) - at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM; - at25->nvmem_config.name = dev_name(&spi->dev); - at25->nvmem_config.dev = &spi->dev; -- at25->nvmem_config.read_only = chip.flags & EE_READONLY; -+ at25->nvmem_config.read_only = at25->chip.flags & EE_READONLY; - at25->nvmem_config.root_only = true; - at25->nvmem_config.owner = THIS_MODULE; - at25->nvmem_config.compat = true; -@@ -474,17 +471,18 @@ static int at25_probe(struct spi_device *spi) - at25->nvmem_config.priv = at25; - at25->nvmem_config.stride = 1; - at25->nvmem_config.word_size = 1; -- at25->nvmem_config.size = chip.byte_len; -+ at25->nvmem_config.size = at25->chip.byte_len; - - at25->nvmem = devm_nvmem_register(&spi->dev, &at25->nvmem_config); - if (IS_ERR(at25->nvmem)) - return PTR_ERR(at25->nvmem); - - dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n", -- (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), -- (chip.byte_len < 1024) ? "Byte" : "KByte", -+ (at25->chip.byte_len < 1024) ? -+ at25->chip.byte_len : (at25->chip.byte_len / 1024), -+ (at25->chip.byte_len < 1024) ? "Byte" : "KByte", - at25->chip.name, is_fram ? "fram" : "eeprom", -- (chip.flags & EE_READONLY) ? " (readonly)" : "", -+ (at25->chip.flags & EE_READONLY) ? " (readonly)" : "", - at25->chip.page_size); - return 0; - } -diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c -index ad6ced4546556..f3002653bd010 100644 ---- a/drivers/misc/fastrpc.c -+++ b/drivers/misc/fastrpc.c -@@ -719,16 +719,18 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) - static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen) - { - u64 size = 0; -- int i; -+ int oix; - - size = ALIGN(metalen, FASTRPC_ALIGN); -- for (i = 0; i < ctx->nscalars; i++) { -+ for (oix = 0; oix < ctx->nbufs; oix++) { -+ int i = ctx->olaps[oix].raix; -+ - if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) { - -- if (ctx->olaps[i].offset == 0) -+ if (ctx->olaps[oix].offset == 0) - size = ALIGN(size, FASTRPC_ALIGN); - -- size += (ctx->olaps[i].mend - ctx->olaps[i].mstart); -+ size += (ctx->olaps[oix].mend - ctx->olaps[oix].mstart); - } - } - -diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c -index 380f9aa56eb26..1e8f1bb3cad7c 100644 ---- a/drivers/mmc/host/dw_mmc.c -+++ b/drivers/mmc/host/dw_mmc.c -@@ -2086,7 +2086,8 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t) - * delayed. Allowing the transfer to take place - * avoids races and keeps things simple. - */ -- if (err != -ETIMEDOUT) { -+ if (err != -ETIMEDOUT && -+ host->dir_status == DW_MCI_RECV_STATUS) { - state = STATE_SENDING_DATA; - continue; - } -diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c -index f4c8e1a61f537..b431cdd27353b 100644 ---- a/drivers/mmc/host/mmc_spi.c -+++ b/drivers/mmc/host/mmc_spi.c -@@ -1514,6 +1514,12 @@ static int mmc_spi_remove(struct spi_device *spi) - return 0; - } - -+static const struct spi_device_id mmc_spi_dev_ids[] = { -+ { "mmc-spi-slot"}, -+ { }, -+}; -+MODULE_DEVICE_TABLE(spi, mmc_spi_dev_ids); -+ - static const struct of_device_id mmc_spi_of_match_table[] = { - { .compatible = "mmc-spi-slot", }, - {}, -@@ -1525,6 +1531,7 @@ static struct spi_driver mmc_spi_driver = { - .name = "mmc_spi", - .of_match_table = mmc_spi_of_match_table, - }, -+ .id_table = mmc_spi_dev_ids, - .probe = mmc_spi_probe, - .remove = mmc_spi_remove, - }; -diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c -index 6c9d38132f74c..16d1c7a43d331 100644 ---- a/drivers/mmc/host/moxart-mmc.c -+++ b/drivers/mmc/host/moxart-mmc.c -@@ -566,37 +566,37 @@ static int moxart_probe(struct platform_device *pdev) - if (!mmc) { - dev_err(dev, "mmc_alloc_host failed\n"); - ret = -ENOMEM; -- goto out; -+ goto out_mmc; - } - - ret = of_address_to_resource(node, 0, &res_mmc); - if (ret) { - dev_err(dev, "of_address_to_resource failed\n"); -- goto out; -+ goto out_mmc; - } - - irq = irq_of_parse_and_map(node, 0); - if (irq <= 0) { - dev_err(dev, "irq_of_parse_and_map failed\n"); - ret = -EINVAL; -- goto out; -+ goto out_mmc; - } - - clk = devm_clk_get(dev, NULL); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); -- goto out; -+ goto out_mmc; - } - - reg_mmc = devm_ioremap_resource(dev, &res_mmc); - if (IS_ERR(reg_mmc)) { - ret = PTR_ERR(reg_mmc); -- goto out; -+ goto out_mmc; - } - - ret = mmc_of_parse(mmc); - if (ret) -- goto out; -+ goto out_mmc; - - host = mmc_priv(mmc); - host->mmc = mmc; -@@ -621,6 +621,14 @@ static int moxart_probe(struct platform_device *pdev) - ret = -EPROBE_DEFER; - goto out; - } -+ if (!IS_ERR(host->dma_chan_tx)) { -+ dma_release_channel(host->dma_chan_tx); -+ host->dma_chan_tx = NULL; -+ } -+ if (!IS_ERR(host->dma_chan_rx)) { -+ dma_release_channel(host->dma_chan_rx); -+ host->dma_chan_rx = NULL; -+ } - dev_dbg(dev, "PIO mode transfer enabled\n"); - host->have_dma = false; - } else { -@@ -675,6 +683,11 @@ static int moxart_probe(struct platform_device *pdev) - return 0; - - out: -+ if (!IS_ERR_OR_NULL(host->dma_chan_tx)) -+ dma_release_channel(host->dma_chan_tx); -+ if (!IS_ERR_OR_NULL(host->dma_chan_rx)) -+ dma_release_channel(host->dma_chan_rx); -+out_mmc: - if (mmc) - mmc_free_host(mmc); - return ret; -@@ -687,9 +700,9 @@ static int moxart_remove(struct platform_device *pdev) - - dev_set_drvdata(&pdev->dev, NULL); - -- if (!IS_ERR(host->dma_chan_tx)) -+ if (!IS_ERR_OR_NULL(host->dma_chan_tx)) - dma_release_channel(host->dma_chan_tx); -- if (!IS_ERR(host->dma_chan_rx)) -+ if (!IS_ERR_OR_NULL(host->dma_chan_rx)) - dma_release_channel(host->dma_chan_rx); - mmc_remove_host(mmc); - mmc_free_host(mmc); -diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c -index b06b4dcb7c782..9e6dab7e34242 100644 ---- a/drivers/mmc/host/mtk-sd.c -+++ b/drivers/mmc/host/mtk-sd.c -@@ -8,6 +8,7 @@ - #include <linux/clk.h> - #include <linux/delay.h> - #include <linux/dma-mapping.h> -+#include <linux/iopoll.h> - #include <linux/ioport.h> - #include <linux/irq.h> - #include <linux/of_address.h> -@@ -2330,6 +2331,7 @@ static void msdc_cqe_enable(struct mmc_host *mmc) - static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) - { - struct msdc_host *host = mmc_priv(mmc); -+ unsigned int val = 0; - - /* disable cmdq irq */ - sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INT_CMDQ); -@@ -2339,6 +2341,9 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) - if (recovery) { - sdr_set_field(host->base + MSDC_DMA_CTRL, - MSDC_DMA_CTRL_STOP, 1); -+ if (WARN_ON(readl_poll_timeout(host->base + MSDC_DMA_CFG, val, -+ !(val & MSDC_DMA_CFG_STS), 1, 3000))) -+ return; - msdc_reset_hw(host); - } - } -diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c -index 947581de78601..8c3655d3be961 100644 ---- a/drivers/mmc/host/mxs-mmc.c -+++ b/drivers/mmc/host/mxs-mmc.c -@@ -552,6 +552,11 @@ static const struct of_device_id mxs_mmc_dt_ids[] = { - }; - MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); - -+static void mxs_mmc_regulator_disable(void *regulator) -+{ -+ regulator_disable(regulator); -+} -+ - static int mxs_mmc_probe(struct platform_device *pdev) - { - struct device_node *np = pdev->dev.of_node; -@@ -591,6 +596,11 @@ static int mxs_mmc_probe(struct platform_device *pdev) - "Failed to enable vmmc regulator: %d\n", ret); - goto out_mmc_free; - } -+ -+ ret = devm_add_action_or_reset(&pdev->dev, mxs_mmc_regulator_disable, -+ reg_vmmc); -+ if (ret) -+ goto out_mmc_free; - } - - ssp->clk = devm_clk_get(&pdev->dev, NULL); -diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c -index a4407f391f66a..f5b2684ad8058 100644 ---- a/drivers/mmc/host/renesas_sdhi_core.c -+++ b/drivers/mmc/host/renesas_sdhi_core.c -@@ -673,7 +673,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) - - /* Issue CMD19 twice for each tap */ - for (i = 0; i < 2 * priv->tap_num; i++) { -- int cmd_error; -+ int cmd_error = 0; - - /* Set sampling clock position */ - sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, i % priv->tap_num); -diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c -index e658f01742420..60f19369de845 100644 ---- a/drivers/mmc/host/sdhci-esdhc-imx.c -+++ b/drivers/mmc/host/sdhci-esdhc-imx.c -@@ -300,7 +300,6 @@ static struct esdhc_soc_data usdhc_imx8qxp_data = { - .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING - | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 - | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES -- | ESDHC_FLAG_CQHCI - | ESDHC_FLAG_STATE_LOST_IN_LPMODE - | ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME, - }; -@@ -309,7 +308,6 @@ static struct esdhc_soc_data usdhc_imx8mm_data = { - .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING - | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 - | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES -- | ESDHC_FLAG_CQHCI - | ESDHC_FLAG_STATE_LOST_IN_LPMODE, - }; - -diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c -index 8f4d1f003f656..fd188b6d88f49 100644 ---- a/drivers/mmc/host/sdhci-omap.c -+++ b/drivers/mmc/host/sdhci-omap.c -@@ -62,6 +62,8 @@ - #define SDHCI_OMAP_IE 0x234 - #define INT_CC_EN BIT(0) - -+#define SDHCI_OMAP_ISE 0x238 -+ - #define SDHCI_OMAP_AC12 0x23c - #define AC12_V1V8_SIGEN BIT(19) - #define AC12_SCLK_SEL BIT(23) -@@ -113,6 +115,8 @@ struct sdhci_omap_host { - u32 hctl; - u32 sysctl; - u32 capa; -+ u32 ie; -+ u32 ise; - }; - - static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host); -@@ -682,7 +686,8 @@ static void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode, - { - struct mmc_host *mmc = host->mmc; - -- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); -+ if (!IS_ERR(mmc->supply.vmmc)) -+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); - } - - static int sdhci_omap_enable_dma(struct sdhci_host *host) -@@ -1244,14 +1249,23 @@ static void sdhci_omap_context_save(struct sdhci_omap_host *omap_host) - { - omap_host->con = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); - omap_host->hctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL); -+ omap_host->sysctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); - omap_host->capa = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); -+ omap_host->ie = sdhci_omap_readl(omap_host, SDHCI_OMAP_IE); -+ omap_host->ise = sdhci_omap_readl(omap_host, SDHCI_OMAP_ISE); - } - -+/* Order matters here, HCTL must be restored in two phases */ - static void sdhci_omap_context_restore(struct sdhci_omap_host *omap_host) - { -- sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, omap_host->con); - sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl); - sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, omap_host->capa); -+ sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl); -+ -+ sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, omap_host->sysctl); -+ sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, omap_host->con); -+ sdhci_omap_writel(omap_host, SDHCI_OMAP_IE, omap_host->ie); -+ sdhci_omap_writel(omap_host, SDHCI_OMAP_ISE, omap_host->ise); - } - - static int __maybe_unused sdhci_omap_suspend(struct device *dev) -diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index 2d80a04e11d87..7728f26adb19f 100644 ---- a/drivers/mmc/host/sdhci.c -+++ b/drivers/mmc/host/sdhci.c -@@ -771,7 +771,19 @@ static void sdhci_adma_table_pre(struct sdhci_host *host, - len -= offset; - } - -- BUG_ON(len > 65536); -+ /* -+ * The block layer forces a minimum segment size of PAGE_SIZE, -+ * so 'len' can be too big here if PAGE_SIZE >= 64KiB. Write -+ * multiple descriptors, noting that the ADMA table is sized -+ * for 4KiB chunks anyway, so it will be big enough. -+ */ -+ while (len > host->max_adma) { -+ int n = 32 * 1024; /* 32KiB*/ -+ -+ __sdhci_adma_write_desc(host, &desc, addr, n, ADMA2_TRAN_VALID); -+ addr += n; -+ len -= n; -+ } - - /* tran, valid */ - if (len) -@@ -3952,6 +3964,7 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev, - * descriptor for each segment, plus 1 for a nop end descriptor. - */ - host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1; -+ host->max_adma = 65536; - - host->max_timeout_count = 0xE; - -@@ -4617,10 +4630,12 @@ int sdhci_setup_host(struct sdhci_host *host) - * be larger than 64 KiB though. - */ - if (host->flags & SDHCI_USE_ADMA) { -- if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) -+ if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) { -+ host->max_adma = 65532; /* 32-bit alignment */ - mmc->max_seg_size = 65535; -- else -+ } else { - mmc->max_seg_size = 65536; -+ } - } else { - mmc->max_seg_size = mmc->max_req_size; - } -diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h -index e8d04e42a5afd..6c689be3e48f6 100644 ---- a/drivers/mmc/host/sdhci.h -+++ b/drivers/mmc/host/sdhci.h -@@ -340,7 +340,8 @@ struct sdhci_adma2_64_desc { - - /* - * Maximum segments assuming a 512KiB maximum requisition size and a minimum -- * 4KiB page size. -+ * 4KiB page size. Note this also allows enough for multiple descriptors in -+ * case of PAGE_SIZE >= 64KiB. - */ - #define SDHCI_MAX_SEGS 128 - -@@ -543,6 +544,7 @@ struct sdhci_host { - unsigned int blocks; /* remaining PIO blocks */ - - int sg_count; /* Mapped sg entries */ -+ int max_adma; /* Max. length in ADMA descriptor */ - - void *adma_table; /* ADMA descriptor table */ - void *align_buffer; /* Bounce buffer */ -diff --git a/drivers/most/most_usb.c b/drivers/most/most_usb.c -index 2640c5b326a49..acabb7715b423 100644 ---- a/drivers/most/most_usb.c -+++ b/drivers/most/most_usb.c -@@ -149,7 +149,8 @@ static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf) - retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - DRCI_READ_REQ, req_type, - 0x0000, -- reg, dma_buf, sizeof(*dma_buf), 5 * HZ); -+ reg, dma_buf, sizeof(*dma_buf), -+ USB_CTRL_GET_TIMEOUT); - *buf = le16_to_cpu(*dma_buf); - kfree(dma_buf); - -@@ -176,7 +177,7 @@ static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) - reg, - NULL, - 0, -- 5 * HZ); -+ USB_CTRL_SET_TIMEOUT); - } - - static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep) -diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c -index 9802e265fca80..2b317ed6c103f 100644 ---- a/drivers/mtd/devices/mtd_dataflash.c -+++ b/drivers/mtd/devices/mtd_dataflash.c -@@ -96,6 +96,13 @@ struct dataflash { - struct mtd_info mtd; - }; - -+static const struct spi_device_id dataflash_dev_ids[] = { -+ { "at45" }, -+ { "dataflash" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(spi, dataflash_dev_ids); -+ - #ifdef CONFIG_OF - static const struct of_device_id dataflash_dt_ids[] = { - { .compatible = "atmel,at45", }, -@@ -927,6 +934,7 @@ static struct spi_driver dataflash_driver = { - .name = "mtd_dataflash", - .of_match_table = of_match_ptr(dataflash_dt_ids), - }, -+ .id_table = dataflash_dev_ids, - - .probe = dataflash_probe, - .remove = dataflash_remove, -diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c -index c8fd7f758938b..1532291989471 100644 ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -724,8 +724,6 @@ int del_mtd_device(struct mtd_info *mtd) - - mutex_lock(&mtd_table_mutex); - -- debugfs_remove_recursive(mtd->dbg.dfs_dir); -- - if (idr_find(&mtd_idr, mtd->index) != mtd) { - ret = -ENODEV; - goto out_error; -@@ -741,6 +739,8 @@ int del_mtd_device(struct mtd_info *mtd) - mtd->index, mtd->name, mtd->usecount); - ret = -EBUSY; - } else { -+ debugfs_remove_recursive(mtd->dbg.dfs_dir); -+ - /* Try to remove the NVMEM provider */ - if (mtd->nvmem) - nvmem_unregister(mtd->nvmem); -diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c -index ff1697f899ba6..13de39aa3288f 100644 ---- a/drivers/mtd/nand/raw/ams-delta.c -+++ b/drivers/mtd/nand/raw/ams-delta.c -@@ -217,9 +217,8 @@ static int gpio_nand_setup_interface(struct nand_chip *this, int csline, - - static int gpio_nand_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -370,6 +369,13 @@ static int gpio_nand_probe(struct platform_device *pdev) - /* Release write protection */ - gpiod_set_value(priv->gpiod_nwp, 0); - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - /* Scan to find existence of the device */ - err = nand_scan(this, 1); - if (err) -diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c -index 9cbcc698c64d8..53bd10738418b 100644 ---- a/drivers/mtd/nand/raw/arasan-nand-controller.c -+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c -@@ -973,6 +973,21 @@ static int anfc_setup_interface(struct nand_chip *chip, int target, - nvddr = nand_get_nvddr_timings(conf); - if (IS_ERR(nvddr)) - return PTR_ERR(nvddr); -+ -+ /* -+ * The controller only supports data payload requests which are -+ * a multiple of 4. In practice, most data accesses are 4-byte -+ * aligned and this is not an issue. However, rounding up will -+ * simply be refused by the controller if we reached the end of -+ * the device *and* we are using the NV-DDR interface(!). In -+ * this situation, unaligned data requests ending at the device -+ * boundary will confuse the controller and cannot be performed. -+ * -+ * This is something that happens in nand_read_subpage() when -+ * selecting software ECC support and must be avoided. -+ */ -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT) -+ return -ENOTSUPP; - } else { - sdr = nand_get_sdr_timings(conf); - if (IS_ERR(sdr)) -diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c -index 99116896cfd6c..5aa3a06d740c7 100644 ---- a/drivers/mtd/nand/raw/au1550nd.c -+++ b/drivers/mtd/nand/raw/au1550nd.c -@@ -239,9 +239,8 @@ static int au1550nd_exec_op(struct nand_chip *this, - - static int au1550nd_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -310,6 +309,13 @@ static int au1550nd_probe(struct platform_device *pdev) - if (pd->devwidth) - this->options |= NAND_BUSWIDTH_16; - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - ret = nand_scan(this, 1); - if (ret) { - dev_err(&pdev->dev, "NAND scan failed with %d\n", ret); -diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c -index a3e66155ae405..6b2bda815b880 100644 ---- a/drivers/mtd/nand/raw/fsmc_nand.c -+++ b/drivers/mtd/nand/raw/fsmc_nand.c -@@ -15,6 +15,7 @@ - - #include <linux/clk.h> - #include <linux/completion.h> -+#include <linux/delay.h> - #include <linux/dmaengine.h> - #include <linux/dma-direction.h> - #include <linux/dma-mapping.h> -@@ -93,6 +94,14 @@ - - #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) - -+/* -+ * According to SPEAr300 Reference Manual (RM0082) -+ * TOUDEL = 7ns (Output delay from the flip-flops to the board) -+ * TINDEL = 5ns (Input delay from the board to the flipflop) -+ */ -+#define TOUTDEL 7000 -+#define TINDEL 5000 -+ - struct fsmc_nand_timings { - u8 tclr; - u8 tar; -@@ -277,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, - { - unsigned long hclk = clk_get_rate(host->clk); - unsigned long hclkn = NSEC_PER_SEC / hclk; -- u32 thiz, thold, twait, tset; -+ u32 thiz, thold, twait, tset, twait_min; - - if (sdrt->tRC_min < 30000) - return -EOPNOTSUPP; -@@ -309,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, - else if (tims->thold > FSMC_THOLD_MASK) - tims->thold = FSMC_THOLD_MASK; - -- twait = max(sdrt->tRP_min, sdrt->tWP_min); -- tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; -- if (tims->twait == 0) -- tims->twait = 1; -- else if (tims->twait > FSMC_TWAIT_MASK) -- tims->twait = FSMC_TWAIT_MASK; -- - tset = max(sdrt->tCS_min - sdrt->tWP_min, - sdrt->tCEA_max - sdrt->tREA_max); - tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; -@@ -324,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, - else if (tims->tset > FSMC_TSET_MASK) - tims->tset = FSMC_TSET_MASK; - -+ /* -+ * According to SPEAr300 Reference Manual (RM0082) which gives more -+ * information related to FSMSC timings than the SPEAr600 one (RM0305), -+ * twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL -+ */ -+ twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000) -+ + TOUTDEL + TINDEL; -+ twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min); -+ -+ tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; -+ if (tims->twait == 0) -+ tims->twait = 1; -+ else if (tims->twait > FSMC_TWAIT_MASK) -+ tims->twait = FSMC_TWAIT_MASK; -+ - return 0; - } - -@@ -438,8 +455,10 @@ static int fsmc_correct_ecc1(struct nand_chip *chip, - unsigned char *read_ecc, - unsigned char *calc_ecc) - { -+ bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER; -+ - return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc, -- chip->ecc.size, false); -+ chip->ecc.size, sm_order); - } - - /* Count the number of 0's in buff upto a max of max_bits */ -@@ -662,6 +681,9 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, - instr->ctx.waitrdy.timeout_ms); - break; - } -+ -+ if (instr->delay_ns) -+ ndelay(instr->delay_ns); - } - - return ret; -diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c -index fb7a086de35e5..fdf073d2e1b6c 100644 ---- a/drivers/mtd/nand/raw/gpio.c -+++ b/drivers/mtd/nand/raw/gpio.c -@@ -163,9 +163,8 @@ static int gpio_nand_exec_op(struct nand_chip *chip, - - static int gpio_nand_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -365,6 +364,13 @@ static int gpio_nand_probe(struct platform_device *pdev) - if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) - gpiod_direction_output(gpiomtd->nwp, 1); - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - ret = nand_scan(chip, 1); - if (ret) - goto err_wp; -diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c -index b9784f3da7a11..7c1c80dae826a 100644 ---- a/drivers/mtd/nand/raw/intel-nand-controller.c -+++ b/drivers/mtd/nand/raw/intel-nand-controller.c -@@ -609,6 +609,11 @@ static int ebu_nand_probe(struct platform_device *pdev) - dev_err(dev, "failed to get chip select: %d\n", ret); - return ret; - } -+ if (cs >= MAX_CS) { -+ dev_err(dev, "got invalid chip select: %d\n", cs); -+ return -EINVAL; -+ } -+ - ebu_host->cs_num = cs; - - resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs); -diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c -index bcd4a556c959c..cb293c50acb87 100644 ---- a/drivers/mtd/nand/raw/mpc5121_nfc.c -+++ b/drivers/mtd/nand/raw/mpc5121_nfc.c -@@ -605,9 +605,8 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) - - static int mpc5121_nfc_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -772,6 +771,13 @@ static int mpc5121_nfc_probe(struct platform_device *op) - goto error; - } - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - /* Detect NAND chips */ - retval = nand_scan(chip, be32_to_cpup(chips_no)); - if (retval) { -diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c -index 3d6c6e8805207..a130320de4128 100644 ---- a/drivers/mtd/nand/raw/nand_base.c -+++ b/drivers/mtd/nand/raw/nand_base.c -@@ -926,7 +926,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, - struct nand_sdr_timings *spec_timings) - { - const struct nand_controller_ops *ops = chip->controller->ops; -- int best_mode = 0, mode, ret; -+ int best_mode = 0, mode, ret = -EOPNOTSUPP; - - iface->type = NAND_SDR_IFACE; - -@@ -977,7 +977,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip, - struct nand_nvddr_timings *spec_timings) - { - const struct nand_controller_ops *ops = chip->controller->ops; -- int best_mode = 0, mode, ret; -+ int best_mode = 0, mode, ret = -EOPNOTSUPP; - - iface->type = NAND_NVDDR_IFACE; - -@@ -1837,7 +1837,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) - NAND_OP_CMD(NAND_CMD_ERASE1, 0), - NAND_OP_ADDR(2, addrs, 0), - NAND_OP_CMD(NAND_CMD_ERASE2, -- NAND_COMMON_TIMING_MS(conf, tWB_max)), -+ NAND_COMMON_TIMING_NS(conf, tWB_max)), - NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max), - 0), - }; -diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c -index 66211c9311d2f..2c87c7d892058 100644 ---- a/drivers/mtd/nand/raw/orion_nand.c -+++ b/drivers/mtd/nand/raw/orion_nand.c -@@ -85,9 +85,8 @@ static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) - - static int orion_nand_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -190,6 +189,13 @@ static int __init orion_nand_probe(struct platform_device *pdev) - return ret; - } - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ nc->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - ret = nand_scan(nc, 1); - if (ret) - goto no_dev; -diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c -index 789f33312c15f..c176036453ed9 100644 ---- a/drivers/mtd/nand/raw/pasemi_nand.c -+++ b/drivers/mtd/nand/raw/pasemi_nand.c -@@ -75,9 +75,8 @@ static int pasemi_device_ready(struct nand_chip *chip) - - static int pasemi_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -154,6 +153,13 @@ static int pasemi_nand_probe(struct platform_device *ofdev) - /* Enable the following for a flash based bad block table */ - chip->bbt_options = NAND_BBT_USE_FLASH; - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - /* Scan to find existence of the device */ - err = nand_scan(chip, 1); - if (err) -diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c -index 7711e1020c21c..0ee08c42cc35b 100644 ---- a/drivers/mtd/nand/raw/plat_nand.c -+++ b/drivers/mtd/nand/raw/plat_nand.c -@@ -21,9 +21,8 @@ struct plat_nand_data { - - static int plat_nand_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -94,6 +93,13 @@ static int plat_nand_probe(struct platform_device *pdev) - goto out; - } - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - /* Scan to find existence of the device */ - err = nand_scan(&data->chip, pdata->chip.nr_chips); - if (err) -diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c -index 70f8305c9b6e1..fb39cc7ebce03 100644 ---- a/drivers/mtd/nand/raw/socrates_nand.c -+++ b/drivers/mtd/nand/raw/socrates_nand.c -@@ -119,9 +119,8 @@ static int socrates_nand_device_ready(struct nand_chip *nand_chip) - - static int socrates_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -175,6 +174,13 @@ static int socrates_nand_probe(struct platform_device *ofdev) - /* TODO: I have no idea what real delay is. */ - nand_chip->legacy.chip_delay = 20; /* 20us command delay time */ - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - dev_set_drvdata(&ofdev->dev, host); - - res = nand_scan(nand_chip, 1); -diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c -index 26751976e5026..236fd8c5a958f 100644 ---- a/drivers/mtd/nand/raw/xway_nand.c -+++ b/drivers/mtd/nand/raw/xway_nand.c -@@ -148,9 +148,8 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len) - - static int xway_attach_chip(struct nand_chip *chip) - { -- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -- -- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) -+ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && -+ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) - chip->ecc.algo = NAND_ECC_ALGO_HAMMING; - - return 0; -@@ -219,6 +218,13 @@ static int xway_nand_probe(struct platform_device *pdev) - | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P - | cs_flag, EBU_NAND_CON); - -+ /* -+ * This driver assumes that the default ECC engine should be TYPE_SOFT. -+ * Set ->engine_type before registering the NAND devices in order to -+ * provide a driver specific default value. -+ */ -+ data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; -+ - /* Scan to find existence of the device */ - err = nand_scan(&data->chip, 1); - if (err) -diff --git a/drivers/mtd/spi-nor/controllers/hisi-sfc.c b/drivers/mtd/spi-nor/controllers/hisi-sfc.c -index 47fbf1d1e5573..516e502694780 100644 ---- a/drivers/mtd/spi-nor/controllers/hisi-sfc.c -+++ b/drivers/mtd/spi-nor/controllers/hisi-sfc.c -@@ -477,7 +477,6 @@ static int hisi_spi_nor_remove(struct platform_device *pdev) - - hisi_spi_nor_unregister_all(host); - mutex_destroy(&host->lock); -- clk_disable_unprepare(host->clk); - return 0; - } - -diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig -index f37b1c56f7c43..dd335ae1122b0 100644 ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -150,7 +150,7 @@ config NET_FC - - config IFB - tristate "Intermediate Functional Block support" -- depends on NET_CLS_ACT -+ depends on NET_ACT_MIRRED || NFT_FWD_NETDEV - select NET_REDIRECT - help - This is an intermediate driver that allows sharing of -diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c -index 7d3752cbf761d..bca36be884b8d 100644 ---- a/drivers/net/bonding/bond_alb.c -+++ b/drivers/net/bonding/bond_alb.c -@@ -1502,14 +1502,14 @@ void bond_alb_monitor(struct work_struct *work) - struct slave *slave; - - if (!bond_has_slaves(bond)) { -- bond_info->tx_rebalance_counter = 0; -+ atomic_set(&bond_info->tx_rebalance_counter, 0); - bond_info->lp_counter = 0; - goto re_arm; - } - - rcu_read_lock(); - -- bond_info->tx_rebalance_counter++; -+ atomic_inc(&bond_info->tx_rebalance_counter); - bond_info->lp_counter++; - - /* send learning packets */ -@@ -1531,7 +1531,7 @@ void bond_alb_monitor(struct work_struct *work) - } - - /* rebalance tx traffic */ -- if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) { -+ if (atomic_read(&bond_info->tx_rebalance_counter) >= BOND_TLB_REBALANCE_TICKS) { - bond_for_each_slave_rcu(bond, slave, iter) { - tlb_clear_slave(bond, slave, 1); - if (slave == rcu_access_pointer(bond->curr_active_slave)) { -@@ -1541,7 +1541,7 @@ void bond_alb_monitor(struct work_struct *work) - bond_info->unbalanced_load = 0; - } - } -- bond_info->tx_rebalance_counter = 0; -+ atomic_set(&bond_info->tx_rebalance_counter, 0); - } - - if (bond_info->rlb_enabled) { -@@ -1611,7 +1611,8 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) - tlb_init_slave(slave); - - /* order a rebalance ASAP */ -- bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; -+ atomic_set(&bond->alb_info.tx_rebalance_counter, -+ BOND_TLB_REBALANCE_TICKS); - - if (bond->alb_info.rlb_enabled) - bond->alb_info.rlb_rebalance = 1; -@@ -1648,7 +1649,8 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char - rlb_clear_slave(bond, slave); - } else if (link == BOND_LINK_UP) { - /* order a rebalance ASAP */ -- bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; -+ atomic_set(&bond_info->tx_rebalance_counter, -+ BOND_TLB_REBALANCE_TICKS); - if (bond->alb_info.rlb_enabled) { - bond->alb_info.rlb_rebalance = 1; - /* If the updelay module parameter is smaller than the -diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c -index fd07561da0348..6a6cdd0bb2585 100644 ---- a/drivers/net/bonding/bond_sysfs_slave.c -+++ b/drivers/net/bonding/bond_sysfs_slave.c -@@ -108,15 +108,15 @@ static ssize_t ad_partner_oper_port_state_show(struct slave *slave, char *buf) - } - static SLAVE_ATTR_RO(ad_partner_oper_port_state); - --static const struct slave_attribute *slave_attrs[] = { -- &slave_attr_state, -- &slave_attr_mii_status, -- &slave_attr_link_failure_count, -- &slave_attr_perm_hwaddr, -- &slave_attr_queue_id, -- &slave_attr_ad_aggregator_id, -- &slave_attr_ad_actor_oper_port_state, -- &slave_attr_ad_partner_oper_port_state, -+static const struct attribute *slave_attrs[] = { -+ &slave_attr_state.attr, -+ &slave_attr_mii_status.attr, -+ &slave_attr_link_failure_count.attr, -+ &slave_attr_perm_hwaddr.attr, -+ &slave_attr_queue_id.attr, -+ &slave_attr_ad_aggregator_id.attr, -+ &slave_attr_ad_actor_oper_port_state.attr, -+ &slave_attr_ad_partner_oper_port_state.attr, - NULL - }; - -@@ -137,24 +137,10 @@ const struct sysfs_ops slave_sysfs_ops = { - - int bond_sysfs_slave_add(struct slave *slave) - { -- const struct slave_attribute **a; -- int err; -- -- for (a = slave_attrs; *a; ++a) { -- err = sysfs_create_file(&slave->kobj, &((*a)->attr)); -- if (err) { -- kobject_put(&slave->kobj); -- return err; -- } -- } -- -- return 0; -+ return sysfs_create_files(&slave->kobj, slave_attrs); - } - - void bond_sysfs_slave_del(struct slave *slave) - { -- const struct slave_attribute **a; -- -- for (a = slave_attrs; *a; ++a) -- sysfs_remove_file(&slave->kobj, &((*a)->attr)); -+ sysfs_remove_files(&slave->kobj, slave_attrs); - } -diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c -index f49170eadd547..b1b5a82f08299 100644 ---- a/drivers/net/can/dev/bittiming.c -+++ b/drivers/net/can/dev/bittiming.c -@@ -209,7 +209,7 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, - const struct can_bittiming_const *btc) - { - struct can_priv *priv = netdev_priv(dev); -- int tseg1, alltseg; -+ unsigned int tseg1, alltseg; - u64 brp64; - - tseg1 = bt->prop_seg + bt->phase_seg1; -diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c -index 74d9899fc904c..eb74cdf26b88c 100644 ---- a/drivers/net/can/kvaser_pciefd.c -+++ b/drivers/net/can/kvaser_pciefd.c -@@ -248,6 +248,9 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); - #define KVASER_PCIEFD_SPACK_EWLR BIT(23) - #define KVASER_PCIEFD_SPACK_EPLR BIT(24) - -+/* Kvaser KCAN_EPACK second word */ -+#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) -+ - struct kvaser_pciefd; - - struct kvaser_pciefd_can { -@@ -1285,7 +1288,10 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, - - can->err_rep_cnt++; - can->can.can_stats.bus_error++; -- stats->rx_errors++; -+ if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) -+ stats->tx_errors++; -+ else -+ stats->rx_errors++; - - can->bec.txerr = bec.txerr; - can->bec.rxerr = bec.rxerr; -diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c -index 2470c47b2e315..c2a8421e7845c 100644 ---- a/drivers/net/can/m_can/m_can.c -+++ b/drivers/net/can/m_can/m_can.c -@@ -204,16 +204,16 @@ enum m_can_reg { - - /* Interrupts for version 3.0.x */ - #define IR_ERR_LEC_30X (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE) --#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_ELO | IR_BEU | \ -- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ -- IR_RF1L | IR_RF0L) -+#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_BEU | IR_BEC | \ -+ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ -+ IR_RF0L) - #define IR_ERR_ALL_30X (IR_ERR_STATE | IR_ERR_BUS_30X) - - /* Interrupts for version >= 3.1.x */ - #define IR_ERR_LEC_31X (IR_PED | IR_PEA) --#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BEU | \ -- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ -- IR_RF1L | IR_RF0L) -+#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \ -+ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ -+ IR_RF0L) - #define IR_ERR_ALL_31X (IR_ERR_STATE | IR_ERR_BUS_31X) - - /* Interrupt Line Select (ILS) */ -@@ -517,7 +517,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) - err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA, - cf->data, DIV_ROUND_UP(cf->len, 4)); - if (err) -- goto out_fail; -+ goto out_free_skb; - } - - /* acknowledge rx fifo 0 */ -@@ -532,6 +532,8 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) - - return 0; - -+out_free_skb: -+ kfree_skb(skb); - out_fail: - netdev_err(dev, "FIFO read returned %d\n", err); - return err; -@@ -810,8 +812,6 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus) - { - if (irqstatus & IR_WDI) - netdev_err(dev, "Message RAM Watchdog event due to missing READY\n"); -- if (irqstatus & IR_ELO) -- netdev_err(dev, "Error Logging Overflow\n"); - if (irqstatus & IR_BEU) - netdev_err(dev, "Bit Error Uncorrected\n"); - if (irqstatus & IR_BEC) -@@ -1494,20 +1494,32 @@ static int m_can_dev_setup(struct m_can_classdev *cdev) - case 30: - /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ - can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); -- cdev->can.bittiming_const = &m_can_bittiming_const_30X; -- cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X; -+ cdev->can.bittiming_const = cdev->bit_timing ? -+ cdev->bit_timing : &m_can_bittiming_const_30X; -+ -+ cdev->can.data_bittiming_const = cdev->data_timing ? -+ cdev->data_timing : -+ &m_can_data_bittiming_const_30X; - break; - case 31: - /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ - can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); -- cdev->can.bittiming_const = &m_can_bittiming_const_31X; -- cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; -+ cdev->can.bittiming_const = cdev->bit_timing ? -+ cdev->bit_timing : &m_can_bittiming_const_31X; -+ -+ cdev->can.data_bittiming_const = cdev->data_timing ? -+ cdev->data_timing : -+ &m_can_data_bittiming_const_31X; - break; - case 32: - case 33: - /* Support both MCAN version v3.2.x and v3.3.0 */ -- cdev->can.bittiming_const = &m_can_bittiming_const_31X; -- cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; -+ cdev->can.bittiming_const = cdev->bit_timing ? -+ cdev->bit_timing : &m_can_bittiming_const_31X; -+ -+ cdev->can.data_bittiming_const = cdev->data_timing ? -+ cdev->data_timing : -+ &m_can_data_bittiming_const_31X; - - cdev->can.ctrlmode_supported |= - (m_can_niso_supported(cdev) ? -diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h -index d18b515e6ccc7..2c5d409971686 100644 ---- a/drivers/net/can/m_can/m_can.h -+++ b/drivers/net/can/m_can/m_can.h -@@ -85,6 +85,9 @@ struct m_can_classdev { - struct sk_buff *tx_skb; - struct phy *transceiver; - -+ const struct can_bittiming_const *bit_timing; -+ const struct can_bittiming_const *data_timing; -+ - struct m_can_ops *ops; - - int version; -diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c -index 89cc3d41e952b..b56a54d6c5a9c 100644 ---- a/drivers/net/can/m_can/m_can_pci.c -+++ b/drivers/net/can/m_can/m_can_pci.c -@@ -18,9 +18,14 @@ - - #define M_CAN_PCI_MMIO_BAR 0 - --#define M_CAN_CLOCK_FREQ_EHL 100000000 - #define CTL_CSR_INT_CTL_OFFSET 0x508 - -+struct m_can_pci_config { -+ const struct can_bittiming_const *bit_timing; -+ const struct can_bittiming_const *data_timing; -+ unsigned int clock_freq; -+}; -+ - struct m_can_pci_priv { - struct m_can_classdev cdev; - -@@ -42,8 +47,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg) - static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count) - { - struct m_can_pci_priv *priv = cdev_to_priv(cdev); -+ void __iomem *src = priv->base + offset; - -- ioread32_rep(priv->base + offset, val, val_count); -+ while (val_count--) { -+ *(unsigned int *)val = ioread32(src); -+ val += 4; -+ src += 4; -+ } - - return 0; - } -@@ -61,8 +71,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, - const void *val, size_t val_count) - { - struct m_can_pci_priv *priv = cdev_to_priv(cdev); -+ void __iomem *dst = priv->base + offset; - -- iowrite32_rep(priv->base + offset, val, val_count); -+ while (val_count--) { -+ iowrite32(*(unsigned int *)val, dst); -+ val += 4; -+ dst += 4; -+ } - - return 0; - } -@@ -74,9 +89,40 @@ static struct m_can_ops m_can_pci_ops = { - .read_fifo = iomap_read_fifo, - }; - -+static const struct can_bittiming_const m_can_bittiming_const_ehl = { -+ .name = KBUILD_MODNAME, -+ .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ -+ .tseg1_max = 64, -+ .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ -+ .tseg2_max = 128, -+ .sjw_max = 128, -+ .brp_min = 1, -+ .brp_max = 512, -+ .brp_inc = 1, -+}; -+ -+static const struct can_bittiming_const m_can_data_bittiming_const_ehl = { -+ .name = KBUILD_MODNAME, -+ .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ -+ .tseg1_max = 16, -+ .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ -+ .tseg2_max = 8, -+ .sjw_max = 4, -+ .brp_min = 1, -+ .brp_max = 32, -+ .brp_inc = 1, -+}; -+ -+static const struct m_can_pci_config m_can_pci_ehl = { -+ .bit_timing = &m_can_bittiming_const_ehl, -+ .data_timing = &m_can_data_bittiming_const_ehl, -+ .clock_freq = 200000000, -+}; -+ - static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) - { - struct device *dev = &pci->dev; -+ const struct m_can_pci_config *cfg; - struct m_can_classdev *mcan_class; - struct m_can_pci_priv *priv; - void __iomem *base; -@@ -104,6 +150,8 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) - if (!mcan_class) - return -ENOMEM; - -+ cfg = (const struct m_can_pci_config *)id->driver_data; -+ - priv = cdev_to_priv(mcan_class); - - priv->base = base; -@@ -115,7 +163,9 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) - mcan_class->dev = &pci->dev; - mcan_class->net->irq = pci_irq_vector(pci, 0); - mcan_class->pm_clock_support = 1; -- mcan_class->can.clock.freq = id->driver_data; -+ mcan_class->bit_timing = cfg->bit_timing; -+ mcan_class->data_timing = cfg->data_timing; -+ mcan_class->can.clock.freq = cfg->clock_freq; - mcan_class->ops = &m_can_pci_ops; - - pci_set_drvdata(pci, mcan_class); -@@ -168,8 +218,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops, - m_can_pci_suspend, m_can_pci_resume); - - static const struct pci_device_id m_can_pci_id_table[] = { -- { PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, }, -- { PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, }, -+ { PCI_VDEVICE(INTEL, 0x4bc1), (kernel_ulong_t)&m_can_pci_ehl, }, -+ { PCI_VDEVICE(INTEL, 0x4bc2), (kernel_ulong_t)&m_can_pci_ehl, }, - { } /* Terminating Entry */ - }; - MODULE_DEVICE_TABLE(pci, m_can_pci_id_table); -diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c -index 92a54a5fd4c50..964c8a09226a9 100644 ---- a/drivers/net/can/pch_can.c -+++ b/drivers/net/can/pch_can.c -@@ -692,11 +692,11 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota) - cf->data[i + 1] = data_reg >> 8; - } - -- netif_receive_skb(skb); - rcv_pkts++; - stats->rx_packets++; - quota--; - stats->rx_bytes += cf->len; -+ netif_receive_skb(skb); - - pch_fifo_thresh(priv, obj_num); - obj_num++; -diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c -index e21b169c14c01..4642b6d4aaf7b 100644 ---- a/drivers/net/can/sja1000/ems_pcmcia.c -+++ b/drivers/net/can/sja1000/ems_pcmcia.c -@@ -234,7 +234,12 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base) - free_sja1000dev(dev); - } - -- err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, -+ if (!card->channels) { -+ err = -ENODEV; -+ goto failure_cleanup; -+ } -+ -+ err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, - DRV_NAME, card); - if (!err) - return 0; -diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c -index 673861ab665a4..e16dc482f3270 100644 ---- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c -+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c -@@ -1092,7 +1092,7 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv) - - err = mcp251xfd_chip_rx_int_enable(priv); - if (err) -- return err; -+ goto out_chip_stop; - - err = mcp251xfd_chip_ecc_init(priv); - if (err) -@@ -2290,8 +2290,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) - * check will fail, too. So leave IRQ handler - * directly. - */ -- if (priv->can.state == CAN_STATE_BUS_OFF) -+ if (priv->can.state == CAN_STATE_BUS_OFF) { -+ can_rx_offload_threaded_irq_finish(&priv->offload); - return IRQ_HANDLED; -+ } - } - - handled = IRQ_HANDLED; -diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c -index 96a13c770e4a1..24627ab146261 100644 ---- a/drivers/net/can/usb/etas_es58x/es58x_core.c -+++ b/drivers/net/can/usb/etas_es58x/es58x_core.c -@@ -664,7 +664,7 @@ int es58x_rx_err_msg(struct net_device *netdev, enum es58x_err error, - struct can_device_stats *can_stats = &can->can_stats; - struct can_frame *cf = NULL; - struct sk_buff *skb; -- int ret; -+ int ret = 0; - - if (!netif_running(netdev)) { - if (net_ratelimit()) -@@ -823,8 +823,6 @@ int es58x_rx_err_msg(struct net_device *netdev, enum es58x_err error, - can->state = CAN_STATE_BUS_OFF; - can_bus_off(netdev); - ret = can->do_set_mode(netdev, CAN_MODE_STOP); -- if (ret) -- return ret; - } - break; - -@@ -881,7 +879,7 @@ int es58x_rx_err_msg(struct net_device *netdev, enum es58x_err error, - ES58X_EVENT_BUSOFF, timestamp); - } - -- return 0; -+ return ret; - } - - /** -diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c -index 59ba7c7beec00..f7af1bf5ab46d 100644 ---- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c -+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c -@@ -28,10 +28,6 @@ - - #include "kvaser_usb.h" - --/* Forward declaration */ --static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; -- --#define CAN_USB_CLOCK 8000000 - #define MAX_USBCAN_NET_DEVICES 2 - - /* Command header size */ -@@ -80,6 +76,12 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; - - #define CMD_LEAF_LOG_MESSAGE 106 - -+/* Leaf frequency options */ -+#define KVASER_USB_LEAF_SWOPTION_FREQ_MASK 0x60 -+#define KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK 0 -+#define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) -+#define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) -+ - /* error factors */ - #define M16C_EF_ACKE BIT(0) - #define M16C_EF_CRCE BIT(1) -@@ -340,6 +342,50 @@ struct kvaser_usb_err_summary { - }; - }; - -+static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { -+ .name = "kvaser_usb", -+ .tseg1_min = KVASER_USB_TSEG1_MIN, -+ .tseg1_max = KVASER_USB_TSEG1_MAX, -+ .tseg2_min = KVASER_USB_TSEG2_MIN, -+ .tseg2_max = KVASER_USB_TSEG2_MAX, -+ .sjw_max = KVASER_USB_SJW_MAX, -+ .brp_min = KVASER_USB_BRP_MIN, -+ .brp_max = KVASER_USB_BRP_MAX, -+ .brp_inc = KVASER_USB_BRP_INC, -+}; -+ -+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = { -+ .clock = { -+ .freq = 8000000, -+ }, -+ .timestamp_freq = 1, -+ .bittiming_const = &kvaser_usb_leaf_bittiming_const, -+}; -+ -+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = { -+ .clock = { -+ .freq = 16000000, -+ }, -+ .timestamp_freq = 1, -+ .bittiming_const = &kvaser_usb_leaf_bittiming_const, -+}; -+ -+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = { -+ .clock = { -+ .freq = 24000000, -+ }, -+ .timestamp_freq = 1, -+ .bittiming_const = &kvaser_usb_leaf_bittiming_const, -+}; -+ -+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = { -+ .clock = { -+ .freq = 32000000, -+ }, -+ .timestamp_freq = 1, -+ .bittiming_const = &kvaser_usb_leaf_bittiming_const, -+}; -+ - static void * - kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, - const struct sk_buff *skb, int *frame_len, -@@ -471,6 +517,27 @@ static int kvaser_usb_leaf_send_simple_cmd(const struct kvaser_usb *dev, - return rc; - } - -+static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, -+ const struct leaf_cmd_softinfo *softinfo) -+{ -+ u32 sw_options = le32_to_cpu(softinfo->sw_options); -+ -+ dev->fw_version = le32_to_cpu(softinfo->fw_version); -+ dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); -+ -+ switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { -+ case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: -+ dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz; -+ break; -+ case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: -+ dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz; -+ break; -+ case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: -+ dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz; -+ break; -+ } -+} -+ - static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) - { - struct kvaser_cmd cmd; -@@ -486,14 +553,13 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) - - switch (dev->card_data.leaf.family) { - case KVASER_LEAF: -- dev->fw_version = le32_to_cpu(cmd.u.leaf.softinfo.fw_version); -- dev->max_tx_urbs = -- le16_to_cpu(cmd.u.leaf.softinfo.max_outstanding_tx); -+ kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); - break; - case KVASER_USBCAN: - dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version); - dev->max_tx_urbs = - le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); -+ dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz; - break; - } - -@@ -1225,24 +1291,11 @@ static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) - { - struct kvaser_usb_dev_card_data *card_data = &dev->card_data; - -- dev->cfg = &kvaser_usb_leaf_dev_cfg; - card_data->ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; - - return 0; - } - --static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { -- .name = "kvaser_usb", -- .tseg1_min = KVASER_USB_TSEG1_MIN, -- .tseg1_max = KVASER_USB_TSEG1_MAX, -- .tseg2_min = KVASER_USB_TSEG2_MIN, -- .tseg2_max = KVASER_USB_TSEG2_MAX, -- .sjw_max = KVASER_USB_SJW_MAX, -- .brp_min = KVASER_USB_BRP_MIN, -- .brp_max = KVASER_USB_BRP_MAX, -- .brp_inc = KVASER_USB_BRP_INC, --}; -- - static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) - { - struct kvaser_usb_net_priv *priv = netdev_priv(netdev); -@@ -1348,11 +1401,3 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { - .dev_read_bulk_callback = kvaser_usb_leaf_read_bulk_callback, - .dev_frame_to_cmd = kvaser_usb_leaf_frame_to_cmd, - }; -- --static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg = { -- .clock = { -- .freq = CAN_USB_CLOCK, -- }, -- .timestamp_freq = 1, -- .bittiming_const = &kvaser_usb_leaf_bittiming_const, --}; -diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c -index 837b3fecd71e9..af8d3dadbbb8b 100644 ---- a/drivers/net/can/usb/peak_usb/pcan_usb.c -+++ b/drivers/net/can/usb/peak_usb/pcan_usb.c -@@ -841,14 +841,14 @@ static int pcan_usb_start(struct peak_usb_device *dev) - pdev->bec.rxerr = 0; - pdev->bec.txerr = 0; - -- /* be notified on error counter changes (if requested by user) */ -- if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) { -- err = pcan_usb_set_err_frame(dev, PCAN_USB_BERR_MASK); -- if (err) -- netdev_warn(dev->netdev, -- "Asking for BERR reporting error %u\n", -- err); -- } -+ /* always ask the device for BERR reporting, to be able to switch from -+ * WARNING to PASSIVE state -+ */ -+ err = pcan_usb_set_err_frame(dev, PCAN_USB_BERR_MASK); -+ if (err) -+ netdev_warn(dev->netdev, -+ "Asking for BERR reporting error %u\n", -+ err); - - /* if revision greater than 3, can put silent mode on/off */ - if (dev->device_rev > 3) { -@@ -986,7 +986,6 @@ const struct peak_usb_adapter pcan_usb = { - .device_id = PCAN_USB_PRODUCT_ID, - .ctrl_count = 1, - .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY | -- CAN_CTRLMODE_BERR_REPORTING | - CAN_CTRLMODE_CC_LEN8_DLC, - .clock = { - .freq = PCAN_USB_CRYSTAL_HZ / 2, -diff --git a/drivers/net/dsa/b53/b53_spi.c b/drivers/net/dsa/b53/b53_spi.c -index 01e37b75471e1..2b88f03e52521 100644 ---- a/drivers/net/dsa/b53/b53_spi.c -+++ b/drivers/net/dsa/b53/b53_spi.c -@@ -349,6 +349,19 @@ static const struct of_device_id b53_spi_of_match[] = { - }; - MODULE_DEVICE_TABLE(of, b53_spi_of_match); - -+static const struct spi_device_id b53_spi_ids[] = { -+ { .name = "bcm5325" }, -+ { .name = "bcm5365" }, -+ { .name = "bcm5395" }, -+ { .name = "bcm5397" }, -+ { .name = "bcm5398" }, -+ { .name = "bcm53115" }, -+ { .name = "bcm53125" }, -+ { .name = "bcm53128" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(spi, b53_spi_ids); -+ - static struct spi_driver b53_spi_driver = { - .driver = { - .name = "b53-switch", -@@ -357,6 +370,7 @@ static struct spi_driver b53_spi_driver = { - .probe = b53_spi_probe, - .remove = b53_spi_remove, - .shutdown = b53_spi_shutdown, -+ .id_table = b53_spi_ids, - }; - - module_spi_driver(b53_spi_driver); -diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c -index 8dadcae93c9b5..43d126628610b 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -471,6 +471,12 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) - u16 reg; - int err; - -+ /* The 88e6250 family does not have the PHY detect bit. Instead, -+ * report whether the port is internal. -+ */ -+ if (chip->info->family == MV88E6XXX_FAMILY_6250) -+ return port < chip->info->num_internal_phys; -+ - err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); - if (err) { - dev_err(chip->dev, -@@ -640,7 +646,10 @@ static void mv88e6393x_phylink_validate(struct mv88e6xxx_chip *chip, int port, - unsigned long *mask, - struct phylink_link_state *state) - { -- if (port == 0 || port == 9 || port == 10) { -+ bool is_6191x = -+ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; -+ -+ if (((port == 0 || port == 9) && !is_6191x) || port == 10) { - phylink_set(mask, 10000baseT_Full); - phylink_set(mask, 10000baseKR_Full); - phylink_set(mask, 10000baseCR_Full); -@@ -690,44 +699,48 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, - { - struct mv88e6xxx_chip *chip = ds->priv; - struct mv88e6xxx_port *p; -- int err; -+ int err = 0; - - p = &chip->ports[port]; - -- /* FIXME: is this the correct test? If we're in fixed mode on an -- * internal port, why should we process this any different from -- * PHY mode? On the other hand, the port may be automedia between -- * an internal PHY and the serdes... -- */ -- if ((mode == MLO_AN_PHY) && mv88e6xxx_phy_is_internal(ds, port)) -- return; -- - mv88e6xxx_reg_lock(chip); -- /* In inband mode, the link may come up at any time while the link -- * is not forced down. Force the link down while we reconfigure the -- * interface mode. -- */ -- if (mode == MLO_AN_INBAND && p->interface != state->interface && -- chip->info->ops->port_set_link) -- chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN); -- -- err = mv88e6xxx_port_config_interface(chip, port, state->interface); -- if (err && err != -EOPNOTSUPP) -- goto err_unlock; - -- err = mv88e6xxx_serdes_pcs_config(chip, port, mode, state->interface, -- state->advertising); -- /* FIXME: we should restart negotiation if something changed - which -- * is something we get if we convert to using phylinks PCS operations. -- */ -- if (err > 0) -- err = 0; -+ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { -+ /* In inband mode, the link may come up at any time while the -+ * link is not forced down. Force the link down while we -+ * reconfigure the interface mode. -+ */ -+ if (mode == MLO_AN_INBAND && -+ p->interface != state->interface && -+ chip->info->ops->port_set_link) -+ chip->info->ops->port_set_link(chip, port, -+ LINK_FORCED_DOWN); -+ -+ err = mv88e6xxx_port_config_interface(chip, port, -+ state->interface); -+ if (err && err != -EOPNOTSUPP) -+ goto err_unlock; -+ -+ err = mv88e6xxx_serdes_pcs_config(chip, port, mode, -+ state->interface, -+ state->advertising); -+ /* FIXME: we should restart negotiation if something changed - -+ * which is something we get if we convert to using phylinks -+ * PCS operations. -+ */ -+ if (err > 0) -+ err = 0; -+ } - - /* Undo the forced down state above after completing configuration -- * irrespective of its state on entry, which allows the link to come up. -+ * irrespective of its state on entry, which allows the link to come -+ * up in the in-band case where there is no separate SERDES. Also -+ * ensure that the link can come up if the PPU is in use and we are -+ * in PHY mode (we treat the PPU as an effective in-band mechanism.) - */ -- if (mode == MLO_AN_INBAND && p->interface != state->interface && -- chip->info->ops->port_set_link) -+ if (chip->info->ops->port_set_link && -+ ((mode == MLO_AN_INBAND && p->interface != state->interface) || -+ (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port)))) - chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); - - p->interface = state->interface; -@@ -750,13 +763,16 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, - ops = chip->info->ops; - - mv88e6xxx_reg_lock(chip); -- /* Internal PHYs propagate their configuration directly to the MAC. -- * External PHYs depend on whether the PPU is enabled for this port. -+ /* Force the link down if we know the port may not be automatically -+ * updated by the switch or if we are using fixed-link mode. - */ -- if (((!mv88e6xxx_phy_is_internal(ds, port) && -- !mv88e6xxx_port_ppu_updates(chip, port)) || -+ if ((!mv88e6xxx_port_ppu_updates(chip, port) || - mode == MLO_AN_FIXED) && ops->port_sync_link) - err = ops->port_sync_link(chip, port, mode, false); -+ -+ if (!err && ops->port_set_speed_duplex) -+ err = ops->port_set_speed_duplex(chip, port, SPEED_UNFORCED, -+ DUPLEX_UNFORCED); - mv88e6xxx_reg_unlock(chip); - - if (err) -@@ -777,11 +793,11 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, - ops = chip->info->ops; - - mv88e6xxx_reg_lock(chip); -- /* Internal PHYs propagate their configuration directly to the MAC. -- * External PHYs depend on whether the PPU is enabled for this port. -+ /* Configure and force the link up if we know that the port may not -+ * automatically updated by the switch or if we are using fixed-link -+ * mode. - */ -- if ((!mv88e6xxx_phy_is_internal(ds, port) && -- !mv88e6xxx_port_ppu_updates(chip, port)) || -+ if (!mv88e6xxx_port_ppu_updates(chip, port) || - mode == MLO_AN_FIXED) { - /* FIXME: for an automedia port, should we force the link - * down here - what if the link comes up due to "other" media -diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c -index d9817b20ea641..ab41619a809b3 100644 ---- a/drivers/net/dsa/mv88e6xxx/port.c -+++ b/drivers/net/dsa/mv88e6xxx/port.c -@@ -283,7 +283,7 @@ static int mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip *chip, - if (err) - return err; - -- if (speed) -+ if (speed != SPEED_UNFORCED) - dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed); - else - dev_dbg(chip->dev, "p%d: Speed unforced\n", port); -@@ -516,7 +516,7 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, - if (err) - return err; - -- if (speed) -+ if (speed != SPEED_UNFORCED) - dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed); - else - dev_dbg(chip->dev, "p%d: Speed unforced\n", port); -diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c -index 6ea0036787986..2b05ead515cdc 100644 ---- a/drivers/net/dsa/mv88e6xxx/serdes.c -+++ b/drivers/net/dsa/mv88e6xxx/serdes.c -@@ -50,11 +50,22 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, - } - - static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, -- u16 status, u16 lpa, -+ u16 ctrl, u16 status, u16 lpa, - struct phylink_link_state *state) - { -+ state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); -+ - if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { -- state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); -+ /* The Spped and Duplex Resolved register is 1 if AN is enabled -+ * and complete, or if AN is disabled. So with disabled AN we -+ * still get here on link up. But we want to set an_complete -+ * only if AN was enabled, thus we look at BMCR_ANENABLE. -+ * (According to 802.3-2008 section 22.2.4.2.10, we should be -+ * able to get this same value from BMSR_ANEGCAPABLE, but tests -+ * show that these Marvell PHYs don't conform to this part of -+ * the specificaion - BMSR_ANEGCAPABLE is simply always 1.) -+ */ -+ state->an_complete = !!(ctrl & BMCR_ANENABLE); - state->duplex = status & - MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? - DUPLEX_FULL : DUPLEX_HALF; -@@ -81,6 +92,18 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, - dev_err(chip->dev, "invalid PHY speed\n"); - return -EINVAL; - } -+ } else if (state->link && -+ state->interface != PHY_INTERFACE_MODE_SGMII) { -+ /* If Speed and Duplex Resolved register is 0 and link is up, it -+ * means that AN was enabled, but link partner had it disabled -+ * and the PHY invoked the Auto-Negotiation Bypass feature and -+ * linked anyway. -+ */ -+ state->duplex = DUPLEX_FULL; -+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) -+ state->speed = SPEED_2500; -+ else -+ state->speed = SPEED_1000; - } else { - state->link = false; - } -@@ -168,9 +191,15 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - int lane, struct phylink_link_state *state) - { -- u16 lpa, status; -+ u16 lpa, status, ctrl; - int err; - -+ err = mv88e6352_serdes_read(chip, MII_BMCR, &ctrl); -+ if (err) { -+ dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); -+ return err; -+ } -+ - err = mv88e6352_serdes_read(chip, 0x11, &status); - if (err) { - dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); -@@ -183,7 +212,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, - return err; - } - -- return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); -+ return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); - } - - int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, -@@ -801,7 +830,7 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool up) - { - u8 cmode = chip->ports[port].cmode; -- int err = 0; -+ int err; - - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: -@@ -813,6 +842,9 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - case MV88E6XXX_PORT_STS_CMODE_RXAUI: - err = mv88e6390_serdes_power_10g(chip, lane, up); - break; -+ default: -+ err = -EINVAL; -+ break; - } - - if (!err && up) -@@ -883,9 +915,16 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, - static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, - int port, int lane, struct phylink_link_state *state) - { -- u16 lpa, status; -+ u16 lpa, status, ctrl; - int err; - -+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6390_SGMII_BMCR, &ctrl); -+ if (err) { -+ dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); -+ return err; -+ } -+ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_PHY_STATUS, &status); - if (err) { -@@ -900,7 +939,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, - return err; - } - -- return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); -+ return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); - } - - static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, -@@ -1271,9 +1310,31 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) - } - } - --static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) -+static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane, -+ bool on) - { -- u16 reg, pcs; -+ u16 reg; -+ int err; -+ -+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6393X_SERDES_CTRL1, ®); -+ if (err) -+ return err; -+ -+ if (on) -+ reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN | -+ MV88E6393X_SERDES_CTRL1_RX_PDOWN); -+ else -+ reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN | -+ MV88E6393X_SERDES_CTRL1_RX_PDOWN; -+ -+ return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6393X_SERDES_CTRL1, reg); -+} -+ -+static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) -+{ -+ u16 reg; - int err; - - /* mv88e6393x family errata 4.6: -@@ -1284,26 +1345,45 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) - * It seems that after this workaround the SERDES is automatically - * powered up (the bit is cleared), so power it down. - */ -- if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE || -- lane == MV88E6393X_PORT10_LANE) { -- err = mv88e6390_serdes_read(chip, lane, -- MDIO_MMD_PHYXS, -- MV88E6393X_SERDES_POC, ®); -- if (err) -- return err; -+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6393X_SERDES_POC, ®); -+ if (err) -+ return err; - -- reg &= ~MV88E6393X_SERDES_POC_PDOWN; -- reg |= MV88E6393X_SERDES_POC_RESET; -+ reg &= ~MV88E6393X_SERDES_POC_PDOWN; -+ reg |= MV88E6393X_SERDES_POC_RESET; - -- err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, -- MV88E6393X_SERDES_POC, reg); -- if (err) -- return err; -+ err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6393X_SERDES_POC, reg); -+ if (err) -+ return err; - -- err = mv88e6390_serdes_power_sgmii(chip, lane, false); -- if (err) -- return err; -- } -+ err = mv88e6390_serdes_power_sgmii(chip, lane, false); -+ if (err) -+ return err; -+ -+ return mv88e6393x_serdes_power_lane(chip, lane, false); -+} -+ -+int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) -+{ -+ int err; -+ -+ err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE); -+ if (err) -+ return err; -+ -+ err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE); -+ if (err) -+ return err; -+ -+ return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE); -+} -+ -+static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane) -+{ -+ u16 reg, pcs; -+ int err; - - /* mv88e6393x family errata 4.8: - * When a SERDES port is operating in 1000BASE-X or SGMII mode link may -@@ -1334,38 +1414,152 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) - MV88E6393X_ERRATA_4_8_REG, reg); - } - --int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) -+static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, -+ u8 cmode) -+{ -+ static const struct { -+ u16 dev, reg, val, mask; -+ } fixes[] = { -+ { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, -+ { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, -+ { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, -+ { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, -+ { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, -+ { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, -+ { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, -+ MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, -+ }; -+ int err, i; -+ u16 reg; -+ -+ /* mv88e6393x family errata 5.2: -+ * For optimal signal integrity the following sequence should be applied -+ * to SERDES operating in 10G mode. These registers only apply to 10G -+ * operation and have no effect on other speeds. -+ */ -+ if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER) -+ return 0; -+ -+ for (i = 0; i < ARRAY_SIZE(fixes); ++i) { -+ err = mv88e6390_serdes_read(chip, lane, fixes[i].dev, -+ fixes[i].reg, ®); -+ if (err) -+ return err; -+ -+ reg &= ~fixes[i].mask; -+ reg |= fixes[i].val; -+ -+ err = mv88e6390_serdes_write(chip, lane, fixes[i].dev, -+ fixes[i].reg, reg); -+ if (err) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip, -+ int lane, u8 cmode, bool on) - { -+ u16 reg; - int err; - -- err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT0_LANE); -+ if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX) -+ return 0; -+ -+ /* Inband AN is broken on Amethyst in 2500base-x mode when set by -+ * standard mechanism (via cmode). -+ * We can get around this by configuring the PCS mode to 1000base-x -+ * and then writing value 0x58 to register 1e.8000. (This must be done -+ * while SerDes receiver and transmitter are disabled, which is, when -+ * this function is called.) -+ * It seem that when we do this configuration to 2500base-x mode (by -+ * changing PCS mode to 1000base-x and frequency to 3.125 GHz from -+ * 1.25 GHz) and then configure to sgmii or 1000base-x, the device -+ * thinks that it already has SerDes at 1.25 GHz and does not change -+ * the 1e.8000 register, leaving SerDes at 3.125 GHz. -+ * To avoid this, change PCS mode back to 2500base-x when disabling -+ * SerDes from 2500base-x mode. -+ */ -+ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6393X_SERDES_POC, ®); -+ if (err) -+ return err; -+ -+ reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN); -+ if (on) -+ reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX | -+ MV88E6393X_SERDES_POC_AN; -+ else -+ reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX; -+ reg |= MV88E6393X_SERDES_POC_RESET; -+ -+ err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, -+ MV88E6393X_SERDES_POC, reg); - if (err) - return err; - -- err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT9_LANE); -+ err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58); - if (err) - return err; - -- return mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT10_LANE); -+ return 0; - } - - int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, - bool on) - { - u8 cmode = chip->ports[port].cmode; -+ int err; - - if (port != 0 && port != 9 && port != 10) - return -EOPNOTSUPP; - -+ if (on) { -+ err = mv88e6393x_serdes_erratum_4_8(chip, lane); -+ if (err) -+ return err; -+ -+ err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode); -+ if (err) -+ return err; -+ -+ err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, -+ true); -+ if (err) -+ return err; -+ -+ err = mv88e6393x_serdes_power_lane(chip, lane, true); -+ if (err) -+ return err; -+ } -+ - switch (cmode) { - case MV88E6XXX_PORT_STS_CMODE_SGMII: - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: -- return mv88e6390_serdes_power_sgmii(chip, lane, on); -+ err = mv88e6390_serdes_power_sgmii(chip, lane, on); -+ break; - case MV88E6393X_PORT_STS_CMODE_5GBASER: - case MV88E6393X_PORT_STS_CMODE_10GBASER: -- return mv88e6390_serdes_power_10g(chip, lane, on); -+ err = mv88e6390_serdes_power_10g(chip, lane, on); -+ break; -+ default: -+ err = -EINVAL; -+ break; - } - -- return 0; -+ if (err) -+ return err; -+ -+ if (!on) { -+ err = mv88e6393x_serdes_power_lane(chip, lane, false); -+ if (err) -+ return err; -+ -+ err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, -+ false); -+ } -+ -+ return err; - } -diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h -index cbb3ba30caea9..8dd8ed225b459 100644 ---- a/drivers/net/dsa/mv88e6xxx/serdes.h -+++ b/drivers/net/dsa/mv88e6xxx/serdes.h -@@ -93,6 +93,10 @@ - #define MV88E6393X_SERDES_POC_PCS_MASK 0x0007 - #define MV88E6393X_SERDES_POC_RESET BIT(15) - #define MV88E6393X_SERDES_POC_PDOWN BIT(5) -+#define MV88E6393X_SERDES_POC_AN BIT(3) -+#define MV88E6393X_SERDES_CTRL1 0xf003 -+#define MV88E6393X_SERDES_CTRL1_TX_PDOWN BIT(9) -+#define MV88E6393X_SERDES_CTRL1_RX_PDOWN BIT(8) - - #define MV88E6393X_ERRATA_4_8_REG 0xF074 - #define MV88E6393X_ERRATA_4_8_BIT BIT(14) -diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c -index 341236dcbdb47..1513dfb523de7 100644 ---- a/drivers/net/dsa/ocelot/felix.c -+++ b/drivers/net/dsa/ocelot/felix.c -@@ -290,8 +290,11 @@ static int felix_setup_mmio_filtering(struct felix *felix) - } - } - -- if (cpu < 0) -+ if (cpu < 0) { -+ kfree(tagging_rule); -+ kfree(redirect_rule); - return -EINVAL; -+ } - - tagging_rule->key_type = OCELOT_VCAP_KEY_ETYPE; - *(__be16 *)tagging_rule->key.etype.etype.value = htons(ETH_P_1588); -@@ -1368,12 +1371,12 @@ out: - static bool felix_rxtstamp(struct dsa_switch *ds, int port, - struct sk_buff *skb, unsigned int type) - { -- u8 *extraction = skb->data - ETH_HLEN - OCELOT_TAG_LEN; -+ u32 tstamp_lo = OCELOT_SKB_CB(skb)->tstamp_lo; - struct skb_shared_hwtstamps *shhwtstamps; - struct ocelot *ocelot = ds->priv; -- u32 tstamp_lo, tstamp_hi; - struct timespec64 ts; -- u64 tstamp, val; -+ u32 tstamp_hi; -+ u64 tstamp; - - /* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb - * for RX timestamping. Then free it, and poll for its copy through -@@ -1388,9 +1391,6 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port, - ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); - tstamp = ktime_set(ts.tv_sec, ts.tv_nsec); - -- ocelot_xfh_get_rew_val(extraction, &val); -- tstamp_lo = (u32)val; -- - tstamp_hi = tstamp >> 32; - if ((tstamp & 0xffffffff) < tstamp_lo) - tstamp_hi--; -diff --git a/drivers/net/dsa/rtl8366.c b/drivers/net/dsa/rtl8366.c -index 75897a3690969..ffbe5b6b2655b 100644 ---- a/drivers/net/dsa/rtl8366.c -+++ b/drivers/net/dsa/rtl8366.c -@@ -457,7 +457,7 @@ int rtl8366_vlan_del(struct dsa_switch *ds, int port, - * anymore then clear the whole member - * config so it can be reused. - */ -- if (!vlanmc.member && vlanmc.untag) { -+ if (!vlanmc.member) { - vlanmc.vid = 0; - vlanmc.priority = 0; - vlanmc.fid = 0; -diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c -index a89093bc6c6ad..9e3b572ed999e 100644 ---- a/drivers/net/dsa/rtl8366rb.c -+++ b/drivers/net/dsa/rtl8366rb.c -@@ -1350,7 +1350,7 @@ static int rtl8366rb_set_mc_index(struct realtek_smi *smi, int port, int index) - - static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan) - { -- unsigned int max = RTL8366RB_NUM_VLANS; -+ unsigned int max = RTL8366RB_NUM_VLANS - 1; - - if (smi->vlan4k_enabled) - max = RTL8366RB_NUM_VIDS - 1; -diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c -index 1c00d719e5d76..804b37c76b1e6 100644 ---- a/drivers/net/ethernet/altera/altera_tse_main.c -+++ b/drivers/net/ethernet/altera/altera_tse_main.c -@@ -1430,16 +1430,19 @@ static int altera_tse_probe(struct platform_device *pdev) - priv->rxdescmem_busaddr = dma_res->start; - - } else { -+ ret = -ENODEV; - goto err_free_netdev; - } - -- if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) -+ if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) { - dma_set_coherent_mask(priv->device, - DMA_BIT_MASK(priv->dmaops->dmamask)); -- else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) -+ } else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) { - dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); -- else -+ } else { -+ ret = -EIO; - goto err_free_netdev; -+ } - - /* MAC address space */ - ret = request_and_map(pdev, "control_port", &control_port, -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h -index b2cd3bdba9f89..533b8519ec352 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h -@@ -1331,6 +1331,10 @@ - #define MDIO_VEND2_PMA_CDR_CONTROL 0x8056 - #endif - -+#ifndef MDIO_VEND2_PMA_MISC_CTRL0 -+#define MDIO_VEND2_PMA_MISC_CTRL0 0x8090 -+#endif -+ - #ifndef MDIO_CTRL1_SPEED1G - #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) - #endif -@@ -1389,6 +1393,10 @@ - #define XGBE_PMA_RX_RST_0_RESET_ON 0x10 - #define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 - -+#define XGBE_PMA_PLL_CTRL_MASK BIT(15) -+#define XGBE_PMA_PLL_CTRL_ENABLE BIT(15) -+#define XGBE_PMA_PLL_CTRL_DISABLE 0x0000 -+ - /* Bit setting and getting macros - * The get macro will extract the current bit field value from within - * the variable -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c -index 18e48b3bc402b..213769054391c 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c -@@ -1977,12 +1977,26 @@ static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) - } - } - -+static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable) -+{ -+ XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0, -+ XGBE_PMA_PLL_CTRL_MASK, -+ enable ? XGBE_PMA_PLL_CTRL_ENABLE -+ : XGBE_PMA_PLL_CTRL_DISABLE); -+ -+ /* Wait for command to complete */ -+ usleep_range(100, 200); -+} -+ - static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, - unsigned int cmd, unsigned int sub_cmd) - { - unsigned int s0 = 0; - unsigned int wait; - -+ /* Disable PLL re-initialization during FW command processing */ -+ xgbe_phy_pll_ctrl(pdata, false); -+ - /* Log if a previous command did not complete */ - if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { - netif_dbg(pdata, link, pdata->netdev, -@@ -2003,7 +2017,7 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, - wait = XGBE_RATECHANGE_COUNT; - while (wait--) { - if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) -- return; -+ goto reenable_pll; - - usleep_range(1000, 2000); - } -@@ -2013,6 +2027,10 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, - - /* Reset on error */ - xgbe_phy_rx_reset(pdata); -+ -+reenable_pll: -+ /* Enable PLL re-initialization */ -+ xgbe_phy_pll_ctrl(pdata, true); - } - - static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h -index 23b2d390fcdda..ace691d7cd759 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h -@@ -40,10 +40,12 @@ - - #define AQ_DEVICE_ID_AQC113DEV 0x00C0 - #define AQ_DEVICE_ID_AQC113CS 0x94C0 -+#define AQ_DEVICE_ID_AQC113CA 0x34C0 - #define AQ_DEVICE_ID_AQC114CS 0x93C0 - #define AQ_DEVICE_ID_AQC113 0x04C0 - #define AQ_DEVICE_ID_AQC113C 0x14C0 - #define AQ_DEVICE_ID_AQC115C 0x12C0 -+#define AQ_DEVICE_ID_AQC116C 0x11C0 - - #define HW_ATL_NIC_NAME "Marvell (aQuantia) AQtion 10Gbit Network Adapter" - -@@ -53,20 +55,19 @@ - - #define AQ_NIC_RATE_10G BIT(0) - #define AQ_NIC_RATE_5G BIT(1) --#define AQ_NIC_RATE_5GSR BIT(2) --#define AQ_NIC_RATE_2G5 BIT(3) --#define AQ_NIC_RATE_1G BIT(4) --#define AQ_NIC_RATE_100M BIT(5) --#define AQ_NIC_RATE_10M BIT(6) --#define AQ_NIC_RATE_1G_HALF BIT(7) --#define AQ_NIC_RATE_100M_HALF BIT(8) --#define AQ_NIC_RATE_10M_HALF BIT(9) -+#define AQ_NIC_RATE_2G5 BIT(2) -+#define AQ_NIC_RATE_1G BIT(3) -+#define AQ_NIC_RATE_100M BIT(4) -+#define AQ_NIC_RATE_10M BIT(5) -+#define AQ_NIC_RATE_1G_HALF BIT(6) -+#define AQ_NIC_RATE_100M_HALF BIT(7) -+#define AQ_NIC_RATE_10M_HALF BIT(8) - --#define AQ_NIC_RATE_EEE_10G BIT(10) --#define AQ_NIC_RATE_EEE_5G BIT(11) --#define AQ_NIC_RATE_EEE_2G5 BIT(12) --#define AQ_NIC_RATE_EEE_1G BIT(13) --#define AQ_NIC_RATE_EEE_100M BIT(14) -+#define AQ_NIC_RATE_EEE_10G BIT(9) -+#define AQ_NIC_RATE_EEE_5G BIT(10) -+#define AQ_NIC_RATE_EEE_2G5 BIT(11) -+#define AQ_NIC_RATE_EEE_1G BIT(12) -+#define AQ_NIC_RATE_EEE_100M BIT(13) - #define AQ_NIC_RATE_EEE_MSK (AQ_NIC_RATE_EEE_10G |\ - AQ_NIC_RATE_EEE_5G |\ - AQ_NIC_RATE_EEE_2G5 |\ -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h -index bed481816ea31..7442850ca95f0 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h -@@ -80,6 +80,8 @@ struct aq_hw_link_status_s { - }; - - struct aq_stats_s { -+ u64 brc; -+ u64 btc; - u64 uprc; - u64 mprc; - u64 bprc; -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c -index 6c049864dac08..9de0065f89b90 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c -@@ -903,8 +903,14 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) - data[++i] = stats->mbtc; - data[++i] = stats->bbrc; - data[++i] = stats->bbtc; -- data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; -- data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; -+ if (stats->brc) -+ data[++i] = stats->brc; -+ else -+ data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; -+ if (stats->btc) -+ data[++i] = stats->btc; -+ else -+ data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; - data[++i] = stats->dma_pkt_rc; - data[++i] = stats->dma_pkt_tc; - data[++i] = stats->dma_oct_rc; -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c -index d4b1976ee69b9..797a95142d1f4 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c -@@ -49,6 +49,8 @@ static const struct pci_device_id aq_pci_tbl[] = { - { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), }, - { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), }, - { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), }, -+ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CA), }, -+ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC116C), }, - - {} - }; -@@ -85,7 +87,10 @@ static const struct aq_board_revision_s hw_atl_boards[] = { - { AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, - { AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, - { AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, -- { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, -+ { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc115c, }, -+ { AQ_DEVICE_ID_AQC113CA, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, -+ { AQ_DEVICE_ID_AQC116C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc116c, }, -+ - }; - - MODULE_DEVICE_TABLE(pci, aq_pci_tbl); -diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c -index d281322d7dd29..f4774cf051c97 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c -+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c -@@ -362,9 +362,6 @@ unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u - { - unsigned int count; - -- WARN_ONCE(!aq_vec_is_valid_tc(self, tc), -- "Invalid tc %u (#rx=%u, #tx=%u)\n", -- tc, self->rx_rings, self->tx_rings); - if (!aq_vec_is_valid_tc(self, tc)) - return 0; - -diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c -index 404cbf60d3f2f..65b9e5846be45 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c -+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c -@@ -559,6 +559,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, - goto err_exit; - - if (fw.len == 0xFFFFU) { -+ if (sw.len > sizeof(self->rpc)) { -+ printk(KERN_INFO "Invalid sw len: %x\n", sw.len); -+ err = -EINVAL; -+ goto err_exit; -+ } - err = hw_atl_utils_fw_rpc_call(self, sw.len); - if (err < 0) - goto err_exit; -@@ -567,6 +572,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, - - if (rpc) { - if (fw.len) { -+ if (fw.len > sizeof(self->rpc)) { -+ printk(KERN_INFO "Invalid fw len: %x\n", fw.len); -+ err = -EINVAL; -+ goto err_exit; -+ } - err = - hw_atl_utils_fw_downld_dwords(self, - self->rpc_addr, -@@ -857,12 +867,20 @@ static int hw_atl_fw1x_deinit(struct aq_hw_s *self) - int hw_atl_utils_update_stats(struct aq_hw_s *self) - { - struct aq_stats_s *cs = &self->curr_stats; -+ struct aq_stats_s curr_stats = *cs; - struct hw_atl_utils_mbox mbox; -+ bool corrupted_stats = false; - - hw_atl_utils_mpi_read_stats(self, &mbox); - --#define AQ_SDELTA(_N_) (self->curr_stats._N_ += \ -- mbox.stats._N_ - self->last_stats._N_) -+#define AQ_SDELTA(_N_) \ -+do { \ -+ if (!corrupted_stats && \ -+ ((s64)(mbox.stats._N_ - self->last_stats._N_)) >= 0) \ -+ curr_stats._N_ += mbox.stats._N_ - self->last_stats._N_; \ -+ else \ -+ corrupted_stats = true; \ -+} while (0) - - if (self->aq_link_status.mbps) { - AQ_SDELTA(uprc); -@@ -882,6 +900,9 @@ int hw_atl_utils_update_stats(struct aq_hw_s *self) - AQ_SDELTA(bbrc); - AQ_SDELTA(bbtc); - AQ_SDELTA(dpc); -+ -+ if (!corrupted_stats) -+ *cs = curr_stats; - } - #undef AQ_SDELTA - -diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c -index ee0c22d049354..05086f0040fd9 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c -+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c -@@ -132,9 +132,6 @@ static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) - if (speed & AQ_NIC_RATE_5G) - rate |= FW2X_RATE_5G; - -- if (speed & AQ_NIC_RATE_5GSR) -- rate |= FW2X_RATE_5G; -- - if (speed & AQ_NIC_RATE_2G5) - rate |= FW2X_RATE_2G5; - -diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c -index 92f64048bf691..c76ccdc77ba60 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c -+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c -@@ -65,11 +65,25 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { - AQ_NIC_RATE_5G | - AQ_NIC_RATE_2G5 | - AQ_NIC_RATE_1G | -- AQ_NIC_RATE_1G_HALF | - AQ_NIC_RATE_100M | -- AQ_NIC_RATE_100M_HALF | -- AQ_NIC_RATE_10M | -- AQ_NIC_RATE_10M_HALF, -+ AQ_NIC_RATE_10M, -+}; -+ -+const struct aq_hw_caps_s hw_atl2_caps_aqc115c = { -+ DEFAULT_BOARD_BASIC_CAPABILITIES, -+ .media_type = AQ_HW_MEDIA_TYPE_TP, -+ .link_speed_msk = AQ_NIC_RATE_2G5 | -+ AQ_NIC_RATE_1G | -+ AQ_NIC_RATE_100M | -+ AQ_NIC_RATE_10M, -+}; -+ -+const struct aq_hw_caps_s hw_atl2_caps_aqc116c = { -+ DEFAULT_BOARD_BASIC_CAPABILITIES, -+ .media_type = AQ_HW_MEDIA_TYPE_TP, -+ .link_speed_msk = AQ_NIC_RATE_1G | -+ AQ_NIC_RATE_100M | -+ AQ_NIC_RATE_10M, - }; - - static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) -diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h -index de8723f1c28a1..346f0dc9912e5 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h -+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h -@@ -9,6 +9,8 @@ - #include "aq_common.h" - - extern const struct aq_hw_caps_s hw_atl2_caps_aqc113; -+extern const struct aq_hw_caps_s hw_atl2_caps_aqc115c; -+extern const struct aq_hw_caps_s hw_atl2_caps_aqc116c; - extern const struct aq_hw_ops hw_atl2_ops; - - #endif /* HW_ATL2_H */ -diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h -index b66fa346581ce..6bad64c77b87c 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h -+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h -@@ -239,7 +239,8 @@ struct version_s { - u8 minor; - u16 build; - } phy; -- u32 rsvd; -+ u32 drv_iface_ver:4; -+ u32 rsvd:28; - }; - - struct link_status_s { -@@ -424,7 +425,7 @@ struct cable_diag_status_s { - u16 rsvd2; - }; - --struct statistics_s { -+struct statistics_a0_s { - struct { - u32 link_up; - u32 link_down; -@@ -457,6 +458,33 @@ struct statistics_s { - u32 reserve_fw_gap; - }; - -+struct __packed statistics_b0_s { -+ u64 rx_good_octets; -+ u64 rx_pause_frames; -+ u64 rx_good_frames; -+ u64 rx_errors; -+ u64 rx_unicast_frames; -+ u64 rx_multicast_frames; -+ u64 rx_broadcast_frames; -+ -+ u64 tx_good_octets; -+ u64 tx_pause_frames; -+ u64 tx_good_frames; -+ u64 tx_errors; -+ u64 tx_unicast_frames; -+ u64 tx_multicast_frames; -+ u64 tx_broadcast_frames; -+ -+ u32 main_loop_cycles; -+}; -+ -+struct __packed statistics_s { -+ union __packed { -+ struct statistics_a0_s a0; -+ struct statistics_b0_s b0; -+ }; -+}; -+ - struct filter_caps_s { - u8 l2_filters_base_index:6; - u8 flexible_filter_mask:2; -@@ -545,7 +573,7 @@ struct management_status_s { - u32 rsvd5; - }; - --struct fw_interface_out { -+struct __packed fw_interface_out { - struct transaction_counter_s transaction_id; - struct version_s version; - struct link_status_s link_status; -@@ -569,7 +597,6 @@ struct fw_interface_out { - struct core_dump_s core_dump; - u32 rsvd11; - struct statistics_s stats; -- u32 rsvd12; - struct filter_caps_s filter_caps; - struct device_caps_s device_caps; - u32 rsvd13; -@@ -592,6 +619,9 @@ struct fw_interface_out { - #define AQ_HOST_MODE_LOW_POWER 3U - #define AQ_HOST_MODE_SHUTDOWN 4U - -+#define AQ_A2_FW_INTERFACE_A0 0 -+#define AQ_A2_FW_INTERFACE_B0 1 -+ - int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops); - - int hw_atl2_utils_soft_reset(struct aq_hw_s *self); -diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c -index dd259c8f2f4f3..58d426dda3edb 100644 ---- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c -+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c -@@ -84,7 +84,7 @@ static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self, - if (cnt > AQ_A2_FW_READ_TRY_MAX) - return -ETIME; - if (tid1.transaction_cnt_a != tid1.transaction_cnt_b) -- udelay(1); -+ mdelay(1); - } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b); - - hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords); -@@ -154,7 +154,7 @@ static void a2_link_speed_mask2fw(u32 speed, - { - link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G); - link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G); -- link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR); -+ link_options->rate_N5G = link_options->rate_5G; - link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5); - link_options->rate_N2P5G = link_options->rate_2P5G; - link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); -@@ -192,8 +192,6 @@ static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps) - rate |= AQ_NIC_RATE_10G; - if (lkp_link_caps->rate_5G) - rate |= AQ_NIC_RATE_5G; -- if (lkp_link_caps->rate_N5G) -- rate |= AQ_NIC_RATE_5GSR; - if (lkp_link_caps->rate_2P5G) - rate |= AQ_NIC_RATE_2G5; - if (lkp_link_caps->rate_1G) -@@ -335,15 +333,22 @@ static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) - return 0; - } - --static int aq_a2_fw_update_stats(struct aq_hw_s *self) -+static void aq_a2_fill_a0_stats(struct aq_hw_s *self, -+ struct statistics_s *stats) - { - struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; -- struct statistics_s stats; -- -- hw_atl2_shared_buffer_read_safe(self, stats, &stats); -- --#define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \ -- stats.msm._F_ - priv->last_stats.msm._F_) -+ struct aq_stats_s *cs = &self->curr_stats; -+ struct aq_stats_s curr_stats = *cs; -+ bool corrupted_stats = false; -+ -+#define AQ_SDELTA(_N, _F) \ -+do { \ -+ if (!corrupted_stats && \ -+ ((s64)(stats->a0.msm._F - priv->last_stats.a0.msm._F)) >= 0) \ -+ curr_stats._N += stats->a0.msm._F - priv->last_stats.a0.msm._F;\ -+ else \ -+ corrupted_stats = true; \ -+} while (0) - - if (self->aq_link_status.mbps) { - AQ_SDELTA(uprc, rx_unicast_frames); -@@ -362,17 +367,76 @@ static int aq_a2_fw_update_stats(struct aq_hw_s *self) - AQ_SDELTA(mbtc, tx_multicast_octets); - AQ_SDELTA(bbrc, rx_broadcast_octets); - AQ_SDELTA(bbtc, tx_broadcast_octets); -+ -+ if (!corrupted_stats) -+ *cs = curr_stats; - } - #undef AQ_SDELTA -- self->curr_stats.dma_pkt_rc = -- hw_atl_stats_rx_dma_good_pkt_counter_get(self); -- self->curr_stats.dma_pkt_tc = -- hw_atl_stats_tx_dma_good_pkt_counter_get(self); -- self->curr_stats.dma_oct_rc = -- hw_atl_stats_rx_dma_good_octet_counter_get(self); -- self->curr_stats.dma_oct_tc = -- hw_atl_stats_tx_dma_good_octet_counter_get(self); -- self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); -+ -+} -+ -+static void aq_a2_fill_b0_stats(struct aq_hw_s *self, -+ struct statistics_s *stats) -+{ -+ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; -+ struct aq_stats_s *cs = &self->curr_stats; -+ struct aq_stats_s curr_stats = *cs; -+ bool corrupted_stats = false; -+ -+#define AQ_SDELTA(_N, _F) \ -+do { \ -+ if (!corrupted_stats && \ -+ ((s64)(stats->b0._F - priv->last_stats.b0._F)) >= 0) \ -+ curr_stats._N += stats->b0._F - priv->last_stats.b0._F; \ -+ else \ -+ corrupted_stats = true; \ -+} while (0) -+ -+ if (self->aq_link_status.mbps) { -+ AQ_SDELTA(uprc, rx_unicast_frames); -+ AQ_SDELTA(mprc, rx_multicast_frames); -+ AQ_SDELTA(bprc, rx_broadcast_frames); -+ AQ_SDELTA(erpr, rx_errors); -+ AQ_SDELTA(brc, rx_good_octets); -+ -+ AQ_SDELTA(uptc, tx_unicast_frames); -+ AQ_SDELTA(mptc, tx_multicast_frames); -+ AQ_SDELTA(bptc, tx_broadcast_frames); -+ AQ_SDELTA(erpt, tx_errors); -+ AQ_SDELTA(btc, tx_good_octets); -+ -+ if (!corrupted_stats) -+ *cs = curr_stats; -+ } -+#undef AQ_SDELTA -+} -+ -+static int aq_a2_fw_update_stats(struct aq_hw_s *self) -+{ -+ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; -+ struct aq_stats_s *cs = &self->curr_stats; -+ struct statistics_s stats; -+ struct version_s version; -+ int err; -+ -+ err = hw_atl2_shared_buffer_read_safe(self, version, &version); -+ if (err) -+ return err; -+ -+ err = hw_atl2_shared_buffer_read_safe(self, stats, &stats); -+ if (err) -+ return err; -+ -+ if (version.drv_iface_ver == AQ_A2_FW_INTERFACE_A0) -+ aq_a2_fill_a0_stats(self, &stats); -+ else -+ aq_a2_fill_b0_stats(self, &stats); -+ -+ cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self); -+ cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self); -+ cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self); -+ cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self); -+ cs->dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); - - memcpy(&priv->last_stats, &stats, sizeof(stats)); - -@@ -499,9 +563,9 @@ u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) - hw_atl2_shared_buffer_read_safe(self, version, &version); - - /* A2 FW version is stored in reverse order */ -- return version.mac.major << 24 | -- version.mac.minor << 16 | -- version.mac.build; -+ return version.bundle.major << 24 | -+ version.bundle.minor << 16 | -+ version.bundle.build; - } - - int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, -diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c -index 02a569500234c..376f81796a293 100644 ---- a/drivers/net/ethernet/broadcom/bcm4908_enet.c -+++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c -@@ -708,7 +708,9 @@ static int bcm4908_enet_probe(struct platform_device *pdev) - - enet->irq_tx = platform_get_irq_byname(pdev, "tx"); - -- dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); -+ err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); -+ if (err) -+ return err; - - err = bcm4908_enet_dma_alloc(enet); - if (err) -diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c -index 7fa1b695400d7..0877b3d7f88c5 100644 ---- a/drivers/net/ethernet/broadcom/bcmsysport.c -+++ b/drivers/net/ethernet/broadcom/bcmsysport.c -@@ -1309,11 +1309,11 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, - struct bcm_sysport_priv *priv = netdev_priv(dev); - struct device *kdev = &priv->pdev->dev; - struct bcm_sysport_tx_ring *ring; -+ unsigned long flags, desc_flags; - struct bcm_sysport_cb *cb; - struct netdev_queue *txq; - u32 len_status, addr_lo; - unsigned int skb_len; -- unsigned long flags; - dma_addr_t mapping; - u16 queue; - int ret; -@@ -1373,8 +1373,10 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, - ring->desc_count--; - - /* Ports are latched, so write upper address first */ -+ spin_lock_irqsave(&priv->desc_lock, desc_flags); - tdma_writel(priv, len_status, TDMA_WRITE_PORT_HI(ring->index)); - tdma_writel(priv, addr_lo, TDMA_WRITE_PORT_LO(ring->index)); -+ spin_unlock_irqrestore(&priv->desc_lock, desc_flags); - - /* Check ring space and update SW control flow */ - if (ring->desc_count == 0) -@@ -2013,6 +2015,7 @@ static int bcm_sysport_open(struct net_device *dev) - } - - /* Initialize both hardware and software ring */ -+ spin_lock_init(&priv->desc_lock); - for (i = 0; i < dev->num_tx_queues; i++) { - ret = bcm_sysport_init_tx_ring(priv, i); - if (ret) { -diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h -index 984f76e74b43e..16b73bb9acc78 100644 ---- a/drivers/net/ethernet/broadcom/bcmsysport.h -+++ b/drivers/net/ethernet/broadcom/bcmsysport.h -@@ -711,6 +711,7 @@ struct bcm_sysport_priv { - int wol_irq; - - /* Transmit rings */ -+ spinlock_t desc_lock; - struct bcm_sysport_tx_ring *tx_rings; - - /* Receive queue */ -diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h -index 1835d2e451c01..fc7fce642666c 100644 ---- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h -+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h -@@ -635,11 +635,13 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, - { - int i, rc; - struct bnx2x_ilt *ilt = BP_ILT(bp); -- struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; -+ struct ilt_client_info *ilt_cli; - - if (!ilt || !ilt->lines) - return -1; - -+ ilt_cli = &ilt->clients[cli_num]; -+ - if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM)) - return 0; - -diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c -index 62f84cc91e4d1..0fba01db336cc 100644 ---- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c -+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c -@@ -13370,7 +13370,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - } - - bnxt_inv_fw_health_reg(bp); -- bnxt_dl_register(bp); -+ rc = bnxt_dl_register(bp); -+ if (rc) -+ goto init_err_dl; - - rc = register_netdev(dev); - if (rc) -@@ -13390,6 +13392,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - - init_err_cleanup: - bnxt_dl_unregister(bp); -+init_err_dl: - bnxt_shutdown_tc(bp); - bnxt_clear_int_mode(bp); - -diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c -index 9576547df4aba..2a80882971e3d 100644 ---- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c -+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c -@@ -134,7 +134,7 @@ void bnxt_dl_fw_reporters_create(struct bnxt *bp) - { - struct bnxt_fw_health *health = bp->fw_health; - -- if (!bp->dl || !health) -+ if (!health) - return; - - if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter) -@@ -188,7 +188,7 @@ void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all) - { - struct bnxt_fw_health *health = bp->fw_health; - -- if (!bp->dl || !health) -+ if (!health) - return; - - if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) && -@@ -781,6 +781,7 @@ int bnxt_dl_register(struct bnxt *bp) - { - const struct devlink_ops *devlink_ops; - struct devlink_port_attrs attrs = {}; -+ struct bnxt_dl *bp_dl; - struct devlink *dl; - int rc; - -@@ -795,7 +796,9 @@ int bnxt_dl_register(struct bnxt *bp) - return -ENOMEM; - } - -- bnxt_link_bp_to_dl(bp, dl); -+ bp->dl = dl; -+ bp_dl = devlink_priv(dl); -+ bp_dl->bp = bp; - - /* Add switchdev eswitch mode setting, if SRIOV supported */ - if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) && -@@ -833,7 +836,6 @@ err_dl_port_unreg: - err_dl_unreg: - devlink_unregister(dl); - err_dl_free: -- bnxt_link_bp_to_dl(bp, NULL); - devlink_free(dl); - return rc; - } -@@ -842,9 +844,6 @@ void bnxt_dl_unregister(struct bnxt *bp) - { - struct devlink *dl = bp->dl; - -- if (!dl) -- return; -- - if (BNXT_PF(bp)) { - bnxt_dl_params_unregister(bp); - devlink_port_unregister(&bp->dl_port); -diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h -index d889f240da2b2..406dc655a5fc9 100644 ---- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h -+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h -@@ -20,19 +20,6 @@ static inline struct bnxt *bnxt_get_bp_from_dl(struct devlink *dl) - return ((struct bnxt_dl *)devlink_priv(dl))->bp; - } - --/* To clear devlink pointer from bp, pass NULL dl */ --static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl) --{ -- bp->dl = dl; -- -- /* add a back pointer in dl to bp */ -- if (dl) { -- struct bnxt_dl *bp_dl = devlink_priv(dl); -- -- bp_dl->bp = bp; -- } --} -- - #define NVM_OFF_MSIX_VEC_PER_PF_MAX 108 - #define NVM_OFF_MSIX_VEC_PER_PF_MIN 114 - #define NVM_OFF_IGNORE_ARI 164 -diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c -index e6a4a768b10b2..1471b6130a2b9 100644 ---- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c -+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c -@@ -1868,7 +1868,7 @@ static int bnxt_tc_setup_indr_block_cb(enum tc_setup_type type, - struct flow_cls_offload *flower = type_data; - struct bnxt *bp = priv->bp; - -- if (flower->common.chain_index) -+ if (!tc_cls_can_offload_and_chain0(bp->dev, type_data)) - return -EOPNOTSUPP; - - switch (type) { -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c -index 5903bdb78916f..129352bbe1143 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c -@@ -2015,12 +2015,15 @@ static int cxgb4_get_module_info(struct net_device *dev, - if (ret) - return ret; - -- if (!sff8472_comp || (sff_diag_type & 4)) { -+ if (!sff8472_comp || (sff_diag_type & SFP_DIAG_ADDRMODE)) { - modinfo->type = ETH_MODULE_SFF_8079; - modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; - } else { - modinfo->type = ETH_MODULE_SFF_8472; -- modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; -+ if (sff_diag_type & SFP_DIAG_IMPLEMENTED) -+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; -+ else -+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2; - } - break; - -diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h -index 002fc62ea7262..63bc956d20376 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h -+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h -@@ -293,6 +293,8 @@ enum { - #define I2C_PAGE_SIZE 0x100 - #define SFP_DIAG_TYPE_ADDR 0x5c - #define SFP_DIAG_TYPE_LEN 0x1 -+#define SFP_DIAG_ADDRMODE BIT(2) -+#define SFP_DIAG_IMPLEMENTED BIT(6) - #define SFF_8472_COMP_ADDR 0x5e - #define SFF_8472_COMP_LEN 0x1 - #define SFF_REV_ADDR 0x1 -diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c -index bcad69c480740..4af5561cbfc54 100644 ---- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c -+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c -@@ -870,7 +870,7 @@ static void do_abort_syn_rcv(struct sock *child, struct sock *parent) - * created only after 3 way handshake is done. - */ - sock_orphan(child); -- percpu_counter_inc((child)->sk_prot->orphan_count); -+ INC_ORPHAN_COUNT(child); - chtls_release_resources(child); - chtls_conn_done(child); - } else { -diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h -index b1161bdeda4dc..f61ca657601ca 100644 ---- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h -+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h -@@ -95,7 +95,7 @@ struct deferred_skb_cb { - #define WSCALE_OK(tp) ((tp)->rx_opt.wscale_ok) - #define TSTAMP_OK(tp) ((tp)->rx_opt.tstamp_ok) - #define SACK_OK(tp) ((tp)->rx_opt.sack_ok) --#define INC_ORPHAN_COUNT(sk) percpu_counter_inc((sk)->sk_prot->orphan_count) -+#define INC_ORPHAN_COUNT(sk) this_cpu_inc(*(sk)->sk_prot->orphan_count) - - /* TLS SKB */ - #define skb_ulp_tls_inline(skb) (ULP_SKB_CB(skb)->ulp.tls.ofld) -diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c -index 36ab4cbf2ad08..b9d967e419387 100644 ---- a/drivers/net/ethernet/dec/tulip/de4x5.c -+++ b/drivers/net/ethernet/dec/tulip/de4x5.c -@@ -4708,6 +4708,10 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p) - lp->ibn = 3; - lp->active = *p++; - if (MOTO_SROM_BUG) lp->active = 0; -+ /* if (MOTO_SROM_BUG) statement indicates lp->active could -+ * be 8 (i.e. the size of array lp->phy) */ -+ if (WARN_ON(lp->active >= ARRAY_SIZE(lp->phy))) -+ return -EINVAL; - lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1); - lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1); - lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2; -@@ -4999,19 +5003,23 @@ mii_get_phy(struct net_device *dev) - } - if ((j == limit) && (i < DE4X5_MAX_MII)) { - for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++); -- lp->phy[k].addr = i; -- lp->phy[k].id = id; -- lp->phy[k].spd.reg = GENERIC_REG; /* ANLPA register */ -- lp->phy[k].spd.mask = GENERIC_MASK; /* 100Mb/s technologies */ -- lp->phy[k].spd.value = GENERIC_VALUE; /* TX & T4, H/F Duplex */ -- lp->mii_cnt++; -- lp->active++; -- printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name); -- j = de4x5_debug; -- de4x5_debug |= DEBUG_MII; -- de4x5_dbg_mii(dev, k); -- de4x5_debug = j; -- printk("\n"); -+ if (k < DE4X5_MAX_PHY) { -+ lp->phy[k].addr = i; -+ lp->phy[k].id = id; -+ lp->phy[k].spd.reg = GENERIC_REG; /* ANLPA register */ -+ lp->phy[k].spd.mask = GENERIC_MASK; /* 100Mb/s technologies */ -+ lp->phy[k].spd.value = GENERIC_VALUE; /* TX & T4, H/F Duplex */ -+ lp->mii_cnt++; -+ lp->active++; -+ printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name); -+ j = de4x5_debug; -+ de4x5_debug |= DEBUG_MII; -+ de4x5_dbg_mii(dev, k); -+ de4x5_debug = j; -+ printk("\n"); -+ } else { -+ goto purgatory; -+ } - } - } - purgatory: -diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c -index 85b99099c6b94..5babcf05bc2f1 100644 ---- a/drivers/net/ethernet/dec/tulip/winbond-840.c -+++ b/drivers/net/ethernet/dec/tulip/winbond-840.c -@@ -877,7 +877,7 @@ static void init_registers(struct net_device *dev) - 8000 16 longwords 0200 2 longwords 2000 32 longwords - C000 32 longwords 0400 4 longwords */ - --#if defined (__i386__) && !defined(MODULE) -+#if defined (__i386__) && !defined(MODULE) && !defined(CONFIG_UML) - /* When not a module we can work around broken '486 PCI boards. */ - if (boot_cpu_data.x86 <= 4) { - i |= 0x4800; -diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c -index 25c91b3c5fd30..819266d463b07 100644 ---- a/drivers/net/ethernet/fealnx.c -+++ b/drivers/net/ethernet/fealnx.c -@@ -857,7 +857,7 @@ static int netdev_open(struct net_device *dev) - np->bcrvalue |= 0x04; /* big-endian */ - #endif - --#if defined(__i386__) && !defined(MODULE) -+#if defined(__i386__) && !defined(MODULE) && !defined(CONFIG_UML) - if (boot_cpu_data.x86 <= 4) - np->crvalue = 0xa00; - else -diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -index 7065c71ed7b86..1108e1730841b 100644 ---- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4538,10 +4538,12 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) - - fsl_mc_portal_free(priv->mc_io); - -- free_netdev(net_dev); -+ destroy_workqueue(priv->dpaa2_ptp_wq); - - dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); - -+ free_netdev(net_dev); -+ - return 0; - } - -diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c -index 4577226d3c6ad..0536d2c76fbc4 100644 ---- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c -+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c -@@ -486,14 +486,16 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, - - data_size = sizeof(struct streamid_data); - si_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL); -+ if (!si_data) -+ return -ENOMEM; - cbd.length = cpu_to_le16(data_size); - - dma = dma_map_single(&priv->si->pdev->dev, si_data, - data_size, DMA_FROM_DEVICE); - if (dma_mapping_error(&priv->si->pdev->dev, dma)) { - netdev_err(priv->si->ndev, "DMA mapping failed!\n"); -- kfree(si_data); -- return -ENOMEM; -+ err = -ENOMEM; -+ goto out; - } - - cbd.addr[0] = cpu_to_le32(lower_32_bits(dma)); -@@ -512,12 +514,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, - - err = enetc_send_cmd(priv->si, &cbd); - if (err) -- return -EINVAL; -+ goto out; - -- if (!enable) { -- kfree(si_data); -- return 0; -- } -+ if (!enable) -+ goto out; - - /* Enable the entry overwrite again incase space flushed by hardware */ - memset(&cbd, 0, sizeof(cbd)); -@@ -560,6 +560,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, - } - - err = enetc_send_cmd(priv->si, &cbd); -+out: -+ if (!dma_mapping_error(&priv->si->pdev->dev, dma)) -+ dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_FROM_DEVICE); -+ - kfree(si_data); - - return err; -diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h -index 7b4961daa2540..ed7301b691694 100644 ---- a/drivers/net/ethernet/freescale/fec.h -+++ b/drivers/net/ethernet/freescale/fec.h -@@ -377,6 +377,9 @@ struct bufdesc_ex { - #define FEC_ENET_WAKEUP ((uint)0x00020000) /* Wakeup request */ - #define FEC_ENET_TXF (FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2) - #define FEC_ENET_RXF (FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2) -+#define FEC_ENET_RXF_GET(X) (((X) == 0) ? FEC_ENET_RXF_0 : \ -+ (((X) == 1) ? FEC_ENET_RXF_1 : \ -+ FEC_ENET_RXF_2)) - #define FEC_ENET_TS_AVAIL ((uint)0x00010000) - #define FEC_ENET_TS_TIMER ((uint)0x00008000) - -diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c -index ec87b370bba1f..a3e87e10ee6bd 100644 ---- a/drivers/net/ethernet/freescale/fec_main.c -+++ b/drivers/net/ethernet/freescale/fec_main.c -@@ -1480,7 +1480,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) - break; - pkt_received++; - -- writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); -+ writel(FEC_ENET_RXF_GET(queue_id), fep->hwp + FEC_IEVENT); - - /* Check for errors. */ - status ^= BD_ENET_RX_LAST; -diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h -index 92dc18a4bcc41..c1d4042671f9f 100644 ---- a/drivers/net/ethernet/google/gve/gve.h -+++ b/drivers/net/ethernet/google/gve/gve.h -@@ -30,7 +30,7 @@ - #define GVE_MIN_MSIX 3 - - /* Numbers of gve tx/rx stats in stats report. */ --#define GVE_TX_STATS_REPORT_NUM 5 -+#define GVE_TX_STATS_REPORT_NUM 6 - #define GVE_RX_STATS_REPORT_NUM 2 - - /* Interval to schedule a stats report update, 20000ms. */ -@@ -224,11 +224,6 @@ struct gve_tx_iovec { - u32 iov_padding; /* padding associated with this segment */ - }; - --struct gve_tx_dma_buf { -- DEFINE_DMA_UNMAP_ADDR(dma); -- DEFINE_DMA_UNMAP_LEN(len); --}; -- - /* Tracks the memory in the fifo occupied by the skb. Mapped 1:1 to a desc - * ring entry but only used for a pkt_desc not a seg_desc - */ -@@ -236,7 +231,10 @@ struct gve_tx_buffer_state { - struct sk_buff *skb; /* skb for this pkt */ - union { - struct gve_tx_iovec iov[GVE_TX_MAX_IOVEC]; /* segments of this pkt */ -- struct gve_tx_dma_buf buf; -+ struct { -+ DEFINE_DMA_UNMAP_ADDR(dma); -+ DEFINE_DMA_UNMAP_LEN(len); -+ }; - }; - }; - -@@ -280,7 +278,8 @@ struct gve_tx_pending_packet_dqo { - * All others correspond to `skb`'s frags and should be unmapped with - * `dma_unmap_page`. - */ -- struct gve_tx_dma_buf bufs[MAX_SKB_FRAGS + 1]; -+ DEFINE_DMA_UNMAP_ADDR(dma[MAX_SKB_FRAGS + 1]); -+ DEFINE_DMA_UNMAP_LEN(len[MAX_SKB_FRAGS + 1]); - u16 num_bufs; - - /* Linked list index to next element in the list, or -1 if none */ -@@ -414,7 +413,9 @@ struct gve_tx_ring { - u32 q_num ____cacheline_aligned; /* queue idx */ - u32 stop_queue; /* count of queue stops */ - u32 wake_queue; /* count of queue wakes */ -+ u32 queue_timeout; /* count of queue timeouts */ - u32 ntfy_id; /* notification block index */ -+ u32 last_kick_msec; /* Last time the queue was kicked */ - dma_addr_t bus; /* dma address of the descr ring */ - dma_addr_t q_resources_bus; /* dma address of the queue resources */ - dma_addr_t complq_bus_dqo; /* dma address of the dqo.compl_ring */ -diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h -index 47c3d8f313fcf..3953f6f7a4273 100644 ---- a/drivers/net/ethernet/google/gve/gve_adminq.h -+++ b/drivers/net/ethernet/google/gve/gve_adminq.h -@@ -270,6 +270,7 @@ enum gve_stat_names { - TX_LAST_COMPLETION_PROCESSED = 5, - RX_NEXT_EXPECTED_SEQUENCE = 6, - RX_BUFFERS_POSTED = 7, -+ TX_TIMEOUT_CNT = 8, - // stats from NIC - RX_QUEUE_DROP_CNT = 65, - RX_NO_BUFFERS_POSTED = 66, -diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c -index bf8a4a7c43f78..959352fceead7 100644 ---- a/drivers/net/ethernet/google/gve/gve_main.c -+++ b/drivers/net/ethernet/google/gve/gve_main.c -@@ -24,6 +24,9 @@ - #define GVE_VERSION "1.0.0" - #define GVE_VERSION_PREFIX "GVE-" - -+// Minimum amount of time between queue kicks in msec (10 seconds) -+#define MIN_TX_TIMEOUT_GAP (1000 * 10) -+ - const char gve_version_str[] = GVE_VERSION; - static const char gve_version_prefix[] = GVE_VERSION_PREFIX; - -@@ -1116,9 +1119,47 @@ static void gve_turnup(struct gve_priv *priv) - - static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue) - { -- struct gve_priv *priv = netdev_priv(dev); -+ struct gve_notify_block *block; -+ struct gve_tx_ring *tx = NULL; -+ struct gve_priv *priv; -+ u32 last_nic_done; -+ u32 current_time; -+ u32 ntfy_idx; -+ -+ netdev_info(dev, "Timeout on tx queue, %d", txqueue); -+ priv = netdev_priv(dev); -+ if (txqueue > priv->tx_cfg.num_queues) -+ goto reset; -+ -+ ntfy_idx = gve_tx_idx_to_ntfy(priv, txqueue); -+ if (ntfy_idx >= priv->num_ntfy_blks) -+ goto reset; -+ -+ block = &priv->ntfy_blocks[ntfy_idx]; -+ tx = block->tx; - -+ current_time = jiffies_to_msecs(jiffies); -+ if (tx->last_kick_msec + MIN_TX_TIMEOUT_GAP > current_time) -+ goto reset; -+ -+ /* Check to see if there are missed completions, which will allow us to -+ * kick the queue. -+ */ -+ last_nic_done = gve_tx_load_event_counter(priv, tx); -+ if (last_nic_done - tx->done) { -+ netdev_info(dev, "Kicking queue %d", txqueue); -+ iowrite32be(GVE_IRQ_MASK, gve_irq_doorbell(priv, block)); -+ napi_schedule(&block->napi); -+ tx->last_kick_msec = current_time; -+ goto out; -+ } // Else reset. -+ -+reset: - gve_schedule_reset(priv); -+ -+out: -+ if (tx) -+ tx->queue_timeout++; - priv->tx_timeo_cnt++; - } - -@@ -1247,6 +1288,11 @@ void gve_handle_report_stats(struct gve_priv *priv) - .value = cpu_to_be64(last_completion), - .queue_id = cpu_to_be32(idx), - }; -+ stats[stats_idx++] = (struct stats) { -+ .stat_name = cpu_to_be32(TX_TIMEOUT_CNT), -+ .value = cpu_to_be64(priv->tx[idx].queue_timeout), -+ .queue_id = cpu_to_be32(idx), -+ }; - } - } - /* rx stats */ -diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c -index 94941d4e47449..16169f291ad9f 100644 ---- a/drivers/net/ethernet/google/gve/gve_rx.c -+++ b/drivers/net/ethernet/google/gve/gve_rx.c -@@ -514,8 +514,13 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx) - - gve_rx_free_buffer(dev, page_info, data_slot); - page_info->page = NULL; -- if (gve_rx_alloc_buffer(priv, dev, page_info, data_slot)) -+ if (gve_rx_alloc_buffer(priv, dev, page_info, -+ data_slot)) { -+ u64_stats_update_begin(&rx->statss); -+ rx->rx_buf_alloc_fail++; -+ u64_stats_update_end(&rx->statss); - break; -+ } - } - } - fill_cnt++; -diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c -index 665ac795a1adf..9922ce46a6351 100644 ---- a/drivers/net/ethernet/google/gve/gve_tx.c -+++ b/drivers/net/ethernet/google/gve/gve_tx.c -@@ -303,15 +303,15 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx, - static void gve_tx_unmap_buf(struct device *dev, struct gve_tx_buffer_state *info) - { - if (info->skb) { -- dma_unmap_single(dev, dma_unmap_addr(&info->buf, dma), -- dma_unmap_len(&info->buf, len), -+ dma_unmap_single(dev, dma_unmap_addr(info, dma), -+ dma_unmap_len(info, len), - DMA_TO_DEVICE); -- dma_unmap_len_set(&info->buf, len, 0); -+ dma_unmap_len_set(info, len, 0); - } else { -- dma_unmap_page(dev, dma_unmap_addr(&info->buf, dma), -- dma_unmap_len(&info->buf, len), -+ dma_unmap_page(dev, dma_unmap_addr(info, dma), -+ dma_unmap_len(info, len), - DMA_TO_DEVICE); -- dma_unmap_len_set(&info->buf, len, 0); -+ dma_unmap_len_set(info, len, 0); - } - } - -@@ -491,7 +491,6 @@ static int gve_tx_add_skb_no_copy(struct gve_priv *priv, struct gve_tx_ring *tx, - struct gve_tx_buffer_state *info; - bool is_gso = skb_is_gso(skb); - u32 idx = tx->req & tx->mask; -- struct gve_tx_dma_buf *buf; - u64 addr; - u32 len; - int i; -@@ -515,9 +514,8 @@ static int gve_tx_add_skb_no_copy(struct gve_priv *priv, struct gve_tx_ring *tx, - tx->dma_mapping_error++; - goto drop; - } -- buf = &info->buf; -- dma_unmap_len_set(buf, len, len); -- dma_unmap_addr_set(buf, dma, addr); -+ dma_unmap_len_set(info, len, len); -+ dma_unmap_addr_set(info, dma, addr); - - payload_nfrags = shinfo->nr_frags; - if (hlen < len) { -@@ -549,10 +547,9 @@ static int gve_tx_add_skb_no_copy(struct gve_priv *priv, struct gve_tx_ring *tx, - tx->dma_mapping_error++; - goto unmap_drop; - } -- buf = &tx->info[idx].buf; - tx->info[idx].skb = NULL; -- dma_unmap_len_set(buf, len, len); -- dma_unmap_addr_set(buf, dma, addr); -+ dma_unmap_len_set(&tx->info[idx], len, len); -+ dma_unmap_addr_set(&tx->info[idx], dma, addr); - - gve_tx_fill_seg_desc(seg_desc, skb, is_gso, len, addr); - } -diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c -index 05ddb6a75c38f..ec394d9916681 100644 ---- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c -+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c -@@ -85,18 +85,16 @@ static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx) - int j; - - for (j = 0; j < cur_state->num_bufs; j++) { -- struct gve_tx_dma_buf *buf = &cur_state->bufs[j]; -- - if (j == 0) { - dma_unmap_single(tx->dev, -- dma_unmap_addr(buf, dma), -- dma_unmap_len(buf, len), -- DMA_TO_DEVICE); -+ dma_unmap_addr(cur_state, dma[j]), -+ dma_unmap_len(cur_state, len[j]), -+ DMA_TO_DEVICE); - } else { - dma_unmap_page(tx->dev, -- dma_unmap_addr(buf, dma), -- dma_unmap_len(buf, len), -- DMA_TO_DEVICE); -+ dma_unmap_addr(cur_state, dma[j]), -+ dma_unmap_len(cur_state, len[j]), -+ DMA_TO_DEVICE); - } - } - if (cur_state->skb) { -@@ -457,15 +455,15 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - const bool is_gso = skb_is_gso(skb); - u32 desc_idx = tx->dqo_tx.tail; - -- struct gve_tx_pending_packet_dqo *pending_packet; -+ struct gve_tx_pending_packet_dqo *pkt; - struct gve_tx_metadata_dqo metadata; - s16 completion_tag; - int i; - -- pending_packet = gve_alloc_pending_packet(tx); -- pending_packet->skb = skb; -- pending_packet->num_bufs = 0; -- completion_tag = pending_packet - tx->dqo.pending_packets; -+ pkt = gve_alloc_pending_packet(tx); -+ pkt->skb = skb; -+ pkt->num_bufs = 0; -+ completion_tag = pkt - tx->dqo.pending_packets; - - gve_extract_tx_metadata_dqo(skb, &metadata); - if (is_gso) { -@@ -493,8 +491,6 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - - /* Map the linear portion of skb */ - { -- struct gve_tx_dma_buf *buf = -- &pending_packet->bufs[pending_packet->num_bufs]; - u32 len = skb_headlen(skb); - dma_addr_t addr; - -@@ -502,9 +498,9 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - if (unlikely(dma_mapping_error(tx->dev, addr))) - goto err; - -- dma_unmap_len_set(buf, len, len); -- dma_unmap_addr_set(buf, dma, addr); -- ++pending_packet->num_bufs; -+ dma_unmap_len_set(pkt, len[pkt->num_bufs], len); -+ dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr); -+ ++pkt->num_bufs; - - gve_tx_fill_pkt_desc_dqo(tx, &desc_idx, skb, len, addr, - completion_tag, -@@ -512,8 +508,6 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - } - - for (i = 0; i < shinfo->nr_frags; i++) { -- struct gve_tx_dma_buf *buf = -- &pending_packet->bufs[pending_packet->num_bufs]; - const skb_frag_t *frag = &shinfo->frags[i]; - bool is_eop = i == (shinfo->nr_frags - 1); - u32 len = skb_frag_size(frag); -@@ -523,9 +517,9 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - if (unlikely(dma_mapping_error(tx->dev, addr))) - goto err; - -- dma_unmap_len_set(buf, len, len); -- dma_unmap_addr_set(buf, dma, addr); -- ++pending_packet->num_bufs; -+ dma_unmap_len_set(pkt, len[pkt->num_bufs], len); -+ dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr); -+ ++pkt->num_bufs; - - gve_tx_fill_pkt_desc_dqo(tx, &desc_idx, skb, len, addr, - completion_tag, is_eop, is_gso); -@@ -552,22 +546,23 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, - return 0; - - err: -- for (i = 0; i < pending_packet->num_bufs; i++) { -- struct gve_tx_dma_buf *buf = &pending_packet->bufs[i]; -- -+ for (i = 0; i < pkt->num_bufs; i++) { - if (i == 0) { -- dma_unmap_single(tx->dev, dma_unmap_addr(buf, dma), -- dma_unmap_len(buf, len), -+ dma_unmap_single(tx->dev, -+ dma_unmap_addr(pkt, dma[i]), -+ dma_unmap_len(pkt, len[i]), - DMA_TO_DEVICE); - } else { -- dma_unmap_page(tx->dev, dma_unmap_addr(buf, dma), -- dma_unmap_len(buf, len), DMA_TO_DEVICE); -+ dma_unmap_page(tx->dev, -+ dma_unmap_addr(pkt, dma[i]), -+ dma_unmap_len(pkt, len[i]), -+ DMA_TO_DEVICE); - } - } - -- pending_packet->skb = NULL; -- pending_packet->num_bufs = 0; -- gve_free_pending_packet(tx, pending_packet); -+ pkt->skb = NULL; -+ pkt->num_bufs = 0; -+ gve_free_pending_packet(tx, pkt); - - return -1; - } -@@ -725,12 +720,12 @@ static void add_to_list(struct gve_tx_ring *tx, struct gve_index_list *list, - - static void remove_from_list(struct gve_tx_ring *tx, - struct gve_index_list *list, -- struct gve_tx_pending_packet_dqo *pending_packet) -+ struct gve_tx_pending_packet_dqo *pkt) - { - s16 prev_index, next_index; - -- prev_index = pending_packet->prev; -- next_index = pending_packet->next; -+ prev_index = pkt->prev; -+ next_index = pkt->next; - - if (prev_index == -1) { - /* Node is head */ -@@ -747,21 +742,18 @@ static void remove_from_list(struct gve_tx_ring *tx, - } - - static void gve_unmap_packet(struct device *dev, -- struct gve_tx_pending_packet_dqo *pending_packet) -+ struct gve_tx_pending_packet_dqo *pkt) - { -- struct gve_tx_dma_buf *buf; - int i; - - /* SKB linear portion is guaranteed to be mapped */ -- buf = &pending_packet->bufs[0]; -- dma_unmap_single(dev, dma_unmap_addr(buf, dma), -- dma_unmap_len(buf, len), DMA_TO_DEVICE); -- for (i = 1; i < pending_packet->num_bufs; i++) { -- buf = &pending_packet->bufs[i]; -- dma_unmap_page(dev, dma_unmap_addr(buf, dma), -- dma_unmap_len(buf, len), DMA_TO_DEVICE); -+ dma_unmap_single(dev, dma_unmap_addr(pkt, dma[0]), -+ dma_unmap_len(pkt, len[0]), DMA_TO_DEVICE); -+ for (i = 1; i < pkt->num_bufs; i++) { -+ dma_unmap_page(dev, dma_unmap_addr(pkt, dma[i]), -+ dma_unmap_len(pkt, len[i]), DMA_TO_DEVICE); - } -- pending_packet->num_bufs = 0; -+ pkt->num_bufs = 0; - } - - /* Completion types and expected behavior: -diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c -index 23d9cbf262c32..740850b64aff5 100644 ---- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c -+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c -@@ -400,6 +400,10 @@ static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, - return; - - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { -+ /* DSAF_MAX_PORT_NUM is 6, but DSAF_GE_NUM is 8. -+ We need check to prevent array overflow */ -+ if (port >= DSAF_MAX_PORT_NUM) -+ return; - reg_val_1 = 0x1 << port; - port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off; - /* there is difference between V1 and V2 in register.*/ -diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h -index d701451596c82..47bba4c62f040 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h -@@ -830,6 +830,8 @@ struct hnae3_handle { - - u8 netdev_flags; - struct dentry *hnae3_dbgfs; -+ /* protects concurrent contention between debugfs commands */ -+ struct mutex dbgfs_lock; - - /* Network interface message level enabled bits */ - u32 msg_enable; -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c -index e54f96251fea9..3205849bdb95b 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c -@@ -1021,6 +1021,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, - if (ret) - return ret; - -+ mutex_lock(&handle->dbgfs_lock); - save_buf = &hns3_dbg_cmd[index].buf; - - if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || -@@ -1033,15 +1034,15 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, - read_buf = *save_buf; - } else { - read_buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL); -- if (!read_buf) -- return -ENOMEM; -+ if (!read_buf) { -+ ret = -ENOMEM; -+ goto out; -+ } - - /* save the buffer addr until the last read operation */ - *save_buf = read_buf; -- } - -- /* get data ready for the first time to read */ -- if (!*ppos) { -+ /* get data ready for the first time to read */ - ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd, - read_buf, hns3_dbg_cmd[index].buf_len); - if (ret) -@@ -1050,8 +1051,10 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, - - size = simple_read_from_buffer(buffer, count, ppos, read_buf, - strlen(read_buf)); -- if (size > 0) -+ if (size > 0) { -+ mutex_unlock(&handle->dbgfs_lock); - return size; -+ } - - out: - /* free the buffer for the last read operation */ -@@ -1060,6 +1063,7 @@ out: - *save_buf = NULL; - } - -+ mutex_unlock(&handle->dbgfs_lock); - return ret; - } - -@@ -1132,6 +1136,8 @@ int hns3_dbg_init(struct hnae3_handle *handle) - debugfs_create_dir(hns3_dbg_dentry[i].name, - handle->hnae3_dbgfs); - -+ mutex_init(&handle->dbgfs_lock); -+ - for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { - if ((hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES && - ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) || -@@ -1158,6 +1164,7 @@ int hns3_dbg_init(struct hnae3_handle *handle) - return 0; - - out: -+ mutex_destroy(&handle->dbgfs_lock); - debugfs_remove_recursive(handle->hnae3_dbgfs); - handle->hnae3_dbgfs = NULL; - return ret; -@@ -1173,6 +1180,7 @@ void hns3_dbg_uninit(struct hnae3_handle *handle) - hns3_dbg_cmd[i].buf = NULL; - } - -+ mutex_destroy(&handle->dbgfs_lock); - debugfs_remove_recursive(handle->hnae3_dbgfs); - handle->hnae3_dbgfs = NULL; - } -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c -index 5ebd96f6833d6..526fb56c84f24 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c -@@ -985,6 +985,7 @@ static int hns3_set_reset(struct net_device *netdev, u32 *flags) - struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); - const struct hnae3_ae_ops *ops = h->ae_algo->ops; - const struct hns3_reset_type_map *rst_type_map; -+ enum ethtool_reset_flags rst_flags; - u32 i, size; - - if (ops->ae_dev_resetting && ops->ae_dev_resetting(h)) -@@ -1004,6 +1005,7 @@ static int hns3_set_reset(struct net_device *netdev, u32 *flags) - for (i = 0; i < size; i++) { - if (rst_type_map[i].rst_flags == *flags) { - rst_type = rst_type_map[i].rst_type; -+ rst_flags = rst_type_map[i].rst_flags; - break; - } - } -@@ -1019,6 +1021,8 @@ static int hns3_set_reset(struct net_device *netdev, u32 *flags) - - ops->reset_event(h->pdev, h); - -+ *flags &= ~rst_flags; -+ - return 0; - } - -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c -index 91cb578f56b80..375ebf105a9aa 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c -@@ -129,7 +129,7 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev, - u32 total_ets_bw = 0; - u8 i; - -- for (i = 0; i < hdev->tc_max; i++) { -+ for (i = 0; i < HNAE3_MAX_TC; i++) { - switch (ets->tc_tsa[i]) { - case IEEE_8021QAZ_TSA_STRICT: - if (hdev->tm_info.tc_info[i].tc_sch_mode != -@@ -286,28 +286,24 @@ err_out: - - static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) - { -- u64 requests[HNAE3_MAX_TC], indications[HNAE3_MAX_TC]; - struct hclge_vport *vport = hclge_get_vport(h); - struct hclge_dev *hdev = vport->back; - int ret; -- u8 i; - - memset(pfc, 0, sizeof(*pfc)); - pfc->pfc_cap = hdev->pfc_max; - pfc->pfc_en = hdev->tm_info.pfc_en; - -- ret = hclge_pfc_tx_stats_get(hdev, requests); -- if (ret) -+ ret = hclge_mac_update_stats(hdev); -+ if (ret) { -+ dev_err(&hdev->pdev->dev, -+ "failed to update MAC stats, ret = %d.\n", ret); - return ret; -+ } - -- ret = hclge_pfc_rx_stats_get(hdev, indications); -- if (ret) -- return ret; -+ hclge_pfc_tx_stats_get(hdev, pfc->requests); -+ hclge_pfc_rx_stats_get(hdev, pfc->indications); - -- for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { -- pfc->requests[i] = requests[i]; -- pfc->indications[i] = indications[i]; -- } - return 0; - } - -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c -index d891390d492f6..66c407d0d507e 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c -@@ -26,8 +26,6 @@ - #include "hclge_devlink.h" - - #define HCLGE_NAME "hclge" --#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) --#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f)) - - #define HCLGE_BUF_SIZE_UNIT 256U - #define HCLGE_BUF_MUL_BY 2 -@@ -548,7 +546,7 @@ static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *desc_num) - return 0; - } - --static int hclge_mac_update_stats(struct hclge_dev *hdev) -+int hclge_mac_update_stats(struct hclge_dev *hdev) - { - u32 desc_num; - int ret; -@@ -2498,7 +2496,7 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport) - if (hdev->num_msi < hdev->num_nic_msi + hdev->num_roce_msi) - return -EINVAL; - -- roce->rinfo.base_vector = hdev->roce_base_vector; -+ roce->rinfo.base_vector = hdev->num_nic_msi; - - roce->rinfo.netdev = nic->kinfo.netdev; - roce->rinfo.roce_io_base = hdev->hw.io_base; -@@ -2534,10 +2532,6 @@ static int hclge_init_msi(struct hclge_dev *hdev) - hdev->num_msi = vectors; - hdev->num_msi_left = vectors; - -- hdev->base_msi_vector = pdev->irq; -- hdev->roce_base_vector = hdev->base_msi_vector + -- hdev->num_nic_msi; -- - hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi, - sizeof(u16), GFP_KERNEL); - if (!hdev->vector_status) { -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h -index 69cd8f87b4c86..2fa6e14c96e5b 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h -@@ -824,6 +824,9 @@ struct hclge_vf_vlan_cfg { - (y) = (_k_ ^ ~_v_) & (_k_); \ - } while (0) - -+#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f)) -+#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) -+ - #define HCLGE_MAC_TNL_LOG_SIZE 8 - #define HCLGE_VPORT_NUM 256 - struct hclge_dev { -@@ -876,12 +879,10 @@ struct hclge_dev { - u16 num_msi; - u16 num_msi_left; - u16 num_msi_used; -- u32 base_msi_vector; - u16 *vector_status; - int *vector_irq; - u16 num_nic_msi; /* Num of nic vectors for this PF */ - u16 num_roce_msi; /* Num of roce vectors for this PF */ -- int roce_base_vector; - - unsigned long service_timer_period; - unsigned long service_timer_previous; -@@ -1138,4 +1139,5 @@ void hclge_inform_vf_promisc_info(struct hclge_vport *vport); - int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); - int hclge_push_vf_link_status(struct hclge_vport *vport); - int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en); -+int hclge_mac_update_stats(struct hclge_dev *hdev); - #endif -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c -index 95074e91a8466..429652a8cde16 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c -@@ -113,50 +113,50 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, - return 0; - } - --static int hclge_pfc_stats_get(struct hclge_dev *hdev, -- enum hclge_opcode_type opcode, u64 *stats) --{ -- struct hclge_desc desc[HCLGE_TM_PFC_PKT_GET_CMD_NUM]; -- int ret, i, j; -- -- if (!(opcode == HCLGE_OPC_QUERY_PFC_RX_PKT_CNT || -- opcode == HCLGE_OPC_QUERY_PFC_TX_PKT_CNT)) -- return -EINVAL; -- -- for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM - 1; i++) { -- hclge_cmd_setup_basic_desc(&desc[i], opcode, true); -- desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); -- } -- -- hclge_cmd_setup_basic_desc(&desc[i], opcode, true); -+static const u16 hclge_pfc_tx_stats_offset[] = { -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri1_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri2_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri3_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri4_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri5_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_pkt_num) -+}; - -- ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_TM_PFC_PKT_GET_CMD_NUM); -- if (ret) -- return ret; -+static const u16 hclge_pfc_rx_stats_offset[] = { -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri1_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri2_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri3_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri4_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri5_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri6_pkt_num), -+ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri7_pkt_num) -+}; - -- for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM; i++) { -- struct hclge_pfc_stats_cmd *pfc_stats = -- (struct hclge_pfc_stats_cmd *)desc[i].data; -+static void hclge_pfc_stats_get(struct hclge_dev *hdev, bool tx, u64 *stats) -+{ -+ const u16 *offset; -+ int i; - -- for (j = 0; j < HCLGE_TM_PFC_NUM_GET_PER_CMD; j++) { -- u32 index = i * HCLGE_TM_PFC_PKT_GET_CMD_NUM + j; -+ if (tx) -+ offset = hclge_pfc_tx_stats_offset; -+ else -+ offset = hclge_pfc_rx_stats_offset; - -- if (index < HCLGE_MAX_TC_NUM) -- stats[index] = -- le64_to_cpu(pfc_stats->pkt_num[j]); -- } -- } -- return 0; -+ for (i = 0; i < HCLGE_MAX_TC_NUM; i++) -+ stats[i] = HCLGE_STATS_READ(&hdev->mac_stats, offset[i]); - } - --int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats) -+void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats) - { -- return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_RX_PKT_CNT, stats); -+ hclge_pfc_stats_get(hdev, false, stats); - } - --int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats) -+void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats) - { -- return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_TX_PKT_CNT, stats); -+ hclge_pfc_stats_get(hdev, true, stats); - } - - int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx) -@@ -1123,7 +1123,6 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) - - static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) - { --#define DEFAULT_TC_WEIGHT 1 - #define DEFAULT_TC_OFFSET 14 - - struct hclge_ets_tc_weight_cmd *ets_weight; -@@ -1136,13 +1135,7 @@ static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) - for (i = 0; i < HNAE3_MAX_TC; i++) { - struct hclge_pg_info *pg_info; - -- ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT; -- -- if (!(hdev->hw_tc_map & BIT(i))) -- continue; -- -- pg_info = -- &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; -+ pg_info = &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; - ets_weight->tc_weight[i] = pg_info->tc_dwrr[i]; - } - -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h -index 2ee9b795f71dc..1db7f40b45255 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h -@@ -228,8 +228,8 @@ int hclge_tm_dwrr_cfg(struct hclge_dev *hdev); - int hclge_tm_init_hw(struct hclge_dev *hdev, bool init); - int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); - int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); --int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); --int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); -+void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); -+void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); - int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate); - int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num); - int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num); -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c -index cf00ad7bb881f..fee7d9e79f8c3 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c -@@ -703,9 +703,9 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) - roundup_size = ilog2(roundup_size); - - for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) { -- tc_valid[i] = !!(hdev->hw_tc_map & BIT(i)); -+ tc_valid[i] = 1; - tc_size[i] = roundup_size; -- tc_offset[i] = rss_size * i; -+ tc_offset[i] = (hdev->hw_tc_map & BIT(i)) ? rss_size * i : 0; - } - - hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_TC_MODE, false); -@@ -2557,7 +2557,7 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev) - hdev->num_msi_left == 0) - return -EINVAL; - -- roce->rinfo.base_vector = hdev->roce_base_vector; -+ roce->rinfo.base_vector = hdev->roce_base_msix_offset; - - roce->rinfo.netdev = nic->kinfo.netdev; - roce->rinfo.roce_io_base = hdev->hw.io_base; -@@ -2823,9 +2823,6 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev) - hdev->num_msi = vectors; - hdev->num_msi_left = vectors; - -- hdev->base_msi_vector = pdev->irq; -- hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset; -- - hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi, - sizeof(u16), GFP_KERNEL); - if (!hdev->vector_status) { -@@ -3013,7 +3010,10 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client, - - /* un-init roce, if it exists */ - if (hdev->roce_client) { -+ while (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) -+ msleep(HCLGEVF_WAIT_RESET_DONE); - clear_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state); -+ - hdev->roce_client->ops->uninit_instance(&hdev->roce, 0); - hdev->roce_client = NULL; - hdev->roce.client = NULL; -@@ -3022,6 +3022,8 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client, - /* un-init nic/unic, if this was not called by roce client */ - if (client->ops->uninit_instance && hdev->nic_client && - client->type != HNAE3_CLIENT_ROCE) { -+ while (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) -+ msleep(HCLGEVF_WAIT_RESET_DONE); - clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state); - - client->ops->uninit_instance(&hdev->nic, 0); -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h -index 28288d7e33032..f6f736c0091c0 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h -@@ -109,6 +109,8 @@ - #define HCLGEVF_VF_RST_ING 0x07008 - #define HCLGEVF_VF_RST_ING_BIT BIT(16) - -+#define HCLGEVF_WAIT_RESET_DONE 100 -+ - #define HCLGEVF_RSS_IND_TBL_SIZE 512 - #define HCLGEVF_RSS_SET_BITMAP_MSK 0xffff - #define HCLGEVF_RSS_KEY_SIZE 40 -@@ -308,8 +310,6 @@ struct hclgevf_dev { - u16 num_nic_msix; /* Num of nic vectors for this VF */ - u16 num_roce_msix; /* Num of roce vectors for this VF */ - u16 roce_base_msix_offset; -- int roce_base_vector; -- u32 base_msi_vector; - u16 *vector_status; - int *vector_irq; - -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c -index fdc66fae09601..c5ac6ecf36e10 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c -@@ -114,7 +114,8 @@ int hclgevf_send_mbx_msg(struct hclgevf_dev *hdev, - - memcpy(&req->msg, send_msg, sizeof(struct hclge_vf_to_pf_msg)); - -- trace_hclge_vf_mbx_send(hdev, req); -+ if (test_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state)) -+ trace_hclge_vf_mbx_send(hdev, req); - - /* synchronous send */ - if (need_resp) { -diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c -index 6aa6ff89a7651..352ffe982d849 100644 ---- a/drivers/net/ethernet/ibm/ibmvnic.c -+++ b/drivers/net/ethernet/ibm/ibmvnic.c -@@ -1724,8 +1724,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) - ind_bufp = &tx_scrq->ind_buf; - - if (test_bit(0, &adapter->resetting)) { -- if (!netif_subqueue_stopped(netdev, skb)) -- netif_stop_subqueue(netdev, queue_num); - dev_kfree_skb_any(skb); - - tx_send_failed++; -@@ -2567,7 +2565,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, - - if (adapter->state == VNIC_PROBING) { - netdev_warn(netdev, "Adapter reset during probe\n"); -- adapter->init_done_rc = EAGAIN; -+ adapter->init_done_rc = -EAGAIN; - ret = EAGAIN; - goto err; - } -@@ -5069,11 +5067,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, - */ - adapter->login_pending = false; - -- if (!completion_done(&adapter->init_done)) { -- complete(&adapter->init_done); -- adapter->init_done_rc = -EIO; -- } -- - if (adapter->state == VNIC_DOWN) - rc = ibmvnic_reset(adapter, VNIC_RESET_PASSIVE_INIT); - else -@@ -5094,6 +5087,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, - rc); - adapter->failover_pending = false; - } -+ -+ if (!completion_done(&adapter->init_done)) { -+ complete(&adapter->init_done); -+ if (!adapter->init_done_rc) -+ adapter->init_done_rc = -EAGAIN; -+ } -+ - break; - case IBMVNIC_CRQ_INIT_COMPLETE: - dev_info(dev, "Partner initialization complete\n"); -@@ -5414,6 +5414,9 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) - crq->cur = 0; - spin_lock_init(&crq->lock); - -+ /* process any CRQs that were queued before we enabled interrupts */ -+ tasklet_schedule(&adapter->tasklet); -+ - return retrc; - - req_irq_failed: -@@ -5558,7 +5561,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) - } - - rc = ibmvnic_reset_init(adapter, false); -- } while (rc == EAGAIN); -+ } while (rc == -EAGAIN); - - /* We are ignoring the error from ibmvnic_reset_init() assuming that the - * partner is not ready. CRQ is not active. When the partner becomes -diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c -index 09ae1939e6db4..36d52246bdc66 100644 ---- a/drivers/net/ethernet/intel/e100.c -+++ b/drivers/net/ethernet/intel/e100.c -@@ -3003,9 +3003,10 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) - struct net_device *netdev = pci_get_drvdata(pdev); - struct nic *nic = netdev_priv(netdev); - -+ netif_device_detach(netdev); -+ - if (netif_running(netdev)) - e100_down(nic); -- netif_device_detach(netdev); - - if ((nic->flags & wol_magic) | e100_asf(nic)) { - /* enable reverse auto-negotiation */ -@@ -3022,7 +3023,7 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) - *enable_wake = false; - } - -- pci_clear_master(pdev); -+ pci_disable_device(pdev); - } - - static int __e100_power_off(struct pci_dev *pdev, bool wake) -@@ -3042,8 +3043,6 @@ static int __maybe_unused e100_suspend(struct device *dev_d) - - __e100_shutdown(to_pci_dev(dev_d), &wake); - -- device_wakeup_disable(dev_d); -- - return 0; - } - -@@ -3051,6 +3050,14 @@ static int __maybe_unused e100_resume(struct device *dev_d) - { - struct net_device *netdev = dev_get_drvdata(dev_d); - struct nic *nic = netdev_priv(netdev); -+ int err; -+ -+ err = pci_enable_device(to_pci_dev(dev_d)); -+ if (err) { -+ netdev_err(netdev, "Resume cannot enable PCI device, aborting\n"); -+ return err; -+ } -+ pci_set_master(to_pci_dev(dev_d)); - - /* disable reverse auto-negotiation */ - if (nic->phy == phy_82552_v) { -@@ -3062,10 +3069,11 @@ static int __maybe_unused e100_resume(struct device *dev_d) - smartspeed & ~(E100_82552_REV_ANEG)); - } - -- netif_device_attach(netdev); - if (netif_running(netdev)) - e100_up(nic); - -+ netif_device_attach(netdev); -+ - return 0; - } - -diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h -index 39fb3d57c0574..b10bc59c5700f 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e.h -+++ b/drivers/net/ethernet/intel/i40e/i40e.h -@@ -161,6 +161,7 @@ enum i40e_vsi_state_t { - __I40E_VSI_OVERFLOW_PROMISC, - __I40E_VSI_REINIT_REQUESTED, - __I40E_VSI_DOWN_REQUESTED, -+ __I40E_VSI_RELEASING, - /* This must be last as it determines the size of the BITMAP */ - __I40E_VSI_STATE_SIZE__, - }; -@@ -1247,6 +1248,7 @@ void i40e_ptp_restore_hw_time(struct i40e_pf *pf); - void i40e_ptp_init(struct i40e_pf *pf); - void i40e_ptp_stop(struct i40e_pf *pf); - int i40e_ptp_alloc_pins(struct i40e_pf *pf); -+int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset); - int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi); - i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf); - i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf); -diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c -index 291e61ac3e448..2c1b1da1220ec 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c -@@ -553,6 +553,14 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, - dev_info(&pf->pdev->dev, "vsi %d not found\n", vsi_seid); - return; - } -+ if (vsi->type != I40E_VSI_MAIN && -+ vsi->type != I40E_VSI_FDIR && -+ vsi->type != I40E_VSI_VMDQ2) { -+ dev_info(&pf->pdev->dev, -+ "vsi %d type %d descriptor rings not available\n", -+ vsi_seid, vsi->type); -+ return; -+ } - if (type == RING_TYPE_XDP && !i40e_enabled_xdp_vsi(vsi)) { - dev_info(&pf->pdev->dev, "XDP not enabled on VSI %d\n", vsi_seid); - return; -diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c -index e04b540cedc85..76d0b809d1340 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_main.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c -@@ -1790,6 +1790,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, - bool is_add) - { - struct i40e_pf *pf = vsi->back; -+ u16 num_tc_qps = 0; - u16 sections = 0; - u8 netdev_tc = 0; - u16 numtc = 1; -@@ -1797,13 +1798,33 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, - u8 offset; - u16 qmap; - int i; -- u16 num_tc_qps = 0; - - sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID; - offset = 0; -+ /* zero out queue mapping, it will get updated on the end of the function */ -+ memset(ctxt->info.queue_mapping, 0, sizeof(ctxt->info.queue_mapping)); -+ -+ if (vsi->type == I40E_VSI_MAIN) { -+ /* This code helps add more queue to the VSI if we have -+ * more cores than RSS can support, the higher cores will -+ * be served by ATR or other filters. Furthermore, the -+ * non-zero req_queue_pairs says that user requested a new -+ * queue count via ethtool's set_channels, so use this -+ * value for queues distribution across traffic classes -+ */ -+ if (vsi->req_queue_pairs > 0) -+ vsi->num_queue_pairs = vsi->req_queue_pairs; -+ else if (pf->flags & I40E_FLAG_MSIX_ENABLED) -+ vsi->num_queue_pairs = pf->num_lan_msix; -+ } - - /* Number of queues per enabled TC */ -- num_tc_qps = vsi->alloc_queue_pairs; -+ if (vsi->type == I40E_VSI_MAIN || -+ (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs != 0)) -+ num_tc_qps = vsi->num_queue_pairs; -+ else -+ num_tc_qps = vsi->alloc_queue_pairs; -+ - if (enabled_tc && (vsi->back->flags & I40E_FLAG_DCB_ENABLED)) { - /* Find numtc from enabled TC bitmap */ - for (i = 0, numtc = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { -@@ -1881,15 +1902,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, - } - ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); - } -- -- /* Set actual Tx/Rx queue pairs */ -- vsi->num_queue_pairs = offset; -- if ((vsi->type == I40E_VSI_MAIN) && (numtc == 1)) { -- if (vsi->req_queue_pairs > 0) -- vsi->num_queue_pairs = vsi->req_queue_pairs; -- else if (pf->flags & I40E_FLAG_MSIX_ENABLED) -- vsi->num_queue_pairs = pf->num_lan_msix; -- } -+ /* Do not change previously set num_queue_pairs for PFs and VFs*/ -+ if ((vsi->type == I40E_VSI_MAIN && numtc != 1) || -+ (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs == 0) || -+ (vsi->type != I40E_VSI_MAIN && vsi->type != I40E_VSI_SRIOV)) -+ vsi->num_queue_pairs = offset; - - /* Scheduler section valid can only be set for ADD VSI */ - if (is_add) { -@@ -2623,7 +2640,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) - - for (v = 0; v < pf->num_alloc_vsi; v++) { - if (pf->vsi[v] && -- (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) { -+ (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED) && -+ !test_bit(__I40E_VSI_RELEASING, pf->vsi[v]->state)) { - int ret = i40e_sync_vsi_filters(pf->vsi[v]); - - if (ret) { -@@ -5426,6 +5444,58 @@ static void i40e_vsi_update_queue_map(struct i40e_vsi *vsi, - sizeof(vsi->info.tc_mapping)); - } - -+/** -+ * i40e_update_adq_vsi_queues - update queue mapping for ADq VSI -+ * @vsi: the VSI being reconfigured -+ * @vsi_offset: offset from main VF VSI -+ */ -+int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset) -+{ -+ struct i40e_vsi_context ctxt = {}; -+ struct i40e_pf *pf; -+ struct i40e_hw *hw; -+ int ret; -+ -+ if (!vsi) -+ return I40E_ERR_PARAM; -+ pf = vsi->back; -+ hw = &pf->hw; -+ -+ ctxt.seid = vsi->seid; -+ ctxt.pf_num = hw->pf_id; -+ ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id + vsi_offset; -+ ctxt.uplink_seid = vsi->uplink_seid; -+ ctxt.connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL; -+ ctxt.flags = I40E_AQ_VSI_TYPE_VF; -+ ctxt.info = vsi->info; -+ -+ i40e_vsi_setup_queue_map(vsi, &ctxt, vsi->tc_config.enabled_tc, -+ false); -+ if (vsi->reconfig_rss) { -+ vsi->rss_size = min_t(int, pf->alloc_rss_size, -+ vsi->num_queue_pairs); -+ ret = i40e_vsi_config_rss(vsi); -+ if (ret) { -+ dev_info(&pf->pdev->dev, "Failed to reconfig rss for num_queues\n"); -+ return ret; -+ } -+ vsi->reconfig_rss = false; -+ } -+ -+ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); -+ if (ret) { -+ dev_info(&pf->pdev->dev, "Update vsi config failed, err %s aq_err %s\n", -+ i40e_stat_str(hw, ret), -+ i40e_aq_str(hw, hw->aq.asq_last_status)); -+ return ret; -+ } -+ /* update the local VSI info with updated queue map */ -+ i40e_vsi_update_queue_map(vsi, &ctxt); -+ vsi->info.valid_sections = 0; -+ -+ return ret; -+} -+ - /** - * i40e_vsi_config_tc - Configure VSI Tx Scheduler for given TC map - * @vsi: VSI to be configured -@@ -5716,24 +5786,6 @@ static void i40e_remove_queue_channels(struct i40e_vsi *vsi) - INIT_LIST_HEAD(&vsi->ch_list); - } - --/** -- * i40e_is_any_channel - channel exist or not -- * @vsi: ptr to VSI to which channels are associated with -- * -- * Returns true or false if channel(s) exist for associated VSI or not -- **/ --static bool i40e_is_any_channel(struct i40e_vsi *vsi) --{ -- struct i40e_channel *ch, *ch_tmp; -- -- list_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) { -- if (ch->initialized) -- return true; -- } -- -- return false; --} -- - /** - * i40e_get_max_queues_for_channel - * @vsi: ptr to VSI to which channels are associated with -@@ -6240,26 +6292,15 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi, - /* By default we are in VEPA mode, if this is the first VF/VMDq - * VSI to be added switch to VEB mode. - */ -- if ((!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) || -- (!i40e_is_any_channel(vsi))) { -- if (!is_power_of_2(vsi->tc_config.tc_info[0].qcount)) { -- dev_dbg(&pf->pdev->dev, -- "Failed to create channel. Override queues (%u) not power of 2\n", -- vsi->tc_config.tc_info[0].qcount); -- return -EINVAL; -- } - -- if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) { -- pf->flags |= I40E_FLAG_VEB_MODE_ENABLED; -+ if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) { -+ pf->flags |= I40E_FLAG_VEB_MODE_ENABLED; - -- if (vsi->type == I40E_VSI_MAIN) { -- if (pf->flags & I40E_FLAG_TC_MQPRIO) -- i40e_do_reset(pf, I40E_PF_RESET_FLAG, -- true); -- else -- i40e_do_reset_safe(pf, -- I40E_PF_RESET_FLAG); -- } -+ if (vsi->type == I40E_VSI_MAIN) { -+ if (pf->flags & I40E_FLAG_TC_MQPRIO) -+ i40e_do_reset(pf, I40E_PF_RESET_FLAG, true); -+ else -+ i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG); - } - /* now onwards for main VSI, number of queues will be value - * of TC0's queue count -@@ -7912,12 +7953,20 @@ config_tc: - vsi->seid); - need_reset = true; - goto exit; -- } else { -- dev_info(&vsi->back->pdev->dev, -- "Setup channel (id:%u) utilizing num_queues %d\n", -- vsi->seid, vsi->tc_config.tc_info[0].qcount); -+ } else if (enabled_tc && -+ (!is_power_of_2(vsi->tc_config.tc_info[0].qcount))) { -+ netdev_info(netdev, -+ "Failed to create channel. Override queues (%u) not power of 2\n", -+ vsi->tc_config.tc_info[0].qcount); -+ ret = -EINVAL; -+ need_reset = true; -+ goto exit; - } - -+ dev_info(&vsi->back->pdev->dev, -+ "Setup channel (id:%u) utilizing num_queues %d\n", -+ vsi->seid, vsi->tc_config.tc_info[0].qcount); -+ - if (pf->flags & I40E_FLAG_TC_MQPRIO) { - if (vsi->mqprio_qopt.max_rate[0]) { - u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0]; -@@ -8482,9 +8531,8 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi, - err = i40e_add_del_cloud_filter(vsi, filter, true); - - if (err) { -- dev_err(&pf->pdev->dev, -- "Failed to add cloud filter, err %s\n", -- i40e_stat_str(&pf->hw, err)); -+ dev_err(&pf->pdev->dev, "Failed to add cloud filter, err %d\n", -+ err); - goto err; - } - -@@ -13771,7 +13819,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) - dev_info(&pf->pdev->dev, "Can't remove PF VSI\n"); - return -ENODEV; - } -- -+ set_bit(__I40E_VSI_RELEASING, vsi->state); - uplink_seid = vsi->uplink_seid; - if (vsi->type != I40E_VSI_SRIOV) { - if (vsi->netdev_registered) { -diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c -index 472f56b360b8c..2ea4deb8fc44c 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c -@@ -183,17 +183,18 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf) - /***********************misc routines*****************************/ - - /** -- * i40e_vc_disable_vf -+ * i40e_vc_reset_vf - * @vf: pointer to the VF info -- * -- * Disable the VF through a SW reset. -+ * @notify_vf: notify vf about reset or not -+ * Reset VF handler. - **/ --static inline void i40e_vc_disable_vf(struct i40e_vf *vf) -+static void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf) - { - struct i40e_pf *pf = vf->pf; - int i; - -- i40e_vc_notify_vf_reset(vf); -+ if (notify_vf) -+ i40e_vc_notify_vf_reset(vf); - - /* We want to ensure that an actual reset occurs initiated after this - * function was called. However, we do not want to wait forever, so -@@ -211,9 +212,14 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) - usleep_range(10000, 20000); - } - -- dev_warn(&vf->pf->pdev->dev, -- "Failed to initiate reset for VF %d after 200 milliseconds\n", -- vf->vf_id); -+ if (notify_vf) -+ dev_warn(&vf->pf->pdev->dev, -+ "Failed to initiate reset for VF %d after 200 milliseconds\n", -+ vf->vf_id); -+ else -+ dev_dbg(&vf->pf->pdev->dev, -+ "Failed to initiate reset for VF %d after 200 milliseconds\n", -+ vf->vf_id); - } - - /** -@@ -674,14 +680,13 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id, - u16 vsi_queue_id, - struct virtchnl_rxq_info *info) - { -+ u16 pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); - struct i40e_pf *pf = vf->pf; -+ struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx]; - struct i40e_hw *hw = &pf->hw; - struct i40e_hmc_obj_rxq rx_ctx; -- u16 pf_queue_id; - int ret = 0; - -- pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); -- - /* clear the context structure first */ - memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); - -@@ -719,6 +724,10 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id, - } - rx_ctx.rxmax = info->max_pkt_size; - -+ /* if port VLAN is configured increase the max packet size */ -+ if (vsi->info.pvid) -+ rx_ctx.rxmax += VLAN_HLEN; -+ - /* enable 32bytes desc always */ - rx_ctx.dsize = 1; - -@@ -1939,6 +1948,32 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf, - return i40e_vc_send_msg_to_vf(vf, opcode, retval, NULL, 0); - } - -+/** -+ * i40e_sync_vf_state -+ * @vf: pointer to the VF info -+ * @state: VF state -+ * -+ * Called from a VF message to synchronize the service with a potential -+ * VF reset state -+ **/ -+static bool i40e_sync_vf_state(struct i40e_vf *vf, enum i40e_vf_states state) -+{ -+ int i; -+ -+ /* When handling some messages, it needs VF state to be set. -+ * It is possible that this flag is cleared during VF reset, -+ * so there is a need to wait until the end of the reset to -+ * handle the request message correctly. -+ */ -+ for (i = 0; i < I40E_VF_STATE_WAIT_COUNT; i++) { -+ if (test_bit(state, &vf->vf_states)) -+ return true; -+ usleep_range(10000, 20000); -+ } -+ -+ return test_bit(state, &vf->vf_states); -+} -+ - /** - * i40e_vc_get_version_msg - * @vf: pointer to the VF info -@@ -1999,7 +2034,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) - size_t len = 0; - int ret; - -- if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -2105,20 +2140,6 @@ err: - return ret; - } - --/** -- * i40e_vc_reset_vf_msg -- * @vf: pointer to the VF info -- * -- * called from the VF to reset itself, -- * unlike other virtchnl messages, PF driver -- * doesn't send the response back to the VF -- **/ --static void i40e_vc_reset_vf_msg(struct i40e_vf *vf) --{ -- if (test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) -- i40e_reset_vf(vf, false); --} -- - /** - * i40e_vc_config_promiscuous_mode_msg - * @vf: pointer to the VF info -@@ -2136,7 +2157,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) - bool allmulti = false; - bool alluni = false; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err_out; - } -@@ -2217,13 +2238,14 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) - struct virtchnl_vsi_queue_config_info *qci = - (struct virtchnl_vsi_queue_config_info *)msg; - struct virtchnl_queue_pair_info *qpi; -- struct i40e_pf *pf = vf->pf; - u16 vsi_id, vsi_queue_id = 0; -- u16 num_qps_all = 0; -+ struct i40e_pf *pf = vf->pf; - i40e_status aq_ret = 0; - int i, j = 0, idx = 0; -+ struct i40e_vsi *vsi; -+ u16 num_qps_all = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto error_param; - } -@@ -2310,9 +2332,15 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) - pf->vsi[vf->lan_vsi_idx]->num_queue_pairs = - qci->num_queue_pairs; - } else { -- for (i = 0; i < vf->num_tc; i++) -- pf->vsi[vf->ch[i].vsi_idx]->num_queue_pairs = -- vf->ch[i].num_qps; -+ for (i = 0; i < vf->num_tc; i++) { -+ vsi = pf->vsi[vf->ch[i].vsi_idx]; -+ vsi->num_queue_pairs = vf->ch[i].num_qps; -+ -+ if (i40e_update_adq_vsi_queues(vsi, i)) { -+ aq_ret = I40E_ERR_CONFIG; -+ goto error_param; -+ } -+ } - } - - error_param: -@@ -2366,7 +2394,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - int i; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto error_param; - } -@@ -2538,7 +2566,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg) - struct i40e_pf *pf = vf->pf; - i40e_status aq_ret = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto error_param; - } -@@ -2588,7 +2616,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg) - u8 cur_pairs = vf->num_queue_pairs; - struct i40e_pf *pf = vf->pf; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) - return -EINVAL; - - if (req_pairs > I40E_MAX_VF_QUEUES) { -@@ -2607,8 +2635,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg) - } else { - /* successful request */ - vf->num_req_queues = req_pairs; -- i40e_vc_notify_vf_reset(vf); -- i40e_reset_vf(vf, false); -+ i40e_vc_reset_vf(vf, true); - return 0; - } - -@@ -2634,7 +2661,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg) - - memset(&stats, 0, sizeof(struct i40e_eth_stats)); - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto error_param; - } -@@ -2751,7 +2778,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) - i40e_status ret = 0; - int i; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || - !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { - ret = I40E_ERR_PARAM; - goto error_param; -@@ -2823,7 +2850,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) - i40e_status ret = 0; - int i; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || - !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { - ret = I40E_ERR_PARAM; - goto error_param; -@@ -2967,7 +2994,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - int i; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || - !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) { - aq_ret = I40E_ERR_PARAM; - goto error_param; -@@ -3087,9 +3114,9 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg) - struct i40e_vsi *vsi = NULL; - i40e_status aq_ret = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || - !i40e_vc_isvalid_vsi_id(vf, vrk->vsi_id) || -- (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) { -+ vrk->key_len != I40E_HKEY_ARRAY_SIZE) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3118,9 +3145,9 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - u16 i; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || - !i40e_vc_isvalid_vsi_id(vf, vrl->vsi_id) || -- (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) { -+ vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3153,7 +3180,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - int len = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3189,7 +3216,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg) - struct i40e_hw *hw = &pf->hw; - i40e_status aq_ret = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3214,7 +3241,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - struct i40e_vsi *vsi; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3240,7 +3267,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - struct i40e_vsi *vsi; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3467,7 +3494,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - int i, ret; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3598,7 +3625,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - int i, ret; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err_out; - } -@@ -3707,7 +3734,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) - i40e_status aq_ret = 0; - u64 speed = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3796,15 +3823,9 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) - - /* set this flag only after making sure all inputs are sane */ - vf->adq_enabled = true; -- /* num_req_queues is set when user changes number of queues via ethtool -- * and this causes issue for default VSI(which depends on this variable) -- * when ADq is enabled, hence reset it. -- */ -- vf->num_req_queues = 0; - - /* reset the VF in order to allocate resources */ -- i40e_vc_notify_vf_reset(vf); -- i40e_reset_vf(vf, false); -+ i40e_vc_reset_vf(vf, true); - - return I40E_SUCCESS; - -@@ -3824,7 +3845,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) - struct i40e_pf *pf = vf->pf; - i40e_status aq_ret = 0; - -- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { -+ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { - aq_ret = I40E_ERR_PARAM; - goto err; - } -@@ -3844,8 +3865,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) - } - - /* reset the VF in order to allocate resources */ -- i40e_vc_notify_vf_reset(vf); -- i40e_reset_vf(vf, false); -+ i40e_vc_reset_vf(vf, true); - - return I40E_SUCCESS; - -@@ -3907,7 +3927,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, - i40e_vc_notify_vf_link_state(vf); - break; - case VIRTCHNL_OP_RESET_VF: -- i40e_vc_reset_vf_msg(vf); -+ i40e_vc_reset_vf(vf, false); - ret = 0; - break; - case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: -@@ -4161,7 +4181,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) - /* Force the VF interface down so it has to bring up with new MAC - * address - */ -- i40e_vc_disable_vf(vf); -+ i40e_vc_reset_vf(vf, true); - dev_info(&pf->pdev->dev, "Bring down and up the VF interface to make this change effective.\n"); - - error_param: -@@ -4169,34 +4189,6 @@ error_param: - return ret; - } - --/** -- * i40e_vsi_has_vlans - True if VSI has configured VLANs -- * @vsi: pointer to the vsi -- * -- * Check if a VSI has configured any VLANs. False if we have a port VLAN or if -- * we have no configured VLANs. Do not call while holding the -- * mac_filter_hash_lock. -- */ --static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi) --{ -- bool have_vlans; -- -- /* If we have a port VLAN, then the VSI cannot have any VLANs -- * configured, as all MAC/VLAN filters will be assigned to the PVID. -- */ -- if (vsi->info.pvid) -- return false; -- -- /* Since we don't have a PVID, we know that if the device is in VLAN -- * mode it must be because of a VLAN filter configured on this VSI. -- */ -- spin_lock_bh(&vsi->mac_filter_hash_lock); -- have_vlans = i40e_is_vsi_in_vlan(vsi); -- spin_unlock_bh(&vsi->mac_filter_hash_lock); -- -- return have_vlans; --} -- - /** - * i40e_ndo_set_vf_port_vlan - * @netdev: network interface device structure -@@ -4253,19 +4245,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, - /* duplicate request, so just return success */ - goto error_pvid; - -- if (i40e_vsi_has_vlans(vsi)) { -- dev_err(&pf->pdev->dev, -- "VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n", -- vf_id); -- /* Administrator Error - knock the VF offline until he does -- * the right thing by reconfiguring his network correctly -- * and then reloading the VF driver. -- */ -- i40e_vc_disable_vf(vf); -- /* During reset the VF got a new VSI, so refresh the pointer. */ -- vsi = pf->vsi[vf->lan_vsi_idx]; -- } -- -+ i40e_vc_reset_vf(vf, true); -+ /* During reset the VF got a new VSI, so refresh a pointer. */ -+ vsi = pf->vsi[vf->lan_vsi_idx]; - /* Locked once because multiple functions below iterate list */ - spin_lock_bh(&vsi->mac_filter_hash_lock); - -@@ -4641,7 +4623,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting) - goto out; - - vf->trusted = setting; -- i40e_vc_disable_vf(vf); -+ i40e_vc_reset_vf(vf, true); - dev_info(&pf->pdev->dev, "VF %u is now %strusted\n", - vf_id, setting ? "" : "un"); - -diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h -index 091e32c1bb46f..49575a640a84c 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h -+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h -@@ -18,6 +18,8 @@ - - #define I40E_MAX_VF_PROMISC_FLAGS 3 - -+#define I40E_VF_STATE_WAIT_COUNT 20 -+ - /* Various queue ctrls */ - enum i40e_queue_ctrl { - I40E_QUEUE_CTRL_UNKNOWN = 0, -diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h -index 68c80f04113c8..0ae6da2992d01 100644 ---- a/drivers/net/ethernet/intel/iavf/iavf.h -+++ b/drivers/net/ethernet/intel/iavf/iavf.h -@@ -39,6 +39,7 @@ - #include "iavf_txrx.h" - #include "iavf_fdir.h" - #include "iavf_adv_rss.h" -+#include <linux/bitmap.h> - - #define DEFAULT_DEBUG_LEVEL_SHIFT 3 - #define PFX "iavf: " -@@ -304,6 +305,7 @@ struct iavf_adapter { - #define IAVF_FLAG_AQ_DEL_FDIR_FILTER BIT(26) - #define IAVF_FLAG_AQ_ADD_ADV_RSS_CFG BIT(27) - #define IAVF_FLAG_AQ_DEL_ADV_RSS_CFG BIT(28) -+#define IAVF_FLAG_AQ_REQUEST_STATS BIT(29) - - /* OS defined structs */ - struct net_device *netdev; -@@ -397,6 +399,7 @@ int iavf_up(struct iavf_adapter *adapter); - void iavf_down(struct iavf_adapter *adapter); - int iavf_process_config(struct iavf_adapter *adapter); - void iavf_schedule_reset(struct iavf_adapter *adapter); -+void iavf_schedule_request_stats(struct iavf_adapter *adapter); - void iavf_reset(struct iavf_adapter *adapter); - void iavf_set_ethtool_ops(struct net_device *netdev); - void iavf_update_stats(struct iavf_adapter *adapter); -@@ -454,4 +457,5 @@ void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter); - void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter); - struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, - const u8 *macaddr); -+int iavf_lock_timeout(struct mutex *lock, unsigned int msecs); - #endif /* _IAVF_H_ */ -diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c -index 5a359a0a20ecc..461f5237a2f88 100644 ---- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c -+++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c -@@ -354,6 +354,9 @@ static void iavf_get_ethtool_stats(struct net_device *netdev, - struct iavf_adapter *adapter = netdev_priv(netdev); - unsigned int i; - -+ /* Explicitly request stats refresh */ -+ iavf_schedule_request_stats(adapter); -+ - iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats); - - rcu_read_lock(); -@@ -612,23 +615,44 @@ static int iavf_set_ringparam(struct net_device *netdev, - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - -- new_tx_count = clamp_t(u32, ring->tx_pending, -- IAVF_MIN_TXD, -- IAVF_MAX_TXD); -- new_tx_count = ALIGN(new_tx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); -+ if (ring->tx_pending > IAVF_MAX_TXD || -+ ring->tx_pending < IAVF_MIN_TXD || -+ ring->rx_pending > IAVF_MAX_RXD || -+ ring->rx_pending < IAVF_MIN_RXD) { -+ netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", -+ ring->tx_pending, ring->rx_pending, IAVF_MIN_TXD, -+ IAVF_MAX_RXD, IAVF_REQ_DESCRIPTOR_MULTIPLE); -+ return -EINVAL; -+ } -+ -+ new_tx_count = ALIGN(ring->tx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); -+ if (new_tx_count != ring->tx_pending) -+ netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n", -+ new_tx_count); - -- new_rx_count = clamp_t(u32, ring->rx_pending, -- IAVF_MIN_RXD, -- IAVF_MAX_RXD); -- new_rx_count = ALIGN(new_rx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); -+ new_rx_count = ALIGN(ring->rx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); -+ if (new_rx_count != ring->rx_pending) -+ netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n", -+ new_rx_count); - - /* if nothing to do return success */ - if ((new_tx_count == adapter->tx_desc_count) && -- (new_rx_count == adapter->rx_desc_count)) -+ (new_rx_count == adapter->rx_desc_count)) { -+ netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); - return 0; -+ } -+ -+ if (new_tx_count != adapter->tx_desc_count) { -+ netdev_dbg(netdev, "Changing Tx descriptor count from %d to %d\n", -+ adapter->tx_desc_count, new_tx_count); -+ adapter->tx_desc_count = new_tx_count; -+ } - -- adapter->tx_desc_count = new_tx_count; -- adapter->rx_desc_count = new_rx_count; -+ if (new_rx_count != adapter->rx_desc_count) { -+ netdev_dbg(netdev, "Changing Rx descriptor count from %d to %d\n", -+ adapter->rx_desc_count, new_rx_count); -+ adapter->rx_desc_count = new_rx_count; -+ } - - if (netif_running(netdev)) { - adapter->flags |= IAVF_FLAG_RESET_NEEDED; -@@ -723,12 +747,31 @@ static int iavf_get_per_queue_coalesce(struct net_device *netdev, u32 queue, - * - * Change the ITR settings for a specific queue. - **/ --static void iavf_set_itr_per_queue(struct iavf_adapter *adapter, -- struct ethtool_coalesce *ec, int queue) -+static int iavf_set_itr_per_queue(struct iavf_adapter *adapter, -+ struct ethtool_coalesce *ec, int queue) - { - struct iavf_ring *rx_ring = &adapter->rx_rings[queue]; - struct iavf_ring *tx_ring = &adapter->tx_rings[queue]; - struct iavf_q_vector *q_vector; -+ u16 itr_setting; -+ -+ itr_setting = rx_ring->itr_setting & ~IAVF_ITR_DYNAMIC; -+ -+ if (ec->rx_coalesce_usecs != itr_setting && -+ ec->use_adaptive_rx_coalesce) { -+ netif_info(adapter, drv, adapter->netdev, -+ "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n"); -+ return -EINVAL; -+ } -+ -+ itr_setting = tx_ring->itr_setting & ~IAVF_ITR_DYNAMIC; -+ -+ if (ec->tx_coalesce_usecs != itr_setting && -+ ec->use_adaptive_tx_coalesce) { -+ netif_info(adapter, drv, adapter->netdev, -+ "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n"); -+ return -EINVAL; -+ } - - rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); - tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); -@@ -751,6 +794,7 @@ static void iavf_set_itr_per_queue(struct iavf_adapter *adapter, - * the Tx and Rx ITR values based on the values we have entered - * into the q_vector, no need to write the values now. - */ -+ return 0; - } - - /** -@@ -792,9 +836,11 @@ static int __iavf_set_coalesce(struct net_device *netdev, - */ - if (queue < 0) { - for (i = 0; i < adapter->num_active_queues; i++) -- iavf_set_itr_per_queue(adapter, ec, i); -+ if (iavf_set_itr_per_queue(adapter, ec, i)) -+ return -EINVAL; - } else if (queue < adapter->num_active_queues) { -- iavf_set_itr_per_queue(adapter, ec, queue); -+ if (iavf_set_itr_per_queue(adapter, ec, queue)) -+ return -EINVAL; - } else { - netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n", - adapter->num_active_queues - 1); -@@ -1776,6 +1822,7 @@ static int iavf_set_channels(struct net_device *netdev, - { - struct iavf_adapter *adapter = netdev_priv(netdev); - u32 num_req = ch->combined_count; -+ int i; - - if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) && - adapter->num_tc) { -@@ -1786,7 +1833,7 @@ static int iavf_set_channels(struct net_device *netdev, - /* All of these should have already been checked by ethtool before this - * even gets to us, but just to be sure. - */ -- if (num_req > adapter->vsi_res->num_queue_pairs) -+ if (num_req == 0 || num_req > adapter->vsi_res->num_queue_pairs) - return -EINVAL; - - if (num_req == adapter->num_active_queues) -@@ -1798,6 +1845,20 @@ static int iavf_set_channels(struct net_device *netdev, - adapter->num_req_queues = num_req; - adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED; - iavf_schedule_reset(adapter); -+ -+ /* wait for the reset is done */ -+ for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) { -+ msleep(IAVF_RESET_WAIT_MS); -+ if (adapter->flags & IAVF_FLAG_RESET_PENDING) -+ continue; -+ break; -+ } -+ if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { -+ adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED; -+ adapter->num_active_queues = num_req; -+ return -EOPNOTSUPP; -+ } -+ - return 0; - } - -@@ -1844,14 +1905,13 @@ static int iavf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - - if (hfunc) - *hfunc = ETH_RSS_HASH_TOP; -- if (!indir) -- return 0; -- -- memcpy(key, adapter->rss_key, adapter->rss_key_size); -+ if (key) -+ memcpy(key, adapter->rss_key, adapter->rss_key_size); - -- /* Each 32 bits pointed by 'indir' is stored with a lut entry */ -- for (i = 0; i < adapter->rss_lut_size; i++) -- indir[i] = (u32)adapter->rss_lut[i]; -+ if (indir) -+ /* Each 32 bits pointed by 'indir' is stored with a lut entry */ -+ for (i = 0; i < adapter->rss_lut_size; i++) -+ indir[i] = (u32)adapter->rss_lut[i]; - - return 0; - } -diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c -index cada4e0e40b48..4f3b025daa14f 100644 ---- a/drivers/net/ethernet/intel/iavf/iavf_main.c -+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c -@@ -138,7 +138,7 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw, - * - * Returns 0 on success, negative on failure - **/ --static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) -+int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) - { - unsigned int wait, delay = 10; - -@@ -165,6 +165,19 @@ void iavf_schedule_reset(struct iavf_adapter *adapter) - } - } - -+/** -+ * iavf_schedule_request_stats - Set the flags and schedule statistics request -+ * @adapter: board private structure -+ * -+ * Sets IAVF_FLAG_AQ_REQUEST_STATS flag so iavf_watchdog_task() will explicitly -+ * request and refresh ethtool stats -+ **/ -+void iavf_schedule_request_stats(struct iavf_adapter *adapter) -+{ -+ adapter->aq_required |= IAVF_FLAG_AQ_REQUEST_STATS; -+ mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); -+} -+ - /** - * iavf_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure -@@ -687,6 +700,21 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, u16 vlan) - spin_unlock_bh(&adapter->mac_vlan_list_lock); - } - -+/** -+ * iavf_restore_filters -+ * @adapter: board private structure -+ * -+ * Restore existing non MAC filters when VF netdev comes back up -+ **/ -+static void iavf_restore_filters(struct iavf_adapter *adapter) -+{ -+ u16 vid; -+ -+ /* re-add all VLAN filters */ -+ for_each_set_bit(vid, adapter->vsi.active_vlans, VLAN_N_VID) -+ iavf_add_vlan(adapter, vid); -+} -+ - /** - * iavf_vlan_rx_add_vid - Add a VLAN filter to a device - * @netdev: network device struct -@@ -700,8 +728,11 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev, - - if (!VLAN_ALLOWED(adapter)) - return -EIO; -+ - if (iavf_add_vlan(adapter, vid) == NULL) - return -ENOMEM; -+ -+ set_bit(vid, adapter->vsi.active_vlans); - return 0; - } - -@@ -716,11 +747,10 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev, - { - struct iavf_adapter *adapter = netdev_priv(netdev); - -- if (VLAN_ALLOWED(adapter)) { -- iavf_del_vlan(adapter, vid); -- return 0; -- } -- return -EIO; -+ iavf_del_vlan(adapter, vid); -+ clear_bit(vid, adapter->vsi.active_vlans); -+ -+ return 0; - } - - /** -@@ -1630,8 +1660,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) - iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC); - return 0; - } -- -- if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) && -+ if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) || - (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) { - iavf_set_promiscuous(adapter, 0); - return 0; -@@ -1679,6 +1708,11 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) - iavf_del_adv_rss_cfg(adapter); - return 0; - } -+ if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_STATS) { -+ iavf_request_stats(adapter); -+ return 0; -+ } -+ - return -EAGAIN; - } - -@@ -2074,8 +2108,8 @@ static void iavf_disable_vf(struct iavf_adapter *adapter) - - iavf_free_misc_irq(adapter); - iavf_reset_interrupt_capability(adapter); -- iavf_free_queues(adapter); - iavf_free_q_vectors(adapter); -+ iavf_free_queues(adapter); - memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE); - iavf_shutdown_adminq(&adapter->hw); - adapter->netdev->flags &= ~IFF_UP; -@@ -2103,7 +2137,6 @@ static void iavf_reset_task(struct work_struct *work) - struct net_device *netdev = adapter->netdev; - struct iavf_hw *hw = &adapter->hw; - struct iavf_mac_filter *f, *ftmp; -- struct iavf_vlan_filter *vlf; - struct iavf_cloud_filter *cf; - u32 reg_val; - int i = 0, err; -@@ -2166,6 +2199,7 @@ static void iavf_reset_task(struct work_struct *work) - } - - pci_set_master(adapter->pdev); -+ pci_restore_msi_state(adapter->pdev); - - if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { - dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", -@@ -2243,11 +2277,6 @@ continue_reset: - list_for_each_entry(f, &adapter->mac_filter_list, list) { - f->add = true; - } -- /* re-add all VLAN filters */ -- list_for_each_entry(vlf, &adapter->vlan_filter_list, list) { -- vlf->add = true; -- } -- - spin_unlock_bh(&adapter->mac_vlan_list_lock); - - /* check if TCs are running and re-add all cloud filters */ -@@ -2261,7 +2290,6 @@ continue_reset: - spin_unlock_bh(&adapter->cloud_filter_list_lock); - - adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; -- adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER; - adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER; - iavf_misc_irq_enable(adapter); - -@@ -2356,7 +2384,7 @@ static void iavf_adminq_task(struct work_struct *work) - - /* check for error indications */ - val = rd32(hw, hw->aq.arq.len); -- if (val == 0xdeadbeef) /* indicates device in reset */ -+ if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */ - goto freedom; - oldval = val; - if (val & IAVF_VF_ARQLEN1_ARQVFE_MASK) { -@@ -3041,8 +3069,10 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter, - return -ENOMEM; - - while (!mutex_trylock(&adapter->crit_lock)) { -- if (--count == 0) -- goto err; -+ if (--count == 0) { -+ kfree(filter); -+ return err; -+ } - udelay(1); - } - -@@ -3053,11 +3083,11 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter, - /* start out with flow type and eth type IPv4 to begin with */ - filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW; - err = iavf_parse_cls_flower(adapter, cls_flower, filter); -- if (err < 0) -+ if (err) - goto err; - - err = iavf_handle_tclass(adapter, tc, filter); -- if (err < 0) -+ if (err) - goto err; - - /* add filter to the list */ -@@ -3247,6 +3277,9 @@ static int iavf_open(struct net_device *netdev) - - spin_unlock_bh(&adapter->mac_vlan_list_lock); - -+ /* Restore VLAN filters that were removed with IFF_DOWN */ -+ iavf_restore_filters(adapter); -+ - iavf_configure(adapter); - - iavf_up_complete(adapter); -@@ -3354,11 +3387,16 @@ static int iavf_set_features(struct net_device *netdev, - { - struct iavf_adapter *adapter = netdev_priv(netdev); - -- /* Don't allow changing VLAN_RX flag when adapter is not capable -- * of VLAN offload -+ /* Don't allow enabling VLAN features when adapter is not capable -+ * of VLAN offload/filtering - */ - if (!VLAN_ALLOWED(adapter)) { -- if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) -+ netdev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_RX | -+ NETIF_F_HW_VLAN_CTAG_TX | -+ NETIF_F_HW_VLAN_CTAG_FILTER); -+ if (features & (NETIF_F_HW_VLAN_CTAG_RX | -+ NETIF_F_HW_VLAN_CTAG_TX | -+ NETIF_F_HW_VLAN_CTAG_FILTER)) - return -EINVAL; - } else if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) { - if (features & NETIF_F_HW_VLAN_CTAG_RX) -@@ -3442,7 +3480,8 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev, - { - struct iavf_adapter *adapter = netdev_priv(netdev); - -- if (!(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) -+ if (adapter->vf_res && -+ !(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) - features &= ~(NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_FILTER); -diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c -index 3c735968e1b85..08302ab35d687 100644 ---- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c -+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c -@@ -607,7 +607,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter) - if (f->add) - count++; - } -- if (!count) { -+ if (!count || !VLAN_ALLOWED(adapter)) { - adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_VLAN_FILTER; - spin_unlock_bh(&adapter->mac_vlan_list_lock); - return; -@@ -673,9 +673,19 @@ void iavf_del_vlans(struct iavf_adapter *adapter) - - spin_lock_bh(&adapter->mac_vlan_list_lock); - -- list_for_each_entry(f, &adapter->vlan_filter_list, list) { -- if (f->remove) -+ list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { -+ /* since VLAN capabilities are not allowed, we dont want to send -+ * a VLAN delete request because it will most likely fail and -+ * create unnecessary errors/noise, so just free the VLAN -+ * filters marked for removal to enable bailing out before -+ * sending a virtchnl message -+ */ -+ if (f->remove && !VLAN_ALLOWED(adapter)) { -+ list_del(&f->list); -+ kfree(f); -+ } else if (f->remove) { - count++; -+ } - } - if (!count) { - adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_VLAN_FILTER; -@@ -784,6 +794,8 @@ void iavf_request_stats(struct iavf_adapter *adapter) - /* no error message, this isn't crucial */ - return; - } -+ -+ adapter->aq_required &= ~IAVF_FLAG_AQ_REQUEST_STATS; - adapter->current_op = VIRTCHNL_OP_GET_STATS; - vqs.vsi_id = adapter->vsi_res->vsi_id; - /* queue maps are ignored for this message - only the vsi is used */ -@@ -1722,8 +1734,37 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, - } - spin_lock_bh(&adapter->mac_vlan_list_lock); - iavf_add_filter(adapter, adapter->hw.mac.addr); -+ -+ if (VLAN_ALLOWED(adapter)) { -+ if (!list_empty(&adapter->vlan_filter_list)) { -+ struct iavf_vlan_filter *vlf; -+ -+ /* re-add all VLAN filters over virtchnl */ -+ list_for_each_entry(vlf, -+ &adapter->vlan_filter_list, -+ list) -+ vlf->add = true; -+ -+ adapter->aq_required |= -+ IAVF_FLAG_AQ_ADD_VLAN_FILTER; -+ } -+ } -+ - spin_unlock_bh(&adapter->mac_vlan_list_lock); - iavf_process_config(adapter); -+ -+ /* unlock crit_lock before acquiring rtnl_lock as other -+ * processes holding rtnl_lock could be waiting for the same -+ * crit_lock -+ */ -+ mutex_unlock(&adapter->crit_lock); -+ rtnl_lock(); -+ netdev_update_features(adapter->netdev); -+ rtnl_unlock(); -+ if (iavf_lock_timeout(&adapter->crit_lock, 10000)) -+ dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", -+ __FUNCTION__); -+ - } - break; - case VIRTCHNL_OP_ENABLE_QUEUES: -diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h -index 3c4f08d20414e..fba8f021c397d 100644 ---- a/drivers/net/ethernet/intel/ice/ice.h -+++ b/drivers/net/ethernet/intel/ice/ice.h -@@ -139,13 +139,10 @@ - #define ice_for_each_q_vector(vsi, i) \ - for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++) - --#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \ -- ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX) -+#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_UCAST_RX) - - #define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \ -- ICE_PROMISC_MCAST_TX | \ - ICE_PROMISC_UCAST_RX | \ -- ICE_PROMISC_MCAST_RX | \ - ICE_PROMISC_VLAN_TX | \ - ICE_PROMISC_VLAN_RX) - -@@ -306,10 +303,6 @@ struct ice_vsi { - spinlock_t arfs_lock; /* protects aRFS hash table and filter state */ - atomic_t *arfs_last_fltr_id; - -- /* devlink port data */ -- struct devlink_port devlink_port; -- bool devlink_port_registered; -- - u16 max_frame; - u16 rx_buf_len; - -@@ -421,6 +414,9 @@ struct ice_pf { - struct devlink_region *nvm_region; - struct devlink_region *devcaps_region; - -+ /* devlink port data */ -+ struct devlink_port devlink_port; -+ - /* OS reserved IRQ details */ - struct msix_entry *msix_entries; - struct ice_res_tracker *irq_tracker; -diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c -index c36057efc7ae3..f74610442bda7 100644 ---- a/drivers/net/ethernet/intel/ice/ice_base.c -+++ b/drivers/net/ethernet/intel/ice/ice_base.c -@@ -909,7 +909,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, - } else if (status == ICE_ERR_DOES_NOT_EXIST) { - dev_dbg(ice_pf_to_dev(vsi->back), "LAN Tx queues do not exist, nothing to disable\n"); - } else if (status) { -- dev_err(ice_pf_to_dev(vsi->back), "Failed to disable LAN Tx queues, error: %s\n", -+ dev_dbg(ice_pf_to_dev(vsi->back), "Failed to disable LAN Tx queues, error: %s\n", - ice_stat_str(status)); - return -ENODEV; - } -diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c -index da7288bdc9a3f..2ec5d5cb72803 100644 ---- a/drivers/net/ethernet/intel/ice/ice_devlink.c -+++ b/drivers/net/ethernet/intel/ice/ice_devlink.c -@@ -526,60 +526,115 @@ void ice_devlink_unregister(struct ice_pf *pf) - } - - /** -- * ice_devlink_create_port - Create a devlink port for this VSI -- * @vsi: the VSI to create a port for -+ * ice_devlink_create_pf_port - Create a devlink port for this PF -+ * @pf: the PF to create a devlink port for - * -- * Create and register a devlink_port for this VSI. -+ * Create and register a devlink_port for this PF. - * - * Return: zero on success or an error code on failure. - */ --int ice_devlink_create_port(struct ice_vsi *vsi) -+int ice_devlink_create_pf_port(struct ice_pf *pf) - { - struct devlink_port_attrs attrs = {}; -- struct ice_port_info *pi; -+ struct devlink_port *devlink_port; - struct devlink *devlink; -+ struct ice_vsi *vsi; - struct device *dev; -- struct ice_pf *pf; - int err; - -- /* Currently we only create devlink_port instances for PF VSIs */ -- if (vsi->type != ICE_VSI_PF) -- return -EINVAL; -- -- pf = vsi->back; -- devlink = priv_to_devlink(pf); - dev = ice_pf_to_dev(pf); -- pi = pf->hw.port_info; -+ -+ devlink_port = &pf->devlink_port; -+ -+ vsi = ice_get_main_vsi(pf); -+ if (!vsi) -+ return -EIO; - - attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; -- attrs.phys.port_number = pi->lport; -- devlink_port_attrs_set(&vsi->devlink_port, &attrs); -- err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx); -+ attrs.phys.port_number = pf->hw.bus.func; -+ devlink_port_attrs_set(devlink_port, &attrs); -+ devlink = priv_to_devlink(pf); -+ -+ err = devlink_port_register(devlink, devlink_port, vsi->idx); - if (err) { -- dev_err(dev, "devlink_port_register failed: %d\n", err); -+ dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", -+ pf->hw.pf_id, err); - return err; - } - -- vsi->devlink_port_registered = true; -+ return 0; -+} -+ -+/** -+ * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF -+ * @pf: the PF to cleanup -+ * -+ * Unregisters the devlink_port structure associated with this PF. -+ */ -+void ice_devlink_destroy_pf_port(struct ice_pf *pf) -+{ -+ struct devlink_port *devlink_port; -+ -+ devlink_port = &pf->devlink_port; -+ -+ devlink_port_type_clear(devlink_port); -+ devlink_port_unregister(devlink_port); -+} -+ -+/** -+ * ice_devlink_create_vf_port - Create a devlink port for this VF -+ * @vf: the VF to create a port for -+ * -+ * Create and register a devlink_port for this VF. -+ * -+ * Return: zero on success or an error code on failure. -+ */ -+int ice_devlink_create_vf_port(struct ice_vf *vf) -+{ -+ struct devlink_port_attrs attrs = {}; -+ struct devlink_port *devlink_port; -+ struct devlink *devlink; -+ struct ice_vsi *vsi; -+ struct device *dev; -+ struct ice_pf *pf; -+ int err; -+ -+ pf = vf->pf; -+ dev = ice_pf_to_dev(pf); -+ vsi = ice_get_vf_vsi(vf); -+ devlink_port = &vf->devlink_port; -+ -+ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; -+ attrs.pci_vf.pf = pf->hw.bus.func; -+ attrs.pci_vf.vf = vf->vf_id; -+ -+ devlink_port_attrs_set(devlink_port, &attrs); -+ devlink = priv_to_devlink(pf); -+ -+ err = devlink_port_register(devlink, devlink_port, vsi->idx); -+ if (err) { -+ dev_err(dev, "Failed to create devlink port for VF %d, error %d\n", -+ vf->vf_id, err); -+ return err; -+ } - - return 0; - } - - /** -- * ice_devlink_destroy_port - Destroy the devlink_port for this VSI -- * @vsi: the VSI to cleanup -+ * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF -+ * @vf: the VF to cleanup - * -- * Unregisters the devlink_port structure associated with this VSI. -+ * Unregisters the devlink_port structure associated with this VF. - */ --void ice_devlink_destroy_port(struct ice_vsi *vsi) -+void ice_devlink_destroy_vf_port(struct ice_vf *vf) - { -- if (!vsi->devlink_port_registered) -- return; -+ struct devlink_port *devlink_port; - -- devlink_port_type_clear(&vsi->devlink_port); -- devlink_port_unregister(&vsi->devlink_port); -+ devlink_port = &vf->devlink_port; - -- vsi->devlink_port_registered = false; -+ devlink_port_type_clear(devlink_port); -+ devlink_port_unregister(devlink_port); - } - - /** -diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.h b/drivers/net/ethernet/intel/ice/ice_devlink.h -index e07e74426bde8..e30284ccbed4c 100644 ---- a/drivers/net/ethernet/intel/ice/ice_devlink.h -+++ b/drivers/net/ethernet/intel/ice/ice_devlink.h -@@ -8,8 +8,10 @@ struct ice_pf *ice_allocate_pf(struct device *dev); - - int ice_devlink_register(struct ice_pf *pf); - void ice_devlink_unregister(struct ice_pf *pf); --int ice_devlink_create_port(struct ice_vsi *vsi); --void ice_devlink_destroy_port(struct ice_vsi *vsi); -+int ice_devlink_create_pf_port(struct ice_pf *pf); -+void ice_devlink_destroy_pf_port(struct ice_pf *pf); -+int ice_devlink_create_vf_port(struct ice_vf *vf); -+void ice_devlink_destroy_vf_port(struct ice_vf *vf); - - void ice_devlink_init_regions(struct ice_pf *pf); - void ice_devlink_destroy_regions(struct ice_pf *pf); -diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c -index b718e196af2a4..62bf879dc6232 100644 ---- a/drivers/net/ethernet/intel/ice/ice_lib.c -+++ b/drivers/net/ethernet/intel/ice/ice_lib.c -@@ -83,8 +83,13 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) - if (!vsi->rx_rings) - goto err_rings; - -- /* XDP will have vsi->alloc_txq Tx queues as well, so double the size */ -- vsi->txq_map = devm_kcalloc(dev, (2 * vsi->alloc_txq), -+ /* txq_map needs to have enough space to track both Tx (stack) rings -+ * and XDP rings; at this point vsi->num_xdp_txq might not be set, -+ * so use num_possible_cpus() as we want to always provide XDP ring -+ * per CPU, regardless of queue count settings from user that might -+ * have come from ethtool's set_channels() callback; -+ */ -+ vsi->txq_map = devm_kcalloc(dev, (vsi->alloc_txq + num_possible_cpus()), - sizeof(*vsi->txq_map), GFP_KERNEL); - - if (!vsi->txq_map) -@@ -2860,7 +2865,8 @@ int ice_vsi_release(struct ice_vsi *vsi) - clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state); - } - -- ice_devlink_destroy_port(vsi); -+ if (vsi->type == ICE_VSI_PF) -+ ice_devlink_destroy_pf_port(pf); - - if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) - ice_rss_clean(vsi); -diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c -index 06fa93e597fbc..819c32a721e84 100644 ---- a/drivers/net/ethernet/intel/ice/ice_main.c -+++ b/drivers/net/ethernet/intel/ice/ice_main.c -@@ -2497,7 +2497,18 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog) - ice_stat_str(status)); - goto clear_xdp_rings; - } -- ice_vsi_assign_bpf_prog(vsi, prog); -+ -+ /* assign the prog only when it's not already present on VSI; -+ * this flow is a subject of both ethtool -L and ndo_bpf flows; -+ * VSI rebuild that happens under ethtool -L can expose us to -+ * the bpf_prog refcount issues as we would be swapping same -+ * bpf_prog pointers from vsi->xdp_prog and calling bpf_prog_put -+ * on it as it would be treated as an 'old_prog'; for ndo_bpf -+ * this is not harmful as dev_xdp_install bumps the refcount -+ * before calling the op exposed by the driver; -+ */ -+ if (!ice_is_xdp_ena_vsi(vsi)) -+ ice_vsi_assign_bpf_prog(vsi, prog); - - return 0; - clear_xdp_rings: -@@ -2643,6 +2654,11 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog, - if (xdp_ring_err) - NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed"); - } else { -+ /* safe to call even when prog == vsi->xdp_prog as -+ * dev_xdp_install in net/core/dev.c incremented prog's -+ * refcount so corresponding bpf_prog_put won't cause -+ * underflow -+ */ - ice_vsi_assign_bpf_prog(vsi, prog); - } - -@@ -4170,11 +4186,11 @@ static int ice_register_netdev(struct ice_pf *pf) - set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state); - netif_carrier_off(vsi->netdev); - netif_tx_stop_all_queues(vsi->netdev); -- err = ice_devlink_create_port(vsi); -+ err = ice_devlink_create_pf_port(pf); - if (err) - goto err_devlink_create; - -- devlink_port_type_eth_set(&vsi->devlink_port, vsi->netdev); -+ devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev); - - return 0; - err_devlink_create: -@@ -4600,9 +4616,6 @@ static void ice_remove(struct pci_dev *pdev) - struct ice_pf *pf = pci_get_drvdata(pdev); - int i; - -- if (!pf) -- return; -- - for (i = 0; i < ICE_MAX_RESET_WAIT; i++) { - if (!ice_is_reset_in_progress(pf->state)) - break; -@@ -5608,6 +5621,9 @@ static int ice_up_complete(struct ice_vsi *vsi) - netif_carrier_on(vsi->netdev); - } - -+ /* clear this now, and the first stats read will be used as baseline */ -+ vsi->stat_offsets_loaded = false; -+ - ice_service_task_schedule(pf); - - return 0; -diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c -index d1ef3d48a4b03..ac27a4fe8b94c 100644 ---- a/drivers/net/ethernet/intel/ice/ice_ptp.c -+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c -@@ -459,7 +459,7 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm) - scaled_ppm = -scaled_ppm; - } - -- while ((u64)scaled_ppm > div_u64(U64_MAX, incval)) { -+ while ((u64)scaled_ppm > div64_u64(U64_MAX, incval)) { - /* handle overflow by scaling down the scaled_ppm and - * the divisor, losing some precision - */ -@@ -1182,19 +1182,16 @@ static void ice_ptp_tx_tstamp_work(struct kthread_work *work) - if (err) - continue; - -- /* Check if the timestamp is valid */ -- if (!(raw_tstamp & ICE_PTP_TS_VALID)) -+ /* Check if the timestamp is invalid or stale */ -+ if (!(raw_tstamp & ICE_PTP_TS_VALID) || -+ raw_tstamp == tx->tstamps[idx].cached_tstamp) - continue; - -- /* clear the timestamp register, so that it won't show valid -- * again when re-used. -- */ -- ice_clear_phy_tstamp(hw, tx->quad, phy_idx); -- - /* The timestamp is valid, so we'll go ahead and clear this - * index and then send the timestamp up to the stack. - */ - spin_lock(&tx->lock); -+ tx->tstamps[idx].cached_tstamp = raw_tstamp; - clear_bit(idx, tx->in_use); - skb = tx->tstamps[idx].skb; - tx->tstamps[idx].skb = NULL; -diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h -index e1c787bd5b967..8cdd6f7046b73 100644 ---- a/drivers/net/ethernet/intel/ice/ice_ptp.h -+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h -@@ -46,15 +46,21 @@ struct ice_perout_channel { - * struct ice_tx_tstamp - Tracking for a single Tx timestamp - * @skb: pointer to the SKB for this timestamp request - * @start: jiffies when the timestamp was first requested -+ * @cached_tstamp: last read timestamp - * - * This structure tracks a single timestamp request. The SKB pointer is - * provided when initiating a request. The start time is used to ensure that - * we discard old requests that were not fulfilled within a 2 second time - * window. -+ * Timestamp values in the PHY are read only and do not get cleared except at -+ * hardware reset or when a new timestamp value is captured. The cached_tstamp -+ * field is used to detect the case where a new timestamp has not yet been -+ * captured, ensuring that we avoid sending stale timestamp data to the stack. - */ - struct ice_tx_tstamp { - struct sk_buff *skb; - unsigned long start; -+ u64 cached_tstamp; - }; - - /** -diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c -index e93430ab37f1e..a78e8f00cf71b 100644 ---- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c -+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c -@@ -251,7 +251,7 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list_comms[] = { - * ice_get_vf_vsi - get VF's VSI based on the stored index - * @vf: VF used to get VSI - */ --static struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) -+struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) - { - return vf->pf->vsi[vf->lan_vsi_idx]; - } -@@ -634,8 +634,7 @@ void ice_free_vfs(struct ice_pf *pf) - - /* Avoid wait time by stopping all VFs at the same time */ - ice_for_each_vf(pf, i) -- if (test_bit(ICE_VF_STATE_QS_ENA, pf->vf[i].vf_states)) -- ice_dis_vf_qs(&pf->vf[i]); -+ ice_dis_vf_qs(&pf->vf[i]); - - tmp = pf->num_alloc_vfs; - pf->num_qps_per_vf = 0; -@@ -1570,6 +1569,7 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr) - ice_vc_set_default_allowlist(vf); - - ice_vf_fdir_exit(vf); -+ ice_vf_fdir_init(vf); - /* clean VF control VSI when resetting VFs since it should be - * setup only when VF creates its first FDIR rule. - */ -@@ -1645,8 +1645,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) - - vsi = ice_get_vf_vsi(vf); - -- if (test_bit(ICE_VF_STATE_QS_ENA, vf->vf_states)) -- ice_dis_vf_qs(vf); -+ ice_dis_vf_qs(vf); - - /* Call Disable LAN Tx queue AQ whether or not queues are - * enabled. This is needed for successful completion of VFR. -@@ -1697,6 +1696,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) - } - - ice_vf_fdir_exit(vf); -+ ice_vf_fdir_init(vf); - /* clean VF control VSI when resetting VF since it should be setup - * only when VF creates its first FDIR rule. - */ -@@ -2954,6 +2954,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf) - static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) - { - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; -+ enum ice_status mcast_status = 0, ucast_status = 0; - bool rm_promisc, alluni = false, allmulti = false; - struct virtchnl_promisc_info *info = - (struct virtchnl_promisc_info *)msg; -@@ -3043,52 +3044,51 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) - goto error_param; - } - } else { -- enum ice_status status; -- u8 promisc_m; -- -- if (alluni) { -- if (vf->port_vlan_info || vsi->num_vlan) -- promisc_m = ICE_UCAST_VLAN_PROMISC_BITS; -- else -- promisc_m = ICE_UCAST_PROMISC_BITS; -- } else if (allmulti) { -- if (vf->port_vlan_info || vsi->num_vlan) -- promisc_m = ICE_MCAST_VLAN_PROMISC_BITS; -- else -- promisc_m = ICE_MCAST_PROMISC_BITS; -+ u8 mcast_m, ucast_m; -+ -+ if (vf->port_vlan_info || vsi->num_vlan > 1) { -+ mcast_m = ICE_MCAST_VLAN_PROMISC_BITS; -+ ucast_m = ICE_UCAST_VLAN_PROMISC_BITS; - } else { -- if (vf->port_vlan_info || vsi->num_vlan) -- promisc_m = ICE_UCAST_VLAN_PROMISC_BITS; -- else -- promisc_m = ICE_UCAST_PROMISC_BITS; -+ mcast_m = ICE_MCAST_PROMISC_BITS; -+ ucast_m = ICE_UCAST_PROMISC_BITS; - } - -- /* Configure multicast/unicast with or without VLAN promiscuous -- * mode -- */ -- status = ice_vf_set_vsi_promisc(vf, vsi, promisc_m, rm_promisc); -- if (status) { -- dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed, error: %s\n", -- rm_promisc ? "dis" : "en", vf->vf_id, -- ice_stat_str(status)); -- v_ret = ice_err_to_virt_err(status); -- goto error_param; -- } else { -- dev_dbg(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d succeeded\n", -- rm_promisc ? "dis" : "en", vf->vf_id); -+ ucast_status = ice_vf_set_vsi_promisc(vf, vsi, ucast_m, -+ !alluni); -+ if (ucast_status) { -+ dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed\n", -+ alluni ? "en" : "dis", vf->vf_id); -+ v_ret = ice_err_to_virt_err(ucast_status); -+ } -+ -+ mcast_status = ice_vf_set_vsi_promisc(vf, vsi, mcast_m, -+ !allmulti); -+ if (mcast_status) { -+ dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed\n", -+ allmulti ? "en" : "dis", vf->vf_id); -+ v_ret = ice_err_to_virt_err(mcast_status); - } - } - -- if (allmulti && -- !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) -- dev_info(dev, "VF %u successfully set multicast promiscuous mode\n", vf->vf_id); -- else if (!allmulti && test_and_clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) -- dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n", vf->vf_id); -+ if (!mcast_status) { -+ if (allmulti && -+ !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) -+ dev_info(dev, "VF %u successfully set multicast promiscuous mode\n", -+ vf->vf_id); -+ else if (!allmulti && test_and_clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) -+ dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n", -+ vf->vf_id); -+ } - -- if (alluni && !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) -- dev_info(dev, "VF %u successfully set unicast promiscuous mode\n", vf->vf_id); -- else if (!alluni && test_and_clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) -- dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n", vf->vf_id); -+ if (!ucast_status) { -+ if (alluni && !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) -+ dev_info(dev, "VF %u successfully set unicast promiscuous mode\n", -+ vf->vf_id); -+ else if (!alluni && test_and_clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) -+ dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n", -+ vf->vf_id); -+ } - - error_param: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, -@@ -3762,6 +3762,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, - struct device *dev = ice_pf_to_dev(vf->pf); - u8 *mac_addr = vc_ether_addr->addr; - enum ice_status status; -+ int ret = 0; - - /* device MAC already added */ - if (ether_addr_equal(mac_addr, vf->dev_lan_addr.addr)) -@@ -3774,20 +3775,23 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, - - status = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI); - if (status == ICE_ERR_ALREADY_EXISTS) { -- dev_err(dev, "MAC %pM already exists for VF %d\n", mac_addr, -+ dev_dbg(dev, "MAC %pM already exists for VF %d\n", mac_addr, - vf->vf_id); -- return -EEXIST; -+ /* don't return since we might need to update -+ * the primary MAC in ice_vfhw_mac_add() below -+ */ -+ ret = -EEXIST; - } else if (status) { - dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %s\n", - mac_addr, vf->vf_id, ice_stat_str(status)); - return -EIO; -+ } else { -+ vf->num_mac++; - } - - ice_vfhw_mac_add(vf, vc_ether_addr); - -- vf->num_mac++; -- -- return 0; -+ return ret; - } - - /** -diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h -index 842cb077df861..38b4dc82c5c18 100644 ---- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h -+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h -@@ -111,9 +111,13 @@ struct ice_vf { - struct ice_mdd_vf_events mdd_rx_events; - struct ice_mdd_vf_events mdd_tx_events; - DECLARE_BITMAP(opcodes_allowlist, VIRTCHNL_OP_MAX); -+ -+ /* devlink port data */ -+ struct devlink_port devlink_port; - }; - - #ifdef CONFIG_PCI_IOV -+struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf); - void ice_process_vflr_event(struct ice_pf *pf); - int ice_sriov_configure(struct pci_dev *pdev, int num_vfs); - int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac); -@@ -171,6 +175,11 @@ static inline void ice_print_vfs_mdd_events(struct ice_pf *pf) { } - static inline void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { } - static inline void ice_restore_all_vfs_msi_state(struct pci_dev *pdev) { } - -+static inline struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) -+{ -+ return NULL; -+} -+ - static inline bool - ice_is_malicious_vf(struct ice_pf __always_unused *pf, - struct ice_rq_event_info __always_unused *event, -diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c -index 751de06019a0e..533199d819501 100644 ---- a/drivers/net/ethernet/intel/igb/igb_main.c -+++ b/drivers/net/ethernet/intel/igb/igb_main.c -@@ -7641,6 +7641,20 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf, - struct vf_mac_filter *entry = NULL; - int ret = 0; - -+ if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && -+ !vf_data->trusted) { -+ dev_warn(&pdev->dev, -+ "VF %d requested MAC filter but is administratively denied\n", -+ vf); -+ return -EINVAL; -+ } -+ if (!is_valid_ether_addr(addr)) { -+ dev_warn(&pdev->dev, -+ "VF %d attempted to set invalid MAC filter\n", -+ vf); -+ return -EINVAL; -+ } -+ - switch (info) { - case E1000_VF_MAC_FILTER_CLR: - /* remove all unicast MAC filters related to the current VF */ -@@ -7654,20 +7668,6 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf, - } - break; - case E1000_VF_MAC_FILTER_ADD: -- if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && -- !vf_data->trusted) { -- dev_warn(&pdev->dev, -- "VF %d requested MAC filter but is administratively denied\n", -- vf); -- return -EINVAL; -- } -- if (!is_valid_ether_addr(addr)) { -- dev_warn(&pdev->dev, -- "VF %d attempted to set invalid MAC filter\n", -- vf); -- return -EINVAL; -- } -- - /* try to find empty slot in the list */ - list_for_each(pos, &adapter->vf_macs.l) { - entry = list_entry(pos, struct vf_mac_filter, l); -@@ -8019,7 +8019,7 @@ static int igb_poll(struct napi_struct *napi, int budget) - if (likely(napi_complete_done(napi, work_done))) - igb_ring_irq_enable(q_vector); - -- return min(work_done, budget - 1); -+ return work_done; - } - - /** -diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c -index d32e72d953c8d..d051918dfdff9 100644 ---- a/drivers/net/ethernet/intel/igbvf/netdev.c -+++ b/drivers/net/ethernet/intel/igbvf/netdev.c -@@ -2861,6 +2861,7 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) - return 0; - - err_hw_init: -+ netif_napi_del(&adapter->rx_ring->napi); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - err_sw_init: -diff --git a/drivers/net/ethernet/intel/igc/igc_i225.c b/drivers/net/ethernet/intel/igc/igc_i225.c -index b2ef9fde97b38..b6807e16eea93 100644 ---- a/drivers/net/ethernet/intel/igc/igc_i225.c -+++ b/drivers/net/ethernet/intel/igc/igc_i225.c -@@ -636,7 +636,7 @@ s32 igc_set_ltr_i225(struct igc_hw *hw, bool link) - ltrv = rd32(IGC_LTRMAXV); - if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) { - ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max | -- (scale_min << IGC_LTRMAXV_SCALE_SHIFT); -+ (scale_max << IGC_LTRMAXV_SCALE_SHIFT); - wr32(IGC_LTRMAXV, ltrv); - } - } -diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c -index 0f021909b430a..30568e3544cda 100644 ---- a/drivers/net/ethernet/intel/igc/igc_ptp.c -+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c -@@ -773,7 +773,7 @@ static bool igc_is_crosststamp_supported(struct igc_adapter *adapter) - - static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp) - { --#if IS_ENABLED(CONFIG_X86_TSC) -+#if IS_ENABLED(CONFIG_X86_TSC) && !defined(CONFIG_UML) - return convert_art_ns_to_tsc(tstamp); - #else - return (struct system_counterval_t) { }; -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -index 13c4782b920a7..750b02bb2fdc2 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -@@ -5526,6 +5526,10 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw) - if (!speed && hw->mac.ops.get_link_capabilities) { - ret = hw->mac.ops.get_link_capabilities(hw, &speed, - &autoneg); -+ /* remove NBASE-T speeds from default autonegotiation -+ * to accommodate broken network switches in the field -+ * which cannot cope with advertised NBASE-T speeds -+ */ - speed &= ~(IXGBE_LINK_SPEED_5GB_FULL | - IXGBE_LINK_SPEED_2_5GB_FULL); - } -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -index 9724ffb165189..e4b50c7781ffa 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -@@ -3405,6 +3405,9 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) - /* flush pending Tx transactions */ - ixgbe_clear_tx_pending(hw); - -+ /* set MDIO speed before talking to the PHY in case it's the 1st time */ -+ ixgbe_set_mdio_speed(hw); -+ - /* PHY ops must be identified and initialized prior to reset */ - status = hw->phy.ops.init(hw); - if (status == IXGBE_ERR_SFP_NOT_SUPPORTED || -diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c -index a9bdbf0dcfe1e..5bb1cc8a2ce13 100644 ---- a/drivers/net/ethernet/litex/litex_liteeth.c -+++ b/drivers/net/ethernet/litex/litex_liteeth.c -@@ -289,7 +289,6 @@ static int liteeth_remove(struct platform_device *pdev) - struct net_device *netdev = platform_get_drvdata(pdev); - - unregister_netdev(netdev); -- free_netdev(netdev); - - return 0; - } -diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c -index 62a97c46fba05..ef878973b8597 100644 ---- a/drivers/net/ethernet/marvell/mvmdio.c -+++ b/drivers/net/ethernet/marvell/mvmdio.c -@@ -429,12 +429,14 @@ static const struct of_device_id orion_mdio_match[] = { - }; - MODULE_DEVICE_TABLE(of, orion_mdio_match); - -+#ifdef CONFIG_ACPI - static const struct acpi_device_id orion_mdio_acpi_match[] = { - { "MRVL0100", BUS_TYPE_SMI }, - { "MRVL0101", BUS_TYPE_XSMI }, - { }, - }; - MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match); -+#endif - - static struct platform_driver orion_mdio_driver = { - .probe = orion_mdio_probe, -diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -index d5c92e43f89e6..2baa909290b3b 100644 ---- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -1605,7 +1605,7 @@ static void mvpp22_gop_fca_set_periodic_timer(struct mvpp2_port *port) - mvpp22_gop_fca_enable_periodic(port, true); - } - --static int mvpp22_gop_init(struct mvpp2_port *port) -+static int mvpp22_gop_init(struct mvpp2_port *port, phy_interface_t interface) - { - struct mvpp2 *priv = port->priv; - u32 val; -@@ -1613,7 +1613,7 @@ static int mvpp22_gop_init(struct mvpp2_port *port) - if (!priv->sysctrl_base) - return 0; - -- switch (port->phy_interface) { -+ switch (interface) { - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: -@@ -1743,15 +1743,15 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port) - * lanes by the physical layer. This is why configurations like - * "PPv2 (2500BaseX) - COMPHY (2500SGMII)" are valid. - */ --static int mvpp22_comphy_init(struct mvpp2_port *port) -+static int mvpp22_comphy_init(struct mvpp2_port *port, -+ phy_interface_t interface) - { - int ret; - - if (!port->comphy) - return 0; - -- ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, -- port->phy_interface); -+ ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, interface); - if (ret) - return ret; - -@@ -2172,7 +2172,8 @@ static void mvpp22_pcs_reset_assert(struct mvpp2_port *port) - writel(val & ~MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0); - } - --static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port) -+static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port, -+ phy_interface_t interface) - { - struct mvpp2 *priv = port->priv; - void __iomem *mpcs, *xpcs; -@@ -2184,7 +2185,7 @@ static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port) - mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id); - xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); - -- switch (port->phy_interface) { -+ switch (interface) { - case PHY_INTERFACE_MODE_10GBASER: - val = readl(mpcs + MVPP22_MPCS_CLK_RESET); - val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | -@@ -2959,11 +2960,11 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, - mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size); - - if (priv->percpu_pools) { -- err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->id, 0); -+ err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->logic_rxq, 0); - if (err < 0) - goto err_free_dma; - -- err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->id, 0); -+ err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->logic_rxq, 0); - if (err < 0) - goto err_unregister_rxq_short; - -@@ -4529,7 +4530,8 @@ static int mvpp2_poll(struct napi_struct *napi, int budget) - return rx_done; - } - --static void mvpp22_mode_reconfigure(struct mvpp2_port *port) -+static void mvpp22_mode_reconfigure(struct mvpp2_port *port, -+ phy_interface_t interface) - { - u32 ctrl3; - -@@ -4540,18 +4542,18 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) - mvpp22_pcs_reset_assert(port); - - /* comphy reconfiguration */ -- mvpp22_comphy_init(port); -+ mvpp22_comphy_init(port, interface); - - /* gop reconfiguration */ -- mvpp22_gop_init(port); -+ mvpp22_gop_init(port, interface); - -- mvpp22_pcs_reset_deassert(port); -+ mvpp22_pcs_reset_deassert(port, interface); - - if (mvpp2_port_supports_xlg(port)) { - ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG); - ctrl3 &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK; - -- if (mvpp2_is_xlg(port->phy_interface)) -+ if (mvpp2_is_xlg(interface)) - ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_10G; - else - ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC; -@@ -4559,7 +4561,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) - writel(ctrl3, port->base + MVPP22_XLG_CTRL3_REG); - } - -- if (mvpp2_port_supports_xlg(port) && mvpp2_is_xlg(port->phy_interface)) -+ if (mvpp2_port_supports_xlg(port) && mvpp2_is_xlg(interface)) - mvpp2_xlg_max_rx_size_set(port); - else - mvpp2_gmac_max_rx_size_set(port); -@@ -4579,7 +4581,7 @@ static void mvpp2_start_dev(struct mvpp2_port *port) - mvpp2_interrupts_enable(port); - - if (port->priv->hw_version >= MVPP22) -- mvpp22_mode_reconfigure(port); -+ mvpp22_mode_reconfigure(port, port->phy_interface); - - if (port->phylink) { - phylink_start(port->phylink); -@@ -5015,11 +5017,13 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu) - mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8); - } - -+ if (port->xdp_prog && mtu > MVPP2_MAX_RX_BUF_SIZE) { -+ netdev_err(dev, "Illegal MTU value %d (> %d) for XDP mode\n", -+ mtu, (int)MVPP2_MAX_RX_BUF_SIZE); -+ return -EINVAL; -+ } -+ - if (MVPP2_RX_PKT_SIZE(mtu) > MVPP2_BM_LONG_PKT_SIZE) { -- if (port->xdp_prog) { -- netdev_err(dev, "Jumbo frames are not supported with XDP\n"); -- return -EINVAL; -- } - if (priv->percpu_pools) { - netdev_warn(dev, "mtu %d too high, switching to shared buffers", mtu); - mvpp2_bm_switch_buffers(priv, false); -@@ -5305,8 +5309,8 @@ static int mvpp2_xdp_setup(struct mvpp2_port *port, struct netdev_bpf *bpf) - bool running = netif_running(port->dev); - bool reset = !prog != !port->xdp_prog; - -- if (port->dev->mtu > ETH_DATA_LEN) { -- NL_SET_ERR_MSG_MOD(bpf->extack, "XDP is not supported with jumbo frames enabled"); -+ if (port->dev->mtu > MVPP2_MAX_RX_BUF_SIZE) { -+ NL_SET_ERR_MSG_MOD(bpf->extack, "MTU too large for XDP"); - return -EOPNOTSUPP; - } - -@@ -6477,6 +6481,9 @@ static int mvpp2__mac_prepare(struct phylink_config *config, unsigned int mode, - mvpp22_gop_mask_irq(port); - - phy_power_off(port->comphy); -+ -+ /* Reconfigure the serdes lanes */ -+ mvpp22_mode_reconfigure(port, interface); - } - } - -@@ -6531,9 +6538,6 @@ static int mvpp2_mac_finish(struct phylink_config *config, unsigned int mode, - port->phy_interface != interface) { - port->phy_interface = interface; - -- /* Reconfigure the serdes lanes */ -- mvpp22_mode_reconfigure(port); -- - /* Unmask interrupts */ - mvpp22_gop_unmask_irq(port); - } -@@ -6960,7 +6964,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, - * driver does this, we can remove this code. - */ - if (port->comphy) { -- err = mvpp22_comphy_init(port); -+ err = mvpp22_comphy_init(port, port->phy_interface); - if (err == 0) - phy_power_off(port->comphy); - } -@@ -7453,7 +7457,7 @@ static int mvpp2_probe(struct platform_device *pdev) - - shared = num_present_cpus() - priv->nthreads; - if (shared > 0) -- bitmap_fill(&priv->lock_map, -+ bitmap_set(&priv->lock_map, 0, - min_t(int, shared, MVPP2_MAX_THREADS)); - - for (i = 0; i < MVPP2_MAX_THREADS; i++) { -diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig -index 3f982ccf2c85f..639893d870550 100644 ---- a/drivers/net/ethernet/marvell/octeontx2/Kconfig -+++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig -@@ -31,6 +31,7 @@ config NDC_DIS_DYNAMIC_CACHING - config OCTEONTX2_PF - tristate "Marvell OcteonTX2 NIC Physical Function driver" - select OCTEONTX2_MBOX -+ select NET_DEVLINK - depends on (64BIT && COMPILE_TEST) || ARM64 - depends on PCI - depends on PTP_1588_CLOCK_OPTIONAL -diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c -index 35836903b7fbc..90dc5343827f0 100644 ---- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c -+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c -@@ -2281,7 +2281,7 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw, - goto free_regions; - break; - default: -- return err; -+ goto free_regions; - } - - mw->mbox_wq = alloc_workqueue(name, -diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c -index 53df7fff92c40..53a3e8de1a51e 100644 ---- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c -+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c -@@ -1493,6 +1493,44 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) - mutex_unlock(&mbox->lock); - } - -+static void otx2_do_set_rx_mode(struct otx2_nic *pf) -+{ -+ struct net_device *netdev = pf->netdev; -+ struct nix_rx_mode *req; -+ bool promisc = false; -+ -+ if (!(netdev->flags & IFF_UP)) -+ return; -+ -+ if ((netdev->flags & IFF_PROMISC) || -+ (netdev_uc_count(netdev) > OTX2_MAX_UNICAST_FLOWS)) { -+ promisc = true; -+ } -+ -+ /* Write unicast address to mcam entries or del from mcam */ -+ if (!promisc && netdev->priv_flags & IFF_UNICAST_FLT) -+ __dev_uc_sync(netdev, otx2_add_macfilter, otx2_del_macfilter); -+ -+ mutex_lock(&pf->mbox.lock); -+ req = otx2_mbox_alloc_msg_nix_set_rx_mode(&pf->mbox); -+ if (!req) { -+ mutex_unlock(&pf->mbox.lock); -+ return; -+ } -+ -+ req->mode = NIX_RX_MODE_UCAST; -+ -+ if (promisc) -+ req->mode |= NIX_RX_MODE_PROMISC; -+ if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) -+ req->mode |= NIX_RX_MODE_ALLMULTI; -+ -+ req->mode |= NIX_RX_MODE_USE_MCE; -+ -+ otx2_sync_mbox_msg(&pf->mbox); -+ mutex_unlock(&pf->mbox.lock); -+} -+ - int otx2_open(struct net_device *netdev) - { - struct otx2_nic *pf = netdev_priv(netdev); -@@ -1646,6 +1684,8 @@ int otx2_open(struct net_device *netdev) - if (err) - goto err_tx_stop_queues; - -+ otx2_do_set_rx_mode(pf); -+ - return 0; - - err_tx_stop_queues: -@@ -1791,43 +1831,11 @@ static void otx2_set_rx_mode(struct net_device *netdev) - queue_work(pf->otx2_wq, &pf->rx_mode_work); - } - --static void otx2_do_set_rx_mode(struct work_struct *work) -+static void otx2_rx_mode_wrk_handler(struct work_struct *work) - { - struct otx2_nic *pf = container_of(work, struct otx2_nic, rx_mode_work); -- struct net_device *netdev = pf->netdev; -- struct nix_rx_mode *req; -- bool promisc = false; -- -- if (!(netdev->flags & IFF_UP)) -- return; -- -- if ((netdev->flags & IFF_PROMISC) || -- (netdev_uc_count(netdev) > OTX2_MAX_UNICAST_FLOWS)) { -- promisc = true; -- } - -- /* Write unicast address to mcam entries or del from mcam */ -- if (!promisc && netdev->priv_flags & IFF_UNICAST_FLT) -- __dev_uc_sync(netdev, otx2_add_macfilter, otx2_del_macfilter); -- -- mutex_lock(&pf->mbox.lock); -- req = otx2_mbox_alloc_msg_nix_set_rx_mode(&pf->mbox); -- if (!req) { -- mutex_unlock(&pf->mbox.lock); -- return; -- } -- -- req->mode = NIX_RX_MODE_UCAST; -- -- if (promisc) -- req->mode |= NIX_RX_MODE_PROMISC; -- if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) -- req->mode |= NIX_RX_MODE_ALLMULTI; -- -- req->mode |= NIX_RX_MODE_USE_MCE; -- -- otx2_sync_mbox_msg(&pf->mbox); -- mutex_unlock(&pf->mbox.lock); -+ otx2_do_set_rx_mode(pf); - } - - static int otx2_set_features(struct net_device *netdev, -@@ -2358,7 +2366,7 @@ static int otx2_wq_init(struct otx2_nic *pf) - if (!pf->otx2_wq) - return -ENOMEM; - -- INIT_WORK(&pf->rx_mode_work, otx2_do_set_rx_mode); -+ INIT_WORK(&pf->rx_mode_work, otx2_rx_mode_wrk_handler); - INIT_WORK(&pf->reset_task, otx2_reset_task); - return 0; - } -diff --git a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c -index 3ce6ccd0f5394..b4599fe4ca8da 100644 ---- a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c -+++ b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c -@@ -497,8 +497,8 @@ int prestera_bridge_port_join(struct net_device *br_dev, - - br_port = prestera_bridge_port_add(bridge, port->dev); - if (IS_ERR(br_port)) { -- err = PTR_ERR(br_port); -- goto err_brport_create; -+ prestera_bridge_put(bridge); -+ return PTR_ERR(br_port); - } - - err = switchdev_bridge_port_offload(br_port->dev, port->dev, NULL, -@@ -519,8 +519,6 @@ err_port_join: - switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL); - err_switchdev_offload: - prestera_bridge_port_put(br_port); --err_brport_create: -- prestera_bridge_put(bridge); - return err; - } - -@@ -1124,7 +1122,7 @@ static int prestera_switchdev_blk_event(struct notifier_block *unused, - prestera_port_obj_attr_set); - break; - default: -- err = -EOPNOTSUPP; -+ return NOTIFY_DONE; - } - - return notifier_from_errno(err); -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c -index ef518b1040f72..fde521b1eecad 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c -@@ -663,7 +663,7 @@ void __init mlx4_en_init_ptys2ethtool_map(void) - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_T, SPEED_1000, - ETHTOOL_LINK_MODE_1000baseT_Full_BIT); - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_CX_SGMII, SPEED_1000, -- ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); -+ ETHTOOL_LINK_MODE_1000baseX_Full_BIT); - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_KX, SPEED_1000, - ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_T, SPEED_10000, -@@ -675,9 +675,9 @@ void __init mlx4_en_init_ptys2ethtool_map(void) - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KR, SPEED_10000, - ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CR, SPEED_10000, -- ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); -+ ETHTOOL_LINK_MODE_10000baseCR_Full_BIT); - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_SR, SPEED_10000, -- ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); -+ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT); - MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_20GBASE_KR2, SPEED_20000, - ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT, - ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c -index 8af7f28273225..3bd3603873e32 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c -@@ -2286,9 +2286,14 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, - bool carry_xdp_prog) - { - struct bpf_prog *xdp_prog; -- int i, t; -+ int i, t, ret; - -- mlx4_en_copy_priv(tmp, priv, prof); -+ ret = mlx4_en_copy_priv(tmp, priv, prof); -+ if (ret) { -+ en_warn(priv, "%s: mlx4_en_copy_priv() failed, return\n", -+ __func__); -+ return ret; -+ } - - if (mlx4_en_alloc_resources(tmp)) { - en_warn(priv, -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c -index db5dfff585c99..bea35530c2d0b 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c -@@ -334,6 +334,9 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, - case MLX5_CMD_OP_PAGE_FAULT_RESUME: - case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS: - case MLX5_CMD_OP_DEALLOC_SF: -+ case MLX5_CMD_OP_DESTROY_UCTX: -+ case MLX5_CMD_OP_DESTROY_UMEM: -+ case MLX5_CMD_OP_MODIFY_RQT: - return MLX5_CMD_STAT_OK; - - case MLX5_CMD_OP_QUERY_HCA_CAP: -@@ -439,7 +442,6 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, - case MLX5_CMD_OP_MODIFY_TIS: - case MLX5_CMD_OP_QUERY_TIS: - case MLX5_CMD_OP_CREATE_RQT: -- case MLX5_CMD_OP_MODIFY_RQT: - case MLX5_CMD_OP_QUERY_RQT: - - case MLX5_CMD_OP_CREATE_FLOW_TABLE: -@@ -459,9 +461,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, - case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: - case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: - case MLX5_CMD_OP_CREATE_UCTX: -- case MLX5_CMD_OP_DESTROY_UCTX: - case MLX5_CMD_OP_CREATE_UMEM: -- case MLX5_CMD_OP_DESTROY_UMEM: - case MLX5_CMD_OP_ALLOC_MEMIC: - case MLX5_CMD_OP_MODIFY_XRQ: - case MLX5_CMD_OP_RELEASE_XRQ_ERROR: -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c -index 02e77ffe5c3e4..5371ad0a12eb5 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c -@@ -164,13 +164,14 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) - MLX5_SET(destroy_cq_in, in, cqn, cq->cqn); - MLX5_SET(destroy_cq_in, in, uid, cq->uid); - err = mlx5_cmd_exec_in(dev, destroy_cq, in); -+ if (err) -+ return err; - - synchronize_irq(cq->irqn); -- - mlx5_cq_put(cq); - wait_for_completion(&cq->free); - -- return err; -+ return 0; - } - EXPORT_SYMBOL(mlx5_core_destroy_cq); - -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c -index 07c8d9811bc81..10d195042ab55 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c -@@ -507,6 +507,8 @@ void mlx5_debug_cq_remove(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) - if (!mlx5_debugfs_root) - return; - -- if (cq->dbg) -+ if (cq->dbg) { - rem_res_tree(cq->dbg); -+ cq->dbg = NULL; -+ } - } -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c -index dcf9f27ba2efd..d7576b6fa43b7 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c -@@ -625,7 +625,6 @@ static int mlx5_devlink_eth_param_register(struct devlink *devlink) - devlink_param_driverinit_value_set(devlink, - DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, - value); -- devlink_param_publish(devlink, &enable_eth_param); - return 0; - } - -@@ -636,7 +635,6 @@ static void mlx5_devlink_eth_param_unregister(struct devlink *devlink) - if (!mlx5_eth_supported(dev)) - return; - -- devlink_param_unpublish(devlink, &enable_eth_param); - devlink_param_unregister(devlink, &enable_eth_param); - } - -@@ -672,7 +670,6 @@ static int mlx5_devlink_rdma_param_register(struct devlink *devlink) - devlink_param_driverinit_value_set(devlink, - DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, - value); -- devlink_param_publish(devlink, &enable_rdma_param); - return 0; - } - -@@ -681,7 +678,6 @@ static void mlx5_devlink_rdma_param_unregister(struct devlink *devlink) - if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND)) - return; - -- devlink_param_unpublish(devlink, &enable_rdma_param); - devlink_param_unregister(devlink, &enable_rdma_param); - } - -@@ -706,7 +702,6 @@ static int mlx5_devlink_vnet_param_register(struct devlink *devlink) - devlink_param_driverinit_value_set(devlink, - DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, - value); -- devlink_param_publish(devlink, &enable_rdma_param); - return 0; - } - -@@ -717,7 +712,6 @@ static void mlx5_devlink_vnet_param_unregister(struct devlink *devlink) - if (!mlx5_vnet_supported(dev)) - return; - -- devlink_param_unpublish(devlink, &enable_vnet_param); - devlink_param_unregister(devlink, &enable_vnet_param); - } - -@@ -799,16 +793,12 @@ int mlx5_devlink_register(struct devlink *devlink) - { - int err; - -- err = devlink_register(devlink); -- if (err) -- return err; -- - err = devlink_params_register(devlink, mlx5_devlink_params, - ARRAY_SIZE(mlx5_devlink_params)); - if (err) -- goto params_reg_err; -+ return err; -+ - mlx5_devlink_set_params_init_values(devlink); -- devlink_params_publish(devlink); - - err = mlx5_devlink_auxdev_params_register(devlink); - if (err) -@@ -825,8 +815,6 @@ traps_reg_err: - auxdev_reg_err: - devlink_params_unregister(devlink, mlx5_devlink_params, - ARRAY_SIZE(mlx5_devlink_params)); --params_reg_err: -- devlink_unregister(devlink); - return err; - } - -@@ -834,8 +822,6 @@ void mlx5_devlink_unregister(struct devlink *devlink) - { - mlx5_devlink_traps_unregister(devlink); - mlx5_devlink_auxdev_params_unregister(devlink); -- devlink_params_unpublish(devlink); - devlink_params_unregister(devlink, mlx5_devlink_params, - ARRAY_SIZE(mlx5_devlink_params)); -- devlink_unregister(devlink); - } -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h -index 03a7a4ce5cd5e..c10a107a3ea53 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h -@@ -244,6 +244,17 @@ enum mlx5e_priv_flag { - - #define MLX5E_GET_PFLAG(params, pflag) (!!((params)->pflags & (BIT(pflag)))) - -+enum packet_merge { -+ MLX5E_PACKET_MERGE_NONE, -+ MLX5E_PACKET_MERGE_LRO, -+ MLX5E_PACKET_MERGE_SHAMPO, -+}; -+ -+struct mlx5e_packet_merge_param { -+ enum packet_merge type; -+ u32 timeout; -+}; -+ - struct mlx5e_params { - u8 log_sq_size; - u8 rq_wq_type; -@@ -258,13 +269,12 @@ struct mlx5e_params { - bool tunneled_offload_en; - struct dim_cq_moder rx_cq_moderation; - struct dim_cq_moder tx_cq_moderation; -- bool lro_en; -+ struct mlx5e_packet_merge_param packet_merge; - u8 tx_min_inline_mode; - bool vlan_strip_disable; - bool scatter_fcs_en; - bool rx_dim_enabled; - bool tx_dim_enabled; -- u32 lro_timeout; - u32 pflags; - struct bpf_prog *xdp_prog; - struct mlx5e_xsk *xsk; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c -index 3cbb596821e89..15f441a1b80c2 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c -@@ -87,7 +87,8 @@ bool mlx5e_rx_is_linear_skb(struct mlx5e_params *params, - u32 linear_frag_sz = max(mlx5e_rx_get_linear_frag_sz(params, xsk), - mlx5e_rx_get_linear_frag_sz(params, NULL)); - -- return !params->lro_en && linear_frag_sz <= PAGE_SIZE; -+ return params->packet_merge.type == MLX5E_PACKET_MERGE_NONE && -+ linear_frag_sz <= PAGE_SIZE; - } - - bool mlx5e_verify_rx_mpwqe_strides(struct mlx5_core_dev *mdev, -@@ -164,19 +165,8 @@ u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev, - mlx5e_rx_is_linear_skb(params, xsk) : - mlx5e_rx_mpwqe_is_linear_skb(mdev, params, xsk); - -- return is_linear_skb ? mlx5e_get_linear_rq_headroom(params, xsk) : 0; --} -- --struct mlx5e_lro_param mlx5e_get_lro_param(struct mlx5e_params *params) --{ -- struct mlx5e_lro_param lro_param; -- -- lro_param = (struct mlx5e_lro_param) { -- .enabled = params->lro_en, -- .timeout = params->lro_timeout, -- }; -- -- return lro_param; -+ return is_linear_skb || params->packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO ? -+ mlx5e_get_linear_rq_headroom(params, xsk) : 0; - } - - u16 mlx5e_calc_sq_stop_room(struct mlx5_core_dev *mdev, struct mlx5e_params *params) -@@ -485,10 +475,11 @@ static void mlx5e_build_rx_cq_param(struct mlx5_core_dev *mdev, - - static u8 rq_end_pad_mode(struct mlx5_core_dev *mdev, struct mlx5e_params *params) - { -+ bool lro_en = params->packet_merge.type == MLX5E_PACKET_MERGE_LRO; - bool ro = pcie_relaxed_ordering_enabled(mdev->pdev) && - MLX5_CAP_GEN(mdev, relaxed_ordering_write); - -- return ro && params->lro_en ? -+ return ro && lro_en ? - MLX5_WQ_END_PAD_MODE_NONE : MLX5_WQ_END_PAD_MODE_ALIGN; - } - -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h -index 879ad46d754e1..e9593f5f06610 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h -@@ -11,11 +11,6 @@ struct mlx5e_xsk_param { - u16 chunk_size; - }; - --struct mlx5e_lro_param { -- bool enabled; -- u32 timeout; --}; -- - struct mlx5e_cq_param { - u32 cqc[MLX5_ST_SZ_DW(cqc)]; - struct mlx5_wq_param wq; -@@ -125,7 +120,6 @@ u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev, - u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev, - struct mlx5e_params *params, - struct mlx5e_xsk_param *xsk); --struct mlx5e_lro_param mlx5e_get_lro_param(struct mlx5e_params *params); - - /* Build queue parameters */ - -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c -index 625cd49ef96c5..7b55b14d47ef7 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c -@@ -127,7 +127,7 @@ mlx5e_rss_get_tt_config(struct mlx5e_rss *rss, enum mlx5_traffic_types tt) - - static int mlx5e_rss_create_tir(struct mlx5e_rss *rss, - enum mlx5_traffic_types tt, -- const struct mlx5e_lro_param *init_lro_param, -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param, - bool inner) - { - struct mlx5e_rss_params_traffic_type rss_tt; -@@ -161,7 +161,7 @@ static int mlx5e_rss_create_tir(struct mlx5e_rss *rss, - rqtn = mlx5e_rqt_get_rqtn(&rss->rqt); - mlx5e_tir_builder_build_rqt(builder, rss->mdev->mlx5e_res.hw_objs.td.tdn, - rqtn, rss->inner_ft_support); -- mlx5e_tir_builder_build_lro(builder, init_lro_param); -+ mlx5e_tir_builder_build_packet_merge(builder, init_pkt_merge_param); - rss_tt = mlx5e_rss_get_tt_config(rss, tt); - mlx5e_tir_builder_build_rss(builder, &rss->hash, &rss_tt, inner); - -@@ -198,14 +198,14 @@ static void mlx5e_rss_destroy_tir(struct mlx5e_rss *rss, enum mlx5_traffic_types - } - - static int mlx5e_rss_create_tirs(struct mlx5e_rss *rss, -- const struct mlx5e_lro_param *init_lro_param, -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param, - bool inner) - { - enum mlx5_traffic_types tt, max_tt; - int err; - - for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { -- err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner); -+ err = mlx5e_rss_create_tir(rss, tt, init_pkt_merge_param, inner); - if (err) - goto err_destroy_tirs; - } -@@ -297,7 +297,7 @@ int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, - - int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, - bool inner_ft_support, u32 drop_rqn, -- const struct mlx5e_lro_param *init_lro_param) -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param) - { - int err; - -@@ -305,12 +305,12 @@ int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, - if (err) - goto err_out; - -- err = mlx5e_rss_create_tirs(rss, init_lro_param, false); -+ err = mlx5e_rss_create_tirs(rss, init_pkt_merge_param, false); - if (err) - goto err_destroy_rqt; - - if (inner_ft_support) { -- err = mlx5e_rss_create_tirs(rss, init_lro_param, true); -+ err = mlx5e_rss_create_tirs(rss, init_pkt_merge_param, true); - if (err) - goto err_destroy_tirs; - } -@@ -372,7 +372,7 @@ u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, - */ - int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss, - enum mlx5_traffic_types tt, -- const struct mlx5e_lro_param *init_lro_param, -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param, - bool inner, u32 *tirn) - { - struct mlx5e_tir *tir; -@@ -381,7 +381,7 @@ int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss, - if (!tir) { /* TIR doesn't exist, create one */ - int err; - -- err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner); -+ err = mlx5e_rss_create_tir(rss, tt, init_pkt_merge_param, inner); - if (err) - return err; - tir = rss_get_tir(rss, tt, inner); -@@ -418,7 +418,8 @@ void mlx5e_rss_disable(struct mlx5e_rss *rss) - mlx5e_rqt_get_rqtn(&rss->rqt), rss->drop_rqn, err); - } - --int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_param) -+int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss, -+ struct mlx5e_packet_merge_param *pkt_merge_param) - { - struct mlx5e_tir_builder *builder; - enum mlx5_traffic_types tt; -@@ -428,7 +429,7 @@ int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_p - if (!builder) - return -ENOMEM; - -- mlx5e_tir_builder_build_lro(builder, lro_param); -+ mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param); - - final_err = 0; - -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h -index d522a10dadf33..c6b2164163440 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h -@@ -17,7 +17,7 @@ struct mlx5e_rss *mlx5e_rss_alloc(void); - void mlx5e_rss_free(struct mlx5e_rss *rss); - int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, - bool inner_ft_support, u32 drop_rqn, -- const struct mlx5e_lro_param *init_lro_param); -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param); - int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, - bool inner_ft_support, u32 drop_rqn); - int mlx5e_rss_cleanup(struct mlx5e_rss *rss); -@@ -30,13 +30,14 @@ u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, - bool inner); - int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss, - enum mlx5_traffic_types tt, -- const struct mlx5e_lro_param *init_lro_param, -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param, - bool inner, u32 *tirn); - - void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns); - void mlx5e_rss_disable(struct mlx5e_rss *rss); - --int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_param); -+int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss, -+ struct mlx5e_packet_merge_param *pkt_merge_param); - int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc); - int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir, - const u8 *key, const u8 *hfunc, -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c -index 13056cb9757d4..0015a81eb9a17 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c -@@ -13,6 +13,9 @@ struct mlx5e_rx_res { - unsigned int max_nch; - u32 drop_rqn; - -+ struct mlx5e_packet_merge_param pkt_merge_param; -+ struct rw_semaphore pkt_merge_param_sem; -+ - struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS]; - bool rss_active; - u32 rss_rqns[MLX5E_INDIR_RQT_SIZE]; -@@ -34,7 +37,7 @@ struct mlx5e_rx_res { - /* API for rx_res_rss_* */ - - static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res, -- const struct mlx5e_lro_param *init_lro_param, -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param, - unsigned int init_nch) - { - bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; -@@ -49,7 +52,7 @@ static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res, - return -ENOMEM; - - err = mlx5e_rss_init(rss, res->mdev, inner_ft_support, res->drop_rqn, -- init_lro_param); -+ init_pkt_merge_param); - if (err) - goto err_rss_free; - -@@ -275,7 +278,7 @@ struct mlx5e_rx_res *mlx5e_rx_res_alloc(void) - } - - static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, -- const struct mlx5e_lro_param *init_lro_param) -+ const struct mlx5e_packet_merge_param *init_pkt_merge_param) - { - bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; - struct mlx5e_tir_builder *builder; -@@ -306,7 +309,7 @@ static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, - mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, - mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), - inner_ft_support); -- mlx5e_tir_builder_build_lro(builder, init_lro_param); -+ mlx5e_tir_builder_build_packet_merge(builder, init_pkt_merge_param); - mlx5e_tir_builder_build_direct(builder); - - err = mlx5e_tir_init(&res->channels[ix].direct_tir, builder, res->mdev, true); -@@ -336,7 +339,7 @@ static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, - mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, - mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), - inner_ft_support); -- mlx5e_tir_builder_build_lro(builder, init_lro_param); -+ mlx5e_tir_builder_build_packet_merge(builder, init_pkt_merge_param); - mlx5e_tir_builder_build_direct(builder); - - err = mlx5e_tir_init(&res->channels[ix].xsk_tir, builder, res->mdev, true); -@@ -392,6 +395,7 @@ static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res) - if (err) - goto out; - -+ /* Separated from the channels RQs, does not share pkt_merge state with them */ - mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, - mlx5e_rqt_get_rqtn(&res->ptp.rqt), - inner_ft_support); -@@ -437,7 +441,7 @@ static void mlx5e_rx_res_ptp_destroy(struct mlx5e_rx_res *res) - - int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, - enum mlx5e_rx_res_features features, unsigned int max_nch, -- u32 drop_rqn, const struct mlx5e_lro_param *init_lro_param, -+ u32 drop_rqn, const struct mlx5e_packet_merge_param *init_pkt_merge_param, - unsigned int init_nch) - { - int err; -@@ -447,11 +451,14 @@ int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, - res->max_nch = max_nch; - res->drop_rqn = drop_rqn; - -- err = mlx5e_rx_res_rss_init_def(res, init_lro_param, init_nch); -+ res->pkt_merge_param = *init_pkt_merge_param; -+ init_rwsem(&res->pkt_merge_param_sem); -+ -+ err = mlx5e_rx_res_rss_init_def(res, init_pkt_merge_param, init_nch); - if (err) - goto err_out; - -- err = mlx5e_rx_res_channels_init(res, init_lro_param); -+ err = mlx5e_rx_res_channels_init(res, init_pkt_merge_param); - if (err) - goto err_rss_destroy; - -@@ -513,7 +520,7 @@ u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res) - return mlx5e_tir_get_tirn(&res->ptp.tir); - } - --u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) -+static u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) - { - return mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt); - } -@@ -645,7 +652,8 @@ int mlx5e_rx_res_xsk_deactivate(struct mlx5e_rx_res *res, unsigned int ix) - return err; - } - --int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param *lro_param) -+int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, -+ struct mlx5e_packet_merge_param *pkt_merge_param) - { - struct mlx5e_tir_builder *builder; - int err, final_err; -@@ -655,7 +663,10 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param - if (!builder) - return -ENOMEM; - -- mlx5e_tir_builder_build_lro(builder, lro_param); -+ down_write(&res->pkt_merge_param_sem); -+ res->pkt_merge_param = *pkt_merge_param; -+ -+ mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param); - - final_err = 0; - -@@ -665,7 +676,7 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param - if (!rss) - continue; - -- err = mlx5e_rss_lro_set_param(rss, lro_param); -+ err = mlx5e_rss_packet_merge_set_param(rss, pkt_merge_param); - if (err) - final_err = final_err ? : err; - } -@@ -673,13 +684,14 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param - for (ix = 0; ix < res->max_nch; ix++) { - err = mlx5e_tir_modify(&res->channels[ix].direct_tir, builder); - if (err) { -- mlx5_core_warn(res->mdev, "Failed to update LRO state of direct TIR %#x for channel %u: err = %d\n", -+ mlx5_core_warn(res->mdev, "Failed to update packet merge state of direct TIR %#x for channel %u: err = %d\n", - mlx5e_tir_get_tirn(&res->channels[ix].direct_tir), ix, err); - if (!final_err) - final_err = err; - } - } - -+ up_write(&res->pkt_merge_param_sem); - mlx5e_tir_builder_free(builder); - return final_err; - } -@@ -688,3 +700,31 @@ struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res * - { - return mlx5e_rss_get_hash(res->rss[0]); - } -+ -+int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, -+ struct mlx5e_tir *tir) -+{ -+ bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; -+ struct mlx5e_tir_builder *builder; -+ u32 rqtn; -+ int err; -+ -+ builder = mlx5e_tir_builder_alloc(false); -+ if (!builder) -+ return -ENOMEM; -+ -+ rqtn = mlx5e_rx_res_get_rqtn_direct(res, rxq); -+ -+ mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, rqtn, -+ inner_ft_support); -+ mlx5e_tir_builder_build_direct(builder); -+ mlx5e_tir_builder_build_tls(builder); -+ down_read(&res->pkt_merge_param_sem); -+ mlx5e_tir_builder_build_packet_merge(builder, &res->pkt_merge_param); -+ err = mlx5e_tir_init(tir, builder, res->mdev, false); -+ up_read(&res->pkt_merge_param_sem); -+ -+ mlx5e_tir_builder_free(builder); -+ -+ return err; -+} -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h -index 4a15942d79f7d..b39b20a720e0f 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h -@@ -25,7 +25,7 @@ enum mlx5e_rx_res_features { - struct mlx5e_rx_res *mlx5e_rx_res_alloc(void); - int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, - enum mlx5e_rx_res_features features, unsigned int max_nch, -- u32 drop_rqn, const struct mlx5e_lro_param *init_lro_param, -+ u32 drop_rqn, const struct mlx5e_packet_merge_param *init_pkt_merge_param, - unsigned int init_nch); - void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res); - void mlx5e_rx_res_free(struct mlx5e_rx_res *res); -@@ -37,9 +37,6 @@ u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5_traffic_types - u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt); - u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res); - --/* RQTN getters for modules that create their own TIRs */ --u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix); -- - /* Activate/deactivate API */ - void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs); - void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res); -@@ -57,7 +54,8 @@ int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, - u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt); - int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt, - u8 rx_hash_fields); --int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param *lro_param); -+int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, -+ struct mlx5e_packet_merge_param *pkt_merge_param); - - int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch); - int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx); -@@ -68,4 +66,7 @@ struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx); - /* Workaround for hairpin */ - struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res); - -+/* Accel TIRs */ -+int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, -+ struct mlx5e_tir *tir); - #endif /* __MLX5_EN_RX_RES_H__ */ -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c -index 6c949abcd2e14..bc65151321ec2 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c -@@ -1356,9 +1356,13 @@ mlx5_tc_ct_match_add(struct mlx5_tc_ct_priv *priv, - int - mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, - struct mlx5_flow_attr *attr, -+ struct mlx5e_tc_mod_hdr_acts *mod_acts, - const struct flow_action_entry *act, - struct netlink_ext_ack *extack) - { -+ bool clear_action = act->ct.action & TCA_CT_ACT_CLEAR; -+ int err; -+ - if (!priv) { - NL_SET_ERR_MSG_MOD(extack, - "offload of ct action isn't available"); -@@ -1369,6 +1373,17 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, - attr->ct_attr.ct_action = act->ct.action; - attr->ct_attr.nf_ft = act->ct.flow_table; - -+ if (!clear_action) -+ goto out; -+ -+ err = mlx5_tc_ct_entry_set_registers(priv, mod_acts, 0, 0, 0, 0); -+ if (err) { -+ NL_SET_ERR_MSG_MOD(extack, "Failed to set registers for ct clear"); -+ return err; -+ } -+ attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; -+ -+out: - return 0; - } - -@@ -1898,23 +1913,16 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv, - - memcpy(pre_ct_attr, attr, attr_sz); - -- err = mlx5_tc_ct_entry_set_registers(ct_priv, mod_acts, 0, 0, 0, 0); -- if (err) { -- ct_dbg("Failed to set register for ct clear"); -- goto err_set_registers; -- } -- - mod_hdr = mlx5_modify_header_alloc(priv->mdev, ct_priv->ns_type, - mod_acts->num_actions, - mod_acts->actions); - if (IS_ERR(mod_hdr)) { - err = PTR_ERR(mod_hdr); - ct_dbg("Failed to add create ct clear mod hdr"); -- goto err_set_registers; -+ goto err_mod_hdr; - } - - pre_ct_attr->modify_hdr = mod_hdr; -- pre_ct_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; - - rule = mlx5_tc_rule_insert(priv, orig_spec, pre_ct_attr); - if (IS_ERR(rule)) { -@@ -1930,7 +1938,7 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv, - - err_insert: - mlx5_modify_header_dealloc(priv->mdev, mod_hdr); --err_set_registers: -+err_mod_hdr: - netdev_warn(priv->netdev, - "Failed to offload ct clear flow, err %d\n", err); - kfree(pre_ct_attr); -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h -index 363329f4aac61..99662af1e41a7 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h -@@ -110,6 +110,7 @@ int mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec); - int - mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, - struct mlx5_flow_attr *attr, -+ struct mlx5e_tc_mod_hdr_acts *mod_acts, - const struct flow_action_entry *act, - struct netlink_ext_ack *extack); - -@@ -172,6 +173,7 @@ mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec) - static inline int - mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, - struct mlx5_flow_attr *attr, -+ struct mlx5e_tc_mod_hdr_acts *mod_acts, - const struct flow_action_entry *act, - struct netlink_ext_ack *extack) - { -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h -index d1599b7b944bf..c340bf90354a0 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h -@@ -102,6 +102,7 @@ struct mlx5e_tc_flow { - refcount_t refcnt; - struct rcu_head rcu_head; - struct completion init_done; -+ struct completion del_hw_done; - int tunnel_id; /* the mapped tunnel id of this flow */ - struct mlx5_flow_attr *attr; - }; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c -index 1c44c6c345f5d..ec0163d75dd25 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c -@@ -221,8 +221,14 @@ static void mlx5e_take_tmp_flow(struct mlx5e_tc_flow *flow, - struct list_head *flow_list, - int index) - { -- if (IS_ERR(mlx5e_flow_get(flow))) -+ if (IS_ERR(mlx5e_flow_get(flow))) { -+ /* Flow is being deleted concurrently. Wait for it to be -+ * unoffloaded from hardware, otherwise deleting encap will -+ * fail. -+ */ -+ wait_for_completion(&flow->del_hw_done); - return; -+ } - wait_for_completion(&flow->init_done); - - flow->tmp_entry_index = index; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c -index de936dc4bc483..a1afb8585e37f 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c -@@ -70,24 +70,24 @@ void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn, - MLX5_SET(tirc, tirc, tunneled_offload_en, inner_ft_support); - } - --void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder, -- const struct mlx5e_lro_param *lro_param) -+void mlx5e_tir_builder_build_packet_merge(struct mlx5e_tir_builder *builder, -+ const struct mlx5e_packet_merge_param *pkt_merge_param) - { - void *tirc = mlx5e_tir_builder_get_tirc(builder); - const unsigned int rough_max_l2_l3_hdr_sz = 256; - - if (builder->modify) -- MLX5_SET(modify_tir_in, builder->in, bitmask.lro, 1); -+ MLX5_SET(modify_tir_in, builder->in, bitmask.packet_merge, 1); - -- if (!lro_param->enabled) -+ if (pkt_merge_param->type == MLX5E_PACKET_MERGE_NONE) - return; - -- MLX5_SET(tirc, tirc, lro_enable_mask, -- MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO | -- MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO); -+ MLX5_SET(tirc, tirc, packet_merge_mask, -+ MLX5_TIRC_PACKET_MERGE_MASK_IPV4_LRO | -+ MLX5_TIRC_PACKET_MERGE_MASK_IPV6_LRO); - MLX5_SET(tirc, tirc, lro_max_ip_payload_size, - (MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - rough_max_l2_l3_hdr_sz) >> 8); -- MLX5_SET(tirc, tirc, lro_timeout_period_usecs, lro_param->timeout); -+ MLX5_SET(tirc, tirc, lro_timeout_period_usecs, pkt_merge_param->timeout); - } - - static int mlx5e_hfunc_to_hw(u8 hfunc) -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h -index e45149a78ed9d..857a84bcd53af 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h -@@ -18,7 +18,7 @@ struct mlx5e_rss_params_traffic_type { - }; - - struct mlx5e_tir_builder; --struct mlx5e_lro_param; -+struct mlx5e_packet_merge_param; - - struct mlx5e_tir_builder *mlx5e_tir_builder_alloc(bool modify); - void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder); -@@ -27,8 +27,8 @@ void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder); - void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn); - void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn, - u32 rqtn, bool inner_ft_support); --void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder, -- const struct mlx5e_lro_param *lro_param); -+void mlx5e_tir_builder_build_packet_merge(struct mlx5e_tir_builder *builder, -+ const struct mlx5e_packet_merge_param *pkt_merge_param); - void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder, - const struct mlx5e_rss_params_hash *rss_hash, - const struct mlx5e_rss_params_traffic_type *rss_tt, -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c -index fb5397324aa4f..2db9573a3fe69 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c -@@ -191,7 +191,7 @@ static void mlx5e_ipsec_set_swp(struct sk_buff *skb, - eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2; - eseg->swp_inner_l4_offset = - (skb->csum_start + skb->head - skb->data) / 2; -- if (skb->protocol == htons(ETH_P_IPV6)) -+ if (inner_ip_hdr(skb)->version == 6) - eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6; - break; - default: -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c -index 62abce008c7b8..15711814d2d28 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c -@@ -55,6 +55,7 @@ struct mlx5e_ktls_offload_context_rx { - DECLARE_BITMAP(flags, MLX5E_NUM_PRIV_RX_FLAGS); - - /* resync */ -+ spinlock_t lock; /* protects resync fields */ - struct mlx5e_ktls_rx_resync_ctx resync; - struct list_head list; - }; -@@ -99,25 +100,6 @@ mlx5e_ktls_rx_resync_create_resp_list(void) - return resp_list; - } - --static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 rqtn) --{ -- struct mlx5e_tir_builder *builder; -- int err; -- -- builder = mlx5e_tir_builder_alloc(false); -- if (!builder) -- return -ENOMEM; -- -- mlx5e_tir_builder_build_rqt(builder, mdev->mlx5e_res.hw_objs.td.tdn, rqtn, false); -- mlx5e_tir_builder_build_direct(builder); -- mlx5e_tir_builder_build_tls(builder); -- err = mlx5e_tir_init(tir, builder, mdev, false); -- -- mlx5e_tir_builder_free(builder); -- -- return err; --} -- - static void accel_rule_handle_work(struct work_struct *work) - { - struct mlx5e_ktls_offload_context_rx *priv_rx; -@@ -386,14 +368,18 @@ static void resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_r - struct mlx5e_icosq *sq; - bool trigger_poll; - -- memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq)); -- - sq = &c->async_icosq; - ktls_resync = sq->ktls_resync; -+ trigger_poll = false; - - spin_lock_bh(&ktls_resync->lock); -- list_add_tail(&priv_rx->list, &ktls_resync->list); -- trigger_poll = !test_and_set_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &sq->state); -+ spin_lock_bh(&priv_rx->lock); -+ memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq)); -+ if (list_empty(&priv_rx->list)) { -+ list_add_tail(&priv_rx->list, &ktls_resync->list); -+ trigger_poll = !test_and_set_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &sq->state); -+ } -+ spin_unlock_bh(&priv_rx->lock); - spin_unlock_bh(&ktls_resync->lock); - - if (!trigger_poll) -@@ -604,7 +590,6 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, - struct mlx5_core_dev *mdev; - struct mlx5e_priv *priv; - int rxq, err; -- u32 rqtn; - - tls_ctx = tls_get_ctx(sk); - priv = netdev_priv(netdev); -@@ -617,6 +602,8 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, - if (err) - goto err_create_key; - -+ INIT_LIST_HEAD(&priv_rx->list); -+ spin_lock_init(&priv_rx->lock); - priv_rx->crypto_info = - *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info; - -@@ -628,9 +615,7 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, - priv_rx->sw_stats = &priv->tls->sw_stats; - mlx5e_set_ktls_rx_priv_ctx(tls_ctx, priv_rx); - -- rqtn = mlx5e_rx_res_get_rqtn_direct(priv->rx_res, rxq); -- -- err = mlx5e_ktls_create_tir(mdev, &priv_rx->tir, rqtn); -+ err = mlx5e_rx_res_tls_tir_create(priv->rx_res, rxq, &priv_rx->tir); - if (err) - goto err_create_tir; - -@@ -730,10 +715,14 @@ bool mlx5e_ktls_rx_handle_resync_list(struct mlx5e_channel *c, int budget) - priv_rx = list_first_entry(&local_list, - struct mlx5e_ktls_offload_context_rx, - list); -+ spin_lock(&priv_rx->lock); - cseg = post_static_params(sq, priv_rx); -- if (IS_ERR(cseg)) -+ if (IS_ERR(cseg)) { -+ spin_unlock(&priv_rx->lock); - break; -- list_del(&priv_rx->list); -+ } -+ list_del_init(&priv_rx->list); -+ spin_unlock(&priv_rx->lock); - db_cseg = cseg; - } - if (db_cseg) -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c -index 9d451b8ee467c..dc9b8718c3c10 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c -@@ -1954,8 +1954,8 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable) - return -EOPNOTSUPP; - if (!mlx5e_striding_rq_possible(mdev, &priv->channels.params)) - return -EINVAL; -- } else if (priv->channels.params.lro_en) { -- netdev_warn(netdev, "Can't set legacy RQ with LRO, disable LRO first\n"); -+ } else if (priv->channels.params.packet_merge.type != MLX5E_PACKET_MERGE_NONE) { -+ netdev_warn(netdev, "Can't set legacy RQ with HW-GRO/LRO, disable them first\n"); - return -EINVAL; - } - -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c -index 03693fa74a704..d32b70c62c949 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c -@@ -411,7 +411,7 @@ static int flow_get_tirn(struct mlx5e_priv *priv, - u32 rss_context, u32 *tirn) - { - if (fs->flow_type & FLOW_RSS) { -- struct mlx5e_lro_param lro_param; -+ struct mlx5e_packet_merge_param pkt_merge_param; - struct mlx5e_rss *rss; - u32 flow_type; - int err; -@@ -426,8 +426,8 @@ static int flow_get_tirn(struct mlx5e_priv *priv, - if (tt < 0) - return -EINVAL; - -- lro_param = mlx5e_get_lro_param(&priv->channels.params); -- err = mlx5e_rss_obtain_tirn(rss, tt, &lro_param, false, tirn); -+ pkt_merge_param = priv->channels.params.packet_merge; -+ err = mlx5e_rss_obtain_tirn(rss, tt, &pkt_merge_param, false, tirn); - if (err) - return err; - eth_rule->rss = rss; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c -index 41ef6eb70a585..8cf5fbebd674b 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c -@@ -2185,17 +2185,14 @@ void mlx5e_close_channels(struct mlx5e_channels *chs) - chs->num = 0; - } - --static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv) -+static int mlx5e_modify_tirs_packet_merge(struct mlx5e_priv *priv) - { - struct mlx5e_rx_res *res = priv->rx_res; -- struct mlx5e_lro_param lro_param; - -- lro_param = mlx5e_get_lro_param(&priv->channels.params); -- -- return mlx5e_rx_res_lro_set_param(res, &lro_param); -+ return mlx5e_rx_res_packet_merge_set_param(res, &priv->channels.params.packet_merge); - } - --static MLX5E_DEFINE_PREACTIVATE_WRAPPER_CTX(mlx5e_modify_tirs_lro); -+static MLX5E_DEFINE_PREACTIVATE_WRAPPER_CTX(mlx5e_modify_tirs_packet_merge); - - static int mlx5e_set_mtu(struct mlx5_core_dev *mdev, - struct mlx5e_params *params, u16 mtu) -@@ -3270,16 +3267,25 @@ static int set_feature_lro(struct net_device *netdev, bool enable) - } - - new_params = *cur_params; -- new_params.lro_en = enable; - -- if (cur_params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { -- if (mlx5e_rx_mpwqe_is_linear_skb(mdev, cur_params, NULL) == -- mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_params, NULL)) -- reset = false; -+ if (enable) -+ new_params.packet_merge.type = MLX5E_PACKET_MERGE_LRO; -+ else if (new_params.packet_merge.type == MLX5E_PACKET_MERGE_LRO) -+ new_params.packet_merge.type = MLX5E_PACKET_MERGE_NONE; -+ else -+ goto out; -+ -+ if (!(cur_params->packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO && -+ new_params.packet_merge.type == MLX5E_PACKET_MERGE_LRO)) { -+ if (cur_params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { -+ if (mlx5e_rx_mpwqe_is_linear_skb(mdev, cur_params, NULL) == -+ mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_params, NULL)) -+ reset = false; -+ } - } - - err = mlx5e_safe_switch_params(priv, &new_params, -- mlx5e_modify_tirs_lro_ctx, NULL, reset); -+ mlx5e_modify_tirs_packet_merge_ctx, NULL, reset); - out: - mutex_unlock(&priv->state_lock); - return err; -@@ -3606,7 +3612,7 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu, - goto out; - } - -- if (params->lro_en) -+ if (params->packet_merge.type == MLX5E_PACKET_MERGE_LRO) - reset = false; - - if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { -@@ -4063,8 +4069,8 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog) - struct net_device *netdev = priv->netdev; - struct mlx5e_params new_params; - -- if (priv->channels.params.lro_en) { -- netdev_warn(netdev, "can't set XDP while LRO is on, disable LRO first\n"); -+ if (priv->channels.params.packet_merge.type != MLX5E_PACKET_MERGE_NONE) { -+ netdev_warn(netdev, "can't set XDP while HW-GRO/LRO is on, disable them first\n"); - return -EINVAL; - } - -@@ -4321,9 +4327,10 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 - params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { - /* No XSK params: checking the availability of striding RQ in general. */ - if (!mlx5e_rx_mpwqe_is_linear_skb(mdev, params, NULL)) -- params->lro_en = !slow_pci_heuristic(mdev); -+ params->packet_merge.type = slow_pci_heuristic(mdev) ? -+ MLX5E_PACKET_MERGE_NONE : MLX5E_PACKET_MERGE_LRO; - } -- params->lro_timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT); -+ params->packet_merge.timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT); - - /* CQ moderation params */ - rx_cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ? -@@ -4608,7 +4615,6 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) - { - struct mlx5_core_dev *mdev = priv->mdev; - enum mlx5e_rx_res_features features; -- struct mlx5e_lro_param lro_param; - int err; - - priv->rx_res = mlx5e_rx_res_alloc(); -@@ -4626,9 +4632,9 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) - features = MLX5E_RX_RES_FEATURE_XSK | MLX5E_RX_RES_FEATURE_PTP; - if (priv->channels.params.tunneled_offload_en) - features |= MLX5E_RX_RES_FEATURE_INNER_FT; -- lro_param = mlx5e_get_lro_param(&priv->channels.params); - err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, features, -- priv->max_nch, priv->drop_rq.rqn, &lro_param, -+ priv->max_nch, priv->drop_rq.rqn, -+ &priv->channels.params.packet_merge, - priv->channels.params.num_channels); - if (err) - goto err_close_drop_rq; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c -index 0684ac6699b2d..edecd149dcab3 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c -@@ -793,7 +793,6 @@ int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup) - static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) - { - struct mlx5_core_dev *mdev = priv->mdev; -- struct mlx5e_lro_param lro_param; - int err; - - priv->rx_res = mlx5e_rx_res_alloc(); -@@ -808,9 +807,9 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) - return err; - } - -- lro_param = mlx5e_get_lro_param(&priv->channels.params); - err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, -- priv->max_nch, priv->drop_rq.rqn, &lro_param, -+ priv->max_nch, priv->drop_rq.rqn, -+ &priv->channels.params.packet_merge, - priv->channels.params.num_channels); - if (err) - goto err_close_drop_rq; -@@ -1070,6 +1069,10 @@ static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = { - &MLX5E_STATS_GRP(pme), - &MLX5E_STATS_GRP(channels), - &MLX5E_STATS_GRP(per_port_buff_congest), -+#ifdef CONFIG_MLX5_EN_IPSEC -+ &MLX5E_STATS_GRP(ipsec_sw), -+ &MLX5E_STATS_GRP(ipsec_hw), -+#endif - }; - - static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv) -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -index 129ff7e0d65cc..e3b320b6d85b9 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c -@@ -1544,6 +1544,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, - else - mlx5e_tc_unoffload_fdb_rules(esw, flow, attr); - } -+ complete_all(&flow->del_hw_done); - - if (mlx5_flow_has_geneve_opt(flow)) - mlx5_geneve_tlv_option_del(priv->mdev->geneve); -@@ -3457,7 +3458,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, - attr->dest_chain = act->chain_index; - break; - case FLOW_ACTION_CT: -- err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, act, extack); -+ err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, -+ &parse_attr->mod_hdr_acts, -+ act, extack); - if (err) - return err; - -@@ -4008,7 +4011,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, - NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported"); - return -EOPNOTSUPP; - } -- err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, act, extack); -+ err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, -+ &parse_attr->mod_hdr_acts, -+ act, extack); - if (err) - return err; - -@@ -4222,6 +4227,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, - INIT_LIST_HEAD(&flow->l3_to_l2_reformat); - refcount_set(&flow->refcnt, 1); - init_completion(&flow->init_done); -+ init_completion(&flow->del_hw_done); - - *__flow = flow; - *__parse_attr = parse_attr; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c -index c6cc67cb4f6ad..d377ddc70fc70 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c -@@ -130,7 +130,7 @@ static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw, - /* If vports min rate divider is 0 but their group has bw_share configured, then - * need to set bw_share for vports to minimal value. - */ -- if (!group_level && !max_guarantee && group->bw_share) -+ if (!group_level && !max_guarantee && group && group->bw_share) - return 1; - return 0; - } -@@ -423,7 +423,7 @@ static int esw_qos_vport_update_group(struct mlx5_eswitch *esw, - return err; - - /* Recalculate bw share weights of old and new groups */ -- if (vport->qos.bw_share) { -+ if (vport->qos.bw_share || new_group->bw_share) { - esw_qos_normalize_vports_min_rate(esw, curr_group, extack); - esw_qos_normalize_vports_min_rate(esw, new_group, extack); - } -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c -index ec136b4992045..51a8cecc4a7ce 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c -@@ -1305,12 +1305,17 @@ abort: - */ - int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) - { -+ bool toggle_lag; - int ret; - - if (!mlx5_esw_allowed(esw)) - return 0; - -- mlx5_lag_disable_change(esw->dev); -+ toggle_lag = esw->mode == MLX5_ESWITCH_NONE; -+ -+ if (toggle_lag) -+ mlx5_lag_disable_change(esw->dev); -+ - down_write(&esw->mode_lock); - if (esw->mode == MLX5_ESWITCH_NONE) { - ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs); -@@ -1324,7 +1329,10 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) - esw->esw_funcs.num_vfs = num_vfs; - } - up_write(&esw->mode_lock); -- mlx5_lag_enable_change(esw->dev); -+ -+ if (toggle_lag) -+ mlx5_lag_enable_change(esw->dev); -+ - return ret; - } - -@@ -1572,6 +1580,11 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) - esw->enabled_vports = 0; - esw->mode = MLX5_ESWITCH_NONE; - esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; -+ if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) && -+ MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)) -+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; -+ else -+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; - - dev->priv.eswitch = esw; - BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); -@@ -1934,7 +1947,7 @@ free_out: - return err; - } - --u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev) -+u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) - { - struct mlx5_eswitch *esw = dev->priv.eswitch; - -@@ -1948,7 +1961,7 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) - struct mlx5_eswitch *esw; - - esw = dev->priv.eswitch; -- return mlx5_esw_allowed(esw) ? esw->offloads.encap : -+ return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS) ? esw->offloads.encap : - DEVLINK_ESWITCH_ENCAP_MODE_NONE; - } - EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode); -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c -index 0d461e38add37..f3f23fdc20229 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c -@@ -2471,6 +2471,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, - struct mlx5_eswitch *esw = master->priv.eswitch; - struct mlx5_flow_table_attr ft_attr = { - .max_fte = 1, .prio = 0, .level = 0, -+ .flags = MLX5_FLOW_TABLE_OTHER_VPORT, - }; - struct mlx5_flow_namespace *egress_ns; - struct mlx5_flow_table *acl; -@@ -3141,12 +3142,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) - u64 mapping_id; - int err; - -- if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat) && -- MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, decap)) -- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; -- else -- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; -- - mutex_init(&esw->offloads.termtbl_mutex); - mlx5_rdma_enable_roce(esw->dev); - -@@ -3244,7 +3239,6 @@ void esw_offloads_disable(struct mlx5_eswitch *esw) - esw_offloads_metadata_uninit(esw); - mlx5_rdma_disable_roce(esw->dev); - mutex_destroy(&esw->offloads.termtbl_mutex); -- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; - } - - static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode) -@@ -3588,7 +3582,7 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, - *encap = esw->offloads.encap; - unlock: - up_write(&esw->mode_lock); -- return 0; -+ return err; - } - - static bool -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c -index 269ebb53eda67..cfde0a45b8b8a 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c -@@ -67,7 +67,7 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, - MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE : - MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE; - -- params->lro_en = false; -+ params->packet_merge.type = MLX5E_PACKET_MERGE_NONE; - params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; - params->tunneled_offload_en = false; - } -@@ -353,7 +353,6 @@ static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv) - static int mlx5i_init_rx(struct mlx5e_priv *priv) - { - struct mlx5_core_dev *mdev = priv->mdev; -- struct mlx5e_lro_param lro_param; - int err; - - priv->rx_res = mlx5e_rx_res_alloc(); -@@ -368,9 +367,9 @@ static int mlx5i_init_rx(struct mlx5e_priv *priv) - goto err_destroy_q_counters; - } - -- lro_param = mlx5e_get_lro_param(&priv->channels.params); - err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, -- priv->max_nch, priv->drop_rq.rqn, &lro_param, -+ priv->max_nch, priv->drop_rq.rqn, -+ &priv->channels.params.packet_merge, - priv->channels.params.num_channels); - if (err) - goto err_close_drop_rq; -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c -index d2105c1635c34..c19d9327095b2 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c -@@ -565,6 +565,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, - bool is_bonded, is_in_lag, mode_supported; - int bond_status = 0; - int num_slaves = 0; -+ int changed = 0; - int idx; - - if (!netif_is_lag_master(upper)) -@@ -601,27 +602,27 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, - */ - is_in_lag = num_slaves == MLX5_MAX_PORTS && bond_status == 0x3; - -- if (!mlx5_lag_is_ready(ldev) && is_in_lag) { -- NL_SET_ERR_MSG_MOD(info->info.extack, -- "Can't activate LAG offload, PF is configured with more than 64 VFs"); -- return 0; -- } -- - /* Lag mode must be activebackup or hash. */ - mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP || - tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH; - -- if (is_in_lag && !mode_supported) -- NL_SET_ERR_MSG_MOD(info->info.extack, -- "Can't activate LAG offload, TX type isn't supported"); -- - is_bonded = is_in_lag && mode_supported; - if (tracker->is_bonded != is_bonded) { - tracker->is_bonded = is_bonded; -- return 1; -+ changed = 1; - } - -- return 0; -+ if (!is_in_lag) -+ return changed; -+ -+ if (!mlx5_lag_is_ready(ldev)) -+ NL_SET_ERR_MSG_MOD(info->info.extack, -+ "Can't activate LAG offload, PF is configured with more than 64 VFs"); -+ else if (!mode_supported) -+ NL_SET_ERR_MSG_MOD(info->info.extack, -+ "Can't activate LAG offload, TX type isn't supported"); -+ -+ return changed; - } - - static int mlx5_handle_changelowerstate_event(struct mlx5_lag *ldev, -@@ -664,9 +665,6 @@ static int mlx5_lag_netdev_event(struct notifier_block *this, - - ldev = container_of(this, struct mlx5_lag, nb); - -- if (!mlx5_lag_is_ready(ldev) && event == NETDEV_CHANGELOWERSTATE) -- return NOTIFY_DONE; -- - tracker = ldev->tracker; - - switch (event) { -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c -index 79482824c64ff..92b08fa07efae 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/main.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c -@@ -1537,6 +1537,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id) - dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err); - - pci_save_state(pdev); -+ devlink_register(devlink); - if (!mlx5_core_is_mp_slave(dev)) - devlink_reload_enable(devlink); - return 0; -@@ -1559,6 +1560,7 @@ static void remove_one(struct pci_dev *pdev) - struct devlink *devlink = priv_to_devlink(dev); - - devlink_reload_disable(devlink); -+ devlink_unregister(devlink); - mlx5_crdump_disable(dev); - mlx5_drain_health_wq(dev); - mlx5_uninit_one(dev); -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c -index 052f48068dc16..3cf272fa21646 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c -@@ -46,6 +46,7 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia - mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err); - goto init_one_err; - } -+ devlink_register(devlink); - devlink_reload_enable(devlink); - return 0; - -@@ -65,6 +66,7 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev) - - devlink = priv_to_devlink(sf_dev->mdev); - devlink_reload_disable(devlink); -+ devlink_unregister(devlink); - mlx5_uninit_one(sf_dev->mdev); - iounmap(sf_dev->mdev->iseg); - mlx5_mdev_uninit(sf_dev->mdev); -diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -index 250c5a24264dc..edfdd44de579c 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c -@@ -2131,7 +2131,7 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, - max_ports = mlxsw_core_max_ports(mlxsw_sp->core); - local_port = mlxsw_reg_pude_local_port_get(pude_pl); - -- if (WARN_ON_ONCE(local_port >= max_ports)) -+ if (WARN_ON_ONCE(!local_port || local_port >= max_ports)) - return; - mlxsw_sp_port = mlxsw_sp->ports[local_port]; - if (!mlxsw_sp_port) -diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c -index 4d5a5d6595b3b..d64ce65a3c174 100644 ---- a/drivers/net/ethernet/microchip/lan743x_main.c -+++ b/drivers/net/ethernet/microchip/lan743x_main.c -@@ -914,8 +914,7 @@ static int lan743x_phy_reset(struct lan743x_adapter *adapter) - } - - static void lan743x_phy_update_flowcontrol(struct lan743x_adapter *adapter, -- u8 duplex, u16 local_adv, -- u16 remote_adv) -+ u16 local_adv, u16 remote_adv) - { - struct lan743x_phy *phy = &adapter->phy; - u8 cap; -@@ -943,7 +942,6 @@ static void lan743x_phy_link_status_change(struct net_device *netdev) - - phy_print_status(phydev); - if (phydev->state == PHY_RUNNING) { -- struct ethtool_link_ksettings ksettings; - int remote_advertisement = 0; - int local_advertisement = 0; - -@@ -980,18 +978,14 @@ static void lan743x_phy_link_status_change(struct net_device *netdev) - } - lan743x_csr_write(adapter, MAC_CR, data); - -- memset(&ksettings, 0, sizeof(ksettings)); -- phy_ethtool_get_link_ksettings(netdev, &ksettings); - local_advertisement = - linkmode_adv_to_mii_adv_t(phydev->advertising); - remote_advertisement = - linkmode_adv_to_mii_adv_t(phydev->lp_advertising); - -- lan743x_phy_update_flowcontrol(adapter, -- ksettings.base.duplex, -- local_advertisement, -+ lan743x_phy_update_flowcontrol(adapter, local_advertisement, - remote_advertisement); -- lan743x_ptp_update_latency(adapter, ksettings.base.speed); -+ lan743x_ptp_update_latency(adapter, phydev->speed); - } - } - -diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c -index a08e4f530c1c1..00b5e6860bf69 100644 ---- a/drivers/net/ethernet/mscc/ocelot.c -+++ b/drivers/net/ethernet/mscc/ocelot.c -@@ -1175,12 +1175,6 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) - switch (cfg.rx_filter) { - case HWTSTAMP_FILTER_NONE: - break; -- case HWTSTAMP_FILTER_ALL: -- case HWTSTAMP_FILTER_SOME: -- case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: -- case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: -- case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: -- case HWTSTAMP_FILTER_NTP_ALL: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: -@@ -1299,7 +1293,10 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port, - SOF_TIMESTAMPING_RAW_HARDWARE; - info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) | - BIT(HWTSTAMP_TX_ONESTEP_SYNC); -- info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); -+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | -+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | -+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | -+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT); - - return 0; - } -diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c -index ca4686094701c..0a02d8bd0a3e5 100644 ---- a/drivers/net/ethernet/natsemi/xtsonic.c -+++ b/drivers/net/ethernet/natsemi/xtsonic.c -@@ -120,7 +120,7 @@ static const struct net_device_ops xtsonic_netdev_ops = { - .ndo_set_mac_address = eth_mac_addr, - }; - --static int __init sonic_probe1(struct net_device *dev) -+static int sonic_probe1(struct net_device *dev) - { - unsigned int silicon_revision; - struct sonic_local *lp = netdev_priv(dev); -diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h -index df203738511bf..0b1865e9f0b59 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfp_net.h -+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h -@@ -565,7 +565,6 @@ struct nfp_net_dp { - * @exn_name: Name for Exception interrupt - * @shared_handler: Handler for shared interrupts - * @shared_name: Name for shared interrupt -- * @me_freq_mhz: ME clock_freq (MHz) - * @reconfig_lock: Protects @reconfig_posted, @reconfig_timer_active, - * @reconfig_sync_present and HW reconfiguration request - * regs/machinery from async requests (sync must take -@@ -650,8 +649,6 @@ struct nfp_net { - irq_handler_t shared_handler; - char shared_name[IFNAMSIZ + 8]; - -- u32 me_freq_mhz; -- - bool link_up; - spinlock_t link_status_lock; - -diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c -index 5bfa22accf2c9..850bfdf83d0a4 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c -+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c -@@ -2067,7 +2067,7 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) - if (napi_complete_done(napi, pkts_polled)) - nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_entry); - -- if (r_vec->nfp_net->rx_coalesce_adapt_on) { -+ if (r_vec->nfp_net->rx_coalesce_adapt_on && r_vec->rx_ring) { - struct dim_sample dim_sample = {}; - unsigned int start; - u64 pkts, bytes; -@@ -2082,7 +2082,7 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) - net_dim(&r_vec->rx_dim, dim_sample); - } - -- if (r_vec->nfp_net->tx_coalesce_adapt_on) { -+ if (r_vec->nfp_net->tx_coalesce_adapt_on && r_vec->tx_ring) { - struct dim_sample dim_sample = {}; - unsigned int start; - u64 pkts, bytes; -@@ -3016,10 +3016,8 @@ static void nfp_net_rx_dim_work(struct work_struct *work) - - /* copy RX interrupt coalesce parameters */ - value = (moder.pkts << 16) | (factor * moder.usec); -- rtnl_lock(); - nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(r_vec->rx_ring->idx), value); - (void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); -- rtnl_unlock(); - - dim->state = DIM_START_MEASURE; - } -@@ -3047,10 +3045,8 @@ static void nfp_net_tx_dim_work(struct work_struct *work) - - /* copy TX interrupt coalesce parameters */ - value = (moder.pkts << 16) | (factor * moder.usec); -- rtnl_lock(); - nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(r_vec->tx_ring->idx), value); - (void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); -- rtnl_unlock(); - - dim->state = DIM_START_MEASURE; - } -diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c -index 0685ece1f155d..be1a358baadb9 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c -+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c -@@ -1343,7 +1343,7 @@ static int nfp_net_set_coalesce(struct net_device *netdev, - * ME timestamp ticks. There are 16 ME clock cycles for each timestamp - * count. - */ -- factor = nn->me_freq_mhz / 16; -+ factor = nn->tlv_caps.me_freq_mhz / 16; - - /* Each pair of (usecs, max_frames) fields specifies that interrupts - * should be coalesced until -diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c -index d7ac0307797fd..34c0d2ddf9ef6 100644 ---- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c -+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c -@@ -803,8 +803,10 @@ int nfp_cpp_area_cache_add(struct nfp_cpp *cpp, size_t size) - return -ENOMEM; - - cache = kzalloc(sizeof(*cache), GFP_KERNEL); -- if (!cache) -+ if (!cache) { -+ nfp_cpp_area_free(area); - return -ENOMEM; -+ } - - cache->id = 0; - cache->addr = 0; -diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c -index 065e9004598ee..999abcfe3310a 100644 ---- a/drivers/net/ethernet/qlogic/qede/qede_fp.c -+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c -@@ -1643,6 +1643,13 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev) - data_split = true; - } - } else { -+ if (unlikely(skb->len > ETH_TX_MAX_NON_LSO_PKT_LEN)) { -+ DP_ERR(edev, "Unexpected non LSO skb length = 0x%x\n", skb->len); -+ qede_free_failed_tx_pkt(txq, first_bd, 0, false); -+ qede_update_tx_producer(txq); -+ return NETDEV_TX_OK; -+ } -+ - val |= ((skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK) << - ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); - } -diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c -index 9837bdb89cd40..ee4c3bd28a934 100644 ---- a/drivers/net/ethernet/qlogic/qede/qede_main.c -+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c -@@ -1176,19 +1176,17 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, - edev->devlink = qed_ops->common->devlink_register(cdev); - if (IS_ERR(edev->devlink)) { - DP_NOTICE(edev, "Cannot register devlink\n"); -+ rc = PTR_ERR(edev->devlink); - edev->devlink = NULL; -- /* Go on, we can live without devlink */ -+ goto err3; - } - } else { - struct net_device *ndev = pci_get_drvdata(pdev); -+ struct qed_devlink *qdl; - - edev = netdev_priv(ndev); -- -- if (edev->devlink) { -- struct qed_devlink *qdl = devlink_priv(edev->devlink); -- -- qdl->cdev = cdev; -- } -+ qdl = devlink_priv(edev->devlink); -+ qdl->cdev = cdev; - edev->cdev = cdev; - memset(&edev->stats, 0, sizeof(edev->stats)); - memcpy(&edev->dev_info, &dev_info, sizeof(dev_info)); -diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c -index c00ad57575eab..4eb9ea280474f 100644 ---- a/drivers/net/ethernet/qlogic/qla3xxx.c -+++ b/drivers/net/ethernet/qlogic/qla3xxx.c -@@ -3478,20 +3478,19 @@ static int ql_adapter_up(struct ql3_adapter *qdev) - - spin_lock_irqsave(&qdev->hw_lock, hw_flags); - -- err = ql_wait_for_drvr_lock(qdev); -- if (err) { -- err = ql_adapter_initialize(qdev); -- if (err) { -- netdev_err(ndev, "Unable to initialize adapter\n"); -- goto err_init; -- } -- netdev_err(ndev, "Releasing driver lock\n"); -- ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); -- } else { -+ if (!ql_wait_for_drvr_lock(qdev)) { - netdev_err(ndev, "Could not acquire driver lock\n"); -+ err = -ENODEV; - goto err_lock; - } - -+ err = ql_adapter_initialize(qdev); -+ if (err) { -+ netdev_err(ndev, "Unable to initialize adapter\n"); -+ goto err_init; -+ } -+ ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); -+ - spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); - - set_bit(QL_ADAPTER_UP, &qdev->flags); -diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c -index d51bac7ba5afa..bd06076803295 100644 ---- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c -+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c -@@ -1077,8 +1077,14 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter) - sds_mbx_size = sizeof(struct qlcnic_sds_mbx); - context_id = recv_ctx->context_id; - num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS; -- ahw->hw_ops->alloc_mbx_args(&cmd, adapter, -- QLCNIC_CMD_ADD_RCV_RINGS); -+ err = ahw->hw_ops->alloc_mbx_args(&cmd, adapter, -+ QLCNIC_CMD_ADD_RCV_RINGS); -+ if (err) { -+ dev_err(&adapter->pdev->dev, -+ "Failed to alloc mbx args %d\n", err); -+ return err; -+ } -+ - cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16); - - /* set up status rings, mbx 2-81 */ -diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c -index 518268ce20644..d35cafd422b1c 100644 ---- a/drivers/net/ethernet/sfc/ef100_nic.c -+++ b/drivers/net/ethernet/sfc/ef100_nic.c -@@ -609,6 +609,9 @@ static size_t ef100_update_stats(struct efx_nic *efx, - ef100_common_stat_mask(mask); - ef100_ethtool_stat_mask(mask); - -+ if (!mc_stats) -+ return 0; -+ - efx_nic_copy_stats(efx, mc_stats); - efx_nic_update_stats(ef100_stat_desc, EF100_STAT_COUNT, mask, - stats, mc_stats, false); -diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c -index bf1443539a1a4..bd552c7dffcb1 100644 ---- a/drivers/net/ethernet/sfc/ethtool_common.c -+++ b/drivers/net/ethernet/sfc/ethtool_common.c -@@ -563,20 +563,14 @@ int efx_ethtool_get_link_ksettings(struct net_device *net_dev, - { - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_link_state *link_state = &efx->link_state; -- u32 supported; - - mutex_lock(&efx->mac_lock); - efx_mcdi_phy_get_link_ksettings(efx, cmd); - mutex_unlock(&efx->mac_lock); - - /* Both MACs support pause frames (bidirectional and respond-only) */ -- ethtool_convert_link_mode_to_legacy_u32(&supported, -- cmd->link_modes.supported); -- -- supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -- -- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, -- supported); -+ ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); -+ ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); - - if (LOOPBACK_INTERNAL(efx)) { - cmd->base.speed = link_state->speed; -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -index 6924a6aacbd53..c469abc91fa1b 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -33,6 +33,7 @@ struct rk_gmac_ops { - void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); - void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); - void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); -+ bool regs_valid; - u32 regs[]; - }; - -@@ -1092,6 +1093,7 @@ static const struct rk_gmac_ops rk3568_ops = { - .set_to_rmii = rk3568_set_to_rmii, - .set_rgmii_speed = rk3568_set_gmac_speed, - .set_rmii_speed = rk3568_set_gmac_speed, -+ .regs_valid = true, - .regs = { - 0xfe2a0000, /* gmac0 */ - 0xfe010000, /* gmac1 */ -@@ -1383,7 +1385,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, - * to be distinguished. - */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (res) { -+ if (res && ops->regs_valid) { - int i = 0; - - while (ops->regs[i]) { -diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -index 85208128f135c..b7c2579c963b6 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -485,8 +485,28 @@ static int socfpga_dwmac_resume(struct device *dev) - } - #endif /* CONFIG_PM_SLEEP */ - --static SIMPLE_DEV_PM_OPS(socfpga_dwmac_pm_ops, stmmac_suspend, -- socfpga_dwmac_resume); -+static int __maybe_unused socfpga_dwmac_runtime_suspend(struct device *dev) -+{ -+ struct net_device *ndev = dev_get_drvdata(dev); -+ struct stmmac_priv *priv = netdev_priv(ndev); -+ -+ stmmac_bus_clks_config(priv, false); -+ -+ return 0; -+} -+ -+static int __maybe_unused socfpga_dwmac_runtime_resume(struct device *dev) -+{ -+ struct net_device *ndev = dev_get_drvdata(dev); -+ struct stmmac_priv *priv = netdev_priv(ndev); -+ -+ return stmmac_bus_clks_config(priv, true); -+} -+ -+static const struct dev_pm_ops socfpga_dwmac_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(stmmac_suspend, socfpga_dwmac_resume) -+ SET_RUNTIME_PM_OPS(socfpga_dwmac_runtime_suspend, socfpga_dwmac_runtime_resume, NULL) -+}; - - static const struct socfpga_dwmac_ops socfpga_gen5_ops = { - .set_phy_mode = socfpga_gen5_set_phy_mode, -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -index 43eead726886a..873b9e3e5da25 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -172,6 +172,19 @@ struct stmmac_flow_entry { - int is_l4; - }; - -+/* Rx Frame Steering */ -+enum stmmac_rfs_type { -+ STMMAC_RFS_T_VLAN, -+ STMMAC_RFS_T_MAX, -+}; -+ -+struct stmmac_rfs_entry { -+ unsigned long cookie; -+ int in_use; -+ int type; -+ int tc; -+}; -+ - struct stmmac_priv { - /* Frequently used values are kept adjacent for cache effect */ - u32 tx_coal_frames[MTL_MAX_TX_QUEUES]; -@@ -289,6 +302,10 @@ struct stmmac_priv { - struct stmmac_tc_entry *tc_entries; - unsigned int flow_entries_max; - struct stmmac_flow_entry *flow_entries; -+ unsigned int rfs_entries_max[STMMAC_RFS_T_MAX]; -+ unsigned int rfs_entries_cnt[STMMAC_RFS_T_MAX]; -+ unsigned int rfs_entries_total; -+ struct stmmac_rfs_entry *rfs_entries; - - /* Pulse Per Second output */ - struct stmmac_pps_cfg pps[STMMAC_PPS_MAX]; -@@ -314,6 +331,7 @@ int stmmac_mdio_reset(struct mii_bus *mii); - int stmmac_xpcs_setup(struct mii_bus *mii); - void stmmac_set_ethtool_ops(struct net_device *netdev); - -+int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags); - void stmmac_ptp_register(struct stmmac_priv *priv); - void stmmac_ptp_unregister(struct stmmac_priv *priv); - int stmmac_open(struct net_device *dev); -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -index 3d67d1fa36906..3422f0746d825 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -50,6 +50,13 @@ - #include "dwxgmac2.h" - #include "hwif.h" - -+/* As long as the interface is active, we keep the timestamping counter enabled -+ * with fine resolution and binary rollover. This avoid non-monotonic behavior -+ * (clock jumps) when changing timestamping settings at runtime. -+ */ -+#define STMMAC_HWTS_ACTIVE (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | \ -+ PTP_TCR_TSCTRLSSR) -+ - #define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16) - #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) - -@@ -511,6 +518,14 @@ bool stmmac_eee_init(struct stmmac_priv *priv) - return true; - } - -+static inline u32 stmmac_cdc_adjust(struct stmmac_priv *priv) -+{ -+ /* Correct the clk domain crossing(CDC) error */ -+ if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) -+ return (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate; -+ return 0; -+} -+ - /* stmmac_get_tx_hwtstamp - get HW TX timestamps - * @priv: driver private structure - * @p : descriptor pointer -@@ -524,7 +539,6 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, - { - struct skb_shared_hwtstamps shhwtstamp; - bool found = false; -- s64 adjust = 0; - u64 ns = 0; - - if (!priv->hwts_tx_en) -@@ -543,12 +557,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, - } - - if (found) { -- /* Correct the clk domain crossing(CDC) error */ -- if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) { -- adjust += -(2 * (NSEC_PER_SEC / -- priv->plat->clk_ptp_rate)); -- ns += adjust; -- } -+ ns -= stmmac_cdc_adjust(priv); - - memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); - shhwtstamp.hwtstamp = ns_to_ktime(ns); -@@ -573,7 +582,6 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, - { - struct skb_shared_hwtstamps *shhwtstamp = NULL; - struct dma_desc *desc = p; -- u64 adjust = 0; - u64 ns = 0; - - if (!priv->hwts_rx_en) -@@ -586,11 +594,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, - if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) { - stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns); - -- /* Correct the clk domain crossing(CDC) error */ -- if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) { -- adjust += 2 * (NSEC_PER_SEC / priv->plat->clk_ptp_rate); -- ns -= adjust; -- } -+ ns -= stmmac_cdc_adjust(priv); - - netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns); - shhwtstamp = skb_hwtstamps(skb); -@@ -616,8 +620,6 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) - { - struct stmmac_priv *priv = netdev_priv(dev); - struct hwtstamp_config config; -- struct timespec64 now; -- u64 temp = 0; - u32 ptp_v2 = 0; - u32 tstamp_all = 0; - u32 ptp_over_ipv4_udp = 0; -@@ -626,11 +628,6 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) - u32 snap_type_sel = 0; - u32 ts_master_en = 0; - u32 ts_event_en = 0; -- u32 sec_inc = 0; -- u32 value = 0; -- bool xmac; -- -- xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; - - if (!(priv->dma_cap.time_stamp || priv->adv_ts)) { - netdev_alert(priv->dev, "No support for HW time stamping\n"); -@@ -792,42 +789,17 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) - priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1); - priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON; - -- if (!priv->hwts_tx_en && !priv->hwts_rx_en) -- stmmac_config_hw_tstamping(priv, priv->ptpaddr, 0); -- else { -- value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR | -- tstamp_all | ptp_v2 | ptp_over_ethernet | -- ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en | -- ts_master_en | snap_type_sel); -- stmmac_config_hw_tstamping(priv, priv->ptpaddr, value); -- -- /* program Sub Second Increment reg */ -- stmmac_config_sub_second_increment(priv, -- priv->ptpaddr, priv->plat->clk_ptp_rate, -- xmac, &sec_inc); -- temp = div_u64(1000000000ULL, sec_inc); -- -- /* Store sub second increment and flags for later use */ -- priv->sub_second_inc = sec_inc; -- priv->systime_flags = value; -- -- /* calculate default added value: -- * formula is : -- * addend = (2^32)/freq_div_ratio; -- * where, freq_div_ratio = 1e9ns/sec_inc -- */ -- temp = (u64)(temp << 32); -- priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); -- stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend); -+ priv->systime_flags = STMMAC_HWTS_ACTIVE; - -- /* initialize system time */ -- ktime_get_real_ts64(&now); -- -- /* lower 32 bits of tv_sec are safe until y2106 */ -- stmmac_init_systime(priv, priv->ptpaddr, -- (u32)now.tv_sec, now.tv_nsec); -+ if (priv->hwts_tx_en || priv->hwts_rx_en) { -+ priv->systime_flags |= tstamp_all | ptp_v2 | -+ ptp_over_ethernet | ptp_over_ipv6_udp | -+ ptp_over_ipv4_udp | ts_event_en | -+ ts_master_en | snap_type_sel; - } - -+ stmmac_config_hw_tstamping(priv, priv->ptpaddr, priv->systime_flags); -+ - memcpy(&priv->tstamp_config, &config, sizeof(config)); - - return copy_to_user(ifr->ifr_data, &config, -@@ -855,6 +827,66 @@ static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) - sizeof(*config)) ? -EFAULT : 0; - } - -+/** -+ * stmmac_init_tstamp_counter - init hardware timestamping counter -+ * @priv: driver private structure -+ * @systime_flags: timestamping flags -+ * Description: -+ * Initialize hardware counter for packet timestamping. -+ * This is valid as long as the interface is open and not suspended. -+ * Will be rerun after resuming from suspend, case in which the timestamping -+ * flags updated by stmmac_hwtstamp_set() also need to be restored. -+ */ -+int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags) -+{ -+ bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; -+ struct timespec64 now; -+ u32 sec_inc = 0; -+ u64 temp = 0; -+ int ret; -+ -+ if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) -+ return -EOPNOTSUPP; -+ -+ ret = clk_prepare_enable(priv->plat->clk_ptp_ref); -+ if (ret < 0) { -+ netdev_warn(priv->dev, -+ "failed to enable PTP reference clock: %pe\n", -+ ERR_PTR(ret)); -+ return ret; -+ } -+ -+ stmmac_config_hw_tstamping(priv, priv->ptpaddr, systime_flags); -+ priv->systime_flags = systime_flags; -+ -+ /* program Sub Second Increment reg */ -+ stmmac_config_sub_second_increment(priv, priv->ptpaddr, -+ priv->plat->clk_ptp_rate, -+ xmac, &sec_inc); -+ temp = div_u64(1000000000ULL, sec_inc); -+ -+ /* Store sub second increment for later use */ -+ priv->sub_second_inc = sec_inc; -+ -+ /* calculate default added value: -+ * formula is : -+ * addend = (2^32)/freq_div_ratio; -+ * where, freq_div_ratio = 1e9ns/sec_inc -+ */ -+ temp = (u64)(temp << 32); -+ priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); -+ stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend); -+ -+ /* initialize system time */ -+ ktime_get_real_ts64(&now); -+ -+ /* lower 32 bits of tv_sec are safe until y2106 */ -+ stmmac_init_systime(priv, priv->ptpaddr, (u32)now.tv_sec, now.tv_nsec); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(stmmac_init_tstamp_counter); -+ - /** - * stmmac_init_ptp - init PTP - * @priv: driver private structure -@@ -865,9 +897,11 @@ static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) - static int stmmac_init_ptp(struct stmmac_priv *priv) - { - bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; -+ int ret; - -- if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) -- return -EOPNOTSUPP; -+ ret = stmmac_init_tstamp_counter(priv, STMMAC_HWTS_ACTIVE); -+ if (ret) -+ return ret; - - priv->adv_ts = 0; - /* Check if adv_ts can be enabled for dwmac 4.x / xgmac core */ -@@ -3271,10 +3305,6 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) - stmmac_mmc_setup(priv); - - if (init_ptp) { -- ret = clk_prepare_enable(priv->plat->clk_ptp_ref); -- if (ret < 0) -- netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret); -- - ret = stmmac_init_ptp(priv); - if (ret == -EOPNOTSUPP) - netdev_warn(priv->dev, "PTP not supported by HW\n"); -@@ -3764,6 +3794,8 @@ int stmmac_release(struct net_device *dev) - struct stmmac_priv *priv = netdev_priv(dev); - u32 chan; - -+ netif_tx_disable(dev); -+ - if (device_may_wakeup(priv->device)) - phylink_speed_down(priv->phylink, false); - /* Stop and disconnect the PHY */ -@@ -5499,8 +5531,6 @@ static int stmmac_set_features(struct net_device *netdev, - netdev_features_t features) - { - struct stmmac_priv *priv = netdev_priv(netdev); -- bool sph_en; -- u32 chan; - - /* Keep the COE Type in case of csum is supporting */ - if (features & NETIF_F_RXCSUM) -@@ -5512,10 +5542,13 @@ static int stmmac_set_features(struct net_device *netdev, - */ - stmmac_rx_ipc(priv, priv->hw); - -- sph_en = (priv->hw->rx_csum > 0) && priv->sph; -+ if (priv->sph_cap) { -+ bool sph_en = (priv->hw->rx_csum > 0) && priv->sph; -+ u32 chan; - -- for (chan = 0; chan < priv->plat->rx_queues_to_use; chan++) -- stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); -+ for (chan = 0; chan < priv->plat->rx_queues_to_use; chan++) -+ stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); -+ } - - return 0; - } -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -index 232ac98943cd0..5d29f336315b7 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -816,7 +816,7 @@ static int __maybe_unused stmmac_pltfr_noirq_resume(struct device *dev) - if (ret) - return ret; - -- clk_prepare_enable(priv->plat->clk_ptp_ref); -+ stmmac_init_tstamp_counter(priv, priv->systime_flags); - } - - return 0; -diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c -index 8160087ee92f2..d0a2b289f4603 100644 ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c -@@ -232,11 +232,33 @@ static int tc_setup_cls_u32(struct stmmac_priv *priv, - } - } - -+static int tc_rfs_init(struct stmmac_priv *priv) -+{ -+ int i; -+ -+ priv->rfs_entries_max[STMMAC_RFS_T_VLAN] = 8; -+ -+ for (i = 0; i < STMMAC_RFS_T_MAX; i++) -+ priv->rfs_entries_total += priv->rfs_entries_max[i]; -+ -+ priv->rfs_entries = devm_kcalloc(priv->device, -+ priv->rfs_entries_total, -+ sizeof(*priv->rfs_entries), -+ GFP_KERNEL); -+ if (!priv->rfs_entries) -+ return -ENOMEM; -+ -+ dev_info(priv->device, "Enabled RFS Flow TC (entries=%d)\n", -+ priv->rfs_entries_total); -+ -+ return 0; -+} -+ - static int tc_init(struct stmmac_priv *priv) - { - struct dma_features *dma_cap = &priv->dma_cap; - unsigned int count; -- int i; -+ int ret, i; - - if (dma_cap->l3l4fnum) { - priv->flow_entries_max = dma_cap->l3l4fnum; -@@ -250,10 +272,14 @@ static int tc_init(struct stmmac_priv *priv) - for (i = 0; i < priv->flow_entries_max; i++) - priv->flow_entries[i].idx = i; - -- dev_info(priv->device, "Enabled Flow TC (entries=%d)\n", -+ dev_info(priv->device, "Enabled L3L4 Flow TC (entries=%d)\n", - priv->flow_entries_max); - } - -+ ret = tc_rfs_init(priv); -+ if (ret) -+ return -ENOMEM; -+ - if (!priv->plat->fpe_cfg) { - priv->plat->fpe_cfg = devm_kzalloc(priv->device, - sizeof(*priv->plat->fpe_cfg), -@@ -607,16 +633,45 @@ static int tc_del_flow(struct stmmac_priv *priv, - return ret; - } - -+static struct stmmac_rfs_entry *tc_find_rfs(struct stmmac_priv *priv, -+ struct flow_cls_offload *cls, -+ bool get_free) -+{ -+ int i; -+ -+ for (i = 0; i < priv->rfs_entries_total; i++) { -+ struct stmmac_rfs_entry *entry = &priv->rfs_entries[i]; -+ -+ if (entry->cookie == cls->cookie) -+ return entry; -+ if (get_free && entry->in_use == false) -+ return entry; -+ } -+ -+ return NULL; -+} -+ - #define VLAN_PRIO_FULL_MASK (0x07) - - static int tc_add_vlan_flow(struct stmmac_priv *priv, - struct flow_cls_offload *cls) - { -+ struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false); - struct flow_rule *rule = flow_cls_offload_flow_rule(cls); - struct flow_dissector *dissector = rule->match.dissector; - int tc = tc_classid_to_hwtc(priv->dev, cls->classid); - struct flow_match_vlan match; - -+ if (!entry) { -+ entry = tc_find_rfs(priv, cls, true); -+ if (!entry) -+ return -ENOENT; -+ } -+ -+ if (priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN] >= -+ priv->rfs_entries_max[STMMAC_RFS_T_VLAN]) -+ return -ENOENT; -+ - /* Nothing to do here */ - if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN)) - return -EINVAL; -@@ -638,6 +693,12 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv, - - prio = BIT(match.key->vlan_priority); - stmmac_rx_queue_prio(priv, priv->hw, prio, tc); -+ -+ entry->in_use = true; -+ entry->cookie = cls->cookie; -+ entry->tc = tc; -+ entry->type = STMMAC_RFS_T_VLAN; -+ priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]++; - } - - return 0; -@@ -646,20 +707,19 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv, - static int tc_del_vlan_flow(struct stmmac_priv *priv, - struct flow_cls_offload *cls) - { -- struct flow_rule *rule = flow_cls_offload_flow_rule(cls); -- struct flow_dissector *dissector = rule->match.dissector; -- int tc = tc_classid_to_hwtc(priv->dev, cls->classid); -+ struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false); - -- /* Nothing to do here */ -- if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN)) -- return -EINVAL; -+ if (!entry || !entry->in_use || entry->type != STMMAC_RFS_T_VLAN) -+ return -ENOENT; - -- if (tc < 0) { -- netdev_err(priv->dev, "Invalid traffic class\n"); -- return -EINVAL; -- } -+ stmmac_rx_queue_prio(priv, priv->hw, 0, entry->tc); -+ -+ entry->in_use = false; -+ entry->cookie = 0; -+ entry->tc = 0; -+ entry->type = 0; - -- stmmac_rx_queue_prio(priv, priv->hw, 0, tc); -+ priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]--; - - return 0; - } -@@ -786,8 +846,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv, - goto disable; - if (qopt->num_entries >= dep) - return -EINVAL; -- if (!qopt->base_time) -- return -ERANGE; - if (!qopt->cycle_time) - return -ERANGE; - -diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c -index 0c75e0576ee1f..1ef0aaef5c61c 100644 ---- a/drivers/net/ethernet/ti/cpsw_ale.c -+++ b/drivers/net/ethernet/ti/cpsw_ale.c -@@ -1299,10 +1299,8 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params) - if (!ale) - return ERR_PTR(-ENOMEM); - -- ale->p0_untag_vid_mask = -- devm_kmalloc_array(params->dev, BITS_TO_LONGS(VLAN_N_VID), -- sizeof(unsigned long), -- GFP_KERNEL); -+ ale->p0_untag_vid_mask = devm_bitmap_zalloc(params->dev, VLAN_N_VID, -+ GFP_KERNEL); - if (!ale->p0_untag_vid_mask) - return ERR_PTR(-ENOMEM); - -diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c -index e8291d8488391..d243ca5dfde00 100644 ---- a/drivers/net/ethernet/ti/davinci_emac.c -+++ b/drivers/net/ethernet/ti/davinci_emac.c -@@ -420,8 +420,20 @@ static int emac_set_coalesce(struct net_device *ndev, - u32 int_ctrl, num_interrupts = 0; - u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0; - -- if (!coal->rx_coalesce_usecs) -- return -EINVAL; -+ if (!coal->rx_coalesce_usecs) { -+ priv->coal_intvl = 0; -+ -+ switch (priv->version) { -+ case EMAC_VERSION_2: -+ emac_ctrl_write(EMAC_DM646X_CMINTCTRL, 0); -+ break; -+ default: -+ emac_ctrl_write(EMAC_CTRL_EWINTTCNT, 0); -+ break; -+ } -+ -+ return 0; -+ } - - coal_intvl = coal->rx_coalesce_usecs; - -diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c -index e9258a9f3702c..31bc02421dd4e 100644 ---- a/drivers/net/ifb.c -+++ b/drivers/net/ifb.c -@@ -76,7 +76,9 @@ static void ifb_ri_tasklet(struct tasklet_struct *t) - - while ((skb = __skb_dequeue(&txp->tq)) != NULL) { - skb->redirected = 0; -+#ifdef CONFIG_NET_CLS_ACT - skb->tc_skip_classify = 1; -+#endif - - u64_stats_update_begin(&txp->tsync); - txp->tx_packets++; -diff --git a/drivers/net/ipa/ipa_cmd.c b/drivers/net/ipa/ipa_cmd.c -index cff51731195aa..d57472ea077f2 100644 ---- a/drivers/net/ipa/ipa_cmd.c -+++ b/drivers/net/ipa/ipa_cmd.c -@@ -661,22 +661,6 @@ void ipa_cmd_pipeline_clear_wait(struct ipa *ipa) - wait_for_completion(&ipa->completion); - } - --void ipa_cmd_pipeline_clear(struct ipa *ipa) --{ -- u32 count = ipa_cmd_pipeline_clear_count(); -- struct gsi_trans *trans; -- -- trans = ipa_cmd_trans_alloc(ipa, count); -- if (trans) { -- ipa_cmd_pipeline_clear_add(trans); -- gsi_trans_commit_wait(trans); -- ipa_cmd_pipeline_clear_wait(ipa); -- } else { -- dev_err(&ipa->pdev->dev, -- "error allocating %u entry tag transaction\n", count); -- } --} -- - static struct ipa_cmd_info * - ipa_cmd_info_alloc(struct ipa_endpoint *endpoint, u32 tre_count) - { -diff --git a/drivers/net/ipa/ipa_cmd.h b/drivers/net/ipa/ipa_cmd.h -index 69cd085d427db..05ed7e42e1842 100644 ---- a/drivers/net/ipa/ipa_cmd.h -+++ b/drivers/net/ipa/ipa_cmd.h -@@ -163,12 +163,6 @@ u32 ipa_cmd_pipeline_clear_count(void); - */ - void ipa_cmd_pipeline_clear_wait(struct ipa *ipa); - --/** -- * ipa_cmd_pipeline_clear() - Clear the hardware pipeline -- * @ipa: - IPA pointer -- */ --void ipa_cmd_pipeline_clear(struct ipa *ipa); -- - /** - * ipa_cmd_trans_alloc() - Allocate a transaction for the command TX endpoint - * @ipa: IPA pointer -diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c -index 5528d97110d56..03a1709934208 100644 ---- a/drivers/net/ipa/ipa_endpoint.c -+++ b/drivers/net/ipa/ipa_endpoint.c -@@ -853,6 +853,7 @@ static void ipa_endpoint_init_hol_block_timer(struct ipa_endpoint *endpoint, - u32 offset; - u32 val; - -+ /* This should only be changed when HOL_BLOCK_EN is disabled */ - offset = IPA_REG_ENDP_INIT_HOL_BLOCK_TIMER_N_OFFSET(endpoint_id); - val = hol_block_timer_val(ipa, microseconds); - iowrite32(val, ipa->reg_virt + offset); -@@ -868,6 +869,9 @@ ipa_endpoint_init_hol_block_enable(struct ipa_endpoint *endpoint, bool enable) - val = enable ? HOL_BLOCK_EN_FMASK : 0; - offset = IPA_REG_ENDP_INIT_HOL_BLOCK_EN_N_OFFSET(endpoint_id); - iowrite32(val, endpoint->ipa->reg_virt + offset); -+ /* When enabling, the register must be written twice for IPA v4.5+ */ -+ if (enable && endpoint->ipa->version >= IPA_VERSION_4_5) -+ iowrite32(val, endpoint->ipa->reg_virt + offset); - } - - void ipa_endpoint_modem_hol_block_clear_all(struct ipa *ipa) -@@ -880,6 +884,7 @@ void ipa_endpoint_modem_hol_block_clear_all(struct ipa *ipa) - if (endpoint->toward_ipa || endpoint->ee_id != GSI_EE_MODEM) - continue; - -+ ipa_endpoint_init_hol_block_enable(endpoint, false); - ipa_endpoint_init_hol_block_timer(endpoint, 0); - ipa_endpoint_init_hol_block_enable(endpoint, true); - } -@@ -1631,8 +1636,6 @@ void ipa_endpoint_suspend(struct ipa *ipa) - if (ipa->modem_netdev) - ipa_modem_suspend(ipa->modem_netdev); - -- ipa_cmd_pipeline_clear(ipa); -- - ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_LAN_RX]); - ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]); - } -diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c -index cdfa98a76e1f4..a448ec198bee1 100644 ---- a/drivers/net/ipa/ipa_main.c -+++ b/drivers/net/ipa/ipa_main.c -@@ -28,6 +28,7 @@ - #include "ipa_reg.h" - #include "ipa_mem.h" - #include "ipa_table.h" -+#include "ipa_smp2p.h" - #include "ipa_modem.h" - #include "ipa_uc.h" - #include "ipa_interrupt.h" -@@ -801,6 +802,11 @@ static int ipa_remove(struct platform_device *pdev) - struct device *dev = &pdev->dev; - int ret; - -+ /* Prevent the modem from triggering a call to ipa_setup(). This -+ * also ensures a modem-initiated setup that's underway completes. -+ */ -+ ipa_smp2p_irq_disable_setup(ipa); -+ - ret = pm_runtime_get_sync(dev); - if (WARN_ON(ret < 0)) - goto out_power_put; -diff --git a/drivers/net/ipa/ipa_modem.c b/drivers/net/ipa/ipa_modem.c -index ad116bcc0580e..d0ab4d70c303b 100644 ---- a/drivers/net/ipa/ipa_modem.c -+++ b/drivers/net/ipa/ipa_modem.c -@@ -339,9 +339,6 @@ int ipa_modem_stop(struct ipa *ipa) - if (state != IPA_MODEM_STATE_RUNNING) - return -EBUSY; - -- /* Prevent the modem from triggering a call to ipa_setup() */ -- ipa_smp2p_disable(ipa); -- - /* Clean up the netdev and endpoints if it was started */ - if (netdev) { - struct ipa_priv *priv = netdev_priv(netdev); -@@ -369,6 +366,9 @@ static void ipa_modem_crashed(struct ipa *ipa) - struct device *dev = &ipa->pdev->dev; - int ret; - -+ /* Prevent the modem from triggering a call to ipa_setup() */ -+ ipa_smp2p_irq_disable_setup(ipa); -+ - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - dev_err(dev, "error %d getting power to handle crash\n", ret); -diff --git a/drivers/net/ipa/ipa_resource.c b/drivers/net/ipa/ipa_resource.c -index e3da95d694099..06cec71993823 100644 ---- a/drivers/net/ipa/ipa_resource.c -+++ b/drivers/net/ipa/ipa_resource.c -@@ -52,7 +52,7 @@ static bool ipa_resource_limits_valid(struct ipa *ipa, - return false; - } - -- group_count = data->rsrc_group_src_count; -+ group_count = data->rsrc_group_dst_count; - if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX) - return false; - -diff --git a/drivers/net/ipa/ipa_smp2p.c b/drivers/net/ipa/ipa_smp2p.c -index df7639c39d716..2112336120391 100644 ---- a/drivers/net/ipa/ipa_smp2p.c -+++ b/drivers/net/ipa/ipa_smp2p.c -@@ -53,7 +53,7 @@ - * @setup_ready_irq: IPA interrupt triggered by modem to signal GSI ready - * @power_on: Whether IPA power is on - * @notified: Whether modem has been notified of power state -- * @disabled: Whether setup ready interrupt handling is disabled -+ * @setup_disabled: Whether setup ready interrupt handler is disabled - * @mutex: Mutex protecting ready-interrupt/shutdown interlock - * @panic_notifier: Panic notifier structure - */ -@@ -67,7 +67,7 @@ struct ipa_smp2p { - u32 setup_ready_irq; - bool power_on; - bool notified; -- bool disabled; -+ bool setup_disabled; - struct mutex mutex; - struct notifier_block panic_notifier; - }; -@@ -155,11 +155,9 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id) - struct device *dev; - int ret; - -- mutex_lock(&smp2p->mutex); -- -- if (smp2p->disabled) -- goto out_mutex_unlock; -- smp2p->disabled = true; /* If any others arrive, ignore them */ -+ /* Ignore any (spurious) interrupts received after the first */ -+ if (smp2p->ipa->setup_complete) -+ return IRQ_HANDLED; - - /* Power needs to be active for setup */ - dev = &smp2p->ipa->pdev->dev; -@@ -176,8 +174,6 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id) - out_power_put: - pm_runtime_mark_last_busy(dev); - (void)pm_runtime_put_autosuspend(dev); --out_mutex_unlock: -- mutex_unlock(&smp2p->mutex); - - return IRQ_HANDLED; - } -@@ -313,7 +309,7 @@ void ipa_smp2p_exit(struct ipa *ipa) - kfree(smp2p); - } - --void ipa_smp2p_disable(struct ipa *ipa) -+void ipa_smp2p_irq_disable_setup(struct ipa *ipa) - { - struct ipa_smp2p *smp2p = ipa->smp2p; - -@@ -322,7 +318,10 @@ void ipa_smp2p_disable(struct ipa *ipa) - - mutex_lock(&smp2p->mutex); - -- smp2p->disabled = true; -+ if (!smp2p->setup_disabled) { -+ disable_irq(smp2p->setup_ready_irq); -+ smp2p->setup_disabled = true; -+ } - - mutex_unlock(&smp2p->mutex); - } -diff --git a/drivers/net/ipa/ipa_smp2p.h b/drivers/net/ipa/ipa_smp2p.h -index 99a9567896388..59cee31a73836 100644 ---- a/drivers/net/ipa/ipa_smp2p.h -+++ b/drivers/net/ipa/ipa_smp2p.h -@@ -27,13 +27,12 @@ int ipa_smp2p_init(struct ipa *ipa, bool modem_init); - void ipa_smp2p_exit(struct ipa *ipa); - - /** -- * ipa_smp2p_disable() - Prevent "ipa-setup-ready" interrupt handling -+ * ipa_smp2p_irq_disable_setup() - Disable the "setup ready" interrupt - * @ipa: IPA pointer - * -- * Prevent handling of the "setup ready" interrupt from the modem. -- * This is used before initiating shutdown of the driver. -+ * Disable the "ipa-setup-ready" interrupt from the modem. - */ --void ipa_smp2p_disable(struct ipa *ipa); -+void ipa_smp2p_irq_disable_setup(struct ipa *ipa); - - /** - * ipa_smp2p_notify_reset() - Reset modem notification state -diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c -index cad820568f751..966c3b4ad59d1 100644 ---- a/drivers/net/mdio/mdio-aspeed.c -+++ b/drivers/net/mdio/mdio-aspeed.c -@@ -61,6 +61,13 @@ static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum) - - iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); - -+ rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl, -+ !(ctrl & ASPEED_MDIO_CTRL_FIRE), -+ ASPEED_MDIO_INTERVAL_US, -+ ASPEED_MDIO_TIMEOUT_US); -+ if (rc < 0) -+ return rc; -+ - rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_DATA, data, - data & ASPEED_MDIO_DATA_IDLE, - ASPEED_MDIO_INTERVAL_US, -diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c -index 90aafb56f1409..a438202129323 100644 ---- a/drivers/net/netdevsim/bpf.c -+++ b/drivers/net/netdevsim/bpf.c -@@ -514,6 +514,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap) - goto err_free; - key = nmap->entry[i].key; - *key = i; -+ memset(nmap->entry[i].value, 0, offmap->map.value_size); - } - } - -diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c -index b03a0513eb7e7..2e7c1cc16cb93 100644 ---- a/drivers/net/netdevsim/ethtool.c -+++ b/drivers/net/netdevsim/ethtool.c -@@ -77,7 +77,10 @@ static int nsim_set_ringparam(struct net_device *dev, - { - struct netdevsim *ns = netdev_priv(dev); - -- memcpy(&ns->ethtool.ring, ring, sizeof(ns->ethtool.ring)); -+ ns->ethtool.ring.rx_pending = ring->rx_pending; -+ ns->ethtool.ring.rx_jumbo_pending = ring->rx_jumbo_pending; -+ ns->ethtool.ring.rx_mini_pending = ring->rx_mini_pending; -+ ns->ethtool.ring.tx_pending = ring->tx_pending; - return 0; - } - -diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c -index 5c928f827173c..aec0fcefdccd6 100644 ---- a/drivers/net/phy/micrel.c -+++ b/drivers/net/phy/micrel.c -@@ -863,9 +863,9 @@ static int ksz9031_config_init(struct phy_device *phydev) - MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4, - tx_data_skews, 4, &update); - -- if (update && phydev->interface != PHY_INTERFACE_MODE_RGMII) -+ if (update && !phy_interface_is_rgmii(phydev)) - phydev_warn(phydev, -- "*-skew-ps values should be used only with phy-mode = \"rgmii\"\n"); -+ "*-skew-ps values should be used only with RGMII PHY modes\n"); - - /* Silicon Errata Sheet (DS80000691D or DS80000692D): - * When the device links in the 1000BASE-T slave mode only, -@@ -1593,8 +1593,9 @@ static struct phy_driver ksphy_driver[] = { - .get_sset_count = kszphy_get_sset_count, - .get_strings = kszphy_get_strings, - .get_stats = kszphy_get_stats, -- .suspend = genphy_suspend, -- .resume = genphy_resume, -+ /* No suspend/resume callbacks because of errata DS80000700A, -+ * receiver error following software power down. -+ */ - }, { - .phy_id = PHY_ID_KSZ8041RNLI, - .phy_id_mask = MICREL_PHY_ID_MASK, -diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c -index a3bfb156c83d7..beb2b66da1324 100644 ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -815,7 +815,12 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev, - phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl; - - /* Restart the PHY */ -- _phy_start_aneg(phydev); -+ if (phy_is_started(phydev)) { -+ phydev->state = PHY_UP; -+ phy_trigger_machine(phydev); -+ } else { -+ _phy_start_aneg(phydev); -+ } - - mutex_unlock(&phydev->lock); - return 0; -diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c -index 0a0abe8e4be0b..fef1416dcee4c 100644 ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -657,6 +657,7 @@ static void phylink_resolve(struct work_struct *w) - struct phylink_link_state link_state; - struct net_device *ndev = pl->netdev; - bool mac_config = false; -+ bool retrigger = false; - bool cur_link_state; - - mutex_lock(&pl->state_mutex); -@@ -670,6 +671,7 @@ static void phylink_resolve(struct work_struct *w) - link_state.link = false; - } else if (pl->mac_link_dropped) { - link_state.link = false; -+ retrigger = true; - } else { - switch (pl->cur_link_an_mode) { - case MLO_AN_PHY: -@@ -686,6 +688,19 @@ static void phylink_resolve(struct work_struct *w) - case MLO_AN_INBAND: - phylink_mac_pcs_get_state(pl, &link_state); - -+ /* The PCS may have a latching link-fail indicator. -+ * If the link was up, bring the link down and -+ * re-trigger the resolve. Otherwise, re-read the -+ * PCS state to get the current status of the link. -+ */ -+ if (!link_state.link) { -+ if (cur_link_state) -+ retrigger = true; -+ else -+ phylink_mac_pcs_get_state(pl, -+ &link_state); -+ } -+ - /* If we have a phy, the "up" state is the union of - * both the PHY and the MAC - */ -@@ -694,6 +709,15 @@ static void phylink_resolve(struct work_struct *w) - - /* Only update if the PHY link is up */ - if (pl->phydev && pl->phy_state.link) { -+ /* If the interface has changed, force a -+ * link down event if the link isn't already -+ * down, and re-resolve. -+ */ -+ if (link_state.interface != -+ pl->phy_state.interface) { -+ retrigger = true; -+ link_state.link = false; -+ } - link_state.interface = pl->phy_state.interface; - - /* If we have a PHY, we need to update with -@@ -736,7 +760,7 @@ static void phylink_resolve(struct work_struct *w) - else - phylink_link_up(pl, link_state); - } -- if (!link_state.link && pl->mac_link_dropped) { -+ if (!link_state.link && retrigger) { - pl->mac_link_dropped = false; - queue_work(system_power_efficient_wq, &pl->resolve); - } -@@ -1333,7 +1357,10 @@ void phylink_suspend(struct phylink *pl, bool mac_wol) - * but one would hope all packets have been sent. This - * also means phylink_resolve() will do nothing. - */ -- netif_carrier_off(pl->netdev); -+ if (pl->netdev) -+ netif_carrier_off(pl->netdev); -+ else -+ pl->old_link_state = false; - - /* We do not call mac_link_down() here as we want the - * link to remain up to receive the WoL packets. -@@ -1724,7 +1751,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl, - return -EOPNOTSUPP; - - if (!phylink_test(pl->supported, Asym_Pause) && -- !pause->autoneg && pause->rx_pause != pause->tx_pause) -+ pause->rx_pause != pause->tx_pause) - return -EINVAL; - - pause_state = 0; -diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index fecc9a1d293ae..1572878c34031 100644 ---- a/drivers/net/tun.c -+++ b/drivers/net/tun.c -@@ -1010,6 +1010,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct tun_struct *tun = netdev_priv(dev); - int txq = skb->queue_mapping; -+ struct netdev_queue *queue; - struct tun_file *tfile; - int len = skb->len; - -@@ -1054,6 +1055,10 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) - if (ptr_ring_produce(&tfile->tx_ring, skb)) - goto drop; - -+ /* NETIF_F_LLTX requires to do our own update of trans_start */ -+ queue = netdev_get_tx_queue(dev, txq); -+ queue->trans_start = jiffies; -+ - /* Notify and wake up reader process */ - if (tfile->flags & TUN_FASYNC) - kill_fasync(&tfile->fasync, SIGIO, POLL_IN); -diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c -index 24753a4da7e60..e303b522efb50 100644 ---- a/drivers/net/usb/cdc_ncm.c -+++ b/drivers/net/usb/cdc_ncm.c -@@ -181,6 +181,8 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx) - min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32); - - max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)); -+ if (max == 0) -+ max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */ - - /* some devices set dwNtbOutMaxSize too low for the above default */ - min = min(min, max); -diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c -index 63cd72c5f580c..a0401a9dade5b 100644 ---- a/drivers/net/usb/lan78xx.c -+++ b/drivers/net/usb/lan78xx.c -@@ -2228,7 +2228,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) - if (dev->domain_data.phyirq > 0) - phydev->irq = dev->domain_data.phyirq; - else -- phydev->irq = 0; -+ phydev->irq = PHY_POLL; - netdev_dbg(dev->net, "phydev->irq = %d\n", phydev->irq); - - /* set to AUTOMDIX */ -diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c -index f329e39100a7d..d3da350777a4d 100644 ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -9603,12 +9603,9 @@ static int rtl8152_probe(struct usb_interface *intf, - netdev->hw_features &= ~NETIF_F_RXCSUM; - } - -- if (le16_to_cpu(udev->descriptor.idVendor) == VENDOR_ID_LENOVO) { -- switch (le16_to_cpu(udev->descriptor.idProduct)) { -- case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2: -- case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2: -- tp->lenovo_macpassthru = 1; -- } -+ if (udev->parent && -+ le16_to_cpu(udev->parent->descriptor.idVendor) == VENDOR_ID_LENOVO) { -+ tp->lenovo_macpassthru = 1; - } - - if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial && -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 26b1bd8e845b4..f91dabd65ecd8 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -1049,6 +1049,14 @@ static const struct net_device_ops smsc95xx_netdev_ops = { - .ndo_set_features = smsc95xx_set_features, - }; - -+static void smsc95xx_handle_link_change(struct net_device *net) -+{ -+ struct usbnet *dev = netdev_priv(net); -+ -+ phy_print_status(net->phydev); -+ usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); -+} -+ - static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) - { - struct smsc95xx_priv *pdata; -@@ -1153,6 +1161,17 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) - dev->net->min_mtu = ETH_MIN_MTU; - dev->net->max_mtu = ETH_DATA_LEN; - dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; -+ -+ ret = phy_connect_direct(dev->net, pdata->phydev, -+ &smsc95xx_handle_link_change, -+ PHY_INTERFACE_MODE_MII); -+ if (ret) { -+ netdev_err(dev->net, "can't attach PHY to %s\n", pdata->mdiobus->id); -+ goto unregister_mdio; -+ } -+ -+ phy_attached_info(dev->net->phydev); -+ - return 0; - - unregister_mdio: -@@ -1170,47 +1189,25 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) - { - struct smsc95xx_priv *pdata = dev->driver_priv; - -+ phy_disconnect(dev->net->phydev); - mdiobus_unregister(pdata->mdiobus); - mdiobus_free(pdata->mdiobus); - netif_dbg(dev, ifdown, dev->net, "free pdata\n"); - kfree(pdata); - } - --static void smsc95xx_handle_link_change(struct net_device *net) --{ -- struct usbnet *dev = netdev_priv(net); -- -- phy_print_status(net->phydev); -- usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); --} -- - static int smsc95xx_start_phy(struct usbnet *dev) - { -- struct smsc95xx_priv *pdata = dev->driver_priv; -- struct net_device *net = dev->net; -- int ret; -+ phy_start(dev->net->phydev); - -- ret = smsc95xx_reset(dev); -- if (ret < 0) -- return ret; -- -- ret = phy_connect_direct(net, pdata->phydev, -- &smsc95xx_handle_link_change, -- PHY_INTERFACE_MODE_MII); -- if (ret) { -- netdev_err(net, "can't attach PHY to %s\n", pdata->mdiobus->id); -- return ret; -- } -- -- phy_attached_info(net->phydev); -- phy_start(net->phydev); - return 0; - } - --static int smsc95xx_disconnect_phy(struct usbnet *dev) -+static int smsc95xx_stop(struct usbnet *dev) - { -- phy_stop(dev->net->phydev); -- phy_disconnect(dev->net->phydev); -+ if (dev->net->phydev) -+ phy_stop(dev->net->phydev); -+ - return 0; - } - -@@ -1965,7 +1962,7 @@ static const struct driver_info smsc95xx_info = { - .unbind = smsc95xx_unbind, - .link_reset = smsc95xx_link_reset, - .reset = smsc95xx_start_phy, -- .stop = smsc95xx_disconnect_phy, -+ .stop = smsc95xx_stop, - .rx_fixup = smsc95xx_rx_fixup, - .tx_fixup = smsc95xx_tx_fixup, - .status = smsc95xx_status, -diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c -index 8799854bacb29..5b0215b7c1761 100644 ---- a/drivers/net/vmxnet3/vmxnet3_drv.c -+++ b/drivers/net/vmxnet3/vmxnet3_drv.c -@@ -3261,7 +3261,7 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) - - #ifdef CONFIG_PCI_MSI - if (adapter->intr.type == VMXNET3_IT_MSIX) { -- int i, nvec; -+ int i, nvec, nvec_allocated; - - nvec = adapter->share_intr == VMXNET3_INTR_TXSHARE ? - 1 : adapter->num_tx_queues; -@@ -3274,14 +3274,15 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) - for (i = 0; i < nvec; i++) - adapter->intr.msix_entries[i].entry = i; - -- nvec = vmxnet3_acquire_msix_vectors(adapter, nvec); -- if (nvec < 0) -+ nvec_allocated = vmxnet3_acquire_msix_vectors(adapter, nvec); -+ if (nvec_allocated < 0) - goto msix_err; - - /* If we cannot allocate one MSIx vector per queue - * then limit the number of rx queues to 1 - */ -- if (nvec == VMXNET3_LINUX_MIN_MSIX_VECT) { -+ if (nvec_allocated == VMXNET3_LINUX_MIN_MSIX_VECT && -+ nvec != VMXNET3_LINUX_MIN_MSIX_VECT) { - if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE - || adapter->num_rx_queues != 1) { - adapter->share_intr = VMXNET3_INTR_TXSHARE; -@@ -3291,14 +3292,14 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) - } - } - -- adapter->intr.num_intrs = nvec; -+ adapter->intr.num_intrs = nvec_allocated; - return; - - msix_err: - /* If we cannot allocate MSIx vectors use only one rx queue */ - dev_info(&adapter->pdev->dev, - "Failed to enable MSI-X, error %d. " -- "Limiting #rx queues to 1, try MSI.\n", nvec); -+ "Limiting #rx queues to 1, try MSI.\n", nvec_allocated); - - adapter->intr.type = VMXNET3_IT_MSI; - } -diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c -index 662e261173539..b2242a082431c 100644 ---- a/drivers/net/vrf.c -+++ b/drivers/net/vrf.c -@@ -35,6 +35,7 @@ - #include <net/l3mdev.h> - #include <net/fib_rules.h> - #include <net/netns/generic.h> -+#include <net/netfilter/nf_conntrack.h> - - #define DRV_NAME "vrf" - #define DRV_VERSION "1.1" -@@ -424,12 +425,26 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev, - return NETDEV_TX_OK; - } - -+static void vrf_nf_set_untracked(struct sk_buff *skb) -+{ -+ if (skb_get_nfct(skb) == 0) -+ nf_ct_set(skb, NULL, IP_CT_UNTRACKED); -+} -+ -+static void vrf_nf_reset_ct(struct sk_buff *skb) -+{ -+ if (skb_get_nfct(skb) == IP_CT_UNTRACKED) -+ nf_reset_ct(skb); -+} -+ - #if IS_ENABLED(CONFIG_IPV6) - static int vrf_ip6_local_out(struct net *net, struct sock *sk, - struct sk_buff *skb) - { - int err; - -+ vrf_nf_reset_ct(skb); -+ - err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, - sk, skb, NULL, skb_dst(skb)->dev, dst_output); - -@@ -482,6 +497,7 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, - /* strip the ethernet header added for pass through VRF device */ - __skb_pull(skb, skb_network_offset(skb)); - -+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); - ret = vrf_ip6_local_out(net, skb->sk, skb); - if (unlikely(net_xmit_eval(ret))) - dev->stats.tx_errors++; -@@ -508,6 +524,8 @@ static int vrf_ip_local_out(struct net *net, struct sock *sk, - { - int err; - -+ vrf_nf_reset_ct(skb); -+ - err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, - skb, NULL, skb_dst(skb)->dev, dst_output); - if (likely(err == 1)) -@@ -562,6 +580,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, - RT_SCOPE_LINK); - } - -+ memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - ret = vrf_ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb); - if (unlikely(net_xmit_eval(ret))) - vrf_dev->stats.tx_errors++; -@@ -626,8 +645,7 @@ static void vrf_finish_direct(struct sk_buff *skb) - skb_pull(skb, ETH_HLEN); - } - -- /* reset skb device */ -- nf_reset_ct(skb); -+ vrf_nf_reset_ct(skb); - } - - #if IS_ENABLED(CONFIG_IPV6) -@@ -641,7 +659,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, - struct neighbour *neigh; - int ret; - -- nf_reset_ct(skb); -+ vrf_nf_reset_ct(skb); - - skb->protocol = htons(ETH_P_IPV6); - skb->dev = dev; -@@ -772,6 +790,8 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev, - if (rt6_need_strict(&ipv6_hdr(skb)->daddr)) - return skb; - -+ vrf_nf_set_untracked(skb); -+ - if (qdisc_tx_is_default(vrf_dev) || - IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) - return vrf_ip6_out_direct(vrf_dev, sk, skb); -@@ -858,7 +878,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s - struct neighbour *neigh; - bool is_v6gw = false; - -- nf_reset_ct(skb); -+ vrf_nf_reset_ct(skb); - - /* Be paranoid, rather than too clever. */ - if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { -@@ -1001,6 +1021,8 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev, - ipv4_is_lbcast(ip_hdr(skb)->daddr)) - return skb; - -+ vrf_nf_set_untracked(skb); -+ - if (qdisc_tx_is_default(vrf_dev) || - IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) - return vrf_ip_out_direct(vrf_dev, sk, skb); -diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c -index b7197e80f2264..9a4c8ff32d9dd 100644 ---- a/drivers/net/wireguard/allowedips.c -+++ b/drivers/net/wireguard/allowedips.c -@@ -163,7 +163,7 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key, - return exact; - } - --static inline void connect_node(struct allowedips_node **parent, u8 bit, struct allowedips_node *node) -+static inline void connect_node(struct allowedips_node __rcu **parent, u8 bit, struct allowedips_node *node) - { - node->parent_bit_packed = (unsigned long)parent | bit; - rcu_assign_pointer(*parent, node); -diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c -index 551ddaaaf5400..a46067c38bf5d 100644 ---- a/drivers/net/wireguard/device.c -+++ b/drivers/net/wireguard/device.c -@@ -98,6 +98,7 @@ static int wg_stop(struct net_device *dev) - { - struct wg_device *wg = netdev_priv(dev); - struct wg_peer *peer; -+ struct sk_buff *skb; - - mutex_lock(&wg->device_update_lock); - list_for_each_entry(peer, &wg->peer_list, peer_list) { -@@ -108,7 +109,9 @@ static int wg_stop(struct net_device *dev) - wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake); - } - mutex_unlock(&wg->device_update_lock); -- skb_queue_purge(&wg->incoming_handshakes); -+ while ((skb = ptr_ring_consume(&wg->handshake_queue.ring)) != NULL) -+ kfree_skb(skb); -+ atomic_set(&wg->handshake_queue_len, 0); - wg_socket_reinit(wg, NULL, NULL); - return 0; - } -@@ -235,14 +238,13 @@ static void wg_destruct(struct net_device *dev) - destroy_workqueue(wg->handshake_receive_wq); - destroy_workqueue(wg->handshake_send_wq); - destroy_workqueue(wg->packet_crypt_wq); -- wg_packet_queue_free(&wg->decrypt_queue); -- wg_packet_queue_free(&wg->encrypt_queue); -+ wg_packet_queue_free(&wg->handshake_queue, true); -+ wg_packet_queue_free(&wg->decrypt_queue, false); -+ wg_packet_queue_free(&wg->encrypt_queue, false); - rcu_barrier(); /* Wait for all the peers to be actually freed. */ - wg_ratelimiter_uninit(); - memzero_explicit(&wg->static_identity, sizeof(wg->static_identity)); -- skb_queue_purge(&wg->incoming_handshakes); - free_percpu(dev->tstats); -- free_percpu(wg->incoming_handshakes_worker); - kvfree(wg->index_hashtable); - kvfree(wg->peer_hashtable); - mutex_unlock(&wg->device_update_lock); -@@ -298,7 +300,6 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, - init_rwsem(&wg->static_identity.lock); - mutex_init(&wg->socket_update_lock); - mutex_init(&wg->device_update_lock); -- skb_queue_head_init(&wg->incoming_handshakes); - wg_allowedips_init(&wg->peer_allowedips); - wg_cookie_checker_init(&wg->cookie_checker, wg); - INIT_LIST_HEAD(&wg->peer_list); -@@ -316,16 +317,10 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, - if (!dev->tstats) - goto err_free_index_hashtable; - -- wg->incoming_handshakes_worker = -- wg_packet_percpu_multicore_worker_alloc( -- wg_packet_handshake_receive_worker, wg); -- if (!wg->incoming_handshakes_worker) -- goto err_free_tstats; -- - wg->handshake_receive_wq = alloc_workqueue("wg-kex-%s", - WQ_CPU_INTENSIVE | WQ_FREEZABLE, 0, dev->name); - if (!wg->handshake_receive_wq) -- goto err_free_incoming_handshakes; -+ goto err_free_tstats; - - wg->handshake_send_wq = alloc_workqueue("wg-kex-%s", - WQ_UNBOUND | WQ_FREEZABLE, 0, dev->name); -@@ -347,10 +342,15 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, - if (ret < 0) - goto err_free_encrypt_queue; - -- ret = wg_ratelimiter_init(); -+ ret = wg_packet_queue_init(&wg->handshake_queue, wg_packet_handshake_receive_worker, -+ MAX_QUEUED_INCOMING_HANDSHAKES); - if (ret < 0) - goto err_free_decrypt_queue; - -+ ret = wg_ratelimiter_init(); -+ if (ret < 0) -+ goto err_free_handshake_queue; -+ - ret = register_netdevice(dev); - if (ret < 0) - goto err_uninit_ratelimiter; -@@ -367,18 +367,18 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, - - err_uninit_ratelimiter: - wg_ratelimiter_uninit(); -+err_free_handshake_queue: -+ wg_packet_queue_free(&wg->handshake_queue, false); - err_free_decrypt_queue: -- wg_packet_queue_free(&wg->decrypt_queue); -+ wg_packet_queue_free(&wg->decrypt_queue, false); - err_free_encrypt_queue: -- wg_packet_queue_free(&wg->encrypt_queue); -+ wg_packet_queue_free(&wg->encrypt_queue, false); - err_destroy_packet_crypt: - destroy_workqueue(wg->packet_crypt_wq); - err_destroy_handshake_send: - destroy_workqueue(wg->handshake_send_wq); - err_destroy_handshake_receive: - destroy_workqueue(wg->handshake_receive_wq); --err_free_incoming_handshakes: -- free_percpu(wg->incoming_handshakes_worker); - err_free_tstats: - free_percpu(dev->tstats); - err_free_index_hashtable: -@@ -398,6 +398,7 @@ static struct rtnl_link_ops link_ops __read_mostly = { - static void wg_netns_pre_exit(struct net *net) - { - struct wg_device *wg; -+ struct wg_peer *peer; - - rtnl_lock(); - list_for_each_entry(wg, &device_list, device_list) { -@@ -407,6 +408,8 @@ static void wg_netns_pre_exit(struct net *net) - mutex_lock(&wg->device_update_lock); - rcu_assign_pointer(wg->creating_net, NULL); - wg_socket_reinit(wg, NULL, NULL); -+ list_for_each_entry(peer, &wg->peer_list, peer_list) -+ wg_socket_clear_peer_endpoint_src(peer); - mutex_unlock(&wg->device_update_lock); - } - } -diff --git a/drivers/net/wireguard/device.h b/drivers/net/wireguard/device.h -index 854bc3d97150e..43c7cebbf50b0 100644 ---- a/drivers/net/wireguard/device.h -+++ b/drivers/net/wireguard/device.h -@@ -39,21 +39,18 @@ struct prev_queue { - - struct wg_device { - struct net_device *dev; -- struct crypt_queue encrypt_queue, decrypt_queue; -+ struct crypt_queue encrypt_queue, decrypt_queue, handshake_queue; - struct sock __rcu *sock4, *sock6; - struct net __rcu *creating_net; - struct noise_static_identity static_identity; -- struct workqueue_struct *handshake_receive_wq, *handshake_send_wq; -- struct workqueue_struct *packet_crypt_wq; -- struct sk_buff_head incoming_handshakes; -- int incoming_handshake_cpu; -- struct multicore_worker __percpu *incoming_handshakes_worker; -+ struct workqueue_struct *packet_crypt_wq,*handshake_receive_wq, *handshake_send_wq; - struct cookie_checker cookie_checker; - struct pubkey_hashtable *peer_hashtable; - struct index_hashtable *index_hashtable; - struct allowedips peer_allowedips; - struct mutex device_update_lock, socket_update_lock; - struct list_head device_list, peer_list; -+ atomic_t handshake_queue_len; - unsigned int num_peers, device_update_gen; - u32 fwmark; - u16 incoming_port; -diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c -index 48e7b982a3073..1de413b19e342 100644 ---- a/drivers/net/wireguard/queueing.c -+++ b/drivers/net/wireguard/queueing.c -@@ -38,11 +38,11 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, - return 0; - } - --void wg_packet_queue_free(struct crypt_queue *queue) -+void wg_packet_queue_free(struct crypt_queue *queue, bool purge) - { - free_percpu(queue->worker); -- WARN_ON(!__ptr_ring_empty(&queue->ring)); -- ptr_ring_cleanup(&queue->ring, NULL); -+ WARN_ON(!purge && !__ptr_ring_empty(&queue->ring)); -+ ptr_ring_cleanup(&queue->ring, purge ? (void(*)(void*))kfree_skb : NULL); - } - - #define NEXT(skb) ((skb)->prev) -diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h -index 4ef2944a68bc9..e2388107f7fdc 100644 ---- a/drivers/net/wireguard/queueing.h -+++ b/drivers/net/wireguard/queueing.h -@@ -23,7 +23,7 @@ struct sk_buff; - /* queueing.c APIs: */ - int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, - unsigned int len); --void wg_packet_queue_free(struct crypt_queue *queue); -+void wg_packet_queue_free(struct crypt_queue *queue, bool purge); - struct multicore_worker __percpu * - wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr); - -diff --git a/drivers/net/wireguard/ratelimiter.c b/drivers/net/wireguard/ratelimiter.c -index 3fedd1d21f5ee..dd55e5c26f468 100644 ---- a/drivers/net/wireguard/ratelimiter.c -+++ b/drivers/net/wireguard/ratelimiter.c -@@ -176,12 +176,12 @@ int wg_ratelimiter_init(void) - (1U << 14) / sizeof(struct hlist_head))); - max_entries = table_size * 8; - -- table_v4 = kvzalloc(table_size * sizeof(*table_v4), GFP_KERNEL); -+ table_v4 = kvcalloc(table_size, sizeof(*table_v4), GFP_KERNEL); - if (unlikely(!table_v4)) - goto err_kmemcache; - - #if IS_ENABLED(CONFIG_IPV6) -- table_v6 = kvzalloc(table_size * sizeof(*table_v6), GFP_KERNEL); -+ table_v6 = kvcalloc(table_size, sizeof(*table_v6), GFP_KERNEL); - if (unlikely(!table_v6)) { - kvfree(table_v4); - goto err_kmemcache; -diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c -index 7dc84bcca2613..7b8df406c7737 100644 ---- a/drivers/net/wireguard/receive.c -+++ b/drivers/net/wireguard/receive.c -@@ -116,8 +116,8 @@ static void wg_receive_handshake_packet(struct wg_device *wg, - return; - } - -- under_load = skb_queue_len(&wg->incoming_handshakes) >= -- MAX_QUEUED_INCOMING_HANDSHAKES / 8; -+ under_load = atomic_read(&wg->handshake_queue_len) >= -+ MAX_QUEUED_INCOMING_HANDSHAKES / 8; - if (under_load) { - last_under_load = ktime_get_coarse_boottime_ns(); - } else if (last_under_load) { -@@ -212,13 +212,14 @@ static void wg_receive_handshake_packet(struct wg_device *wg, - - void wg_packet_handshake_receive_worker(struct work_struct *work) - { -- struct wg_device *wg = container_of(work, struct multicore_worker, -- work)->ptr; -+ struct crypt_queue *queue = container_of(work, struct multicore_worker, work)->ptr; -+ struct wg_device *wg = container_of(queue, struct wg_device, handshake_queue); - struct sk_buff *skb; - -- while ((skb = skb_dequeue(&wg->incoming_handshakes)) != NULL) { -+ while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) { - wg_receive_handshake_packet(wg, skb); - dev_kfree_skb(skb); -+ atomic_dec(&wg->handshake_queue_len); - cond_resched(); - } - } -@@ -553,22 +554,28 @@ void wg_packet_receive(struct wg_device *wg, struct sk_buff *skb) - case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION): - case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): - case cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE): { -- int cpu; -- -- if (skb_queue_len(&wg->incoming_handshakes) > -- MAX_QUEUED_INCOMING_HANDSHAKES || -- unlikely(!rng_is_initialized())) { -+ int cpu, ret = -EBUSY; -+ -+ if (unlikely(!rng_is_initialized())) -+ goto drop; -+ if (atomic_read(&wg->handshake_queue_len) > MAX_QUEUED_INCOMING_HANDSHAKES / 2) { -+ if (spin_trylock_bh(&wg->handshake_queue.ring.producer_lock)) { -+ ret = __ptr_ring_produce(&wg->handshake_queue.ring, skb); -+ spin_unlock_bh(&wg->handshake_queue.ring.producer_lock); -+ } -+ } else -+ ret = ptr_ring_produce_bh(&wg->handshake_queue.ring, skb); -+ if (ret) { -+ drop: - net_dbg_skb_ratelimited("%s: Dropping handshake packet from %pISpfsc\n", - wg->dev->name, skb); - goto err; - } -- skb_queue_tail(&wg->incoming_handshakes, skb); -- /* Queues up a call to packet_process_queued_handshake_ -- * packets(skb): -- */ -- cpu = wg_cpumask_next_online(&wg->incoming_handshake_cpu); -+ atomic_inc(&wg->handshake_queue_len); -+ cpu = wg_cpumask_next_online(&wg->handshake_queue.last_cpu); -+ /* Queues up a call to packet_process_queued_handshake_packets(skb): */ - queue_work_on(cpu, wg->handshake_receive_wq, -- &per_cpu_ptr(wg->incoming_handshakes_worker, cpu)->work); -+ &per_cpu_ptr(wg->handshake_queue.worker, cpu)->work); - break; - } - case cpu_to_le32(MESSAGE_DATA): -diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c -index 8c496b7471082..6f07b949cb81d 100644 ---- a/drivers/net/wireguard/socket.c -+++ b/drivers/net/wireguard/socket.c -@@ -308,7 +308,7 @@ void wg_socket_clear_peer_endpoint_src(struct wg_peer *peer) - { - write_lock_bh(&peer->endpoint_lock); - memset(&peer->endpoint.src6, 0, sizeof(peer->endpoint.src6)); -- dst_cache_reset(&peer->endpoint_cache); -+ dst_cache_reset_now(&peer->endpoint_cache); - write_unlock_bh(&peer->endpoint_lock); - } - -diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c -index 2f9be182fbfbb..64c7145b51a2e 100644 ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -2690,9 +2690,16 @@ static int ath10k_core_copy_target_iram(struct ath10k *ar) - int i, ret; - u32 len, remaining_len; - -- hw_mem = ath10k_coredump_get_mem_layout(ar); -+ /* copy target iram feature must work also when -+ * ATH10K_FW_CRASH_DUMP_RAM_DATA is disabled, so -+ * _ath10k_coredump_get_mem_layout() to accomplist that -+ */ -+ hw_mem = _ath10k_coredump_get_mem_layout(ar); - if (!hw_mem) -- return -ENOMEM; -+ /* if CONFIG_DEV_COREDUMP is disabled we get NULL, then -+ * just silently disable the feature by doing nothing -+ */ -+ return 0; - - for (i = 0; i < hw_mem->region_table.size; i++) { - tmp = &hw_mem->region_table.regions[i]; -diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c -index 7eb72290a925c..55e7e11d06d94 100644 ---- a/drivers/net/wireless/ath/ath10k/coredump.c -+++ b/drivers/net/wireless/ath/ath10k/coredump.c -@@ -1447,11 +1447,17 @@ static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar) - - const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar) - { -- int i; -- - if (!test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) - return NULL; - -+ return _ath10k_coredump_get_mem_layout(ar); -+} -+EXPORT_SYMBOL(ath10k_coredump_get_mem_layout); -+ -+const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar) -+{ -+ int i; -+ - if (WARN_ON(ar->target_version == 0)) - return NULL; - -@@ -1464,7 +1470,6 @@ const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k - - return NULL; - } --EXPORT_SYMBOL(ath10k_coredump_get_mem_layout); - - struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar) - { -diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h -index 42404e246e0e9..240d705150888 100644 ---- a/drivers/net/wireless/ath/ath10k/coredump.h -+++ b/drivers/net/wireless/ath/ath10k/coredump.h -@@ -176,6 +176,7 @@ int ath10k_coredump_register(struct ath10k *ar); - void ath10k_coredump_unregister(struct ath10k *ar); - void ath10k_coredump_destroy(struct ath10k *ar); - -+const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar); - const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar); - - #else /* CONFIG_DEV_COREDUMP */ -@@ -214,6 +215,12 @@ ath10k_coredump_get_mem_layout(struct ath10k *ar) - return NULL; - } - -+static inline const struct ath10k_hw_mem_layout * -+_ath10k_coredump_get_mem_layout(struct ath10k *ar) -+{ -+ return NULL; -+} -+ - #endif /* CONFIG_DEV_COREDUMP */ - - #endif /* _COREDUMP_H_ */ -diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c -index c272b290fa73d..1f73fbfee0c06 100644 ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -993,8 +993,12 @@ static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif) - ath10k_mac_vif_beacon_free(arvif); - - if (arvif->beacon_buf) { -- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, -- arvif->beacon_buf, arvif->beacon_paddr); -+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) -+ kfree(arvif->beacon_buf); -+ else -+ dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, -+ arvif->beacon_buf, -+ arvif->beacon_paddr); - arvif->beacon_buf = NULL; - } - } -@@ -1048,7 +1052,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) - arg.channel.min_power = 0; - arg.channel.max_power = channel->max_power * 2; - arg.channel.max_reg_power = channel->max_reg_power * 2; -- arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; -+ arg.channel.max_antenna_gain = channel->max_antenna_gain; - - reinit_completion(&ar->vdev_setup_done); - reinit_completion(&ar->vdev_delete_done); -@@ -1494,7 +1498,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, - arg.channel.min_power = 0; - arg.channel.max_power = chandef->chan->max_power * 2; - arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; -- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; -+ arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; - - if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - arg.ssid = arvif->u.ap.ssid; -@@ -3422,7 +3426,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) - ch->min_power = 0; - ch->max_power = channel->max_power * 2; - ch->max_reg_power = channel->max_reg_power * 2; -- ch->max_antenna_gain = channel->max_antenna_gain * 2; -+ ch->max_antenna_gain = channel->max_antenna_gain; - ch->reg_class_id = 0; /* FIXME */ - - /* FIXME: why use only legacy modes, why not any -@@ -5576,10 +5580,25 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, - if (vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_AP) { -- arvif->beacon_buf = dma_alloc_coherent(ar->dev, -- IEEE80211_MAX_FRAME_LEN, -- &arvif->beacon_paddr, -- GFP_ATOMIC); -+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) { -+ arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN, -+ GFP_KERNEL); -+ -+ /* Using a kernel pointer in place of a dma_addr_t -+ * token can lead to undefined behavior if that -+ * makes it into cache management functions. Use a -+ * known-invalid address token instead, which -+ * avoids the warning and makes it easier to catch -+ * bugs if it does end up getting used. -+ */ -+ arvif->beacon_paddr = DMA_MAPPING_ERROR; -+ } else { -+ arvif->beacon_buf = -+ dma_alloc_coherent(ar->dev, -+ IEEE80211_MAX_FRAME_LEN, -+ &arvif->beacon_paddr, -+ GFP_ATOMIC); -+ } - if (!arvif->beacon_buf) { - ret = -ENOMEM; - ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", -@@ -5794,8 +5813,12 @@ err_vdev_delete: - - err: - if (arvif->beacon_buf) { -- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, -- arvif->beacon_buf, arvif->beacon_paddr); -+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) -+ kfree(arvif->beacon_buf); -+ else -+ dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, -+ arvif->beacon_buf, -+ arvif->beacon_paddr); - arvif->beacon_buf = NULL; - } - -diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c -index 07e478f9a808c..80fcb917fe4e1 100644 ---- a/drivers/net/wireless/ath/ath10k/qmi.c -+++ b/drivers/net/wireless/ath/ath10k/qmi.c -@@ -864,7 +864,8 @@ static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi) - - ath10k_qmi_remove_msa_permission(qmi); - ath10k_core_free_board_files(ar); -- if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags)) -+ if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags) && -+ !test_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags)) - ath10k_snoc_fw_crashed_dump(ar); - - ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND); -diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c -index b746052737e0b..eb705214f3f0a 100644 ---- a/drivers/net/wireless/ath/ath10k/sdio.c -+++ b/drivers/net/wireless/ath/ath10k/sdio.c -@@ -1363,8 +1363,11 @@ static void ath10k_rx_indication_async_work(struct work_struct *work) - ep->ep_ops.ep_rx_complete(ar, skb); - } - -- if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) -+ if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) { -+ local_bh_disable(); - napi_schedule(&ar->napi); -+ local_bh_enable(); -+ } - } - - static int ath10k_sdio_read_rtc_state(struct ath10k_sdio *ar_sdio, unsigned char *state) -diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c -index ea00fbb156015..9513ab696fff1 100644 ---- a/drivers/net/wireless/ath/ath10k/snoc.c -+++ b/drivers/net/wireless/ath/ath10k/snoc.c -@@ -12,6 +12,7 @@ - #include <linux/platform_device.h> - #include <linux/property.h> - #include <linux/regulator/consumer.h> -+#include <linux/remoteproc/qcom_rproc.h> - #include <linux/of_address.h> - #include <linux/iommu.h> - -@@ -1477,6 +1478,74 @@ void ath10k_snoc_fw_crashed_dump(struct ath10k *ar) - mutex_unlock(&ar->dump_mutex); - } - -+static int ath10k_snoc_modem_notify(struct notifier_block *nb, unsigned long action, -+ void *data) -+{ -+ struct ath10k_snoc *ar_snoc = container_of(nb, struct ath10k_snoc, nb); -+ struct ath10k *ar = ar_snoc->ar; -+ struct qcom_ssr_notify_data *notify_data = data; -+ -+ switch (action) { -+ case QCOM_SSR_BEFORE_POWERUP: -+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem starting event\n"); -+ clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags); -+ break; -+ -+ case QCOM_SSR_AFTER_POWERUP: -+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem running event\n"); -+ break; -+ -+ case QCOM_SSR_BEFORE_SHUTDOWN: -+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem %s event\n", -+ notify_data->crashed ? "crashed" : "stopping"); -+ if (!notify_data->crashed) -+ set_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags); -+ else -+ clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags); -+ break; -+ -+ case QCOM_SSR_AFTER_SHUTDOWN: -+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem offline event\n"); -+ break; -+ -+ default: -+ ath10k_err(ar, "received unrecognized event %lu\n", action); -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+static int ath10k_modem_init(struct ath10k *ar) -+{ -+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); -+ void *notifier; -+ int ret; -+ -+ ar_snoc->nb.notifier_call = ath10k_snoc_modem_notify; -+ -+ notifier = qcom_register_ssr_notifier("mpss", &ar_snoc->nb); -+ if (IS_ERR(notifier)) { -+ ret = PTR_ERR(notifier); -+ ath10k_err(ar, "failed to initialize modem notifier: %d\n", ret); -+ return ret; -+ } -+ -+ ar_snoc->notifier = notifier; -+ -+ return 0; -+} -+ -+static void ath10k_modem_deinit(struct ath10k *ar) -+{ -+ int ret; -+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); -+ -+ ret = qcom_unregister_ssr_notifier(ar_snoc->notifier, &ar_snoc->nb); -+ if (ret) -+ ath10k_err(ar, "error %d unregistering notifier\n", ret); -+} -+ - static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size) - { - struct device *dev = ar->dev; -@@ -1740,10 +1809,17 @@ static int ath10k_snoc_probe(struct platform_device *pdev) - goto err_fw_deinit; - } - -+ ret = ath10k_modem_init(ar); -+ if (ret) -+ goto err_qmi_deinit; -+ - ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n"); - - return 0; - -+err_qmi_deinit: -+ ath10k_qmi_deinit(ar); -+ - err_fw_deinit: - ath10k_fw_deinit(ar); - -@@ -1771,6 +1847,7 @@ static int ath10k_snoc_free_resources(struct ath10k *ar) - ath10k_fw_deinit(ar); - ath10k_snoc_free_irq(ar); - ath10k_snoc_release_resource(ar); -+ ath10k_modem_deinit(ar); - ath10k_qmi_deinit(ar); - ath10k_core_destroy(ar); - -diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h -index 5095d1893681b..d4bce17076960 100644 ---- a/drivers/net/wireless/ath/ath10k/snoc.h -+++ b/drivers/net/wireless/ath/ath10k/snoc.h -@@ -6,6 +6,8 @@ - #ifndef _SNOC_H_ - #define _SNOC_H_ - -+#include <linux/notifier.h> -+ - #include "hw.h" - #include "ce.h" - #include "qmi.h" -@@ -45,6 +47,7 @@ struct ath10k_snoc_ce_irq { - enum ath10k_snoc_flags { - ATH10K_SNOC_FLAG_REGISTERED, - ATH10K_SNOC_FLAG_UNREGISTERING, -+ ATH10K_SNOC_FLAG_MODEM_STOPPED, - ATH10K_SNOC_FLAG_RECOVERY, - ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, - }; -@@ -75,6 +78,8 @@ struct ath10k_snoc { - struct clk_bulk_data *clks; - size_t num_clks; - struct ath10k_qmi *qmi; -+ struct notifier_block nb; -+ void *notifier; - unsigned long flags; - bool xo_cal_supported; - u32 xo_cal_data; -diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c -index 19b9c27e30e20..3d98f19c6ec8a 100644 ---- a/drivers/net/wireless/ath/ath10k/usb.c -+++ b/drivers/net/wireless/ath/ath10k/usb.c -@@ -525,7 +525,7 @@ static int ath10k_usb_submit_ctrl_in(struct ath10k *ar, - req, - USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, buf, -- size, 2 * HZ); -+ size, 2000); - - if (ret < 0) { - ath10k_warn(ar, "Failed to read usb control message: %d\n", -@@ -853,6 +853,11 @@ static int ath10k_usb_setup_pipe_resources(struct ath10k *ar, - le16_to_cpu(endpoint->wMaxPacketSize), - endpoint->bInterval); - } -+ -+ /* Ignore broken descriptors. */ -+ if (usb_endpoint_maxp(endpoint) == 0) -+ continue; -+ - urbcount = 0; - - pipe_num = -diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c -index b8a4bbfe10b87..7c1c2658cb5f8 100644 ---- a/drivers/net/wireless/ath/ath10k/wmi.c -+++ b/drivers/net/wireless/ath/ath10k/wmi.c -@@ -2610,6 +2610,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) - if (ieee80211_is_beacon(hdr->frame_control)) - ath10k_mac_handle_beacon(ar, skb); - -+ if (ieee80211_is_beacon(hdr->frame_control) || -+ ieee80211_is_probe_resp(hdr->frame_control)) -+ status->boottime_ns = ktime_get_boottime_ns(); -+ - ath10k_dbg(ar, ATH10K_DBG_MGMT, - "event mgmt rx skb %pK len %d ftype %02x stype %02x\n", - skb, skb->len, -diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h -index 41c1a3d339c25..01bfd09a9d88c 100644 ---- a/drivers/net/wireless/ath/ath10k/wmi.h -+++ b/drivers/net/wireless/ath/ath10k/wmi.h -@@ -2066,7 +2066,9 @@ struct wmi_channel { - union { - __le32 reginfo1; - struct { -+ /* note: power unit is 1 dBm */ - u8 antenna_max; -+ /* note: power unit is 0.5 dBm */ - u8 max_tx_power; - } __packed; - } __packed; -@@ -2086,6 +2088,7 @@ struct wmi_channel_arg { - u32 min_power; - u32 max_power; - u32 max_reg_power; -+ /* note: power unit is 1 dBm */ - u32 max_antenna_gain; - u32 reg_class_id; - enum wmi_phy_mode mode; -diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireless/ath/ath11k/dbring.c -index 5e1f5437b4185..fd98ba5b1130b 100644 ---- a/drivers/net/wireless/ath/ath11k/dbring.c -+++ b/drivers/net/wireless/ath/ath11k/dbring.c -@@ -8,8 +8,7 @@ - - static int ath11k_dbring_bufs_replenish(struct ath11k *ar, - struct ath11k_dbring *ring, -- struct ath11k_dbring_element *buff, -- gfp_t gfp) -+ struct ath11k_dbring_element *buff) - { - struct ath11k_base *ab = ar->ab; - struct hal_srng *srng; -@@ -35,7 +34,7 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar, - goto err; - - spin_lock_bh(&ring->idr_lock); -- buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, gfp); -+ buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, GFP_ATOMIC); - spin_unlock_bh(&ring->idr_lock); - if (buf_id < 0) { - ret = -ENOBUFS; -@@ -72,8 +71,7 @@ err: - } - - static int ath11k_dbring_fill_bufs(struct ath11k *ar, -- struct ath11k_dbring *ring, -- gfp_t gfp) -+ struct ath11k_dbring *ring) - { - struct ath11k_dbring_element *buff; - struct hal_srng *srng; -@@ -92,11 +90,11 @@ static int ath11k_dbring_fill_bufs(struct ath11k *ar, - size = sizeof(*buff) + ring->buf_sz + align - 1; - - while (num_remain > 0) { -- buff = kzalloc(size, gfp); -+ buff = kzalloc(size, GFP_ATOMIC); - if (!buff) - break; - -- ret = ath11k_dbring_bufs_replenish(ar, ring, buff, gfp); -+ ret = ath11k_dbring_bufs_replenish(ar, ring, buff); - if (ret) { - ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n", - num_remain, req_entries); -@@ -176,7 +174,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar, - ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng); - ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng); - -- ret = ath11k_dbring_fill_bufs(ar, ring, GFP_KERNEL); -+ ret = ath11k_dbring_fill_bufs(ar, ring); - - return ret; - } -@@ -322,7 +320,7 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab, - } - - memset(buff, 0, size); -- ath11k_dbring_bufs_replenish(ar, ring, buff, GFP_ATOMIC); -+ ath11k_dbring_bufs_replenish(ar, ring, buff); - } - - spin_unlock_bh(&srng->lock); -diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c -index 9a224817630ae..0ae6bebff801d 100644 ---- a/drivers/net/wireless/ath/ath11k/dp_rx.c -+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c -@@ -2337,8 +2337,10 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, - channel_num = meta_data; - center_freq = meta_data >> 16; - -- if (center_freq >= 5935 && center_freq <= 7105) { -+ if (center_freq >= ATH11K_MIN_6G_FREQ && -+ center_freq <= ATH11K_MAX_6G_FREQ) { - rx_status->band = NL80211_BAND_6GHZ; -+ rx_status->freq = center_freq; - } else if (channel_num >= 1 && channel_num <= 14) { - rx_status->band = NL80211_BAND_2GHZ; - } else if (channel_num >= 36 && channel_num <= 173) { -@@ -2356,8 +2358,9 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, - rx_desc, sizeof(struct hal_rx_desc)); - } - -- rx_status->freq = ieee80211_channel_to_frequency(channel_num, -- rx_status->band); -+ if (rx_status->band != NL80211_BAND_6GHZ) -+ rx_status->freq = ieee80211_channel_to_frequency(channel_num, -+ rx_status->band); - - ath11k_dp_rx_h_rate(ar, rx_desc, rx_status); - } -@@ -3310,7 +3313,7 @@ static int ath11k_dp_rx_h_defrag_reo_reinject(struct ath11k *ar, struct dp_rx_ti - - paddr = dma_map_single(ab->dev, defrag_skb->data, - defrag_skb->len + skb_tailroom(defrag_skb), -- DMA_FROM_DEVICE); -+ DMA_TO_DEVICE); - if (dma_mapping_error(ab->dev, paddr)) - return -ENOMEM; - -@@ -3375,7 +3378,7 @@ err_free_idr: - spin_unlock_bh(&rx_refill_ring->idr_lock); - err_unmap_dma: - dma_unmap_single(ab->dev, paddr, defrag_skb->len + skb_tailroom(defrag_skb), -- DMA_FROM_DEVICE); -+ DMA_TO_DEVICE); - return ret; - } - -diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c -index e9b3689331ec2..89a64ebd620f3 100644 ---- a/drivers/net/wireless/ath/ath11k/mac.c -+++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -6590,7 +6590,7 @@ static int __ath11k_mac_register(struct ath11k *ar) - ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR); - - /* Apply the regd received during initialization */ -- ret = ath11k_regd_update(ar, true); -+ ret = ath11k_regd_update(ar); - if (ret) { - ath11k_err(ar->ab, "ath11k regd update failed: %d\n", ret); - goto err_unregister_hw; -diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c -index 26c7ae242db67..49c0b1ad40a02 100644 ---- a/drivers/net/wireless/ath/ath11k/mhi.c -+++ b/drivers/net/wireless/ath/ath11k/mhi.c -@@ -533,7 +533,11 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, - ret = mhi_pm_suspend(ab_pci->mhi_ctrl); - break; - case ATH11K_MHI_RESUME: -- ret = mhi_pm_resume(ab_pci->mhi_ctrl); -+ /* Do force MHI resume as some devices like QCA6390, WCN6855 -+ * are not in M3 state but they are functional. So just ignore -+ * the MHI state while resuming. -+ */ -+ ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); - break; - case ATH11K_MHI_TRIGGER_RDDM: - ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); -diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c -index b5e34d670715e..4c5071b7d11dc 100644 ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -2707,8 +2707,10 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) - list_del(&event->list); - spin_unlock(&qmi->event_lock); - -- if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)) -+ if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)) { -+ kfree(event); - return; -+ } - - switch (event->type) { - case ATH11K_QMI_EVENT_SERVER_ARRIVE: -diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c -index e1a1df169034b..92c59009a8ac2 100644 ---- a/drivers/net/wireless/ath/ath11k/reg.c -+++ b/drivers/net/wireless/ath/ath11k/reg.c -@@ -198,7 +198,7 @@ static void ath11k_copy_regd(struct ieee80211_regdomain *regd_orig, - sizeof(struct ieee80211_reg_rule)); - } - --int ath11k_regd_update(struct ath11k *ar, bool init) -+int ath11k_regd_update(struct ath11k *ar) - { - struct ieee80211_regdomain *regd, *regd_copy = NULL; - int ret, regd_len, pdev_id; -@@ -209,7 +209,10 @@ int ath11k_regd_update(struct ath11k *ar, bool init) - - spin_lock_bh(&ab->base_lock); - -- if (init) { -+ /* Prefer the latest regd update over default if it's available */ -+ if (ab->new_regd[pdev_id]) { -+ regd = ab->new_regd[pdev_id]; -+ } else { - /* Apply the regd received during init through - * WMI_REG_CHAN_LIST_CC event. In case of failure to - * receive the regd, initialize with a default world -@@ -222,8 +225,6 @@ int ath11k_regd_update(struct ath11k *ar, bool init) - "failed to receive default regd during init\n"); - regd = (struct ieee80211_regdomain *)&ath11k_world_regd; - } -- } else { -- regd = ab->new_regd[pdev_id]; - } - - if (!regd) { -@@ -683,7 +684,7 @@ void ath11k_regd_update_work(struct work_struct *work) - regd_update_work); - int ret; - -- ret = ath11k_regd_update(ar, false); -+ ret = ath11k_regd_update(ar); - if (ret) { - /* Firmware has already moved to the new regd. We need - * to maintain channel consistency across FW, Host driver -diff --git a/drivers/net/wireless/ath/ath11k/reg.h b/drivers/net/wireless/ath/ath11k/reg.h -index 65d56d44796f6..5fb9dc03a74e8 100644 ---- a/drivers/net/wireless/ath/ath11k/reg.h -+++ b/drivers/net/wireless/ath/ath11k/reg.h -@@ -31,6 +31,6 @@ void ath11k_regd_update_work(struct work_struct *work); - struct ieee80211_regdomain * - ath11k_reg_build_regd(struct ath11k_base *ab, - struct cur_regulatory_info *reg_info, bool intersect); --int ath11k_regd_update(struct ath11k *ar, bool init); -+int ath11k_regd_update(struct ath11k *ar); - int ath11k_reg_update_chan_list(struct ath11k *ar); - #endif -diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c -index 6c253eae9d069..99c0b81e496bf 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.c -+++ b/drivers/net/wireless/ath/ath11k/wmi.c -@@ -1339,6 +1339,7 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar, - WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST) | - FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); - cmd->req_type = type; -+ cmd->pdev_id = ar->pdev->pdev_id; - - ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "WMI bss chan info req type %d\n", type); -@@ -5792,6 +5793,17 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk - - pdev_idx = reg_info->phy_id; - -+ /* Avoid default reg rule updates sent during FW recovery if -+ * it is already available -+ */ -+ spin_lock(&ab->base_lock); -+ if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) && -+ ab->default_regd[pdev_idx]) { -+ spin_unlock(&ab->base_lock); -+ goto mem_free; -+ } -+ spin_unlock(&ab->base_lock); -+ - if (pdev_idx >= ab->num_radios) { - /* Process the event for phy0 only if single_pdev_only - * is true. If pdev_idx is valid but not 0, discard the -@@ -5829,10 +5841,10 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk - } - - spin_lock(&ab->base_lock); -- if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { -- /* Once mac is registered, ar is valid and all CC events from -- * fw is considered to be received due to user requests -- * currently. -+ if (ab->default_regd[pdev_idx]) { -+ /* The initial rules from FW after WMI Init is to build -+ * the default regd. From then on, any rules updated for -+ * the pdev could be due to user reg changes. - * Free previously built regd before assigning the newly - * generated regd to ar. NULL pointer handling will be - * taken care by kfree itself. -@@ -5842,13 +5854,9 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk - ab->new_regd[pdev_idx] = regd; - ieee80211_queue_work(ar->hw, &ar->regd_update_work); - } else { -- /* Multiple events for the same *ar is not expected. But we -- * can still clear any previously stored default_regd if we -- * are receiving this event for the same radio by mistake. -- * NULL pointer handling will be taken care by kfree itself. -+ /* This regd would be applied during mac registration and is -+ * held constant throughout for regd intersection purpose - */ -- kfree(ab->default_regd[pdev_idx]); -- /* This regd would be applied during mac registration */ - ab->default_regd[pdev_idx] = regd; - } - ab->dfs_region = reg_info->dfs_region; -@@ -6119,8 +6127,10 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) - if (rx_ev.status & WMI_RX_STATUS_ERR_MIC) - status->flag |= RX_FLAG_MMIC_ERROR; - -- if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ) { -+ if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ && -+ rx_ev.chan_freq <= ATH11K_MAX_6G_FREQ) { - status->band = NL80211_BAND_6GHZ; -+ status->freq = rx_ev.chan_freq; - } else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) { - status->band = NL80211_BAND_2GHZ; - } else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH11K_MAX_5G_CHAN) { -@@ -6141,8 +6151,10 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) - - sband = &ar->mac.sbands[status->band]; - -- status->freq = ieee80211_channel_to_frequency(rx_ev.channel, -- status->band); -+ if (status->band != NL80211_BAND_6GHZ) -+ status->freq = ieee80211_channel_to_frequency(rx_ev.channel, -+ status->band); -+ - status->signal = rx_ev.snr + ATH11K_DEFAULT_NOISE_FLOOR; - status->rate_idx = ath11k_mac_bitrate_to_idx(sband, rx_ev.rate / 100); - -@@ -6301,6 +6313,8 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb) - ath11k_wmi_event_scan_start_failed(ar); - break; - case WMI_SCAN_EVENT_DEQUEUED: -+ __ath11k_mac_scan_finish(ar); -+ break; - case WMI_SCAN_EVENT_PREEMPTED: - case WMI_SCAN_EVENT_RESTARTED: - case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT: -diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h -index d35c47e0b19d4..0b7d337b36930 100644 ---- a/drivers/net/wireless/ath/ath11k/wmi.h -+++ b/drivers/net/wireless/ath/ath11k/wmi.h -@@ -2960,6 +2960,7 @@ struct wmi_pdev_bss_chan_info_req_cmd { - u32 tlv_header; - /* ref wmi_bss_chan_info_req_type */ - u32 req_type; -+ u32 pdev_id; - } __packed; - - struct wmi_ap_ps_peer_cmd { -@@ -4056,7 +4057,6 @@ struct wmi_vdev_stopped_event { - } __packed; - - struct wmi_pdev_bss_chan_info_event { -- u32 pdev_id; - u32 freq; /* Units in MHz */ - u32 noise_floor; /* units are dBm */ - /* rx clear - how often the channel was unused */ -@@ -4074,6 +4074,7 @@ struct wmi_pdev_bss_chan_info_event { - /*rx_cycle cnt for my bss in 64bits format */ - u32 rx_bss_cycle_count_low; - u32 rx_bss_cycle_count_high; -+ u32 pdev_id; - } __packed; - - #define WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS 0 -diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c -index 5372e948e761d..aba70f35e574b 100644 ---- a/drivers/net/wireless/ath/ath6kl/usb.c -+++ b/drivers/net/wireless/ath/ath6kl/usb.c -@@ -340,6 +340,11 @@ static int ath6kl_usb_setup_pipe_resources(struct ath6kl_usb *ar_usb) - le16_to_cpu(endpoint->wMaxPacketSize), - endpoint->bInterval); - } -+ -+ /* Ignore broken descriptors. */ -+ if (usb_endpoint_maxp(endpoint) == 0) -+ continue; -+ - urbcount = 0; - - pipe_num = -@@ -907,7 +912,7 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, - req, - USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, value, index, buf, -- size, 2 * HZ); -+ size, 2000); - - if (ret < 0) { - ath6kl_warn("Failed to read usb control message: %d\n", ret); -diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c -index 139831539da37..98090e40e1cf4 100644 ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -533,8 +533,10 @@ irqreturn_t ath_isr(int irq, void *dev) - ath9k_debug_sync_cause(sc, sync_cause); - status &= ah->imask; /* discard unasked-for bits */ - -- if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) -+ if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) { -+ ath9k_hw_kill_interrupts(sc->sc_ah); - return IRQ_HANDLED; -+ } - - /* - * If there are no status bits set, then this interrupt was not -diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c -index 80390495ea250..75cb53a3ec15e 100644 ---- a/drivers/net/wireless/ath/dfs_pattern_detector.c -+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c -@@ -183,10 +183,12 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd, - if (cd == NULL) - return; - list_del(&cd->head); -- for (i = 0; i < dpd->num_radar_types; i++) { -- struct pri_detector *de = cd->detectors[i]; -- if (de != NULL) -- de->exit(de); -+ if (cd->detectors) { -+ for (i = 0; i < dpd->num_radar_types; i++) { -+ struct pri_detector *de = cd->detectors[i]; -+ if (de != NULL) -+ de->exit(de); -+ } - } - kfree(cd->detectors); - kfree(cd); -diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c -index 8e1dbfda65386..aff04ef662663 100644 ---- a/drivers/net/wireless/ath/wcn36xx/dxe.c -+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c -@@ -403,8 +403,21 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) - dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, - ctl->skb->len, DMA_TO_DEVICE); - info = IEEE80211_SKB_CB(ctl->skb); -- if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { -- /* Keep frame until TX status comes */ -+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { -+ if (info->flags & IEEE80211_TX_CTL_NO_ACK) { -+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; -+ ieee80211_tx_status_irqsafe(wcn->hw, ctl->skb); -+ } else { -+ /* Wait for the TX ack indication or timeout... */ -+ spin_lock(&wcn->dxe_lock); -+ if (WARN_ON(wcn->tx_ack_skb)) -+ ieee80211_free_txskb(wcn->hw, wcn->tx_ack_skb); -+ wcn->tx_ack_skb = ctl->skb; /* Tracking ref */ -+ mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10); -+ spin_unlock(&wcn->dxe_lock); -+ } -+ /* do not free, ownership transferred to mac80211 status cb */ -+ } else { - ieee80211_free_txskb(wcn->hw, ctl->skb); - } - -@@ -426,7 +439,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) - { - struct wcn36xx *wcn = (struct wcn36xx *)dev; - int int_src, int_reason; -- bool transmitted = false; - - wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); - -@@ -466,7 +478,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) - if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | - WCN36XX_CH_STAT_INT_ED_MASK)) { - reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); -- transmitted = true; - } - } - -@@ -479,7 +490,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) - WCN36XX_DXE_0_INT_CLR, - WCN36XX_INT_MASK_CHAN_TX_L); - -- - if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { - wcn36xx_dxe_write_register(wcn, - WCN36XX_DXE_0_INT_ERR_CLR, -@@ -507,25 +517,8 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) - if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | - WCN36XX_CH_STAT_INT_ED_MASK)) { - reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); -- transmitted = true; -- } -- } -- -- spin_lock(&wcn->dxe_lock); -- if (wcn->tx_ack_skb && transmitted) { -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(wcn->tx_ack_skb); -- -- /* TX complete, no need to wait for 802.11 ack indication */ -- if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS && -- info->flags & IEEE80211_TX_CTL_NO_ACK) { -- info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; -- del_timer(&wcn->tx_ack_timer); -- ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); -- wcn->tx_ack_skb = NULL; -- ieee80211_wake_queues(wcn->hw); - } - } -- spin_unlock(&wcn->dxe_lock); - - return IRQ_HANDLED; - } -@@ -613,6 +606,10 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, - dxe = ctl->desc; - - while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) { -+ /* do not read until we own DMA descriptor */ -+ dma_rmb(); -+ -+ /* read/modify DMA descriptor */ - skb = ctl->skb; - dma_addr = dxe->dst_addr_l; - ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl, GFP_ATOMIC); -@@ -623,9 +620,15 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, - dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE, - DMA_FROM_DEVICE); - wcn36xx_rx_skb(wcn, skb); -- } /* else keep old skb not submitted and use it for rx DMA */ -+ } -+ /* else keep old skb not submitted and reuse it for rx DMA -+ * (dropping the packet that it contained) -+ */ - -+ /* flush descriptor changes before re-marking as valid */ -+ dma_wmb(); - dxe->ctrl = ctrl; -+ - ctl = ctl->next; - dxe = ctl->desc; - } -diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h -index 455143c4164ee..de3bca043c2b3 100644 ---- a/drivers/net/wireless/ath/wcn36xx/hal.h -+++ b/drivers/net/wireless/ath/wcn36xx/hal.h -@@ -359,6 +359,8 @@ enum wcn36xx_hal_host_msg_type { - WCN36XX_HAL_START_SCAN_OFFLOAD_RSP = 205, - WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ = 206, - WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP = 207, -+ WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ = 208, -+ WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP = 209, - WCN36XX_HAL_SCAN_OFFLOAD_IND = 210, - - WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233, -@@ -1353,6 +1355,36 @@ struct wcn36xx_hal_stop_scan_offload_rsp_msg { - u32 status; - } __packed; - -+#define WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK 0x000000ff -+#define WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK 0x0000ff00 -+#define WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK 0x00ff0000 -+#define WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK 0xff000000 -+#define WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK 0x000000ff -+#define WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE BIT(7) -+#define WCN36XX_HAL_CHAN_INFO_FLAG_DFS BIT(10) -+#define WCN36XX_HAL_CHAN_INFO_FLAG_HT BIT(11) -+#define WCN36XX_HAL_CHAN_INFO_FLAG_VHT BIT(12) -+#define WCN36XX_HAL_CHAN_INFO_PHY_11A 0 -+#define WCN36XX_HAL_CHAN_INFO_PHY_11BG 1 -+#define WCN36XX_HAL_DEFAULT_ANT_GAIN 6 -+#define WCN36XX_HAL_DEFAULT_MIN_POWER 6 -+ -+struct wcn36xx_hal_channel_param { -+ u32 mhz; -+ u32 band_center_freq1; -+ u32 band_center_freq2; -+ u32 channel_info; -+ u32 reg_info_1; -+ u32 reg_info_2; -+} __packed; -+ -+struct wcn36xx_hal_update_channel_list_req_msg { -+ struct wcn36xx_hal_msg_header header; -+ -+ u8 num_channel; -+ struct wcn36xx_hal_channel_param channels[80]; -+} __packed; -+ - enum wcn36xx_hal_rate_index { - HW_RATE_INDEX_1MBPS = 0x82, - HW_RATE_INDEX_2MBPS = 0x84, -diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c -index ec913ec991f3f..5d82aca370a72 100644 ---- a/drivers/net/wireless/ath/wcn36xx/main.c -+++ b/drivers/net/wireless/ath/wcn36xx/main.c -@@ -135,7 +135,9 @@ static struct ieee80211_supported_band wcn_band_2ghz = { - .cap = IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | -- IEEE80211_HT_CAP_LSIG_TXOP_PROT, -+ IEEE80211_HT_CAP_LSIG_TXOP_PROT | -+ IEEE80211_HT_CAP_SGI_40 | -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40, - .ht_supported = true, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, -@@ -569,12 +571,14 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { - sta_priv->is_data_encrypted = true; - /* Reconfigure bss with encrypt_type */ -- if (NL80211_IFTYPE_STATION == vif->type) -+ if (NL80211_IFTYPE_STATION == vif->type) { - wcn36xx_smd_config_bss(wcn, - vif, - sta, - sta->addr, - true); -+ wcn36xx_smd_config_sta(wcn, vif, sta); -+ } - - wcn36xx_smd_set_stakey(wcn, - vif_priv->encrypt_type, -@@ -604,15 +608,6 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - } - } - } -- /* FIXME: Only enable bmps support when encryption is enabled. -- * For any reasons, when connected to open/no-security BSS, -- * the wcn36xx controller in bmps mode does not forward -- * 'wake-up' beacons despite AP sends DTIM with station AID. -- * It could be due to a firmware issue or to the way driver -- * configure the station. -- */ -- if (vif->type == NL80211_IFTYPE_STATION) -- vif_priv->allow_bmps = true; - break; - case DISABLE_KEY: - if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { -@@ -676,6 +671,7 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw, - - mutex_unlock(&wcn->scan_lock); - -+ wcn36xx_smd_update_channel_list(wcn, &hw_req->req); - return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req); - } - -@@ -913,7 +909,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, - vif->addr, - bss_conf->aid); - vif_priv->sta_assoc = false; -- vif_priv->allow_bmps = false; - wcn36xx_smd_set_link_st(wcn, - bss_conf->bssid, - vif->addr, -@@ -1123,6 +1118,13 @@ static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) - goto out; - ret = wcn36xx_smd_wlan_host_suspend_ind(wcn); - } -+ -+ /* Disable IRQ, we don't want to handle any packet before mac80211 is -+ * resumed and ready to receive packets. -+ */ -+ disable_irq(wcn->tx_irq); -+ disable_irq(wcn->rx_irq); -+ - out: - mutex_unlock(&wcn->conf_mutex); - return ret; -@@ -1145,6 +1147,10 @@ static int wcn36xx_resume(struct ieee80211_hw *hw) - wcn36xx_smd_ipv6_ns_offload(wcn, vif, false); - wcn36xx_smd_arp_offload(wcn, vif, false); - } -+ -+ enable_irq(wcn->tx_irq); -+ enable_irq(wcn->rx_irq); -+ - mutex_unlock(&wcn->conf_mutex); - - return 0; -@@ -1338,7 +1344,6 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) - ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); - ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS); - ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS); -- ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR); - - wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | -diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c -index 2d0780fefd477..2936aaf532738 100644 ---- a/drivers/net/wireless/ath/wcn36xx/pmc.c -+++ b/drivers/net/wireless/ath/wcn36xx/pmc.c -@@ -23,10 +23,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, - { - int ret = 0; - struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); -- -- if (!vif_priv->allow_bmps) -- return -ENOTSUPP; -- -+ /* TODO: Make sure the TX chain clean */ - ret = wcn36xx_smd_enter_bmps(wcn, vif); - if (!ret) { - wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); -diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c -index 57fa857b290b7..70bffe3d87a12 100644 ---- a/drivers/net/wireless/ath/wcn36xx/smd.c -+++ b/drivers/net/wireless/ath/wcn36xx/smd.c -@@ -16,6 +16,7 @@ - - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -+#include <linux/bitfield.h> - #include <linux/etherdevice.h> - #include <linux/firmware.h> - #include <linux/bitops.h> -@@ -927,6 +928,86 @@ out: - return ret; - } - -+int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req) -+{ -+ struct wcn36xx_hal_update_channel_list_req_msg *msg_body; -+ int ret, i; -+ -+ msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL); -+ if (!msg_body) -+ return -ENOMEM; -+ -+ INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ); -+ -+ msg_body->num_channel = min_t(u8, req->n_channels, sizeof(msg_body->channels)); -+ for (i = 0; i < msg_body->num_channel; i++) { -+ struct wcn36xx_hal_channel_param *param = &msg_body->channels[i]; -+ u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER; -+ u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN; -+ -+ param->mhz = req->channels[i]->center_freq; -+ param->band_center_freq1 = req->channels[i]->center_freq; -+ param->band_center_freq2 = 0; -+ -+ if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) -+ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE; -+ -+ if (req->channels[i]->flags & IEEE80211_CHAN_RADAR) -+ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS; -+ -+ if (req->channels[i]->band == NL80211_BAND_5GHZ) { -+ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT; -+ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT; -+ param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A; -+ } else { -+ param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG; -+ } -+ -+ if (min_power > req->channels[i]->max_power) -+ min_power = req->channels[i]->max_power; -+ -+ if (req->channels[i]->max_antenna_gain) -+ ant_gain = req->channels[i]->max_antenna_gain; -+ -+ u32p_replace_bits(¶m->reg_info_1, min_power, -+ WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK); -+ u32p_replace_bits(¶m->reg_info_1, req->channels[i]->max_power, -+ WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK); -+ u32p_replace_bits(¶m->reg_info_1, req->channels[i]->max_reg_power, -+ WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK); -+ u32p_replace_bits(¶m->reg_info_1, 0, -+ WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK); -+ u32p_replace_bits(¶m->reg_info_2, ant_gain, -+ WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK); -+ -+ wcn36xx_dbg(WCN36XX_DBG_HAL, -+ "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n", -+ __func__, param->mhz, param->channel_info, param->reg_info_1, -+ param->reg_info_2); -+ } -+ -+ mutex_lock(&wcn->hal_mutex); -+ -+ PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body)); -+ -+ ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); -+ if (ret) { -+ wcn36xx_err("Sending hal_update_channel_list failed\n"); -+ goto out; -+ } -+ -+ ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); -+ if (ret) { -+ wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret); -+ goto out; -+ } -+ -+out: -+ kfree(msg_body); -+ mutex_unlock(&wcn->hal_mutex); -+ return ret; -+} -+ - static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) - { - struct wcn36xx_hal_switch_channel_rsp_msg *rsp; -@@ -2623,30 +2704,52 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, - size_t len) - { - struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; -- struct wcn36xx_vif *tmp; -+ struct wcn36xx_vif *vif_priv; -+ struct ieee80211_vif *vif; -+ struct ieee80211_bss_conf *bss_conf; - struct ieee80211_sta *sta; -+ bool found = false; - - if (len != sizeof(*rsp)) { - wcn36xx_warn("Corrupted delete sta indication\n"); - return -EIO; - } - -- wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n", -- rsp->addr2, rsp->sta_id); -+ wcn36xx_dbg(WCN36XX_DBG_HAL, -+ "delete station indication %pM index %d reason %d\n", -+ rsp->addr2, rsp->sta_id, rsp->reason_code); - -- list_for_each_entry(tmp, &wcn->vif_list, list) { -+ list_for_each_entry(vif_priv, &wcn->vif_list, list) { - rcu_read_lock(); -- sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2); -- if (sta) -- ieee80211_report_low_ack(sta, 0); -+ vif = wcn36xx_priv_to_vif(vif_priv); -+ -+ if (vif->type == NL80211_IFTYPE_STATION) { -+ /* We could call ieee80211_find_sta too, but checking -+ * bss_conf is clearer. -+ */ -+ bss_conf = &vif->bss_conf; -+ if (vif_priv->sta_assoc && -+ !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) { -+ found = true; -+ wcn36xx_dbg(WCN36XX_DBG_HAL, -+ "connection loss bss_index %d\n", -+ vif_priv->bss_index); -+ ieee80211_connection_loss(vif); -+ } -+ } else { -+ sta = ieee80211_find_sta(vif, rsp->addr2); -+ if (sta) { -+ found = true; -+ ieee80211_report_low_ack(sta, 0); -+ } -+ } -+ - rcu_read_unlock(); -- if (sta) -+ if (found) - return 0; - } - -- wcn36xx_warn("STA with addr %pM and index %d not found\n", -- rsp->addr2, -- rsp->sta_id); -+ wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2); - return -ENOENT; - } - -@@ -3060,6 +3163,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, - case WCN36XX_HAL_GTK_OFFLOAD_RSP: - case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP: - case WCN36XX_HAL_HOST_RESUME_RSP: -+ case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP: - memcpy(wcn->hal_buf, buf, len); - wcn->hal_rsp_len = len; - complete(&wcn->hal_rsp_compl); -diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h -index d8bded03945d4..d3774568d885e 100644 ---- a/drivers/net/wireless/ath/wcn36xx/smd.h -+++ b/drivers/net/wireless/ath/wcn36xx/smd.h -@@ -70,6 +70,7 @@ int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t cha - int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif, - struct cfg80211_scan_request *req); - int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn); -+int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req); - int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif); - int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr); - int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index); -diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c -index cab196bb38cd4..bbd7194c82e27 100644 ---- a/drivers/net/wireless/ath/wcn36xx/txrx.c -+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c -@@ -31,6 +31,13 @@ struct wcn36xx_rate { - enum rate_info_bw bw; - }; - -+/* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used -+ * for 11A Channels. -+ */ -+static const u8 ab_rx_ch_map[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, -+ 108, 112, 116, 120, 124, 128, 132, 136, 140, -+ 149, 153, 157, 161, 165, 144 }; -+ - static const struct wcn36xx_rate wcn36xx_rate_table[] = { - /* 11b rates */ - { 10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, -@@ -291,6 +298,22 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) - ieee80211_is_probe_resp(hdr->frame_control)) - status.boottime_ns = ktime_get_boottime_ns(); - -+ if (bd->scan_learn) { -+ /* If packet originates from hardware scanning, extract the -+ * band/channel from bd descriptor. -+ */ -+ u8 hwch = (bd->reserved0 << 4) + bd->rx_ch; -+ -+ if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) { -+ status.band = NL80211_BAND_5GHZ; -+ status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1], -+ status.band); -+ } else { -+ status.band = NL80211_BAND_2GHZ; -+ status.freq = ieee80211_channel_to_frequency(hwch, status.band); -+ } -+ } -+ - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - - if (ieee80211_is_beacon(hdr->frame_control)) { -@@ -321,8 +344,6 @@ static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, - bd->pdu.mpdu_header_off; - bd->pdu.mpdu_len = len; - bd->pdu.tid = tid; -- /* Use seq number generated by mac80211 */ -- bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST; - } - - static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, -@@ -419,6 +440,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, - tid = ieee80211_get_tid(hdr); - /* TID->QID is one-to-one mapping */ - bd->queue_id = tid; -+ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS; -+ } else { -+ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS; - } - - if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT || -@@ -429,6 +453,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, - if (ieee80211_is_any_nullfunc(hdr->frame_control)) { - /* Don't use a regular queue for null packet (no ampdu) */ - bd->queue_id = WCN36XX_TX_U_WQ_ID; -+ bd->bd_rate = WCN36XX_BD_RATE_CTRL; -+ if (ieee80211_is_qos_nullfunc(hdr->frame_control)) -+ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST; - } - - if (bcast) { -@@ -488,6 +515,8 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, - bd->queue_id = WCN36XX_TX_U_WQ_ID; - *vif_priv = __vif_priv; - -+ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS; -+ - wcn36xx_set_tx_pdu(bd, - ieee80211_is_data_qos(hdr->frame_control) ? - sizeof(struct ieee80211_qos_hdr) : -@@ -502,10 +531,11 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct wcn36xx_vif *vif_priv = NULL; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- unsigned long flags; - bool is_low = ieee80211_is_data(hdr->frame_control); - bool bcast = is_broadcast_ether_addr(hdr->addr1) || - is_multicast_ether_addr(hdr->addr1); -+ bool ack_ind = (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) && -+ !(info->flags & IEEE80211_TX_CTL_NO_ACK); - struct wcn36xx_tx_bd bd; - int ret; - -@@ -521,30 +551,16 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, - - bd.dpu_rf = WCN36XX_BMU_WQ_TX; - -- if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { -+ if (unlikely(ack_ind)) { - wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); - -- spin_lock_irqsave(&wcn->dxe_lock, flags); -- if (wcn->tx_ack_skb) { -- spin_unlock_irqrestore(&wcn->dxe_lock, flags); -- wcn36xx_warn("tx_ack_skb already set\n"); -- return -EINVAL; -- } -- -- wcn->tx_ack_skb = skb; -- spin_unlock_irqrestore(&wcn->dxe_lock, flags); -- - /* Only one at a time is supported by fw. Stop the TX queues - * until the ack status gets back. - */ - ieee80211_stop_queues(wcn->hw); - -- /* TX watchdog if no TX irq or ack indication received */ -- mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10); -- - /* Request ack indication from the firmware */ -- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) -- bd.tx_comp = 1; -+ bd.tx_comp = 1; - } - - /* Data frames served first*/ -@@ -558,14 +574,8 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, - bd.tx_bd_sign = 0xbdbdbdbd; - - ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low); -- if (ret && (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { -- /* If the skb has not been transmitted, -- * don't keep a reference to it. -- */ -- spin_lock_irqsave(&wcn->dxe_lock, flags); -- wcn->tx_ack_skb = NULL; -- spin_unlock_irqrestore(&wcn->dxe_lock, flags); -- -+ if (unlikely(ret && ack_ind)) { -+ /* If the skb has not been transmitted, resume TX queue */ - ieee80211_wake_queues(wcn->hw); - } - -diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h -index 032216e82b2be..b54311ffde9c5 100644 ---- a/drivers/net/wireless/ath/wcn36xx/txrx.h -+++ b/drivers/net/wireless/ath/wcn36xx/txrx.h -@@ -110,7 +110,8 @@ struct wcn36xx_rx_bd { - /* 0x44 */ - u32 exp_seq_num:12; - u32 cur_seq_num:12; -- u32 fr_type_subtype:8; -+ u32 rf_band:2; -+ u32 fr_type_subtype:6; - - /* 0x48 */ - u32 msdu_size:16; -diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h -index add6e527e8330..e9560f35e9bcf 100644 ---- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h -+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h -@@ -128,7 +128,6 @@ struct wcn36xx_vif { - enum wcn36xx_hal_bss_type bss_type; - - /* Power management */ -- bool allow_bmps; - enum wcn36xx_power_state pw_state; - - u8 bss_index; -diff --git a/drivers/net/wireless/broadcom/b43/phy_g.c b/drivers/net/wireless/broadcom/b43/phy_g.c -index d5a1a5c582366..ac72ca39e409b 100644 ---- a/drivers/net/wireless/broadcom/b43/phy_g.c -+++ b/drivers/net/wireless/broadcom/b43/phy_g.c -@@ -2297,7 +2297,7 @@ static u8 b43_gphy_aci_scan(struct b43_wldev *dev) - b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF); - b43_set_all_gains(dev, 3, 8, 1); - -- start = (channel - 5 > 0) ? channel - 5 : 1; -+ start = (channel > 5) ? channel - 5 : 1; - end = (channel + 5 < 14) ? channel + 5 : 13; - - for (i = start; i <= end; i++) { -diff --git a/drivers/net/wireless/broadcom/b43legacy/radio.c b/drivers/net/wireless/broadcom/b43legacy/radio.c -index 06891b4f837b9..fdf78c10a05c2 100644 ---- a/drivers/net/wireless/broadcom/b43legacy/radio.c -+++ b/drivers/net/wireless/broadcom/b43legacy/radio.c -@@ -283,7 +283,7 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev) - & 0x7FFF); - b43legacy_set_all_gains(dev, 3, 8, 1); - -- start = (channel - 5 > 0) ? channel - 5 : 1; -+ start = (channel > 5) ? channel - 5 : 1; - end = (channel + 5 < 14) ? channel + 5 : 13; - - for (i = start; i <= end; i++) { -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c -index 6d5188b78f2de..0af452dca7664 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c -@@ -75,6 +75,16 @@ static const struct dmi_system_id dmi_platform_data[] = { - }, - .driver_data = (void *)&acepc_t8_data, - }, -+ { -+ /* Cyberbook T116 rugged tablet */ -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"), -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "20170531"), -+ }, -+ /* The factory image nvram file is identical to the ACEPC T8 one */ -+ .driver_data = (void *)&acepc_t8_data, -+ }, - { - /* Match for the GPDwin which unfortunately uses somewhat - * generic dmi strings, which is why we test for 4 strings. -diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c -index dde22bdc87039..069fcbc46d2ba 100644 ---- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c -+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c -@@ -284,16 +284,19 @@ int iwl_pnvm_load(struct iwl_trans *trans, - /* First attempt to get the PNVM from BIOS */ - package = iwl_uefi_get_pnvm(trans, &len); - if (!IS_ERR_OR_NULL(package)) { -- data = kmemdup(package->data, len, GFP_KERNEL); -+ if (len >= sizeof(*package)) { -+ /* we need only the data */ -+ len -= sizeof(*package); -+ data = kmemdup(package->data, len, GFP_KERNEL); -+ } else { -+ data = NULL; -+ } - - /* free package regardless of whether kmemdup succeeded */ - kfree(package); - -- if (data) { -- /* we need only the data size */ -- len -= sizeof(*package); -+ if (data) - goto parse; -- } - } - - /* If it's not available, try from the filesystem */ -diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c -index c875bf35533ce..009dd4be597b0 100644 ---- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c -+++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c -@@ -86,6 +86,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, - if (len < tlv_len) { - IWL_ERR(trans, "invalid TLV len: %zd/%u\n", - len, tlv_len); -+ kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-EINVAL); - goto out; - } -@@ -105,6 +106,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, - IWL_DEBUG_FW(trans, - "Couldn't allocate (more) reduce_power_data\n"); - -+ kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOMEM); - goto out; - } -@@ -134,6 +136,10 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, - done: - if (!size) { - IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); -+ /* Better safe than sorry, but 'reduce_power_data' should -+ * always be NULL if !size. -+ */ -+ kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOENT); - goto out; - } -diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c -index 77124b8b235ee..94553f272d377 100644 ---- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c -+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c -@@ -1271,23 +1271,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) - const struct iwl_op_mode_ops *ops = op->ops; - struct dentry *dbgfs_dir = NULL; - struct iwl_op_mode *op_mode = NULL; -+ int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY; -+ -+ for (retry = 0; retry <= max_retry; retry++) { - - #ifdef CONFIG_IWLWIFI_DEBUGFS -- drv->dbgfs_op_mode = debugfs_create_dir(op->name, -- drv->dbgfs_drv); -- dbgfs_dir = drv->dbgfs_op_mode; -+ drv->dbgfs_op_mode = debugfs_create_dir(op->name, -+ drv->dbgfs_drv); -+ dbgfs_dir = drv->dbgfs_op_mode; - #endif - -- op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir); -+ op_mode = ops->start(drv->trans, drv->trans->cfg, -+ &drv->fw, dbgfs_dir); -+ -+ if (op_mode) -+ return op_mode; -+ -+ IWL_ERR(drv, "retry init count %d\n", retry); - - #ifdef CONFIG_IWLWIFI_DEBUGFS -- if (!op_mode) { - debugfs_remove_recursive(drv->dbgfs_op_mode); - drv->dbgfs_op_mode = NULL; -- } - #endif -+ } - -- return op_mode; -+ return NULL; - } - - static void _iwl_op_mode_stop(struct iwl_drv *drv) -diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h -index b6442df0c6439..56f2fd3b94906 100644 ---- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h -+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h -@@ -90,4 +90,7 @@ void iwl_drv_stop(struct iwl_drv *drv); - #define IWL_EXPORT_SYMBOL(sym) - #endif - -+/* max retry for init flow */ -+#define IWL_MAX_INIT_RETRY 2 -+ - #endif /* __iwl_drv_h__ */ -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c -index 9f706fffb5922..d3013a51a5096 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c -@@ -2336,7 +2336,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) - iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, - false, 0); - ret = 1; -- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; - goto err; - } - -@@ -2385,6 +2384,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) - } - } - -+ /* after the successful handshake, we're out of D3 */ - mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; - - /* -@@ -2455,6 +2455,9 @@ out: - */ - set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); - -+ /* regardless of what happened, we're now out of D3 */ -+ mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; -+ - return 1; - } - -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c -index 3a4585222d6d4..7e5ad943b20cb 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c -@@ -16,6 +16,7 @@ - #include <net/ieee80211_radiotap.h> - #include <net/tcp.h> - -+#include "iwl-drv.h" - #include "iwl-op-mode.h" - #include "iwl-io.h" - #include "mvm.h" -@@ -1116,9 +1117,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) - { - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - int ret; -+ int retry, max_retry = 0; - - mutex_lock(&mvm->mutex); -- ret = __iwl_mvm_mac_start(mvm); -+ -+ /* we are starting the mac not in error flow, and restart is enabled */ -+ if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) && -+ iwlwifi_mod_params.fw_restart) { -+ max_retry = IWL_MAX_INIT_RETRY; -+ /* -+ * This will prevent mac80211 recovery flows to trigger during -+ * init failures -+ */ -+ set_bit(IWL_MVM_STATUS_STARTING, &mvm->status); -+ } -+ -+ for (retry = 0; retry <= max_retry; retry++) { -+ ret = __iwl_mvm_mac_start(mvm); -+ if (!ret) -+ break; -+ -+ IWL_ERR(mvm, "mac start retry %d\n", retry); -+ } -+ clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status); -+ - mutex_unlock(&mvm->mutex); - - return ret; -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h -index f877d86b038e3..46af8dd2dc930 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h -@@ -1121,6 +1121,8 @@ struct iwl_mvm { - * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running - * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA - * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) -+ * @IWL_MVM_STATUS_STARTING: starting mac, -+ * used to disable restart flow while in STARTING state - */ - enum iwl_mvm_status { - IWL_MVM_STATUS_HW_RFKILL, -@@ -1132,6 +1134,7 @@ enum iwl_mvm_status { - IWL_MVM_STATUS_FIRMWARE_RUNNING, - IWL_MVM_STATUS_NEED_FLUSH_P2P, - IWL_MVM_STATUS_IN_D3, -+ IWL_MVM_STATUS_STARTING, - }; - - /* Keep track of completed init configuration */ -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c -index 77ea2d0a30916..49c32a8132a0f 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c -@@ -687,6 +687,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) - int ret; - - rtnl_lock(); -+ wiphy_lock(mvm->hw->wiphy); - mutex_lock(&mvm->mutex); - - ret = iwl_run_init_mvm_ucode(mvm); -@@ -702,6 +703,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) - iwl_mvm_stop_device(mvm); - - mutex_unlock(&mvm->mutex); -+ wiphy_unlock(mvm->hw->wiphy); - rtnl_unlock(); - - if (ret < 0) -@@ -1424,6 +1426,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) - */ - if (!mvm->fw_restart && fw_error) { - iwl_fw_error_collect(&mvm->fwrt, false); -+ } else if (test_bit(IWL_MVM_STATUS_STARTING, -+ &mvm->status)) { -+ IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n"); - } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { - struct iwl_mvm_reprobe *reprobe; - -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -index 0a13c2bda2eed..06fbd9ab37dfe 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c -@@ -268,17 +268,18 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, - int rate_idx = -1; - u8 rate_plcp; - u32 rate_flags = 0; -- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - - /* info->control is only relevant for non HW rate control */ - if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) { -+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); -+ - /* HT rate doesn't make sense for a non data frame */ - WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS && - !ieee80211_is_data(fc), - "Got a HT rate (flags:0x%x/mcs:%d/fc:0x%x/state:%d) for a non data frame\n", - info->control.rates[0].flags, - info->control.rates[0].idx, -- le16_to_cpu(fc), mvmsta->sta_state); -+ le16_to_cpu(fc), sta ? mvmsta->sta_state : -1); - - rate_idx = info->control.rates[0].idx; - } -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c -index 4a3d2971a98b7..ec8a223f90e85 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c -@@ -405,6 +405,9 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm, - - lockdep_assert_held(&mvm->mutex); - -+ if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) -+ return false; -+ - if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1) - return false; - -diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c -index e3996ff99bad5..3b974388d834d 100644 ---- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c -+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c -@@ -931,9 +931,9 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { - IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_qu_b0_hr1_b0, iwl_ax101_name), - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, -- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, -+ IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, -- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, -+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_qu_b0_hr_b0, iwl_ax203_name), - - /* Qu C step */ -@@ -945,7 +945,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { - _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, - IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, - IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, -- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, -+ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_qu_c0_hr_b0, iwl_ax203_name), - - /* QuZ */ -diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c -index 20436a289d5cd..5d6dc1dd050d4 100644 ---- a/drivers/net/wireless/marvell/libertas/if_usb.c -+++ b/drivers/net/wireless/marvell/libertas/if_usb.c -@@ -292,6 +292,7 @@ err_add_card: - if_usb_reset_device(cardp); - dealloc: - if_usb_free(cardp); -+ kfree(cardp); - - error: - return r; -@@ -316,6 +317,7 @@ static void if_usb_disconnect(struct usb_interface *intf) - - /* Unlink and free urb */ - if_usb_free(cardp); -+ kfree(cardp); - - usb_set_intfdata(intf, NULL); - usb_put_dev(interface_to_usbdev(intf)); -diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c -index fe0a69e804d8c..75b5319d033f3 100644 ---- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c -+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c -@@ -230,6 +230,7 @@ static int if_usb_probe(struct usb_interface *intf, - - dealloc: - if_usb_free(cardp); -+ kfree(cardp); - error: - lbtf_deb_leave(LBTF_DEB_MAIN); - return -ENOMEM; -@@ -254,6 +255,7 @@ static void if_usb_disconnect(struct usb_interface *intf) - - /* Unlink and free urb */ - if_usb_free(cardp); -+ kfree(cardp); - - usb_set_intfdata(intf, NULL); - usb_put_dev(interface_to_usbdev(intf)); -diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c -index 6696bce561786..cf08a4af84d6d 100644 ---- a/drivers/net/wireless/marvell/mwifiex/11n.c -+++ b/drivers/net/wireless/marvell/mwifiex/11n.c -@@ -657,14 +657,15 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, - uint16_t del_ba_param_set; - - memset(&delba, 0, sizeof(delba)); -- delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); - -- del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); -+ del_ba_param_set = tid << DELBA_TID_POS; -+ - if (initiator) - del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; - else - del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; - -+ delba.del_ba_param_set = cpu_to_le16(del_ba_param_set); - memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); - - /* We don't wait for the response of this command */ -diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c -index 0961f4a5e415c..97f0f39364d67 100644 ---- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c -+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c -@@ -908,16 +908,20 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, - switch (type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: -- priv->bss_role = MWIFIEX_BSS_ROLE_STA; -+ priv->bss_role = MWIFIEX_BSS_ROLE_STA; -+ priv->bss_type = MWIFIEX_BSS_TYPE_STA; - break; - case NL80211_IFTYPE_P2P_CLIENT: -- priv->bss_role = MWIFIEX_BSS_ROLE_STA; -+ priv->bss_role = MWIFIEX_BSS_ROLE_STA; -+ priv->bss_type = MWIFIEX_BSS_TYPE_P2P; - break; - case NL80211_IFTYPE_P2P_GO: -- priv->bss_role = MWIFIEX_BSS_ROLE_UAP; -+ priv->bss_role = MWIFIEX_BSS_ROLE_UAP; -+ priv->bss_type = MWIFIEX_BSS_TYPE_P2P; - break; - case NL80211_IFTYPE_AP: - priv->bss_role = MWIFIEX_BSS_ROLE_UAP; -+ priv->bss_type = MWIFIEX_BSS_TYPE_UAP; - break; - default: - mwifiex_dbg(adapter, ERROR, -@@ -1229,29 +1233,15 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: -+ if (mwifiex_cfg80211_deinit_p2p(priv)) -+ return -EFAULT; -+ - switch (type) { -- case NL80211_IFTYPE_STATION: -- if (mwifiex_cfg80211_deinit_p2p(priv)) -- return -EFAULT; -- priv->adapter->curr_iface_comb.p2p_intf--; -- priv->adapter->curr_iface_comb.sta_intf++; -- dev->ieee80211_ptr->iftype = type; -- if (mwifiex_deinit_priv_params(priv)) -- return -1; -- if (mwifiex_init_new_priv_params(priv, dev, type)) -- return -1; -- if (mwifiex_sta_init_cmd(priv, false, false)) -- return -1; -- break; - case NL80211_IFTYPE_ADHOC: -- if (mwifiex_cfg80211_deinit_p2p(priv)) -- return -EFAULT; -+ case NL80211_IFTYPE_STATION: - return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, - type, params); -- break; - case NL80211_IFTYPE_AP: -- if (mwifiex_cfg80211_deinit_p2p(priv)) -- return -EFAULT; - return mwifiex_change_vif_to_ap(dev, curr_iftype, type, - params); - case NL80211_IFTYPE_UNSPECIFIED: -diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c -index c6ccce426b496..c3f5583ea70df 100644 ---- a/drivers/net/wireless/marvell/mwifiex/pcie.c -+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c -@@ -17,6 +17,7 @@ - * this warranty disclaimer. - */ - -+#include <linux/iopoll.h> - #include <linux/firmware.h> - - #include "decl.h" -@@ -647,11 +648,15 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, - "max count reached while accessing sleep cookie\n"); - } - -+#define N_WAKEUP_TRIES_SHORT_INTERVAL 15 -+#define N_WAKEUP_TRIES_LONG_INTERVAL 35 -+ - /* This function wakes up the card by reading fw_status register. */ - static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) - { - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; -+ int retval; - - mwifiex_dbg(adapter, EVENT, - "event: Wakeup device...\n"); -@@ -659,11 +664,24 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) - if (reg->sleep_cookie) - mwifiex_pcie_dev_wakeup_delay(adapter); - -- /* Accessing fw_status register will wakeup device */ -- if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { -- mwifiex_dbg(adapter, ERROR, -- "Writing fw_status register failed\n"); -- return -1; -+ /* The 88W8897 PCIe+USB firmware (latest version 15.68.19.p21) sometimes -+ * appears to ignore or miss our wakeup request, so we continue trying -+ * until we receive an interrupt from the card. -+ */ -+ if (read_poll_timeout(mwifiex_write_reg, retval, -+ READ_ONCE(adapter->int_status) != 0, -+ 500, 500 * N_WAKEUP_TRIES_SHORT_INTERVAL, -+ false, -+ adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { -+ if (read_poll_timeout(mwifiex_write_reg, retval, -+ READ_ONCE(adapter->int_status) != 0, -+ 10000, 10000 * N_WAKEUP_TRIES_LONG_INTERVAL, -+ false, -+ adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { -+ mwifiex_dbg(adapter, ERROR, -+ "Firmware didn't wake up\n"); -+ return -EIO; -+ } - } - - if (reg->sleep_cookie) { -@@ -1490,6 +1508,14 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, - ret = -1; - goto done_unmap; - } -+ -+ /* The firmware (latest version 15.68.19.p21) of the 88W8897 PCIe+USB card -+ * seems to crash randomly after setting the TX ring write pointer when -+ * ASPM powersaving is enabled. A workaround seems to be keeping the bus -+ * busy by reading a random register afterwards. -+ */ -+ mwifiex_read_reg(adapter, PCI_VENDOR_ID, &rx_val); -+ - if ((mwifiex_pcie_txbd_not_full(card)) && - tx_param->next_pkt_len) { - /* have more packets and TxBD still can hold more */ -diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c -index 426e39d4ccf0f..9736aa0ab7fd4 100644 ---- a/drivers/net/wireless/marvell/mwifiex/usb.c -+++ b/drivers/net/wireless/marvell/mwifiex/usb.c -@@ -505,6 +505,22 @@ static int mwifiex_usb_probe(struct usb_interface *intf, - } - } - -+ switch (card->usb_boot_state) { -+ case USB8XXX_FW_DNLD: -+ /* Reject broken descriptors. */ -+ if (!card->rx_cmd_ep || !card->tx_cmd_ep) -+ return -ENODEV; -+ if (card->bulk_out_maxpktsize == 0) -+ return -ENODEV; -+ break; -+ case USB8XXX_FW_READY: -+ /* Assume the driver can handle missing endpoints for now. */ -+ break; -+ default: -+ WARN_ON(1); -+ return -ENODEV; -+ } -+ - usb_set_intfdata(intf, card); - - ret = mwifiex_add_card(card, &card->fw_done, &usb_ops, -diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c -index 3bf6571f41490..529e325498cdb 100644 ---- a/drivers/net/wireless/marvell/mwl8k.c -+++ b/drivers/net/wireless/marvell/mwl8k.c -@@ -5800,8 +5800,8 @@ static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) - fail: - priv->fw_state = FW_STATE_ERROR; - complete(&priv->firmware_loading_complete); -- device_release_driver(&priv->pdev->dev); - mwl8k_release_firmware(priv); -+ device_release_driver(&priv->pdev->dev); - } - - #define MAX_RESTART_ATTEMPTS 1 -diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c -index fa48cc3a7a8f7..ad97308c78534 100644 ---- a/drivers/net/wireless/mediatek/mt76/debugfs.c -+++ b/drivers/net/wireless/mediatek/mt76/debugfs.c -@@ -116,8 +116,11 @@ static int mt76_read_rate_txpower(struct seq_file *s, void *data) - return 0; - } - --struct dentry *mt76_register_debugfs(struct mt76_dev *dev) -+struct dentry * -+mt76_register_debugfs_fops(struct mt76_dev *dev, -+ const struct file_operations *ops) - { -+ const struct file_operations *fops = ops ? ops : &fops_regval; - struct dentry *dir; - - dir = debugfs_create_dir("mt76", dev->hw->wiphy->debugfsdir); -@@ -126,8 +129,7 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev) - - debugfs_create_u8("led_pin", 0600, dir, &dev->led_pin); - debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg); -- debugfs_create_file_unsafe("regval", 0600, dir, dev, -- &fops_regval); -+ debugfs_create_file_unsafe("regval", 0600, dir, dev, fops); - debugfs_create_file_unsafe("napi_threaded", 0600, dir, dev, - &fops_napi_threaded); - debugfs_create_blob("eeprom", 0400, dir, &dev->eeprom); -@@ -140,4 +142,4 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev) - - return dir; - } --EXPORT_SYMBOL_GPL(mt76_register_debugfs); -+EXPORT_SYMBOL_GPL(mt76_register_debugfs_fops); -diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h -index 25c5ceef52577..4d01fd85283df 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt76.h -+++ b/drivers/net/wireless/mediatek/mt76/mt76.h -@@ -869,7 +869,13 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, - int mt76_register_phy(struct mt76_phy *phy, bool vht, - struct ieee80211_rate *rates, int n_rates); - --struct dentry *mt76_register_debugfs(struct mt76_dev *dev); -+struct dentry *mt76_register_debugfs_fops(struct mt76_dev *dev, -+ const struct file_operations *ops); -+static inline struct dentry *mt76_register_debugfs(struct mt76_dev *dev) -+{ -+ return mt76_register_debugfs_fops(dev, NULL); -+} -+ - int mt76_queues_read(struct seq_file *s, void *data); - void mt76_seq_puts_array(struct seq_file *file, const char *str, - s8 *val, int len); -diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c -index cb4659771fd97..bda22ca0bd714 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c -@@ -2,6 +2,33 @@ - - #include "mt7615.h" - -+static int -+mt7615_reg_set(void *data, u64 val) -+{ -+ struct mt7615_dev *dev = data; -+ -+ mt7615_mutex_acquire(dev); -+ mt76_wr(dev, dev->mt76.debugfs_reg, val); -+ mt7615_mutex_release(dev); -+ -+ return 0; -+} -+ -+static int -+mt7615_reg_get(void *data, u64 *val) -+{ -+ struct mt7615_dev *dev = data; -+ -+ mt7615_mutex_acquire(dev); -+ *val = mt76_rr(dev, dev->mt76.debugfs_reg); -+ mt7615_mutex_release(dev); -+ -+ return 0; -+} -+ -+DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7615_reg_get, mt7615_reg_set, -+ "0x%08llx\n"); -+ - static int - mt7615_radar_pattern_set(void *data, u64 val) - { -@@ -506,7 +533,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) - { - struct dentry *dir; - -- dir = mt76_register_debugfs(&dev->mt76); -+ dir = mt76_register_debugfs_fops(&dev->mt76, &fops_regval); - if (!dir) - return -ENOMEM; - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c -index 2f1ac644e018e..47f23ac905a3c 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c -@@ -49,12 +49,14 @@ int mt7615_thermal_init(struct mt7615_dev *dev) - { - struct wiphy *wiphy = mt76_hw(dev)->wiphy; - struct device *hwmon; -+ const char *name; - - if (!IS_REACHABLE(CONFIG_HWMON)) - return 0; - -- hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, -- wiphy_name(wiphy), dev, -+ name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s", -+ wiphy_name(wiphy)); -+ hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, - mt7615_hwmon_groups); - if (IS_ERR(hwmon)) - return PTR_ERR(hwmon); -diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c -index ff3f85e4087c9..5455231f51881 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c -@@ -755,12 +755,15 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK); - -- txwi[7] = FIELD_PREP(MT_TXD7_TYPE, fc_type) | -- FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) | -- FIELD_PREP(MT_TXD7_SPE_IDX, 0x18); -- if (!is_mmio) -- txwi[8] = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) | -- FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype); -+ val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | -+ FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) | -+ FIELD_PREP(MT_TXD7_SPE_IDX, 0x18); -+ txwi[7] = cpu_to_le32(val); -+ if (!is_mmio) { -+ val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) | -+ FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype); -+ txwi[8] = cpu_to_le32(val); -+ } - - return 0; - } -@@ -1494,32 +1497,41 @@ out: - } - - static void --mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) -+mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi) - { - struct mt76_dev *mdev = &dev->mt76; -- struct mt76_txwi_cache *txwi; - __le32 *txwi_data; - u32 val; - u8 wcid; - -- trace_mac_tx_free(dev, token); -- txwi = mt76_token_put(mdev, token); -- if (!txwi) -- return; -+ mt7615_txp_skb_unmap(mdev, txwi); -+ if (!txwi->skb) -+ goto out; - - txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi); - val = le32_to_cpu(txwi_data[1]); - wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val); -+ mt76_tx_complete_skb(mdev, wcid, txwi->skb); - -- mt7615_txp_skb_unmap(mdev, txwi); -- if (txwi->skb) { -- mt76_tx_complete_skb(mdev, wcid, txwi->skb); -- txwi->skb = NULL; -- } -- -+out: -+ txwi->skb = NULL; - mt76_put_txwi(mdev, txwi); - } - -+static void -+mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) -+{ -+ struct mt76_dev *mdev = &dev->mt76; -+ struct mt76_txwi_cache *txwi; -+ -+ trace_mac_tx_free(dev, token); -+ txwi = mt76_token_put(mdev, token); -+ if (!txwi) -+ return; -+ -+ mt7615_txwi_free(dev, txwi); -+} -+ - static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) - { - struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; -@@ -2026,16 +2038,8 @@ void mt7615_tx_token_put(struct mt7615_dev *dev) - int id; - - spin_lock_bh(&dev->mt76.token_lock); -- idr_for_each_entry(&dev->mt76.token, txwi, id) { -- mt7615_txp_skb_unmap(&dev->mt76, txwi); -- if (txwi->skb) { -- struct ieee80211_hw *hw; -- -- hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb); -- ieee80211_free_txskb(hw, txwi->skb); -- } -- mt76_put_txwi(&dev->mt76, txwi); -- } -+ idr_for_each_entry(&dev->mt76.token, txwi, id) -+ mt7615_txwi_free(dev, txwi); - spin_unlock_bh(&dev->mt76.token_lock); - idr_destroy(&dev->mt76.token); - } -diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c -index dada43d6d879e..51260a669d166 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c -@@ -135,8 +135,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) - int i; - - switch (type) { -- case NL80211_IFTYPE_MESH_POINT: -- case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - /* prefer hw bssid slot 1-3 */ - i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); -@@ -160,6 +158,8 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) - return HW_BSSID_0; - - break; -+ case NL80211_IFTYPE_ADHOC: -+ case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_AP: - /* ap uses hw bssid 0 and ext bssid */ -diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c -index f8a09692d3e4c..4fed3afad67cc 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c -@@ -808,7 +808,8 @@ mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) - - static int - mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, -- struct ieee80211_sta *sta, bool enable) -+ struct ieee80211_sta *sta, struct mt7615_phy *phy, -+ bool enable) - { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA; -@@ -821,6 +822,7 @@ mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_MONITOR: - break; - case NL80211_IFTYPE_STATION: - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ -@@ -840,14 +842,19 @@ mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, - } - - bss = (struct bss_info_basic *)tlv; -- memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); -- bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - bss->network_type = cpu_to_le32(type); -- bss->dtim_period = vif->bss_conf.dtim_period; - bss->bmc_tx_wlan_idx = wlan_idx; - bss->wmm_idx = mvif->mt76.wmm_idx; - bss->active = enable; - -+ if (vif->type != NL80211_IFTYPE_MONITOR) { -+ memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); -+ bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); -+ bss->dtim_period = vif->bss_conf.dtim_period; -+ } else { -+ memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN); -+ } -+ - return 0; - } - -@@ -863,6 +870,7 @@ mt7615_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) - tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); - - switch (vif->type) { -+ case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - if (vif->p2p) -@@ -929,7 +937,7 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, - if (enable) - mt7615_mcu_bss_omac_tlv(skb, vif); - -- mt7615_mcu_bss_basic_tlv(skb, vif, sta, enable); -+ mt7615_mcu_bss_basic_tlv(skb, vif, sta, phy, enable); - - if (enable && mvif->mt76.omac_idx >= EXT_BSSID_START && - mvif->mt76.omac_idx < REPEATER_BSSID_START) -diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c -index 5c3a81e5f559d..d25b50e769328 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c -+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c -@@ -689,7 +689,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, - if (ht_cap->ht_supported) - mode |= PHY_TYPE_BIT_HT; - -- if (he_cap->has_he) -+ if (he_cap && he_cap->has_he) - mode |= PHY_TYPE_BIT_HE; - } else if (band == NL80211_BAND_5GHZ) { - mode |= PHY_TYPE_BIT_OFDM; -@@ -700,7 +700,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, - if (vht_cap->vht_supported) - mode |= PHY_TYPE_BIT_VHT; - -- if (he_cap->has_he) -+ if (he_cap && he_cap->has_he) - mode |= PHY_TYPE_BIT_HE; - } - -@@ -719,6 +719,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, - struct sta_rec_state *state; - struct sta_rec_phy *phy; - struct tlv *tlv; -+ u16 supp_rates; - - /* starec ht */ - if (sta->ht_cap.ht_supported) { -@@ -767,7 +768,15 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, - - tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info)); - ra_info = (struct sta_rec_ra_info *)tlv; -- ra_info->legacy = cpu_to_le16((u16)sta->supp_rates[band]); -+ -+ supp_rates = sta->supp_rates[band]; -+ if (band == NL80211_BAND_2GHZ) -+ supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) | -+ FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf); -+ else -+ supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates); -+ -+ ra_info->legacy = cpu_to_le16(supp_rates); - - if (sta->ht_cap.ht_supported) - memcpy(ra_info->rx_mcs_bitmask, sta->ht_cap.mcs.rx_mask, -@@ -1929,19 +1938,22 @@ mt76_connac_mcu_key_iter(struct ieee80211_hw *hw, - key->cipher != WLAN_CIPHER_SUITE_TKIP) - return; - -- if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { -- gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1); -+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) - cipher = BIT(3); -- } else { -- gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2); -+ else - cipher = BIT(4); -- } - - /* we are assuming here to have a single pairwise key */ - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { -+ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) -+ gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1); -+ else -+ gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2); -+ - gtk_tlv->pairwise_cipher = cpu_to_le32(cipher); -- gtk_tlv->group_cipher = cpu_to_le32(cipher); - gtk_tlv->keyid = key->keyidx; -+ } else { -+ gtk_tlv->group_cipher = cpu_to_le32(cipher); - } - } - -diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h -index 1c73beb226771..77d4435e4581e 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h -+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h -@@ -124,6 +124,8 @@ struct sta_rec_state { - u8 rsv[1]; - } __packed; - -+#define RA_LEGACY_OFDM GENMASK(13, 6) -+#define RA_LEGACY_CCK GENMASK(3, 0) - #define HT_MCS_MASK_NUM 10 - struct sta_rec_ra_info { - __le16 tag; -@@ -844,14 +846,14 @@ struct mt76_connac_gtk_rekey_tlv { - * 2: rekey update - */ - u8 keyid; -- u8 pad[2]; -+ u8 option; /* 1: rekey data update without enabling offload */ -+ u8 pad[1]; - __le32 proto; /* WPA-RSN-WAPI-OPSN */ - __le32 pairwise_cipher; - __le32 group_cipher; - __le32 key_mgmt; /* NONE-PSK-IEEE802.1X */ - __le32 mgmt_group_cipher; -- u8 option; /* 1: rekey data update without enabling offload */ -- u8 reserverd[3]; -+ u8 reserverd[4]; - } __packed; - - #define MT76_CONNAC_WOW_MASK_MAX_LEN 16 -diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c -index c32e6dc687739..07b21b2085823 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c -+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c -@@ -176,7 +176,7 @@ void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) - mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop)); - } - --static __le16 -+static u16 - mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, - const struct ieee80211_tx_rate *rate, u8 *nss_val) - { -@@ -222,14 +222,14 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, - rateval |= MT_RXWI_RATE_SGI; - - *nss_val = nss; -- return cpu_to_le16(rateval); -+ return rateval; - } - - void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid, - const struct ieee80211_tx_rate *rate) - { - s8 max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); -- __le16 rateval; -+ u16 rateval; - u32 tx_info; - s8 nss; - -@@ -342,7 +342,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, - struct ieee80211_key_conf *key = info->control.hw_key; - u32 wcid_tx_info; - u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2)); -- u16 txwi_flags = 0; -+ u16 txwi_flags = 0, rateval; - u8 nss; - s8 txpwr_adj, max_txpwr_adj; - u8 ccmp_pn[8], nstreams = dev->mphy.chainmask & 0xf; -@@ -380,14 +380,15 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, - - if (wcid && (rate->idx < 0 || !rate->count)) { - wcid_tx_info = wcid->tx_info; -- txwi->rate = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info); -+ rateval = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info); - max_txpwr_adj = FIELD_GET(MT_WCID_TX_INFO_TXPWR_ADJ, - wcid_tx_info); - nss = FIELD_GET(MT_WCID_TX_INFO_NSS, wcid_tx_info); - } else { -- txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss); -+ rateval = mt76x02_mac_tx_rate_val(dev, rate, &nss); - max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); - } -+ txwi->rate = cpu_to_le16(rateval); - - txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf, - max_txpwr_adj); -diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c -index 4798d6344305d..b171027e0cfa8 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c -@@ -130,9 +130,12 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) - struct wiphy *wiphy = phy->mt76->hw->wiphy; - struct thermal_cooling_device *cdev; - struct device *hwmon; -+ const char *name; - -- cdev = thermal_cooling_device_register(wiphy_name(wiphy), phy, -- &mt7915_thermal_ops); -+ name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s", -+ wiphy_name(wiphy)); -+ -+ cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops); - if (!IS_ERR(cdev)) { - if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj, - "cooling_device") < 0) -@@ -144,8 +147,7 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) - if (!IS_REACHABLE(CONFIG_HWMON)) - return 0; - -- hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, -- wiphy_name(wiphy), phy, -+ hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, - mt7915_hwmon_groups); - if (IS_ERR(hwmon)) - return PTR_ERR(hwmon); -diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c -index 2462704094b0a..bbc996f86b5c3 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c -@@ -1232,7 +1232,7 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, - goto out; - - info = IEEE80211_SKB_CB(skb); -- if (!(txs_data[0] & le32_to_cpu(MT_TXS0_ACK_ERROR_MASK))) -+ if (!(txs_data[0] & cpu_to_le32(MT_TXS0_ACK_ERROR_MASK))) - info->flags |= IEEE80211_TX_STAT_ACK; - - info->status.ampdu_len = 1; -diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h -index eb1885f4bd8eb..fee7741b5d421 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h -+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h -@@ -272,7 +272,8 @@ enum tx_mcu_port_q_idx { - #define MT_TX_RATE_MODE GENMASK(9, 6) - #define MT_TX_RATE_SU_EXT_TONE BIT(5) - #define MT_TX_RATE_DCM BIT(4) --#define MT_TX_RATE_IDX GENMASK(3, 0) -+/* VHT/HE only use bits 0-3 */ -+#define MT_TX_RATE_IDX GENMASK(5, 0) - - #define MT_TXP_MAX_BUF_NUM 6 - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c -index 43960770a9af2..7440f2b443eca 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c -@@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) - if (ht_cap->ht_supported) - mode |= PHY_MODE_GN; - -- if (he_cap->has_he) -+ if (he_cap && he_cap->has_he) - mode |= PHY_MODE_AX_24G; - } else if (band == NL80211_BAND_5GHZ) { - mode |= PHY_MODE_A; -@@ -187,7 +187,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) - if (vht_cap->vht_supported) - mode |= PHY_MODE_AC; - -- if (he_cap->has_he) -+ if (he_cap && he_cap->has_he) - mode |= PHY_MODE_AX_5G; - } - -@@ -721,7 +721,7 @@ mt7915_mcu_alloc_sta_req(struct mt7915_dev *dev, struct mt7915_vif *mvif, - .bss_idx = mvif->idx, - .wlan_idx_lo = msta ? to_wcid_lo(msta->wcid.idx) : 0, - .wlan_idx_hi = msta ? to_wcid_hi(msta->wcid.idx) : 0, -- .muar_idx = msta ? mvif->omac_idx : 0, -+ .muar_idx = msta && msta->wcid.sta ? mvif->omac_idx : 0xe, - .is_tlv_append = 1, - }; - struct sk_buff *skb; -@@ -757,7 +757,7 @@ mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta, - } - - if (sta_hdr) -- sta_hdr->len = cpu_to_le16(sizeof(hdr)); -+ le16_add_cpu(&sta_hdr->len, sizeof(hdr)); - - return skb_put_data(nskb, &hdr, sizeof(hdr)); - } -@@ -925,7 +925,7 @@ static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, - - elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY); - -- if (!elem || elem->datalen < 10 || -+ if (!elem || elem->datalen <= 10 || - !(elem->data[10] & - WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) - data->tolerated = false; -@@ -1201,7 +1201,7 @@ mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb, - u8 cipher; - - cipher = mt7915_mcu_get_cipher(key->cipher); -- if (cipher == MT_CIPHER_NONE) -+ if (cipher == MCU_CIPHER_NONE) - return -EOPNOTSUPP; - - sec_key = &sec->key[0]; -@@ -2790,7 +2790,7 @@ out: - default: - ret = -EAGAIN; - dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); -- goto out; -+ break; - } - release_firmware(fw); - -@@ -3391,20 +3391,20 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) - - static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) - { --#define TOTAL_PAGE_MASK GENMASK(7, 5) -+#define MAX_PAGE_IDX_MASK GENMASK(7, 5) - #define PAGE_IDX_MASK GENMASK(4, 2) - #define PER_PAGE_SIZE 0x400 - struct mt7915_mcu_eeprom req = { .buffer_mode = EE_MODE_BUFFER }; -- u8 total = MT7915_EEPROM_SIZE / PER_PAGE_SIZE; -+ u8 total = DIV_ROUND_UP(MT7915_EEPROM_SIZE, PER_PAGE_SIZE); - u8 *eep = (u8 *)dev->mt76.eeprom.data; - int eep_len; - int i; - -- for (i = 0; i <= total; i++, eep += eep_len) { -+ for (i = 0; i < total; i++, eep += eep_len) { - struct sk_buff *skb; - int ret; - -- if (i == total) -+ if (i == total - 1 && !!(MT7915_EEPROM_SIZE % PER_PAGE_SIZE)) - eep_len = MT7915_EEPROM_SIZE % PER_PAGE_SIZE; - else - eep_len = PER_PAGE_SIZE; -@@ -3414,7 +3414,7 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) - if (!skb) - return -ENOMEM; - -- req.format = FIELD_PREP(TOTAL_PAGE_MASK, total) | -+ req.format = FIELD_PREP(MAX_PAGE_IDX_MASK, total - 1) | - FIELD_PREP(PAGE_IDX_MASK, i) | EE_FORMAT_WHOLE; - req.len = cpu_to_le16(eep_len); - -@@ -3481,7 +3481,7 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx, - u8 idx; - u8 rsv[4]; - __le32 len; -- } req; -+ } req = {}; - struct sk_buff *skb; - - skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len); -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c -index 77468bdae460b..30f3b3085c786 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c -@@ -4,6 +4,32 @@ - #include "mt7921.h" - #include "eeprom.h" - -+static int -+mt7921_reg_set(void *data, u64 val) -+{ -+ struct mt7921_dev *dev = data; -+ -+ mt7921_mutex_acquire(dev); -+ mt76_wr(dev, dev->mt76.debugfs_reg, val); -+ mt7921_mutex_release(dev); -+ -+ return 0; -+} -+ -+static int -+mt7921_reg_get(void *data, u64 *val) -+{ -+ struct mt7921_dev *dev = data; -+ -+ mt7921_mutex_acquire(dev); -+ *val = mt76_rr(dev, dev->mt76.debugfs_reg); -+ mt7921_mutex_release(dev); -+ -+ return 0; -+} -+ -+DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set, -+ "0x%08llx\n"); - static int - mt7921_fw_debug_set(void *data, u64 val) - { -@@ -69,6 +95,8 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) - struct mt7921_dev *dev = file->private; - int stat[8], i, n; - -+ mt7921_mutex_acquire(dev); -+ - mt7921_ampdu_stat_read_phy(&dev->phy, file); - - /* Tx amsdu info */ -@@ -78,6 +106,8 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) - n += stat[i]; - } - -+ mt7921_mutex_release(dev); -+ - for (i = 0; i < ARRAY_SIZE(stat); i++) { - seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ", - i + 1, stat[i]); -@@ -98,6 +128,8 @@ mt7921_queues_acq(struct seq_file *s, void *data) - struct mt7921_dev *dev = dev_get_drvdata(s->private); - int i; - -+ mt7921_mutex_acquire(dev); -+ - for (i = 0; i < 16; i++) { - int j, acs = i / 4, index = i % 4; - u32 ctrl, val, qlen = 0; -@@ -117,6 +149,8 @@ mt7921_queues_acq(struct seq_file *s, void *data) - seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); - } - -+ mt7921_mutex_release(dev); -+ - return 0; - } - -@@ -373,7 +407,7 @@ int mt7921_init_debugfs(struct mt7921_dev *dev) - { - struct dentry *dir; - -- dir = mt76_register_debugfs(&dev->mt76); -+ dir = mt76_register_debugfs_fops(&dev->mt76, &fops_regval); - if (!dir) - return -ENOMEM; - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c -index a9ce10b988273..78a00028137bd 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c -@@ -106,6 +106,10 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); - mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); - -+ /* enable MIB tx-rx time reporting */ -+ mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN); -+ mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN); -+ - mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); - /* disable rx rate report by default due to hw issues */ - mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); -@@ -247,8 +251,17 @@ int mt7921_register_device(struct mt7921_dev *dev) - - void mt7921_unregister_device(struct mt7921_dev *dev) - { -+ int i; -+ struct mt76_connac_pm *pm = &dev->pm; -+ - mt76_unregister_device(&dev->mt76); -+ mt76_for_each_q_rx(&dev->mt76, i) -+ napi_disable(&dev->mt76.napi[i]); -+ cancel_delayed_work_sync(&pm->ps_work); -+ cancel_work_sync(&pm->wake_work); -+ - mt7921_tx_token_put(dev); -+ mt7921_mcu_drv_pmctrl(dev); - mt7921_dma_cleanup(dev); - mt7921_mcu_exit(dev); - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c -index 7fe2e3a50428f..8a16f3f4d5253 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c -@@ -180,12 +180,56 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); - } - -+static void -+mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, -+ struct mt76_rx_status *status, -+ __le32 *rxv) -+{ -+ static const struct ieee80211_radiotap_he_mu mu_known = { -+ .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | -+ HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | -+ HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | -+ HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN) | -+ HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN), -+ .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN) | -+ HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN), -+ }; -+ struct ieee80211_radiotap_he_mu *he_mu = NULL; -+ -+ he_mu = skb_push(skb, sizeof(mu_known)); -+ memcpy(he_mu, &mu_known, sizeof(mu_known)); -+ -+#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) -+ -+ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); -+ if (status->he_dcm) -+ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); -+ -+ he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | -+ MU_PREP(FLAGS2_SIG_B_SYMS_USERS, -+ le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); -+ -+ he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, cpu_to_le32(rxv[3])); -+ -+ if (status->bw >= RATE_INFO_BW_40) { -+ he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); -+ he_mu->ru_ch2[0] = -+ FIELD_GET(MT_CRXV_HE_RU1, cpu_to_le32(rxv[3])); -+ } -+ -+ if (status->bw >= RATE_INFO_BW_80) { -+ he_mu->ru_ch1[1] = -+ FIELD_GET(MT_CRXV_HE_RU2, cpu_to_le32(rxv[3])); -+ he_mu->ru_ch2[1] = -+ FIELD_GET(MT_CRXV_HE_RU3, cpu_to_le32(rxv[3])); -+ } -+} -+ - static void - mt7921_mac_decode_he_radiotap(struct sk_buff *skb, - struct mt76_rx_status *status, - __le32 *rxv, u32 phy) - { -- /* TODO: struct ieee80211_radiotap_he_mu */ - static const struct ieee80211_radiotap_he known = { - .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | - HE_BITS(DATA1_DATA_DCM_KNOWN) | -@@ -193,6 +237,7 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, - HE_BITS(DATA1_CODING_KNOWN) | - HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | -+ HE_BITS(DATA1_SPTL_REUSE_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN), - .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN) | -@@ -207,9 +252,12 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, - - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | - HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); -+ he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); - he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | - le16_encode_bits(ltf_size, - IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); -+ if (cpu_to_le32(rxv[0]) & MT_PRXV_TXBF) -+ he->data5 |= HE_BITS(DATA5_TXBF); - he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | - HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); - -@@ -217,8 +265,7 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, - case MT_PHY_TYPE_HE_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | -- HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | -- HE_BITS(DATA1_SPTL_REUSE_KNOWN); -+ HE_BITS(DATA1_BEAM_CHANGE_KNOWN); - - he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | - HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); -@@ -232,17 +279,15 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, - break; - case MT_PHY_TYPE_HE_MU: - he->data1 |= HE_BITS(DATA1_FORMAT_MU) | -- HE_BITS(DATA1_UL_DL_KNOWN) | -- HE_BITS(DATA1_SPTL_REUSE_KNOWN); -+ HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); -- he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); -+ he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); - - mt7921_mac_decode_he_radiotap_ru(status, he, rxv); - break; - case MT_PHY_TYPE_HE_TB: - he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | -- HE_BITS(DATA1_SPTL_REUSE_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE4_KNOWN); -@@ -606,9 +651,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) - - mt7921_mac_assoc_rssi(dev, skb); - -- if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) -+ if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) { - mt7921_mac_decode_he_radiotap(skb, status, rxv, mode); - -+ if (status->flag & RX_FLAG_RADIOTAP_HE_MU) -+ mt7921_mac_decode_he_mu_radiotap(skb, status, rxv); -+ } -+ - if (!status->wcid || !ieee80211_is_data_qos(fc)) - return 0; - -@@ -735,8 +784,9 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi, - static void mt7921_update_txs(struct mt76_wcid *wcid, __le32 *txwi) - { - struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid); -- u32 pid, frame_type = FIELD_GET(MT_TXD2_FRAME_TYPE, txwi[2]); -+ u32 pid, frame_type; - -+ frame_type = FIELD_GET(MT_TXD2_FRAME_TYPE, le32_to_cpu(txwi[2])); - if (!(frame_type & (IEEE80211_FTYPE_DATA >> 2))) - return; - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h -index 3af67fac213df..f0194c8780372 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h -@@ -116,6 +116,7 @@ enum rx_pkt_type { - #define MT_PRXV_TX_DCM BIT(4) - #define MT_PRXV_TX_ER_SU_106T BIT(5) - #define MT_PRXV_NSTS GENMASK(9, 7) -+#define MT_PRXV_TXBF BIT(10) - #define MT_PRXV_HT_AD_CODE BIT(11) - #define MT_PRXV_FRAME_MODE GENMASK(14, 12) - #define MT_PRXV_SGI GENMASK(16, 15) -@@ -138,8 +139,15 @@ enum rx_pkt_type { - #define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) - #define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) - #define MT_CRXV_HE_PE_DISAMBIG BIT(23) -+#define MT_CRXV_HE_NUM_USER GENMASK(30, 24) - #define MT_CRXV_HE_UPLINK BIT(31) - -+#define MT_CRXV_HE_RU0 GENMASK(7, 0) -+#define MT_CRXV_HE_RU1 GENMASK(15, 8) -+#define MT_CRXV_HE_RU2 GENMASK(23, 16) -+#define MT_CRXV_HE_RU3 GENMASK(31, 24) -+#define MT_CRXV_HE_MU_AID GENMASK(30, 20) -+ - #define MT_CRXV_HE_SR_MASK GENMASK(11, 8) - #define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) - #define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c -index 9fbaacc67cfad..506a1909ce6d5 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c -@@ -157,6 +157,7 @@ mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, - struct sk_buff *skb, int seq) - { - struct mt7921_mcu_rxd *rxd; -+ int mcu_cmd = cmd & MCU_CMD_MASK; - int ret = 0; - - if (!skb) { -@@ -194,6 +195,9 @@ mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, - skb_pull(skb, sizeof(*rxd)); - event = (struct mt7921_mcu_uni_event *)skb->data; - ret = le32_to_cpu(event->status); -+ /* skip invalid event */ -+ if (mcu_cmd != event->cid) -+ ret = -EAGAIN; - break; - } - case MCU_CMD_REG_READ: { -@@ -316,11 +320,13 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy, - struct rate_info *rate, u16 r) - { - struct ieee80211_supported_band *sband; -- u16 flags = 0; -+ u16 flags = 0, rate_idx; - u8 txmode = FIELD_GET(MT_WTBL_RATE_TX_MODE, r); - u8 gi = 0; - u8 bw = 0; -+ bool cck = false; - -+ memset(rate, 0, sizeof(*rate)); - rate->mcs = FIELD_GET(MT_WTBL_RATE_MCS, r); - rate->nss = FIELD_GET(MT_WTBL_RATE_NSS, r) + 1; - -@@ -345,13 +351,18 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy, - - switch (txmode) { - case MT_PHY_TYPE_CCK: -+ cck = true; -+ fallthrough; - case MT_PHY_TYPE_OFDM: - if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) - sband = &mphy->sband_5g.sband; - else - sband = &mphy->sband_2g.sband; - -- rate->legacy = sband->bitrates[rate->mcs].bitrate; -+ rate_idx = FIELD_GET(MT_TX_RATE_IDX, r); -+ rate_idx = mt76_get_rate(mphy->dev, sband, rate_idx, -+ cck); -+ rate->legacy = sband->bitrates[rate_idx].bitrate; - break; - case MT_PHY_TYPE_HT: - case MT_PHY_TYPE_HT_GF: -@@ -532,7 +543,8 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) - peer.g8 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); - peer.g16 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); - mt7921_mcu_tx_rate_parse(mphy->mt76, &peer, -- &msta->stats.tx_rate, event->tx_rate); -+ &msta->stats.tx_rate, -+ le16_to_cpu(event->tx_rate)); - - spin_lock_bh(&dev->sta_poll_lock); - break; -@@ -619,7 +631,7 @@ mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb, - u8 cipher; - - cipher = mt7921_mcu_get_cipher(key->cipher); -- if (cipher == MT_CIPHER_NONE) -+ if (cipher == MCU_CIPHER_NONE) - return -EOPNOTSUPP; - - sec_key = &sec->key[0]; -@@ -815,7 +827,7 @@ out: - default: - ret = -EAGAIN; - dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); -- goto out; -+ break; - } - release_firmware(fw); - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h -index de3c091f67368..42e7271848956 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h -@@ -296,11 +296,11 @@ struct mt7921_txpwr_event { - struct mt7921_mcu_tx_done_event { - u8 pid; - u8 status; -- u16 seq; -+ __le16 seq; - - u8 wlan_idx; - u8 tx_cnt; -- u16 tx_rate; -+ __le16 tx_rate; - - u8 flag; - u8 tid; -@@ -312,9 +312,9 @@ struct mt7921_mcu_tx_done_event { - u8 reason; - u8 rsv0[1]; - -- u32 delay; -- u32 timestamp; -- u32 applied_flag; -+ __le32 delay; -+ __le32 timestamp; -+ __le32 applied_flag; - - u8 txs[28]; - -diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h -index b6944c867a573..26fb118237626 100644 ---- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h -+++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h -@@ -96,6 +96,10 @@ - #define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800) - #define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) - -+#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004) -+#define MT_MIB_TXDUR_EN BIT(8) -+#define MT_MIB_RXDUR_EN BIT(9) -+ - #define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) - #define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) - -@@ -108,9 +112,9 @@ - #define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) - #define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) - --#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x098) -+#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054) - #define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) --#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x09c) -+#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058) - #define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) - - #define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) -diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c -index 96973ec7bd9ac..87c14969c75fa 100644 ---- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c -+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c -@@ -129,8 +129,7 @@ static void cfg_scan_result(enum scan_event scan_event, - info->frame_len, - (s32)info->rssi * 100, - GFP_KERNEL); -- if (!bss) -- cfg80211_put_bss(wiphy, bss); -+ cfg80211_put_bss(wiphy, bss); - } else if (scan_event == SCAN_EVENT_DONE) { - mutex_lock(&priv->scan_req_lock); - -diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c -index e4473a5512415..74c3d8cb31002 100644 ---- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c -+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c -@@ -25,6 +25,9 @@ static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status) - if (status == -ENODEV || status == -ENOENT) - return true; - -+ if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) -+ return false; -+ - if (status == -EPROTO || status == -ETIMEDOUT) - rt2x00dev->num_proto_errs++; - else -diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c -index 585784258c665..4efab907a3ac6 100644 ---- a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c -+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c -@@ -28,7 +28,7 @@ u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, -- &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); -+ &priv->io_dmabuf->bits8, sizeof(val), 500); - - val = priv->io_dmabuf->bits8; - mutex_unlock(&priv->io_mutex); -@@ -45,7 +45,7 @@ u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, -- &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); -+ &priv->io_dmabuf->bits16, sizeof(val), 500); - - val = priv->io_dmabuf->bits16; - mutex_unlock(&priv->io_mutex); -@@ -62,7 +62,7 @@ u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, -- &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); -+ &priv->io_dmabuf->bits32, sizeof(val), 500); - - val = priv->io_dmabuf->bits32; - mutex_unlock(&priv->io_mutex); -@@ -79,7 +79,7 @@ void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, -- &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); -+ &priv->io_dmabuf->bits8, sizeof(val), 500); - - mutex_unlock(&priv->io_mutex); - } -@@ -93,7 +93,7 @@ void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, -- &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); -+ &priv->io_dmabuf->bits16, sizeof(val), 500); - - mutex_unlock(&priv->io_mutex); - } -@@ -107,7 +107,7 @@ void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, -- &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); -+ &priv->io_dmabuf->bits32, sizeof(val), 500); - - mutex_unlock(&priv->io_mutex); - } -@@ -183,7 +183,7 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data) - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data), -- HZ / 2); -+ 500); - - mutex_unlock(&priv->io_mutex); - -diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c -index e6399519584bd..a384fc3a4f2b0 100644 ---- a/drivers/net/wireless/realtek/rtw88/fw.c -+++ b/drivers/net/wireless/realtek/rtw88/fw.c -@@ -1556,12 +1556,10 @@ static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, - u32 i; - u16 idx = 0; - u16 ctl; -- u8 rcr; - -- rcr = rtw_read8(rtwdev, REG_RCR + 2); - ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000; - /* disable rx clock gate */ -- rtw_write8(rtwdev, REG_RCR, rcr | BIT(3)); -+ rtw_write32_set(rtwdev, REG_RCR, BIT_DISGCLK); - - do { - rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, start_pg | ctl); -@@ -1580,7 +1578,8 @@ static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, - - out: - rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl); -- rtw_write8(rtwdev, REG_RCR + 2, rcr); -+ /* restore rx clock gate */ -+ rtw_write32_clr(rtwdev, REG_RCR, BIT_DISGCLK); - } - - static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel, -diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h -index f5ce75095e904..c0fb1e446245f 100644 ---- a/drivers/net/wireless/realtek/rtw88/reg.h -+++ b/drivers/net/wireless/realtek/rtw88/reg.h -@@ -406,6 +406,7 @@ - #define BIT_MFBEN BIT(22) - #define BIT_DISCHKPPDLLEN BIT(21) - #define BIT_PKTCTL_DLEN BIT(20) -+#define BIT_DISGCLK BIT(19) - #define BIT_TIM_PARSER_EN BIT(18) - #define BIT_BC_MD_EN BIT(17) - #define BIT_UC_MD_EN BIT(16) -diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c -index a48e616e0fb91..6bfaab48b507d 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_core.c -+++ b/drivers/net/wireless/rsi/rsi_91x_core.c -@@ -399,6 +399,8 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) - - info = IEEE80211_SKB_CB(skb); - tx_params = (struct skb_info *)info->driver_data; -+ /* info->driver_data and info->control part of union so make copy */ -+ tx_params->have_key = !!info->control.hw_key; - wh = (struct ieee80211_hdr *)&skb->data[0]; - tx_params->sta_id = 0; - -diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c -index f4a26f16f00f4..dca81a4bbdd7f 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_hal.c -+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c -@@ -203,7 +203,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) - wh->frame_control |= cpu_to_le16(RSI_SET_PS_ENABLE); - - if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) && -- info->control.hw_key) { -+ tx_params->have_key) { - if (rsi_is_cipher_wep(common)) - ieee80211_size += 4; - else -@@ -214,15 +214,17 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) - RSI_WIFI_DATA_Q); - data_desc->header_len = ieee80211_size; - -- if (common->min_rate != RSI_RATE_AUTO) { -+ if (common->rate_config[common->band].fixed_enabled) { - /* Send fixed rate */ -+ u16 fixed_rate = common->rate_config[common->band].fixed_hw_rate; -+ - data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE); -- data_desc->rate_info = cpu_to_le16(common->min_rate); -+ data_desc->rate_info = cpu_to_le16(fixed_rate); - - if (conf_is_ht40(&common->priv->hw->conf)) - data_desc->bbp_info = cpu_to_le16(FULL40M_ENABLE); - -- if ((common->vif_info[0].sgi) && (common->min_rate & 0x100)) { -+ if (common->vif_info[0].sgi && (fixed_rate & 0x100)) { - /* Only MCS rates */ - data_desc->rate_info |= - cpu_to_le16(ENABLE_SHORTGI_RATE); -diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c -index b66975f545675..e70c1c7fdf595 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c -+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c -@@ -510,7 +510,6 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw, - if ((vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_P2P_GO)) { - rsi_send_rx_filter_frame(common, DISALLOW_BEACONS); -- common->min_rate = RSI_RATE_AUTO; - for (i = 0; i < common->max_stations; i++) - common->stations[i].sta = NULL; - } -@@ -1228,20 +1227,32 @@ static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const struct cfg80211_bitrate_mask *mask) - { -+ const unsigned int mcs_offset = ARRAY_SIZE(rsi_rates); - struct rsi_hw *adapter = hw->priv; - struct rsi_common *common = adapter->priv; -- enum nl80211_band band = hw->conf.chandef.chan->band; -+ int i; - - mutex_lock(&common->mutex); -- common->fixedrate_mask[band] = 0; - -- if (mask->control[band].legacy == 0xfff) { -- common->fixedrate_mask[band] = -- (mask->control[band].ht_mcs[0] << 12); -- } else { -- common->fixedrate_mask[band] = -- mask->control[band].legacy; -+ for (i = 0; i < ARRAY_SIZE(common->rate_config); i++) { -+ struct rsi_rate_config *cfg = &common->rate_config[i]; -+ u32 bm; -+ -+ bm = mask->control[i].legacy | (mask->control[i].ht_mcs[0] << mcs_offset); -+ if (hweight32(bm) == 1) { /* single rate */ -+ int rate_index = ffs(bm) - 1; -+ -+ if (rate_index < mcs_offset) -+ cfg->fixed_hw_rate = rsi_rates[rate_index].hw_value; -+ else -+ cfg->fixed_hw_rate = rsi_mcsrates[rate_index - mcs_offset]; -+ cfg->fixed_enabled = true; -+ } else { -+ cfg->configured_mask = bm; -+ cfg->fixed_enabled = false; -+ } - } -+ - mutex_unlock(&common->mutex); - - return 0; -@@ -1378,46 +1389,6 @@ void rsi_indicate_pkt_to_os(struct rsi_common *common, - ieee80211_rx_irqsafe(hw, skb); - } - --static void rsi_set_min_rate(struct ieee80211_hw *hw, -- struct ieee80211_sta *sta, -- struct rsi_common *common) --{ -- u8 band = hw->conf.chandef.chan->band; -- u8 ii; -- u32 rate_bitmap; -- bool matched = false; -- -- common->bitrate_mask[band] = sta->supp_rates[band]; -- -- rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]); -- -- if (rate_bitmap & 0xfff) { -- /* Find out the min rate */ -- for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) { -- if (rate_bitmap & BIT(ii)) { -- common->min_rate = rsi_rates[ii].hw_value; -- matched = true; -- break; -- } -- } -- } -- -- common->vif_info[0].is_ht = sta->ht_cap.ht_supported; -- -- if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) { -- for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) { -- if ((rate_bitmap >> 12) & BIT(ii)) { -- common->min_rate = rsi_mcsrates[ii]; -- matched = true; -- break; -- } -- } -- } -- -- if (!matched) -- common->min_rate = 0xffff; --} -- - /** - * rsi_mac80211_sta_add() - This function notifies driver about a peer getting - * connected. -@@ -1516,9 +1487,9 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw, - - if ((vif->type == NL80211_IFTYPE_STATION) || - (vif->type == NL80211_IFTYPE_P2P_CLIENT)) { -- rsi_set_min_rate(hw, sta, common); -+ common->bitrate_mask[common->band] = sta->supp_rates[common->band]; -+ common->vif_info[0].is_ht = sta->ht_cap.ht_supported; - if (sta->ht_cap.ht_supported) { -- common->vif_info[0].is_ht = true; - common->bitrate_mask[NL80211_BAND_2GHZ] = - sta->supp_rates[NL80211_BAND_2GHZ]; - if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) || -@@ -1592,7 +1563,6 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw, - bss->qos = sta->wme; - common->bitrate_mask[NL80211_BAND_2GHZ] = 0; - common->bitrate_mask[NL80211_BAND_5GHZ] = 0; -- common->min_rate = 0xffff; - common->vif_info[0].is_ht = false; - common->vif_info[0].sgi = false; - common->vif_info[0].seq_start = 0; -diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c -index d98483298555c..f1bf71e6c6081 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_main.c -+++ b/drivers/net/wireless/rsi/rsi_91x_main.c -@@ -211,9 +211,10 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len) - bt_pkt_type = frame_desc[offset + BT_RX_PKT_TYPE_OFST]; - if (bt_pkt_type == BT_CARD_READY_IND) { - rsi_dbg(INFO_ZONE, "BT Card ready recvd\n"); -- if (rsi_bt_ops.attach(common, &g_proto_ops)) -- rsi_dbg(ERR_ZONE, -- "Failed to attach BT module\n"); -+ if (common->fsm_state == FSM_MAC_INIT_DONE) -+ rsi_attach_bt(common); -+ else -+ common->bt_defer_attach = true; - } else { - if (common->bt_adapter) - rsi_bt_ops.recv_pkt(common->bt_adapter, -@@ -278,6 +279,15 @@ void rsi_set_bt_context(void *priv, void *bt_context) - } - #endif - -+void rsi_attach_bt(struct rsi_common *common) -+{ -+#ifdef CONFIG_RSI_COEX -+ if (rsi_bt_ops.attach(common, &g_proto_ops)) -+ rsi_dbg(ERR_ZONE, -+ "Failed to attach BT module\n"); -+#endif -+} -+ - /** - * rsi_91x_init() - This function initializes os interface operations. - * @oper_mode: One of DEV_OPMODE_*. -@@ -359,6 +369,7 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode) - if (common->coex_mode > 1) { - if (rsi_coex_attach(common)) { - rsi_dbg(ERR_ZONE, "Failed to init coex module\n"); -+ rsi_kill_thread(&common->tx_thread); - goto err; - } - } -diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c -index 891fd5f0fa765..0848f7a7e76c6 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c -+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c -@@ -276,7 +276,7 @@ static void rsi_set_default_parameters(struct rsi_common *common) - common->channel_width = BW_20MHZ; - common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - common->channel = 1; -- common->min_rate = 0xffff; -+ memset(&common->rate_config, 0, sizeof(common->rate_config)); - common->fsm_state = FSM_CARD_NOT_READY; - common->iface_down = true; - common->endpoint = EP_2GHZ_20MHZ; -@@ -1314,7 +1314,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common, - u8 band = hw->conf.chandef.chan->band; - u8 num_supported_rates = 0; - u8 rate_table_offset, rate_offset = 0; -- u32 rate_bitmap; -+ u32 rate_bitmap, configured_rates; - u16 *selected_rates, min_rate; - bool is_ht = false, is_sgi = false; - u16 frame_len = sizeof(struct rsi_auto_rate); -@@ -1364,6 +1364,10 @@ static int rsi_send_auto_rate_request(struct rsi_common *common, - is_sgi = true; - } - -+ /* Limit to any rates administratively configured by cfg80211 */ -+ configured_rates = common->rate_config[band].configured_mask ?: 0xffffffff; -+ rate_bitmap &= configured_rates; -+ - if (band == NL80211_BAND_2GHZ) { - if ((rate_bitmap == 0) && (is_ht)) - min_rate = RSI_RATE_MCS0; -@@ -1389,10 +1393,13 @@ static int rsi_send_auto_rate_request(struct rsi_common *common, - num_supported_rates = jj; - - if (is_ht) { -- for (ii = 0; ii < ARRAY_SIZE(mcs); ii++) -- selected_rates[jj++] = mcs[ii]; -- num_supported_rates += ARRAY_SIZE(mcs); -- rate_offset += ARRAY_SIZE(mcs); -+ for (ii = 0; ii < ARRAY_SIZE(mcs); ii++) { -+ if (configured_rates & BIT(ii + ARRAY_SIZE(rsi_rates))) { -+ selected_rates[jj++] = mcs[ii]; -+ num_supported_rates++; -+ rate_offset++; -+ } -+ } - } - - sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL); -@@ -1482,7 +1489,7 @@ void rsi_inform_bss_status(struct rsi_common *common, - qos_enable, - aid, sta_id, - vif); -- if (common->min_rate == 0xffff) -+ if (!common->rate_config[common->band].fixed_enabled) - rsi_send_auto_rate_request(common, sta, sta_id, vif); - if (opmode == RSI_OPMODE_STA && - !(assoc_cap & WLAN_CAPABILITY_PRIVACY) && -@@ -2071,6 +2078,9 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, - if (common->reinit_hw) { - complete(&common->wlan_init_completion); - } else { -+ if (common->bt_defer_attach) -+ rsi_attach_bt(common); -+ - return rsi_mac80211_attach(common); - } - } -diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c -index e0c502bc42707..9f16128e4ffab 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_sdio.c -+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c -@@ -24,10 +24,7 @@ - /* Default operating mode is wlan STA + BT */ - static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL; - module_param(dev_oper_mode, ushort, 0444); --MODULE_PARM_DESC(dev_oper_mode, -- "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n" -- "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n" -- "6[AP + BT classic], 14[AP + BT classic + BT LE]"); -+MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC); - - /** - * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg. -diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c -index 416976f098882..6821ea9918956 100644 ---- a/drivers/net/wireless/rsi/rsi_91x_usb.c -+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c -@@ -25,10 +25,7 @@ - /* Default operating mode is wlan STA + BT */ - static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL; - module_param(dev_oper_mode, ushort, 0444); --MODULE_PARM_DESC(dev_oper_mode, -- "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n" -- "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n" -- "6[AP + BT classic], 14[AP + BT classic + BT LE]"); -+MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC); - - static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t flags); - -@@ -61,7 +58,7 @@ static int rsi_usb_card_write(struct rsi_hw *adapter, - (void *)seg, - (int)len, - &transfer, -- HZ * 5); -+ USB_CTRL_SET_TIMEOUT); - - if (status < 0) { - rsi_dbg(ERR_ZONE, -diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h -index d044a440fa080..5b07262a97408 100644 ---- a/drivers/net/wireless/rsi/rsi_hal.h -+++ b/drivers/net/wireless/rsi/rsi_hal.h -@@ -28,6 +28,17 @@ - #define DEV_OPMODE_AP_BT 6 - #define DEV_OPMODE_AP_BT_DUAL 14 - -+#define DEV_OPMODE_PARAM_DESC \ -+ __stringify(DEV_OPMODE_WIFI_ALONE) "[Wi-Fi alone], " \ -+ __stringify(DEV_OPMODE_BT_ALONE) "[BT classic alone], " \ -+ __stringify(DEV_OPMODE_BT_LE_ALONE) "[BT LE alone], " \ -+ __stringify(DEV_OPMODE_BT_DUAL) "[BT classic + BT LE alone], " \ -+ __stringify(DEV_OPMODE_STA_BT) "[Wi-Fi STA + BT classic], " \ -+ __stringify(DEV_OPMODE_STA_BT_LE) "[Wi-Fi STA + BT LE], " \ -+ __stringify(DEV_OPMODE_STA_BT_DUAL) "[Wi-Fi STA + BT classic + BT LE], " \ -+ __stringify(DEV_OPMODE_AP_BT) "[Wi-Fi AP + BT classic], " \ -+ __stringify(DEV_OPMODE_AP_BT_DUAL) "[Wi-Fi AP + BT classic + BT LE]" -+ - #define FLASH_WRITE_CHUNK_SIZE (4 * 1024) - #define FLASH_SECTOR_SIZE (4 * 1024) - -diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h -index 0f535850a3836..dcf8fb40698b7 100644 ---- a/drivers/net/wireless/rsi/rsi_main.h -+++ b/drivers/net/wireless/rsi/rsi_main.h -@@ -61,6 +61,7 @@ enum RSI_FSM_STATES { - extern u32 rsi_zone_enabled; - extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...); - -+#define RSI_MAX_BANDS 2 - #define RSI_MAX_VIFS 3 - #define NUM_EDCA_QUEUES 4 - #define IEEE80211_ADDR_LEN 6 -@@ -139,6 +140,7 @@ struct skb_info { - u8 internal_hdr_size; - struct ieee80211_vif *vif; - u8 vap_id; -+ bool have_key; - }; - - enum edca_queue { -@@ -229,6 +231,12 @@ struct rsi_9116_features { - u32 ps_options; - }; - -+struct rsi_rate_config { -+ u32 configured_mask; /* configured by mac80211 bits 0-11=legacy 12+ mcs */ -+ u16 fixed_hw_rate; -+ bool fixed_enabled; -+}; -+ - struct rsi_common { - struct rsi_hw *priv; - struct vif_priv vif_info[RSI_MAX_VIFS]; -@@ -254,8 +262,8 @@ struct rsi_common { - u8 channel_width; - - u16 rts_threshold; -- u16 bitrate_mask[2]; -- u32 fixedrate_mask[2]; -+ u32 bitrate_mask[RSI_MAX_BANDS]; -+ struct rsi_rate_config rate_config[RSI_MAX_BANDS]; - - u8 rf_reset; - struct transmit_q_stats tx_stats; -@@ -276,7 +284,6 @@ struct rsi_common { - u8 mac_id; - u8 radio_id; - u16 rate_pwr[20]; -- u16 min_rate; - - /* WMM algo related */ - u8 selected_qnum; -@@ -320,6 +327,7 @@ struct rsi_common { - struct ieee80211_vif *roc_vif; - - bool eapol4_confirm; -+ bool bt_defer_attach; - void *bt_adapter; - - struct cfg80211_scan_request *hwscan; -@@ -401,5 +409,6 @@ struct rsi_host_intf_ops { - - enum rsi_host_intf rsi_get_host_intf(void *priv); - void rsi_set_bt_context(void *priv, void *bt_context); -+void rsi_attach_bt(struct rsi_common *common); - - #endif -diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h -index 4a16d6e33c093..d9dea4829c86e 100644 ---- a/drivers/net/xen-netback/common.h -+++ b/drivers/net/xen-netback/common.h -@@ -203,6 +203,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */ - unsigned int rx_queue_max; - unsigned int rx_queue_len; - unsigned long last_rx_time; -+ unsigned int rx_slots_needed; - bool stalled; - - struct xenvif_copy_state rx_copy; -diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c -index accc991d153f7..dbac4c03d21a1 100644 ---- a/drivers/net/xen-netback/rx.c -+++ b/drivers/net/xen-netback/rx.c -@@ -33,28 +33,36 @@ - #include <xen/xen.h> - #include <xen/events.h> - --static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) -+/* -+ * Update the needed ring page slots for the first SKB queued. -+ * Note that any call sequence outside the RX thread calling this function -+ * needs to wake up the RX thread via a call of xenvif_kick_thread() -+ * afterwards in order to avoid a race with putting the thread to sleep. -+ */ -+static void xenvif_update_needed_slots(struct xenvif_queue *queue, -+ const struct sk_buff *skb) - { -- RING_IDX prod, cons; -- struct sk_buff *skb; -- int needed; -- unsigned long flags; -- -- spin_lock_irqsave(&queue->rx_queue.lock, flags); -+ unsigned int needed = 0; - -- skb = skb_peek(&queue->rx_queue); -- if (!skb) { -- spin_unlock_irqrestore(&queue->rx_queue.lock, flags); -- return false; -+ if (skb) { -+ needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); -+ if (skb_is_gso(skb)) -+ needed++; -+ if (skb->sw_hash) -+ needed++; - } - -- needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); -- if (skb_is_gso(skb)) -- needed++; -- if (skb->sw_hash) -- needed++; -+ WRITE_ONCE(queue->rx_slots_needed, needed); -+} - -- spin_unlock_irqrestore(&queue->rx_queue.lock, flags); -+static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) -+{ -+ RING_IDX prod, cons; -+ unsigned int needed; -+ -+ needed = READ_ONCE(queue->rx_slots_needed); -+ if (!needed) -+ return false; - - do { - prod = queue->rx.sring->req_prod; -@@ -80,13 +88,19 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb) - - spin_lock_irqsave(&queue->rx_queue.lock, flags); - -- __skb_queue_tail(&queue->rx_queue, skb); -- -- queue->rx_queue_len += skb->len; -- if (queue->rx_queue_len > queue->rx_queue_max) { -+ if (queue->rx_queue_len >= queue->rx_queue_max) { - struct net_device *dev = queue->vif->dev; - - netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id)); -+ kfree_skb(skb); -+ queue->vif->dev->stats.rx_dropped++; -+ } else { -+ if (skb_queue_empty(&queue->rx_queue)) -+ xenvif_update_needed_slots(queue, skb); -+ -+ __skb_queue_tail(&queue->rx_queue, skb); -+ -+ queue->rx_queue_len += skb->len; - } - - spin_unlock_irqrestore(&queue->rx_queue.lock, flags); -@@ -100,6 +114,8 @@ static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue) - - skb = __skb_dequeue(&queue->rx_queue); - if (skb) { -+ xenvif_update_needed_slots(queue, skb_peek(&queue->rx_queue)); -+ - queue->rx_queue_len -= skb->len; - if (queue->rx_queue_len < queue->rx_queue_max) { - struct netdev_queue *txq; -@@ -134,6 +150,7 @@ static void xenvif_rx_queue_drop_expired(struct xenvif_queue *queue) - break; - xenvif_rx_dequeue(queue); - kfree_skb(skb); -+ queue->vif->dev->stats.rx_dropped++; - } - } - -@@ -487,27 +504,31 @@ void xenvif_rx_action(struct xenvif_queue *queue) - xenvif_rx_copy_flush(queue); - } - --static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue) -+static RING_IDX xenvif_rx_queue_slots(const struct xenvif_queue *queue) - { - RING_IDX prod, cons; - - prod = queue->rx.sring->req_prod; - cons = queue->rx.req_cons; - -+ return prod - cons; -+} -+ -+static bool xenvif_rx_queue_stalled(const struct xenvif_queue *queue) -+{ -+ unsigned int needed = READ_ONCE(queue->rx_slots_needed); -+ - return !queue->stalled && -- prod - cons < 1 && -+ xenvif_rx_queue_slots(queue) < needed && - time_after(jiffies, - queue->last_rx_time + queue->vif->stall_timeout); - } - - static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) - { -- RING_IDX prod, cons; -- -- prod = queue->rx.sring->req_prod; -- cons = queue->rx.req_cons; -+ unsigned int needed = READ_ONCE(queue->rx_slots_needed); - -- return queue->stalled && prod - cons >= 1; -+ return queue->stalled && xenvif_rx_queue_slots(queue) >= needed; - } - - bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread) -diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c -index fc41ba95f81d0..8126e08f11a99 100644 ---- a/drivers/net/xen-netfront.c -+++ b/drivers/net/xen-netfront.c -@@ -148,6 +148,9 @@ struct netfront_queue { - grant_ref_t gref_rx_head; - grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; - -+ unsigned int rx_rsp_unconsumed; -+ spinlock_t rx_cons_lock; -+ - struct page_pool *page_pool; - struct xdp_rxq_info xdp_rxq; - }; -@@ -376,12 +379,13 @@ static int xennet_open(struct net_device *dev) - return 0; - } - --static void xennet_tx_buf_gc(struct netfront_queue *queue) -+static bool xennet_tx_buf_gc(struct netfront_queue *queue) - { - RING_IDX cons, prod; - unsigned short id; - struct sk_buff *skb; - bool more_to_do; -+ bool work_done = false; - const struct device *dev = &queue->info->netdev->dev; - - BUG_ON(!netif_carrier_ok(queue->info->netdev)); -@@ -398,6 +402,8 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) - for (cons = queue->tx.rsp_cons; cons != prod; cons++) { - struct xen_netif_tx_response txrsp; - -+ work_done = true; -+ - RING_COPY_RESPONSE(&queue->tx, cons, &txrsp); - if (txrsp.status == XEN_NETIF_RSP_NULL) - continue; -@@ -441,11 +447,13 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) - - xennet_maybe_wake_tx(queue); - -- return; -+ return work_done; - - err: - queue->info->broken = true; - dev_alert(dev, "Disabled for further use\n"); -+ -+ return work_done; - } - - struct xennet_gnttab_make_txreq { -@@ -834,6 +842,16 @@ static int xennet_close(struct net_device *dev) - return 0; - } - -+static void xennet_set_rx_rsp_cons(struct netfront_queue *queue, RING_IDX val) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&queue->rx_cons_lock, flags); -+ queue->rx.rsp_cons = val; -+ queue->rx_rsp_unconsumed = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx); -+ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); -+} -+ - static void xennet_move_rx_slot(struct netfront_queue *queue, struct sk_buff *skb, - grant_ref_t ref) - { -@@ -885,7 +903,7 @@ static int xennet_get_extras(struct netfront_queue *queue, - xennet_move_rx_slot(queue, skb, ref); - } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); - -- queue->rx.rsp_cons = cons; -+ xennet_set_rx_rsp_cons(queue, cons); - return err; - } - -@@ -1039,7 +1057,7 @@ next: - } - - if (unlikely(err)) -- queue->rx.rsp_cons = cons + slots; -+ xennet_set_rx_rsp_cons(queue, cons + slots); - - return err; - } -@@ -1093,7 +1111,8 @@ static int xennet_fill_frags(struct netfront_queue *queue, - __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); - } - if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) { -- queue->rx.rsp_cons = ++cons + skb_queue_len(list); -+ xennet_set_rx_rsp_cons(queue, -+ ++cons + skb_queue_len(list)); - kfree_skb(nskb); - return -ENOENT; - } -@@ -1106,7 +1125,7 @@ static int xennet_fill_frags(struct netfront_queue *queue, - kfree_skb(nskb); - } - -- queue->rx.rsp_cons = cons; -+ xennet_set_rx_rsp_cons(queue, cons); - - return 0; - } -@@ -1229,7 +1248,9 @@ err: - - if (unlikely(xennet_set_skb_gso(skb, gso))) { - __skb_queue_head(&tmpq, skb); -- queue->rx.rsp_cons += skb_queue_len(&tmpq); -+ xennet_set_rx_rsp_cons(queue, -+ queue->rx.rsp_cons + -+ skb_queue_len(&tmpq)); - goto err; - } - } -@@ -1253,7 +1274,8 @@ err: - - __skb_queue_tail(&rxq, skb); - -- i = ++queue->rx.rsp_cons; -+ i = queue->rx.rsp_cons + 1; -+ xennet_set_rx_rsp_cons(queue, i); - work_done++; - } - if (need_xdp_flush) -@@ -1417,40 +1439,79 @@ static int xennet_set_features(struct net_device *dev, - return 0; - } - --static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) -+static bool xennet_handle_tx(struct netfront_queue *queue, unsigned int *eoi) - { -- struct netfront_queue *queue = dev_id; - unsigned long flags; - -- if (queue->info->broken) -- return IRQ_HANDLED; -+ if (unlikely(queue->info->broken)) -+ return false; - - spin_lock_irqsave(&queue->tx_lock, flags); -- xennet_tx_buf_gc(queue); -+ if (xennet_tx_buf_gc(queue)) -+ *eoi = 0; - spin_unlock_irqrestore(&queue->tx_lock, flags); - -+ return true; -+} -+ -+static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) -+{ -+ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; -+ -+ if (likely(xennet_handle_tx(dev_id, &eoiflag))) -+ xen_irq_lateeoi(irq, eoiflag); -+ - return IRQ_HANDLED; - } - --static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) -+static bool xennet_handle_rx(struct netfront_queue *queue, unsigned int *eoi) - { -- struct netfront_queue *queue = dev_id; -- struct net_device *dev = queue->info->netdev; -+ unsigned int work_queued; -+ unsigned long flags; - -- if (queue->info->broken) -- return IRQ_HANDLED; -+ if (unlikely(queue->info->broken)) -+ return false; -+ -+ spin_lock_irqsave(&queue->rx_cons_lock, flags); -+ work_queued = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx); -+ if (work_queued > queue->rx_rsp_unconsumed) { -+ queue->rx_rsp_unconsumed = work_queued; -+ *eoi = 0; -+ } else if (unlikely(work_queued < queue->rx_rsp_unconsumed)) { -+ const struct device *dev = &queue->info->netdev->dev; -+ -+ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); -+ dev_alert(dev, "RX producer index going backwards\n"); -+ dev_alert(dev, "Disabled for further use\n"); -+ queue->info->broken = true; -+ return false; -+ } -+ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); - -- if (likely(netif_carrier_ok(dev) && -- RING_HAS_UNCONSUMED_RESPONSES(&queue->rx))) -+ if (likely(netif_carrier_ok(queue->info->netdev) && work_queued)) - napi_schedule(&queue->napi); - -+ return true; -+} -+ -+static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) -+{ -+ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; -+ -+ if (likely(xennet_handle_rx(dev_id, &eoiflag))) -+ xen_irq_lateeoi(irq, eoiflag); -+ - return IRQ_HANDLED; - } - - static irqreturn_t xennet_interrupt(int irq, void *dev_id) - { -- xennet_tx_interrupt(irq, dev_id); -- xennet_rx_interrupt(irq, dev_id); -+ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; -+ -+ if (xennet_handle_tx(dev_id, &eoiflag) && -+ xennet_handle_rx(dev_id, &eoiflag)) -+ xen_irq_lateeoi(irq, eoiflag); -+ - return IRQ_HANDLED; - } - -@@ -1768,9 +1829,10 @@ static int setup_netfront_single(struct netfront_queue *queue) - if (err < 0) - goto fail; - -- err = bind_evtchn_to_irqhandler(queue->tx_evtchn, -- xennet_interrupt, -- 0, queue->info->netdev->name, queue); -+ err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn, -+ xennet_interrupt, 0, -+ queue->info->netdev->name, -+ queue); - if (err < 0) - goto bind_fail; - queue->rx_evtchn = queue->tx_evtchn; -@@ -1798,18 +1860,18 @@ static int setup_netfront_split(struct netfront_queue *queue) - - snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), - "%s-tx", queue->name); -- err = bind_evtchn_to_irqhandler(queue->tx_evtchn, -- xennet_tx_interrupt, -- 0, queue->tx_irq_name, queue); -+ err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn, -+ xennet_tx_interrupt, 0, -+ queue->tx_irq_name, queue); - if (err < 0) - goto bind_tx_fail; - queue->tx_irq = err; - - snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), - "%s-rx", queue->name); -- err = bind_evtchn_to_irqhandler(queue->rx_evtchn, -- xennet_rx_interrupt, -- 0, queue->rx_irq_name, queue); -+ err = bind_evtchn_to_irqhandler_lateeoi(queue->rx_evtchn, -+ xennet_rx_interrupt, 0, -+ queue->rx_irq_name, queue); - if (err < 0) - goto bind_rx_fail; - queue->rx_irq = err; -@@ -1911,6 +1973,7 @@ static int xennet_init_queue(struct netfront_queue *queue) - - spin_lock_init(&queue->tx_lock); - spin_lock_init(&queue->rx_lock); -+ spin_lock_init(&queue->rx_cons_lock); - - timer_setup(&queue->rx_refill_timer, rx_refill_timeout, 0); - -diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c -index 2f3f3fe9a0baa..d32aec0c334fe 100644 ---- a/drivers/nfc/pn533/pn533.c -+++ b/drivers/nfc/pn533/pn533.c -@@ -2218,7 +2218,7 @@ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) - frag = pn533_alloc_skb(dev, frag_size); - if (!frag) { - skb_queue_purge(&dev->fragment_skb); -- break; -+ return -ENOMEM; - } - - if (!dev->tgt_mode) { -@@ -2287,7 +2287,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, - /* jumbo frame ? */ - if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { - rc = pn533_fill_fragment_skbs(dev, skb); -- if (rc <= 0) -+ if (rc < 0) - goto error; - - skb = skb_dequeue(&dev->fragment_skb); -@@ -2355,7 +2355,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) - /* let's split in multiple chunks if size's too big */ - if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { - rc = pn533_fill_fragment_skbs(dev, skb); -- if (rc <= 0) -+ if (rc < 0) - goto error; - - /* get the first skb */ -diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c -index 92dec49522972..3fd1bdb9fc05b 100644 ---- a/drivers/nvdimm/btt.c -+++ b/drivers/nvdimm/btt.c -@@ -1538,7 +1538,6 @@ static int btt_blk_init(struct btt *btt) - int rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt)); - - if (rc) { -- del_gendisk(btt->btt_disk); - blk_cleanup_disk(btt->btt_disk); - return rc; - } -diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c -index 054154c22899a..2721dd2ead0a7 100644 ---- a/drivers/nvdimm/pmem.c -+++ b/drivers/nvdimm/pmem.c -@@ -429,8 +429,10 @@ static int pmem_attach_disk(struct device *dev, - bb_range.end = res->end; - } - -- if (IS_ERR(addr)) -- return PTR_ERR(addr); -+ if (IS_ERR(addr)) { -+ rc = PTR_ERR(addr); -+ goto out; -+ } - pmem->virt_addr = addr; - - blk_queue_write_cache(q, true, fua); -@@ -455,7 +457,8 @@ static int pmem_attach_disk(struct device *dev, - flags = DAXDEV_F_SYNC; - dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags); - if (IS_ERR(dax_dev)) { -- return PTR_ERR(dax_dev); -+ rc = PTR_ERR(dax_dev); -+ goto out; - } - dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); - pmem->dax_dev = dax_dev; -@@ -470,8 +473,10 @@ static int pmem_attach_disk(struct device *dev, - "badblocks"); - if (!pmem->bb_state) - dev_warn(dev, "'badblocks' notification disabled\n"); -- - return 0; -+out: -+ blk_cleanup_disk(pmem->disk); -+ return rc; - } - - static int nd_pmem_probe(struct device *dev) -diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c -index fba06618c6c23..2f76969408b27 100644 ---- a/drivers/nvme/host/multipath.c -+++ b/drivers/nvme/host/multipath.c -@@ -138,13 +138,12 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl) - { - struct nvme_ns *ns; - -- mutex_lock(&ctrl->scan_lock); - down_read(&ctrl->namespaces_rwsem); -- list_for_each_entry(ns, &ctrl->namespaces, list) -- if (nvme_mpath_clear_current_path(ns)) -- kblockd_schedule_work(&ns->head->requeue_work); -+ list_for_each_entry(ns, &ctrl->namespaces, list) { -+ nvme_mpath_clear_current_path(ns); -+ kblockd_schedule_work(&ns->head->requeue_work); -+ } - up_read(&ctrl->namespaces_rwsem); -- mutex_unlock(&ctrl->scan_lock); - } - - void nvme_mpath_revalidate_paths(struct nvme_ns *ns) -diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c -index 042c594bc57e2..0498801542eb6 100644 ---- a/drivers/nvme/host/rdma.c -+++ b/drivers/nvme/host/rdma.c -@@ -1095,11 +1095,13 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new) - return ret; - - if (ctrl->ctrl.icdoff) { -+ ret = -EOPNOTSUPP; - dev_err(ctrl->ctrl.device, "icdoff is not supported!\n"); - goto destroy_admin; - } - - if (!(ctrl->ctrl.sgls & (1 << 2))) { -+ ret = -EOPNOTSUPP; - dev_err(ctrl->ctrl.device, - "Mandatory keyed sgls are not supported!\n"); - goto destroy_admin; -diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c -index be5d82421e3a4..496d775c67707 100644 ---- a/drivers/nvme/target/configfs.c -+++ b/drivers/nvme/target/configfs.c -@@ -1553,6 +1553,8 @@ static void nvmet_port_release(struct config_item *item) - { - struct nvmet_port *port = to_nvmet_port(item); - -+ /* Let inflight controllers teardown complete */ -+ flush_scheduled_work(); - list_del(&port->global_entry); - - kfree(port->ana_state); -diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c -index 1dd1a0fe2e819..df7e033dd2732 100644 ---- a/drivers/nvme/target/io-cmd-file.c -+++ b/drivers/nvme/target/io-cmd-file.c -@@ -8,6 +8,7 @@ - #include <linux/uio.h> - #include <linux/falloc.h> - #include <linux/file.h> -+#include <linux/fs.h> - #include "nvmet.h" - - #define NVMET_MAX_MPOOL_BVEC 16 -@@ -266,7 +267,8 @@ static void nvmet_file_execute_rw(struct nvmet_req *req) - - if (req->ns->buffered_io) { - if (likely(!req->f.mpool_alloc) && -- nvmet_file_execute_io(req, IOCB_NOWAIT)) -+ (req->ns->file->f_mode & FMODE_NOWAIT) && -+ nvmet_file_execute_io(req, IOCB_NOWAIT)) - return; - nvmet_file_submit_buffered_io(req); - } else -diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c -index 891174ccd44bb..f1eedbf493d5b 100644 ---- a/drivers/nvme/target/rdma.c -+++ b/drivers/nvme/target/rdma.c -@@ -1818,12 +1818,36 @@ restart: - mutex_unlock(&nvmet_rdma_queue_mutex); - } - -+static void nvmet_rdma_destroy_port_queues(struct nvmet_rdma_port *port) -+{ -+ struct nvmet_rdma_queue *queue, *tmp; -+ struct nvmet_port *nport = port->nport; -+ -+ mutex_lock(&nvmet_rdma_queue_mutex); -+ list_for_each_entry_safe(queue, tmp, &nvmet_rdma_queue_list, -+ queue_list) { -+ if (queue->port != nport) -+ continue; -+ -+ list_del_init(&queue->queue_list); -+ __nvmet_rdma_queue_disconnect(queue); -+ } -+ mutex_unlock(&nvmet_rdma_queue_mutex); -+} -+ - static void nvmet_rdma_disable_port(struct nvmet_rdma_port *port) - { - struct rdma_cm_id *cm_id = xchg(&port->cm_id, NULL); - - if (cm_id) - rdma_destroy_id(cm_id); -+ -+ /* -+ * Destroy the remaining queues, which are not belong to any -+ * controller yet. Do it here after the RDMA-CM was destroyed -+ * guarantees that no new queue will be created. -+ */ -+ nvmet_rdma_destroy_port_queues(port); - } - - static int nvmet_rdma_enable_port(struct nvmet_rdma_port *port) -diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c -index 46c3b3be7e033..2b8bab28417b8 100644 ---- a/drivers/nvme/target/tcp.c -+++ b/drivers/nvme/target/tcp.c -@@ -700,10 +700,11 @@ static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch) - static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch) - { - struct nvmet_tcp_queue *queue = cmd->queue; -+ int left = NVME_TCP_DIGEST_LENGTH - cmd->offset; - struct msghdr msg = { .msg_flags = MSG_DONTWAIT }; - struct kvec iov = { - .iov_base = (u8 *)&cmd->exp_ddgst + cmd->offset, -- .iov_len = NVME_TCP_DIGEST_LENGTH - cmd->offset -+ .iov_len = left - }; - int ret; - -@@ -717,6 +718,10 @@ static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch) - return ret; - - cmd->offset += ret; -+ left -= ret; -+ -+ if (left) -+ return -EAGAIN; - - if (queue->nvme_sq.sqhd_disabled) { - cmd->queue->snd_cmd = NULL; -@@ -1740,6 +1745,17 @@ err_port: - return ret; - } - -+static void nvmet_tcp_destroy_port_queues(struct nvmet_tcp_port *port) -+{ -+ struct nvmet_tcp_queue *queue; -+ -+ mutex_lock(&nvmet_tcp_queue_mutex); -+ list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list) -+ if (queue->port == port) -+ kernel_sock_shutdown(queue->sock, SHUT_RDWR); -+ mutex_unlock(&nvmet_tcp_queue_mutex); -+} -+ - static void nvmet_tcp_remove_port(struct nvmet_port *nport) - { - struct nvmet_tcp_port *port = nport->priv; -@@ -1749,6 +1765,11 @@ static void nvmet_tcp_remove_port(struct nvmet_port *nport) - port->sock->sk->sk_user_data = NULL; - write_unlock_bh(&port->sock->sk->sk_callback_lock); - cancel_work_sync(&port->accept_work); -+ /* -+ * Destroy the remaining queues, which are not belong to any -+ * controller yet. -+ */ -+ nvmet_tcp_destroy_port_queues(port); - - sock_release(port->sock); - kfree(port); -diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c -index 8c056972a6ddc..5b85a2a3792ae 100644 ---- a/drivers/of/unittest.c -+++ b/drivers/of/unittest.c -@@ -1688,19 +1688,19 @@ static void __init of_unittest_overlay_gpio(void) - */ - - EXPECT_BEGIN(KERN_INFO, -- "GPIO line <<int>> (line-B-input) hogged as input\n"); -+ "gpio-<<int>> (line-B-input): hogged as input\n"); - - EXPECT_BEGIN(KERN_INFO, -- "GPIO line <<int>> (line-A-input) hogged as input\n"); -+ "gpio-<<int>> (line-A-input): hogged as input\n"); - - ret = platform_driver_register(&unittest_gpio_driver); - if (unittest(ret == 0, "could not register unittest gpio driver\n")) - return; - - EXPECT_END(KERN_INFO, -- "GPIO line <<int>> (line-A-input) hogged as input\n"); -+ "gpio-<<int>> (line-A-input): hogged as input\n"); - EXPECT_END(KERN_INFO, -- "GPIO line <<int>> (line-B-input) hogged as input\n"); -+ "gpio-<<int>> (line-B-input): hogged as input\n"); - - unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, - "unittest_gpio_probe() failed or not called\n"); -@@ -1727,7 +1727,7 @@ static void __init of_unittest_overlay_gpio(void) - chip_request_count = unittest_gpio_chip_request_count; - - EXPECT_BEGIN(KERN_INFO, -- "GPIO line <<int>> (line-D-input) hogged as input\n"); -+ "gpio-<<int>> (line-D-input): hogged as input\n"); - - /* overlay_gpio_03 contains gpio node and child gpio hog node */ - -@@ -1735,7 +1735,7 @@ static void __init of_unittest_overlay_gpio(void) - "Adding overlay 'overlay_gpio_03' failed\n"); - - EXPECT_END(KERN_INFO, -- "GPIO line <<int>> (line-D-input) hogged as input\n"); -+ "gpio-<<int>> (line-D-input): hogged as input\n"); - - unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, - "unittest_gpio_probe() failed or not called\n"); -@@ -1774,7 +1774,7 @@ static void __init of_unittest_overlay_gpio(void) - */ - - EXPECT_BEGIN(KERN_INFO, -- "GPIO line <<int>> (line-C-input) hogged as input\n"); -+ "gpio-<<int>> (line-C-input): hogged as input\n"); - - /* overlay_gpio_04b contains child gpio hog node */ - -@@ -1782,7 +1782,7 @@ static void __init of_unittest_overlay_gpio(void) - "Adding overlay 'overlay_gpio_04b' failed\n"); - - EXPECT_END(KERN_INFO, -- "GPIO line <<int>> (line-C-input) hogged as input\n"); -+ "gpio-<<int>> (line-C-input): hogged as input\n"); - - unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, - "unittest_gpio_chip_request() called %d times (expected 1 time)\n", -diff --git a/drivers/opp/of.c b/drivers/opp/of.c -index 2a97c6535c4c6..c32ae7497392b 100644 ---- a/drivers/opp/of.c -+++ b/drivers/opp/of.c -@@ -921,7 +921,7 @@ free_required_opps: - free_opp: - _opp_free(new_opp); - -- return ERR_PTR(ret); -+ return ret ? ERR_PTR(ret) : NULL; - } - - /* Initializes OPP tables based on new bindings */ -diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c -index ffb176d288cd9..918e11082e6a7 100644 ---- a/drivers/pci/controller/cadence/pci-j721e.c -+++ b/drivers/pci/controller/cadence/pci-j721e.c -@@ -474,7 +474,7 @@ static int j721e_pcie_probe(struct platform_device *pdev) - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "failed to enable pcie_refclk\n"); -- goto err_get_sync; -+ goto err_pcie_setup; - } - pcie->refclk = clk; - -diff --git a/drivers/pci/controller/cadence/pcie-cadence-plat.c b/drivers/pci/controller/cadence/pcie-cadence-plat.c -index 5fee0f89ab594..a224afadbcc00 100644 ---- a/drivers/pci/controller/cadence/pcie-cadence-plat.c -+++ b/drivers/pci/controller/cadence/pcie-cadence-plat.c -@@ -127,6 +127,8 @@ static int cdns_plat_pcie_probe(struct platform_device *pdev) - goto err_init; - } - -+ return 0; -+ - err_init: - err_get_sync: - pm_runtime_put_sync(dev); -diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c -index d842fd0181299..d05be942956e2 100644 ---- a/drivers/pci/controller/dwc/pcie-uniphier.c -+++ b/drivers/pci/controller/dwc/pcie-uniphier.c -@@ -168,30 +168,21 @@ static void uniphier_pcie_irq_enable(struct uniphier_pcie_priv *priv) - writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX); - } - --static void uniphier_pcie_irq_ack(struct irq_data *d) --{ -- struct pcie_port *pp = irq_data_get_irq_chip_data(d); -- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -- struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); -- u32 val; -- -- val = readl(priv->base + PCL_RCV_INTX); -- val &= ~PCL_RCV_INTX_ALL_STATUS; -- val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_STATUS_SHIFT); -- writel(val, priv->base + PCL_RCV_INTX); --} -- - static void uniphier_pcie_irq_mask(struct irq_data *d) - { - struct pcie_port *pp = irq_data_get_irq_chip_data(d); - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); -+ unsigned long flags; - u32 val; - -+ raw_spin_lock_irqsave(&pp->lock, flags); -+ - val = readl(priv->base + PCL_RCV_INTX); -- val &= ~PCL_RCV_INTX_ALL_MASK; - val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT); - writel(val, priv->base + PCL_RCV_INTX); -+ -+ raw_spin_unlock_irqrestore(&pp->lock, flags); - } - - static void uniphier_pcie_irq_unmask(struct irq_data *d) -@@ -199,17 +190,20 @@ static void uniphier_pcie_irq_unmask(struct irq_data *d) - struct pcie_port *pp = irq_data_get_irq_chip_data(d); - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); -+ unsigned long flags; - u32 val; - -+ raw_spin_lock_irqsave(&pp->lock, flags); -+ - val = readl(priv->base + PCL_RCV_INTX); -- val &= ~PCL_RCV_INTX_ALL_MASK; - val &= ~BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT); - writel(val, priv->base + PCL_RCV_INTX); -+ -+ raw_spin_unlock_irqrestore(&pp->lock, flags); - } - - static struct irq_chip uniphier_pcie_irq_chip = { - .name = "PCI", -- .irq_ack = uniphier_pcie_irq_ack, - .irq_mask = uniphier_pcie_irq_mask, - .irq_unmask = uniphier_pcie_irq_unmask, - }; -diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c -index 596ebcfcc82dc..c3b725afa11fd 100644 ---- a/drivers/pci/controller/pci-aardvark.c -+++ b/drivers/pci/controller/pci-aardvark.c -@@ -31,9 +31,6 @@ - /* PCIe core registers */ - #define PCIE_CORE_DEV_ID_REG 0x0 - #define PCIE_CORE_CMD_STATUS_REG 0x4 --#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0) --#define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1) --#define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2) - #define PCIE_CORE_DEV_REV_REG 0x8 - #define PCIE_CORE_PCIEXP_CAP 0xc0 - #define PCIE_CORE_ERR_CAPCTL_REG 0x118 -@@ -99,6 +96,7 @@ - #define PCIE_CORE_CTRL2_MSI_ENABLE BIT(10) - #define PCIE_CORE_REF_CLK_REG (CONTROL_BASE_ADDR + 0x14) - #define PCIE_CORE_REF_CLK_TX_ENABLE BIT(1) -+#define PCIE_CORE_REF_CLK_RX_ENABLE BIT(2) - #define PCIE_MSG_LOG_REG (CONTROL_BASE_ADDR + 0x30) - #define PCIE_ISR0_REG (CONTROL_BASE_ADDR + 0x40) - #define PCIE_MSG_PM_PME_MASK BIT(7) -@@ -106,18 +104,19 @@ - #define PCIE_ISR0_MSI_INT_PENDING BIT(24) - #define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val)) - #define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val)) --#define PCIE_ISR0_ALL_MASK GENMASK(26, 0) -+#define PCIE_ISR0_ALL_MASK GENMASK(31, 0) - #define PCIE_ISR1_REG (CONTROL_BASE_ADDR + 0x48) - #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C) - #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4) - #define PCIE_ISR1_FLUSH BIT(5) - #define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val)) --#define PCIE_ISR1_ALL_MASK GENMASK(11, 4) -+#define PCIE_ISR1_ALL_MASK GENMASK(31, 0) - #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50) - #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) - #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) - #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) - #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) -+#define PCIE_MSI_DATA_MASK GENMASK(15, 0) - - /* PCIe window configuration */ - #define OB_WIN_BASE_ADDR 0x4c00 -@@ -164,8 +163,50 @@ - #define CFG_REG (LMI_BASE_ADDR + 0x0) - #define LTSSM_SHIFT 24 - #define LTSSM_MASK 0x3f --#define LTSSM_L0 0x10 - #define RC_BAR_CONFIG 0x300 -+ -+/* LTSSM values in CFG_REG */ -+enum { -+ LTSSM_DETECT_QUIET = 0x0, -+ LTSSM_DETECT_ACTIVE = 0x1, -+ LTSSM_POLLING_ACTIVE = 0x2, -+ LTSSM_POLLING_COMPLIANCE = 0x3, -+ LTSSM_POLLING_CONFIGURATION = 0x4, -+ LTSSM_CONFIG_LINKWIDTH_START = 0x5, -+ LTSSM_CONFIG_LINKWIDTH_ACCEPT = 0x6, -+ LTSSM_CONFIG_LANENUM_ACCEPT = 0x7, -+ LTSSM_CONFIG_LANENUM_WAIT = 0x8, -+ LTSSM_CONFIG_COMPLETE = 0x9, -+ LTSSM_CONFIG_IDLE = 0xa, -+ LTSSM_RECOVERY_RCVR_LOCK = 0xb, -+ LTSSM_RECOVERY_SPEED = 0xc, -+ LTSSM_RECOVERY_RCVR_CFG = 0xd, -+ LTSSM_RECOVERY_IDLE = 0xe, -+ LTSSM_L0 = 0x10, -+ LTSSM_RX_L0S_ENTRY = 0x11, -+ LTSSM_RX_L0S_IDLE = 0x12, -+ LTSSM_RX_L0S_FTS = 0x13, -+ LTSSM_TX_L0S_ENTRY = 0x14, -+ LTSSM_TX_L0S_IDLE = 0x15, -+ LTSSM_TX_L0S_FTS = 0x16, -+ LTSSM_L1_ENTRY = 0x17, -+ LTSSM_L1_IDLE = 0x18, -+ LTSSM_L2_IDLE = 0x19, -+ LTSSM_L2_TRANSMIT_WAKE = 0x1a, -+ LTSSM_DISABLED = 0x20, -+ LTSSM_LOOPBACK_ENTRY_MASTER = 0x21, -+ LTSSM_LOOPBACK_ACTIVE_MASTER = 0x22, -+ LTSSM_LOOPBACK_EXIT_MASTER = 0x23, -+ LTSSM_LOOPBACK_ENTRY_SLAVE = 0x24, -+ LTSSM_LOOPBACK_ACTIVE_SLAVE = 0x25, -+ LTSSM_LOOPBACK_EXIT_SLAVE = 0x26, -+ LTSSM_HOT_RESET = 0x27, -+ LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 0x28, -+ LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 0x29, -+ LTSSM_RECOVERY_EQUALIZATION_PHASE2 = 0x2a, -+ LTSSM_RECOVERY_EQUALIZATION_PHASE3 = 0x2b, -+}; -+ - #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) - - /* PCIe core controller registers */ -@@ -198,7 +239,7 @@ - #define PCIE_IRQ_MSI_INT2_DET BIT(21) - #define PCIE_IRQ_RC_DBELL_DET BIT(22) - #define PCIE_IRQ_EP_STATUS BIT(23) --#define PCIE_IRQ_ALL_MASK 0xfff0fb -+#define PCIE_IRQ_ALL_MASK GENMASK(31, 0) - #define PCIE_IRQ_ENABLE_INTS_MASK PCIE_IRQ_CORE_INT - - /* Transaction types */ -@@ -257,18 +298,49 @@ static inline u32 advk_readl(struct advk_pcie *pcie, u64 reg) - return readl(pcie->base + reg); - } - --static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg) -+static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie) - { -- return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8); -+ u32 val; -+ u8 ltssm_state; -+ -+ val = advk_readl(pcie, CFG_REG); -+ ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; -+ return ltssm_state; - } - --static int advk_pcie_link_up(struct advk_pcie *pcie) -+static inline bool advk_pcie_link_up(struct advk_pcie *pcie) - { -- u32 val, ltssm_state; -+ /* check if LTSSM is in normal operation - some L* state */ -+ u8 ltssm_state = advk_pcie_ltssm_state(pcie); -+ return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; -+} - -- val = advk_readl(pcie, CFG_REG); -- ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; -- return ltssm_state >= LTSSM_L0; -+static inline bool advk_pcie_link_active(struct advk_pcie *pcie) -+{ -+ /* -+ * According to PCIe Base specification 3.0, Table 4-14: Link -+ * Status Mapped to the LTSSM, and 4.2.6.3.6 Configuration.Idle -+ * is Link Up mapped to LTSSM Configuration.Idle, Recovery, L0, -+ * L0s, L1 and L2 states. And according to 3.2.1. Data Link -+ * Control and Management State Machine Rules is DL Up status -+ * reported in DL Active state. -+ */ -+ u8 ltssm_state = advk_pcie_ltssm_state(pcie); -+ return ltssm_state >= LTSSM_CONFIG_IDLE && ltssm_state < LTSSM_DISABLED; -+} -+ -+static inline bool advk_pcie_link_training(struct advk_pcie *pcie) -+{ -+ /* -+ * According to PCIe Base specification 3.0, Table 4-14: Link -+ * Status Mapped to the LTSSM is Link Training mapped to LTSSM -+ * Configuration and Recovery states. -+ */ -+ u8 ltssm_state = advk_pcie_ltssm_state(pcie); -+ return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START && -+ ltssm_state < LTSSM_L0) || -+ (ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 && -+ ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3)); - } - - static int advk_pcie_wait_for_link(struct advk_pcie *pcie) -@@ -291,7 +363,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie) - size_t retries; - - for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) { -- if (!advk_pcie_link_up(pcie)) -+ if (advk_pcie_link_training(pcie)) - break; - udelay(RETRAIN_WAIT_USLEEP_US); - } -@@ -299,23 +371,9 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie) - - static void advk_pcie_issue_perst(struct advk_pcie *pcie) - { -- u32 reg; -- - if (!pcie->reset_gpio) - return; - -- /* -- * As required by PCI Express spec (PCI Express Base Specification, REV. -- * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay -- * for at least 100ms after de-asserting PERST# signal is needed before -- * link training is enabled. So ensure that link training is disabled -- * prior de-asserting PERST# signal to fulfill that PCI Express spec -- * requirement. -- */ -- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); -- reg &= ~LINK_TRAINING_EN; -- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); -- - /* 10ms delay is needed for some cards */ - dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); - gpiod_set_value_cansleep(pcie->reset_gpio, 1); -@@ -323,53 +381,46 @@ static void advk_pcie_issue_perst(struct advk_pcie *pcie) - gpiod_set_value_cansleep(pcie->reset_gpio, 0); - } - --static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen) -+static void advk_pcie_train_link(struct advk_pcie *pcie) - { -- int ret, neg_gen; -+ struct device *dev = &pcie->pdev->dev; - u32 reg; -+ int ret; - -- /* Setup link speed */ -+ /* -+ * Setup PCIe rev / gen compliance based on device tree property -+ * 'max-link-speed' which also forces maximal link speed. -+ */ - reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); - reg &= ~PCIE_GEN_SEL_MSK; -- if (gen == 3) -+ if (pcie->link_gen == 3) - reg |= SPEED_GEN_3; -- else if (gen == 2) -+ else if (pcie->link_gen == 2) - reg |= SPEED_GEN_2; - else - reg |= SPEED_GEN_1; - advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); - - /* -- * Enable link training. This is not needed in every call to this -- * function, just once suffices, but it does not break anything either. -+ * Set maximal link speed value also into PCIe Link Control 2 register. -+ * Armada 3700 Functional Specification says that default value is based -+ * on SPEED_GEN but tests showed that default value is always 8.0 GT/s. - */ -+ reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); -+ reg &= ~PCI_EXP_LNKCTL2_TLS; -+ if (pcie->link_gen == 3) -+ reg |= PCI_EXP_LNKCTL2_TLS_8_0GT; -+ else if (pcie->link_gen == 2) -+ reg |= PCI_EXP_LNKCTL2_TLS_5_0GT; -+ else -+ reg |= PCI_EXP_LNKCTL2_TLS_2_5GT; -+ advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); -+ -+ /* Enable link training after selecting PCIe generation */ - reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); - reg |= LINK_TRAINING_EN; - advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); - -- /* -- * Start link training immediately after enabling it. -- * This solves problems for some buggy cards. -- */ -- reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); -- reg |= PCI_EXP_LNKCTL_RL; -- advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); -- -- ret = advk_pcie_wait_for_link(pcie); -- if (ret) -- return ret; -- -- reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA); -- neg_gen = reg & PCI_EXP_LNKSTA_CLS; -- -- return neg_gen; --} -- --static void advk_pcie_train_link(struct advk_pcie *pcie) --{ -- struct device *dev = &pcie->pdev->dev; -- int neg_gen = -1, gen; -- - /* - * Reset PCIe card via PERST# signal. Some cards are not detected - * during link training when they are in some non-initial state. -@@ -380,41 +431,18 @@ static void advk_pcie_train_link(struct advk_pcie *pcie) - * PERST# signal could have been asserted by pinctrl subsystem before - * probe() callback has been called or issued explicitly by reset gpio - * function advk_pcie_issue_perst(), making the endpoint going into -- * fundamental reset. As required by PCI Express spec a delay for at -- * least 100ms after such a reset before link training is needed. -- */ -- msleep(PCI_PM_D3COLD_WAIT); -- -- /* -- * Try link training at link gen specified by device tree property -- * 'max-link-speed'. If this fails, iteratively train at lower gen. -+ * fundamental reset. As required by PCI Express spec (PCI Express -+ * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1 -+ * Conventional Reset) a delay for at least 100ms after such a reset -+ * before sending a Configuration Request to the device is needed. -+ * So wait until PCIe link is up. Function advk_pcie_wait_for_link() -+ * waits for link at least 900ms. - */ -- for (gen = pcie->link_gen; gen > 0; --gen) { -- neg_gen = advk_pcie_train_at_gen(pcie, gen); -- if (neg_gen > 0) -- break; -- } -- -- if (neg_gen < 0) -- goto err; -- -- /* -- * After successful training if negotiated gen is lower than requested, -- * train again on negotiated gen. This solves some stability issues for -- * some buggy gen1 cards. -- */ -- if (neg_gen < gen) { -- gen = neg_gen; -- neg_gen = advk_pcie_train_at_gen(pcie, gen); -- } -- -- if (neg_gen == gen) { -- dev_info(dev, "link up at gen %i\n", gen); -- return; -- } -- --err: -- dev_err(dev, "link never came up\n"); -+ ret = advk_pcie_wait_for_link(pcie); -+ if (ret < 0) -+ dev_err(dev, "link never came up\n"); -+ else -+ dev_info(dev, "link up\n"); - } - - /* -@@ -451,9 +479,15 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) - u32 reg; - int i; - -- /* Enable TX */ -+ /* -+ * Configure PCIe Reference clock. Direction is from the PCIe -+ * controller to the endpoint card, so enable transmitting of -+ * Reference clock differential signal off-chip and disable -+ * receiving off-chip differential signal. -+ */ - reg = advk_readl(pcie, PCIE_CORE_REF_CLK_REG); - reg |= PCIE_CORE_REF_CLK_TX_ENABLE; -+ reg &= ~PCIE_CORE_REF_CLK_RX_ENABLE; - advk_writel(pcie, reg, PCIE_CORE_REF_CLK_REG); - - /* Set to Direct mode */ -@@ -477,6 +511,31 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) - reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL; - advk_writel(pcie, reg, VENDOR_ID_REG); - -+ /* -+ * Change Class Code of PCI Bridge device to PCI Bridge (0x600400), -+ * because the default value is Mass storage controller (0x010400). -+ * -+ * Note that this Aardvark PCI Bridge does not have compliant Type 1 -+ * Configuration Space and it even cannot be accessed via Aardvark's -+ * PCI config space access method. Something like config space is -+ * available in internal Aardvark registers starting at offset 0x0 -+ * and is reported as Type 0. In range 0x10 - 0x34 it has totally -+ * different registers. -+ * -+ * Therefore driver uses emulation of PCI Bridge which emulates -+ * access to configuration space via internal Aardvark registers or -+ * emulated configuration buffer. -+ */ -+ reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG); -+ reg &= ~0xffffff00; -+ reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8; -+ advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG); -+ -+ /* Disable Root Bridge I/O space, memory space and bus mastering */ -+ reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); -+ reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); -+ advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); -+ - /* Set Advanced Error Capabilities and Control PF0 register */ - reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX | - PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN | -@@ -488,8 +547,9 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) - reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); - reg &= ~PCI_EXP_DEVCTL_RELAX_EN; - reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; -+ reg &= ~PCI_EXP_DEVCTL_PAYLOAD; - reg &= ~PCI_EXP_DEVCTL_READRQ; -- reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */ -+ reg |= PCI_EXP_DEVCTL_PAYLOAD_512B; - reg |= PCI_EXP_DEVCTL_READRQ_512B; - advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); - -@@ -574,19 +634,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) - advk_pcie_disable_ob_win(pcie, i); - - advk_pcie_train_link(pcie); -- -- /* -- * FIXME: The following register update is suspicious. This register is -- * applicable only when the PCI controller is configured for Endpoint -- * mode, not as a Root Complex. But apparently when this code is -- * removed, some cards stop working. This should be investigated and -- * a comment explaining this should be put here. -- */ -- reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); -- reg |= PCIE_CORE_CMD_MEM_ACCESS_EN | -- PCIE_CORE_CMD_IO_ACCESS_EN | -- PCIE_CORE_CMD_MEM_IO_REQ_EN; -- advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); - } - - static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val) -@@ -595,6 +642,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 - u32 reg; - unsigned int status; - char *strcomp_status, *str_posted; -+ int ret; - - reg = advk_readl(pcie, PIO_STAT); - status = (reg & PIO_COMPLETION_STATUS_MASK) >> -@@ -619,6 +667,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 - case PIO_COMPLETION_STATUS_OK: - if (reg & PIO_ERR_STATUS) { - strcomp_status = "COMP_ERR"; -+ ret = -EFAULT; - break; - } - /* Get the read result */ -@@ -626,9 +675,11 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 - *val = advk_readl(pcie, PIO_RD_DATA); - /* No error */ - strcomp_status = NULL; -+ ret = 0; - break; - case PIO_COMPLETION_STATUS_UR: - strcomp_status = "UR"; -+ ret = -EOPNOTSUPP; - break; - case PIO_COMPLETION_STATUS_CRS: - if (allow_crs && val) { -@@ -646,6 +697,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 - */ - *val = CFG_RD_CRS_VAL; - strcomp_status = NULL; -+ ret = 0; - break; - } - /* PCIe r4.0, sec 2.3.2, says: -@@ -661,31 +713,34 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 - * Request and taking appropriate action, e.g., complete the - * Request to the host as a failed transaction. - * -- * To simplify implementation do not re-issue the Configuration -- * Request and complete the Request as a failed transaction. -+ * So return -EAGAIN and caller (pci-aardvark.c driver) will -+ * re-issue request again up to the PIO_RETRY_CNT retries. - */ - strcomp_status = "CRS"; -+ ret = -EAGAIN; - break; - case PIO_COMPLETION_STATUS_CA: - strcomp_status = "CA"; -+ ret = -ECANCELED; - break; - default: - strcomp_status = "Unknown"; -+ ret = -EINVAL; - break; - } - - if (!strcomp_status) -- return 0; -+ return ret; - - if (reg & PIO_NON_POSTED_REQ) - str_posted = "Non-posted"; - else - str_posted = "Posted"; - -- dev_err(dev, "%s PIO Response Status: %s, %#x @ %#x\n", -+ dev_dbg(dev, "%s PIO Response Status: %s, %#x @ %#x\n", - str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS)); - -- return -EFAULT; -+ return ret; - } - - static int advk_pcie_wait_pio(struct advk_pcie *pcie) -@@ -693,13 +748,13 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie) - struct device *dev = &pcie->pdev->dev; - int i; - -- for (i = 0; i < PIO_RETRY_CNT; i++) { -+ for (i = 1; i <= PIO_RETRY_CNT; i++) { - u32 start, isr; - - start = advk_readl(pcie, PIO_START); - isr = advk_readl(pcie, PIO_ISR); - if (!start && isr) -- return 0; -+ return i; - udelay(PIO_RETRY_DELAY); - } - -@@ -707,6 +762,64 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie) - return -ETIMEDOUT; - } - -+static pci_bridge_emul_read_status_t -+advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, -+ int reg, u32 *value) -+{ -+ struct advk_pcie *pcie = bridge->data; -+ -+ switch (reg) { -+ case PCI_COMMAND: -+ *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); -+ return PCI_BRIDGE_EMUL_HANDLED; -+ -+ case PCI_INTERRUPT_LINE: { -+ /* -+ * From the whole 32bit register we support reading from HW only -+ * one bit: PCI_BRIDGE_CTL_BUS_RESET. -+ * Other bits are retrieved only from emulated config buffer. -+ */ -+ __le32 *cfgspace = (__le32 *)&bridge->conf; -+ u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]); -+ if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN) -+ val |= PCI_BRIDGE_CTL_BUS_RESET << 16; -+ else -+ val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16); -+ *value = val; -+ return PCI_BRIDGE_EMUL_HANDLED; -+ } -+ -+ default: -+ return PCI_BRIDGE_EMUL_NOT_HANDLED; -+ } -+} -+ -+static void -+advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, -+ int reg, u32 old, u32 new, u32 mask) -+{ -+ struct advk_pcie *pcie = bridge->data; -+ -+ switch (reg) { -+ case PCI_COMMAND: -+ advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG); -+ break; -+ -+ case PCI_INTERRUPT_LINE: -+ if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { -+ u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); -+ if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) -+ val |= HOT_RESET_GEN; -+ else -+ val &= ~HOT_RESET_GEN; -+ advk_writel(pcie, val, PCIE_CORE_CTRL1_REG); -+ } -+ break; -+ -+ default: -+ break; -+ } -+} - - static pci_bridge_emul_read_status_t - advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, -@@ -723,6 +836,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, - case PCI_EXP_RTCTL: { - u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); - *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; -+ *value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE; - *value |= PCI_EXP_RTCAP_CRSVIS << 16; - return PCI_BRIDGE_EMUL_HANDLED; - } -@@ -734,12 +848,26 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, - return PCI_BRIDGE_EMUL_HANDLED; - } - -+ case PCI_EXP_LNKCAP: { -+ u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); -+ /* -+ * PCI_EXP_LNKCAP_DLLLARC bit is hardwired in aardvark HW to 0. -+ * But support for PCI_EXP_LNKSTA_DLLLA is emulated via ltssm -+ * state so explicitly enable PCI_EXP_LNKCAP_DLLLARC flag. -+ */ -+ val |= PCI_EXP_LNKCAP_DLLLARC; -+ *value = val; -+ return PCI_BRIDGE_EMUL_HANDLED; -+ } -+ - case PCI_EXP_LNKCTL: { - /* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */ - u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) & - ~(PCI_EXP_LNKSTA_LT << 16); -- if (!advk_pcie_link_up(pcie)) -+ if (advk_pcie_link_training(pcie)) - val |= (PCI_EXP_LNKSTA_LT << 16); -+ if (advk_pcie_link_active(pcie)) -+ val |= (PCI_EXP_LNKSTA_DLLLA << 16); - *value = val; - return PCI_BRIDGE_EMUL_HANDLED; - } -@@ -747,7 +875,6 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, - case PCI_CAP_LIST_ID: - case PCI_EXP_DEVCAP: - case PCI_EXP_DEVCTL: -- case PCI_EXP_LNKCAP: - *value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); - return PCI_BRIDGE_EMUL_HANDLED; - default: -@@ -794,6 +921,8 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, - } - - static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = { -+ .read_base = advk_pci_bridge_emul_base_conf_read, -+ .write_base = advk_pci_bridge_emul_base_conf_write, - .read_pcie = advk_pci_bridge_emul_pcie_conf_read, - .write_pcie = advk_pci_bridge_emul_pcie_conf_write, - }; -@@ -805,7 +934,6 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = { - static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) - { - struct pci_bridge_emul *bridge = &pcie->bridge; -- int ret; - - bridge->conf.vendor = - cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff); -@@ -825,19 +953,14 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) - /* Support interrupt A for MSI feature */ - bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE; - -+ /* Indicates supports for Completion Retry Status */ -+ bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS); -+ - bridge->has_pcie = true; - bridge->data = pcie; - bridge->ops = &advk_pci_bridge_emul_ops; - -- /* PCIe config space can be initialized after pci_bridge_emul_init() */ -- ret = pci_bridge_emul_init(bridge, 0); -- if (ret < 0) -- return ret; -- -- /* Indicates supports for Completion Retry Status */ -- bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS); -- -- return 0; -+ return pci_bridge_emul_init(bridge, 0); - } - - static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, -@@ -889,6 +1012,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, - int where, int size, u32 *val) - { - struct advk_pcie *pcie = bus->sysdata; -+ int retry_count; - bool allow_crs; - u32 reg; - int ret; -@@ -911,18 +1035,8 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, - (le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & - PCI_EXP_RTCTL_CRSSVE); - -- if (advk_pcie_pio_is_running(pcie)) { -- /* -- * If it is possible return Completion Retry Status so caller -- * tries to issue the request again instead of failing. -- */ -- if (allow_crs) { -- *val = CFG_RD_CRS_VAL; -- return PCIBIOS_SUCCESSFUL; -- } -- *val = 0xffffffff; -- return PCIBIOS_SET_FAILED; -- } -+ if (advk_pcie_pio_is_running(pcie)) -+ goto try_crs; - - /* Program the control register */ - reg = advk_readl(pcie, PIO_CTRL); -@@ -941,30 +1055,24 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, - /* Program the data strobe */ - advk_writel(pcie, 0xf, PIO_WR_DATA_STRB); - -- /* Clear PIO DONE ISR and start the transfer */ -- advk_writel(pcie, 1, PIO_ISR); -- advk_writel(pcie, 1, PIO_START); -+ retry_count = 0; -+ do { -+ /* Clear PIO DONE ISR and start the transfer */ -+ advk_writel(pcie, 1, PIO_ISR); -+ advk_writel(pcie, 1, PIO_START); - -- ret = advk_pcie_wait_pio(pcie); -- if (ret < 0) { -- /* -- * If it is possible return Completion Retry Status so caller -- * tries to issue the request again instead of failing. -- */ -- if (allow_crs) { -- *val = CFG_RD_CRS_VAL; -- return PCIBIOS_SUCCESSFUL; -- } -- *val = 0xffffffff; -- return PCIBIOS_SET_FAILED; -- } -+ ret = advk_pcie_wait_pio(pcie); -+ if (ret < 0) -+ goto try_crs; - -- /* Check PIO status and get the read result */ -- ret = advk_pcie_check_pio_status(pcie, allow_crs, val); -- if (ret < 0) { -- *val = 0xffffffff; -- return PCIBIOS_SET_FAILED; -- } -+ retry_count += ret; -+ -+ /* Check PIO status and get the read result */ -+ ret = advk_pcie_check_pio_status(pcie, allow_crs, val); -+ } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT); -+ -+ if (ret < 0) -+ goto fail; - - if (size == 1) - *val = (*val >> (8 * (where & 3))) & 0xff; -@@ -972,6 +1080,20 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, - *val = (*val >> (8 * (where & 3))) & 0xffff; - - return PCIBIOS_SUCCESSFUL; -+ -+try_crs: -+ /* -+ * If it is possible, return Completion Retry Status so that caller -+ * tries to issue the request again instead of failing. -+ */ -+ if (allow_crs) { -+ *val = CFG_RD_CRS_VAL; -+ return PCIBIOS_SUCCESSFUL; -+ } -+ -+fail: -+ *val = 0xffffffff; -+ return PCIBIOS_SET_FAILED; - } - - static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, -@@ -980,6 +1102,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, - struct advk_pcie *pcie = bus->sysdata; - u32 reg; - u32 data_strobe = 0x0; -+ int retry_count; - int offset; - int ret; - -@@ -1021,19 +1144,22 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, - /* Program the data strobe */ - advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB); - -- /* Clear PIO DONE ISR and start the transfer */ -- advk_writel(pcie, 1, PIO_ISR); -- advk_writel(pcie, 1, PIO_START); -+ retry_count = 0; -+ do { -+ /* Clear PIO DONE ISR and start the transfer */ -+ advk_writel(pcie, 1, PIO_ISR); -+ advk_writel(pcie, 1, PIO_START); - -- ret = advk_pcie_wait_pio(pcie); -- if (ret < 0) -- return PCIBIOS_SET_FAILED; -+ ret = advk_pcie_wait_pio(pcie); -+ if (ret < 0) -+ return PCIBIOS_SET_FAILED; - -- ret = advk_pcie_check_pio_status(pcie, false, NULL); -- if (ret < 0) -- return PCIBIOS_SET_FAILED; -+ retry_count += ret; - -- return PCIBIOS_SUCCESSFUL; -+ ret = advk_pcie_check_pio_status(pcie, false, NULL); -+ } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT); -+ -+ return ret < 0 ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL; - } - - static struct pci_ops advk_pcie_ops = { -@@ -1082,7 +1208,7 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain, - domain->host_data, handle_simple_irq, - NULL, NULL); - -- return hwirq; -+ return 0; - } - - static void advk_msi_irq_domain_free(struct irq_domain *domain, -@@ -1263,8 +1389,12 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie) - if (!(BIT(msi_idx) & msi_status)) - continue; - -+ /* -+ * msi_idx contains bits [4:0] of the msi_data and msi_data -+ * contains 16bit MSI interrupt number -+ */ - advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG); -- msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & 0xFF; -+ msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK; - generic_handle_irq(msi_data); - } - -@@ -1286,12 +1416,6 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie) - isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); - isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); - -- if (!isr0_status && !isr1_status) { -- advk_writel(pcie, isr0_val, PCIE_ISR0_REG); -- advk_writel(pcie, isr1_val, PCIE_ISR1_REG); -- return; -- } -- - /* Process MSI interrupts */ - if (isr0_status & PCIE_ISR0_MSI_INT_PENDING) - advk_pcie_handle_msi(pcie); -diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c -index 4b4792940e869..e11530cb05699 100644 ---- a/drivers/pci/msi.c -+++ b/drivers/pci/msi.c -@@ -148,6 +148,9 @@ static noinline void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 s - raw_spinlock_t *lock = &desc->dev->msi_lock; - unsigned long flags; - -+ if (!desc->msi_attrib.can_mask) -+ return; -+ - raw_spin_lock_irqsave(lock, flags); - desc->msi_mask &= ~clear; - desc->msi_mask |= set; -@@ -181,7 +184,8 @@ static void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl) - { - void __iomem *desc_addr = pci_msix_desc_addr(desc); - -- writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); -+ if (desc->msi_attrib.can_mask) -+ writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); - } - - static inline void pci_msix_mask(struct msi_desc *desc) -@@ -200,23 +204,17 @@ static inline void pci_msix_unmask(struct msi_desc *desc) - - static void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask) - { -- if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual) -- return; -- - if (desc->msi_attrib.is_msix) - pci_msix_mask(desc); -- else if (desc->msi_attrib.maskbit) -+ else - pci_msi_mask(desc, mask); - } - - static void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask) - { -- if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual) -- return; -- - if (desc->msi_attrib.is_msix) - pci_msix_unmask(desc); -- else if (desc->msi_attrib.maskbit) -+ else - pci_msi_unmask(desc, mask); - } - -@@ -370,6 +368,11 @@ static void free_msi_irqs(struct pci_dev *dev) - for (i = 0; i < entry->nvec_used; i++) - BUG_ON(irq_has_action(entry->irq + i)); - -+ if (dev->msi_irq_groups) { -+ msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups); -+ dev->msi_irq_groups = NULL; -+ } -+ - pci_msi_teardown_msi_irqs(dev); - - list_for_each_entry_safe(entry, tmp, msi_list, list) { -@@ -381,11 +384,6 @@ static void free_msi_irqs(struct pci_dev *dev) - list_del(&entry->list); - free_msi_entry(entry); - } -- -- if (dev->msi_irq_groups) { -- msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups); -- dev->msi_irq_groups = NULL; -- } - } - - static void pci_intx_for_msi(struct pci_dev *dev, int enable) -@@ -479,12 +477,16 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) - goto out; - - pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); -+ /* Lies, damned lies, and MSIs */ -+ if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING) -+ control |= PCI_MSI_FLAGS_MASKBIT; - - entry->msi_attrib.is_msix = 0; - entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT); - entry->msi_attrib.is_virtual = 0; - entry->msi_attrib.entry_nr = 0; -- entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT); -+ entry->msi_attrib.can_mask = !pci_msi_ignore_mask && -+ !!(control & PCI_MSI_FLAGS_MASKBIT); - entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ - entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1; - entry->msi_attrib.multiple = ilog2(__roundup_pow_of_two(nvec)); -@@ -495,7 +497,7 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) - entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32; - - /* Save the initial mask status */ -- if (entry->msi_attrib.maskbit) -+ if (entry->msi_attrib.can_mask) - pci_read_config_dword(dev, entry->mask_pos, &entry->msi_mask); - - out: -@@ -638,10 +640,13 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, - entry->msi_attrib.is_virtual = - entry->msi_attrib.entry_nr >= vec_count; - -+ entry->msi_attrib.can_mask = !pci_msi_ignore_mask && -+ !entry->msi_attrib.is_virtual; -+ - entry->msi_attrib.default_irq = dev->irq; - entry->mask_base = base; - -- if (!entry->msi_attrib.is_virtual) { -+ if (entry->msi_attrib.can_mask) { - addr = pci_msix_desc_addr(entry); - entry->msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); - } -@@ -716,9 +721,6 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, - goto out_disable; - } - -- /* Ensure that all table entries are masked. */ -- msix_mask_all(base, tsize); -- - ret = msix_setup_entries(dev, base, entries, nvec, affd); - if (ret) - goto out_disable; -@@ -745,6 +747,16 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, - /* Set MSI-X enabled bits and unmask the function */ - pci_intx_for_msi(dev, 0); - dev->msix_enabled = 1; -+ -+ /* -+ * Ensure that all table entries are masked to prevent -+ * stale entries from firing in a crash kernel. -+ * -+ * Done late to deal with a broken Marvell NVME device -+ * which takes the MSI-X mask bits into account even -+ * when MSI-X is disabled, which prevents MSI delivery. -+ */ -+ msix_mask_all(base, tsize); - pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); - - pcibios_free_irq(dev); -@@ -771,7 +783,7 @@ out_free: - free_msi_irqs(dev); - - out_disable: -- pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); -+ pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); - - return ret; - } -diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c -index fdaf86a888b73..db97cddfc85e1 100644 ---- a/drivers/pci/pci-bridge-emul.c -+++ b/drivers/pci/pci-bridge-emul.c -@@ -431,8 +431,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, - /* Clear the W1C bits */ - new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); - -+ /* Save the new value with the cleared W1C bits into the cfgspace */ - cfgspace[reg / 4] = cpu_to_le32(new); - -+ /* -+ * Clear the W1C bits not specified by the write mask, so that the -+ * write_op() does not clear them. -+ */ -+ new &= ~(behavior[reg / 4].w1c & ~mask); -+ -+ /* -+ * Set the W1C bits specified by the write mask, so that write_op() -+ * knows about that they are to be cleared. -+ */ -+ new |= (value << shift) & (behavior[reg / 4].w1c & mask); -+ - if (write_op) - write_op(bridge, reg, old, new, mask); - -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index ce2ab62b64cfa..a101faf3e88a9 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -3719,6 +3719,14 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) - struct pci_dev *bridge; - u32 cap, ctl2; - -+ /* -+ * Per PCIe r5.0, sec 9.3.5.10, the AtomicOp Requester Enable bit -+ * in Device Control 2 is reserved in VFs and the PF value applies -+ * to all associated VFs. -+ */ -+ if (dev->is_virtfn) -+ return -EINVAL; -+ - if (!pci_is_pcie(dev)) - return -EINVAL; - -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 4537d1ea14fdc..208fa03acdda0 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -3612,6 +3612,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset); -+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset); - - /* - * Root port on some Cavium CN8xxx chips do not successfully complete a bus -@@ -5795,3 +5796,9 @@ static void apex_pci_fixup_class(struct pci_dev *pdev) - } - DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a, - PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class); -+ -+static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) -+{ -+ pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING; -+} -+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup); -diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c -index 4076580fc2cd9..ab1b0986aa671 100644 ---- a/drivers/phy/microchip/sparx5_serdes.c -+++ b/drivers/phy/microchip/sparx5_serdes.c -@@ -2475,10 +2475,10 @@ static int sparx5_serdes_probe(struct platform_device *pdev) - return -EINVAL; - } - iomem = devm_ioremap(priv->dev, iores->start, resource_size(iores)); -- if (IS_ERR(iomem)) { -+ if (!iomem) { - dev_err(priv->dev, "Unable to get serdes registers: %s\n", - iores->name); -- return PTR_ERR(iomem); -+ return -ENOMEM; - } - for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) { - struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx]; -diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c -index f14032170b1c1..06b04606dd7ea 100644 ---- a/drivers/phy/qualcomm/phy-qcom-qmp.c -+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c -@@ -3632,7 +3632,7 @@ static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { - .nlanes = 1, - - .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, -- .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), -+ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), - .tx_tbl = sc8180x_qmp_pcie_tx_tbl, - .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), - .rx_tbl = sc8180x_qmp_pcie_rx_tbl, -diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c -index 3c1d3b71c825b..f1d97fbd13318 100644 ---- a/drivers/phy/qualcomm/phy-qcom-qusb2.c -+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c -@@ -561,7 +561,7 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) - { - struct device *dev = &qphy->phy->dev; - const struct qusb2_phy_cfg *cfg = qphy->cfg; -- u8 *val; -+ u8 *val, hstx_trim; - - /* efuse register is optional */ - if (!qphy->cell) -@@ -575,7 +575,13 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) - * set while configuring the phy. - */ - val = nvmem_cell_read(qphy->cell, NULL); -- if (IS_ERR(val) || !val[0]) { -+ if (IS_ERR(val)) { -+ dev_dbg(dev, "failed to read a valid hs-tx trim value\n"); -+ return; -+ } -+ hstx_trim = val[0]; -+ kfree(val); -+ if (!hstx_trim) { - dev_dbg(dev, "failed to read a valid hs-tx trim value\n"); - return; - } -@@ -583,12 +589,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) - /* Fused TUNE1/2 value is the higher nibble only */ - if (cfg->update_tune1_with_efuse) - qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], -- val[0] << HSTX_TRIM_SHIFT, -- HSTX_TRIM_MASK); -+ hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK); - else - qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2], -- val[0] << HSTX_TRIM_SHIFT, -- HSTX_TRIM_MASK); -+ hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK); - } - - static int qusb2_phy_set_mode(struct phy *phy, -diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c -index ae4bac024c7b1..7e61202aa234e 100644 ---- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c -+++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c -@@ -33,7 +33,7 @@ - - #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) - #define RETENABLEN BIT(3) --#define FSEL_MASK GENMASK(7, 5) -+#define FSEL_MASK GENMASK(6, 4) - #define FSEL_DEFAULT (0x3 << 4) - - #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58) -diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c -index 5fd2e8a08bfcf..d0ab69750c6b4 100644 ---- a/drivers/phy/ti/phy-gmii-sel.c -+++ b/drivers/phy/ti/phy-gmii-sel.c -@@ -320,6 +320,8 @@ static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv) - u64 size; - - offset = of_get_address(dev->of_node, 0, &size, NULL); -+ if (!offset) -+ return -EINVAL; - priv->num_ports = size / sizeof(u32); - if (!priv->num_ports) - return -EINVAL; -diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c -index 5082102d7d0d9..ffe39336fcaca 100644 ---- a/drivers/pinctrl/core.c -+++ b/drivers/pinctrl/core.c -@@ -2100,6 +2100,8 @@ int pinctrl_enable(struct pinctrl_dev *pctldev) - if (error) { - dev_err(pctldev->dev, "could not claim hogs: %i\n", - error); -+ pinctrl_free_pindescs(pctldev, pctldev->desc->pins, -+ pctldev->desc->npins); - mutex_destroy(&pctldev->mutex); - kfree(pctldev); - -diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c -index bae9d429b813e..ecab9064a8458 100644 ---- a/drivers/pinctrl/pinctrl-amd.c -+++ b/drivers/pinctrl/pinctrl-amd.c -@@ -598,14 +598,14 @@ static struct irq_chip amd_gpio_irqchip = { - - #define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF)) - --static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) -+static bool do_amd_gpio_irq_handler(int irq, void *dev_id) - { - struct amd_gpio *gpio_dev = dev_id; - struct gpio_chip *gc = &gpio_dev->gc; -- irqreturn_t ret = IRQ_NONE; - unsigned int i, irqnr; - unsigned long flags; - u32 __iomem *regs; -+ bool ret = false; - u32 regval; - u64 status, mask; - -@@ -627,6 +627,14 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) - /* Each status bit covers four pins */ - for (i = 0; i < 4; i++) { - regval = readl(regs + i); -+ /* caused wake on resume context for shared IRQ */ -+ if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) { -+ dev_dbg(&gpio_dev->pdev->dev, -+ "Waking due to GPIO %d: 0x%x", -+ irqnr + i, regval); -+ return true; -+ } -+ - if (!(regval & PIN_IRQ_PENDING) || - !(regval & BIT(INTERRUPT_MASK_OFF))) - continue; -@@ -650,9 +658,12 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) - } - writel(regval, regs + i); - raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); -- ret = IRQ_HANDLED; -+ ret = true; - } - } -+ /* did not cause wake on resume context for shared IRQ */ -+ if (irq < 0) -+ return false; - - /* Signal EOI to the GPIO unit */ - raw_spin_lock_irqsave(&gpio_dev->lock, flags); -@@ -664,6 +675,16 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) - return ret; - } - -+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) -+{ -+ return IRQ_RETVAL(do_amd_gpio_irq_handler(irq, dev_id)); -+} -+ -+static bool __maybe_unused amd_gpio_check_wake(void *dev_id) -+{ -+ return do_amd_gpio_irq_handler(-1, dev_id); -+} -+ - static int amd_get_groups_count(struct pinctrl_dev *pctldev) - { - struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev); -@@ -1033,6 +1054,7 @@ static int amd_gpio_probe(struct platform_device *pdev) - goto out2; - - platform_set_drvdata(pdev, gpio_dev); -+ acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev); - - dev_dbg(&pdev->dev, "amd gpio driver loaded\n"); - return ret; -@@ -1050,6 +1072,7 @@ static int amd_gpio_remove(struct platform_device *pdev) - gpio_dev = platform_get_drvdata(pdev); - - gpiochip_remove(&gpio_dev->gc); -+ acpi_unregister_wakeup_handler(amd_gpio_check_wake, gpio_dev); - - return 0; - } -diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c -index fb713f9c53d0e..3f0143087cc77 100644 ---- a/drivers/pinctrl/pinctrl-equilibrium.c -+++ b/drivers/pinctrl/pinctrl-equilibrium.c -@@ -675,6 +675,11 @@ static int eqbr_build_functions(struct eqbr_pinctrl_drv_data *drvdata) - return ret; - - for (i = 0; i < nr_funcs; i++) { -+ -+ /* Ignore the same function with multiple groups */ -+ if (funcs[i].name == NULL) -+ continue; -+ - ret = pinmux_generic_add_function(drvdata->pctl_dev, - funcs[i].name, - funcs[i].groups, -@@ -815,7 +820,7 @@ static int pinctrl_reg(struct eqbr_pinctrl_drv_data *drvdata) - - ret = eqbr_build_functions(drvdata); - if (ret) { -- dev_err(dev, "Failed to build groups\n"); -+ dev_err(dev, "Failed to build functions\n"); - return ret; - } - -diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig -index 5ff4207df66e1..f1b5176a5085b 100644 ---- a/drivers/pinctrl/qcom/Kconfig -+++ b/drivers/pinctrl/qcom/Kconfig -@@ -189,6 +189,7 @@ config PINCTRL_QCOM_SPMI_PMIC - select PINMUX - select PINCONF - select GENERIC_PINCONF -+ select GPIOLIB - select GPIOLIB_IRQCHIP - select IRQ_DOMAIN_HIERARCHY - help -@@ -203,6 +204,7 @@ config PINCTRL_QCOM_SSBI_PMIC - select PINMUX - select PINCONF - select GENERIC_PINCONF -+ select GPIOLIB - select GPIOLIB_IRQCHIP - select IRQ_DOMAIN_HIERARCHY - help -diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c -index c51793f6546f1..fdfd7b8f3a76d 100644 ---- a/drivers/pinctrl/qcom/pinctrl-sdm845.c -+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c -@@ -1310,6 +1310,7 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = { - .ngpios = 151, - .wakeirq_map = sdm845_pdc_map, - .nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map), -+ .wakeirq_dual_edge_errata = true, - }; - - static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = { -diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c -index 4d8f8636c2b39..1c042d39380c6 100644 ---- a/drivers/pinctrl/qcom/pinctrl-sm8350.c -+++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c -@@ -1597,10 +1597,10 @@ static const struct msm_pingroup sm8350_groups[] = { - [200] = PINGROUP(200, qdss_gpio, _, _, _, _, _, _, _, _), - [201] = PINGROUP(201, _, _, _, _, _, _, _, _, _), - [202] = PINGROUP(202, _, _, _, _, _, _, _, _, _), -- [203] = UFS_RESET(ufs_reset, 0x1d8000), -- [204] = SDC_PINGROUP(sdc2_clk, 0x1cf000, 14, 6), -- [205] = SDC_PINGROUP(sdc2_cmd, 0x1cf000, 11, 3), -- [206] = SDC_PINGROUP(sdc2_data, 0x1cf000, 9, 0), -+ [203] = UFS_RESET(ufs_reset, 0xd8000), -+ [204] = SDC_PINGROUP(sdc2_clk, 0xcf000, 14, 6), -+ [205] = SDC_PINGROUP(sdc2_cmd, 0xcf000, 11, 3), -+ [206] = SDC_PINGROUP(sdc2_data, 0xcf000, 9, 0), - }; - - static const struct msm_gpio_wakeirq_map sm8350_pdc_map[] = { -diff --git a/drivers/pinctrl/ralink/pinctrl-mt7620.c b/drivers/pinctrl/ralink/pinctrl-mt7620.c -index 425d55a2ee19f..6853b5b8b0fe7 100644 ---- a/drivers/pinctrl/ralink/pinctrl-mt7620.c -+++ b/drivers/pinctrl/ralink/pinctrl-mt7620.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0-only - -+#include <asm/mach-ralink/ralink_regs.h> - #include <asm/mach-ralink/mt7620.h> - #include <linux/module.h> - #include <linux/platform_device.h> -diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c -index f2ab02225837e..f29130957e49a 100644 ---- a/drivers/pinctrl/renesas/core.c -+++ b/drivers/pinctrl/renesas/core.c -@@ -890,7 +890,7 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, - if (!field->pin && !field->offset && !field->size) - continue; - -- mask = GENMASK(field->offset + field->size, field->offset); -+ mask = GENMASK(field->offset + field->size - 1, field->offset); - if (mask & seen) - sh_pfc_err("drive_reg 0x%x: field %u overlap\n", - drive->reg, i); -diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c -index dbf2f521bb272..20b2af889ca96 100644 ---- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c -+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c -@@ -852,7 +852,7 @@ static const u32 rzg2l_gpio_configs[] = { - RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS), - RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS), - RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS), -- RZG2L_GPIO_PORT_PACK(3, 0x22, RZG2L_MPXED_PIN_FUNCS), -+ RZG2L_GPIO_PORT_PACK(3, 0x21, RZG2L_MPXED_PIN_FUNCS), - RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS), - RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS), - RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)), -diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c -index 4428c4330229a..1679811eff502 100644 ---- a/drivers/platform/surface/surface_aggregator_registry.c -+++ b/drivers/platform/surface/surface_aggregator_registry.c -@@ -77,6 +77,42 @@ static const struct software_node ssam_node_bas_dtx = { - .parent = &ssam_node_root, - }; - -+/* HID keyboard (TID1). */ -+static const struct software_node ssam_node_hid_tid1_keyboard = { -+ .name = "ssam:01:15:01:01:00", -+ .parent = &ssam_node_root, -+}; -+ -+/* HID pen stash (TID1; pen taken / stashed away evens). */ -+static const struct software_node ssam_node_hid_tid1_penstash = { -+ .name = "ssam:01:15:01:02:00", -+ .parent = &ssam_node_root, -+}; -+ -+/* HID touchpad (TID1). */ -+static const struct software_node ssam_node_hid_tid1_touchpad = { -+ .name = "ssam:01:15:01:03:00", -+ .parent = &ssam_node_root, -+}; -+ -+/* HID device instance 6 (TID1, unknown HID device). */ -+static const struct software_node ssam_node_hid_tid1_iid6 = { -+ .name = "ssam:01:15:01:06:00", -+ .parent = &ssam_node_root, -+}; -+ -+/* HID device instance 7 (TID1, unknown HID device). */ -+static const struct software_node ssam_node_hid_tid1_iid7 = { -+ .name = "ssam:01:15:01:07:00", -+ .parent = &ssam_node_root, -+}; -+ -+/* HID system controls (TID1). */ -+static const struct software_node ssam_node_hid_tid1_sysctrl = { -+ .name = "ssam:01:15:01:08:00", -+ .parent = &ssam_node_root, -+}; -+ - /* HID keyboard. */ - static const struct software_node ssam_node_hid_main_keyboard = { - .name = "ssam:01:15:02:01:00", -@@ -159,6 +195,21 @@ static const struct software_node *ssam_node_group_sl3[] = { - NULL, - }; - -+/* Devices for Surface Laptop Studio. */ -+static const struct software_node *ssam_node_group_sls[] = { -+ &ssam_node_root, -+ &ssam_node_bat_ac, -+ &ssam_node_bat_main, -+ &ssam_node_tmp_pprof, -+ &ssam_node_hid_tid1_keyboard, -+ &ssam_node_hid_tid1_penstash, -+ &ssam_node_hid_tid1_touchpad, -+ &ssam_node_hid_tid1_iid6, -+ &ssam_node_hid_tid1_iid7, -+ &ssam_node_hid_tid1_sysctrl, -+ NULL, -+}; -+ - /* Devices for Surface Laptop Go. */ - static const struct software_node *ssam_node_group_slg1[] = { - &ssam_node_root, -@@ -507,6 +558,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = { - /* Surface Laptop Go 1 */ - { "MSHW0118", (unsigned long)ssam_node_group_slg1 }, - -+ /* Surface Laptop Studio */ -+ { "MSHW0123", (unsigned long)ssam_node_group_sls }, -+ - { }, - }; - MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_match); -diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c -index fc95620101e85..54b88bedecdf1 100644 ---- a/drivers/platform/x86/amd-pmc.c -+++ b/drivers/platform/x86/amd-pmc.c -@@ -70,7 +70,7 @@ - #define AMD_CPU_ID_CZN AMD_CPU_ID_RN - #define AMD_CPU_ID_YC 0x14B5 - --#define PMC_MSG_DELAY_MIN_US 100 -+#define PMC_MSG_DELAY_MIN_US 50 - #define RESPONSE_REGISTER_LOOP_MAX 20000 - - #define SOC_SUBSYSTEM_IP_MAX 12 -diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig -index 2fffa57e596e4..fe224a54f24c0 100644 ---- a/drivers/platform/x86/dell/Kconfig -+++ b/drivers/platform/x86/dell/Kconfig -@@ -187,7 +187,7 @@ config DELL_WMI_AIO - - config DELL_WMI_DESCRIPTOR - tristate -- default m -+ default n - depends on ACPI_WMI - - config DELL_WMI_LED -diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c -index cc53f725c0419..ef24f53753c6e 100644 ---- a/drivers/platform/x86/hp_accel.c -+++ b/drivers/platform/x86/hp_accel.c -@@ -331,9 +331,11 @@ static int lis3lv02d_probe(struct platform_device *device) - INIT_WORK(&hpled_led.work, delayed_set_status_worker); - ret = led_classdev_register(NULL, &hpled_led.led_classdev); - if (ret) { -+ i8042_remove_filter(hp_accel_i8042_filter); - lis3lv02d_joystick_disable(&lis3_dev); - lis3lv02d_poweroff(&lis3_dev); - flush_work(&hpled_led.work); -+ lis3lv02d_remove_fs(&lis3_dev); - return ret; - } - -diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c -index 08598942a6d78..13f8cf70b9aee 100644 ---- a/drivers/platform/x86/intel/hid.c -+++ b/drivers/platform/x86/intel/hid.c -@@ -99,6 +99,13 @@ static const struct dmi_system_id button_array_table[] = { - DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Tablet Gen 2"), - }, - }, -+ { -+ .ident = "Microsoft Surface Go 3", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), -+ }, -+ }, - { } - }; - -diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c -index 9472aae72df29..c4d9c45350f7c 100644 ---- a/drivers/platform/x86/think-lmi.c -+++ b/drivers/platform/x86/think-lmi.c -@@ -888,8 +888,10 @@ static int tlmi_analyze(void) - break; - if (!item) - break; -- if (!*item) -+ if (!*item) { -+ kfree(item); - continue; -+ } - - /* It is not allowed to have '/' for file name. Convert it into '\'. */ - strreplace(item, '/', '\\'); -@@ -902,6 +904,7 @@ static int tlmi_analyze(void) - setting = kzalloc(sizeof(*setting), GFP_KERNEL); - if (!setting) { - ret = -ENOMEM; -+ kfree(item); - goto fail_clear_attr; - } - setting->index = i; -@@ -916,7 +919,6 @@ static int tlmi_analyze(void) - } - kobject_init(&setting->kobj, &tlmi_attr_setting_ktype); - tlmi_priv.setting[i] = setting; -- tlmi_priv.settings_count++; - kfree(item); - } - -@@ -983,7 +985,12 @@ static void tlmi_remove(struct wmi_device *wdev) - - static int tlmi_probe(struct wmi_device *wdev, const void *context) - { -- tlmi_analyze(); -+ int ret; -+ -+ ret = tlmi_analyze(); -+ if (ret) -+ return ret; -+ - return tlmi_sysfs_init(); - } - -diff --git a/drivers/platform/x86/think-lmi.h b/drivers/platform/x86/think-lmi.h -index f8e26823075fd..2ce5086a5af27 100644 ---- a/drivers/platform/x86/think-lmi.h -+++ b/drivers/platform/x86/think-lmi.h -@@ -55,7 +55,6 @@ struct tlmi_attr_setting { - struct think_lmi { - struct wmi_device *wmi_device; - -- int settings_count; - bool can_set_bios_settings; - bool can_get_bios_selections; - bool can_set_bios_password; -diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c -index 50ff04c84650c..3dc055ce6e61b 100644 ---- a/drivers/platform/x86/thinkpad_acpi.c -+++ b/drivers/platform/x86/thinkpad_acpi.c -@@ -1178,15 +1178,6 @@ static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk) - return status; - } - --/* Query FW and update rfkill sw state for all rfkill switches */ --static void tpacpi_rfk_update_swstate_all(void) --{ -- unsigned int i; -- -- for (i = 0; i < TPACPI_RFK_SW_MAX; i++) -- tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]); --} -- - /* - * Sync the HW-blocking state of all rfkill switches, - * do notice it causes the rfkill core to schedule uevents -@@ -3129,9 +3120,6 @@ static void tpacpi_send_radiosw_update(void) - if (wlsw == TPACPI_RFK_RADIO_OFF) - tpacpi_rfk_update_hwblock_state(true); - -- /* Sync sw blocking state */ -- tpacpi_rfk_update_swstate_all(); -- - /* Sync hw blocking state last if it is hw-unblocked */ - if (wlsw == TPACPI_RFK_RADIO_ON) - tpacpi_rfk_update_hwblock_state(false); -@@ -8853,6 +8841,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = { - TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (1st gen) */ - TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (2nd gen) */ - TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (3nd gen) */ -+ TPACPI_Q_LNV3('N', '4', '0', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (4nd gen) */ - TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL), /* P15 (1st gen) / P15v (1st gen) */ - TPACPI_Q_LNV3('N', '3', '2', TPACPI_FAN_2CTL), /* X1 Carbon (9th gen) */ - }; -@@ -9145,7 +9134,7 @@ static int fan_write_cmd_level(const char *cmd, int *rc) - - if (strlencmp(cmd, "level auto") == 0) - level = TP_EC_FAN_AUTO; -- else if ((strlencmp(cmd, "level disengaged") == 0) | -+ else if ((strlencmp(cmd, "level disengaged") == 0) || - (strlencmp(cmd, "level full-speed") == 0)) - level = TP_EC_FAN_FULLSPEED; - else if (sscanf(cmd, "level %d", &level) != 1) -diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c -index a76313006bdc4..1b65bb61ce888 100644 ---- a/drivers/platform/x86/wmi.c -+++ b/drivers/platform/x86/wmi.c -@@ -353,7 +353,14 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, - * the WQxx method failed - we should disable collection anyway. - */ - if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { -- status = acpi_execute_simple_method(handle, wc_method, 0); -+ /* -+ * Ignore whether this WCxx call succeeds or not since -+ * the previously executed WQxx method call might have -+ * succeeded, and returning the failing status code -+ * of this call would throw away the result of the WQxx -+ * call, potentially leaking memory. -+ */ -+ acpi_execute_simple_method(handle, wc_method, 0); - } - - return status; -diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c -index 026649409135c..64def79d557a8 100644 ---- a/drivers/power/reset/at91-reset.c -+++ b/drivers/power/reset/at91-reset.c -@@ -193,7 +193,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) - return -ENOMEM; - - reset->rstc_base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); -- if (!reset->rstc_base) { -+ if (IS_ERR(reset->rstc_base)) { - dev_err(&pdev->dev, "Could not map reset controller address\n"); - return -ENODEV; - } -@@ -203,7 +203,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) - for_each_matching_node_and_match(np, at91_ramc_of_match, &match) { - reset->ramc_lpr = (u32)match->data; - reset->ramc_base[idx] = devm_of_iomap(&pdev->dev, np, 0, NULL); -- if (!reset->ramc_base[idx]) { -+ if (IS_ERR(reset->ramc_base[idx])) { - dev_err(&pdev->dev, "Could not map ram controller address\n"); - of_node_put(np); - return -ENODEV; -diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c -index 46f078350fd3f..cf38cbfe13e9d 100644 ---- a/drivers/power/supply/bq27xxx_battery_i2c.c -+++ b/drivers/power/supply/bq27xxx_battery_i2c.c -@@ -187,7 +187,8 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client, - dev_err(&client->dev, - "Unable to register IRQ %d error %d\n", - client->irq, ret); -- return ret; -+ bq27xxx_battery_teardown(di); -+ goto err_failed; - } - } - -diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c -index 3cea92e28dc3e..a9aef1e8b186e 100644 ---- a/drivers/power/supply/max17040_battery.c -+++ b/drivers/power/supply/max17040_battery.c -@@ -449,6 +449,8 @@ static int max17040_probe(struct i2c_client *client, - - chip->client = client; - chip->regmap = devm_regmap_init_i2c(client, &max17040_regmap); -+ if (IS_ERR(chip->regmap)) -+ return PTR_ERR(chip->regmap); - chip_id = (enum chip_id) id->driver_data; - if (client->dev.of_node) { - ret = max17040_get_of_data(chip); -diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c -index 8dffae76b6a31..aaf6f1bd3d298 100644 ---- a/drivers/power/supply/max17042_battery.c -+++ b/drivers/power/supply/max17042_battery.c -@@ -313,7 +313,10 @@ static int max17042_get_property(struct power_supply *psy, - val->intval = data * 625 / 8; - break; - case POWER_SUPPLY_PROP_CAPACITY: -- ret = regmap_read(map, MAX17042_RepSOC, &data); -+ if (chip->pdata->enable_current_sense) -+ ret = regmap_read(map, MAX17042_RepSOC, &data); -+ else -+ ret = regmap_read(map, MAX17042_VFSOC, &data); - if (ret < 0) - return ret; - -@@ -857,7 +860,8 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) - regmap_read(map, MAX17042_RepSOC, &soc); - soc >>= 8; - soc_tr = (soc + off) << 8; -- soc_tr |= (soc - off); -+ if (off < soc) -+ soc_tr |= soc - off; - regmap_write(map, MAX17042_SALRT_Th, soc_tr); - } - -@@ -876,6 +880,10 @@ static irqreturn_t max17042_thread_handler(int id, void *dev) - max17042_set_soc_threshold(chip, 1); - } - -+ /* we implicitly handle all alerts via power_supply_changed */ -+ regmap_clear_bits(chip->regmap, MAX17042_STATUS, -+ 0xFFFF & ~(STATUS_POR_BIT | STATUS_BST_BIT)); -+ - power_supply_changed(chip->battery); - return IRQ_HANDLED; - } -diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c -index 9ad0afe83d1b7..7a23c70f48791 100644 ---- a/drivers/power/supply/rt5033_battery.c -+++ b/drivers/power/supply/rt5033_battery.c -@@ -60,7 +60,7 @@ static int rt5033_battery_get_watt_prop(struct i2c_client *client, - regmap_read(battery->regmap, regh, &msb); - regmap_read(battery->regmap, regl, &lsb); - -- ret = ((msb << 4) + (lsb >> 4)) * 1250 / 1000; -+ ret = ((msb << 4) + (lsb >> 4)) * 1250; - - return ret; - } -diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c -index caf9b37c5eb1e..e238ae8e94709 100644 ---- a/drivers/ptp/ptp_ocp.c -+++ b/drivers/ptp/ptp_ocp.c -@@ -1049,10 +1049,11 @@ ptp_ocp_register_ext(struct ptp_ocp *bp, struct ocp_resource *r) - if (!ext) - return -ENOMEM; - -- err = -EINVAL; - ext->mem = ptp_ocp_get_mem(bp, r); -- if (!ext->mem) -+ if (IS_ERR(ext->mem)) { -+ err = PTR_ERR(ext->mem); - goto out; -+ } - - ext->bp = bp; - ext->info = r->extra; -@@ -1122,8 +1123,8 @@ ptp_ocp_register_mem(struct ptp_ocp *bp, struct ocp_resource *r) - void __iomem *mem; - - mem = ptp_ocp_get_mem(bp, r); -- if (!mem) -- return -EINVAL; -+ if (IS_ERR(mem)) -+ return PTR_ERR(mem); - - bp_assign_entry(bp, r, mem); - -diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c -index 7c111bbdc2afa..35269f9982105 100644 ---- a/drivers/regulator/s5m8767.c -+++ b/drivers/regulator/s5m8767.c -@@ -850,18 +850,15 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) - /* DS4 GPIO */ - gpio_direction_output(pdata->buck_ds[2], 0x0); - -- if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || -- pdata->buck4_gpiodvs) { -- regmap_update_bits(s5m8767->iodev->regmap_pmic, -- S5M8767_REG_BUCK2CTRL, 1 << 1, -- (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1)); -- regmap_update_bits(s5m8767->iodev->regmap_pmic, -- S5M8767_REG_BUCK3CTRL, 1 << 1, -- (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1)); -- regmap_update_bits(s5m8767->iodev->regmap_pmic, -- S5M8767_REG_BUCK4CTRL, 1 << 1, -- (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1)); -- } -+ regmap_update_bits(s5m8767->iodev->regmap_pmic, -+ S5M8767_REG_BUCK2CTRL, 1 << 1, -+ (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1)); -+ regmap_update_bits(s5m8767->iodev->regmap_pmic, -+ S5M8767_REG_BUCK3CTRL, 1 << 1, -+ (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1)); -+ regmap_update_bits(s5m8767->iodev->regmap_pmic, -+ S5M8767_REG_BUCK4CTRL, 1 << 1, -+ (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1)); - - /* Initialize GPIO DVS registers */ - for (i = 0; i < 8; i++) { -diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c -index d88f76f5305eb..ff620688fad94 100644 ---- a/drivers/remoteproc/imx_rproc.c -+++ b/drivers/remoteproc/imx_rproc.c -@@ -71,6 +71,7 @@ struct imx_rproc_mem { - /* att flags */ - /* M4 own area. Can be mapped at probe */ - #define ATT_OWN BIT(1) -+#define ATT_IOMEM BIT(2) - - /* address translation table */ - struct imx_rproc_att { -@@ -117,7 +118,7 @@ struct imx_rproc { - static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { - /* dev addr , sys addr , size , flags */ - /* ITCM */ -- { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, -+ { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM }, - /* OCRAM_S */ - { 0x00180000, 0x00180000, 0x00009000, 0 }, - /* OCRAM */ -@@ -131,7 +132,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { - /* DDR (Code) - alias */ - { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, - /* DTCM */ -- { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, -+ { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM }, - /* OCRAM_S - alias */ - { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, - /* OCRAM */ -@@ -147,7 +148,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { - static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { - /* dev addr , sys addr , size , flags */ - /* TCML - alias */ -- { 0x00000000, 0x007e0000, 0x00020000, 0 }, -+ { 0x00000000, 0x007e0000, 0x00020000, ATT_IOMEM}, - /* OCRAM_S */ - { 0x00180000, 0x00180000, 0x00008000, 0 }, - /* OCRAM */ -@@ -159,9 +160,9 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { - /* DDR (Code) - alias */ - { 0x10000000, 0x80000000, 0x0FFE0000, 0 }, - /* TCML */ -- { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN }, -+ { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM}, - /* TCMU */ -- { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, -+ { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM}, - /* OCRAM_S */ - { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, - /* OCRAM */ -@@ -199,12 +200,12 @@ static const struct imx_rproc_att imx_rproc_att_imx7d[] = { - /* OCRAM_PXP (Code) - alias */ - { 0x00940000, 0x00940000, 0x00008000, 0 }, - /* TCML (Code) */ -- { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, -+ { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM }, - /* DDR (Code) - alias, first part of DDR (Data) */ - { 0x10000000, 0x80000000, 0x0FFF0000, 0 }, - - /* TCMU (Data) */ -- { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, -+ { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM }, - /* OCRAM (Data) */ - { 0x20200000, 0x00900000, 0x00020000, 0 }, - /* OCRAM_EPDC (Data) */ -@@ -218,18 +219,18 @@ static const struct imx_rproc_att imx_rproc_att_imx7d[] = { - static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { - /* dev addr , sys addr , size , flags */ - /* TCML (M4 Boot Code) - alias */ -- { 0x00000000, 0x007F8000, 0x00008000, 0 }, -+ { 0x00000000, 0x007F8000, 0x00008000, ATT_IOMEM }, - /* OCRAM_S (Code) */ - { 0x00180000, 0x008F8000, 0x00004000, 0 }, - /* OCRAM_S (Code) - alias */ - { 0x00180000, 0x008FC000, 0x00004000, 0 }, - /* TCML (Code) */ -- { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, -+ { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM }, - /* DDR (Code) - alias, first part of DDR (Data) */ - { 0x10000000, 0x80000000, 0x0FFF8000, 0 }, - - /* TCMU (Data) */ -- { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, -+ { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM }, - /* OCRAM_S (Data) - alias? */ - { 0x208F8000, 0x008F8000, 0x00004000, 0 }, - /* DDR (Data) */ -@@ -341,7 +342,7 @@ static int imx_rproc_stop(struct rproc *rproc) - } - - static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, -- size_t len, u64 *sys) -+ size_t len, u64 *sys, bool *is_iomem) - { - const struct imx_rproc_dcfg *dcfg = priv->dcfg; - int i; -@@ -354,6 +355,8 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, - unsigned int offset = da - att->da; - - *sys = att->sa + offset; -+ if (is_iomem) -+ *is_iomem = att->flags & ATT_IOMEM; - return 0; - } - } -@@ -377,7 +380,7 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i - * On device side we have many aliases, so we need to convert device - * address (M4) to system bus address first. - */ -- if (imx_rproc_da_to_sys(priv, da, len, &sys)) -+ if (imx_rproc_da_to_sys(priv, da, len, &sys, is_iomem)) - return NULL; - - for (i = 0; i < IMX_RPROC_MEM_MAX; i++) { -@@ -553,8 +556,12 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, - if (b >= IMX_RPROC_MEM_MAX) - break; - -- priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, -- att->sa, att->size); -+ if (att->flags & ATT_IOMEM) -+ priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, -+ att->sa, att->size); -+ else -+ priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, -+ att->sa, att->size); - if (!priv->mem[b].cpu_addr) { - dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa); - return -ENOMEM; -@@ -575,8 +582,8 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, - struct resource res; - - node = of_parse_phandle(np, "memory-region", a); -- /* Not map vdev region */ -- if (!strcmp(node->name, "vdev")) -+ /* Not map vdevbuffer, vdevring region */ -+ if (!strncmp(node->name, "vdev", strlen("vdev"))) - continue; - err = of_address_to_resource(node, 0, &res); - if (err) { -@@ -597,7 +604,7 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, - } - priv->mem[b].sys_addr = res.start; - priv->mem[b].size = resource_size(&res); -- if (!strcmp(node->name, "rsc_table")) -+ if (!strcmp(node->name, "rsc-table")) - priv->rsc_table = priv->mem[b].cpu_addr; - b++; - } -diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c -index 502b6604b757b..775df165eb450 100644 ---- a/drivers/remoteproc/remoteproc_core.c -+++ b/drivers/remoteproc/remoteproc_core.c -@@ -556,9 +556,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, - /* Initialise vdev subdevice */ - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index); - rvdev->dev.parent = &rproc->dev; -- ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); -- if (ret) -- return ret; - rvdev->dev.release = rproc_rvdev_release; - dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name); - dev_set_drvdata(&rvdev->dev, rvdev); -@@ -568,6 +565,11 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, - put_device(&rvdev->dev); - return ret; - } -+ -+ ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); -+ if (ret) -+ goto free_rvdev; -+ - /* Make device dma capable by inheriting from parent's capabilities */ - set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent)); - -diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c -index aee657cc08c6a..c892f433a323e 100644 ---- a/drivers/remoteproc/remoteproc_coredump.c -+++ b/drivers/remoteproc/remoteproc_coredump.c -@@ -152,8 +152,8 @@ static void rproc_copy_segment(struct rproc *rproc, void *dest, - struct rproc_dump_segment *segment, - size_t offset, size_t size) - { -+ bool is_iomem = false; - void *ptr; -- bool is_iomem; - - if (segment->dump) { - segment->dump(rproc, segment, dest, offset, size); -diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c -index 469c52e62faff..d635d19a5aa8a 100644 ---- a/drivers/remoteproc/remoteproc_elf_loader.c -+++ b/drivers/remoteproc/remoteproc_elf_loader.c -@@ -178,8 +178,8 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) - u64 filesz = elf_phdr_get_p_filesz(class, phdr); - u64 offset = elf_phdr_get_p_offset(class, phdr); - u32 type = elf_phdr_get_p_type(class, phdr); -+ bool is_iomem = false; - void *ptr; -- bool is_iomem; - - if (type != PT_LOAD) - continue; -@@ -220,7 +220,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) - /* put the segment where the remote processor expects it */ - if (filesz) { - if (is_iomem) -- memcpy_fromio(ptr, (void __iomem *)(elf_data + offset), filesz); -+ memcpy_toio((void __iomem *)ptr, elf_data + offset, filesz); - else - memcpy(ptr, elf_data + offset, filesz); - } -diff --git a/drivers/reset/tegra/reset-bpmp.c b/drivers/reset/tegra/reset-bpmp.c -index 4c5bba52b1059..24d3395964cc4 100644 ---- a/drivers/reset/tegra/reset-bpmp.c -+++ b/drivers/reset/tegra/reset-bpmp.c -@@ -20,7 +20,6 @@ static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc, - struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc); - struct mrq_reset_request request; - struct tegra_bpmp_message msg; -- int err; - - memset(&request, 0, sizeof(request)); - request.cmd = command; -@@ -31,13 +30,7 @@ static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc, - msg.tx.data = &request; - msg.tx.size = sizeof(request); - -- err = tegra_bpmp_transfer(bpmp, &msg); -- if (err) -- return err; -- if (msg.rx.ret) -- return -EINVAL; -- -- return 0; -+ return tegra_bpmp_transfer(bpmp, &msg); - } - - static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc, -diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c -index b3de6d2e680a4..2f83adef966eb 100644 ---- a/drivers/rtc/rtc-ds1302.c -+++ b/drivers/rtc/rtc-ds1302.c -@@ -199,11 +199,18 @@ static const struct of_device_id ds1302_dt_ids[] = { - MODULE_DEVICE_TABLE(of, ds1302_dt_ids); - #endif - -+static const struct spi_device_id ds1302_spi_ids[] = { -+ { .name = "ds1302", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(spi, ds1302_spi_ids); -+ - static struct spi_driver ds1302_driver = { - .driver.name = "rtc-ds1302", - .driver.of_match_table = of_match_ptr(ds1302_dt_ids), - .probe = ds1302_probe, - .remove = ds1302_remove, -+ .id_table = ds1302_spi_ids, - }; - - module_spi_driver(ds1302_driver); -diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c -index 66fc8617d07ee..93ce72b9ae59e 100644 ---- a/drivers/rtc/rtc-ds1390.c -+++ b/drivers/rtc/rtc-ds1390.c -@@ -219,12 +219,19 @@ static const struct of_device_id ds1390_of_match[] = { - }; - MODULE_DEVICE_TABLE(of, ds1390_of_match); - -+static const struct spi_device_id ds1390_spi_ids[] = { -+ { .name = "ds1390" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(spi, ds1390_spi_ids); -+ - static struct spi_driver ds1390_driver = { - .driver = { - .name = "rtc-ds1390", - .of_match_table = of_match_ptr(ds1390_of_match), - }, - .probe = ds1390_probe, -+ .id_table = ds1390_spi_ids, - }; - - module_spi_driver(ds1390_driver); -diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c -index bad7792b6ca58..0d515b3df5710 100644 ---- a/drivers/rtc/rtc-mcp795.c -+++ b/drivers/rtc/rtc-mcp795.c -@@ -430,12 +430,19 @@ static const struct of_device_id mcp795_of_match[] = { - MODULE_DEVICE_TABLE(of, mcp795_of_match); - #endif - -+static const struct spi_device_id mcp795_spi_ids[] = { -+ { .name = "mcp795" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(spi, mcp795_spi_ids); -+ - static struct spi_driver mcp795_driver = { - .driver = { - .name = "rtc-mcp795", - .of_match_table = of_match_ptr(mcp795_of_match), - }, - .probe = mcp795_probe, -+ .id_table = mcp795_spi_ids, - }; - - module_spi_driver(mcp795_driver); -diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c -index 0f58cac81d8c0..7473e6c8a183b 100644 ---- a/drivers/rtc/rtc-pcf2123.c -+++ b/drivers/rtc/rtc-pcf2123.c -@@ -451,12 +451,21 @@ static const struct of_device_id pcf2123_dt_ids[] = { - MODULE_DEVICE_TABLE(of, pcf2123_dt_ids); - #endif - -+static const struct spi_device_id pcf2123_spi_ids[] = { -+ { .name = "pcf2123", }, -+ { .name = "rv2123", }, -+ { .name = "rtc-pcf2123", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(spi, pcf2123_spi_ids); -+ - static struct spi_driver pcf2123_driver = { - .driver = { - .name = "rtc-pcf2123", - .of_match_table = of_match_ptr(pcf2123_dt_ids), - }, - .probe = pcf2123_probe, -+ .id_table = pcf2123_spi_ids, - }; - - module_spi_driver(pcf2123_driver); -diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c -index d63102d5cb1e4..1b62ed2f14594 100644 ---- a/drivers/rtc/rtc-rv3032.c -+++ b/drivers/rtc/rtc-rv3032.c -@@ -617,11 +617,11 @@ static int rv3032_clkout_set_rate(struct clk_hw *hw, unsigned long rate, - - ret = rv3032_enter_eerd(rv3032, &eerd); - if (ret) -- goto exit_eerd; -+ return ret; - - ret = regmap_write(rv3032->regmap, RV3032_CLKOUT1, hfd & 0xff); - if (ret) -- return ret; -+ goto exit_eerd; - - ret = regmap_write(rv3032->regmap, RV3032_CLKOUT2, RV3032_CLKOUT2_OS | - FIELD_PREP(RV3032_CLKOUT2_HFD_MSK, hfd >> 8)); -diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c -index 1f5fab617b679..f7e75d9fedf61 100644 ---- a/drivers/s390/char/tape_std.c -+++ b/drivers/s390/char/tape_std.c -@@ -53,7 +53,6 @@ int - tape_std_assign(struct tape_device *device) - { - int rc; -- struct timer_list timeout; - struct tape_request *request; - - request = tape_alloc_request(2, 11); -@@ -70,7 +69,7 @@ tape_std_assign(struct tape_device *device) - * So we set up a timeout for this call. - */ - timer_setup(&request->timer, tape_std_assign_timeout, 0); -- mod_timer(&timeout, jiffies + 2 * HZ); -+ mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000)); - - rc = tape_do_io_interruptible(device, request); - -diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c -index 44461928aab8a..c278097926093 100644 ---- a/drivers/s390/cio/css.c -+++ b/drivers/s390/cio/css.c -@@ -437,8 +437,8 @@ static ssize_t dev_busid_show(struct device *dev, - struct subchannel *sch = to_subchannel(dev); - struct pmcw *pmcw = &sch->schib.pmcw; - -- if ((pmcw->st == SUBCHANNEL_TYPE_IO || -- pmcw->st == SUBCHANNEL_TYPE_MSG) && pmcw->dnv) -+ if ((pmcw->st == SUBCHANNEL_TYPE_IO && pmcw->dnv) || -+ (pmcw->st == SUBCHANNEL_TYPE_MSG && pmcw->w)) - return sysfs_emit(buf, "0.%x.%04x\n", sch->schid.ssid, - pmcw->dev); - else -diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c -index 0fe7b2f2e7f52..c533d1dadc6bb 100644 ---- a/drivers/s390/cio/device_ops.c -+++ b/drivers/s390/cio/device_ops.c -@@ -825,13 +825,23 @@ EXPORT_SYMBOL_GPL(ccw_device_get_chid); - */ - void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size) - { -- return cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size); -+ void *addr; -+ -+ if (!get_device(&cdev->dev)) -+ return NULL; -+ addr = cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size); -+ if (IS_ERR_OR_NULL(addr)) -+ put_device(&cdev->dev); -+ return addr; - } - EXPORT_SYMBOL(ccw_device_dma_zalloc); - - void ccw_device_dma_free(struct ccw_device *cdev, void *cpu_addr, size_t size) - { -+ if (!cpu_addr) -+ return; - cio_gp_dma_free(cdev->private->dma_pool, cpu_addr, size); -+ put_device(&cdev->dev); - } - EXPORT_SYMBOL(ccw_device_dma_free); - -diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c -index 9ea48bf0ee40d..032bf7b282bab 100644 ---- a/drivers/s390/crypto/ap_queue.c -+++ b/drivers/s390/crypto/ap_queue.c -@@ -157,6 +157,8 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - aq->queue_count = max_t(int, 0, aq->queue_count - 1); -+ if (!status.queue_empty && !aq->queue_count) -+ aq->queue_count++; - if (aq->queue_count > 0) - mod_timer(&aq->timeout, - jiffies + aq->request_timeout); -diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c -index ffb3919675734..97be0765cb9bd 100644 ---- a/drivers/scsi/advansys.c -+++ b/drivers/scsi/advansys.c -@@ -3308,8 +3308,8 @@ static void asc_prt_adv_board_info(struct seq_file *m, struct Scsi_Host *shost) - shost->host_no); - - seq_printf(m, -- " iop_base 0x%lx, cable_detect: %X, err_code %u\n", -- (unsigned long)v->iop_base, -+ " iop_base 0x%p, cable_detect: %X, err_code %u\n", -+ v->iop_base, - AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT, - v->err_code); - -diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c -index dc98f51f466fb..d5ac938970232 100644 ---- a/drivers/scsi/csiostor/csio_lnode.c -+++ b/drivers/scsi/csiostor/csio_lnode.c -@@ -619,7 +619,7 @@ csio_ln_vnp_read_cbfn(struct csio_hw *hw, struct csio_mb *mbp) - struct fc_els_csp *csp; - struct fc_els_cssp *clsp; - enum fw_retval retval; -- __be32 nport_id; -+ __be32 nport_id = 0; - - retval = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)); - if (retval != FW_SUCCESS) { -diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c -index 24c7cefb0b78a..1c79e6c271630 100644 ---- a/drivers/scsi/dc395x.c -+++ b/drivers/scsi/dc395x.c -@@ -4618,6 +4618,7 @@ static int dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id) - /* initialise the adapter and everything we need */ - if (adapter_init(acb, io_port_base, io_port_len, irq)) { - dprintkl(KERN_INFO, "adapter init failed\n"); -+ acb = NULL; - goto fail; - } - -diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c -index 24b72ee4246fb..0165dad803001 100644 ---- a/drivers/scsi/hosts.c -+++ b/drivers/scsi/hosts.c -@@ -388,6 +388,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) - shost->shost_state = SHOST_CREATED; - INIT_LIST_HEAD(&shost->__devices); - INIT_LIST_HEAD(&shost->__targets); -+ INIT_LIST_HEAD(&shost->eh_abort_list); - INIT_LIST_HEAD(&shost->eh_cmd_q); - INIT_LIST_HEAD(&shost->starved_list); - init_waitqueue_head(&shost->host_wait); -diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h -index c512f41991429..c9770b1d2366a 100644 ---- a/drivers/scsi/lpfc/lpfc_crtn.h -+++ b/drivers/scsi/lpfc/lpfc_crtn.h -@@ -119,6 +119,8 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, - struct lpfc_nodelist *lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did); - struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); - int lpfc_nlp_put(struct lpfc_nodelist *); -+void lpfc_check_nlp_post_devloss(struct lpfc_vport *vport, -+ struct lpfc_nodelist *ndlp); - void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_iocbq *rspiocb); - int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp); -diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h -index 871b665bd72e3..37a4b79010bfc 100644 ---- a/drivers/scsi/lpfc/lpfc_disc.h -+++ b/drivers/scsi/lpfc/lpfc_disc.h -@@ -85,6 +85,13 @@ enum lpfc_fc4_xpt_flags { - NLP_XPT_HAS_HH = 0x10 - }; - -+enum lpfc_nlp_save_flags { -+ /* devloss occurred during recovery */ -+ NLP_IN_RECOV_POST_DEV_LOSS = 0x1, -+ /* wait for outstanding LOGO to cmpl */ -+ NLP_WAIT_FOR_LOGO = 0x2, -+}; -+ - struct lpfc_nodelist { - struct list_head nlp_listp; - struct serv_parm fc_sparam; /* buffer for service params */ -@@ -144,8 +151,9 @@ struct lpfc_nodelist { - unsigned long *active_rrqs_xri_bitmap; - struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ - uint32_t fc4_prli_sent; -- u32 upcall_flags; --#define NLP_WAIT_FOR_LOGO 0x2 -+ -+ /* flags to keep ndlp alive until special conditions are met */ -+ enum lpfc_nlp_save_flags save_flags; - - enum lpfc_fc4_xpt_flags fc4_xpt_flags; - -diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c -index 052c0e5b11195..f7197b7161d52 100644 ---- a/drivers/scsi/lpfc/lpfc_els.c -+++ b/drivers/scsi/lpfc/lpfc_els.c -@@ -1059,9 +1059,10 @@ stop_rr_fcf_flogi: - - lpfc_printf_vlog(vport, KERN_WARNING, LOG_TRACE_EVENT, - "0150 FLOGI failure Status:x%x/x%x " -- "xri x%x TMO:x%x\n", -+ "xri x%x TMO:x%x refcnt %d\n", - irsp->ulpStatus, irsp->un.ulpWord[4], -- cmdiocb->sli4_xritag, irsp->ulpTimeout); -+ cmdiocb->sli4_xritag, irsp->ulpTimeout, -+ kref_read(&ndlp->kref)); - - /* If this is not a loop open failure, bail out */ - if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && -@@ -1122,12 +1123,12 @@ stop_rr_fcf_flogi: - /* FLOGI completes successfully */ - lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "0101 FLOGI completes successfully, I/O tag:x%x, " -- "xri x%x Data: x%x x%x x%x x%x x%x x%x x%x\n", -+ "xri x%x Data: x%x x%x x%x x%x x%x x%x x%x %d\n", - cmdiocb->iotag, cmdiocb->sli4_xritag, - irsp->un.ulpWord[4], sp->cmn.e_d_tov, - sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution, - vport->port_state, vport->fc_flag, -- sp->cmn.priority_tagging); -+ sp->cmn.priority_tagging, kref_read(&ndlp->kref)); - - if (sp->cmn.priority_tagging) - vport->vmid_flag |= LPFC_VMID_ISSUE_QFPA; -@@ -1205,8 +1206,6 @@ flogifail: - phba->fcf.fcf_flag &= ~FCF_DISCOVERY; - spin_unlock_irq(&phba->hbalock); - -- if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) -- lpfc_nlp_put(ndlp); - if (!lpfc_error_lost_link(irsp)) { - /* FLOGI failed, so just use loop map to make discovery list */ - lpfc_disc_list_loopmap(vport); -@@ -2899,9 +2898,9 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - irsp = &(rspiocb->iocb); - spin_lock_irq(&ndlp->lock); - ndlp->nlp_flag &= ~NLP_LOGO_SND; -- if (ndlp->upcall_flags & NLP_WAIT_FOR_LOGO) { -+ if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) { - wake_up_waiter = 1; -- ndlp->upcall_flags &= ~NLP_WAIT_FOR_LOGO; -+ ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO; - } - spin_unlock_irq(&ndlp->lock); - -@@ -5076,14 +5075,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - /* NPort Recovery mode or node is just allocated */ - if (!lpfc_nlp_not_used(ndlp)) { - /* A LOGO is completing and the node is in NPR state. -- * If this a fabric node that cleared its transport -- * registration, release the rpi. -+ * Just unregister the RPI because the node is still -+ * required. - */ -- spin_lock_irq(&ndlp->lock); -- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; -- if (phba->sli_rev == LPFC_SLI_REV4) -- ndlp->nlp_flag |= NLP_RELEASE_RPI; -- spin_unlock_irq(&ndlp->lock); - lpfc_unreg_rpi(vport, ndlp); - } else { - /* Indicate the node has already released, should -@@ -6216,6 +6210,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) - * from backend - */ - lpfc_nlp_unreg_node(vport, ndlp); -+ lpfc_unreg_rpi(vport, ndlp); - continue; - } - -@@ -10713,6 +10708,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - irsp->ulpStatus, irsp->un.ulpWord[4]); - goto fdisc_failed; - } -+ -+ lpfc_check_nlp_post_devloss(vport, ndlp); -+ - spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_VPORT_CVL_RCVD; - vport->fc_flag &= ~FC_VPORT_LOGO_RCVD; -diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c -index 7195ca0275f93..9ccb904e35fcf 100644 ---- a/drivers/scsi/lpfc/lpfc_hbadisc.c -+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c -@@ -209,7 +209,12 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) - - spin_lock_irqsave(&ndlp->lock, iflags); - ndlp->nlp_flag |= NLP_IN_DEV_LOSS; -- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; -+ -+ /* If there is a PLOGI in progress, and we are in a -+ * NLP_NPR_2B_DISC state, don't turn off the flag. -+ */ -+ if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE) -+ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; - - /* - * The backend does not expect any more calls associated with this -@@ -340,6 +345,37 @@ static void lpfc_check_inactive_vmid(struct lpfc_hba *phba) - lpfc_destroy_vport_work_array(phba, vports); - } - -+/** -+ * lpfc_check_nlp_post_devloss - Check to restore ndlp refcnt after devloss -+ * @vport: Pointer to vport object. -+ * @ndlp: Pointer to remote node object. -+ * -+ * If NLP_IN_RECOV_POST_DEV_LOSS flag was set due to outstanding recovery of -+ * node during dev_loss_tmo processing, then this function restores the nlp_put -+ * kref decrement from lpfc_dev_loss_tmo_handler. -+ **/ -+void -+lpfc_check_nlp_post_devloss(struct lpfc_vport *vport, -+ struct lpfc_nodelist *ndlp) -+{ -+ unsigned long iflags; -+ -+ spin_lock_irqsave(&ndlp->lock, iflags); -+ if (ndlp->save_flags & NLP_IN_RECOV_POST_DEV_LOSS) { -+ ndlp->save_flags &= ~NLP_IN_RECOV_POST_DEV_LOSS; -+ spin_unlock_irqrestore(&ndlp->lock, iflags); -+ lpfc_nlp_get(ndlp); -+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE, -+ "8438 Devloss timeout reversed on DID x%x " -+ "refcnt %d ndlp %p flag x%x " -+ "port_state = x%x\n", -+ ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp, -+ ndlp->nlp_flag, vport->port_state); -+ spin_lock_irqsave(&ndlp->lock, iflags); -+ } -+ spin_unlock_irqrestore(&ndlp->lock, iflags); -+} -+ - /** - * lpfc_dev_loss_tmo_handler - Remote node devloss timeout handler - * @ndlp: Pointer to remote node object. -@@ -358,6 +394,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) - uint8_t *name; - int warn_on = 0; - int fcf_inuse = 0; -+ bool recovering = false; -+ struct fc_vport *fc_vport = NULL; - unsigned long iflags; - - vport = ndlp->vport; -@@ -394,6 +432,64 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) - - /* Fabric nodes are done. */ - if (ndlp->nlp_type & NLP_FABRIC) { -+ spin_lock_irqsave(&ndlp->lock, iflags); -+ /* In massive vport configuration settings, it's possible -+ * dev_loss_tmo fired during node recovery. So, check if -+ * fabric nodes are in discovery states outstanding. -+ */ -+ switch (ndlp->nlp_DID) { -+ case Fabric_DID: -+ fc_vport = vport->fc_vport; -+ if (fc_vport && -+ fc_vport->vport_state == FC_VPORT_INITIALIZING) -+ recovering = true; -+ break; -+ case Fabric_Cntl_DID: -+ if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) -+ recovering = true; -+ break; -+ case FDMI_DID: -+ fallthrough; -+ case NameServer_DID: -+ if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && -+ ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) -+ recovering = true; -+ break; -+ } -+ spin_unlock_irqrestore(&ndlp->lock, iflags); -+ -+ /* Mark an NLP_IN_RECOV_POST_DEV_LOSS flag to know if reversing -+ * the following lpfc_nlp_put is necessary after fabric node is -+ * recovered. -+ */ -+ if (recovering) { -+ lpfc_printf_vlog(vport, KERN_INFO, -+ LOG_DISCOVERY | LOG_NODE, -+ "8436 Devloss timeout marked on " -+ "DID x%x refcnt %d ndlp %p " -+ "flag x%x port_state = x%x\n", -+ ndlp->nlp_DID, kref_read(&ndlp->kref), -+ ndlp, ndlp->nlp_flag, -+ vport->port_state); -+ spin_lock_irqsave(&ndlp->lock, iflags); -+ ndlp->save_flags |= NLP_IN_RECOV_POST_DEV_LOSS; -+ spin_unlock_irqrestore(&ndlp->lock, iflags); -+ } else if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { -+ /* Fabric node fully recovered before this dev_loss_tmo -+ * queue work is processed. Thus, ignore the -+ * dev_loss_tmo event. -+ */ -+ lpfc_printf_vlog(vport, KERN_INFO, -+ LOG_DISCOVERY | LOG_NODE, -+ "8437 Devloss timeout ignored on " -+ "DID x%x refcnt %d ndlp %p " -+ "flag x%x port_state = x%x\n", -+ ndlp->nlp_DID, kref_read(&ndlp->kref), -+ ndlp, ndlp->nlp_flag, -+ vport->port_state); -+ return fcf_inuse; -+ } -+ - lpfc_nlp_put(ndlp); - return fcf_inuse; - } -@@ -423,6 +519,14 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) - ndlp->nlp_state, ndlp->nlp_rpi); - } - -+ /* If we are devloss, but we are in the process of rediscovering the -+ * ndlp, don't issue a NLP_EVT_DEVICE_RM event. -+ */ -+ if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && -+ ndlp->nlp_state <= NLP_STE_PRLI_ISSUE) { -+ return fcf_inuse; -+ } -+ - if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) - lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); - -@@ -4351,6 +4455,8 @@ lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) - goto out; - } - -+ lpfc_check_nlp_post_devloss(vport, ndlp); -+ - if (phba->sli_rev < LPFC_SLI_REV4) - ndlp->nlp_rpi = mb->un.varWords[0]; - -@@ -4360,6 +4466,7 @@ lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) - ndlp->nlp_state); - - ndlp->nlp_flag |= NLP_RPI_REGISTERED; -+ ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; - ndlp->nlp_type |= NLP_FABRIC; - lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); - -@@ -4449,8 +4556,9 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) - fc_remote_port_rolechg(rport, rport_ids.roles); - - lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, -- "3183 %s rport x%px DID x%x, role x%x\n", -- __func__, rport, rport->port_id, rport->roles); -+ "3183 %s rport x%px DID x%x, role x%x refcnt %d\n", -+ __func__, rport, rport->port_id, rport->roles, -+ kref_read(&ndlp->kref)); - - if ((rport->scsi_target_id != -1) && - (rport->scsi_target_id < LPFC_MAX_TARGET)) { -@@ -4475,8 +4583,9 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) - - lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3184 rport unregister x%06x, rport x%px " -- "xptflg x%x\n", -- ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags); -+ "xptflg x%x refcnt %d\n", -+ ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags, -+ kref_read(&ndlp->kref)); - - fc_remote_port_delete(rport); - lpfc_nlp_put(ndlp); -@@ -4525,9 +4634,10 @@ lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count) - void - lpfc_nlp_reg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) - { -- - unsigned long iflags; - -+ lpfc_check_nlp_post_devloss(vport, ndlp); -+ - spin_lock_irqsave(&ndlp->lock, iflags); - if (ndlp->fc4_xpt_flags & NLP_XPT_REGD) { - /* Already registered with backend, trigger rescan */ -diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c -index 195169badb372..0fee8d590b0c4 100644 ---- a/drivers/scsi/lpfc/lpfc_init.c -+++ b/drivers/scsi/lpfc/lpfc_init.c -@@ -3694,12 +3694,16 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) - lpfc_disc_state_machine(vports[i], ndlp, - NULL, NLP_EVT_DEVICE_RECOVERY); - -- /* Don't remove the node unless the -+ /* Don't remove the node unless the node - * has been unregistered with the -- * transport. If so, let dev_loss -- * take care of the node. -+ * transport, and we're not in recovery -+ * before dev_loss_tmo triggered. -+ * Otherwise, let dev_loss take care of -+ * the node. - */ -- if (!(ndlp->fc4_xpt_flags & -+ if (!(ndlp->save_flags & -+ NLP_IN_RECOV_POST_DEV_LOSS) && -+ !(ndlp->fc4_xpt_flags & - (NVME_XPT_REGD | SCSI_XPT_REGD))) - lpfc_disc_state_machine - (vports[i], ndlp, -diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c -index 479b3eed62085..66cb66aea2cf9 100644 ---- a/drivers/scsi/lpfc/lpfc_nvme.c -+++ b/drivers/scsi/lpfc/lpfc_nvme.c -@@ -209,8 +209,9 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport) - * calling state machine to remove the node. - */ - lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, -- "6146 remoteport delete of remoteport x%px\n", -- remoteport); -+ "6146 remoteport delete of remoteport x%px, ndlp x%px " -+ "DID x%x xflags x%x\n", -+ remoteport, ndlp, ndlp->nlp_DID, ndlp->fc4_xpt_flags); - spin_lock_irq(&ndlp->lock); - - /* The register rebind might have occurred before the delete -diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c -index befdf864c43bd..3d9175f1b6787 100644 ---- a/drivers/scsi/lpfc/lpfc_scsi.c -+++ b/drivers/scsi/lpfc/lpfc_scsi.c -@@ -6455,28 +6455,28 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) - - /* Issue LOGO, if no LOGO is outstanding */ - spin_lock_irqsave(&pnode->lock, flags); -- if (!(pnode->upcall_flags & NLP_WAIT_FOR_LOGO) && -+ if (!(pnode->save_flags & NLP_WAIT_FOR_LOGO) && - !pnode->logo_waitq) { - pnode->logo_waitq = &waitq; - pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; - pnode->nlp_flag |= NLP_ISSUE_LOGO; -- pnode->upcall_flags |= NLP_WAIT_FOR_LOGO; -+ pnode->save_flags |= NLP_WAIT_FOR_LOGO; - spin_unlock_irqrestore(&pnode->lock, flags); - lpfc_unreg_rpi(vport, pnode); - wait_event_timeout(waitq, -- (!(pnode->upcall_flags & -+ (!(pnode->save_flags & - NLP_WAIT_FOR_LOGO)), - msecs_to_jiffies(dev_loss_tmo * - 1000)); - -- if (pnode->upcall_flags & NLP_WAIT_FOR_LOGO) { -+ if (pnode->save_flags & NLP_WAIT_FOR_LOGO) { - lpfc_printf_vlog(vport, KERN_ERR, logit, - "0725 SCSI layer TGTRST " - "failed & LOGO TMO (%d, %llu) " - "return x%x\n", - tgt_id, lun_id, status); - spin_lock_irqsave(&pnode->lock, flags); -- pnode->upcall_flags &= ~NLP_WAIT_FOR_LOGO; -+ pnode->save_flags &= ~NLP_WAIT_FOR_LOGO; - } else { - spin_lock_irqsave(&pnode->lock, flags); - } -@@ -6628,6 +6628,13 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd) - if (rc) - goto error; - -+ /* Wait for successful restart of adapter */ -+ if (phba->sli_rev < LPFC_SLI_REV4) { -+ rc = lpfc_sli_chipset_init(phba); -+ if (rc) -+ goto error; -+ } -+ - rc = lpfc_online(phba); - if (rc) - goto error; -diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c -index 026a1196a54d5..9c1f485952ef7 100644 ---- a/drivers/scsi/lpfc/lpfc_sli.c -+++ b/drivers/scsi/lpfc/lpfc_sli.c -@@ -12404,17 +12404,17 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; -- if (cmdiocb->iocb_flag & LPFC_IO_FCP) { -- abtsiocbp->iocb_flag |= LPFC_IO_FCP; -- abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; -- } -+ if (cmdiocb->iocb_flag & LPFC_IO_FCP) -+ abtsiocbp->iocb_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); - if (cmdiocb->iocb_flag & LPFC_IO_FOF) - abtsiocbp->iocb_flag |= LPFC_IO_FOF; - -- if (phba->link_state >= LPFC_LINK_UP) -- iabt->ulpCommand = CMD_ABORT_XRI_CN; -- else -+ if (phba->link_state < LPFC_LINK_UP || -+ (phba->sli_rev == LPFC_SLI_REV4 && -+ phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN)) - iabt->ulpCommand = CMD_CLOSE_XRI_CN; -+ else -+ iabt->ulpCommand = CMD_ABORT_XRI_CN; - - if (cmpl) - abtsiocbp->iocb_cmpl = cmpl; -@@ -12488,15 +12488,54 @@ lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) - } - - /** -- * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN -+ * lpfc_sli_validate_fcp_iocb_for_abort - filter iocbs appropriate for FCP aborts -+ * @iocbq: Pointer to iocb object. -+ * @vport: Pointer to driver virtual port object. -+ * -+ * This function acts as an iocb filter for functions which abort FCP iocbs. -+ * -+ * Return values -+ * -ENODEV, if a null iocb or vport ptr is encountered -+ * -EINVAL, if the iocb is not an FCP I/O, not on the TX cmpl queue, premarked as -+ * driver already started the abort process, or is an abort iocb itself -+ * 0, passes criteria for aborting the FCP I/O iocb -+ **/ -+static int -+lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq, -+ struct lpfc_vport *vport) -+{ -+ IOCB_t *icmd = NULL; -+ -+ /* No null ptr vports */ -+ if (!iocbq || iocbq->vport != vport) -+ return -ENODEV; -+ -+ /* iocb must be for FCP IO, already exists on the TX cmpl queue, -+ * can't be premarked as driver aborted, nor be an ABORT iocb itself -+ */ -+ icmd = &iocbq->iocb; -+ if (!(iocbq->iocb_flag & LPFC_IO_FCP) || -+ !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || -+ (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || -+ (icmd->ulpCommand == CMD_ABORT_XRI_CN || -+ icmd->ulpCommand == CMD_CLOSE_XRI_CN)) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+/** -+ * lpfc_sli_validate_fcp_iocb - validate commands associated with a SCSI target - * @iocbq: Pointer to driver iocb object. - * @vport: Pointer to driver virtual port object. - * @tgt_id: SCSI ID of the target. - * @lun_id: LUN ID of the scsi device. - * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST - * -- * This function acts as an iocb filter for functions which abort or count -- * all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return -+ * This function acts as an iocb filter for validating a lun/SCSI target/SCSI -+ * host. -+ * -+ * It will return - * 0 if the filtering criteria is met for the given iocb and will return - * 1 if the filtering criteria is not met. - * If ctx_cmd == LPFC_CTX_LUN, the function returns 0 only if the -@@ -12515,22 +12554,8 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, - lpfc_ctx_cmd ctx_cmd) - { - struct lpfc_io_buf *lpfc_cmd; -- IOCB_t *icmd = NULL; - int rc = 1; - -- if (!iocbq || iocbq->vport != vport) -- return rc; -- -- if (!(iocbq->iocb_flag & LPFC_IO_FCP) || -- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || -- iocbq->iocb_flag & LPFC_DRIVER_ABORTED) -- return rc; -- -- icmd = &iocbq->iocb; -- if (icmd->ulpCommand == CMD_ABORT_XRI_CN || -- icmd->ulpCommand == CMD_CLOSE_XRI_CN) -- return rc; -- - lpfc_cmd = container_of(iocbq, struct lpfc_io_buf, cur_iocbq); - - if (lpfc_cmd->pCmd == NULL) -@@ -12585,17 +12610,33 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, - { - struct lpfc_hba *phba = vport->phba; - struct lpfc_iocbq *iocbq; -+ IOCB_t *icmd = NULL; - int sum, i; -+ unsigned long iflags; - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irqsave(&phba->hbalock, iflags); - for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { - iocbq = phba->sli.iocbq_lookup[i]; - -- if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, -- ctx_cmd) == 0) -+ if (!iocbq || iocbq->vport != vport) -+ continue; -+ if (!(iocbq->iocb_flag & LPFC_IO_FCP) || -+ !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) -+ continue; -+ -+ /* Include counting outstanding aborts */ -+ icmd = &iocbq->iocb; -+ if (icmd->ulpCommand == CMD_ABORT_XRI_CN || -+ icmd->ulpCommand == CMD_CLOSE_XRI_CN) { -+ sum++; -+ continue; -+ } -+ -+ if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, -+ ctx_cmd) == 0) - sum++; - } -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irqrestore(&phba->hbalock, iflags); - - return sum; - } -@@ -12662,7 +12703,11 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - * - * This function sends an abort command for every SCSI command - * associated with the given virtual port pending on the ring -- * filtered by lpfc_sli_validate_fcp_iocb function. -+ * filtered by lpfc_sli_validate_fcp_iocb_for_abort and then -+ * lpfc_sli_validate_fcp_iocb function. The ordering for validation before -+ * submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort -+ * followed by lpfc_sli_validate_fcp_iocb. -+ * - * When abort_cmd == LPFC_CTX_LUN, the function sends abort only to the - * FCP iocbs associated with lun specified by tgt_id and lun_id - * parameters -@@ -12694,6 +12739,9 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, - for (i = 1; i <= phba->sli.last_iotag; i++) { - iocbq = phba->sli.iocbq_lookup[i]; - -+ if (lpfc_sli_validate_fcp_iocb_for_abort(iocbq, vport)) -+ continue; -+ - if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, - abort_cmd) != 0) - continue; -@@ -12726,7 +12774,11 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, - * - * This function sends an abort command for every SCSI command - * associated with the given virtual port pending on the ring -- * filtered by lpfc_sli_validate_fcp_iocb function. -+ * filtered by lpfc_sli_validate_fcp_iocb_for_abort and then -+ * lpfc_sli_validate_fcp_iocb function. The ordering for validation before -+ * submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort -+ * followed by lpfc_sli_validate_fcp_iocb. -+ * - * When taskmgmt_cmd == LPFC_CTX_LUN, the function sends abort only to the - * FCP iocbs associated with lun specified by tgt_id and lun_id - * parameters -@@ -12764,6 +12816,9 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, - for (i = 1; i <= phba->sli.last_iotag; i++) { - iocbq = phba->sli.iocbq_lookup[i]; - -+ if (lpfc_sli_validate_fcp_iocb_for_abort(iocbq, vport)) -+ continue; -+ - if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, - cmd) != 0) - continue; -@@ -21107,6 +21162,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) - fail_msg, - piocbq->iotag, piocbq->sli4_xritag); - list_add_tail(&piocbq->list, &completions); -+ fail_msg = NULL; - } - spin_unlock_irqrestore(&pring->ring_lock, iflags); - } -diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c -index 26d0cf9353dd6..eb5ceb75a15ec 100644 ---- a/drivers/scsi/megaraid/megaraid_sas_fusion.c -+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c -@@ -3530,6 +3530,9 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, - if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) - return IRQ_HANDLED; - -+ if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1)) -+ return 0; -+ - desc = fusion->reply_frames_desc[MSIxIndex] + - fusion->last_reply_idx[MSIxIndex]; - -@@ -3540,11 +3543,11 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, - reply_descript_type = reply_desc->ReplyFlags & - MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; - -- if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) -+ if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { -+ if (irq_context) -+ atomic_dec(&irq_context->in_used); - return IRQ_NONE; -- -- if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1)) -- return 0; -+ } - - num_completed = 0; - -diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c -index 27eb652b564f5..81dab9b82f79f 100644 ---- a/drivers/scsi/mpt3sas/mpt3sas_base.c -+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c -@@ -639,8 +639,8 @@ static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc) - mpi_request->IOCParameter = MPI26_SET_IOC_PARAMETER_SYNC_TIMESTAMP; - current_time = ktime_get_real(); - TimeStamp = ktime_to_ms(current_time); -- mpi_request->Reserved7 = cpu_to_le32(TimeStamp & 0xFFFFFFFF); -- mpi_request->IOCParameterValue = cpu_to_le32(TimeStamp >> 32); -+ mpi_request->Reserved7 = cpu_to_le32(TimeStamp >> 32); -+ mpi_request->IOCParameterValue = cpu_to_le32(TimeStamp & 0xFFFFFFFF); - init_completion(&ioc->scsih_cmds.done); - ioc->put_smid_default(ioc, smid); - dinitprintk(ioc, ioc_info(ioc, -diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h -index f87c0911f66ad..1b3a44ce65aae 100644 ---- a/drivers/scsi/mpt3sas/mpt3sas_base.h -+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h -@@ -142,6 +142,8 @@ - - #define MPT_MAX_CALLBACKS 32 - -+#define MPT_MAX_HBA_NUM_PHYS 32 -+ - #define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ - /* reserved for issuing internally framed scsi io cmds */ - #define INTERNAL_SCSIIO_CMDS_COUNT 3 -@@ -798,6 +800,7 @@ struct _sas_phy { - * @enclosure_handle: handle for this a member of an enclosure - * @device_info: bitwise defining capabilities of this sas_host/expander - * @responding: used in _scsih_expander_device_mark_responding -+ * @nr_phys_allocated: Allocated memory for this many count phys - * @phy: a list of phys that make up this sas_host/expander - * @sas_port_list: list of ports attached to this sas_host/expander - * @port: hba port entry containing node's port number info -@@ -813,6 +816,7 @@ struct _sas_node { - u16 enclosure_handle; - u64 enclosure_logical_id; - u8 responding; -+ u8 nr_phys_allocated; - struct hba_port *port; - struct _sas_phy *phy; - struct list_head sas_port_list; -diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -index ad1b6c2b37a74..c1f900c6ea003 100644 ---- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c -+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -@@ -3869,7 +3869,7 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; -- if (!sas_device_priv_data) -+ if (!sas_device_priv_data || !sas_device_priv_data->sas_target) - continue; - if (sas_device_priv_data->sas_target->sas_address - != sas_address) -@@ -6406,11 +6406,26 @@ _scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc) - int i, j, count = 0, lcount = 0; - int ret; - u64 sas_addr; -+ u8 num_phys; - - drsprintk(ioc, ioc_info(ioc, - "updating ports for sas_host(0x%016llx)\n", - (unsigned long long)ioc->sas_hba.sas_address)); - -+ mpt3sas_config_get_number_hba_phys(ioc, &num_phys); -+ if (!num_phys) { -+ ioc_err(ioc, "failure at %s:%d/%s()!\n", -+ __FILE__, __LINE__, __func__); -+ return; -+ } -+ -+ if (num_phys > ioc->sas_hba.nr_phys_allocated) { -+ ioc_err(ioc, "failure at %s:%d/%s()!\n", -+ __FILE__, __LINE__, __func__); -+ return; -+ } -+ ioc->sas_hba.num_phys = num_phys; -+ - port_table = kcalloc(ioc->sas_hba.num_phys, - sizeof(struct hba_port), GFP_KERNEL); - if (!port_table) -@@ -6611,6 +6626,30 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) - ioc->sas_hba.phy[i].hba_vphy = 1; - } - -+ /* -+ * Add new HBA phys to STL if these new phys got added as part -+ * of HBA Firmware upgrade/downgrade operation. -+ */ -+ if (!ioc->sas_hba.phy[i].phy) { -+ if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, -+ &phy_pg0, i))) { -+ ioc_err(ioc, "failure at %s:%d/%s()!\n", -+ __FILE__, __LINE__, __func__); -+ continue; -+ } -+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & -+ MPI2_IOCSTATUS_MASK; -+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { -+ ioc_err(ioc, "failure at %s:%d/%s()!\n", -+ __FILE__, __LINE__, __func__); -+ continue; -+ } -+ ioc->sas_hba.phy[i].phy_id = i; -+ mpt3sas_transport_add_host_phy(ioc, -+ &ioc->sas_hba.phy[i], phy_pg0, -+ ioc->sas_hba.parent_dev); -+ continue; -+ } - ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; - attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. - AttachedDevHandle); -@@ -6622,6 +6661,19 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) - attached_handle, i, link_rate, - ioc->sas_hba.phy[i].port); - } -+ /* -+ * Clear the phy details if this phy got disabled as part of -+ * HBA Firmware upgrade/downgrade operation. -+ */ -+ for (i = ioc->sas_hba.num_phys; -+ i < ioc->sas_hba.nr_phys_allocated; i++) { -+ if (ioc->sas_hba.phy[i].phy && -+ ioc->sas_hba.phy[i].phy->negotiated_linkrate >= -+ SAS_LINK_RATE_1_5_GBPS) -+ mpt3sas_transport_update_links(ioc, -+ ioc->sas_hba.sas_address, 0, i, -+ MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED, NULL); -+ } - out: - kfree(sas_iounit_pg0); - } -@@ -6654,7 +6706,10 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) - __FILE__, __LINE__, __func__); - return; - } -- ioc->sas_hba.phy = kcalloc(num_phys, -+ -+ ioc->sas_hba.nr_phys_allocated = max_t(u8, -+ MPT_MAX_HBA_NUM_PHYS, num_phys); -+ ioc->sas_hba.phy = kcalloc(ioc->sas_hba.nr_phys_allocated, - sizeof(struct _sas_phy), GFP_KERNEL); - if (!ioc->sas_hba.phy) { - ioc_err(ioc, "failure at %s:%d/%s()!\n", -diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c -index 63690508313b7..639b7e38a1947 100644 ---- a/drivers/scsi/pm8001/pm8001_hwi.c -+++ b/drivers/scsi/pm8001/pm8001_hwi.c -@@ -3169,7 +3169,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) - * fw_control_context->usrAddr - */ - complete(pm8001_ha->nvmd_completion); -- pm8001_dbg(pm8001_ha, MSG, "Set nvm data complete!\n"); -+ pm8001_dbg(pm8001_ha, MSG, "Get nvmd data complete!\n"); - ccb->task = NULL; - ccb->ccb_tag = 0xFFFFFFFF; - pm8001_tag_free(pm8001_ha, tag); -diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c -index 47db7e0beae6f..a25a34535b7a4 100644 ---- a/drivers/scsi/pm8001/pm8001_init.c -+++ b/drivers/scsi/pm8001/pm8001_init.c -@@ -281,12 +281,12 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, - if (rc) { - pm8001_dbg(pm8001_ha, FAIL, - "pm8001_setup_irq failed [ret: %d]\n", rc); -- goto err_out_shost; -+ goto err_out; - } - /* Request Interrupt */ - rc = pm8001_request_irq(pm8001_ha); - if (rc) -- goto err_out_shost; -+ goto err_out; - - count = pm8001_ha->max_q_num; - /* Queues are chosen based on the number of cores/msix availability */ -@@ -422,8 +422,6 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, - pm8001_tag_init(pm8001_ha); - return 0; - --err_out_shost: -- scsi_remove_host(pm8001_ha->shost); - err_out_nodev: - for (i = 0; i < pm8001_ha->max_memcnt; i++) { - if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) { -@@ -1198,6 +1196,7 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost, - goto err_out; - - /* Memory region for ccb_info*/ -+ pm8001_ha->ccb_count = ccb_count; - pm8001_ha->ccb_info = - kcalloc(ccb_count, sizeof(struct pm8001_ccb_info), GFP_KERNEL); - if (!pm8001_ha->ccb_info) { -@@ -1259,6 +1258,16 @@ static void pm8001_pci_remove(struct pci_dev *pdev) - tasklet_kill(&pm8001_ha->tasklet[j]); - #endif - scsi_host_put(pm8001_ha->shost); -+ -+ for (i = 0; i < pm8001_ha->ccb_count; i++) { -+ dma_free_coherent(&pm8001_ha->pdev->dev, -+ sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG, -+ pm8001_ha->ccb_info[i].buf_prd, -+ pm8001_ha->ccb_info[i].ccb_dma_handle); -+ } -+ kfree(pm8001_ha->ccb_info); -+ kfree(pm8001_ha->devices); -+ - pm8001_free(pm8001_ha); - kfree(sha->sas_phy); - kfree(sha->sas_port); -diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h -index 62d08b535a4b6..f40a41f450d9b 100644 ---- a/drivers/scsi/pm8001/pm8001_sas.h -+++ b/drivers/scsi/pm8001/pm8001_sas.h -@@ -457,6 +457,7 @@ struct outbound_queue_table { - __le32 producer_index; - u32 consumer_idx; - spinlock_t oq_lock; -+ unsigned long lock_flags; - }; - struct pm8001_hba_memspace { - void __iomem *memvirtaddr; -@@ -516,6 +517,7 @@ struct pm8001_hba_info { - u32 iomb_size; /* SPC and SPCV IOMB size */ - struct pm8001_device *devices; - struct pm8001_ccb_info *ccb_info; -+ u32 ccb_count; - #ifdef PM8001_USE_MSIX - int number_of_intr;/*will be used in remove()*/ - char intr_drvname[PM8001_MAX_MSIX_VEC] -@@ -738,9 +740,7 @@ pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha, - { - pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb_idx); - smp_mb(); /*in order to force CPU ordering*/ -- spin_unlock(&pm8001_ha->lock); - task->task_done(task); -- spin_lock(&pm8001_ha->lock); - } - - #endif -diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c -index 6ffe17b849ae8..ed02e1aaf868c 100644 ---- a/drivers/scsi/pm8001/pm80xx_hwi.c -+++ b/drivers/scsi/pm8001/pm80xx_hwi.c -@@ -2379,7 +2379,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb) - - /*See the comments for mpi_ssp_completion */ - static void --mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) -+mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, -+ struct outbound_queue_table *circularQ, void *piomb) - { - struct sas_task *t; - struct pm8001_ccb_info *ccb; -@@ -2616,7 +2617,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) - IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); - ts->resp = SAS_TASK_UNDELIVERED; - ts->stat = SAS_QUEUE_FULL; -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - return; - } - break; -@@ -2632,7 +2637,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) - IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); - ts->resp = SAS_TASK_UNDELIVERED; - ts->stat = SAS_QUEUE_FULL; -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - return; - } - break; -@@ -2656,7 +2665,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) - IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY); - ts->resp = SAS_TASK_UNDELIVERED; - ts->stat = SAS_QUEUE_FULL; -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - return; - } - break; -@@ -2727,7 +2740,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) - IO_DS_NON_OPERATIONAL); - ts->resp = SAS_TASK_UNDELIVERED; - ts->stat = SAS_QUEUE_FULL; -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - return; - } - break; -@@ -2747,7 +2764,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) - IO_DS_IN_ERROR); - ts->resp = SAS_TASK_UNDELIVERED; - ts->stat = SAS_QUEUE_FULL; -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - return; - } - break; -@@ -2785,12 +2806,17 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - } else { - spin_unlock_irqrestore(&t->task_state_lock, flags); -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - } - } - - /*See the comments for mpi_ssp_completion */ --static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) -+static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, -+ struct outbound_queue_table *circularQ, void *piomb) - { - struct sas_task *t; - struct task_status_struct *ts; -@@ -2890,7 +2916,11 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) - IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); - ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAS_QUEUE_FULL; -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - return; - } - break; -@@ -3002,7 +3032,11 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - } else { - spin_unlock_irqrestore(&t->task_state_lock, flags); -+ spin_unlock_irqrestore(&circularQ->oq_lock, -+ circularQ->lock_flags); - pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); -+ spin_lock_irqsave(&circularQ->oq_lock, -+ circularQ->lock_flags); - } - } - -@@ -3902,7 +3936,8 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha, - * @pm8001_ha: our hba card information - * @piomb: IO message buffer - */ --static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) -+static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, -+ struct outbound_queue_table *circularQ, void *piomb) - { - __le32 pHeader = *(__le32 *)piomb; - u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF); -@@ -3944,11 +3979,11 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) - break; - case OPC_OUB_SATA_COMP: - pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n"); -- mpi_sata_completion(pm8001_ha, piomb); -+ mpi_sata_completion(pm8001_ha, circularQ, piomb); - break; - case OPC_OUB_SATA_EVENT: - pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n"); -- mpi_sata_event(pm8001_ha, piomb); -+ mpi_sata_event(pm8001_ha, circularQ, piomb); - break; - case OPC_OUB_SSP_EVENT: - pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n"); -@@ -4117,7 +4152,6 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) - void *pMsg1 = NULL; - u8 bc; - u32 ret = MPI_IO_STATUS_FAIL; -- unsigned long flags; - u32 regval; - - if (vec == (pm8001_ha->max_q_num - 1)) { -@@ -4134,7 +4168,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) - } - } - circularQ = &pm8001_ha->outbnd_q_tbl[vec]; -- spin_lock_irqsave(&circularQ->oq_lock, flags); -+ spin_lock_irqsave(&circularQ->oq_lock, circularQ->lock_flags); - do { - /* spurious interrupt during setup if kexec-ing and - * driver doing a doorbell access w/ the pre-kexec oq -@@ -4145,7 +4179,8 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) - ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); - if (MPI_IO_STATUS_SUCCESS == ret) { - /* process the outbound message */ -- process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4)); -+ process_one_iomb(pm8001_ha, circularQ, -+ (void *)(pMsg1 - 4)); - /* free the message from the outbound circular buffer */ - pm8001_mpi_msg_free_set(pm8001_ha, pMsg1, - circularQ, bc); -@@ -4160,7 +4195,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) - break; - } - } while (1); -- spin_unlock_irqrestore(&circularQ->oq_lock, flags); -+ spin_unlock_irqrestore(&circularQ->oq_lock, circularQ->lock_flags); - return ret; - } - -diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c -index 42d0d941dba5c..94ee08fab46a5 100644 ---- a/drivers/scsi/qedf/qedf_main.c -+++ b/drivers/scsi/qedf/qedf_main.c -@@ -3416,7 +3416,9 @@ retry_probe: - qedf->devlink = qed_ops->common->devlink_register(qedf->cdev); - if (IS_ERR(qedf->devlink)) { - QEDF_ERR(&qedf->dbg_ctx, "Cannot register devlink\n"); -+ rc = PTR_ERR(qedf->devlink); - qedf->devlink = NULL; -+ goto err2; - } - } - -diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c -index d09776b77af2e..cb5f2ecb652d3 100644 ---- a/drivers/scsi/qla2xxx/qla_attr.c -+++ b/drivers/scsi/qla2xxx/qla_attr.c -@@ -1868,6 +1868,18 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, - return strlen(buf); - } - -+static const struct { -+ u16 rate; -+ char *str; -+} port_speed_str[] = { -+ { PORT_SPEED_4GB, "4" }, -+ { PORT_SPEED_8GB, "8" }, -+ { PORT_SPEED_16GB, "16" }, -+ { PORT_SPEED_32GB, "32" }, -+ { PORT_SPEED_64GB, "64" }, -+ { PORT_SPEED_10GB, "10" }, -+}; -+ - static ssize_t - qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, - char *buf) -@@ -1875,7 +1887,8 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, - struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); - struct qla_hw_data *ha = vha->hw; - ssize_t rval; -- char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"}; -+ u16 i; -+ char *speed = "Unknown"; - - rval = qla2x00_get_data_rate(vha); - if (rval != QLA_SUCCESS) { -@@ -1884,7 +1897,14 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, - return -EINVAL; - } - -- return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]); -+ for (i = 0; i < ARRAY_SIZE(port_speed_str); i++) { -+ if (port_speed_str[i].rate != ha->link_data_rate) -+ continue; -+ speed = port_speed_str[i].str; -+ break; -+ } -+ -+ return scnprintf(buf, PAGE_SIZE, "%s\n", speed); - } - - static ssize_t -diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c -index 25549a8a2d72d..7cf1f78cbaeee 100644 ---- a/drivers/scsi/qla2xxx/qla_dbg.c -+++ b/drivers/scsi/qla2xxx/qla_dbg.c -@@ -2491,6 +2491,9 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) - struct va_format vaf; - char pbuf[64]; - -+ if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled()) -+ return; -+ - va_start(va, fmt); - - vaf.fmt = fmt; -diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c -index ad746c62f0d44..a04693498dc01 100644 ---- a/drivers/scsi/qla2xxx/qla_edif.c -+++ b/drivers/scsi/qla2xxx/qla_edif.c -@@ -290,63 +290,6 @@ qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid) - return false; - } - --static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state, -- int waitonly) --{ -- int cnt, max_cnt = 200; -- bool traced = false; -- -- fcport->keep_nport_handle = 1; -- -- if (!waitonly) { -- qla2x00_set_fcport_disc_state(fcport, state); -- qlt_schedule_sess_for_deletion(fcport); -- } else { -- qla2x00_set_fcport_disc_state(fcport, state); -- } -- -- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, -- "%s: waiting for session, max_cnt=%u\n", -- __func__, max_cnt); -- -- cnt = 0; -- -- if (waitonly) { -- /* Marker wait min 10 msecs. */ -- msleep(50); -- cnt += 50; -- } -- while (1) { -- if (!traced) { -- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, -- "%s: session sleep.\n", -- __func__); -- traced = true; -- } -- msleep(20); -- cnt++; -- if (waitonly && (fcport->disc_state == state || -- fcport->disc_state == DSC_LOGIN_COMPLETE)) -- break; -- if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) -- break; -- if (cnt > max_cnt) -- break; -- } -- -- if (!waitonly) { -- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, -- "%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n", -- __func__, fcport->port_name, fcport->loop_id, -- fcport->d_id.b24, fcport, fcport->disc_state, cnt); -- } else { -- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, -- "%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n", -- __func__, fcport->port_name, fcport->loop_id, -- fcport->d_id.b24, fcport, fcport->disc_state, cnt); -- } --} -- - static void - qla_edif_free_sa_ctl(fc_port_t *fcport, struct edif_sa_ctl *sa_ctl, - int index) -@@ -529,7 +472,8 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - struct app_start_reply appreply; - struct fc_port *fcport, *tf; - -- ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__); -+ ql_log(ql_log_info, vha, 0x1313, -+ "EDIF application registration with driver, FC device connections will be re-established.\n"); - - sg_copy_to_buffer(bsg_job->request_payload.sg_list, - bsg_job->request_payload.sg_cnt, &appstart, -@@ -554,37 +498,36 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - qla2xxx_wake_dpc(vha); - } else { - list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { -+ ql_dbg(ql_dbg_edif, vha, 0x2058, -+ "FCSP - nn %8phN pn %8phN portid=%06x.\n", -+ fcport->node_name, fcport->port_name, -+ fcport->d_id.b24); - ql_dbg(ql_dbg_edif, vha, 0xf084, -- "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n", -- __func__, fcport, fcport->port_name, -- fcport->loop_id, fcport->d_id.b24, -- fcport->logout_on_delete); -- -- ql_dbg(ql_dbg_edif, vha, 0xf084, -- "keep %d els_logo %d disc state %d auth state %d stop state %d\n", -- fcport->keep_nport_handle, -- fcport->send_els_logo, fcport->disc_state, -- fcport->edif.auth_state, fcport->edif.app_stop); -+ "%s: se_sess %p / sess %p from port %8phC " -+ "loop_id %#04x s_id %06x logout %d " -+ "keep %d els_logo %d disc state %d auth state %d" -+ "stop state %d\n", -+ __func__, fcport->se_sess, fcport, -+ fcport->port_name, fcport->loop_id, -+ fcport->d_id.b24, fcport->logout_on_delete, -+ fcport->keep_nport_handle, fcport->send_els_logo, -+ fcport->disc_state, fcport->edif.auth_state, -+ fcport->edif.app_stop); - - if (atomic_read(&vha->loop_state) == LOOP_DOWN) - break; -- if (!(fcport->flags & FCF_FCSP_DEVICE)) -- continue; - - fcport->edif.app_started = 1; -- if (fcport->edif.app_stop || -- (fcport->disc_state != DSC_LOGIN_COMPLETE && -- fcport->disc_state != DSC_LOGIN_PEND && -- fcport->disc_state != DSC_DELETED)) { -- /* no activity */ -- fcport->edif.app_stop = 0; -- -- ql_dbg(ql_dbg_edif, vha, 0x911e, -- "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", -- __func__, fcport->port_name); -- fcport->edif.app_sess_online = 1; -- qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); -- } -+ fcport->login_retry = vha->hw->login_retry_count; -+ -+ /* no activity */ -+ fcport->edif.app_stop = 0; -+ -+ ql_dbg(ql_dbg_edif, vha, 0x911e, -+ "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", -+ __func__, fcport->port_name); -+ fcport->edif.app_sess_online = 0; -+ qlt_schedule_sess_for_deletion(fcport); - qla_edif_sa_ctl_init(vha, fcport); - } - } -@@ -601,14 +544,14 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - appreply.edif_enode_active = vha->pur_cinfo.enode_flags; - appreply.edif_edb_active = vha->e_dbell.db_flags; - -- bsg_job->reply_len = sizeof(struct fc_bsg_reply) + -- sizeof(struct app_start_reply); -+ bsg_job->reply_len = sizeof(struct fc_bsg_reply); - - SET_DID_STATUS(bsg_reply->result, DID_OK); - -- sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -- bsg_job->reply_payload.sg_cnt, &appreply, -- sizeof(struct app_start_reply)); -+ bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -+ bsg_job->reply_payload.sg_cnt, -+ &appreply, -+ sizeof(struct app_start_reply)); - - ql_dbg(ql_dbg_edif, vha, 0x911d, - "%s app start completed with 0x%x\n", -@@ -800,15 +743,15 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - ql_dbg(ql_dbg_edif, vha, 0x911e, - "%s AUTH complete - RESUME with prli for wwpn %8phC\n", - __func__, fcport->port_name); -- qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 1); - qla24xx_post_prli_work(vha, fcport); - } - - errstate_exit: - bsg_job->reply_len = sizeof(struct fc_bsg_reply); -- sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -- bsg_job->reply_payload.sg_cnt, &appplogireply, -- sizeof(struct app_plogi_reply)); -+ bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -+ bsg_job->reply_payload.sg_cnt, -+ &appplogireply, -+ sizeof(struct app_plogi_reply)); - - return rval; - } -@@ -873,7 +816,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - - if (qla_ini_mode_enabled(fcport->vha)) { - fcport->send_els_logo = 1; -- qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); -+ qlt_schedule_sess_for_deletion(fcport); - } - } - -@@ -891,7 +834,7 @@ static int - qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - { - int32_t rval = 0; -- int32_t num_cnt; -+ int32_t pcnt = 0; - struct fc_bsg_reply *bsg_reply = bsg_job->reply; - struct app_pinfo_req app_req; - struct app_pinfo_reply *app_reply; -@@ -903,16 +846,14 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - bsg_job->request_payload.sg_cnt, &app_req, - sizeof(struct app_pinfo_req)); - -- num_cnt = app_req.num_ports; /* num of ports alloc'd by app */ -- - app_reply = kzalloc((sizeof(struct app_pinfo_reply) + -- sizeof(struct app_pinfo) * num_cnt), GFP_KERNEL); -+ sizeof(struct app_pinfo) * app_req.num_ports), GFP_KERNEL); -+ - if (!app_reply) { - SET_DID_STATUS(bsg_reply->result, DID_ERROR); - rval = -1; - } else { - struct fc_port *fcport = NULL, *tf; -- uint32_t pcnt = 0; - - list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { - if (!(fcport->flags & FCF_FCSP_DEVICE)) -@@ -924,7 +865,7 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - "APP request entry - portid=%06x.\n", tdid.b24); - - /* Ran out of space */ -- if (pcnt > app_req.num_ports) -+ if (pcnt >= app_req.num_ports) - break; - - if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24) -@@ -981,9 +922,11 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - SET_DID_STATUS(bsg_reply->result, DID_OK); - } - -- sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -- bsg_job->reply_payload.sg_cnt, app_reply, -- sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * num_cnt); -+ bsg_job->reply_len = sizeof(struct fc_bsg_reply); -+ bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -+ bsg_job->reply_payload.sg_cnt, -+ app_reply, -+ sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * pcnt); - - kfree(app_reply); - -@@ -1000,10 +943,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - { - int32_t rval = 0; - struct fc_bsg_reply *bsg_reply = bsg_job->reply; -- uint32_t ret_size, size; -+ uint32_t size; - - struct app_sinfo_req app_req; - struct app_stats_reply *app_reply; -+ uint32_t pcnt = 0; - - sg_copy_to_buffer(bsg_job->request_payload.sg_list, - bsg_job->request_payload.sg_cnt, &app_req, -@@ -1019,18 +963,12 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - size = sizeof(struct app_stats_reply) + - (sizeof(struct app_sinfo) * app_req.num_ports); - -- if (size > bsg_job->reply_payload.payload_len) -- ret_size = bsg_job->reply_payload.payload_len; -- else -- ret_size = size; -- - app_reply = kzalloc(size, GFP_KERNEL); - if (!app_reply) { - SET_DID_STATUS(bsg_reply->result, DID_ERROR); - rval = -1; - } else { - struct fc_port *fcport = NULL, *tf; -- uint32_t pcnt = 0; - - list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { - if (fcport->edif.enable) { -@@ -1054,9 +992,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) - SET_DID_STATUS(bsg_reply->result, DID_OK); - } - -+ bsg_job->reply_len = sizeof(struct fc_bsg_reply); - bsg_reply->reply_payload_rcv_len = - sg_copy_from_buffer(bsg_job->reply_payload.sg_list, -- bsg_job->reply_payload.sg_cnt, app_reply, ret_size); -+ bsg_job->reply_payload.sg_cnt, app_reply, -+ sizeof(struct app_stats_reply) + (sizeof(struct app_sinfo) * pcnt)); - - kfree(app_reply); - -@@ -1130,8 +1070,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) - __func__, - bsg_request->rqst_data.h_vendor.vendor_cmd[1]); - rval = EXT_STATUS_INVALID_PARAM; -- bsg_job->reply_len = sizeof(struct fc_bsg_reply); -- SET_DID_STATUS(bsg_reply->result, DID_ERROR); -+ done = false; - break; - } - -@@ -1651,6 +1590,40 @@ qla_enode_stop(scsi_qla_host_t *vha) - spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags); - } - -+static void qla_enode_clear(scsi_qla_host_t *vha, port_id_t portid) -+{ -+ unsigned long flags; -+ struct enode *e, *tmp; -+ struct purexevent *purex; -+ LIST_HEAD(enode_list); -+ -+ if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) { -+ ql_dbg(ql_dbg_edif, vha, 0x09102, -+ "%s enode not active\n", __func__); -+ return; -+ } -+ spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags); -+ list_for_each_entry_safe(e, tmp, &vha->pur_cinfo.head, list) { -+ purex = &e->u.purexinfo; -+ if (purex->pur_info.pur_sid.b24 == portid.b24) { -+ ql_dbg(ql_dbg_edif, vha, 0x911d, -+ "%s free ELS sid=%06x. xchg %x, nb=%xh\n", -+ __func__, portid.b24, -+ purex->pur_info.pur_rx_xchg_address, -+ purex->pur_info.pur_bytes_rcvd); -+ -+ list_del_init(&e->list); -+ list_add_tail(&e->list, &enode_list); -+ } -+ } -+ spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags); -+ -+ list_for_each_entry_safe(e, tmp, &enode_list, list) { -+ list_del_init(&e->list); -+ qla_enode_free(vha, e); -+ } -+} -+ - /* - * allocate enode struct and populate buffer - * returns: enode pointer with buffers -@@ -1850,6 +1823,57 @@ qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node) - node->ntype = N_UNDEF; - } - -+static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid) -+{ -+ unsigned long flags; -+ struct edb_node *e, *tmp; -+ port_id_t sid; -+ LIST_HEAD(edb_list); -+ -+ if (vha->e_dbell.db_flags != EDB_ACTIVE) { -+ /* doorbell list not enabled */ -+ ql_dbg(ql_dbg_edif, vha, 0x09102, -+ "%s doorbell not enabled\n", __func__); -+ return; -+ } -+ -+ /* grab lock so list doesn't move */ -+ spin_lock_irqsave(&vha->e_dbell.db_lock, flags); -+ list_for_each_entry_safe(e, tmp, &vha->e_dbell.head, list) { -+ switch (e->ntype) { -+ case VND_CMD_AUTH_STATE_NEEDED: -+ case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN: -+ sid = e->u.plogi_did; -+ break; -+ case VND_CMD_AUTH_STATE_ELS_RCVD: -+ sid = e->u.els_sid; -+ break; -+ case VND_CMD_AUTH_STATE_SAUPDATE_COMPL: -+ /* app wants to see this */ -+ continue; -+ default: -+ ql_log(ql_log_warn, vha, 0x09102, -+ "%s unknown node type: %x\n", __func__, e->ntype); -+ sid.b24 = 0; -+ break; -+ } -+ if (sid.b24 == portid.b24) { -+ ql_dbg(ql_dbg_edif, vha, 0x910f, -+ "%s free doorbell event : node type = %x %p\n", -+ __func__, e->ntype, e); -+ list_del_init(&e->list); -+ list_add_tail(&e->list, &edb_list); -+ } -+ } -+ spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags); -+ -+ list_for_each_entry_safe(e, tmp, &edb_list, list) { -+ qla_edb_node_free(vha, e); -+ list_del_init(&e->list); -+ kfree(e); -+ } -+} -+ - /* function called when app is stopping */ - - void -@@ -2357,7 +2381,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) - return; - } - -- if (totlen > MAX_PAYLOAD) { -+ if (totlen > ELS_MAX_PAYLOAD) { - ql_dbg(ql_dbg_edif, vha, 0x0910d, - "%s WARNING: verbose ELS frame received (totlen=%x)\n", - __func__, totlen); -@@ -2436,7 +2460,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) - ql_dbg(ql_dbg_edif, host, 0x0910c, - "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n", - __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24, -- purex->pur_info.pur_did.b24, p->rx_xchg_addr); -+ purex->pur_info.pur_did.b24, purex->pur_info.pur_rx_xchg_address); - - qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL); - } -@@ -3459,3 +3483,12 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess) - qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24); - } - } -+ -+void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport) -+{ -+ if (!(fcport->flags & FCF_FCSP_DEVICE)) -+ return; -+ -+ qla_edb_clear(vha, fcport->d_id); -+ qla_enode_clear(vha, fcport->d_id); -+} -diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h -index 9e8f28d0caa1b..45cf87e337780 100644 ---- a/drivers/scsi/qla2xxx/qla_edif.h -+++ b/drivers/scsi/qla2xxx/qla_edif.h -@@ -93,7 +93,6 @@ struct sa_update_28xx { - }; - - #define NUM_ENTRIES 256 --#define MAX_PAYLOAD 1024 - #define PUR_GET 1 - - struct dinfo { -@@ -128,6 +127,8 @@ struct enode { - } u; - }; - -+#define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES)) -+ - #define EDIF_SESSION_DOWN(_s) \ - (qla_ini_mode_enabled(_s->vha) && (_s->disc_state == DSC_DELETE_PEND || \ - _s->disc_state == DSC_DELETED || \ -diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h -index 58b718d35d19a..53026d82ebffe 100644 ---- a/drivers/scsi/qla2xxx/qla_edif_bsg.h -+++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h -@@ -8,7 +8,7 @@ - #define __QLA_EDIF_BSG_H - - /* BSG Vendor specific commands */ --#define ELS_MAX_PAYLOAD 1024 -+#define ELS_MAX_PAYLOAD 2112 - #ifndef WWN_SIZE - #define WWN_SIZE 8 - #endif -diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h -index 1c3f055d41b8e..2c7e91bffb827 100644 ---- a/drivers/scsi/qla2xxx/qla_gbl.h -+++ b/drivers/scsi/qla2xxx/qla_gbl.h -@@ -142,6 +142,8 @@ void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport, - void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport); - int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsgjob); - void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess); -+void qla_edif_clear_appdata(struct scsi_qla_host *vha, -+ struct fc_port *fcport); - const char *sc_to_str(uint16_t cmd); - - /* -@@ -171,7 +173,6 @@ extern int ql2xasynctmfenable; - extern int ql2xgffidenable; - extern int ql2xenabledif; - extern int ql2xenablehba_err_chk; --extern int ql2xtargetreset; - extern int ql2xdontresethba; - extern uint64_t ql2xmaxlun; - extern int ql2xmdcapmask; -@@ -816,7 +817,6 @@ extern void qlafx00_abort_iocb(srb_t *, struct abort_iocb_entry_fx00 *); - extern void qlafx00_fxdisc_iocb(srb_t *, struct fxdisc_entry_fx00 *); - extern void qlafx00_timer_routine(scsi_qla_host_t *); - extern int qlafx00_rescan_isp(scsi_qla_host_t *); --extern int qlafx00_loop_reset(scsi_qla_host_t *vha); - - /* qla82xx related functions */ - -diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c -index 5fc7697f0af4c..847a6e5d9cb07 100644 ---- a/drivers/scsi/qla2xxx/qla_init.c -+++ b/drivers/scsi/qla2xxx/qla_init.c -@@ -987,8 +987,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) - sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1], - sp->u.iocb_cmd.u.mbx.in_mb[2]); - -- if (res == QLA_FUNCTION_TIMEOUT) -- return; - - sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE); - memset(&ea, 0, sizeof(ea)); -@@ -1026,8 +1024,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) - spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); - - list_for_each_entry_safe(fcport, tf, &h, gnl_entry) { -- list_del_init(&fcport->gnl_entry); - spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); -+ list_del_init(&fcport->gnl_entry); - fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); - spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); - ea.fcport = fcport; -@@ -1786,16 +1784,52 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) - fc_port_t *fcport; - unsigned long flags; - -- fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); -- if (fcport) { -- if (fcport->flags & FCF_FCP2_DEVICE) { -- ql_dbg(ql_dbg_disc, vha, 0x2115, -- "Delaying session delete for FCP2 portid=%06x %8phC ", -- fcport->d_id.b24, fcport->port_name); -- return; -+ switch (ea->id.b.rsvd_1) { -+ case RSCN_PORT_ADDR: -+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); -+ if (fcport) { -+ if (fcport->flags & FCF_FCP2_DEVICE) { -+ ql_dbg(ql_dbg_disc, vha, 0x2115, -+ "Delaying session delete for FCP2 portid=%06x %8phC ", -+ fcport->d_id.b24, fcport->port_name); -+ return; -+ } -+ fcport->scan_needed = 1; -+ fcport->rscn_gen++; - } -- fcport->scan_needed = 1; -- fcport->rscn_gen++; -+ break; -+ case RSCN_AREA_ADDR: -+ list_for_each_entry(fcport, &vha->vp_fcports, list) { -+ if (fcport->flags & FCF_FCP2_DEVICE) -+ continue; -+ -+ if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) { -+ fcport->scan_needed = 1; -+ fcport->rscn_gen++; -+ } -+ } -+ break; -+ case RSCN_DOM_ADDR: -+ list_for_each_entry(fcport, &vha->vp_fcports, list) { -+ if (fcport->flags & FCF_FCP2_DEVICE) -+ continue; -+ -+ if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) { -+ fcport->scan_needed = 1; -+ fcport->rscn_gen++; -+ } -+ } -+ break; -+ case RSCN_FAB_ADDR: -+ default: -+ list_for_each_entry(fcport, &vha->vp_fcports, list) { -+ if (fcport->flags & FCF_FCP2_DEVICE) -+ continue; -+ -+ fcport->scan_needed = 1; -+ fcport->rscn_gen++; -+ } -+ break; - } - - spin_lock_irqsave(&vha->work_lock, flags); -@@ -4433,6 +4467,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha) - (ha->flags.fawwpn_enabled) ? "enabled" : "disabled"); - } - -+ /* ELS pass through payload is limit by frame size. */ -+ if (ha->flags.edif_enabled) -+ mid_init_cb->init_cb.frame_payload_size = cpu_to_le16(ELS_MAX_PAYLOAD); -+ - rval = qla2x00_init_firmware(vha, ha->init_cb_size); - next_check: - if (rval) { -@@ -5335,15 +5373,14 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) - "LOOP READY.\n"); - ha->flags.fw_init_done = 1; - -+ /* -+ * use link up to wake up app to get ready for -+ * authentication. -+ */ - if (ha->flags.edif_enabled && -- !(vha->e_dbell.db_flags & EDB_ACTIVE) && -- N2N_TOPO(vha->hw)) { -- /* -- * use port online to wake up app to get ready -- * for authentication -- */ -- qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE, 0); -- } -+ !(vha->e_dbell.db_flags & EDB_ACTIVE)) -+ qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, -+ ha->link_data_rate); - - /* - * Process any ATIO queue entries that came in -diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c -index 7811c4952035b..a6debeea30798 100644 ---- a/drivers/scsi/qla2xxx/qla_mbx.c -+++ b/drivers/scsi/qla2xxx/qla_mbx.c -@@ -1695,10 +1695,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, - mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; - if (IS_FWI2_CAPABLE(vha->hw)) - mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; -- if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { -- mcp->in_mb |= MBX_15; -- mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23; -- } -+ if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) -+ mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23; - - mcp->tov = MBX_TOV_SECONDS; - mcp->flags = 0; -diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c -index 6e920da64863e..350b0c4346fb6 100644 ---- a/drivers/scsi/qla2xxx/qla_mr.c -+++ b/drivers/scsi/qla2xxx/qla_mr.c -@@ -738,29 +738,6 @@ qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag) - return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); - } - --int --qlafx00_loop_reset(scsi_qla_host_t *vha) --{ -- int ret; -- struct fc_port *fcport; -- struct qla_hw_data *ha = vha->hw; -- -- if (ql2xtargetreset) { -- list_for_each_entry(fcport, &vha->vp_fcports, list) { -- if (fcport->port_type != FCT_TARGET) -- continue; -- -- ret = ha->isp_ops->target_reset(fcport, 0, 0); -- if (ret != QLA_SUCCESS) { -- ql_dbg(ql_dbg_taskm, vha, 0x803d, -- "Bus Reset failed: Reset=%d " -- "d_id=%x.\n", ret, fcport->d_id.b24); -- } -- } -- } -- return QLA_SUCCESS; --} -- - int - qlafx00_iospace_config(struct qla_hw_data *ha) - { -diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c -index 1c5da2dbd6f97..877b2b6250204 100644 ---- a/drivers/scsi/qla2xxx/qla_nvme.c -+++ b/drivers/scsi/qla2xxx/qla_nvme.c -@@ -228,6 +228,8 @@ static void qla_nvme_abort_work(struct work_struct *work) - fc_port_t *fcport = sp->fcport; - struct qla_hw_data *ha = fcport->vha->hw; - int rval, abts_done_called = 1; -+ bool io_wait_for_abort_done; -+ uint32_t handle; - - ql_dbg(ql_dbg_io, fcport->vha, 0xffff, - "%s called for sp=%p, hndl=%x on fcport=%p desc=%p deleted=%d\n", -@@ -244,12 +246,20 @@ static void qla_nvme_abort_work(struct work_struct *work) - goto out; - } - -+ /* -+ * sp may not be valid after abort_command if return code is either -+ * SUCCESS or ERR_FROM_FW codes, so cache the value here. -+ */ -+ io_wait_for_abort_done = ql2xabts_wait_nvme && -+ QLA_ABTS_WAIT_ENABLED(sp); -+ handle = sp->handle; -+ - rval = ha->isp_ops->abort_command(sp); - - ql_dbg(ql_dbg_io, fcport->vha, 0x212b, - "%s: %s command for sp=%p, handle=%x on fcport=%p rval=%x\n", - __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", -- sp, sp->handle, fcport, rval); -+ sp, handle, fcport, rval); - - /* - * If async tmf is enabled, the abort callback is called only on -@@ -264,7 +274,7 @@ static void qla_nvme_abort_work(struct work_struct *work) - * are waited until ABTS complete. This kref is decreased - * at qla24xx_abort_sp_done function. - */ -- if (abts_done_called && ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp)) -+ if (abts_done_called && io_wait_for_abort_done) - return; - out: - /* kref_get was done before work was schedule. */ -diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c -index 836fedcea241b..8d87cfae9c598 100644 ---- a/drivers/scsi/qla2xxx/qla_os.c -+++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -202,12 +202,6 @@ MODULE_PARM_DESC(ql2xdbwr, - " 0 -- Regular doorbell.\n" - " 1 -- CAMRAM doorbell (faster).\n"); - --int ql2xtargetreset = 1; --module_param(ql2xtargetreset, int, S_IRUGO); --MODULE_PARM_DESC(ql2xtargetreset, -- "Enable target reset." -- "Default is 1 - use hw defaults."); -- - int ql2xgffidenable; - module_param(ql2xgffidenable, int, S_IRUGO); - MODULE_PARM_DESC(ql2xgffidenable, -@@ -1258,6 +1252,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) - uint32_t ratov_j; - struct qla_qpair *qpair; - unsigned long flags; -+ int fast_fail_status = SUCCESS; - - if (qla2x00_isp_reg_stat(ha)) { - ql_log(ql_log_info, vha, 0x8042, -@@ -1266,9 +1261,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) - return FAILED; - } - -+ /* Save any FAST_IO_FAIL value to return later if abort succeeds */ - ret = fc_block_scsi_eh(cmd); - if (ret != 0) -- return ret; -+ fast_fail_status = ret; - - sp = scsi_cmd_priv(cmd); - qpair = sp->qpair; -@@ -1276,7 +1272,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) - vha->cmd_timeout_cnt++; - - if ((sp->fcport && sp->fcport->deleted) || !qpair) -- return SUCCESS; -+ return fast_fail_status != SUCCESS ? fast_fail_status : FAILED; - - spin_lock_irqsave(qpair->qp_lock_ptr, flags); - sp->comp = ∁ -@@ -1311,7 +1307,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) - __func__, ha->r_a_tov/10); - ret = FAILED; - } else { -- ret = SUCCESS; -+ ret = fast_fail_status; - } - break; - default: -@@ -1693,27 +1689,10 @@ int - qla2x00_loop_reset(scsi_qla_host_t *vha) - { - int ret; -- struct fc_port *fcport; - struct qla_hw_data *ha = vha->hw; - -- if (IS_QLAFX00(ha)) { -- return qlafx00_loop_reset(vha); -- } -- -- if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) { -- list_for_each_entry(fcport, &vha->vp_fcports, list) { -- if (fcport->port_type != FCT_TARGET) -- continue; -- -- ret = ha->isp_ops->target_reset(fcport, 0, 0); -- if (ret != QLA_SUCCESS) { -- ql_dbg(ql_dbg_taskm, vha, 0x802c, -- "Bus Reset failed: Reset=%d " -- "d_id=%x.\n", ret, fcport->d_id.b24); -- } -- } -- } -- -+ if (IS_QLAFX00(ha)) -+ return QLA_SUCCESS; - - if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) { - atomic_set(&vha->loop_state, LOOP_DOWN); -@@ -4358,7 +4337,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, - - /* allocate the purex dma pool */ - ha->purex_dma_pool = dma_pool_create(name, &ha->pdev->dev, -- MAX_PAYLOAD, 8, 0); -+ ELS_MAX_PAYLOAD, 8, 0); - - if (!ha->purex_dma_pool) { - ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, -diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c -index 7d8242c120fc7..1aaa4238cb722 100644 ---- a/drivers/scsi/qla2xxx/qla_target.c -+++ b/drivers/scsi/qla2xxx/qla_target.c -@@ -1003,6 +1003,7 @@ void qlt_free_session_done(struct work_struct *work) - "%s bypassing release_all_sadb\n", - __func__); - } -+ qla_edif_clear_appdata(vha, sess); - qla_edif_sess_down(vha, sess); - } - qla2x00_mark_device_lost(vha, sess, 0); -diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c -index 66f507469a31a..cfeadd5f61f18 100644 ---- a/drivers/scsi/scsi_debug.c -+++ b/drivers/scsi/scsi_debug.c -@@ -1189,7 +1189,7 @@ static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr, - __func__, off_dst, scsi_bufflen(scp), act_len, - scsi_get_resid(scp)); - n = scsi_bufflen(scp) - (off_dst + act_len); -- scsi_set_resid(scp, min_t(int, scsi_get_resid(scp), n)); -+ scsi_set_resid(scp, min_t(u32, scsi_get_resid(scp), n)); - return 0; - } - -@@ -1562,7 +1562,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) - unsigned char pq_pdt; - unsigned char *arr; - unsigned char *cmd = scp->cmnd; -- int alloc_len, n, ret; -+ u32 alloc_len, n; -+ int ret; - bool have_wlun, is_disk, is_zbc, is_disk_zbc; - - alloc_len = get_unaligned_be16(cmd + 3); -@@ -1585,7 +1586,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) - kfree(arr); - return check_condition_result; - } else if (0x1 & cmd[1]) { /* EVPD bit set */ -- int lu_id_num, port_group_id, target_dev_id, len; -+ int lu_id_num, port_group_id, target_dev_id; -+ u32 len; - char lu_id_str[6]; - int host_no = devip->sdbg_host->shost->host_no; - -@@ -1676,9 +1678,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) - kfree(arr); - return check_condition_result; - } -- len = min(get_unaligned_be16(arr + 2) + 4, alloc_len); -+ len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len); - ret = fill_from_dev_buffer(scp, arr, -- min(len, SDEBUG_MAX_INQ_ARR_SZ)); -+ min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); - kfree(arr); - return ret; - } -@@ -1714,7 +1716,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) - } - put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */ - ret = fill_from_dev_buffer(scp, arr, -- min_t(int, alloc_len, SDEBUG_LONG_INQ_SZ)); -+ min_t(u32, alloc_len, SDEBUG_LONG_INQ_SZ)); - kfree(arr); - return ret; - } -@@ -1729,8 +1731,8 @@ static int resp_requests(struct scsi_cmnd *scp, - unsigned char *cmd = scp->cmnd; - unsigned char arr[SCSI_SENSE_BUFFERSIZE]; /* assume >= 18 bytes */ - bool dsense = !!(cmd[1] & 1); -- int alloc_len = cmd[4]; -- int len = 18; -+ u32 alloc_len = cmd[4]; -+ u32 len = 18; - int stopped_state = atomic_read(&devip->stopped); - - memset(arr, 0, sizeof(arr)); -@@ -1774,7 +1776,7 @@ static int resp_requests(struct scsi_cmnd *scp, - arr[7] = 0xa; - } - } -- return fill_from_dev_buffer(scp, arr, min_t(int, len, alloc_len)); -+ return fill_from_dev_buffer(scp, arr, min_t(u32, len, alloc_len)); - } - - static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) -@@ -1856,7 +1858,7 @@ static int resp_readcap16(struct scsi_cmnd *scp, - { - unsigned char *cmd = scp->cmnd; - unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; -- int alloc_len; -+ u32 alloc_len; - - alloc_len = get_unaligned_be32(cmd + 10); - /* following just in case virtual_gb changed */ -@@ -1885,7 +1887,7 @@ static int resp_readcap16(struct scsi_cmnd *scp, - } - - return fill_from_dev_buffer(scp, arr, -- min_t(int, alloc_len, SDEBUG_READCAP16_ARR_SZ)); -+ min_t(u32, alloc_len, SDEBUG_READCAP16_ARR_SZ)); - } - - #define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 -@@ -1896,8 +1898,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd *scp, - unsigned char *cmd = scp->cmnd; - unsigned char *arr; - int host_no = devip->sdbg_host->shost->host_no; -- int n, ret, alen, rlen; - int port_group_a, port_group_b, port_a, port_b; -+ u32 alen, n, rlen; -+ int ret; - - alen = get_unaligned_be32(cmd + 6); - arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); -@@ -1959,9 +1962,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd *scp, - * - The constructed command length - * - The maximum array size - */ -- rlen = min_t(int, alen, n); -+ rlen = min(alen, n); - ret = fill_from_dev_buffer(scp, arr, -- min_t(int, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); -+ min_t(u32, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); - kfree(arr); - return ret; - } -@@ -2311,7 +2314,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, - { - int pcontrol, pcode, subpcode, bd_len; - unsigned char dev_spec; -- int alloc_len, offset, len, target_dev_id; -+ u32 alloc_len, offset, len; -+ int target_dev_id; - int target = scp->device->id; - unsigned char *ap; - unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; -@@ -2467,7 +2471,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, - arr[0] = offset - 1; - else - put_unaligned_be16((offset - 2), arr + 0); -- return fill_from_dev_buffer(scp, arr, min_t(int, alloc_len, offset)); -+ return fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, offset)); - } - - #define SDEBUG_MAX_MSELECT_SZ 512 -@@ -2498,11 +2502,11 @@ static int resp_mode_select(struct scsi_cmnd *scp, - __func__, param_len, res); - md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2); - bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6); -- if (md_len > 2) { -+ off = bd_len + (mselect6 ? 4 : 8); -+ if (md_len > 2 || off >= res) { - mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); - return check_condition_result; - } -- off = bd_len + (mselect6 ? 4 : 8); - mpage = arr[off] & 0x3f; - ps = !!(arr[off] & 0x80); - if (ps) { -@@ -2582,7 +2586,8 @@ static int resp_ie_l_pg(unsigned char *arr) - static int resp_log_sense(struct scsi_cmnd *scp, - struct sdebug_dev_info *devip) - { -- int ppc, sp, pcode, subpcode, alloc_len, len, n; -+ int ppc, sp, pcode, subpcode; -+ u32 alloc_len, len, n; - unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; - unsigned char *cmd = scp->cmnd; - -@@ -2652,9 +2657,9 @@ static int resp_log_sense(struct scsi_cmnd *scp, - mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); - return check_condition_result; - } -- len = min_t(int, get_unaligned_be16(arr + 2) + 4, alloc_len); -+ len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len); - return fill_from_dev_buffer(scp, arr, -- min_t(int, len, SDEBUG_MAX_INQ_ARR_SZ)); -+ min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); - } - - static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip) -@@ -4258,6 +4263,8 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) - mk_sense_invalid_opcode(scp); - return check_condition_result; - } -+ if (vnum == 0) -+ return 0; /* not an error */ - a_num = is_bytchk3 ? 1 : vnum; - /* Treat following check like one for read (i.e. no write) access */ - ret = check_device_access_params(scp, lba, a_num, false); -@@ -4321,6 +4328,8 @@ static int resp_report_zones(struct scsi_cmnd *scp, - } - zs_lba = get_unaligned_be64(cmd + 2); - alloc_len = get_unaligned_be32(cmd + 10); -+ if (alloc_len == 0) -+ return 0; /* not an error */ - rep_opts = cmd[14] & 0x3f; - partial = cmd[14] & 0x80; - -@@ -4333,7 +4342,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, - rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD), - max_zones); - -- arr = kcalloc(RZONES_DESC_HD, alloc_len, GFP_ATOMIC); -+ arr = kzalloc(alloc_len, GFP_ATOMIC); - if (!arr) { - mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, - INSUFF_RES_ASCQ); -@@ -4425,7 +4434,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, - put_unaligned_be64(sdebug_capacity - 1, arr + 8); - - rep_len = (unsigned long)desc - (unsigned long)arr; -- ret = fill_from_dev_buffer(scp, arr, min_t(int, alloc_len, rep_len)); -+ ret = fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, rep_len)); - - fini: - read_unlock(macc_lckp); -@@ -4648,6 +4657,7 @@ static void zbc_rwp_zone(struct sdebug_dev_info *devip, - struct sdeb_zone_state *zsp) - { - enum sdebug_z_cond zc; -+ struct sdeb_store_info *sip = devip2sip(devip, false); - - if (zbc_zone_is_conv(zsp)) - return; -@@ -4659,6 +4669,10 @@ static void zbc_rwp_zone(struct sdebug_dev_info *devip, - if (zsp->z_cond == ZC4_CLOSED) - devip->nr_closed--; - -+ if (zsp->z_wp > zsp->z_start) -+ memset(sip->storep + zsp->z_start * sdebug_sector_size, 0, -+ (zsp->z_wp - zsp->z_start) * sdebug_sector_size); -+ - zsp->z_non_seq_resource = false; - zsp->z_wp = zsp->z_start; - zsp->z_cond = ZC1_EMPTY; -diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c -index b6c86cce57bfa..408d49c304b8d 100644 ---- a/drivers/scsi/scsi_error.c -+++ b/drivers/scsi/scsi_error.c -@@ -135,6 +135,23 @@ static bool scsi_eh_should_retry_cmd(struct scsi_cmnd *cmd) - return true; - } - -+static void scsi_eh_complete_abort(struct scsi_cmnd *scmd, struct Scsi_Host *shost) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(shost->host_lock, flags); -+ list_del_init(&scmd->eh_entry); -+ /* -+ * If the abort succeeds, and there is no further -+ * EH action, clear the ->last_reset time. -+ */ -+ if (list_empty(&shost->eh_abort_list) && -+ list_empty(&shost->eh_cmd_q)) -+ if (shost->eh_deadline != -1) -+ shost->last_reset = 0; -+ spin_unlock_irqrestore(shost->host_lock, flags); -+} -+ - /** - * scmd_eh_abort_handler - Handle command aborts - * @work: command to be aborted. -@@ -152,6 +169,7 @@ scmd_eh_abort_handler(struct work_struct *work) - container_of(work, struct scsi_cmnd, abort_work.work); - struct scsi_device *sdev = scmd->device; - enum scsi_disposition rtn; -+ unsigned long flags; - - if (scsi_host_eh_past_deadline(sdev->host)) { - SCSI_LOG_ERROR_RECOVERY(3, -@@ -175,12 +193,14 @@ scmd_eh_abort_handler(struct work_struct *work) - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_WARNING, scmd, - "retry aborted command\n")); -+ scsi_eh_complete_abort(scmd, sdev->host); - scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); - return; - } else { - SCSI_LOG_ERROR_RECOVERY(3, - scmd_printk(KERN_WARNING, scmd, - "finish aborted command\n")); -+ scsi_eh_complete_abort(scmd, sdev->host); - scsi_finish_command(scmd); - return; - } -@@ -193,6 +213,9 @@ scmd_eh_abort_handler(struct work_struct *work) - } - } - -+ spin_lock_irqsave(sdev->host->host_lock, flags); -+ list_del_init(&scmd->eh_entry); -+ spin_unlock_irqrestore(sdev->host->host_lock, flags); - scsi_eh_scmd_add(scmd); - } - -@@ -223,6 +246,8 @@ scsi_abort_command(struct scsi_cmnd *scmd) - spin_lock_irqsave(shost->host_lock, flags); - if (shost->eh_deadline != -1 && !shost->last_reset) - shost->last_reset = jiffies; -+ BUG_ON(!list_empty(&scmd->eh_entry)); -+ list_add_tail(&scmd->eh_entry, &shost->eh_abort_list); - spin_unlock_irqrestore(shost->host_lock, flags); - - scmd->eh_eflags |= SCSI_EH_ABORT_SCHEDULED; -diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c -index 6ff2207bd45a0..a06c61f22742e 100644 ---- a/drivers/scsi/scsi_ioctl.c -+++ b/drivers/scsi/scsi_ioctl.c -@@ -347,6 +347,8 @@ static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq, - { - struct scsi_request *req = scsi_req(rq); - -+ if (hdr->cmd_len < 6) -+ return -EMSGSIZE; - if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len)) - return -EFAULT; - if (!scsi_cmd_allowed(req->cmd, mode)) -diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c -index 572673873ddf8..ef4361b2d1423 100644 ---- a/drivers/scsi/scsi_lib.c -+++ b/drivers/scsi/scsi_lib.c -@@ -1143,6 +1143,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) - cmd->sense_buffer = buf; - cmd->prot_sdb = prot; - cmd->flags = flags; -+ INIT_LIST_HEAD(&cmd->eh_entry); - INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); - cmd->jiffies_at_alloc = jiffies_at_alloc; - cmd->retries = retries; -@@ -1174,8 +1175,6 @@ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, - } - - cmd->cmd_len = scsi_req(req)->cmd_len; -- if (cmd->cmd_len == 0) -- cmd->cmd_len = scsi_command_size(cmd->cmnd); - cmd->cmnd = scsi_req(req)->cmd; - cmd->transfersize = blk_rq_bytes(req); - cmd->allowed = scsi_req(req)->retries; -@@ -2075,7 +2074,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); - /** - * scsi_mode_sense - issue a mode sense, falling back from 10 to six bytes if necessary. - * @sdev: SCSI device to be queried -- * @dbd: set if mode sense will allow block descriptors to be returned -+ * @dbd: set to prevent mode sense from returning block descriptors - * @modepage: mode page being requested - * @buffer: request buffer (may not be smaller than eight bytes) - * @len: length of request buffer. -@@ -2110,18 +2109,18 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, - sshdr = &my_sshdr; - - retry: -- use_10_for_ms = sdev->use_10_for_ms; -+ use_10_for_ms = sdev->use_10_for_ms || len > 255; - - if (use_10_for_ms) { -- if (len < 8) -- len = 8; -+ if (len < 8 || len > 65535) -+ return -EINVAL; - - cmd[0] = MODE_SENSE_10; -- cmd[8] = len; -+ put_unaligned_be16(len, &cmd[7]); - header_length = 8; - } else { - if (len < 4) -- len = 4; -+ return -EINVAL; - - cmd[0] = MODE_SENSE; - cmd[4] = len; -@@ -2145,9 +2144,15 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, - if ((sshdr->sense_key == ILLEGAL_REQUEST) && - (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { - /* -- * Invalid command operation code -+ * Invalid command operation code: retry using -+ * MODE SENSE(6) if this was a MODE SENSE(10) -+ * request, except if the request mode page is -+ * too large for MODE SENSE single byte -+ * allocation length field. - */ - if (use_10_for_ms) { -+ if (len > 255) -+ return -EIO; - sdev->use_10_for_ms = 0; - goto retry; - } -@@ -2171,12 +2176,11 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, - data->longlba = 0; - data->block_descriptor_length = 0; - } else if (use_10_for_ms) { -- data->length = buffer[0]*256 + buffer[1] + 2; -+ data->length = get_unaligned_be16(&buffer[0]) + 2; - data->medium_type = buffer[2]; - data->device_specific = buffer[3]; - data->longlba = buffer[4] & 0x01; -- data->block_descriptor_length = buffer[6]*256 -- + buffer[7]; -+ data->block_descriptor_length = get_unaligned_be16(&buffer[6]); - } else { - data->length = buffer[0] + 1; - data->medium_type = buffer[1]; -diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c -index a35841b34bfd9..920aae661c5b2 100644 ---- a/drivers/scsi/scsi_sysfs.c -+++ b/drivers/scsi/scsi_sysfs.c -@@ -797,6 +797,7 @@ store_state_field(struct device *dev, struct device_attribute *attr, - int i, ret; - struct scsi_device *sdev = to_scsi_device(dev); - enum scsi_device_state state = 0; -+ bool rescan_dev = false; - - for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { - const int len = strlen(sdev_states[i].name); -@@ -815,20 +816,27 @@ store_state_field(struct device *dev, struct device_attribute *attr, - } - - mutex_lock(&sdev->state_mutex); -- ret = scsi_device_set_state(sdev, state); -- /* -- * If the device state changes to SDEV_RUNNING, we need to -- * run the queue to avoid I/O hang, and rescan the device -- * to revalidate it. Running the queue first is necessary -- * because another thread may be waiting inside -- * blk_mq_freeze_queue_wait() and because that call may be -- * waiting for pending I/O to finish. -- */ -- if (ret == 0 && state == SDEV_RUNNING) { -+ if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) { -+ ret = 0; -+ } else { -+ ret = scsi_device_set_state(sdev, state); -+ if (ret == 0 && state == SDEV_RUNNING) -+ rescan_dev = true; -+ } -+ mutex_unlock(&sdev->state_mutex); -+ -+ if (rescan_dev) { -+ /* -+ * If the device state changes to SDEV_RUNNING, we need to -+ * run the queue to avoid I/O hang, and rescan the device -+ * to revalidate it. Running the queue first is necessary -+ * because another thread may be waiting inside -+ * blk_mq_freeze_queue_wait() and because that call may be -+ * waiting for pending I/O to finish. -+ */ - blk_mq_run_hw_queues(sdev->request_queue, true); - scsi_rescan_device(dev); - } -- mutex_unlock(&sdev->state_mutex); - - return ret == 0 ? count : -EINVAL; - } -@@ -1388,6 +1396,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) - * We're treating error on bsg register as non-fatal, so - * pretend nothing went wrong. - */ -+ error = PTR_ERR(sdev->bsg_dev); - sdev_printk(KERN_INFO, sdev, - "Failed to register bsg queue, errno=%d\n", - error); -diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c -index 78343d3f93857..554b6f7842236 100644 ---- a/drivers/scsi/scsi_transport_iscsi.c -+++ b/drivers/scsi/scsi_transport_iscsi.c -@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work) - } - spin_unlock_irqrestore(&session->lock, flags); - -- if (session->transport->session_recovery_timedout) -- session->transport->session_recovery_timedout(session); -- - ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n"); - scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE); - ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n"); -+ -+ if (session->transport->session_recovery_timedout) -+ session->transport->session_recovery_timedout(session); - } - - static void __iscsi_unblock_session(struct work_struct *work) -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index fce63335084ed..78ead3369779c 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -2607,6 +2607,13 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage, - unsigned char *buffer, int len, struct scsi_mode_data *data, - struct scsi_sense_hdr *sshdr) - { -+ /* -+ * If we must use MODE SENSE(10), make sure that the buffer length -+ * is at least 8 bytes so that the mode sense header fits. -+ */ -+ if (sdkp->device->use_10_for_ms && len < 8) -+ len = 8; -+ - return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len, - SD_TIMEOUT, sdkp->max_retries, data, - sshdr); -diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c -index ecb2af3f43ca3..a5453f5e87c3e 100644 ---- a/drivers/scsi/smartpqi/smartpqi_init.c -+++ b/drivers/scsi/smartpqi/smartpqi_init.c -@@ -234,15 +234,46 @@ static inline bool pqi_is_hba_lunid(u8 *scsi3addr) - return pqi_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID); - } - -+#define PQI_DRIVER_SCRATCH_PQI_MODE 0x1 -+#define PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED 0x2 -+ - static inline enum pqi_ctrl_mode pqi_get_ctrl_mode(struct pqi_ctrl_info *ctrl_info) - { -- return sis_read_driver_scratch(ctrl_info); -+ return sis_read_driver_scratch(ctrl_info) & PQI_DRIVER_SCRATCH_PQI_MODE ? PQI_MODE : SIS_MODE; - } - - static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info *ctrl_info, - enum pqi_ctrl_mode mode) - { -- sis_write_driver_scratch(ctrl_info, mode); -+ u32 driver_scratch; -+ -+ driver_scratch = sis_read_driver_scratch(ctrl_info); -+ -+ if (mode == PQI_MODE) -+ driver_scratch |= PQI_DRIVER_SCRATCH_PQI_MODE; -+ else -+ driver_scratch &= ~PQI_DRIVER_SCRATCH_PQI_MODE; -+ -+ sis_write_driver_scratch(ctrl_info, driver_scratch); -+} -+ -+static inline bool pqi_is_fw_triage_supported(struct pqi_ctrl_info *ctrl_info) -+{ -+ return (sis_read_driver_scratch(ctrl_info) & PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED) != 0; -+} -+ -+static inline void pqi_save_fw_triage_setting(struct pqi_ctrl_info *ctrl_info, bool is_supported) -+{ -+ u32 driver_scratch; -+ -+ driver_scratch = sis_read_driver_scratch(ctrl_info); -+ -+ if (is_supported) -+ driver_scratch |= PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED; -+ else -+ driver_scratch &= ~PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED; -+ -+ sis_write_driver_scratch(ctrl_info, driver_scratch); - } - - static inline void pqi_ctrl_block_scan(struct pqi_ctrl_info *ctrl_info) -@@ -7301,6 +7332,7 @@ static void pqi_ctrl_update_feature_flags(struct pqi_ctrl_info *ctrl_info, - ctrl_info->unique_wwid_in_report_phys_lun_supported = - firmware_feature->enabled; - break; -+ pqi_save_fw_triage_setting(ctrl_info, firmware_feature->enabled); - } - - pqi_firmware_feature_status(ctrl_info, firmware_feature); -@@ -7627,6 +7659,11 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) - u32 product_id; - - if (reset_devices) { -+ if (pqi_is_fw_triage_supported(ctrl_info)) { -+ rc = sis_wait_for_fw_triage_completion(ctrl_info); -+ if (rc) -+ return rc; -+ } - sis_soft_reset(ctrl_info); - msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ); - } else { -diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c -index d63c46a8e38bb..8acd3a80f5822 100644 ---- a/drivers/scsi/smartpqi/smartpqi_sis.c -+++ b/drivers/scsi/smartpqi/smartpqi_sis.c -@@ -51,12 +51,20 @@ - #define SIS_BASE_STRUCT_REVISION 9 - #define SIS_BASE_STRUCT_ALIGNMENT 16 - -+#define SIS_CTRL_KERNEL_FW_TRIAGE 0x3 - #define SIS_CTRL_KERNEL_UP 0x80 - #define SIS_CTRL_KERNEL_PANIC 0x100 - #define SIS_CTRL_READY_TIMEOUT_SECS 180 - #define SIS_CTRL_READY_RESUME_TIMEOUT_SECS 90 - #define SIS_CTRL_READY_POLL_INTERVAL_MSECS 10 - -+enum sis_fw_triage_status { -+ FW_TRIAGE_NOT_STARTED = 0, -+ FW_TRIAGE_STARTED, -+ FW_TRIAGE_COND_INVALID, -+ FW_TRIAGE_COMPLETED -+}; -+ - #pragma pack(1) - - /* for use with SIS_CMD_INIT_BASE_STRUCT_ADDRESS command */ -@@ -419,12 +427,55 @@ u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info) - return readl(&ctrl_info->registers->sis_driver_scratch); - } - -+static inline enum sis_fw_triage_status -+ sis_read_firmware_triage_status(struct pqi_ctrl_info *ctrl_info) -+{ -+ return ((enum sis_fw_triage_status)(readl(&ctrl_info->registers->sis_firmware_status) & -+ SIS_CTRL_KERNEL_FW_TRIAGE)); -+} -+ - void sis_soft_reset(struct pqi_ctrl_info *ctrl_info) - { - writel(SIS_SOFT_RESET, - &ctrl_info->registers->sis_host_to_ctrl_doorbell); - } - -+#define SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS 300 -+#define SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS 1 -+ -+int sis_wait_for_fw_triage_completion(struct pqi_ctrl_info *ctrl_info) -+{ -+ int rc; -+ enum sis_fw_triage_status status; -+ unsigned long timeout; -+ -+ timeout = (SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS * PQI_HZ) + jiffies; -+ while (1) { -+ status = sis_read_firmware_triage_status(ctrl_info); -+ if (status == FW_TRIAGE_COND_INVALID) { -+ dev_err(&ctrl_info->pci_dev->dev, -+ "firmware triage condition invalid\n"); -+ rc = -EINVAL; -+ break; -+ } else if (status == FW_TRIAGE_NOT_STARTED || -+ status == FW_TRIAGE_COMPLETED) { -+ rc = 0; -+ break; -+ } -+ -+ if (time_after(jiffies, timeout)) { -+ dev_err(&ctrl_info->pci_dev->dev, -+ "timed out waiting for firmware triage status\n"); -+ rc = -ETIMEDOUT; -+ break; -+ } -+ -+ ssleep(SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS); -+ } -+ -+ return rc; -+} -+ - static void __attribute__((unused)) verify_structures(void) - { - BUILD_BUG_ON(offsetof(struct sis_base_struct, -diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h -index d29c1352a826a..c1db93054c863 100644 ---- a/drivers/scsi/smartpqi/smartpqi_sis.h -+++ b/drivers/scsi/smartpqi/smartpqi_sis.h -@@ -28,5 +28,6 @@ void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value); - u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info); - void sis_soft_reset(struct pqi_ctrl_info *ctrl_info); - u32 sis_get_product_id(struct pqi_ctrl_info *ctrl_info); -+int sis_wait_for_fw_triage_completion(struct pqi_ctrl_info *ctrl_info); - - #endif /* _SMARTPQI_SIS_H */ -diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c -index 51424557810da..f725248ba57f4 100644 ---- a/drivers/scsi/ufs/ufshcd-pci.c -+++ b/drivers/scsi/ufs/ufshcd-pci.c -@@ -421,6 +421,13 @@ static int ufs_intel_lkf_init(struct ufs_hba *hba) - return err; - } - -+static int ufs_intel_adl_init(struct ufs_hba *hba) -+{ -+ hba->nop_out_timeout = 200; -+ hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; -+ return ufs_intel_common_init(hba); -+} -+ - static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = { - .name = "intel-pci", - .init = ufs_intel_common_init, -@@ -449,6 +456,15 @@ static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = { - .device_reset = ufs_intel_device_reset, - }; - -+static struct ufs_hba_variant_ops ufs_intel_adl_hba_vops = { -+ .name = "intel-pci", -+ .init = ufs_intel_adl_init, -+ .exit = ufs_intel_common_exit, -+ .link_startup_notify = ufs_intel_link_startup_notify, -+ .resume = ufs_intel_resume, -+ .device_reset = ufs_intel_device_reset, -+}; -+ - #ifdef CONFIG_PM_SLEEP - static int ufshcd_pci_restore(struct device *dev) - { -@@ -563,6 +579,8 @@ static const struct pci_device_id ufshcd_pci_tbl[] = { - { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, - { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, - { PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops }, -+ { PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, -+ { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, - { } /* terminate list */ - }; - -diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c -index 8859c13f4e091..eaeae83b999fd 100644 ---- a/drivers/scsi/ufs/ufshcd-pltfrm.c -+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c -@@ -91,7 +91,7 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) - - clki->min_freq = clkfreq[i]; - clki->max_freq = clkfreq[i+1]; -- clki->name = kstrdup(name, GFP_KERNEL); -+ clki->name = devm_kstrdup(dev, name, GFP_KERNEL); - if (!strcmp(name, "ref_clk")) - clki->keep_link_active = true; - dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz", -@@ -126,7 +126,7 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, - if (!vreg) - return -ENOMEM; - -- vreg->name = kstrdup(name, GFP_KERNEL); -+ vreg->name = devm_kstrdup(dev, name, GFP_KERNEL); - - snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name); - if (of_property_read_u32(np, prop_name, &vreg->max_uA)) { -diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c -index 41f2ff35f82b2..31adf25e57b0d 100644 ---- a/drivers/scsi/ufs/ufshcd.c -+++ b/drivers/scsi/ufs/ufshcd.c -@@ -222,8 +222,7 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba); - static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd); - static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); - static void ufshcd_hba_exit(struct ufs_hba *hba); --static int ufshcd_clear_ua_wluns(struct ufs_hba *hba); --static int ufshcd_probe_hba(struct ufs_hba *hba, bool async); -+static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params); - static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); - static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); - static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); -@@ -4073,8 +4072,6 @@ int ufshcd_link_recovery(struct ufs_hba *hba) - if (ret) - dev_err(hba->dev, "%s: link recovery failed, err %d", - __func__, ret); -- else -- ufshcd_clear_ua_wluns(hba); - - return ret; - } -@@ -5959,7 +5956,6 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) - ufshcd_release(hba); - if (ufshcd_is_clkscaling_supported(hba)) - ufshcd_clk_scaling_suspend(hba, false); -- ufshcd_clear_ua_wluns(hba); - ufshcd_rpm_put(hba); - } - -@@ -6386,9 +6382,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba) - irqreturn_t ret = IRQ_NONE; - int tag; - -- pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); -- - spin_lock_irqsave(hba->host->host_lock, flags); -+ pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); - issued = hba->outstanding_tasks & ~pending; - for_each_set_bit(tag, &issued, hba->nutmrs) { - struct request *req = hba->tmf_rqs[tag]; -@@ -6545,11 +6540,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, - err = wait_for_completion_io_timeout(&wait, - msecs_to_jiffies(TM_CMD_TIMEOUT)); - if (!err) { -- /* -- * Make sure that ufshcd_compl_tm() does not trigger a -- * use-after-free. -- */ -- req->end_io_data = NULL; - ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR); - dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n", - __func__, tm_function); -@@ -7044,6 +7034,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) - goto release; - } - -+ lrbp->cmd = NULL; - err = SUCCESS; - - release: -@@ -7875,8 +7866,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) - if (ret) - goto out; - -- ufshcd_clear_ua_wluns(hba); -- - /* Initialize devfreq after UFS device is detected */ - if (ufshcd_is_clkscaling_supported(hba)) { - memcpy(&hba->clk_scaling.saved_pwr_info.info, -@@ -7902,116 +7891,6 @@ out: - return ret; - } - --static void ufshcd_request_sense_done(struct request *rq, blk_status_t error) --{ -- if (error != BLK_STS_OK) -- pr_err("%s: REQUEST SENSE failed (%d)\n", __func__, error); -- kfree(rq->end_io_data); -- blk_put_request(rq); --} -- --static int --ufshcd_request_sense_async(struct ufs_hba *hba, struct scsi_device *sdev) --{ -- /* -- * Some UFS devices clear unit attention condition only if the sense -- * size used (UFS_SENSE_SIZE in this case) is non-zero. -- */ -- static const u8 cmd[6] = {REQUEST_SENSE, 0, 0, 0, UFS_SENSE_SIZE, 0}; -- struct scsi_request *rq; -- struct request *req; -- char *buffer; -- int ret; -- -- buffer = kzalloc(UFS_SENSE_SIZE, GFP_KERNEL); -- if (!buffer) -- return -ENOMEM; -- -- req = blk_get_request(sdev->request_queue, REQ_OP_DRV_IN, -- /*flags=*/BLK_MQ_REQ_PM); -- if (IS_ERR(req)) { -- ret = PTR_ERR(req); -- goto out_free; -- } -- -- ret = blk_rq_map_kern(sdev->request_queue, req, -- buffer, UFS_SENSE_SIZE, GFP_NOIO); -- if (ret) -- goto out_put; -- -- rq = scsi_req(req); -- rq->cmd_len = ARRAY_SIZE(cmd); -- memcpy(rq->cmd, cmd, rq->cmd_len); -- rq->retries = 3; -- req->timeout = 1 * HZ; -- req->rq_flags |= RQF_PM | RQF_QUIET; -- req->end_io_data = buffer; -- -- blk_execute_rq_nowait(/*bd_disk=*/NULL, req, /*at_head=*/true, -- ufshcd_request_sense_done); -- return 0; -- --out_put: -- blk_put_request(req); --out_free: -- kfree(buffer); -- return ret; --} -- --static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun) --{ -- struct scsi_device *sdp; -- unsigned long flags; -- int ret = 0; -- -- spin_lock_irqsave(hba->host->host_lock, flags); -- if (wlun == UFS_UPIU_UFS_DEVICE_WLUN) -- sdp = hba->sdev_ufs_device; -- else if (wlun == UFS_UPIU_RPMB_WLUN) -- sdp = hba->sdev_rpmb; -- else -- BUG(); -- if (sdp) { -- ret = scsi_device_get(sdp); -- if (!ret && !scsi_device_online(sdp)) { -- ret = -ENODEV; -- scsi_device_put(sdp); -- } -- } else { -- ret = -ENODEV; -- } -- spin_unlock_irqrestore(hba->host->host_lock, flags); -- if (ret) -- goto out_err; -- -- ret = ufshcd_request_sense_async(hba, sdp); -- scsi_device_put(sdp); --out_err: -- if (ret) -- dev_err(hba->dev, "%s: UAC clear LU=%x ret = %d\n", -- __func__, wlun, ret); -- return ret; --} -- --static int ufshcd_clear_ua_wluns(struct ufs_hba *hba) --{ -- int ret = 0; -- -- if (!hba->wlun_dev_clr_ua) -- goto out; -- -- ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN); -- if (!ret) -- ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN); -- if (!ret) -- hba->wlun_dev_clr_ua = false; --out: -- if (ret) -- dev_err(hba->dev, "%s: Failed to clear UAC WLUNS ret = %d\n", -- __func__, ret); -- return ret; --} -- - /** - * ufshcd_probe_hba - probe hba to detect device and initialize it - * @hba: per-adapter instance -@@ -8062,8 +7941,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params) - /* UFS device is also active now */ - ufshcd_set_ufs_dev_active(hba); - ufshcd_force_reset_auto_bkops(hba); -- hba->wlun_dev_clr_ua = true; -- hba->wlun_rpmb_clr_ua = true; - - /* Gear up to HS gear if supported */ - if (hba->max_pwr_info.is_valid) { -@@ -8600,7 +8477,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, - struct scsi_sense_hdr sshdr; - struct scsi_device *sdp; - unsigned long flags; -- int ret; -+ int ret, retries; - - spin_lock_irqsave(hba->host->host_lock, flags); - sdp = hba->sdev_ufs_device; -@@ -8625,8 +8502,6 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, - * handling context. - */ - hba->host->eh_noresume = 1; -- if (hba->wlun_dev_clr_ua) -- ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN); - - cmd[4] = pwr_mode << 4; - -@@ -8635,8 +8510,14 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, - * callbacks hence set the RQF_PM flag so that it doesn't resume the - * already suspended childs. - */ -- ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, -- START_STOP_TIMEOUT, 0, 0, RQF_PM, NULL); -+ for (retries = 3; retries > 0; --retries) { -+ ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, -+ START_STOP_TIMEOUT, 0, 0, RQF_PM, NULL); -+ if (!scsi_status_is_check_condition(ret) || -+ !scsi_sense_valid(&sshdr) || -+ sshdr.sense_key != UNIT_ATTENTION) -+ break; -+ } - if (ret) { - sdev_printk(KERN_WARNING, sdp, - "START_STOP failed for power mode: %d, result %x\n", -@@ -9699,10 +9580,6 @@ void ufshcd_resume_complete(struct device *dev) - ufshcd_rpm_put(hba); - hba->complete_put = false; - } -- if (hba->rpmb_complete_put) { -- ufshcd_rpmb_rpm_put(hba); -- hba->rpmb_complete_put = false; -- } - } - EXPORT_SYMBOL_GPL(ufshcd_resume_complete); - -@@ -9725,10 +9602,6 @@ int ufshcd_suspend_prepare(struct device *dev) - } - hba->complete_put = true; - } -- if (hba->sdev_rpmb) { -- ufshcd_rpmb_rpm_get_sync(hba); -- hba->rpmb_complete_put = true; -- } - return 0; - } - EXPORT_SYMBOL_GPL(ufshcd_suspend_prepare); -@@ -9797,49 +9670,6 @@ static struct scsi_driver ufs_dev_wlun_template = { - }, - }; - --static int ufshcd_rpmb_probe(struct device *dev) --{ -- return is_rpmb_wlun(to_scsi_device(dev)) ? 0 : -ENODEV; --} -- --static inline int ufshcd_clear_rpmb_uac(struct ufs_hba *hba) --{ -- int ret = 0; -- -- if (!hba->wlun_rpmb_clr_ua) -- return 0; -- ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN); -- if (!ret) -- hba->wlun_rpmb_clr_ua = 0; -- return ret; --} -- --#ifdef CONFIG_PM --static int ufshcd_rpmb_resume(struct device *dev) --{ -- struct ufs_hba *hba = wlun_dev_to_hba(dev); -- -- if (hba->sdev_rpmb) -- ufshcd_clear_rpmb_uac(hba); -- return 0; --} --#endif -- --static const struct dev_pm_ops ufs_rpmb_pm_ops = { -- SET_RUNTIME_PM_OPS(NULL, ufshcd_rpmb_resume, NULL) -- SET_SYSTEM_SLEEP_PM_OPS(NULL, ufshcd_rpmb_resume) --}; -- --/* ufs_rpmb_wlun_template - Describes UFS RPMB WLUN. Used only to send UAC. */ --static struct scsi_driver ufs_rpmb_wlun_template = { -- .gendrv = { -- .name = "ufs_rpmb_wlun", -- .owner = THIS_MODULE, -- .probe = ufshcd_rpmb_probe, -- .pm = &ufs_rpmb_pm_ops, -- }, --}; -- - static int __init ufshcd_core_init(void) - { - int ret; -@@ -9848,24 +9678,13 @@ static int __init ufshcd_core_init(void) - - ret = scsi_register_driver(&ufs_dev_wlun_template.gendrv); - if (ret) -- goto debugfs_exit; -- -- ret = scsi_register_driver(&ufs_rpmb_wlun_template.gendrv); -- if (ret) -- goto unregister; -- -- return ret; --unregister: -- scsi_unregister_driver(&ufs_dev_wlun_template.gendrv); --debugfs_exit: -- ufs_debugfs_exit(); -+ ufs_debugfs_exit(); - return ret; - } - - static void __exit ufshcd_core_exit(void) - { - ufs_debugfs_exit(); -- scsi_unregister_driver(&ufs_rpmb_wlun_template.gendrv); - scsi_unregister_driver(&ufs_dev_wlun_template.gendrv); - } - -diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h -index 41f6e06f91856..07ada6676c3b4 100644 ---- a/drivers/scsi/ufs/ufshcd.h -+++ b/drivers/scsi/ufs/ufshcd.h -@@ -871,9 +871,6 @@ struct ufs_hba { - struct ufs_vreg_info vreg_info; - struct list_head clk_list_head; - -- bool wlun_dev_clr_ua; -- bool wlun_rpmb_clr_ua; -- - /* Number of requests aborts */ - int req_abort_count; - -@@ -920,7 +917,6 @@ struct ufs_hba { - #endif - u32 luns_avail; - bool complete_put; -- bool rpmb_complete_put; - }; - - /* Returns true if clocks can be gated. Otherwise false */ -@@ -1393,14 +1389,4 @@ static inline int ufshcd_rpm_put(struct ufs_hba *hba) - return pm_runtime_put(&hba->sdev_ufs_device->sdev_gendev); - } - --static inline int ufshcd_rpmb_rpm_get_sync(struct ufs_hba *hba) --{ -- return pm_runtime_get_sync(&hba->sdev_rpmb->sdev_gendev); --} -- --static inline int ufshcd_rpmb_rpm_put(struct ufs_hba *hba) --{ -- return pm_runtime_put(&hba->sdev_rpmb->sdev_gendev); --} -- - #endif /* End of Header */ -diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c -index 026a133149dce..a86d0cc50de21 100644 ---- a/drivers/scsi/ufs/ufshpb.c -+++ b/drivers/scsi/ufs/ufshpb.c -@@ -394,8 +394,6 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) - if (!ufshpb_is_supported_chunk(hpb, transfer_len)) - return 0; - -- WARN_ON_ONCE(transfer_len > HPB_MULTI_CHUNK_HIGH); -- - if (hpb->is_hcm) { - /* - * in host control mode, reads are the main source for -@@ -1572,7 +1570,7 @@ static void ufshpb_lu_parameter_init(struct ufs_hba *hba, - if (ufshpb_is_legacy(hba)) - hpb->pre_req_max_tr_len = HPB_LEGACY_CHUNK_HIGH; - else -- hpb->pre_req_max_tr_len = HPB_MULTI_CHUNK_HIGH; -+ hpb->pre_req_max_tr_len = hpb_dev_info->max_hpb_single_cmd; - - hpb->lu_pinned_start = hpb_lu_info->pinned_start; - hpb->lu_pinned_end = hpb_lu_info->num_pinned ? -@@ -2371,11 +2369,11 @@ static int ufshpb_get_lu_info(struct ufs_hba *hba, int lun, - - ufshcd_map_desc_id_to_length(hba, QUERY_DESC_IDN_UNIT, &size); - -- pm_runtime_get_sync(hba->dev); -+ ufshcd_rpm_get_sync(hba); - ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, - QUERY_DESC_IDN_UNIT, lun, 0, - desc_buf, &size); -- pm_runtime_put_sync(hba->dev); -+ ufshcd_rpm_put_sync(hba); - - if (ret) { - dev_err(hba->dev, -@@ -2582,7 +2580,7 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf) - { - struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev; - int version, ret; -- u32 max_hpb_single_cmd = HPB_MULTI_CHUNK_LOW; -+ int max_single_cmd; - - hpb_dev_info->control_mode = desc_buf[DEVICE_DESC_PARAM_HPB_CONTROL]; - -@@ -2598,21 +2596,22 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf) - if (version == HPB_SUPPORT_LEGACY_VERSION) - hpb_dev_info->is_legacy = true; - -- pm_runtime_get_sync(hba->dev); -- ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, -- QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_hpb_single_cmd); -- pm_runtime_put_sync(hba->dev); -- -- if (ret) -- dev_err(hba->dev, "%s: idn: read max size of single hpb cmd query request failed", -- __func__); -- hpb_dev_info->max_hpb_single_cmd = max_hpb_single_cmd; -- - /* - * Get the number of user logical unit to check whether all - * scsi_device finish initialization - */ - hpb_dev_info->num_lu = desc_buf[DEVICE_DESC_PARAM_NUM_LU]; -+ -+ if (hpb_dev_info->is_legacy) -+ return; -+ -+ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, -+ QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_single_cmd); -+ -+ if (ret) -+ hpb_dev_info->max_hpb_single_cmd = HPB_LEGACY_CHUNK_HIGH; -+ else -+ hpb_dev_info->max_hpb_single_cmd = min(max_single_cmd + 1, HPB_MULTI_CHUNK_HIGH); - } - - void ufshpb_init(struct ufs_hba *hba) -diff --git a/drivers/scsi/ufs/ufshpb.h b/drivers/scsi/ufs/ufshpb.h -index f15d8fdbce2ef..b475dbd789883 100644 ---- a/drivers/scsi/ufs/ufshpb.h -+++ b/drivers/scsi/ufs/ufshpb.h -@@ -31,7 +31,6 @@ - - /* hpb support chunk size */ - #define HPB_LEGACY_CHUNK_HIGH 1 --#define HPB_MULTI_CHUNK_LOW 7 - #define HPB_MULTI_CHUNK_HIGH 255 - - /* hpb vender defined opcode */ -diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c -index bd0fbcdbdefe9..e24e220e56eea 100644 ---- a/drivers/sh/maple/maple.c -+++ b/drivers/sh/maple/maple.c -@@ -834,8 +834,10 @@ static int __init maple_bus_init(void) - - maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN); - -- if (!maple_queue_cache) -+ if (!maple_queue_cache) { -+ retval = -ENOMEM; - goto cleanup_bothirqs; -+ } - - INIT_LIST_HEAD(&maple_waitq); - INIT_LIST_HEAD(&maple_sentq); -@@ -848,6 +850,7 @@ static int __init maple_bus_init(void) - if (!mdev[i]) { - while (i-- > 0) - maple_free_dev(mdev[i]); -+ retval = -ENOMEM; - goto cleanup_cache; - } - baseunits[i] = mdev[i]; -diff --git a/drivers/soc/fsl/dpaa2-console.c b/drivers/soc/fsl/dpaa2-console.c -index 27243f706f376..53917410f2bdb 100644 ---- a/drivers/soc/fsl/dpaa2-console.c -+++ b/drivers/soc/fsl/dpaa2-console.c -@@ -231,6 +231,7 @@ static ssize_t dpaa2_console_read(struct file *fp, char __user *buf, - cd->cur_ptr += bytes; - written += bytes; - -+ kfree(kbuf); - return written; - - err_free_buf: -diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c -index 7351f30305506..779c319a4b820 100644 ---- a/drivers/soc/fsl/dpio/dpio-service.c -+++ b/drivers/soc/fsl/dpio/dpio-service.c -@@ -59,7 +59,7 @@ static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d, - * potentially being migrated away. - */ - if (cpu < 0) -- cpu = smp_processor_id(); -+ cpu = raw_smp_processor_id(); - - /* If a specific cpu was requested, pick it up immediately */ - return dpio_by_cpu[cpu]; -diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c -index f13da4d7d1c52..3ec8ab08b9889 100644 ---- a/drivers/soc/fsl/dpio/qbman-portal.c -+++ b/drivers/soc/fsl/dpio/qbman-portal.c -@@ -732,8 +732,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, - int i, num_enqueued = 0; - unsigned long irq_flags; - -- spin_lock(&s->access_spinlock); -- local_irq_save(irq_flags); -+ spin_lock_irqsave(&s->access_spinlock, irq_flags); - - half_mask = (s->eqcr.pi_ci_mask>>1); - full_mask = s->eqcr.pi_ci_mask; -@@ -744,8 +743,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, - s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, - eqcr_ci, s->eqcr.ci); - if (!s->eqcr.available) { -- local_irq_restore(irq_flags); -- spin_unlock(&s->access_spinlock); -+ spin_unlock_irqrestore(&s->access_spinlock, irq_flags); - return 0; - } - } -@@ -784,8 +782,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, - dma_wmb(); - qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI, - (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb); -- local_irq_restore(irq_flags); -- spin_unlock(&s->access_spinlock); -+ spin_unlock_irqrestore(&s->access_spinlock, irq_flags); - - return num_enqueued; - } -diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c -index 34a9ac1f2b9b1..8b7a01773aec2 100644 ---- a/drivers/soc/imx/gpcv2.c -+++ b/drivers/soc/imx/gpcv2.c -@@ -244,6 +244,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) - goto out_regulator_disable; - } - -+ reset_control_assert(domain->reset); -+ - if (domain->bits.pxx) { - /* request the domain to power up */ - regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ, -@@ -266,8 +268,6 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) - GPC_PGC_CTRL_PCR); - } - -- reset_control_assert(domain->reset); -- - /* delay for reset to propagate */ - udelay(5); - -diff --git a/drivers/soc/imx/soc-imx.c b/drivers/soc/imx/soc-imx.c -index ac6d856ba228d..77bc12039c3d4 100644 ---- a/drivers/soc/imx/soc-imx.c -+++ b/drivers/soc/imx/soc-imx.c -@@ -36,6 +36,10 @@ static int __init imx_soc_device_init(void) - int ret; - int i; - -+ /* Return early if this is running on devices with different SoCs */ -+ if (!__mxc_cpu_type) -+ return 0; -+ - if (of_machine_is_compatible("fsl,ls1021a")) - return 0; - -diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c -index 475a57b435b24..2e455d9e3d94a 100644 ---- a/drivers/soc/qcom/apr.c -+++ b/drivers/soc/qcom/apr.c -@@ -321,12 +321,14 @@ static int of_apr_add_pd_lookups(struct device *dev) - 1, &service_path); - if (ret < 0) { - dev_err(dev, "pdr service path missing: %d\n", ret); -+ of_node_put(node); - return ret; - } - - pds = pdr_add_lookup(apr->pdr, service_name, service_path); - if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) { - dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds)); -+ of_node_put(node); - return PTR_ERR(pds); - } - } -diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c -index 15a36dcab990e..e53109a5c3da9 100644 ---- a/drivers/soc/qcom/llcc-qcom.c -+++ b/drivers/soc/qcom/llcc-qcom.c -@@ -115,7 +115,7 @@ static const struct llcc_slice_config sc7280_data[] = { - { LLCC_CMPT, 10, 768, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_GPUHTW, 11, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_GPU, 12, 512, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, -- { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 1, 0}, -+ { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 0, 1, 0}, - { LLCC_MDMPNG, 21, 768, 0, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_WLHW, 24, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, - { LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, -diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c -index fa209b479ab35..d98cc8c2e5d5c 100644 ---- a/drivers/soc/qcom/rpmhpd.c -+++ b/drivers/soc/qcom/rpmhpd.c -@@ -30,6 +30,7 @@ - * @active_only: True if it represents an Active only peer - * @corner: current corner - * @active_corner: current active corner -+ * @enable_corner: lowest non-zero corner - * @level: An array of level (vlvl) to corner (hlvl) mappings - * derived from cmd-db - * @level_count: Number of levels supported by the power domain. max -@@ -47,6 +48,7 @@ struct rpmhpd { - const bool active_only; - unsigned int corner; - unsigned int active_corner; -+ unsigned int enable_corner; - u32 level[RPMH_ARC_MAX_LEVELS]; - size_t level_count; - bool enabled; -@@ -204,7 +206,7 @@ static const struct rpmhpd_desc sm8250_desc = { - static struct rpmhpd sm8350_mxc_ao; - static struct rpmhpd sm8350_mxc = { - .pd = { .name = "mxc", }, -- .peer = &sm8150_mmcx_ao, -+ .peer = &sm8350_mxc_ao, - .res_name = "mxc.lvl", - }; - -@@ -385,13 +387,13 @@ static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner) - static int rpmhpd_power_on(struct generic_pm_domain *domain) - { - struct rpmhpd *pd = domain_to_rpmhpd(domain); -- int ret = 0; -+ unsigned int corner; -+ int ret; - - mutex_lock(&rpmhpd_lock); - -- if (pd->corner) -- ret = rpmhpd_aggregate_corner(pd, pd->corner); -- -+ corner = max(pd->corner, pd->enable_corner); -+ ret = rpmhpd_aggregate_corner(pd, corner); - if (!ret) - pd->enabled = true; - -@@ -436,6 +438,10 @@ static int rpmhpd_set_performance_state(struct generic_pm_domain *domain, - i--; - - if (pd->enabled) { -+ /* Ensure that the domain isn't turn off */ -+ if (i < pd->enable_corner) -+ i = pd->enable_corner; -+ - ret = rpmhpd_aggregate_corner(pd, i); - if (ret) - goto out; -@@ -472,6 +478,10 @@ static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd) - for (i = 0; i < rpmhpd->level_count; i++) { - rpmhpd->level[i] = buf[i]; - -+ /* Remember the first corner with non-zero level */ -+ if (!rpmhpd->level[rpmhpd->enable_corner] && rpmhpd->level[i]) -+ rpmhpd->enable_corner = i; -+ - /* - * The AUX data may be zero padded. These 0 valued entries at - * the end of the map must be ignored. -diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c -index 52e5811671155..5beb452f24013 100644 ---- a/drivers/soc/qcom/socinfo.c -+++ b/drivers/soc/qcom/socinfo.c -@@ -87,8 +87,8 @@ static const char *const pmic_models[] = { - [15] = "PM8901", - [16] = "PM8950/PM8027", - [17] = "PMI8950/ISL9519", -- [18] = "PM8921", -- [19] = "PM8018", -+ [18] = "PMK8001/PM8921", -+ [19] = "PMI8996/PM8018", - [20] = "PM8998/PM8015", - [21] = "PMI8998/PM8014", - [22] = "PM8821", -diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig -index 5745d7e5908e9..1f643c0f5c93f 100644 ---- a/drivers/soc/samsung/Kconfig -+++ b/drivers/soc/samsung/Kconfig -@@ -25,6 +25,7 @@ config EXYNOS_PMU - bool "Exynos PMU controller driver" if COMPILE_TEST - depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST) - select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS -+ select MFD_CORE - - # There is no need to enable these drivers for ARMv8 - config EXYNOS_PMU_ARM_DRIVERS -diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c -index f2151815db585..e714ed3b61bc3 100644 ---- a/drivers/soc/tegra/fuse/fuse-tegra.c -+++ b/drivers/soc/tegra/fuse/fuse-tegra.c -@@ -320,7 +320,7 @@ static struct platform_driver tegra_fuse_driver = { - }; - builtin_platform_driver(tegra_fuse_driver); - --bool __init tegra_fuse_read_spare(unsigned int spare) -+u32 __init tegra_fuse_read_spare(unsigned int spare) - { - unsigned int offset = fuse->soc->info->spare + spare * 4; - -diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h -index de58feba04350..ecff0c08e9595 100644 ---- a/drivers/soc/tegra/fuse/fuse.h -+++ b/drivers/soc/tegra/fuse/fuse.h -@@ -65,7 +65,7 @@ struct tegra_fuse { - void tegra_init_revision(void); - void tegra_init_apbmisc(void); - --bool __init tegra_fuse_read_spare(unsigned int spare); -+u32 __init tegra_fuse_read_spare(unsigned int spare); - u32 __init tegra_fuse_read_early(unsigned int offset); - - u8 tegra_get_major_rev(void); -diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c -index 50091c4ec9481..a60e142ade344 100644 ---- a/drivers/soc/tegra/pmc.c -+++ b/drivers/soc/tegra/pmc.c -@@ -782,7 +782,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, - - err = reset_control_deassert(pg->reset); - if (err) -- goto powergate_off; -+ goto disable_clks; - - usleep_range(10, 20); - -diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c -index 1b115734a8f6b..67369e941d0d6 100644 ---- a/drivers/soundwire/bus.c -+++ b/drivers/soundwire/bus.c -@@ -1110,7 +1110,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) - if (!simple_clk_stop) { - ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); - if (ret < 0) -- dev_warn(&slave->dev, "clock stop deprepare wait failed:%d\n", ret); -+ dev_warn(bus->dev, "clock stop deprepare wait failed:%d\n", ret); - } - - list_for_each_entry(slave, &bus->slaves, node) { -diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c -index b6cad0d59b7b9..49900cd207bc7 100644 ---- a/drivers/soundwire/debugfs.c -+++ b/drivers/soundwire/debugfs.c -@@ -19,7 +19,7 @@ void sdw_bus_debugfs_init(struct sdw_bus *bus) - return; - - /* create the debugfs master-N */ -- snprintf(name, sizeof(name), "master-%d", bus->link_id); -+ snprintf(name, sizeof(name), "master-%d-%d", bus->id, bus->link_id); - bus->debugfs = debugfs_create_dir(name, sdw_debugfs_root); - } - -diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c -index 95d4fa32c2995..92d9610df1fd8 100644 ---- a/drivers/spi/atmel-quadspi.c -+++ b/drivers/spi/atmel-quadspi.c -@@ -310,7 +310,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, - return mode; - ifr |= atmel_qspi_modes[mode].config; - -- if (op->dummy.buswidth && op->dummy.nbytes) -+ if (op->dummy.nbytes) - dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth; - - /* -diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c -index 3043677ba2226..151e154284bde 100644 ---- a/drivers/spi/spi-bcm-qspi.c -+++ b/drivers/spi/spi-bcm-qspi.c -@@ -395,7 +395,8 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, - if (addrlen == BSPI_ADDRLEN_4BYTES) - bpp = BSPI_BPP_ADDR_SELECT_MASK; - -- bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth; -+ if (op->dummy.nbytes) -+ bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth; - - switch (width) { - case SPI_NBITS_SINGLE: -@@ -1460,7 +1461,7 @@ int bcm_qspi_probe(struct platform_device *pdev, - &qspi->dev_ids[val]); - if (ret < 0) { - dev_err(&pdev->dev, "IRQ %s not found\n", name); -- goto qspi_probe_err; -+ goto qspi_unprepare_err; - } - - qspi->dev_ids[val].dev = qspi; -@@ -1475,7 +1476,7 @@ int bcm_qspi_probe(struct platform_device *pdev, - if (!num_ints) { - dev_err(&pdev->dev, "no IRQs registered, cannot init driver\n"); - ret = -EINVAL; -- goto qspi_probe_err; -+ goto qspi_unprepare_err; - } - - bcm_qspi_hw_init(qspi); -@@ -1499,6 +1500,7 @@ int bcm_qspi_probe(struct platform_device *pdev, - - qspi_reg_err: - bcm_qspi_hw_uninit(qspi); -+qspi_unprepare_err: - clk_disable_unprepare(qspi->clk); - qspi_probe_err: - kfree(qspi->dev_ids); -diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c -index 41e7b341d2616..5c93730615f8d 100644 ---- a/drivers/spi/spi-mtk-nor.c -+++ b/drivers/spi/spi-mtk-nor.c -@@ -160,7 +160,7 @@ static bool mtk_nor_match_read(const struct spi_mem_op *op) - { - int dummy = 0; - -- if (op->dummy.buswidth) -+ if (op->dummy.nbytes) - dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth; - - if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) { -diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c -index c53138ce00309..83796a4ead34a 100644 ---- a/drivers/spi/spi-rpc-if.c -+++ b/drivers/spi/spi-rpc-if.c -@@ -139,7 +139,9 @@ static int rpcif_spi_probe(struct platform_device *pdev) - return -ENOMEM; - - rpc = spi_controller_get_devdata(ctlr); -- rpcif_sw_init(rpc, parent); -+ error = rpcif_sw_init(rpc, parent); -+ if (error) -+ return error; - - platform_set_drvdata(pdev, ctlr); - -diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c -index 27f35aa2d746d..514337c86d2c3 100644 ---- a/drivers/spi/spi-stm32-qspi.c -+++ b/drivers/spi/spi-stm32-qspi.c -@@ -397,7 +397,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) - ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1); - } - -- if (op->dummy.buswidth && op->dummy.nbytes) -+ if (op->dummy.nbytes) - ccr |= FIELD_PREP(CCR_DCYC_MASK, - op->dummy.nbytes * 8 / op->dummy.buswidth); - -diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c -index 926b68aa45d3e..97b5a811bd7f7 100644 ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -451,6 +451,47 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) - { - sdrv->driver.owner = owner; - sdrv->driver.bus = &spi_bus_type; -+ -+ /* -+ * For Really Good Reasons we use spi: modaliases not of: -+ * modaliases for DT so module autoloading won't work if we -+ * don't have a spi_device_id as well as a compatible string. -+ */ -+ if (sdrv->driver.of_match_table) { -+ const struct of_device_id *of_id; -+ -+ for (of_id = sdrv->driver.of_match_table; of_id->compatible[0]; -+ of_id++) { -+ const char *of_name; -+ -+ /* Strip off any vendor prefix */ -+ of_name = strnchr(of_id->compatible, -+ sizeof(of_id->compatible), ','); -+ if (of_name) -+ of_name++; -+ else -+ of_name = of_id->compatible; -+ -+ if (sdrv->id_table) { -+ const struct spi_device_id *spi_id; -+ -+ for (spi_id = sdrv->id_table; spi_id->name[0]; -+ spi_id++) -+ if (strcmp(spi_id->name, of_name) == 0) -+ break; -+ -+ if (spi_id->name[0]) -+ continue; -+ } else { -+ if (strcmp(sdrv->driver.name, of_name) == 0) -+ continue; -+ } -+ -+ pr_warn("SPI driver %s has no spi_device_id for %s\n", -+ sdrv->driver.name, of_id->compatible); -+ } -+ } -+ - return driver_register(&sdrv->driver); - } - EXPORT_SYMBOL_GPL(__spi_register_driver); -@@ -2979,12 +3020,6 @@ void spi_unregister_controller(struct spi_controller *ctlr) - - device_del(&ctlr->dev); - -- /* Release the last reference on the controller if its driver -- * has not yet been converted to devm_spi_alloc_master/slave(). -- */ -- if (!ctlr->devm_allocated) -- put_device(&ctlr->dev); -- - /* free bus id */ - mutex_lock(&board_lock); - if (found == ctlr) -@@ -2993,6 +3028,12 @@ void spi_unregister_controller(struct spi_controller *ctlr) - - if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) - mutex_unlock(&ctlr->add_lock); -+ -+ /* Release the last reference on the controller if its driver -+ * has not yet been converted to devm_spi_alloc_master/slave(). -+ */ -+ if (!ctlr->devm_allocated) -+ put_device(&ctlr->dev); - } - EXPORT_SYMBOL_GPL(spi_unregister_controller); - -diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c -index cf263a58a1489..6fd549a424d53 100644 ---- a/drivers/staging/fbtft/fb_ssd1351.c -+++ b/drivers/staging/fbtft/fb_ssd1351.c -@@ -187,7 +187,6 @@ static struct fbtft_display display = { - }, - }; - --#ifdef CONFIG_FB_BACKLIGHT - static int update_onboard_backlight(struct backlight_device *bd) - { - struct fbtft_par *par = bl_get_data(bd); -@@ -231,9 +230,6 @@ static void register_onboard_backlight(struct fbtft_par *par) - if (!par->fbtftops.unregister_backlight) - par->fbtftops.unregister_backlight = fbtft_unregister_backlight; - } --#else --static void register_onboard_backlight(struct fbtft_par *par) { }; --#endif - - FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1351", &display); - -diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c -index ed992ca605ebe..1690358b8f018 100644 ---- a/drivers/staging/fbtft/fbtft-core.c -+++ b/drivers/staging/fbtft/fbtft-core.c -@@ -128,7 +128,6 @@ static int fbtft_request_gpios(struct fbtft_par *par) - return 0; - } - --#ifdef CONFIG_FB_BACKLIGHT - static int fbtft_backlight_update_status(struct backlight_device *bd) - { - struct fbtft_par *par = bl_get_data(bd); -@@ -161,6 +160,7 @@ void fbtft_unregister_backlight(struct fbtft_par *par) - par->info->bl_dev = NULL; - } - } -+EXPORT_SYMBOL(fbtft_unregister_backlight); - - static const struct backlight_ops fbtft_bl_ops = { - .get_brightness = fbtft_backlight_get_brightness, -@@ -198,12 +198,7 @@ void fbtft_register_backlight(struct fbtft_par *par) - if (!par->fbtftops.unregister_backlight) - par->fbtftops.unregister_backlight = fbtft_unregister_backlight; - } --#else --void fbtft_register_backlight(struct fbtft_par *par) { }; --void fbtft_unregister_backlight(struct fbtft_par *par) { }; --#endif - EXPORT_SYMBOL(fbtft_register_backlight); --EXPORT_SYMBOL(fbtft_unregister_backlight); - - static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, - int ye) -@@ -853,13 +848,11 @@ int fbtft_register_framebuffer(struct fb_info *fb_info) - fb_info->fix.smem_len >> 10, text1, - HZ / fb_info->fbdefio->delay, text2); - --#ifdef CONFIG_FB_BACKLIGHT - /* Turn on backlight if available */ - if (fb_info->bl_dev) { - fb_info->bl_dev->props.power = FB_BLANK_UNBLANK; - fb_info->bl_dev->ops->update_status(fb_info->bl_dev); - } --#endif - - return 0; - -diff --git a/drivers/staging/greybus/audio_helper.c b/drivers/staging/greybus/audio_helper.c -index 1ed4772d27715..843760675876a 100644 ---- a/drivers/staging/greybus/audio_helper.c -+++ b/drivers/staging/greybus/audio_helper.c -@@ -192,7 +192,11 @@ int gbaudio_remove_component_controls(struct snd_soc_component *component, - unsigned int num_controls) - { - struct snd_card *card = component->card->snd_card; -+ int err; - -- return gbaudio_remove_controls(card, component->dev, controls, -- num_controls, component->name_prefix); -+ down_write(&card->controls_rwsem); -+ err = gbaudio_remove_controls(card, component->dev, controls, -+ num_controls, component->name_prefix); -+ up_write(&card->controls_rwsem); -+ return err; - } -diff --git a/drivers/staging/ks7010/Kconfig b/drivers/staging/ks7010/Kconfig -index 0987fdc2f70db..8ea6c09286798 100644 ---- a/drivers/staging/ks7010/Kconfig -+++ b/drivers/staging/ks7010/Kconfig -@@ -5,6 +5,9 @@ config KS7010 - select WIRELESS_EXT - select WEXT_PRIV - select FW_LOADER -+ select CRYPTO -+ select CRYPTO_HASH -+ select CRYPTO_MICHAEL_MIC - help - This is a driver for KeyStream KS7010 based SDIO WIFI cards. It is - found on at least later Spectec SDW-821 (FCC-ID "S2Y-WLAN-11G-K" only, -diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c -index 362ed44b4effa..e046489cd253b 100644 ---- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c -+++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c -@@ -835,7 +835,6 @@ static int lm3554_probe(struct i2c_client *client) - int err = 0; - struct lm3554 *flash; - unsigned int i; -- int ret; - - flash = kzalloc(sizeof(*flash), GFP_KERNEL); - if (!flash) -@@ -844,7 +843,7 @@ static int lm3554_probe(struct i2c_client *client) - flash->pdata = lm3554_platform_data_func(client); - if (IS_ERR(flash->pdata)) { - err = PTR_ERR(flash->pdata); -- goto fail1; -+ goto free_flash; - } - - v4l2_i2c_subdev_init(&flash->sd, client, &lm3554_ops); -@@ -852,12 +851,12 @@ static int lm3554_probe(struct i2c_client *client) - flash->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - flash->mode = ATOMISP_FLASH_MODE_OFF; - flash->timeout = LM3554_MAX_TIMEOUT / LM3554_TIMEOUT_STEPSIZE - 1; -- ret = -+ err = - v4l2_ctrl_handler_init(&flash->ctrl_handler, - ARRAY_SIZE(lm3554_controls)); -- if (ret) { -+ if (err) { - dev_err(&client->dev, "error initialize a ctrl_handler.\n"); -- goto fail3; -+ goto unregister_subdev; - } - - for (i = 0; i < ARRAY_SIZE(lm3554_controls); i++) -@@ -866,14 +865,15 @@ static int lm3554_probe(struct i2c_client *client) - - if (flash->ctrl_handler.error) { - dev_err(&client->dev, "ctrl_handler error.\n"); -- goto fail3; -+ err = flash->ctrl_handler.error; -+ goto free_handler; - } - - flash->sd.ctrl_handler = &flash->ctrl_handler; - err = media_entity_pads_init(&flash->sd.entity, 0, NULL); - if (err) { - dev_err(&client->dev, "error initialize a media entity.\n"); -- goto fail2; -+ goto free_handler; - } - - flash->sd.entity.function = MEDIA_ENT_F_FLASH; -@@ -884,16 +884,27 @@ static int lm3554_probe(struct i2c_client *client) - - err = lm3554_gpio_init(client); - if (err) { -- dev_err(&client->dev, "gpio request/direction_output fail"); -- goto fail3; -+ dev_err(&client->dev, "gpio request/direction_output fail.\n"); -+ goto cleanup_media; -+ } -+ -+ err = atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH); -+ if (err) { -+ dev_err(&client->dev, "fail to register atomisp i2c module.\n"); -+ goto uninit_gpio; - } -- return atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH); --fail3: -+ -+ return 0; -+ -+uninit_gpio: -+ lm3554_gpio_uninit(client); -+cleanup_media: - media_entity_cleanup(&flash->sd.entity); -+free_handler: - v4l2_ctrl_handler_free(&flash->ctrl_handler); --fail2: -+unregister_subdev: - v4l2_device_unregister_subdev(&flash->sd); --fail1: -+free_flash: - kfree(flash); - - return err; -diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c -index d186179388d03..4d873726a461b 100644 ---- a/drivers/staging/media/imx/imx-media-dev-common.c -+++ b/drivers/staging/media/imx/imx-media-dev-common.c -@@ -367,6 +367,8 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev, - imxmd->v4l2_dev.notify = imx_media_notify; - strscpy(imxmd->v4l2_dev.name, "imx-media", - sizeof(imxmd->v4l2_dev.name)); -+ snprintf(imxmd->md.bus_info, sizeof(imxmd->md.bus_info), -+ "platform:%s", dev_name(imxmd->md.dev)); - - media_device_init(&imxmd->md); - -diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.c b/drivers/staging/media/ipu3/ipu3-css-fw.c -index 45aff76198e2c..981693eed8155 100644 ---- a/drivers/staging/media/ipu3/ipu3-css-fw.c -+++ b/drivers/staging/media/ipu3/ipu3-css-fw.c -@@ -124,12 +124,11 @@ int imgu_css_fw_init(struct imgu_css *css) - /* Check and display fw header info */ - - css->fwp = (struct imgu_fw_header *)css->fw->data; -- if (css->fw->size < sizeof(struct imgu_fw_header *) || -+ if (css->fw->size < struct_size(css->fwp, binary_header, 1) || - css->fwp->file_header.h_size != sizeof(struct imgu_fw_bi_file_h)) - goto bad_fw; -- if (sizeof(struct imgu_fw_bi_file_h) + -- css->fwp->file_header.binary_nr * sizeof(struct imgu_fw_info) > -- css->fw->size) -+ if (struct_size(css->fwp, binary_header, -+ css->fwp->file_header.binary_nr) > css->fw->size) - goto bad_fw; - - dev_info(dev, "loaded firmware version %.64s, %u binaries, %zu bytes\n", -diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.h b/drivers/staging/media/ipu3/ipu3-css-fw.h -index 3c078f15a2959..c0bc57fd678a7 100644 ---- a/drivers/staging/media/ipu3/ipu3-css-fw.h -+++ b/drivers/staging/media/ipu3/ipu3-css-fw.h -@@ -171,7 +171,7 @@ struct imgu_fw_bi_file_h { - - struct imgu_fw_header { - struct imgu_fw_bi_file_h file_header; -- struct imgu_fw_info binary_header[1]; /* binary_nr items */ -+ struct imgu_fw_info binary_header[]; /* binary_nr items */ - }; - - /******************* Firmware functions *******************/ -diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c -index 38a2407645096..90c86ba5040e3 100644 ---- a/drivers/staging/media/ipu3/ipu3-v4l2.c -+++ b/drivers/staging/media/ipu3/ipu3-v4l2.c -@@ -592,11 +592,12 @@ static const struct imgu_fmt *find_format(struct v4l2_format *f, u32 type) - static int imgu_vidioc_querycap(struct file *file, void *fh, - struct v4l2_capability *cap) - { -- struct imgu_video_device *node = file_to_intel_imgu_node(file); -+ struct imgu_device *imgu = video_drvdata(file); - - strscpy(cap->driver, IMGU_NAME, sizeof(cap->driver)); - strscpy(cap->card, IMGU_NAME, sizeof(cap->card)); -- snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", node->name); -+ snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", -+ pci_name(imgu->pci_dev)); - - return 0; - } -@@ -696,7 +697,7 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, - - /* CSS expects some format on OUT queue */ - if (i != IPU3_CSS_QUEUE_OUT && -- !imgu_pipe->nodes[inode].enabled) { -+ !imgu_pipe->nodes[inode].enabled && !try) { - fmts[i] = NULL; - continue; - } -diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c -index 76e97cbe25123..951e19231da21 100644 ---- a/drivers/staging/media/rkvdec/rkvdec-h264.c -+++ b/drivers/staging/media/rkvdec/rkvdec-h264.c -@@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, - struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; - - fmt->num_planes = 1; -- fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * -- RKVDEC_H264_MAX_DEPTH_IN_BYTES; -+ if (!fmt->plane_fmt[0].sizeimage) -+ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * -+ RKVDEC_H264_MAX_DEPTH_IN_BYTES; - return 0; - } - -diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c -index 7131156c1f2cf..3f3f96488d741 100644 ---- a/drivers/staging/media/rkvdec/rkvdec.c -+++ b/drivers/staging/media/rkvdec/rkvdec.c -@@ -280,31 +280,20 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, - return 0; - } - --static int rkvdec_s_fmt(struct file *file, void *priv, -- struct v4l2_format *f, -- int (*try_fmt)(struct file *, void *, -- struct v4l2_format *)) -+static int rkvdec_s_capture_fmt(struct file *file, void *priv, -+ struct v4l2_format *f) - { - struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); - struct vb2_queue *vq; -+ int ret; - -- if (!try_fmt) -- return -EINVAL; -- -- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); -+ /* Change not allowed if queue is busy */ -+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, -+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (vb2_is_busy(vq)) - return -EBUSY; - -- return try_fmt(file, priv, f); --} -- --static int rkvdec_s_capture_fmt(struct file *file, void *priv, -- struct v4l2_format *f) --{ -- struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); -- int ret; -- -- ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_capture_fmt); -+ ret = rkvdec_try_capture_fmt(file, priv, f); - if (ret) - return ret; - -@@ -319,9 +308,20 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, - struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; - const struct rkvdec_coded_fmt_desc *desc; - struct v4l2_format *cap_fmt; -- struct vb2_queue *peer_vq; -+ struct vb2_queue *peer_vq, *vq; - int ret; - -+ /* -+ * In order to support dynamic resolution change, the decoder admits -+ * a resolution change, as long as the pixelformat remains. Can't be -+ * done if streaming. -+ */ -+ vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ if (vb2_is_streaming(vq) || -+ (vb2_is_busy(vq) && -+ f->fmt.pix_mp.pixelformat != ctx->coded_fmt.fmt.pix_mp.pixelformat)) -+ return -EBUSY; -+ - /* - * Since format change on the OUTPUT queue will reset the CAPTURE - * queue, we can't allow doing so when the CAPTURE queue has buffers -@@ -331,7 +331,7 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, - if (vb2_is_busy(peer_vq)) - return -EBUSY; - -- ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_output_fmt); -+ ret = rkvdec_try_output_fmt(file, priv, f); - if (ret) - return ret; - -diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile -index 861adacf6c729..5f9612af3fa3c 100644 ---- a/drivers/staging/most/dim2/Makefile -+++ b/drivers/staging/most/dim2/Makefile -@@ -1,4 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0 - obj-$(CONFIG_MOST_DIM2) += most_dim2.o - --most_dim2-objs := dim2.o hal.o sysfs.o -+most_dim2-objs := dim2.o hal.o -diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c -index 093ef9a2b2919..81e062009d271 100644 ---- a/drivers/staging/most/dim2/dim2.c -+++ b/drivers/staging/most/dim2/dim2.c -@@ -117,7 +117,8 @@ struct dim2_platform_data { - (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ - ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) - --bool dim2_sysfs_get_state_cb(void) -+static ssize_t state_show(struct device *dev, struct device_attribute *attr, -+ char *buf) - { - bool state; - unsigned long flags; -@@ -126,9 +127,18 @@ bool dim2_sysfs_get_state_cb(void) - state = dim_get_lock_state(); - spin_unlock_irqrestore(&dim_lock, flags); - -- return state; -+ return sysfs_emit(buf, "%s\n", state ? "locked" : ""); - } - -+static DEVICE_ATTR_RO(state); -+ -+static struct attribute *dim2_attrs[] = { -+ &dev_attr_state.attr, -+ NULL, -+}; -+ -+ATTRIBUTE_GROUPS(dim2); -+ - /** - * dimcb_on_error - callback from HAL to report miscommunication between - * HDM and HAL -@@ -716,6 +726,23 @@ static int get_dim2_clk_speed(const char *clock_speed, u8 *val) - return -EINVAL; - } - -+static void dim2_release(struct device *d) -+{ -+ struct dim2_hdm *dev = container_of(d, struct dim2_hdm, dev); -+ unsigned long flags; -+ -+ kthread_stop(dev->netinfo_task); -+ -+ spin_lock_irqsave(&dim_lock, flags); -+ dim_shutdown(); -+ spin_unlock_irqrestore(&dim_lock, flags); -+ -+ if (dev->disable_platform) -+ dev->disable_platform(to_platform_device(d->parent)); -+ -+ kfree(dev); -+} -+ - /* - * dim2_probe - dim2 probe handler - * @pdev: platform device structure -@@ -736,7 +763,7 @@ static int dim2_probe(struct platform_device *pdev) - - enum { MLB_INT_IDX, AHB0_INT_IDX }; - -- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - -@@ -748,25 +775,27 @@ static int dim2_probe(struct platform_device *pdev) - "microchip,clock-speed", &clock_speed); - if (ret) { - dev_err(&pdev->dev, "missing dt property clock-speed\n"); -- return ret; -+ goto err_free_dev; - } - - ret = get_dim2_clk_speed(clock_speed, &dev->clk_speed); - if (ret) { - dev_err(&pdev->dev, "bad dt property clock-speed\n"); -- return ret; -+ goto err_free_dev; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->io_base = devm_ioremap_resource(&pdev->dev, res); -- if (IS_ERR(dev->io_base)) -- return PTR_ERR(dev->io_base); -+ if (IS_ERR(dev->io_base)) { -+ ret = PTR_ERR(dev->io_base); -+ goto err_free_dev; -+ } - - of_id = of_match_node(dim2_of_match, pdev->dev.of_node); - pdata = of_id->data; - ret = pdata && pdata->enable ? pdata->enable(pdev) : 0; - if (ret) -- return ret; -+ goto err_free_dev; - - dev->disable_platform = pdata ? pdata->disable : NULL; - -@@ -857,32 +886,19 @@ static int dim2_probe(struct platform_device *pdev) - dev->most_iface.request_netinfo = request_netinfo; - dev->most_iface.driver_dev = &pdev->dev; - dev->most_iface.dev = &dev->dev; -- dev->dev.init_name = "dim2_state"; -+ dev->dev.init_name = dev->name; - dev->dev.parent = &pdev->dev; -+ dev->dev.release = dim2_release; - -- ret = most_register_interface(&dev->most_iface); -- if (ret) { -- dev_err(&pdev->dev, "failed to register MOST interface\n"); -- goto err_stop_thread; -- } -- -- ret = dim2_sysfs_probe(&dev->dev); -- if (ret) { -- dev_err(&pdev->dev, "failed to create sysfs attribute\n"); -- goto err_unreg_iface; -- } -- -- return 0; -+ return most_register_interface(&dev->most_iface); - --err_unreg_iface: -- most_deregister_interface(&dev->most_iface); --err_stop_thread: -- kthread_stop(dev->netinfo_task); - err_shutdown_dim: - dim_shutdown(); - err_disable_platform: - if (dev->disable_platform) - dev->disable_platform(pdev); -+err_free_dev: -+ kfree(dev); - - return ret; - } -@@ -896,18 +912,8 @@ err_disable_platform: - static int dim2_remove(struct platform_device *pdev) - { - struct dim2_hdm *dev = platform_get_drvdata(pdev); -- unsigned long flags; - -- dim2_sysfs_destroy(&dev->dev); - most_deregister_interface(&dev->most_iface); -- kthread_stop(dev->netinfo_task); -- -- spin_lock_irqsave(&dim_lock, flags); -- dim_shutdown(); -- spin_unlock_irqrestore(&dim_lock, flags); -- -- if (dev->disable_platform) -- dev->disable_platform(pdev); - - return 0; - } -@@ -1082,6 +1088,7 @@ static struct platform_driver dim2_driver = { - .driver = { - .name = "hdm_dim2", - .of_match_table = dim2_of_match, -+ .dev_groups = dim2_groups, - }, - }; - -diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c -deleted file mode 100644 -index c85b2cdcdca3d..0000000000000 ---- a/drivers/staging/most/dim2/sysfs.c -+++ /dev/null -@@ -1,49 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --/* -- * sysfs.c - MediaLB sysfs information -- * -- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG -- */ -- --/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ -- --#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- --#include <linux/kernel.h> --#include "sysfs.h" --#include <linux/device.h> -- --static ssize_t state_show(struct device *dev, struct device_attribute *attr, -- char *buf) --{ -- bool state = dim2_sysfs_get_state_cb(); -- -- return sprintf(buf, "%s\n", state ? "locked" : ""); --} -- --static DEVICE_ATTR_RO(state); -- --static struct attribute *dev_attrs[] = { -- &dev_attr_state.attr, -- NULL, --}; -- --static struct attribute_group dev_attr_group = { -- .attrs = dev_attrs, --}; -- --static const struct attribute_group *dev_attr_groups[] = { -- &dev_attr_group, -- NULL, --}; -- --int dim2_sysfs_probe(struct device *dev) --{ -- dev->groups = dev_attr_groups; -- return device_register(dev); --} -- --void dim2_sysfs_destroy(struct device *dev) --{ -- device_unregister(dev); --} -diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h -index 24277a17cff3d..09115cf4ed00e 100644 ---- a/drivers/staging/most/dim2/sysfs.h -+++ b/drivers/staging/most/dim2/sysfs.h -@@ -16,15 +16,4 @@ struct medialb_bus { - struct kobject kobj_group; - }; - --struct device; -- --int dim2_sysfs_probe(struct device *dev); --void dim2_sysfs_destroy(struct device *dev); -- --/* -- * callback, -- * must deliver MediaLB state as true if locked or false if unlocked -- */ --bool dim2_sysfs_get_state_cb(void); -- - #endif /* DIM2_SYSFS_H */ -diff --git a/drivers/staging/r8188eu/core/rtw_mlme.c b/drivers/staging/r8188eu/core/rtw_mlme.c -index 1115ff5d865ad..bd991d7ed8090 100644 ---- a/drivers/staging/r8188eu/core/rtw_mlme.c -+++ b/drivers/staging/r8188eu/core/rtw_mlme.c -@@ -1722,6 +1722,8 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in - psetkeyparm->grpkey = 1; - break; - default: -+ kfree(psetkeyparm); -+ kfree(pcmd); - res = _FAIL; - goto exit; - } -diff --git a/drivers/staging/r8188eu/core/rtw_mlme_ext.c b/drivers/staging/r8188eu/core/rtw_mlme_ext.c -index 5a472a4954b0f..63d312d01171e 100644 ---- a/drivers/staging/r8188eu/core/rtw_mlme_ext.c -+++ b/drivers/staging/r8188eu/core/rtw_mlme_ext.c -@@ -104,6 +104,7 @@ static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { - {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ - {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ - {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ -+ {0x00}, /* 0x13 */ - {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ - {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ - {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ -@@ -115,6 +116,7 @@ static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { - {0x00}, /* 0x1C, */ - {0x00}, /* 0x1D, */ - {0x00}, /* 0x1E, */ -+ {0x00}, /* 0x1F, */ - /* 0x20 ~ 0x7F , New Define ===== */ - {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ - {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ -@@ -7080,12 +7082,12 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - -- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); -+ pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); -- pevtcmd = kzalloc(cmdsz, GFP_KERNEL); -+ pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; -diff --git a/drivers/staging/r8188eu/os_dep/ioctl_linux.c b/drivers/staging/r8188eu/os_dep/ioctl_linux.c -index 1fd3750760018..0eccce57c63a6 100644 ---- a/drivers/staging/r8188eu/os_dep/ioctl_linux.c -+++ b/drivers/staging/r8188eu/os_dep/ioctl_linux.c -@@ -1978,7 +1978,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, - struct ieee_param *param = NULL; - struct iw_point *pencoding = &wrqu->encoding; - struct iw_encode_ext *pext = (struct iw_encode_ext *)extra; -- int ret = 0; -+ int ret = -1; - - param_len = sizeof(struct ieee_param) + pext->key_len; - param = kzalloc(param_len, GFP_KERNEL); -@@ -2004,7 +2004,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, - alg_name = "CCMP"; - break; - default: -- return -1; -+ goto out; - } - - strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); -@@ -2031,6 +2031,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, - - ret = wpa_set_encryption(dev, param, param_len); - -+out: - kfree(param); - return ret; - } -@@ -2060,6 +2061,7 @@ static int rtw_wx_read32(struct net_device *dev, - u32 data32; - u32 bytes; - u8 *ptmp; -+ int ret; - - padapter = (struct adapter *)rtw_netdev_priv(dev); - p = &wrqu->data; -@@ -2092,12 +2094,17 @@ static int rtw_wx_read32(struct net_device *dev, - break; - default: - DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_free_ptmp; - } - DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra); - - kfree(ptmp); - return 0; -+ -+err_free_ptmp: -+ kfree(ptmp); -+ return ret; - } - - static int rtw_wx_write32(struct net_device *dev, -diff --git a/drivers/staging/r8188eu/os_dep/mlme_linux.c b/drivers/staging/r8188eu/os_dep/mlme_linux.c -index e3ee9dc7ab900..b0d1e20edc4c2 100644 ---- a/drivers/staging/r8188eu/os_dep/mlme_linux.c -+++ b/drivers/staging/r8188eu/os_dep/mlme_linux.c -@@ -114,7 +114,7 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie) - - buff = NULL; - if (authmode == _WPA_IE_ID_) { -- buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL); -+ buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC); - if (!buff) - return; - p = buff; -diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c -index a7dd1578b2c6a..616ab3c8fde4f 100644 ---- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c -+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c -@@ -2549,13 +2549,14 @@ static void _rtl92e_pci_disconnect(struct pci_dev *pdev) - free_irq(dev->irq, dev); - priv->irq = 0; - } -- free_rtllib(dev); - - if (dev->mem_start != 0) { - iounmap((void __iomem *)dev->mem_start); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - } -+ -+ free_rtllib(dev); - } - - pci_disable_device(pdev); -diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c -index b6698656fc014..cf5cfee2936fd 100644 ---- a/drivers/staging/rtl8192u/r8192U_core.c -+++ b/drivers/staging/rtl8192u/r8192U_core.c -@@ -229,7 +229,7 @@ int write_nic_byte_E(struct net_device *dev, int indx, u8 data) - - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, -- indx | 0xfe00, 0, usbdata, 1, HZ / 2); -+ indx | 0xfe00, 0, usbdata, 1, 500); - kfree(usbdata); - - if (status < 0) { -@@ -251,7 +251,7 @@ int read_nic_byte_E(struct net_device *dev, int indx, u8 *data) - - status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, -- indx | 0xfe00, 0, usbdata, 1, HZ / 2); -+ indx | 0xfe00, 0, usbdata, 1, 500); - *data = *usbdata; - kfree(usbdata); - -@@ -279,7 +279,7 @@ int write_nic_byte(struct net_device *dev, int indx, u8 data) - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, - (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, -- usbdata, 1, HZ / 2); -+ usbdata, 1, 500); - kfree(usbdata); - - if (status < 0) { -@@ -305,7 +305,7 @@ int write_nic_word(struct net_device *dev, int indx, u16 data) - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, - (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, -- usbdata, 2, HZ / 2); -+ usbdata, 2, 500); - kfree(usbdata); - - if (status < 0) { -@@ -331,7 +331,7 @@ int write_nic_dword(struct net_device *dev, int indx, u32 data) - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, - (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, -- usbdata, 4, HZ / 2); -+ usbdata, 4, 500); - kfree(usbdata); - - if (status < 0) { -@@ -355,7 +355,7 @@ int read_nic_byte(struct net_device *dev, int indx, u8 *data) - status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, - (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, -- usbdata, 1, HZ / 2); -+ usbdata, 1, 500); - *data = *usbdata; - kfree(usbdata); - -@@ -380,7 +380,7 @@ int read_nic_word(struct net_device *dev, int indx, u16 *data) - status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, - (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, -- usbdata, 2, HZ / 2); -+ usbdata, 2, 500); - *data = *usbdata; - kfree(usbdata); - -@@ -404,7 +404,7 @@ static int read_nic_word_E(struct net_device *dev, int indx, u16 *data) - - status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, -- indx | 0xfe00, 0, usbdata, 2, HZ / 2); -+ indx | 0xfe00, 0, usbdata, 2, 500); - *data = *usbdata; - kfree(usbdata); - -@@ -430,7 +430,7 @@ int read_nic_dword(struct net_device *dev, int indx, u32 *data) - status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, - (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, -- usbdata, 4, HZ / 2); -+ usbdata, 4, 500); - *data = *usbdata; - kfree(usbdata); - -diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c -index 505ebeb643dc2..cae04272deffe 100644 ---- a/drivers/staging/rtl8712/usb_intf.c -+++ b/drivers/staging/rtl8712/usb_intf.c -@@ -595,12 +595,12 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) - - /* never exit with a firmware callback pending */ - wait_for_completion(&padapter->rtl8712_fw_ready); -+ if (pnetdev->reg_state != NETREG_UNINITIALIZED) -+ unregister_netdev(pnetdev); /* will call netdev_close() */ - usb_set_intfdata(pusb_intf, NULL); - release_firmware(padapter->fw); - if (drvpriv.drv_registered) - padapter->surprise_removed = true; -- if (pnetdev->reg_state != NETREG_UNINITIALIZED) -- unregister_netdev(pnetdev); /* will call netdev_close() */ - r8712_flush_rwctrl_works(padapter); - r8712_flush_led_works(padapter); - udelay(1); -diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c -index 655497cead122..f984a5ab2c6ff 100644 ---- a/drivers/staging/rtl8712/usb_ops_linux.c -+++ b/drivers/staging/rtl8712/usb_ops_linux.c -@@ -494,7 +494,7 @@ int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value, - memcpy(pIo_buf, pdata, len); - } - status = usb_control_msg(udev, pipe, request, reqtype, value, index, -- pIo_buf, len, HZ / 2); -+ pIo_buf, len, 500); - if (status > 0) { /* Success this control transfer. */ - if (requesttype == 0x01) { - /* For Control read transfer, we have to copy the read -diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c -index ab6a24d70cc96..cf79bec916c51 100644 ---- a/drivers/staging/rtl8723bs/core/rtw_mlme.c -+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c -@@ -897,7 +897,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) - { - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; -- struct sta_priv *pstapriv = &adapter->stapriv; - struct dvobj_priv *psdpriv = adapter->dvobj; - struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; - -@@ -905,11 +904,7 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) - struct sta_info *psta; - - psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.mac_address); -- spin_lock_bh(&(pstapriv->sta_hash_lock)); - rtw_free_stainfo(adapter, psta); -- -- spin_unlock_bh(&(pstapriv->sta_hash_lock)); -- - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) { -@@ -1239,16 +1234,13 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) - rtw_indicate_connect(adapter); - } - -+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock); -+ - /* s5. Cancel assoc_timer */ - del_timer_sync(&pmlmepriv->assoc_timer); -- - } else { - spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); -- goto ignore_joinbss_callback; - } -- -- spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); -- - } else if (pnetwork->join_res == -4) { - rtw_reset_securitypriv(adapter); - _set_timer(&pmlmepriv->assoc_timer, 1); -diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c -index 375d2a742dd2d..ad9c237054c4b 100644 ---- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c -+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c -@@ -1489,9 +1489,7 @@ unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame) - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - -- /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ - /* rtw_free_stainfo(padapter, psta); */ -- /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ - - netdev_dbg(padapter->pnetdev, - "ap recv deauth reason code(%d) sta:%pM\n", reason, -@@ -1565,9 +1563,7 @@ unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame) - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - -- /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ - /* rtw_free_stainfo(padapter, psta); */ -- /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ - - netdev_dbg(padapter->pnetdev, - "ap recv disassoc reason code(%d) sta:%pM\n", -@@ -5919,7 +5915,6 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) - struct sta_info *psta_bmc; - struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; - struct xmit_frame *pxmitframe = NULL; -- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* for BC/MC Frames */ -@@ -5930,8 +5925,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) - if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { - msleep(10);/* 10ms, ATIM(HIQ) Windows */ - -- /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ -- spin_lock_bh(&pxmitpriv->lock); -+ spin_lock_bh(&psta_bmc->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { -@@ -5954,8 +5948,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) - rtw_hal_xmitframe_enqueue(padapter, pxmitframe); - } - -- /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ -- spin_unlock_bh(&pxmitpriv->lock); -+ spin_unlock_bh(&psta_bmc->sleep_q.lock); - - /* check hi queue and bmc_sleepq */ - rtw_chk_hi_queue_cmd(padapter); -diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c -index 5b0a596eefb77..3564e2af5741b 100644 ---- a/drivers/staging/rtl8723bs/core/rtw_recv.c -+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c -@@ -953,10 +953,8 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_ - if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) { - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; -- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - -- /* spin_lock_bh(&psta->sleep_q.lock); */ -- spin_lock_bh(&pxmitpriv->lock); -+ spin_lock_bh(&psta->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); -@@ -987,12 +985,10 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_ - update_beacon(padapter, WLAN_EID_TIM, NULL, true); - } - -- /* spin_unlock_bh(&psta->sleep_q.lock); */ -- spin_unlock_bh(&pxmitpriv->lock); -+ spin_unlock_bh(&psta->sleep_q.lock); - - } else { -- /* spin_unlock_bh(&psta->sleep_q.lock); */ -- spin_unlock_bh(&pxmitpriv->lock); -+ spin_unlock_bh(&psta->sleep_q.lock); - - if (pstapriv->tim_bitmap&BIT(psta->aid)) { - if (psta->sleepq_len == 0) { -diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c -index 67ca219f95bf8..3d269842677dd 100644 ---- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c -+++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c -@@ -263,7 +263,6 @@ exit: - return psta; - } - --/* using pstapriv->sta_hash_lock to protect */ - u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) - { - int i; -@@ -289,51 +288,55 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) - - /* list_del_init(&psta->wakeup_list); */ - -- spin_lock_bh(&pxmitpriv->lock); -- -+ spin_lock_bh(&psta->sleep_q.lock); - rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); - psta->sleepq_len = 0; -+ spin_unlock_bh(&psta->sleep_q.lock); -+ -+ spin_lock_bh(&pxmitpriv->lock); - - /* vo */ -- /* spin_lock_bh(&(pxmitpriv->vo_pending.lock)); */ -+ spin_lock_bh(&pstaxmitpriv->vo_q.sta_pending.lock); - rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&(pstaxmitpriv->vo_q.tx_pending)); - phwxmit = pxmitpriv->hwxmits; - phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; - pstaxmitpriv->vo_q.qcnt = 0; -- /* spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); */ -+ spin_unlock_bh(&pstaxmitpriv->vo_q.sta_pending.lock); - - /* vi */ -- /* spin_lock_bh(&(pxmitpriv->vi_pending.lock)); */ -+ spin_lock_bh(&pstaxmitpriv->vi_q.sta_pending.lock); - rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&(pstaxmitpriv->vi_q.tx_pending)); - phwxmit = pxmitpriv->hwxmits+1; - phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; - pstaxmitpriv->vi_q.qcnt = 0; -- /* spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); */ -+ spin_unlock_bh(&pstaxmitpriv->vi_q.sta_pending.lock); - - /* be */ -- /* spin_lock_bh(&(pxmitpriv->be_pending.lock)); */ -+ spin_lock_bh(&pstaxmitpriv->be_q.sta_pending.lock); - rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&(pstaxmitpriv->be_q.tx_pending)); - phwxmit = pxmitpriv->hwxmits+2; - phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; - pstaxmitpriv->be_q.qcnt = 0; -- /* spin_unlock_bh(&(pxmitpriv->be_pending.lock)); */ -+ spin_unlock_bh(&pstaxmitpriv->be_q.sta_pending.lock); - - /* bk */ -- /* spin_lock_bh(&(pxmitpriv->bk_pending.lock)); */ -+ spin_lock_bh(&pstaxmitpriv->bk_q.sta_pending.lock); - rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&(pstaxmitpriv->bk_q.tx_pending)); - phwxmit = pxmitpriv->hwxmits+3; - phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; - pstaxmitpriv->bk_q.qcnt = 0; -- /* spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); */ -+ spin_unlock_bh(&pstaxmitpriv->bk_q.sta_pending.lock); - - spin_unlock_bh(&pxmitpriv->lock); - -+ spin_lock_bh(&pstapriv->sta_hash_lock); - list_del_init(&psta->hash_list); - pstapriv->asoc_sta_count--; -+ spin_unlock_bh(&pstapriv->sta_hash_lock); - - /* re-init sta_info; 20061114 will be init in alloc_stainfo */ - /* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */ -@@ -428,6 +431,7 @@ void rtw_free_all_stainfo(struct adapter *padapter) - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter); -+ LIST_HEAD(stainfo_free_list); - - if (pstapriv->asoc_sta_count == 1) - return; -@@ -440,11 +444,16 @@ void rtw_free_all_stainfo(struct adapter *padapter) - psta = list_entry(plist, struct sta_info, hash_list); - - if (pbcmc_stainfo != psta) -- rtw_free_stainfo(padapter, psta); -+ list_move(&psta->hash_list, &stainfo_free_list); - } - } - - spin_unlock_bh(&pstapriv->sta_hash_lock); -+ -+ list_for_each_safe(plist, tmp, &stainfo_free_list) { -+ psta = list_entry(plist, struct sta_info, hash_list); -+ rtw_free_stainfo(padapter, psta); -+ } - } - - /* any station allocated can be searched by hash list */ -diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c -index 79e4d7df1ef57..6b37b42ec2266 100644 ---- a/drivers/staging/rtl8723bs/core/rtw_xmit.c -+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c -@@ -1723,15 +1723,12 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram - struct list_head *plist, *phead, *tmp; - struct xmit_frame *pxmitframe; - -- spin_lock_bh(&pframequeue->lock); -- - phead = get_list_head(pframequeue); - list_for_each_safe(plist, tmp, phead) { - pxmitframe = list_entry(plist, struct xmit_frame, list); - - rtw_free_xmitframe(pxmitpriv, pxmitframe); - } -- spin_unlock_bh(&pframequeue->lock); - } - - s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe) -@@ -1786,6 +1783,7 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; -+ struct xmit_priv *xmit_priv = &padapter->xmitpriv; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - signed int res = _SUCCESS; - -@@ -1803,12 +1801,14 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) - - ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - -+ spin_lock_bh(&xmit_priv->lock); - if (list_empty(&ptxservq->tx_pending)) - list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue)); - - list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); - ptxservq->qcnt++; - phwxmits[ac_index].accnt++; -+ spin_unlock_bh(&xmit_priv->lock); - - exit: - -@@ -2191,11 +2191,10 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) - struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; - struct xmit_frame *pxmitframe = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; -- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - psta_bmc = rtw_get_bcmc_stainfo(padapter); - -- spin_lock_bh(&pxmitpriv->lock); -+ spin_lock_bh(&psta->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { -@@ -2296,7 +2295,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) - - _exit: - -- spin_unlock_bh(&pxmitpriv->lock); -+ spin_unlock_bh(&psta->sleep_q.lock); - - if (update_mask) - update_beacon(padapter, WLAN_EID_TIM, NULL, true); -@@ -2308,9 +2307,8 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst - struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; - struct xmit_frame *pxmitframe = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; -- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - -- spin_lock_bh(&pxmitpriv->lock); -+ spin_lock_bh(&psta->sleep_q.lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { -@@ -2363,7 +2361,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst - } - } - -- spin_unlock_bh(&pxmitpriv->lock); -+ spin_unlock_bh(&psta->sleep_q.lock); - } - - void enqueue_pending_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c -index 156d6aba18ca1..5f5c4719b5868 100644 ---- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c -+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c -@@ -507,9 +507,7 @@ s32 rtl8723bs_hal_xmit( - rtw_issue_addbareq_cmd(padapter, pxmitframe); - } - -- spin_lock_bh(&pxmitpriv->lock); - err = rtw_xmitframe_enqueue(padapter, pxmitframe); -- spin_unlock_bh(&pxmitpriv->lock); - if (err != _SUCCESS) { - rtw_free_xmitframe(pxmitpriv, pxmitframe); - -diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c -index 9d4a233a861e3..295121c268bd4 100644 ---- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c -+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c -@@ -835,9 +835,7 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) - psta = rtw_get_stainfo(pstapriv, param->sta_addr); - if (psta) - { -- spin_lock_bh(&(pstapriv->sta_hash_lock)); - rtw_free_stainfo(padapter, psta); -- spin_unlock_bh(&(pstapriv->sta_hash_lock)); - - psta = NULL; - } -diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c -index e06d7e1ebe9c3..61b8cc05f2935 100644 ---- a/drivers/staging/wfx/bus_sdio.c -+++ b/drivers/staging/wfx/bus_sdio.c -@@ -120,19 +120,22 @@ static int wfx_sdio_irq_subscribe(void *priv) - return ret; - } - -+ flags = irq_get_trigger_type(bus->of_irq); -+ if (!flags) -+ flags = IRQF_TRIGGER_HIGH; -+ flags |= IRQF_ONESHOT; -+ ret = devm_request_threaded_irq(&bus->func->dev, bus->of_irq, NULL, -+ wfx_sdio_irq_handler_ext, flags, -+ "wfx", bus); -+ if (ret) -+ return ret; - sdio_claim_host(bus->func); - cccr = sdio_f0_readb(bus->func, SDIO_CCCR_IENx, NULL); - cccr |= BIT(0); - cccr |= BIT(bus->func->num); - sdio_f0_writeb(bus->func, cccr, SDIO_CCCR_IENx, NULL); - sdio_release_host(bus->func); -- flags = irq_get_trigger_type(bus->of_irq); -- if (!flags) -- flags = IRQF_TRIGGER_HIGH; -- flags |= IRQF_ONESHOT; -- return devm_request_threaded_irq(&bus->func->dev, bus->of_irq, NULL, -- wfx_sdio_irq_handler_ext, flags, -- "wfx", bus); -+ return 0; - } - - static int wfx_sdio_irq_unsubscribe(void *priv) -diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c -index cb1de1ecaaa61..bd0f2ce011dd7 100644 ---- a/drivers/target/target_core_alua.c -+++ b/drivers/target/target_core_alua.c -@@ -1674,7 +1674,6 @@ int core_alua_set_tg_pt_gp_id( - pr_err("Maximum ALUA alua_tg_pt_gps_count:" - " 0x0000ffff reached\n"); - spin_unlock(&dev->t10_alua.tg_pt_gps_lock); -- kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); - return -ENOSPC; - } - again: -diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c -index 8cb1fa0c05857..44bb380e7390c 100644 ---- a/drivers/target/target_core_device.c -+++ b/drivers/target/target_core_device.c -@@ -772,6 +772,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) - INIT_LIST_HEAD(&dev->t10_alua.lba_map_list); - spin_lock_init(&dev->t10_alua.lba_map_lock); - -+ INIT_WORK(&dev->delayed_cmd_work, target_do_delayed_work); -+ - dev->t10_wwn.t10_dev = dev; - /* - * Use OpenFabrics IEEE Company ID: 00 14 05 -diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h -index a343bcfa2180f..a889a6237d9c1 100644 ---- a/drivers/target/target_core_internal.h -+++ b/drivers/target/target_core_internal.h -@@ -151,6 +151,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); - void transport_clear_lun_ref(struct se_lun *); - sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); - void target_qf_do_work(struct work_struct *work); -+void target_do_delayed_work(struct work_struct *work); - bool target_check_wce(struct se_device *dev); - bool target_check_fua(struct se_device *dev); - void __target_execute_cmd(struct se_cmd *, bool); -diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c -index e7fcbc09f9dbc..bac111456fa1d 100644 ---- a/drivers/target/target_core_tmr.c -+++ b/drivers/target/target_core_tmr.c -@@ -50,15 +50,6 @@ EXPORT_SYMBOL(core_tmr_alloc_req); - - void core_tmr_release_req(struct se_tmr_req *tmr) - { -- struct se_device *dev = tmr->tmr_dev; -- unsigned long flags; -- -- if (dev) { -- spin_lock_irqsave(&dev->se_tmr_lock, flags); -- list_del_init(&tmr->tmr_list); -- spin_unlock_irqrestore(&dev->se_tmr_lock, flags); -- } -- - kfree(tmr); - } - -@@ -156,13 +147,6 @@ void core_tmr_abort_task( - se_cmd->state_active = false; - spin_unlock_irqrestore(&dev->queues[i].lock, flags); - -- /* -- * Ensure that this ABORT request is visible to the LU -- * RESET code. -- */ -- if (!tmr->tmr_dev) -- WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < 0); -- - if (dev->transport->tmr_notify) - dev->transport->tmr_notify(dev, TMR_ABORT_TASK, - &aborted_list); -@@ -234,6 +218,7 @@ static void core_tmr_drain_tmr_list( - } - - list_move_tail(&tmr_p->tmr_list, &drain_tmr_list); -+ tmr_p->tmr_dev = NULL; - } - spin_unlock_irqrestore(&dev->se_tmr_lock, flags); - -diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c -index 14c6f2bb1b01d..72edf5bd75ee6 100644 ---- a/drivers/target/target_core_transport.c -+++ b/drivers/target/target_core_transport.c -@@ -676,6 +676,21 @@ static void target_remove_from_state_list(struct se_cmd *cmd) - spin_unlock_irqrestore(&dev->queues[cmd->cpuid].lock, flags); - } - -+static void target_remove_from_tmr_list(struct se_cmd *cmd) -+{ -+ struct se_device *dev = NULL; -+ unsigned long flags; -+ -+ if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) -+ dev = cmd->se_tmr_req->tmr_dev; -+ -+ if (dev) { -+ spin_lock_irqsave(&dev->se_tmr_lock, flags); -+ if (cmd->se_tmr_req->tmr_dev) -+ list_del_init(&cmd->se_tmr_req->tmr_list); -+ spin_unlock_irqrestore(&dev->se_tmr_lock, flags); -+ } -+} - /* - * This function is called by the target core after the target core has - * finished processing a SCSI command or SCSI TMF. Both the regular command -@@ -687,13 +702,6 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd) - { - unsigned long flags; - -- target_remove_from_state_list(cmd); -- -- /* -- * Clear struct se_cmd->se_lun before the handoff to FE. -- */ -- cmd->se_lun = NULL; -- - spin_lock_irqsave(&cmd->t_state_lock, flags); - /* - * Determine if frontend context caller is requesting the stopping of -@@ -728,8 +736,16 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) - if (!lun) - return; - -+ target_remove_from_state_list(cmd); -+ target_remove_from_tmr_list(cmd); -+ - if (cmpxchg(&cmd->lun_ref_active, true, false)) - percpu_ref_put(&lun->lun_ref); -+ -+ /* -+ * Clear struct se_cmd->se_lun before the handoff to FE. -+ */ -+ cmd->se_lun = NULL; - } - - static void target_complete_failure_work(struct work_struct *work) -@@ -2173,32 +2189,35 @@ static bool target_handle_task_attr(struct se_cmd *cmd) - */ - switch (cmd->sam_task_attr) { - case TCM_HEAD_TAG: -+ atomic_inc_mb(&dev->non_ordered); - pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x\n", - cmd->t_task_cdb[0]); - return false; - case TCM_ORDERED_TAG: -- atomic_inc_mb(&dev->dev_ordered_sync); -+ atomic_inc_mb(&dev->delayed_cmd_count); - - pr_debug("Added ORDERED for CDB: 0x%02x to ordered list\n", - cmd->t_task_cdb[0]); -- -- /* -- * Execute an ORDERED command if no other older commands -- * exist that need to be completed first. -- */ -- if (!atomic_read(&dev->simple_cmds)) -- return false; - break; - default: - /* - * For SIMPLE and UNTAGGED Task Attribute commands - */ -- atomic_inc_mb(&dev->simple_cmds); -+ atomic_inc_mb(&dev->non_ordered); -+ -+ if (atomic_read(&dev->delayed_cmd_count) == 0) -+ return false; - break; - } - -- if (atomic_read(&dev->dev_ordered_sync) == 0) -- return false; -+ if (cmd->sam_task_attr != TCM_ORDERED_TAG) { -+ atomic_inc_mb(&dev->delayed_cmd_count); -+ /* -+ * We will account for this when we dequeue from the delayed -+ * list. -+ */ -+ atomic_dec_mb(&dev->non_ordered); -+ } - - spin_lock(&dev->delayed_cmd_lock); - list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); -@@ -2206,6 +2225,12 @@ static bool target_handle_task_attr(struct se_cmd *cmd) - - pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to delayed CMD listn", - cmd->t_task_cdb[0], cmd->sam_task_attr); -+ /* -+ * We may have no non ordered cmds when this function started or we -+ * could have raced with the last simple/head cmd completing, so kick -+ * the delayed handler here. -+ */ -+ schedule_work(&dev->delayed_cmd_work); - return true; - } - -@@ -2243,29 +2268,48 @@ EXPORT_SYMBOL(target_execute_cmd); - * Process all commands up to the last received ORDERED task attribute which - * requires another blocking boundary - */ --static void target_restart_delayed_cmds(struct se_device *dev) -+void target_do_delayed_work(struct work_struct *work) - { -- for (;;) { -+ struct se_device *dev = container_of(work, struct se_device, -+ delayed_cmd_work); -+ -+ spin_lock(&dev->delayed_cmd_lock); -+ while (!dev->ordered_sync_in_progress) { - struct se_cmd *cmd; - -- spin_lock(&dev->delayed_cmd_lock); -- if (list_empty(&dev->delayed_cmd_list)) { -- spin_unlock(&dev->delayed_cmd_lock); -+ if (list_empty(&dev->delayed_cmd_list)) - break; -- } - - cmd = list_entry(dev->delayed_cmd_list.next, - struct se_cmd, se_delayed_node); -+ -+ if (cmd->sam_task_attr == TCM_ORDERED_TAG) { -+ /* -+ * Check if we started with: -+ * [ordered] [simple] [ordered] -+ * and we are now at the last ordered so we have to wait -+ * for the simple cmd. -+ */ -+ if (atomic_read(&dev->non_ordered) > 0) -+ break; -+ -+ dev->ordered_sync_in_progress = true; -+ } -+ - list_del(&cmd->se_delayed_node); -+ atomic_dec_mb(&dev->delayed_cmd_count); - spin_unlock(&dev->delayed_cmd_lock); - -+ if (cmd->sam_task_attr != TCM_ORDERED_TAG) -+ atomic_inc_mb(&dev->non_ordered); -+ - cmd->transport_state |= CMD_T_SENT; - - __target_execute_cmd(cmd, true); - -- if (cmd->sam_task_attr == TCM_ORDERED_TAG) -- break; -+ spin_lock(&dev->delayed_cmd_lock); - } -+ spin_unlock(&dev->delayed_cmd_lock); - } - - /* -@@ -2283,14 +2327,17 @@ static void transport_complete_task_attr(struct se_cmd *cmd) - goto restart; - - if (cmd->sam_task_attr == TCM_SIMPLE_TAG) { -- atomic_dec_mb(&dev->simple_cmds); -+ atomic_dec_mb(&dev->non_ordered); - dev->dev_cur_ordered_id++; - } else if (cmd->sam_task_attr == TCM_HEAD_TAG) { -+ atomic_dec_mb(&dev->non_ordered); - dev->dev_cur_ordered_id++; - pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n", - dev->dev_cur_ordered_id); - } else if (cmd->sam_task_attr == TCM_ORDERED_TAG) { -- atomic_dec_mb(&dev->dev_ordered_sync); -+ spin_lock(&dev->delayed_cmd_lock); -+ dev->ordered_sync_in_progress = false; -+ spin_unlock(&dev->delayed_cmd_lock); - - dev->dev_cur_ordered_id++; - pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", -@@ -2299,7 +2346,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd) - cmd->se_cmd_flags &= ~SCF_TASK_ATTR_SET; - - restart: -- target_restart_delayed_cmds(dev); -+ if (atomic_read(&dev->delayed_cmd_count) > 0) -+ schedule_work(&dev->delayed_cmd_work); - } - - static void transport_complete_qf(struct se_cmd *cmd) -diff --git a/drivers/tee/amdtee/core.c b/drivers/tee/amdtee/core.c -index da6b88e80dc07..297dc62bca298 100644 ---- a/drivers/tee/amdtee/core.c -+++ b/drivers/tee/amdtee/core.c -@@ -203,9 +203,8 @@ static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta, - - *ta_size = roundup(fw->size, PAGE_SIZE); - *ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size)); -- if (IS_ERR(*ta)) { -- pr_err("%s: get_free_pages failed 0x%llx\n", __func__, -- (u64)*ta); -+ if (!*ta) { -+ pr_err("%s: get_free_pages failed\n", __func__); - rc = -ENOMEM; - goto rel_fw; - } -diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c -index 59e93b04f0a9e..66cd0190bc035 100644 ---- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c -+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c -@@ -7,6 +7,7 @@ - #include <linux/kernel.h> - #include <linux/module.h> - #include <linux/pci.h> -+#include <linux/io-64-nonatomic-lo-hi.h> - #include "processor_thermal_device.h" - - #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E -diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c -index 2b8a3235d518b..3b3e81f99a34c 100644 ---- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c -+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c -@@ -29,7 +29,7 @@ static const char * const fivr_strings[] = { - }; - - static const struct mmio_reg tgl_fivr_mmio_regs[] = { -- { 0, 0x5A18, 3, 0x7, 12}, /* vco_ref_code_lo */ -+ { 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */ - { 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */ - { 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */ - { 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */ -diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig -index 7d942f71e5328..bfd889422dd32 100644 ---- a/drivers/thermal/qcom/Kconfig -+++ b/drivers/thermal/qcom/Kconfig -@@ -34,7 +34,7 @@ config QCOM_SPMI_TEMP_ALARM - - config QCOM_LMH - tristate "Qualcomm Limits Management Hardware" -- depends on ARCH_QCOM -+ depends on ARCH_QCOM && QCOM_SCM - help - This enables initialization of Qualcomm limits management - hardware(LMh). LMh allows for hardware-enforced mitigation for cpus based on -diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c -index b1162e566a707..99a8d9f3e03ca 100644 ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -603,22 +603,21 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp) - int ret; - - /* VER_0 doesn't have VALID bit */ -- if (tsens_version(priv) >= VER_0_1) { -- ret = regmap_field_read(priv->rf[valid_idx], &valid); -- if (ret) -- return ret; -- while (!valid) { -- /* Valid bit is 0 for 6 AHB clock cycles. -- * At 19.2MHz, 1 AHB clock is ~60ns. -- * We should enter this loop very, very rarely. -- */ -- ndelay(400); -- ret = regmap_field_read(priv->rf[valid_idx], &valid); -- if (ret) -- return ret; -- } -- } -+ if (tsens_version(priv) == VER_0) -+ goto get_temp; -+ -+ /* Valid bit is 0 for 6 AHB clock cycles. -+ * At 19.2MHz, 1 AHB clock is ~60ns. -+ * We should enter this loop very, very rarely. -+ * Wait 1 us since it's the min of poll_timeout macro. -+ * Old value was 400 ns. -+ */ -+ ret = regmap_field_read_poll_timeout(priv->rf[valid_idx], valid, -+ valid, 1, 20 * USEC_PER_MSEC); -+ if (ret) -+ return ret; - -+get_temp: - /* Valid bit is set, OK to read the temperature */ - *temp = tsens_hw_to_mC(s, temp_idx); - -diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c -index 51374f4e1ccaf..13891745a9719 100644 ---- a/drivers/thermal/thermal_core.c -+++ b/drivers/thermal/thermal_core.c -@@ -419,6 +419,8 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) - { - struct thermal_instance *pos; - tz->temperature = THERMAL_TEMP_INVALID; -+ tz->prev_low_trip = -INT_MAX; -+ tz->prev_high_trip = INT_MAX; - list_for_each_entry(pos, &tz->thermal_instances, tz_node) - pos->initialized = false; - } -@@ -887,7 +889,7 @@ __thermal_cooling_device_register(struct device_node *np, - { - struct thermal_cooling_device *cdev; - struct thermal_zone_device *pos = NULL; -- int ret; -+ int id, ret; - - if (!ops || !ops->get_max_state || !ops->get_cur_state || - !ops->set_cur_state) -@@ -901,6 +903,11 @@ __thermal_cooling_device_register(struct device_node *np, - if (ret < 0) - goto out_kfree_cdev; - cdev->id = ret; -+ id = ret; -+ -+ ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); -+ if (ret) -+ goto out_ida_remove; - - cdev->type = kstrdup(type ? type : "", GFP_KERNEL); - if (!cdev->type) { -@@ -916,7 +923,6 @@ __thermal_cooling_device_register(struct device_node *np, - cdev->device.class = &thermal_class; - cdev->devdata = devdata; - thermal_cooling_device_setup_sysfs(cdev); -- dev_set_name(&cdev->device, "cooling_device%d", cdev->id); - ret = device_register(&cdev->device); - if (ret) - goto out_kfree_type; -@@ -941,8 +947,9 @@ __thermal_cooling_device_register(struct device_node *np, - out_kfree_type: - kfree(cdev->type); - put_device(&cdev->device); -+ cdev = NULL; - out_ida_remove: -- ida_simple_remove(&thermal_cdev_ida, cdev->id); -+ ida_simple_remove(&thermal_cdev_ida, id); - out_kfree_cdev: - kfree(cdev); - return ERR_PTR(ret); -@@ -1227,6 +1234,10 @@ thermal_zone_device_register(const char *type, int trips, int mask, - tz->id = id; - strlcpy(tz->type, type, sizeof(tz->type)); - -+ result = dev_set_name(&tz->device, "thermal_zone%d", tz->id); -+ if (result) -+ goto remove_id; -+ - if (!ops->critical) - ops->critical = thermal_zone_device_critical; - -@@ -1248,7 +1259,6 @@ thermal_zone_device_register(const char *type, int trips, int mask, - /* A new thermal zone needs to be updated anyway. */ - atomic_set(&tz->need_update, 1); - -- dev_set_name(&tz->device, "thermal_zone%d", tz->id); - result = device_register(&tz->device); - if (result) - goto release_device; -diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c -index 6379f26a335f6..9233f7e744544 100644 ---- a/drivers/thermal/thermal_of.c -+++ b/drivers/thermal/thermal_of.c -@@ -89,7 +89,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz, - { - struct __thermal_zone *data = tz->devdata; - -- if (!data->ops->get_temp) -+ if (!data->ops || !data->ops->get_temp) - return -EINVAL; - - return data->ops->get_temp(data->sensor_data, temp); -@@ -186,6 +186,9 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, - { - struct __thermal_zone *data = tz->devdata; - -+ if (!data->ops || !data->ops->set_emul_temp) -+ return -EINVAL; -+ - return data->ops->set_emul_temp(data->sensor_data, temp); - } - -@@ -194,7 +197,7 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, - { - struct __thermal_zone *data = tz->devdata; - -- if (!data->ops->get_trend) -+ if (!data->ops || !data->ops->get_trend) - return -EINVAL; - - return data->ops->get_trend(data->sensor_data, trip, trend); -@@ -301,7 +304,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, - if (trip >= data->ntrips || trip < 0) - return -EDOM; - -- if (data->ops->set_trip_temp) { -+ if (data->ops && data->ops->set_trip_temp) { - int ret; - - ret = data->ops->set_trip_temp(data->sensor_data, trip, temp); -diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c -index f0bf01ea069ae..8ee7ce1206925 100644 ---- a/drivers/tty/hvc/hvc_xen.c -+++ b/drivers/tty/hvc/hvc_xen.c -@@ -37,6 +37,8 @@ struct xencons_info { - struct xenbus_device *xbdev; - struct xencons_interface *intf; - unsigned int evtchn; -+ XENCONS_RING_IDX out_cons; -+ unsigned int out_cons_same; - struct hvc_struct *hvc; - int irq; - int vtermno; -@@ -138,6 +140,8 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) - XENCONS_RING_IDX cons, prod; - int recv = 0; - struct xencons_info *xencons = vtermno_to_xencons(vtermno); -+ unsigned int eoiflag = 0; -+ - if (xencons == NULL) - return -EINVAL; - intf = xencons->intf; -@@ -157,7 +161,27 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) - mb(); /* read ring before consuming */ - intf->in_cons = cons; - -- notify_daemon(xencons); -+ /* -+ * When to mark interrupt having been spurious: -+ * - there was no new data to be read, and -+ * - the backend did not consume some output bytes, and -+ * - the previous round with no read data didn't see consumed bytes -+ * (we might have a race with an interrupt being in flight while -+ * updating xencons->out_cons, so account for that by allowing one -+ * round without any visible reason) -+ */ -+ if (intf->out_cons != xencons->out_cons) { -+ xencons->out_cons = intf->out_cons; -+ xencons->out_cons_same = 0; -+ } -+ if (recv) { -+ notify_daemon(xencons); -+ } else if (xencons->out_cons_same++ > 1) { -+ eoiflag = XEN_EOI_FLAG_SPURIOUS; -+ } -+ -+ xen_irq_lateeoi(xencons->irq, eoiflag); -+ - return recv; - } - -@@ -386,7 +410,7 @@ static int xencons_connect_backend(struct xenbus_device *dev, - if (ret) - return ret; - info->evtchn = evtchn; -- irq = bind_evtchn_to_irq(evtchn); -+ irq = bind_interdomain_evtchn_to_irq_lateeoi(dev, evtchn); - if (irq < 0) - return irq; - info->irq = irq; -@@ -550,7 +574,7 @@ static int __init xen_hvc_init(void) - return r; - - info = vtermno_to_xencons(HVC_COOKIE); -- info->irq = bind_evtchn_to_irq(info->evtchn); -+ info->irq = bind_evtchn_to_irq_lateeoi(info->evtchn); - } - if (info->irq < 0) - info->irq = 0; /* NO_IRQ */ -diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c -index 580a37b3fe1b9..166f651fde33a 100644 ---- a/drivers/tty/n_hdlc.c -+++ b/drivers/tty/n_hdlc.c -@@ -140,6 +140,8 @@ struct n_hdlc { - struct n_hdlc_buf_list rx_buf_list; - struct n_hdlc_buf_list tx_free_buf_list; - struct n_hdlc_buf_list rx_free_buf_list; -+ struct work_struct write_work; -+ struct tty_struct *tty_for_write_work; - }; - - /* -@@ -154,6 +156,7 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); - /* Local functions */ - - static struct n_hdlc *n_hdlc_alloc(void); -+static void n_hdlc_tty_write_work(struct work_struct *work); - - /* max frame size for memory allocations */ - static int maxframe = 4096; -@@ -210,6 +213,8 @@ static void n_hdlc_tty_close(struct tty_struct *tty) - wake_up_interruptible(&tty->read_wait); - wake_up_interruptible(&tty->write_wait); - -+ cancel_work_sync(&n_hdlc->write_work); -+ - n_hdlc_free_buf_list(&n_hdlc->rx_free_buf_list); - n_hdlc_free_buf_list(&n_hdlc->tx_free_buf_list); - n_hdlc_free_buf_list(&n_hdlc->rx_buf_list); -@@ -241,6 +246,8 @@ static int n_hdlc_tty_open(struct tty_struct *tty) - return -ENFILE; - } - -+ INIT_WORK(&n_hdlc->write_work, n_hdlc_tty_write_work); -+ n_hdlc->tty_for_write_work = tty; - tty->disc_data = n_hdlc; - tty->receive_room = 65536; - -@@ -334,6 +341,20 @@ check_again: - goto check_again; - } /* end of n_hdlc_send_frames() */ - -+/** -+ * n_hdlc_tty_write_work - Asynchronous callback for transmit wakeup -+ * @work: pointer to work_struct -+ * -+ * Called when low level device driver can accept more send data. -+ */ -+static void n_hdlc_tty_write_work(struct work_struct *work) -+{ -+ struct n_hdlc *n_hdlc = container_of(work, struct n_hdlc, write_work); -+ struct tty_struct *tty = n_hdlc->tty_for_write_work; -+ -+ n_hdlc_send_frames(n_hdlc, tty); -+} /* end of n_hdlc_tty_write_work() */ -+ - /** - * n_hdlc_tty_wakeup - Callback for transmit wakeup - * @tty: pointer to associated tty instance data -@@ -344,7 +365,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) - { - struct n_hdlc *n_hdlc = tty->disc_data; - -- n_hdlc_send_frames(n_hdlc, tty); -+ schedule_work(&n_hdlc->write_work); - } /* end of n_hdlc_tty_wakeup() */ - - /** -diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c -index 7f656fac503fe..5163d60756b73 100644 ---- a/drivers/tty/serial/8250/8250_bcm7271.c -+++ b/drivers/tty/serial/8250/8250_bcm7271.c -@@ -237,6 +237,7 @@ struct brcmuart_priv { - u32 rx_err; - u32 rx_timeout; - u32 rx_abort; -+ u32 saved_mctrl; - }; - - static struct dentry *brcmuart_debugfs_root; -@@ -1133,16 +1134,27 @@ static int brcmuart_remove(struct platform_device *pdev) - static int __maybe_unused brcmuart_suspend(struct device *dev) - { - struct brcmuart_priv *priv = dev_get_drvdata(dev); -+ struct uart_8250_port *up = serial8250_get_port(priv->line); -+ struct uart_port *port = &up->port; - - serial8250_suspend_port(priv->line); - clk_disable_unprepare(priv->baud_mux_clk); - -+ /* -+ * This will prevent resume from enabling RTS before the -+ * baud rate has been resored. -+ */ -+ priv->saved_mctrl = port->mctrl; -+ port->mctrl = 0; -+ - return 0; - } - - static int __maybe_unused brcmuart_resume(struct device *dev) - { - struct brcmuart_priv *priv = dev_get_drvdata(dev); -+ struct uart_8250_port *up = serial8250_get_port(priv->line); -+ struct uart_port *port = &up->port; - int ret; - - ret = clk_prepare_enable(priv->baud_mux_clk); -@@ -1165,6 +1177,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev) - start_rx_dma(serial8250_get_port(priv->line)); - } - serial8250_resume_port(priv->line); -+ port->mctrl = priv->saved_mctrl; - return 0; - } - -diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c -index a3a0154da567d..49559731bbcf1 100644 ---- a/drivers/tty/serial/8250/8250_dw.c -+++ b/drivers/tty/serial/8250/8250_dw.c -@@ -726,7 +726,7 @@ static struct platform_driver dw8250_platform_driver = { - .name = "dw-apb-uart", - .pm = &dw8250_pm_ops, - .of_match_table = dw8250_of_match, -- .acpi_match_table = ACPI_PTR(dw8250_acpi_match), -+ .acpi_match_table = dw8250_acpi_match, - }, - .probe = dw8250_probe, - .remove = dw8250_remove, -diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c -index 31c9e83ea3cb2..251f0018ae8ca 100644 ---- a/drivers/tty/serial/8250/8250_fintek.c -+++ b/drivers/tty/serial/8250/8250_fintek.c -@@ -290,25 +290,6 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) - } - } - --static void fintek_8250_goto_highspeed(struct uart_8250_port *uart, -- struct fintek_8250 *pdata) --{ -- sio_write_reg(pdata, LDN, pdata->index); -- -- switch (pdata->pid) { -- case CHIP_ID_F81966: -- case CHIP_ID_F81866: /* set uart clock for high speed serial mode */ -- sio_write_mask_reg(pdata, F81866_UART_CLK, -- F81866_UART_CLK_MASK, -- F81866_UART_CLK_14_769MHZ); -- -- uart->port.uartclk = 921600 * 16; -- break; -- default: /* leave clock speed untouched */ -- break; -- } --} -- - static void fintek_8250_set_termios(struct uart_port *port, - struct ktermios *termios, - struct ktermios *old) -@@ -430,7 +411,6 @@ static int probe_setup_port(struct fintek_8250 *pdata, - - fintek_8250_set_irq_mode(pdata, level_mode); - fintek_8250_set_max_fifo(pdata); -- fintek_8250_goto_highspeed(uart, pdata); - - fintek_8250_exit_key(addr[i]); - -diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c -index 726912b16a559..f7d89440076a1 100644 ---- a/drivers/tty/serial/8250/8250_pci.c -+++ b/drivers/tty/serial/8250/8250_pci.c -@@ -1349,29 +1349,33 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud, - { - int scr; - int lcr; -- int actual_baud; -- int tolerance; - -- for (scr = 5 ; scr <= 15 ; scr++) { -- actual_baud = 921600 * 16 / scr; -- tolerance = actual_baud / 50; -+ for (scr = 16; scr > 4; scr--) { -+ unsigned int maxrate = port->uartclk / scr; -+ unsigned int divisor = max(maxrate / baud, 1U); -+ int delta = maxrate / divisor - baud; - -- if ((baud < actual_baud + tolerance) && -- (baud > actual_baud - tolerance)) { -+ if (baud > maxrate + baud / 50) -+ continue; - -+ if (delta > baud / 50) -+ divisor++; -+ -+ if (divisor > 0xffff) -+ continue; -+ -+ /* Update delta due to possible divisor change */ -+ delta = maxrate / divisor - baud; -+ if (abs(delta) < baud / 50) { - lcr = serial_port_in(port, UART_LCR); - serial_port_out(port, UART_LCR, lcr | 0x80); -- -- serial_port_out(port, UART_DLL, 1); -- serial_port_out(port, UART_DLM, 0); -+ serial_port_out(port, UART_DLL, divisor & 0xff); -+ serial_port_out(port, UART_DLM, divisor >> 8 & 0xff); - serial_port_out(port, 2, 16 - scr); - serial_port_out(port, UART_LCR, lcr); - return; -- } else if (baud > actual_baud) { -- break; - } - } -- serial8250_do_set_divisor(port, baud, quot, quot_frac); - } - static int pci_pericom_setup(struct serial_private *priv, - const struct pciserial_board *board, -@@ -2317,12 +2321,19 @@ static struct pci_serial_quirk pci_serial_quirks[] = { - .setup = pci_pericom_setup_four_at_eight, - }, - { -- .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, -+ .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, -+ { -+ .vendor = PCI_VENDOR_ID_ACCESIO, -+ .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID, -+ .setup = pci_pericom_setup_four_at_eight, -+ }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, -diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c -index 66374704747ec..ec88b706e882f 100644 ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -2024,13 +2024,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) - struct uart_8250_port *up = up_to_u8250p(port); - unsigned char mcr; - -- if (port->rs485.flags & SER_RS485_ENABLED) { -- if (serial8250_in_MCR(up) & UART_MCR_RTS) -- mctrl |= TIOCM_RTS; -- else -- mctrl &= ~TIOCM_RTS; -- } -- - mcr = serial8250_TIOCM_to_MCR(mctrl); - - mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; -@@ -2696,21 +2689,32 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, - void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) - { - struct uart_8250_port *up = up_to_u8250p(port); -+ struct tty_port *tport = &port->state->port; - unsigned int baud, quot, frac = 0; - struct ktermios *termios; -+ struct tty_struct *tty; - unsigned long flags; - -- mutex_lock(&port->state->port.mutex); -+ tty = tty_port_tty_get(tport); -+ if (!tty) { -+ mutex_lock(&tport->mutex); -+ port->uartclk = uartclk; -+ mutex_unlock(&tport->mutex); -+ return; -+ } -+ -+ down_write(&tty->termios_rwsem); -+ mutex_lock(&tport->mutex); - - if (port->uartclk == uartclk) - goto out_lock; - - port->uartclk = uartclk; - -- if (!tty_port_initialized(&port->state->port)) -+ if (!tty_port_initialized(tport)) - goto out_lock; - -- termios = &port->state->port.tty->termios; -+ termios = &tty->termios; - - baud = serial8250_get_baud_rate(port, termios, NULL); - quot = serial8250_get_divisor(port, baud, &frac); -@@ -2727,7 +2731,9 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) - serial8250_rpm_put(up); - - out_lock: -- mutex_unlock(&port->state->port.mutex); -+ mutex_unlock(&tport->mutex); -+ up_write(&tty->termios_rwsem); -+ tty_kref_put(tty); - } - EXPORT_SYMBOL_GPL(serial8250_update_uartclk); - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index d361cd84ff8cf..52518a606c06a 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2947,6 +2947,7 @@ MODULE_DEVICE_TABLE(of, sbsa_uart_of_match); - - static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = { - { "ARMH0011", 0 }, -+ { "ARMHB000", 0 }, - {}, - }; - MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match); -diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c -index c719aa2b18328..d6d3db9c3b1f8 100644 ---- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c -+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c -@@ -1090,6 +1090,7 @@ static void cpm_put_poll_char(struct uart_port *port, - cpm_uart_early_write(pinfo, ch, 1, false); - } - -+#ifdef CONFIG_SERIAL_CPM_CONSOLE - static struct uart_port *udbg_port; - - static void udbg_cpm_putc(char c) -@@ -1114,6 +1115,7 @@ static int udbg_cpm_getc(void) - cpu_relax(); - return c; - } -+#endif /* CONFIG_SERIAL_CPM_CONSOLE */ - - #endif /* CONFIG_CONSOLE_POLL */ - -diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c -index b1e7190ae4836..ac5112def40d1 100644 ---- a/drivers/tty/serial/fsl_lpuart.c -+++ b/drivers/tty/serial/fsl_lpuart.c -@@ -2625,6 +2625,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); - OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); - OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); - OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); -+OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); - EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); - EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); - -diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c -index 8b121cd869e94..51a9f9423b1a6 100644 ---- a/drivers/tty/serial/imx.c -+++ b/drivers/tty/serial/imx.c -@@ -2017,7 +2017,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) - * If the port was already initialised (eg, by a boot loader), - * try to determine the current setup. - */ --static void __init -+static void - imx_uart_console_get_options(struct imx_port *sport, int *baud, - int *parity, int *bits) - { -@@ -2076,7 +2076,7 @@ imx_uart_console_get_options(struct imx_port *sport, int *baud, - } - } - --static int __init -+static int - imx_uart_console_setup(struct console *co, char *options) - { - struct imx_port *sport; -diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c -index dbc0559a91575..2941659e52747 100644 ---- a/drivers/tty/serial/liteuart.c -+++ b/drivers/tty/serial/liteuart.c -@@ -270,8 +270,10 @@ static int liteuart_probe(struct platform_device *pdev) - - /* get membase */ - port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); -- if (IS_ERR(port->membase)) -- return PTR_ERR(port->membase); -+ if (IS_ERR(port->membase)) { -+ ret = PTR_ERR(port->membase); -+ goto err_erase_id; -+ } - - /* values not from device tree */ - port->dev = &pdev->dev; -@@ -285,7 +287,18 @@ static int liteuart_probe(struct platform_device *pdev) - port->line = dev_id; - spin_lock_init(&port->lock); - -- return uart_add_one_port(&liteuart_driver, &uart->port); -+ platform_set_drvdata(pdev, port); -+ -+ ret = uart_add_one_port(&liteuart_driver, &uart->port); -+ if (ret) -+ goto err_erase_id; -+ -+ return 0; -+ -+err_erase_id: -+ xa_erase(&liteuart_array, uart->id); -+ -+ return ret; - } - - static int liteuart_remove(struct platform_device *pdev) -@@ -293,6 +306,7 @@ static int liteuart_remove(struct platform_device *pdev) - struct uart_port *port = platform_get_drvdata(pdev); - struct liteuart_port *uart = to_liteuart_port(port); - -+ uart_remove_one_port(&liteuart_driver, port); - xa_erase(&liteuart_array, uart->id); - - return 0; -diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c -index fcef7a961430b..489d19274f9ad 100644 ---- a/drivers/tty/serial/msm_serial.c -+++ b/drivers/tty/serial/msm_serial.c -@@ -598,6 +598,9 @@ static void msm_start_rx_dma(struct msm_port *msm_port) - u32 val; - int ret; - -+ if (IS_ENABLED(CONFIG_CONSOLE_POLL)) -+ return; -+ - if (!dma->chan) - return; - -diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c -index 45e2e4109acd0..b6223fab0687d 100644 ---- a/drivers/tty/serial/serial-tegra.c -+++ b/drivers/tty/serial/serial-tegra.c -@@ -1506,7 +1506,7 @@ static struct tegra_uart_chip_data tegra20_uart_chip_data = { - .fifo_mode_enable_status = false, - .uart_max_port = 5, - .max_dma_burst_bytes = 4, -- .error_tolerance_low_range = 0, -+ .error_tolerance_low_range = -4, - .error_tolerance_high_range = 4, - }; - -@@ -1517,7 +1517,7 @@ static struct tegra_uart_chip_data tegra30_uart_chip_data = { - .fifo_mode_enable_status = false, - .uart_max_port = 5, - .max_dma_burst_bytes = 4, -- .error_tolerance_low_range = 0, -+ .error_tolerance_low_range = -4, - .error_tolerance_high_range = 4, - }; - -diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c -index 0e2e35ab64c79..61e3dd0222af1 100644 ---- a/drivers/tty/serial/serial_core.c -+++ b/drivers/tty/serial/serial_core.c -@@ -222,7 +222,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, - if (retval == 0) { - if (uart_console(uport) && uport->cons->cflag) { - tty->termios.c_cflag = uport->cons->cflag; -+ tty->termios.c_ispeed = uport->cons->ispeed; -+ tty->termios.c_ospeed = uport->cons->ospeed; - uport->cons->cflag = 0; -+ uport->cons->ispeed = 0; -+ uport->cons->ospeed = 0; - } - /* - * Initialise the hardware port settings. -@@ -290,8 +294,11 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) - /* - * Turn off DTR and RTS early. - */ -- if (uport && uart_console(uport) && tty) -+ if (uport && uart_console(uport) && tty) { - uport->cons->cflag = tty->termios.c_cflag; -+ uport->cons->ispeed = tty->termios.c_ispeed; -+ uport->cons->ospeed = tty->termios.c_ospeed; -+ } - - if (!tty || C_HUPCL(tty)) - uart_port_dtr_rts(uport, 0); -@@ -1068,6 +1075,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) - goto out; - - if (!tty_io_error(tty)) { -+ if (uport->rs485.flags & SER_RS485_ENABLED) { -+ set &= ~TIOCM_RTS; -+ clear &= ~TIOCM_RTS; -+ } -+ - uart_update_mctrl(uport, set, clear); - ret = 0; - } -@@ -1542,6 +1554,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) - { - struct uart_state *state = container_of(port, struct uart_state, port); - struct uart_port *uport = uart_port_check(state); -+ char *buf; - - /* - * At this point, we stop accepting input. To do this, we -@@ -1563,8 +1576,18 @@ static void uart_tty_port_shutdown(struct tty_port *port) - */ - tty_port_set_suspended(port, 0); - -- uart_change_pm(state, UART_PM_STATE_OFF); -+ /* -+ * Free the transmit buffer. -+ */ -+ spin_lock_irq(&uport->lock); -+ buf = state->xmit.buf; -+ state->xmit.buf = NULL; -+ spin_unlock_irq(&uport->lock); - -+ if (buf) -+ free_page((unsigned long)buf); -+ -+ uart_change_pm(state, UART_PM_STATE_OFF); - } - - static void uart_wait_until_sent(struct tty_struct *tty, int timeout) -@@ -2094,8 +2117,11 @@ uart_set_options(struct uart_port *port, struct console *co, - * Allow the setting of the UART parameters with a NULL console - * too: - */ -- if (co) -+ if (co) { - co->cflag = termios.c_cflag; -+ co->ispeed = termios.c_ispeed; -+ co->ospeed = termios.c_ospeed; -+ } - - return 0; - } -@@ -2229,6 +2255,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) - */ - memset(&termios, 0, sizeof(struct ktermios)); - termios.c_cflag = uport->cons->cflag; -+ termios.c_ispeed = uport->cons->ispeed; -+ termios.c_ospeed = uport->cons->ospeed; - - /* - * If that's unset, use the tty termios setting. -diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c -index 962e522ccc45c..d5e243908d9fd 100644 ---- a/drivers/tty/serial/xilinx_uartps.c -+++ b/drivers/tty/serial/xilinx_uartps.c -@@ -601,9 +601,10 @@ static void cdns_uart_start_tx(struct uart_port *port) - if (uart_circ_empty(&port->state->xmit)) - return; - -+ writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); -+ - cdns_uart_handle_tx(port); - -- writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); - /* Enable the TX Empty interrupt */ - writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); - } -diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c -index 635d0af229b72..6c7e65b1d9a1c 100644 ---- a/drivers/tty/tty_buffer.c -+++ b/drivers/tty/tty_buffer.c -@@ -544,6 +544,9 @@ static void flush_to_ldisc(struct work_struct *work) - if (!count) - break; - head->read += count; -+ -+ if (need_resched()) -+ cond_resched(); - } - - mutex_unlock(&buf->lock); -diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c -index 1f3b4a1422126..f9af7ebe003d7 100644 ---- a/drivers/usb/cdns3/cdns3-gadget.c -+++ b/drivers/usb/cdns3/cdns3-gadget.c -@@ -337,19 +337,6 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep) - cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); - } - --static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) --{ -- struct cdns3_endpoint *priv_ep = priv_req->priv_ep; -- int current_trb = priv_req->start_trb; -- -- while (current_trb != priv_req->end_trb) { -- cdns3_ep_inc_deq(priv_ep); -- current_trb = priv_ep->dequeue; -- } -- -- cdns3_ep_inc_deq(priv_ep); --} -- - /** - * cdns3_allow_enable_l1 - enable/disable permits to transition to L1. - * @priv_dev: Extended gadget object -@@ -1517,10 +1504,11 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, - - trb = priv_ep->trb_pool + priv_ep->dequeue; - -- /* Request was dequeued and TRB was changed to TRB_LINK. */ -- if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { -+ /* The TRB was changed as link TRB, and the request was handled at ep_dequeue */ -+ while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { - trace_cdns3_complete_trb(priv_ep, trb); -- cdns3_move_deq_to_next_trb(priv_req); -+ cdns3_ep_inc_deq(priv_ep); -+ trb = priv_ep->trb_pool + priv_ep->dequeue; - } - - if (!request->stream_id) { -diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c -index 27df0c6978978..e85bf768c66da 100644 ---- a/drivers/usb/cdns3/cdnsp-gadget.c -+++ b/drivers/usb/cdns3/cdnsp-gadget.c -@@ -1541,15 +1541,27 @@ static int cdnsp_gadget_pullup(struct usb_gadget *gadget, int is_on) - { - struct cdnsp_device *pdev = gadget_to_cdnsp(gadget); - struct cdns *cdns = dev_get_drvdata(pdev->dev); -+ unsigned long flags; - - trace_cdnsp_pullup(is_on); - -+ /* -+ * Disable events handling while controller is being -+ * enabled/disabled. -+ */ -+ disable_irq(cdns->dev_irq); -+ spin_lock_irqsave(&pdev->lock, flags); -+ - if (!is_on) { - cdnsp_reset_device(pdev); - cdns_clear_vbus(cdns); - } else { - cdns_set_vbus(cdns); - } -+ -+ spin_unlock_irqrestore(&pdev->lock, flags); -+ enable_irq(cdns->dev_irq); -+ - return 0; - } - -diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c -index ad9aee3f1e398..97866bfb2da9d 100644 ---- a/drivers/usb/cdns3/cdnsp-mem.c -+++ b/drivers/usb/cdns3/cdnsp-mem.c -@@ -987,6 +987,9 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev, - - /* Set up the endpoint ring. */ - pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags); -+ if (!pep->ring) -+ return -ENOMEM; -+ - pep->skip = false; - - /* Fill the endpoint context */ -diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c -index 1b1438457fb04..e45c3d6e1536c 100644 ---- a/drivers/usb/cdns3/cdnsp-ring.c -+++ b/drivers/usb/cdns3/cdnsp-ring.c -@@ -1029,6 +1029,8 @@ static void cdnsp_process_ctrl_td(struct cdnsp_device *pdev, - return; - } - -+ *status = 0; -+ - cdnsp_finish_td(pdev, td, event, pep, status); - } - -@@ -1523,7 +1525,14 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data) - spin_lock_irqsave(&pdev->lock, flags); - - if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) { -- cdnsp_died(pdev); -+ /* -+ * While removing or stopping driver there may still be deferred -+ * not handled interrupt which should not be treated as error. -+ * Driver should simply ignore it. -+ */ -+ if (pdev->gadget_driver) -+ cdnsp_died(pdev); -+ - spin_unlock_irqrestore(&pdev->lock, flags); - return IRQ_HANDLED; - } -diff --git a/drivers/usb/cdns3/cdnsp-trace.h b/drivers/usb/cdns3/cdnsp-trace.h -index 6a2571c6aa9ed..5983dfb996537 100644 ---- a/drivers/usb/cdns3/cdnsp-trace.h -+++ b/drivers/usb/cdns3/cdnsp-trace.h -@@ -57,9 +57,9 @@ DECLARE_EVENT_CLASS(cdnsp_log_ep, - __entry->first_prime_det = pep->stream_info.first_prime_det; - __entry->drbls_count = pep->stream_info.drbls_count; - ), -- TP_printk("%s: SID: %08x ep state: %x stream: enabled: %d num %d " -+ TP_printk("%s: SID: %08x, ep state: %x, stream: enabled: %d num %d " - "tds %d, first prime: %d drbls %d", -- __get_str(name), __entry->state, __entry->stream_id, -+ __get_str(name), __entry->stream_id, __entry->state, - __entry->enabled, __entry->num_streams, __entry->td_count, - __entry->first_prime_det, __entry->drbls_count) - ); -diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c -index f1d100671ee6a..097142ffb1842 100644 ---- a/drivers/usb/chipidea/ci_hdrc_imx.c -+++ b/drivers/usb/chipidea/ci_hdrc_imx.c -@@ -420,15 +420,15 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) - data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); - if (IS_ERR(data->phy)) { - ret = PTR_ERR(data->phy); -- if (ret == -ENODEV) { -- data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0); -- if (IS_ERR(data->phy)) { -- ret = PTR_ERR(data->phy); -- if (ret == -ENODEV) -- data->phy = NULL; -- else -- goto err_clk; -- } -+ if (ret != -ENODEV) -+ goto err_clk; -+ data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0); -+ if (IS_ERR(data->phy)) { -+ ret = PTR_ERR(data->phy); -+ if (ret == -ENODEV) -+ data->phy = NULL; -+ else -+ goto err_clk; - } - } - -diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c -index 2b18f5088ae4a..a56f06368d142 100644 ---- a/drivers/usb/chipidea/core.c -+++ b/drivers/usb/chipidea/core.c -@@ -514,7 +514,7 @@ int hw_device_reset(struct ci_hdrc *ci) - return 0; - } - --static irqreturn_t ci_irq(int irq, void *data) -+static irqreturn_t ci_irq_handler(int irq, void *data) - { - struct ci_hdrc *ci = data; - irqreturn_t ret = IRQ_NONE; -@@ -567,6 +567,15 @@ static irqreturn_t ci_irq(int irq, void *data) - return ret; - } - -+static void ci_irq(struct ci_hdrc *ci) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ ci_irq_handler(ci->irq, ci); -+ local_irq_restore(flags); -+} -+ - static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, - void *ptr) - { -@@ -576,7 +585,7 @@ static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, - cbl->connected = event; - cbl->changed = true; - -- ci_irq(ci->irq, ci); -+ ci_irq(ci); - return NOTIFY_DONE; - } - -@@ -617,7 +626,7 @@ static int ci_usb_role_switch_set(struct usb_role_switch *sw, - if (cable) { - cable->changed = true; - cable->connected = false; -- ci_irq(ci->irq, ci); -+ ci_irq(ci); - spin_unlock_irqrestore(&ci->lock, flags); - if (ci->wq && role != USB_ROLE_NONE) - flush_workqueue(ci->wq); -@@ -635,7 +644,7 @@ static int ci_usb_role_switch_set(struct usb_role_switch *sw, - if (cable) { - cable->changed = true; - cable->connected = true; -- ci_irq(ci->irq, ci); -+ ci_irq(ci); - } - spin_unlock_irqrestore(&ci->lock, flags); - pm_runtime_put_sync(ci->dev); -@@ -1174,7 +1183,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) - } - } - -- ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, -+ ret = devm_request_irq(dev, ci->irq, ci_irq_handler, IRQF_SHARED, - ci->platdata->name, ci); - if (ret) - goto stop; -@@ -1295,11 +1304,11 @@ static void ci_extcon_wakeup_int(struct ci_hdrc *ci) - - if (!IS_ERR(cable_id->edev) && ci->is_otg && - (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) -- ci_irq(ci->irq, ci); -+ ci_irq(ci); - - if (!IS_ERR(cable_vbus->edev) && ci->is_otg && - (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) -- ci_irq(ci->irq, ci); -+ ci_irq(ci); - } - - static int ci_controller_resume(struct device *dev) -diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c -index b199eb65f3780..00e28456e4cc2 100644 ---- a/drivers/usb/core/config.c -+++ b/drivers/usb/core/config.c -@@ -406,7 +406,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, - * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0 - * (see the end of section 5.6.3), so don't warn about them. - */ -- maxp = usb_endpoint_maxp(&endpoint->desc); -+ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize); - if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) { - dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n", - cfgno, inum, asnum, d->bEndpointAddress); -@@ -422,9 +422,9 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, - maxpacket_maxes = full_speed_maxpacket_maxes; - break; - case USB_SPEED_HIGH: -- /* Bits 12..11 are allowed only for HS periodic endpoints */ -+ /* Multiple-transactions bits are allowed only for HS periodic endpoints */ - if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) { -- i = maxp & (BIT(12) | BIT(11)); -+ i = maxp & USB_EP_MAXP_MULT_MASK; - maxp &= ~i; - } - fallthrough; -diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c -index 9618ba622a2d0..fa66e6e587928 100644 ---- a/drivers/usb/core/devio.c -+++ b/drivers/usb/core/devio.c -@@ -32,6 +32,7 @@ - #include <linux/usb.h> - #include <linux/usbdevice_fs.h> - #include <linux/usb/hcd.h> /* for usbcore internals */ -+#include <linux/usb/quirks.h> - #include <linux/cdev.h> - #include <linux/notifier.h> - #include <linux/security.h> -@@ -1102,14 +1103,55 @@ static int usbdev_release(struct inode *inode, struct file *file) - return 0; - } - -+static void usbfs_blocking_completion(struct urb *urb) -+{ -+ complete((struct completion *) urb->context); -+} -+ -+/* -+ * Much like usb_start_wait_urb, but returns status separately from -+ * actual_length and uses a killable wait. -+ */ -+static int usbfs_start_wait_urb(struct urb *urb, int timeout, -+ unsigned int *actlen) -+{ -+ DECLARE_COMPLETION_ONSTACK(ctx); -+ unsigned long expire; -+ int rc; -+ -+ urb->context = &ctx; -+ urb->complete = usbfs_blocking_completion; -+ *actlen = 0; -+ rc = usb_submit_urb(urb, GFP_KERNEL); -+ if (unlikely(rc)) -+ return rc; -+ -+ expire = (timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT); -+ rc = wait_for_completion_killable_timeout(&ctx, expire); -+ if (rc <= 0) { -+ usb_kill_urb(urb); -+ *actlen = urb->actual_length; -+ if (urb->status != -ENOENT) -+ ; /* Completed before it was killed */ -+ else if (rc < 0) -+ return -EINTR; -+ else -+ return -ETIMEDOUT; -+ } -+ *actlen = urb->actual_length; -+ return urb->status; -+} -+ - static int do_proc_control(struct usb_dev_state *ps, - struct usbdevfs_ctrltransfer *ctrl) - { - struct usb_device *dev = ps->dev; - unsigned int tmo; - unsigned char *tbuf; -- unsigned wLength; -+ unsigned int wLength, actlen; - int i, pipe, ret; -+ struct urb *urb = NULL; -+ struct usb_ctrlrequest *dr = NULL; - - ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest, - ctrl->wIndex); -@@ -1122,51 +1164,63 @@ static int do_proc_control(struct usb_dev_state *ps, - sizeof(struct usb_ctrlrequest)); - if (ret) - return ret; -+ -+ ret = -ENOMEM; - tbuf = (unsigned char *)__get_free_page(GFP_KERNEL); -- if (!tbuf) { -- ret = -ENOMEM; -+ if (!tbuf) - goto done; -- } -+ urb = usb_alloc_urb(0, GFP_NOIO); -+ if (!urb) -+ goto done; -+ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); -+ if (!dr) -+ goto done; -+ -+ dr->bRequestType = ctrl->bRequestType; -+ dr->bRequest = ctrl->bRequest; -+ dr->wValue = cpu_to_le16(ctrl->wValue); -+ dr->wIndex = cpu_to_le16(ctrl->wIndex); -+ dr->wLength = cpu_to_le16(ctrl->wLength); -+ - tmo = ctrl->timeout; - snoop(&dev->dev, "control urb: bRequestType=%02x " - "bRequest=%02x wValue=%04x " - "wIndex=%04x wLength=%04x\n", - ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, - ctrl->wIndex, ctrl->wLength); -- if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) { -+ -+ if ((ctrl->bRequestType & USB_DIR_IN) && wLength) { - pipe = usb_rcvctrlpipe(dev, 0); -- snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0); -+ usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf, -+ wLength, NULL, NULL); -+ snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, NULL, 0); - - usb_unlock_device(dev); -- i = usb_control_msg(dev, pipe, ctrl->bRequest, -- ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, -- tbuf, ctrl->wLength, tmo); -+ i = usbfs_start_wait_urb(urb, tmo, &actlen); - usb_lock_device(dev); -- snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, -- tbuf, max(i, 0)); -- if ((i > 0) && ctrl->wLength) { -- if (copy_to_user(ctrl->data, tbuf, i)) { -+ snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen); -+ if (!i && actlen) { -+ if (copy_to_user(ctrl->data, tbuf, actlen)) { - ret = -EFAULT; -- goto done; -+ goto recv_fault; - } - } - } else { -- if (ctrl->wLength) { -- if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) { -+ if (wLength) { -+ if (copy_from_user(tbuf, ctrl->data, wLength)) { - ret = -EFAULT; - goto done; - } - } - pipe = usb_sndctrlpipe(dev, 0); -- snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, -- tbuf, ctrl->wLength); -+ usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf, -+ wLength, NULL, NULL); -+ snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, tbuf, wLength); - - usb_unlock_device(dev); -- i = usb_control_msg(dev, pipe, ctrl->bRequest, -- ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, -- tbuf, ctrl->wLength, tmo); -+ i = usbfs_start_wait_urb(urb, tmo, &actlen); - usb_lock_device(dev); -- snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); -+ snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0); - } - if (i < 0 && i != -EPIPE) { - dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " -@@ -1174,8 +1228,15 @@ static int do_proc_control(struct usb_dev_state *ps, - current->comm, ctrl->bRequestType, ctrl->bRequest, - ctrl->wLength, i); - } -- ret = i; -+ ret = (i < 0 ? i : actlen); -+ -+ recv_fault: -+ /* Linger a bit, prior to the next control message. */ -+ if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) -+ msleep(200); - done: -+ kfree(dr); -+ usb_free_urb(urb); - free_page((unsigned long) tbuf); - usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) + - sizeof(struct usb_ctrlrequest)); -@@ -1195,10 +1256,11 @@ static int do_proc_bulk(struct usb_dev_state *ps, - struct usbdevfs_bulktransfer *bulk) - { - struct usb_device *dev = ps->dev; -- unsigned int tmo, len1, pipe; -- int len2; -+ unsigned int tmo, len1, len2, pipe; - unsigned char *tbuf; - int i, ret; -+ struct urb *urb = NULL; -+ struct usb_host_endpoint *ep; - - ret = findintfep(ps->dev, bulk->ep); - if (ret < 0) -@@ -1206,14 +1268,17 @@ static int do_proc_bulk(struct usb_dev_state *ps, - ret = checkintf(ps, ret); - if (ret) - return ret; -+ -+ len1 = bulk->len; -+ if (len1 < 0 || len1 >= (INT_MAX - sizeof(struct urb))) -+ return -EINVAL; -+ - if (bulk->ep & USB_DIR_IN) - pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f); - else - pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f); -- if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN))) -- return -EINVAL; -- len1 = bulk->len; -- if (len1 >= (INT_MAX - sizeof(struct urb))) -+ ep = usb_pipe_endpoint(dev, pipe); -+ if (!ep || !usb_endpoint_maxp(&ep->desc)) - return -EINVAL; - ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); - if (ret) -@@ -1223,17 +1288,29 @@ static int do_proc_bulk(struct usb_dev_state *ps, - * len1 can be almost arbitrarily large. Don't WARN if it's - * too big, just fail the request. - */ -+ ret = -ENOMEM; - tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN); -- if (!tbuf) { -- ret = -ENOMEM; -+ if (!tbuf) -+ goto done; -+ urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!urb) - goto done; -+ -+ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT) { -+ pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); -+ usb_fill_int_urb(urb, dev, pipe, tbuf, len1, -+ NULL, NULL, ep->desc.bInterval); -+ } else { -+ usb_fill_bulk_urb(urb, dev, pipe, tbuf, len1, NULL, NULL); - } -+ - tmo = bulk->timeout; - if (bulk->ep & 0x80) { - snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); - - usb_unlock_device(dev); -- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); -+ i = usbfs_start_wait_urb(urb, tmo, &len2); - usb_lock_device(dev); - snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2); - -@@ -1253,12 +1330,13 @@ static int do_proc_bulk(struct usb_dev_state *ps, - snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1); - - usb_unlock_device(dev); -- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); -+ i = usbfs_start_wait_urb(urb, tmo, &len2); - usb_lock_device(dev); - snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0); - } - ret = (i < 0 ? i : len2); - done: -+ usb_free_urb(urb); - kfree(tbuf); - usbfs_decrease_memory_usage(len1 + sizeof(struct urb)); - return ret; -diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index 7ee6e4cc0d89e..00d35fe1fef0b 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -2795,7 +2795,6 @@ int usb_add_hcd(struct usb_hcd *hcd, - { - int retval; - struct usb_device *rhdev; -- struct usb_hcd *shared_hcd; - - if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) { - hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev); -@@ -2956,26 +2955,13 @@ int usb_add_hcd(struct usb_hcd *hcd, - goto err_hcd_driver_start; - } - -- /* starting here, usbcore will pay attention to the shared HCD roothub */ -- shared_hcd = hcd->shared_hcd; -- if (!usb_hcd_is_primary_hcd(hcd) && shared_hcd && HCD_DEFER_RH_REGISTER(shared_hcd)) { -- retval = register_root_hub(shared_hcd); -- if (retval != 0) -- goto err_register_root_hub; -- -- if (shared_hcd->uses_new_polling && HCD_POLL_RH(shared_hcd)) -- usb_hcd_poll_rh_status(shared_hcd); -- } -- - /* starting here, usbcore will pay attention to this root hub */ -- if (!HCD_DEFER_RH_REGISTER(hcd)) { -- retval = register_root_hub(hcd); -- if (retval != 0) -- goto err_register_root_hub; -+ retval = register_root_hub(hcd); -+ if (retval != 0) -+ goto err_register_root_hub; - -- if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) -- usb_hcd_poll_rh_status(hcd); -- } -+ if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) -+ usb_hcd_poll_rh_status(hcd); - - return retval; - -@@ -3013,7 +2999,6 @@ EXPORT_SYMBOL_GPL(usb_add_hcd); - void usb_remove_hcd(struct usb_hcd *hcd) - { - struct usb_device *rhdev = hcd->self.root_hub; -- bool rh_registered; - - dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); - -@@ -3024,7 +3009,6 @@ void usb_remove_hcd(struct usb_hcd *hcd) - - dev_dbg(hcd->self.controller, "roothub graceful disconnect\n"); - spin_lock_irq (&hcd_root_hub_lock); -- rh_registered = hcd->rh_registered; - hcd->rh_registered = 0; - spin_unlock_irq (&hcd_root_hub_lock); - -@@ -3034,8 +3018,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) - cancel_work_sync(&hcd->died_work); - - mutex_lock(&usb_bus_idr_lock); -- if (rh_registered) -- usb_disconnect(&rhdev); /* Sets rhdev to NULL */ -+ usb_disconnect(&rhdev); /* Sets rhdev to NULL */ - mutex_unlock(&usb_bus_idr_lock); - - /* -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 86658a81d2844..00070a8a65079 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4700,8 +4700,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - if (oldspeed == USB_SPEED_LOW) - delay = HUB_LONG_RESET_TIME; - -- mutex_lock(hcd->address0_mutex); -- - /* Reset the device; full speed may morph to high speed */ - /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ - retval = hub_port_reset(hub, port1, udev, delay, false); -@@ -5016,7 +5014,6 @@ fail: - hub_port_disable(hub, port1, 0); - update_devnum(udev, devnum); /* for disconnect processing */ - } -- mutex_unlock(hcd->address0_mutex); - return retval; - } - -@@ -5191,6 +5188,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - struct usb_port *port_dev = hub->ports[port1 - 1]; - struct usb_device *udev = port_dev->child; - static int unreliable_port = -1; -+ bool retry_locked; - - /* Disconnect any existing devices under this port */ - if (udev) { -@@ -5246,8 +5244,11 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - unit_load = 100; - - status = 0; -- for (i = 0; i < PORT_INIT_TRIES; i++) { - -+ for (i = 0; i < PORT_INIT_TRIES; i++) { -+ usb_lock_port(port_dev); -+ mutex_lock(hcd->address0_mutex); -+ retry_locked = true; - /* reallocate for each attempt, since references - * to the previous one can escape in various ways - */ -@@ -5255,6 +5256,8 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - if (!udev) { - dev_err(&port_dev->dev, - "couldn't allocate usb_device\n"); -+ mutex_unlock(hcd->address0_mutex); -+ usb_unlock_port(port_dev); - goto done; - } - -@@ -5276,12 +5279,14 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - } - - /* reset (non-USB 3.0 devices) and get descriptor */ -- usb_lock_port(port_dev); - status = hub_port_init(hub, udev, port1, i); -- usb_unlock_port(port_dev); - if (status < 0) - goto loop; - -+ mutex_unlock(hcd->address0_mutex); -+ usb_unlock_port(port_dev); -+ retry_locked = false; -+ - if (udev->quirks & USB_QUIRK_DELAY_INIT) - msleep(2000); - -@@ -5374,6 +5379,10 @@ loop: - usb_ep0_reinit(udev); - release_devnum(udev); - hub_free_dev(udev); -+ if (retry_locked) { -+ mutex_unlock(hcd->address0_mutex); -+ usb_unlock_port(port_dev); -+ } - usb_put_dev(udev); - if ((status == -ENOTCONN) || (status == -ENOTSUPP)) - break; -@@ -5915,6 +5924,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev) - bos = udev->bos; - udev->bos = NULL; - -+ mutex_lock(hcd->address0_mutex); -+ - for (i = 0; i < PORT_INIT_TRIES; ++i) { - - /* ep0 maxpacket size may change; let the HCD know about it. -@@ -5924,6 +5935,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) - if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) - break; - } -+ mutex_unlock(hcd->address0_mutex); - - if (ret < 0) - goto re_enumerate; -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 8239fe7129dd7..d3c14b5ed4a1f 100644 ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -434,6 +434,12 @@ static const struct usb_device_id usb_quirk_list[] = { - { USB_DEVICE(0x1532, 0x0116), .driver_info = - USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, - -+ /* Lenovo USB-C to Ethernet Adapter RTL8153-04 */ -+ { USB_DEVICE(0x17ef, 0x720c), .driver_info = USB_QUIRK_NO_LPM }, -+ -+ /* Lenovo Powered USB-C Travel Hub (4X90S92381, RTL8153 GigE) */ -+ { USB_DEVICE(0x17ef, 0x721e), .driver_info = USB_QUIRK_NO_LPM }, -+ - /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */ - { USB_DEVICE(0x17ef, 0xa012), .driver_info = - USB_QUIRK_DISCONNECT_SUSPEND }, -diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c -index 2d4176f5788eb..aa6eb76f64ddc 100644 ---- a/drivers/usb/dwc2/drd.c -+++ b/drivers/usb/dwc2/drd.c -@@ -7,6 +7,7 @@ - * Author(s): Amelie Delaunay <amelie.delaunay@st.com> - */ - -+#include <linux/clk.h> - #include <linux/iopoll.h> - #include <linux/platform_device.h> - #include <linux/usb/role.h> -@@ -25,9 +26,9 @@ static void dwc2_ovr_init(struct dwc2_hsotg *hsotg) - gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); - dwc2_writel(hsotg, gotgctl, GOTGCTL); - -- dwc2_force_mode(hsotg, false); -- - spin_unlock_irqrestore(&hsotg->lock, flags); -+ -+ dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST)); - } - - static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) -@@ -39,6 +40,7 @@ static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) - (!valid && !(gotgctl & GOTGCTL_ASESVLD))) - return -EALREADY; - -+ gotgctl &= ~GOTGCTL_BVALOVAL; - if (valid) - gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL; - else -@@ -57,6 +59,7 @@ static int dwc2_ovr_bvalid(struct dwc2_hsotg *hsotg, bool valid) - (!valid && !(gotgctl & GOTGCTL_BSESVLD))) - return -EALREADY; - -+ gotgctl &= ~GOTGCTL_AVALOVAL; - if (valid) - gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; - else -@@ -86,6 +89,20 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) - } - #endif - -+ /* -+ * In case of USB_DR_MODE_PERIPHERAL, clock is disabled at the end of -+ * the probe and enabled on udc_start. -+ * If role-switch set is called before the udc_start, we need to enable -+ * the clock to read/write GOTGCTL and GUSBCFG registers to override -+ * mode and sessions. It is the case if cable is plugged at boot. -+ */ -+ if (!hsotg->ll_hw_enabled && hsotg->clk) { -+ int ret = clk_prepare_enable(hsotg->clk); -+ -+ if (ret) -+ return ret; -+ } -+ - spin_lock_irqsave(&hsotg->lock, flags); - - if (role == USB_ROLE_HOST) { -@@ -110,6 +127,9 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) - /* This will raise a Connector ID Status Change Interrupt */ - dwc2_force_mode(hsotg, role == USB_ROLE_HOST); - -+ if (!hsotg->ll_hw_enabled && hsotg->clk) -+ clk_disable_unprepare(hsotg->clk); -+ - dev_dbg(hsotg->dev, "%s-session valid\n", - role == USB_ROLE_NONE ? "No" : - role == USB_ROLE_HOST ? "A" : "B"); -diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c -index 11d85a6e0b0dc..2190225bf3da2 100644 ---- a/drivers/usb/dwc2/gadget.c -+++ b/drivers/usb/dwc2/gadget.c -@@ -1198,6 +1198,8 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, - } - ctrl |= DXEPCTL_CNAK; - } else { -+ hs_req->req.frame_number = hs_ep->target_frame; -+ hs_req->req.actual = 0; - dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA); - return; - } -@@ -2857,9 +2859,12 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep) - - do { - hs_req = get_ep_head(hs_ep); -- if (hs_req) -+ if (hs_req) { -+ hs_req->req.frame_number = hs_ep->target_frame; -+ hs_req->req.actual = 0; - dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, - -ENODATA); -+ } - dwc2_gadget_incr_frame_num(hs_ep); - /* Update current frame number value. */ - hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg); -@@ -2912,8 +2917,11 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep) - - while (dwc2_gadget_target_frame_elapsed(ep)) { - hs_req = get_ep_head(ep); -- if (hs_req) -+ if (hs_req) { -+ hs_req->req.frame_number = ep->target_frame; -+ hs_req->req.actual = 0; - dwc2_hsotg_complete_request(hsotg, ep, hs_req, -ENODATA); -+ } - - dwc2_gadget_incr_frame_num(ep); - /* Update current frame number value. */ -@@ -3002,8 +3010,11 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) - - while (dwc2_gadget_target_frame_elapsed(hs_ep)) { - hs_req = get_ep_head(hs_ep); -- if (hs_req) -+ if (hs_req) { -+ hs_req->req.frame_number = hs_ep->target_frame; -+ hs_req->req.actual = 0; - dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA); -+ } - - dwc2_gadget_incr_frame_num(hs_ep); - /* Update current frame number value. */ -diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c -index 89a788326c562..24beff610cf2c 100644 ---- a/drivers/usb/dwc2/hcd_queue.c -+++ b/drivers/usb/dwc2/hcd_queue.c -@@ -59,7 +59,7 @@ - #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) - - /* If we get a NAK, wait this long before retrying */ --#define DWC2_RETRY_WAIT_DELAY (1 * 1E6L) -+#define DWC2_RETRY_WAIT_DELAY (1 * NSEC_PER_MSEC) - - /** - * dwc2_periodic_channel_available() - Checks that a channel is available for a -diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c -index c8f18f3ba9e35..c331a5128c2c0 100644 ---- a/drivers/usb/dwc2/platform.c -+++ b/drivers/usb/dwc2/platform.c -@@ -575,6 +575,9 @@ static int dwc2_driver_probe(struct platform_device *dev) - ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; - ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; - dwc2_writel(hsotg, ggpio, GGPIO); -+ -+ /* ID/VBUS detection startup time */ -+ usleep_range(5000, 7000); - } - - retval = dwc2_drd_init(hsotg); -diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c -index 0104a80b185e1..357b7805896e7 100644 ---- a/drivers/usb/dwc3/core.c -+++ b/drivers/usb/dwc3/core.c -@@ -1565,9 +1565,11 @@ static int dwc3_probe(struct platform_device *pdev) - - dwc3_get_properties(dwc); - -- ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); -- if (ret) -- return ret; -+ if (!dwc->sysdev_is_parent) { -+ ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); -+ if (ret) -+ return ret; -+ } - - dwc->reset = devm_reset_control_array_get_optional_shared(dev); - if (IS_ERR(dwc->reset)) -diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h -index 5612bfdf37da9..fd5d42ec53501 100644 ---- a/drivers/usb/dwc3/core.h -+++ b/drivers/usb/dwc3/core.h -@@ -143,7 +143,7 @@ - #define DWC3_GHWPARAMS8 0xc600 - #define DWC3_GUCTL3 0xc60c - #define DWC3_GFLADJ 0xc630 --#define DWC3_GHWPARAMS9 0xc680 -+#define DWC3_GHWPARAMS9 0xc6e0 - - /* Device Registers */ - #define DWC3_DCFG 0xc700 -@@ -723,6 +723,7 @@ struct dwc3_ep { - #define DWC3_EP_FORCE_RESTART_STREAM BIT(9) - #define DWC3_EP_FIRST_STREAM_PRIMED BIT(10) - #define DWC3_EP_PENDING_CLEAR_STALL BIT(11) -+#define DWC3_EP_TXFIFO_RESIZED BIT(12) - - /* This last one is specific to EP0 */ - #define DWC3_EP0_DIR_IN BIT(31) -diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c -index 9abbd01028c5f..3cb01cdd02c29 100644 ---- a/drivers/usb/dwc3/dwc3-qcom.c -+++ b/drivers/usb/dwc3/dwc3-qcom.c -@@ -649,7 +649,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) - struct dwc3_qcom *qcom = platform_get_drvdata(pdev); - struct device_node *np = pdev->dev.of_node, *dwc3_np; - struct device *dev = &pdev->dev; -- struct property *prop; - int ret; - - dwc3_np = of_get_compatible_child(np, "snps,dwc3"); -@@ -658,20 +657,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) - return -ENODEV; - } - -- prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL); -- if (!prop) { -- ret = -ENOMEM; -- dev_err(dev, "unable to allocate memory for property\n"); -- goto node_put; -- } -- -- prop->name = "tx-fifo-resize"; -- ret = of_add_property(dwc3_np, prop); -- if (ret) { -- dev_err(dev, "unable to add property\n"); -- goto node_put; -- } -- - ret = of_platform_populate(np, NULL, NULL, dev); - if (ret) { - dev_err(dev, "failed to register dwc3 core - %d\n", ret); -diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c -index 4519d06c9ca2b..4c16805a2b310 100644 ---- a/drivers/usb/dwc3/gadget.c -+++ b/drivers/usb/dwc3/gadget.c -@@ -310,13 +310,24 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, - if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { - int link_state; - -+ /* -+ * Initiate remote wakeup if the link state is in U3 when -+ * operating in SS/SSP or L1/L2 when operating in HS/FS. If the -+ * link state is in U1/U2, no remote wakeup is needed. The Start -+ * Transfer command will initiate the link recovery. -+ */ - link_state = dwc3_gadget_get_link_state(dwc); -- if (link_state == DWC3_LINK_STATE_U1 || -- link_state == DWC3_LINK_STATE_U2 || -- link_state == DWC3_LINK_STATE_U3) { -+ switch (link_state) { -+ case DWC3_LINK_STATE_U2: -+ if (dwc->gadget->speed >= USB_SPEED_SUPER) -+ break; -+ -+ fallthrough; -+ case DWC3_LINK_STATE_U3: - ret = __dwc3_gadget_wakeup(dwc); - dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n", - ret); -+ break; - } - } - -@@ -702,6 +713,7 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) - DWC31_GTXFIFOSIZ_TXFRAMNUM; - - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size); -+ dep->flags &= ~DWC3_EP_TXFIFO_RESIZED; - } - dwc->num_ep_resized = 0; - } -@@ -747,6 +759,10 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) - if (!usb_endpoint_dir_in(dep->endpoint.desc) || dep->number <= 1) - return 0; - -+ /* bail if already resized */ -+ if (dep->flags & DWC3_EP_TXFIFO_RESIZED) -+ return 0; -+ - ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); - - if ((dep->endpoint.maxburst > 1 && -@@ -807,6 +823,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) - } - - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size); -+ dep->flags |= DWC3_EP_TXFIFO_RESIZED; - dwc->num_ep_resized++; - - return 0; -@@ -995,7 +1012,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) - - dep->stream_capable = false; - dep->type = 0; -- dep->flags = 0; -+ dep->flags &= DWC3_EP_TXFIFO_RESIZED; - - return 0; - } -@@ -3246,6 +3263,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, - struct dwc3 *dwc = dep->dwc; - bool no_started_trb = true; - -+ if (!dep->endpoint.desc) -+ return no_started_trb; -+ - dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); - - if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) -@@ -3293,6 +3313,9 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, - { - int status = 0; - -+ if (!dep->endpoint.desc) -+ return; -+ - if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) - dwc3_gadget_endpoint_frame_from_event(dep, event); - -@@ -3346,6 +3369,14 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep, - if (cmd != DWC3_DEPCMD_ENDTRANSFER) - return; - -+ /* -+ * The END_TRANSFER command will cause the controller to generate a -+ * NoStream Event, and it's not due to the host DP NoStream rejection. -+ * Ignore the next NoStream event. -+ */ -+ if (dep->stream_capable) -+ dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM; -+ - dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; - dep->flags &= ~DWC3_EP_TRANSFER_STARTED; - dwc3_gadget_ep_cleanup_cancelled_requests(dep); -@@ -3568,14 +3599,6 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, - WARN_ON_ONCE(ret); - dep->resource_index = 0; - -- /* -- * The END_TRANSFER command will cause the controller to generate a -- * NoStream Event, and it's not due to the host DP NoStream rejection. -- * Ignore the next NoStream event. -- */ -- if (dep->stream_capable) -- dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM; -- - if (!interrupt) - dep->flags &= ~DWC3_EP_TRANSFER_STARTED; - else -diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c -index be4ecbabdd586..6c0434100e38c 100644 ---- a/drivers/usb/early/xhci-dbc.c -+++ b/drivers/usb/early/xhci-dbc.c -@@ -14,7 +14,6 @@ - #include <linux/pci_ids.h> - #include <linux/memblock.h> - #include <linux/io.h> --#include <linux/iopoll.h> - #include <asm/pci-direct.h> - #include <asm/fixmap.h> - #include <linux/bcd.h> -@@ -136,9 +135,17 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, int wait, int delay) - { - u32 result; - -- return readl_poll_timeout_atomic(ptr, result, -- ((result & mask) == done), -- delay, wait); -+ /* Can not use readl_poll_timeout_atomic() for early boot things */ -+ do { -+ result = readl(ptr); -+ result &= mask; -+ if (result == done) -+ return 0; -+ udelay(delay); -+ wait -= delay; -+ } while (wait > 0); -+ -+ return -ETIMEDOUT; - } - - static void __init xdbc_bios_handoff(void) -diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c -index 504c1cbc255d1..3789c329183ca 100644 ---- a/drivers/usb/gadget/composite.c -+++ b/drivers/usb/gadget/composite.c -@@ -1679,6 +1679,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) - struct usb_function *f = NULL; - u8 endp; - -+ if (w_length > USB_COMP_EP0_BUFSIZ) { -+ if (ctrl->bRequestType & USB_DIR_IN) { -+ /* Cast away the const, we are going to overwrite on purpose. */ -+ __le16 *temp = (__le16 *)&ctrl->wLength; -+ -+ *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); -+ w_length = USB_COMP_EP0_BUFSIZ; -+ } else { -+ goto done; -+ } -+ } -+ - /* partial re-init of the response message; the function or the - * gadget might need to intercept e.g. a control-OUT completion - * when we delegate to it. -@@ -2209,7 +2221,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite, - if (!cdev->req) - return -ENOMEM; - -- cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); -+ cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); - if (!cdev->req->buf) - goto fail; - -diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c -index 85a3f6d4b5af3..d15a54f6c24b9 100644 ---- a/drivers/usb/gadget/function/u_ether.c -+++ b/drivers/usb/gadget/function/u_ether.c -@@ -17,6 +17,7 @@ - #include <linux/etherdevice.h> - #include <linux/ethtool.h> - #include <linux/if_vlan.h> -+#include <linux/etherdevice.h> - - #include "u_ether.h" - -@@ -861,19 +862,23 @@ int gether_register_netdev(struct net_device *net) - { - struct eth_dev *dev; - struct usb_gadget *g; -- struct sockaddr sa; - int status; - - if (!net->dev.parent) - return -EINVAL; - dev = netdev_priv(net); - g = dev->gadget; -+ -+ net->addr_assign_type = NET_ADDR_RANDOM; -+ eth_hw_addr_set(net, dev->dev_mac); -+ - status = register_netdev(net); - if (status < 0) { - dev_dbg(&g->dev, "register_netdev failed, %d\n", status); - return status; - } else { - INFO(dev, "HOST MAC %pM\n", dev->host_mac); -+ INFO(dev, "MAC %pM\n", dev->dev_mac); - - /* two kinds of host-initiated state changes: - * - iff DATA transfer is active, carrier is "on" -@@ -881,15 +886,6 @@ int gether_register_netdev(struct net_device *net) - */ - netif_carrier_off(net); - } -- sa.sa_family = net->type; -- memcpy(sa.sa_data, dev->dev_mac, ETH_ALEN); -- rtnl_lock(); -- status = dev_set_mac_address(net, &sa, NULL); -- rtnl_unlock(); -- if (status) -- pr_warn("cannot set self ethernet address: %d\n", status); -- else -- INFO(dev, "MAC %pM\n", dev->dev_mac); - - return status; - } -diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h -index 255a61bd6a6a8..9d5f17b551bbd 100644 ---- a/drivers/usb/gadget/function/uvc.h -+++ b/drivers/usb/gadget/function/uvc.h -@@ -126,6 +126,7 @@ struct uvc_device { - enum uvc_state state; - struct usb_function func; - struct uvc_video video; -+ bool func_connected; - - /* Descriptors */ - struct { -@@ -156,6 +157,7 @@ static inline struct uvc_device *to_uvc(struct usb_function *f) - struct uvc_file_handle { - struct v4l2_fh vfh; - struct uvc_video *device; -+ bool is_uvc_app_handle; - }; - - #define to_uvc_file_handle(handle) \ -diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c -index 4ca89eab61590..197c26f7aec63 100644 ---- a/drivers/usb/gadget/function/uvc_v4l2.c -+++ b/drivers/usb/gadget/function/uvc_v4l2.c -@@ -227,17 +227,55 @@ static int - uvc_v4l2_subscribe_event(struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) - { -+ struct uvc_device *uvc = video_get_drvdata(fh->vdev); -+ struct uvc_file_handle *handle = to_uvc_file_handle(fh); -+ int ret; -+ - if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) - return -EINVAL; - -- return v4l2_event_subscribe(fh, sub, 2, NULL); -+ if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) -+ return -EBUSY; -+ -+ ret = v4l2_event_subscribe(fh, sub, 2, NULL); -+ if (ret < 0) -+ return ret; -+ -+ if (sub->type == UVC_EVENT_SETUP) { -+ uvc->func_connected = true; -+ handle->is_uvc_app_handle = true; -+ uvc_function_connect(uvc); -+ } -+ -+ return 0; -+} -+ -+static void uvc_v4l2_disable(struct uvc_device *uvc) -+{ -+ uvc->func_connected = false; -+ uvc_function_disconnect(uvc); -+ uvcg_video_enable(&uvc->video, 0); -+ uvcg_free_buffers(&uvc->video.queue); - } - - static int - uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) - { -- return v4l2_event_unsubscribe(fh, sub); -+ struct uvc_device *uvc = video_get_drvdata(fh->vdev); -+ struct uvc_file_handle *handle = to_uvc_file_handle(fh); -+ int ret; -+ -+ ret = v4l2_event_unsubscribe(fh, sub); -+ if (ret < 0) -+ return ret; -+ -+ if (sub->type == UVC_EVENT_SETUP && handle->is_uvc_app_handle) { -+ uvc_v4l2_disable(uvc); -+ handle->is_uvc_app_handle = false; -+ } -+ -+ return 0; - } - - static long -@@ -292,7 +330,6 @@ uvc_v4l2_open(struct file *file) - handle->device = &uvc->video; - file->private_data = &handle->vfh; - -- uvc_function_connect(uvc); - return 0; - } - -@@ -304,11 +341,9 @@ uvc_v4l2_release(struct file *file) - struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); - struct uvc_video *video = handle->device; - -- uvc_function_disconnect(uvc); -- - mutex_lock(&video->mutex); -- uvcg_video_enable(video, 0); -- uvcg_free_buffers(&video->queue); -+ if (handle->is_uvc_app_handle) -+ uvc_v4l2_disable(uvc); - mutex_unlock(&video->mutex); - - file->private_data = NULL; -diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c -index e1d566c9918ae..6bcbad3825802 100644 ---- a/drivers/usb/gadget/legacy/dbgp.c -+++ b/drivers/usb/gadget/legacy/dbgp.c -@@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep) - goto fail_1; - } - -- req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL); -+ req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL); - if (!req->buf) { - err = -ENOMEM; - stp = 2; -@@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget, - void *data = NULL; - u16 len = 0; - -+ if (length > DBGP_REQ_LEN) { -+ if (ctrl->bRequestType & USB_DIR_IN) { -+ /* Cast away the const, we are going to overwrite on purpose. */ -+ __le16 *temp = (__le16 *)&ctrl->wLength; -+ -+ *temp = cpu_to_le16(DBGP_REQ_LEN); -+ length = DBGP_REQ_LEN; -+ } else { -+ return err; -+ } -+ } -+ -+ - if (request == USB_REQ_GET_DESCRIPTOR) { - switch (value>>8) { - case USB_DT_DEVICE: -diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c -index 5b27d289443fe..3912cc805f3af 100644 ---- a/drivers/usb/gadget/legacy/hid.c -+++ b/drivers/usb/gadget/legacy/hid.c -@@ -99,8 +99,10 @@ static int do_config(struct usb_configuration *c) - - list_for_each_entry(e, &hidg_func_list, node) { - e->f = usb_get_function(e->fi); -- if (IS_ERR(e->f)) -+ if (IS_ERR(e->f)) { -+ status = PTR_ERR(e->f); - goto put; -+ } - status = usb_add_function(c, e->f); - if (status < 0) { - usb_put_function(e->f); -diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c -index 539220d7f5b62..1b223cba4c2c9 100644 ---- a/drivers/usb/gadget/legacy/inode.c -+++ b/drivers/usb/gadget/legacy/inode.c -@@ -110,6 +110,8 @@ enum ep0_state { - /* enough for the whole queue: most events invalidate others */ - #define N_EVENT 5 - -+#define RBUF_SIZE 256 -+ - struct dev_data { - spinlock_t lock; - refcount_t count; -@@ -144,7 +146,7 @@ struct dev_data { - struct dentry *dentry; - - /* except this scratch i/o buffer for ep0 */ -- u8 rbuf [256]; -+ u8 rbuf[RBUF_SIZE]; - }; - - static inline void get_dev (struct dev_data *data) -@@ -1334,6 +1336,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - -+ if (w_length > RBUF_SIZE) { -+ if (ctrl->bRequestType & USB_DIR_IN) { -+ /* Cast away the const, we are going to overwrite on purpose. */ -+ __le16 *temp = (__le16 *)&ctrl->wLength; -+ -+ *temp = cpu_to_le16(RBUF_SIZE); -+ w_length = RBUF_SIZE; -+ } else { -+ return value; -+ } -+ } -+ - spin_lock (&dev->lock); - dev->setup_abort = 0; - if (dev->state == STATE_DEV_UNCONNECTED) { -diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig -index 8c614bb86c665..69394dc1cdfb6 100644 ---- a/drivers/usb/gadget/udc/Kconfig -+++ b/drivers/usb/gadget/udc/Kconfig -@@ -330,6 +330,7 @@ config USB_AMD5536UDC - config USB_FSL_QE - tristate "Freescale QE/CPM USB Device Controller" - depends on FSL_SOC && (QUICC_ENGINE || CPM) -+ depends on !64BIT || BROKEN - help - Some of Freescale PowerPC processors have a Full Speed - QE/CPM2 USB controller, which support device mode with 4 -diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c -index 1776c05d0a486..1440803216297 100644 ---- a/drivers/usb/host/ehci-hcd.c -+++ b/drivers/usb/host/ehci-hcd.c -@@ -635,7 +635,16 @@ static int ehci_run (struct usb_hcd *hcd) - /* Wait until HC become operational */ - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - msleep(5); -- rc = ehci_handshake(ehci, &ehci->regs->status, STS_HALT, 0, 100 * 1000); -+ -+ /* For Aspeed, STS_HALT also depends on ASS/PSS status. -+ * Check CMD_RUN instead. -+ */ -+ if (ehci->is_aspeed) -+ rc = ehci_handshake(ehci, &ehci->regs->command, CMD_RUN, -+ 1, 100 * 1000); -+ else -+ rc = ehci_handshake(ehci, &ehci->regs->status, STS_HALT, -+ 0, 100 * 1000); - - up_write(&ehci_cf_port_reset_rwsem); - -diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c -index c70f2d0b4aaf0..c3dc906274d93 100644 ---- a/drivers/usb/host/ehci-platform.c -+++ b/drivers/usb/host/ehci-platform.c -@@ -297,6 +297,12 @@ static int ehci_platform_probe(struct platform_device *dev) - "has-transaction-translator")) - hcd->has_tt = 1; - -+ if (of_device_is_compatible(dev->dev.of_node, -+ "aspeed,ast2500-ehci") || -+ of_device_is_compatible(dev->dev.of_node, -+ "aspeed,ast2600-ehci")) -+ ehci->is_aspeed = 1; -+ - if (soc_device_match(quirk_poll_match)) - priv->quirk_poll = true; - -diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h -index 80bb823aa9fe8..fdd073cc053b8 100644 ---- a/drivers/usb/host/ehci.h -+++ b/drivers/usb/host/ehci.h -@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controller */ - unsigned need_oc_pp_cycle:1; /* MPC834X port power */ - unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ - unsigned spurious_oc:1; -+ unsigned is_aspeed:1; - - /* required for usb32 quirk */ - #define OHCI_CTRL_HCFS (3 << 6) -diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c -index 59cc1bc7f12f5..30de85a707fef 100644 ---- a/drivers/usb/host/max3421-hcd.c -+++ b/drivers/usb/host/max3421-hcd.c -@@ -125,8 +125,6 @@ struct max3421_hcd { - - struct task_struct *spi_thread; - -- struct max3421_hcd *next; -- - enum max3421_rh_state rh_state; - /* lower 16 bits contain port status, upper 16 bits the change mask: */ - u32 port_status; -@@ -174,8 +172,6 @@ struct max3421_ep { - u8 retransmit; /* packet needs retransmission */ - }; - --static struct max3421_hcd *max3421_hcd_list; -- - #define MAX3421_FIFO_SIZE 64 - - #define MAX3421_SPI_DIR_RD 0 /* read register from MAX3421 */ -@@ -1882,9 +1878,8 @@ max3421_probe(struct spi_device *spi) - } - set_bit(HCD_FLAG_POLL_RH, &hcd->flags); - max3421_hcd = hcd_to_max3421(hcd); -- max3421_hcd->next = max3421_hcd_list; -- max3421_hcd_list = max3421_hcd; - INIT_LIST_HEAD(&max3421_hcd->ep_list); -+ spi_set_drvdata(spi, max3421_hcd); - - max3421_hcd->tx = kmalloc(sizeof(*max3421_hcd->tx), GFP_KERNEL); - if (!max3421_hcd->tx) -@@ -1934,28 +1929,18 @@ error: - static int - max3421_remove(struct spi_device *spi) - { -- struct max3421_hcd *max3421_hcd = NULL, **prev; -- struct usb_hcd *hcd = NULL; -+ struct max3421_hcd *max3421_hcd; -+ struct usb_hcd *hcd; - unsigned long flags; - -- for (prev = &max3421_hcd_list; *prev; prev = &(*prev)->next) { -- max3421_hcd = *prev; -- hcd = max3421_to_hcd(max3421_hcd); -- if (hcd->self.controller == &spi->dev) -- break; -- } -- if (!max3421_hcd) { -- dev_err(&spi->dev, "no MAX3421 HCD found for SPI device %p\n", -- spi); -- return -ENODEV; -- } -+ max3421_hcd = spi_get_drvdata(spi); -+ hcd = max3421_to_hcd(max3421_hcd); - - usb_remove_hcd(hcd); - - spin_lock_irqsave(&max3421_hcd->lock, flags); - - kthread_stop(max3421_hcd->spi_thread); -- *prev = max3421_hcd->next; - - spin_unlock_irqrestore(&max3421_hcd->lock, flags); - -diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c -index 08ec2ab0d95a5..3f3d62dc06746 100644 ---- a/drivers/usb/host/ohci-tmio.c -+++ b/drivers/usb/host/ohci-tmio.c -@@ -199,7 +199,7 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev) - if (usb_disabled()) - return -ENODEV; - -- if (!cell) -+ if (!cell || !regs || !config || !sram) - return -EINVAL; - - if (irq < 0) -diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c -index a3f875eea7519..df3522dab31b5 100644 ---- a/drivers/usb/host/xhci-hub.c -+++ b/drivers/usb/host/xhci-hub.c -@@ -257,7 +257,6 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, - { - u16 temp; - -- desc->bPwrOn2PwrGood = 10; /* xhci section 5.4.9 says 20ms max */ - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = ports; -@@ -292,6 +291,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, - desc->bDescriptorType = USB_DT_HUB; - temp = 1 + (ports / 8); - desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp; -+ desc->bPwrOn2PwrGood = 10; /* xhci section 5.4.8 says 20ms */ - - /* The Device Removable bits are reported on a byte granularity. - * If the port doesn't exist within that byte, the bit is set to 0. -@@ -344,6 +344,7 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, - xhci_common_hub_descriptor(xhci, desc, ports); - desc->bDescriptorType = USB_DT_SS_HUB; - desc->bDescLength = USB_DT_SS_HUB_SIZE; -+ desc->bPwrOn2PwrGood = 50; /* usb 3.1 may fail if less than 100ms */ - - /* header decode latency should be zero for roothubs, - * see section 4.23.5.2. -@@ -716,6 +717,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, - continue; - - retval = xhci_disable_slot(xhci, i); -+ xhci_free_virt_device(xhci, i); - if (retval) - xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", - i, retval); -diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c -index 134f4789bd897..b4c84b3635074 100644 ---- a/drivers/usb/host/xhci-mtk-sch.c -+++ b/drivers/usb/host/xhci-mtk-sch.c -@@ -781,7 +781,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) - - ret = xhci_check_bandwidth(hcd, udev); - if (!ret) -- INIT_LIST_HEAD(&mtk->bw_ep_chk_list); -+ list_del_init(&mtk->bw_ep_chk_list); - - return ret; - } -diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c -index 2484a9d38ce2b..8c04a7d73388b 100644 ---- a/drivers/usb/host/xhci-pci.c -+++ b/drivers/usb/host/xhci-pci.c -@@ -65,6 +65,15 @@ - #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba - #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb - #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 0x161a -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 0x161b -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 0x161d -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6 -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7 -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 0x161c -+#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8 0x161f -+ - #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 - #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 - #define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242 -@@ -317,6 +326,17 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) - pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) - xhci->quirks |= XHCI_NO_SOFT_RETRY; - -+ if (pdev->vendor == PCI_VENDOR_ID_AMD && -+ (pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 || -+ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8)) -+ xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; -+ - if (xhci->quirks & XHCI_RESET_ON_RESUME) - xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, - "QUIRK: Resetting on resume"); -diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c -index 311597bba80e2..d0b6806275e01 100644 ---- a/drivers/usb/host/xhci-ring.c -+++ b/drivers/usb/host/xhci-ring.c -@@ -366,7 +366,9 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci, - /* Must be called with xhci->lock held, releases and aquires lock back */ - static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) - { -- u32 temp_32; -+ struct xhci_segment *new_seg = xhci->cmd_ring->deq_seg; -+ union xhci_trb *new_deq = xhci->cmd_ring->dequeue; -+ u64 crcr; - int ret; - - xhci_dbg(xhci, "Abort command ring\n"); -@@ -375,13 +377,18 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) - - /* - * The control bits like command stop, abort are located in lower -- * dword of the command ring control register. Limit the write -- * to the lower dword to avoid corrupting the command ring pointer -- * in case if the command ring is stopped by the time upper dword -- * is written. -+ * dword of the command ring control register. -+ * Some controllers require all 64 bits to be written to abort the ring. -+ * Make sure the upper dword is valid, pointing to the next command, -+ * avoiding corrupting the command ring pointer in case the command ring -+ * is stopped by the time the upper dword is written. - */ -- temp_32 = readl(&xhci->op_regs->cmd_ring); -- writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); -+ next_trb(xhci, NULL, &new_seg, &new_deq); -+ if (trb_is_link(new_deq)) -+ next_trb(xhci, NULL, &new_seg, &new_deq); -+ -+ crcr = xhci_trb_virt_to_dma(new_seg, new_deq); -+ xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); - - /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the - * completion of the Command Abort operation. If CRR is not negated in 5 -@@ -1518,7 +1525,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) - if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) - /* Delete default control endpoint resources */ - xhci_free_device_endpoint_resources(xhci, virt_dev, true); -- xhci_free_virt_device(xhci, slot_id); - } - - static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, -diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c -index 1bf494b649bd2..c8af2cd2216d6 100644 ---- a/drivers/usb/host/xhci-tegra.c -+++ b/drivers/usb/host/xhci-tegra.c -@@ -1400,6 +1400,7 @@ static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra) - - static int tegra_xusb_probe(struct platform_device *pdev) - { -+ struct of_phandle_args args; - struct tegra_xusb *tegra; - struct device_node *np; - struct resource *regs; -@@ -1454,10 +1455,17 @@ static int tegra_xusb_probe(struct platform_device *pdev) - goto put_padctl; - } - -- tegra->padctl_irq = of_irq_get(np, 0); -- if (tegra->padctl_irq <= 0) { -- err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq; -- goto put_padctl; -+ /* Older device-trees don't have padctrl interrupt */ -+ err = of_irq_parse_one(np, 0, &args); -+ if (!err) { -+ tegra->padctl_irq = of_irq_get(np, 0); -+ if (tegra->padctl_irq <= 0) { -+ err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq; -+ goto put_padctl; -+ } -+ } else { -+ dev_dbg(&pdev->dev, -+ "%pOF is missing an interrupt, disabling PM support\n", np); - } - - tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host"); -@@ -1696,11 +1704,15 @@ static int tegra_xusb_probe(struct platform_device *pdev) - goto remove_usb3; - } - -- err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq, NULL, tegra_xusb_padctl_irq, -- IRQF_ONESHOT, dev_name(&pdev->dev), tegra); -- if (err < 0) { -- dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err); -- goto remove_usb3; -+ if (tegra->padctl_irq) { -+ err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq, -+ NULL, tegra_xusb_padctl_irq, -+ IRQF_ONESHOT, dev_name(&pdev->dev), -+ tegra); -+ if (err < 0) { -+ dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err); -+ goto remove_usb3; -+ } - } - - err = tegra_xusb_enable_firmware_messages(tegra); -@@ -1718,13 +1730,16 @@ static int tegra_xusb_probe(struct platform_device *pdev) - /* Enable wake for both USB 2.0 and USB 3.0 roothubs */ - device_init_wakeup(&tegra->hcd->self.root_hub->dev, true); - device_init_wakeup(&xhci->shared_hcd->self.root_hub->dev, true); -- device_init_wakeup(tegra->dev, true); - - pm_runtime_use_autosuspend(tegra->dev); - pm_runtime_set_autosuspend_delay(tegra->dev, 2000); - pm_runtime_mark_last_busy(tegra->dev); - pm_runtime_set_active(tegra->dev); -- pm_runtime_enable(tegra->dev); -+ -+ if (tegra->padctl_irq) { -+ device_init_wakeup(tegra->dev, true); -+ pm_runtime_enable(tegra->dev); -+ } - - return 0; - -@@ -1772,7 +1787,9 @@ static int tegra_xusb_remove(struct platform_device *pdev) - dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt, - tegra->fw.phys); - -- pm_runtime_disable(&pdev->dev); -+ if (tegra->padctl_irq) -+ pm_runtime_disable(&pdev->dev); -+ - pm_runtime_put(&pdev->dev); - - tegra_xusb_powergate_partitions(tegra); -diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c -index 541fe4dcc43a2..f5b1bcc875ded 100644 ---- a/drivers/usb/host/xhci.c -+++ b/drivers/usb/host/xhci.c -@@ -692,7 +692,6 @@ int xhci_run(struct usb_hcd *hcd) - if (ret) - xhci_free_command(xhci, command); - } -- set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Finished xhci_run for USB2 roothub"); - -@@ -3935,7 +3934,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) - struct xhci_slot_ctx *slot_ctx; - int i, ret; - --#ifndef CONFIG_USB_DEFAULT_PERSIST - /* - * We called pm_runtime_get_noresume when the device was attached. - * Decrement the counter here to allow controller to runtime suspend -@@ -3943,7 +3941,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) - */ - if (xhci->quirks & XHCI_RESET_ON_RESUME) - pm_runtime_put_noidle(hcd->self.controller); --#endif - - ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); - /* If the host is halted due to driver unload, we still need to free the -@@ -3962,9 +3959,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) - del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); - } - virt_dev->udev = NULL; -- ret = xhci_disable_slot(xhci, udev->slot_id); -- if (ret) -- xhci_free_virt_device(xhci, udev->slot_id); -+ xhci_disable_slot(xhci, udev->slot_id); -+ xhci_free_virt_device(xhci, udev->slot_id); - } - - int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) -@@ -3974,7 +3970,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) - u32 state; - int ret = 0; - -- command = xhci_alloc_command(xhci, false, GFP_KERNEL); -+ command = xhci_alloc_command(xhci, true, GFP_KERNEL); - if (!command) - return -ENOMEM; - -@@ -3999,6 +3995,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) - } - xhci_ring_cmd_db(xhci); - spin_unlock_irqrestore(&xhci->lock, flags); -+ -+ wait_for_completion(command->completion); -+ -+ if (command->status != COMP_SUCCESS) -+ xhci_warn(xhci, "Unsuccessful disable slot %u command, status %d\n", -+ slot_id, command->status); -+ -+ xhci_free_command(xhci, command); -+ - return ret; - } - -@@ -4095,23 +4100,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) - - xhci_debugfs_create_slot(xhci, slot_id); - --#ifndef CONFIG_USB_DEFAULT_PERSIST - /* - * If resetting upon resume, we can't put the controller into runtime - * suspend if there is a device attached. - */ - if (xhci->quirks & XHCI_RESET_ON_RESUME) - pm_runtime_get_noresume(hcd->self.controller); --#endif - - /* Is this a LS or FS device under a HS hub? */ - /* Hub or peripherial? */ - return 1; - - disable_slot: -- ret = xhci_disable_slot(xhci, udev->slot_id); -- if (ret) -- xhci_free_virt_device(xhci, udev->slot_id); -+ xhci_disable_slot(xhci, udev->slot_id); -+ xhci_free_virt_device(xhci, udev->slot_id); - - return 0; - } -@@ -4241,6 +4243,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, - - mutex_unlock(&xhci->mutex); - ret = xhci_disable_slot(xhci, udev->slot_id); -+ xhci_free_virt_device(xhci, udev->slot_id); - if (!ret) - xhci_alloc_dev(hcd, udev); - kfree(command->completion); -diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c -index efbd317f2f252..988a8c02e7e24 100644 ---- a/drivers/usb/misc/iowarrior.c -+++ b/drivers/usb/misc/iowarrior.c -@@ -99,10 +99,6 @@ struct iowarrior { - /* globals */ - /*--------------*/ - --/* -- * USB spec identifies 5 second timeouts. -- */ --#define GET_TIMEOUT 5 - #define USB_REQ_GET_REPORT 0x01 - //#if 0 - static int usb_get_report(struct usb_device *dev, -@@ -114,7 +110,7 @@ static int usb_get_report(struct usb_device *dev, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, (type << 8) + id, - inter->desc.bInterfaceNumber, buf, size, -- GET_TIMEOUT*HZ); -+ USB_CTRL_GET_TIMEOUT); - } - //#endif - -@@ -129,7 +125,7 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, - intf->cur_altsetting->desc.bInterfaceNumber, buf, -- size, HZ); -+ size, 1000); - } - - /*---------------------*/ -diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig -index 8de143807c1ae..4d61df6a9b5c8 100644 ---- a/drivers/usb/musb/Kconfig -+++ b/drivers/usb/musb/Kconfig -@@ -120,7 +120,7 @@ config USB_MUSB_MEDIATEK - tristate "MediaTek platforms" - depends on ARCH_MEDIATEK || COMPILE_TEST - depends on NOP_USB_XCEIV -- depends on GENERIC_PHY -+ select GENERIC_PHY - select USB_ROLE_SWITCH - - comment "MUSB DMA mode" -diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c -index 98c0f4c1bffd9..51274b87f46c9 100644 ---- a/drivers/usb/musb/musb_gadget.c -+++ b/drivers/usb/musb/musb_gadget.c -@@ -1247,9 +1247,11 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, - status = musb_queue_resume_work(musb, - musb_ep_restart_resume_work, - request); -- if (status < 0) -+ if (status < 0) { - dev_err(musb->controller, "%s resume work: %i\n", - __func__, status); -+ list_del(&request->list); -+ } - } - - unlock: -diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c -index c968ecda42aa8..7ed4cc348d993 100644 ---- a/drivers/usb/musb/tusb6010.c -+++ b/drivers/usb/musb/tusb6010.c -@@ -1104,6 +1104,11 @@ static int tusb_musb_init(struct musb *musb) - - /* dma address for async dma */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!mem) { -+ pr_debug("no async dma resource?\n"); -+ ret = -ENODEV; -+ goto done; -+ } - musb->async = mem->start; - - /* dma address for sync dma */ -diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c -index 189279869a8b0..22e62c01c0aa8 100644 ---- a/drivers/usb/serial/cp210x.c -+++ b/drivers/usb/serial/cp210x.c -@@ -1682,6 +1682,8 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) - - /* 2 banks of GPIO - One for the pins taken from each serial port */ - if (intf_num == 0) { -+ priv->gc.ngpio = 2; -+ - if (mode.eci == CP210X_PIN_MODE_MODEM) { - /* mark all GPIOs of this interface as reserved */ - priv->gpio_altfunc = 0xff; -@@ -1692,8 +1694,9 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) - priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & - CP210X_ECI_GPIO_MODE_MASK) >> - CP210X_ECI_GPIO_MODE_OFFSET); -- priv->gc.ngpio = 2; - } else if (intf_num == 1) { -+ priv->gc.ngpio = 3; -+ - if (mode.sci == CP210X_PIN_MODE_MODEM) { - /* mark all GPIOs of this interface as reserved */ - priv->gpio_altfunc = 0xff; -@@ -1704,7 +1707,6 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) - priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & - CP210X_SCI_GPIO_MODE_MASK) >> - CP210X_SCI_GPIO_MODE_OFFSET); -- priv->gc.ngpio = 3; - } else { - return -ENODEV; - } -diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c -index 87b89c99d5177..1cfcd805f2868 100644 ---- a/drivers/usb/serial/keyspan.c -+++ b/drivers/usb/serial/keyspan.c -@@ -2890,22 +2890,22 @@ static int keyspan_port_probe(struct usb_serial_port *port) - for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) { - p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL); - if (!p_priv->in_buffer[i]) -- goto err_in_buffer; -+ goto err_free_in_buffer; - } - - for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) { - p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL); - if (!p_priv->out_buffer[i]) -- goto err_out_buffer; -+ goto err_free_out_buffer; - } - - p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL); - if (!p_priv->inack_buffer) -- goto err_inack_buffer; -+ goto err_free_out_buffer; - - p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL); - if (!p_priv->outcont_buffer) -- goto err_outcont_buffer; -+ goto err_free_inack_buffer; - - p_priv->device_details = d_details; - -@@ -2951,15 +2951,14 @@ static int keyspan_port_probe(struct usb_serial_port *port) - - return 0; - --err_outcont_buffer: -+err_free_inack_buffer: - kfree(p_priv->inack_buffer); --err_inack_buffer: -+err_free_out_buffer: - for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) - kfree(p_priv->out_buffer[i]); --err_out_buffer: -+err_free_in_buffer: - for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) - kfree(p_priv->in_buffer[i]); --err_in_buffer: - kfree(p_priv); - - return -ENOMEM; -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index a484ff5e4ebf8..42420bfc983c2 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -1219,6 +1219,14 @@ static const struct usb_device_id option_ids[] = { - .driver_info = NCTRL(2) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ - .driver_info = NCTRL(0) | RSVD(1) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */ -+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */ -+ .driver_info = NCTRL(0) | RSVD(1) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */ -+ .driver_info = NCTRL(2) | RSVD(3) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ -+ .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), - .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), -@@ -1267,6 +1275,8 @@ static const struct usb_device_id option_ids[] = { - .driver_info = NCTRL(2) }, - { USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */ - .driver_info = NCTRL(0) | ZLP }, -+ { USB_DEVICE(TELIT_VENDOR_ID, 0x9200), /* Telit LE910S1 flashing device */ -+ .driver_info = NCTRL(0) | ZLP }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), - .driver_info = RSVD(1) }, -@@ -2094,6 +2104,9 @@ static const struct usb_device_id option_ids[] = { - { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */ - { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ -+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ -+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */ -+ .driver_info = RSVD(4) }, - { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ - { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ - { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ -diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c -index f45ca7ddf78ea..a70fd86f735ca 100644 ---- a/drivers/usb/serial/pl2303.c -+++ b/drivers/usb/serial/pl2303.c -@@ -432,6 +432,7 @@ static int pl2303_detect_type(struct usb_serial *serial) - case 0x200: - switch (bcdDevice) { - case 0x100: -+ case 0x105: - case 0x305: - case 0x405: - /* -diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h -index c6b3fcf901805..29191d33c0e3e 100644 ---- a/drivers/usb/storage/unusual_devs.h -+++ b/drivers/usb/storage/unusual_devs.h -@@ -406,6 +406,16 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, - "785EPX Storage", - USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_SINGLE_LUN), - -+/* -+ * Reported by James Buren <braewoods+lkml@braewoods.net> -+ * Virtual ISOs cannot be remounted if ejected while the device is locked -+ * Disable locking to mimic Windows behavior that bypasses the issue -+ */ -+UNUSUAL_DEV( 0x04c5, 0x2028, 0x0001, 0x0001, -+ "iODD", -+ "2531/2541", -+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE), -+ - /* - * Not sure who reported this originally but - * Pavel Machek <pavel@ucw.cz> reported that the extra US_FL_SINGLE_LUN -diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig -index a0418f23b4aae..ab480f38523aa 100644 ---- a/drivers/usb/typec/Kconfig -+++ b/drivers/usb/typec/Kconfig -@@ -65,9 +65,9 @@ config TYPEC_HD3SS3220 - - config TYPEC_STUSB160X - tristate "STMicroelectronics STUSB160x Type-C controller driver" -- depends on I2C -- depends on REGMAP_I2C - depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH -+ depends on I2C -+ select REGMAP_I2C - help - Say Y or M here if your system has STMicroelectronics STUSB160x - Type-C port controller. -diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c -index 7a2a17866a823..72f9001b07921 100644 ---- a/drivers/usb/typec/tcpm/fusb302.c -+++ b/drivers/usb/typec/tcpm/fusb302.c -@@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) - ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, - FUSB_REG_MASK_BC_LVL | - FUSB_REG_MASK_COMP_CHNG, -- FUSB_REG_MASK_COMP_CHNG); -+ FUSB_REG_MASK_BC_LVL); - if (ret < 0) { - fusb302_log(chip, "cannot set SRC interrupt, ret=%d", - ret); - goto done; - } - chip->intr_comp_chng = true; -+ chip->intr_bc_lvl = false; - break; - case TYPEC_CC_RD: - ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, - FUSB_REG_MASK_BC_LVL | - FUSB_REG_MASK_COMP_CHNG, -- FUSB_REG_MASK_BC_LVL); -+ FUSB_REG_MASK_COMP_CHNG); - if (ret < 0) { - fusb302_log(chip, "cannot set SRC interrupt, ret=%d", - ret); - goto done; - } - chip->intr_bc_lvl = true; -+ chip->intr_comp_chng = false; - break; - default: - break; -diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c -index 7f2f3ff1b3911..59d4fa2443f2b 100644 ---- a/drivers/usb/typec/tcpm/tcpm.c -+++ b/drivers/usb/typec/tcpm/tcpm.c -@@ -324,6 +324,7 @@ struct tcpm_port { - - bool attached; - bool connected; -+ bool registered; - bool pd_supported; - enum typec_port_type port_type; - -@@ -4110,11 +4111,7 @@ static void run_state_machine(struct tcpm_port *port) - tcpm_try_src(port) ? SRC_TRY - : SNK_ATTACHED, - 0); -- else -- /* Wait for VBUS, but not forever */ -- tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON); - break; -- - case SRC_TRY: - port->try_src_count++; - tcpm_set_cc(port, tcpm_rp_cc(port)); -@@ -6295,7 +6292,8 @@ static enum hrtimer_restart state_machine_timer_handler(struct hrtimer *timer) - { - struct tcpm_port *port = container_of(timer, struct tcpm_port, state_machine_timer); - -- kthread_queue_work(port->wq, &port->state_machine); -+ if (port->registered) -+ kthread_queue_work(port->wq, &port->state_machine); - return HRTIMER_NORESTART; - } - -@@ -6303,7 +6301,8 @@ static enum hrtimer_restart vdm_state_machine_timer_handler(struct hrtimer *time - { - struct tcpm_port *port = container_of(timer, struct tcpm_port, vdm_state_machine_timer); - -- kthread_queue_work(port->wq, &port->vdm_state_machine); -+ if (port->registered) -+ kthread_queue_work(port->wq, &port->vdm_state_machine); - return HRTIMER_NORESTART; - } - -@@ -6311,7 +6310,8 @@ static enum hrtimer_restart enable_frs_timer_handler(struct hrtimer *timer) - { - struct tcpm_port *port = container_of(timer, struct tcpm_port, enable_frs_timer); - -- kthread_queue_work(port->wq, &port->enable_frs); -+ if (port->registered) -+ kthread_queue_work(port->wq, &port->enable_frs); - return HRTIMER_NORESTART; - } - -@@ -6319,7 +6319,8 @@ static enum hrtimer_restart send_discover_timer_handler(struct hrtimer *timer) - { - struct tcpm_port *port = container_of(timer, struct tcpm_port, send_discover_timer); - -- kthread_queue_work(port->wq, &port->send_discover_work); -+ if (port->registered) -+ kthread_queue_work(port->wq, &port->send_discover_work); - return HRTIMER_NORESTART; - } - -@@ -6407,6 +6408,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) - typec_port_register_altmodes(port->typec_port, - &tcpm_altmode_ops, port, - port->port_altmode, ALTMODE_DISCOVERY_MAX); -+ port->registered = true; - - mutex_lock(&port->lock); - tcpm_init(port); -@@ -6428,6 +6430,9 @@ void tcpm_unregister_port(struct tcpm_port *port) - { - int i; - -+ port->registered = false; -+ kthread_destroy_worker(port->wq); -+ - hrtimer_cancel(&port->send_discover_timer); - hrtimer_cancel(&port->enable_frs_timer); - hrtimer_cancel(&port->vdm_state_machine_timer); -@@ -6439,7 +6444,6 @@ void tcpm_unregister_port(struct tcpm_port *port) - typec_unregister_port(port->typec_port); - usb_role_switch_put(port->role_sw); - tcpm_debugfs_exit(port); -- kthread_destroy_worker(port->wq); - } - EXPORT_SYMBOL_GPL(tcpm_unregister_port); - -diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c -index ea4cc0a6e40cc..97f50f301f13b 100644 ---- a/drivers/usb/typec/tipd/core.c -+++ b/drivers/usb/typec/tipd/core.c -@@ -117,7 +117,7 @@ tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len) - u8 data[TPS_MAX_LEN + 1]; - int ret; - -- if (WARN_ON(len + 1 > sizeof(data))) -+ if (len + 1 > sizeof(data)) - return -EINVAL; - - if (!tps->i2c_protocol) -diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c -index bd56de7484dcb..ae85d2dd6eb76 100644 ---- a/drivers/vdpa/mlx5/net/mlx5_vnet.c -+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c -@@ -2192,7 +2192,6 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) - clear_vqs_ready(ndev); - mlx5_vdpa_destroy_mr(&ndev->mvdev); - ndev->mvdev.status = 0; -- ndev->mvdev.mlx_features = 0; - memset(ndev->event_cbs, 0, sizeof(ndev->event_cbs)); - ndev->mvdev.actual_features = 0; - ++mvdev->generation; -diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c -index 1dc121a07a934..12bf3d16a40ff 100644 ---- a/drivers/vdpa/vdpa.c -+++ b/drivers/vdpa/vdpa.c -@@ -353,7 +353,8 @@ static int vdpa_mgmtdev_fill(const struct vdpa_mgmt_dev *mdev, struct sk_buff *m - goto msg_err; - - while (mdev->id_table[i].device) { -- supported_classes |= BIT(mdev->id_table[i].device); -+ if (mdev->id_table[i].device <= 63) -+ supported_classes |= BIT_ULL(mdev->id_table[i].device); - i++; - } - -diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c -index 5f484fff8dbec..41b0cd17fcbac 100644 ---- a/drivers/vdpa/vdpa_sim/vdpa_sim.c -+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c -@@ -591,8 +591,11 @@ static void vdpasim_free(struct vdpa_device *vdpa) - vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov); - } - -- put_iova_domain(&vdpasim->iova); -- iova_cache_put(); -+ if (vdpa_get_dma_dev(vdpa)) { -+ put_iova_domain(&vdpasim->iova); -+ iova_cache_put(); -+ } -+ - kvfree(vdpasim->buffer); - if (vdpasim->iommu) - vhost_iotlb_free(vdpasim->iommu); -diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c -index 841667a896dd0..8c3de5a76282a 100644 ---- a/drivers/vdpa/vdpa_user/vduse_dev.c -+++ b/drivers/vdpa/vdpa_user/vduse_dev.c -@@ -655,7 +655,8 @@ static void vduse_vdpa_get_config(struct vdpa_device *vdpa, unsigned int offset, - { - struct vduse_dev *dev = vdpa_to_vduse(vdpa); - -- if (len > dev->config_size - offset) -+ if (offset > dev->config_size || -+ len > dev->config_size - offset) - return; - - memcpy(buf, dev->config + offset, len); -@@ -975,7 +976,8 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, - break; - - ret = -EINVAL; -- if (config.length == 0 || -+ if (config.offset > dev->config_size || -+ config.length == 0 || - config.length > dev->config_size - config.offset) - break; - -diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c -index 39039e0461175..d62f05d056b7b 100644 ---- a/drivers/vhost/vdpa.c -+++ b/drivers/vhost/vdpa.c -@@ -197,7 +197,7 @@ static int vhost_vdpa_config_validate(struct vhost_vdpa *v, - struct vdpa_device *vdpa = v->vdpa; - long size = vdpa->config->get_config_size(vdpa); - -- if (c->len == 0) -+ if (c->len == 0 || c->off > size) - return -EINVAL; - - if (c->len > size - c->off) -diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c -index 938aefbc75ecc..4e3b95af7ee4d 100644 ---- a/drivers/vhost/vsock.c -+++ b/drivers/vhost/vsock.c -@@ -554,7 +554,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) - virtio_transport_free_pkt(pkt); - - len += sizeof(pkt->hdr); -- vhost_add_used(vq, head, len); -+ vhost_add_used(vq, head, 0); - total_len += len; - added = true; - } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); -diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c -index 537fe1b376ad7..fc990e576340b 100644 ---- a/drivers/video/backlight/backlight.c -+++ b/drivers/video/backlight/backlight.c -@@ -688,12 +688,6 @@ static struct backlight_device *of_find_backlight(struct device *dev) - of_node_put(np); - if (!bd) - return ERR_PTR(-EPROBE_DEFER); -- /* -- * Note: gpio_backlight uses brightness as -- * power state during probe -- */ -- if (!bd->props.brightness) -- bd->props.brightness = bd->props.max_brightness; - } - } - -diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c -index 1b451165311c9..40496e9e9b438 100644 ---- a/drivers/video/console/sticon.c -+++ b/drivers/video/console/sticon.c -@@ -332,13 +332,13 @@ static u8 sticon_build_attr(struct vc_data *conp, u8 color, - bool blink, bool underline, bool reverse, - bool italic) - { -- u8 attr = ((color & 0x70) >> 1) | ((color & 7)); -+ u8 fg = color & 7; -+ u8 bg = (color & 0x70) >> 4; - -- if (reverse) { -- color = ((color >> 3) & 0x7) | ((color & 0x7) << 3); -- } -- -- return attr; -+ if (reverse) -+ return (fg << 3) | bg; -+ else -+ return (bg << 3) | fg; - } - - static void sticon_invert_region(struct vc_data *conp, u16 *p, int count) -diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c -index ef9c57ce09066..9a49ea6b5112f 100644 ---- a/drivers/video/console/vgacon.c -+++ b/drivers/video/console/vgacon.c -@@ -366,11 +366,17 @@ static void vgacon_init(struct vc_data *c, int init) - struct uni_pagedir *p; - - /* -- * We cannot be loaded as a module, therefore init is always 1, -- * but vgacon_init can be called more than once, and init will -- * not be 1. -+ * We cannot be loaded as a module, therefore init will be 1 -+ * if we are the default console, however if we are a fallback -+ * console, for example if fbcon has failed registration, then -+ * init will be 0, so we need to make sure our boot parameters -+ * have been copied to the console structure for vgacon_resize -+ * ultimately called by vc_resize. Any subsequent calls to -+ * vgacon_init init will have init set to 0 too. - */ - c->vc_can_do_color = vga_can_do_color; -+ c->vc_scan_lines = vga_scan_lines; -+ c->vc_font.height = c->vc_cell_height = vga_video_font_height; - - /* set dimensions manually if init != 0 since vc_resize() will fail */ - if (init) { -@@ -379,8 +385,6 @@ static void vgacon_init(struct vc_data *c, int init) - } else - vc_resize(c, vga_video_num_columns, vga_video_num_lines); - -- c->vc_scan_lines = vga_scan_lines; -- c->vc_font.height = c->vc_cell_height = vga_video_font_height; - c->vc_complement_mask = 0x7700; - if (vga_512_chars) - c->vc_hi_font_mask = 0x0800; -diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c -index 998067b701fa0..393894af26f84 100644 ---- a/drivers/video/fbdev/chipsfb.c -+++ b/drivers/video/fbdev/chipsfb.c -@@ -331,7 +331,7 @@ static const struct fb_var_screeninfo chipsfb_var = { - - static void init_chips(struct fb_info *p, unsigned long addr) - { -- memset(p->screen_base, 0, 0x100000); -+ fb_memset(p->screen_base, 0, 0x100000); - - p->fix = chipsfb_fix; - p->fix.smem_start = addr; -diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c -index 8ea8f079cde26..ea42ba6445b2d 100644 ---- a/drivers/video/fbdev/efifb.c -+++ b/drivers/video/fbdev/efifb.c -@@ -47,6 +47,8 @@ static bool use_bgrt = true; - static bool request_mem_succeeded = false; - static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC; - -+static struct pci_dev *efifb_pci_dev; /* dev with BAR covering the efifb */ -+ - static struct fb_var_screeninfo efifb_defined = { - .activate = FB_ACTIVATE_NOW, - .height = -1, -@@ -243,6 +245,9 @@ static inline void efifb_show_boot_graphics(struct fb_info *info) {} - - static void efifb_destroy(struct fb_info *info) - { -+ if (efifb_pci_dev) -+ pm_runtime_put(&efifb_pci_dev->dev); -+ - if (info->screen_base) { - if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) - iounmap(info->screen_base); -@@ -333,7 +338,6 @@ ATTRIBUTE_GROUPS(efifb); - - static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */ - --static struct pci_dev *efifb_pci_dev; /* dev with BAR covering the efifb */ - static struct resource *bar_resource; - static u64 bar_offset; - -@@ -347,6 +351,17 @@ static int efifb_probe(struct platform_device *dev) - char *option = NULL; - efi_memory_desc_t md; - -+ /* -+ * Generic drivers must not be registered if a framebuffer exists. -+ * If a native driver was probed, the display hardware was already -+ * taken and attempting to use the system framebuffer is dangerous. -+ */ -+ if (num_registered_fb > 0) { -+ dev_err(&dev->dev, -+ "efifb: a framebuffer is already registered\n"); -+ return -EINVAL; -+ } -+ - if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled) - return -ENODEV; - -@@ -569,17 +584,22 @@ static int efifb_probe(struct platform_device *dev) - pr_err("efifb: cannot allocate colormap\n"); - goto err_groups; - } -+ -+ if (efifb_pci_dev) -+ WARN_ON(pm_runtime_get_sync(&efifb_pci_dev->dev) < 0); -+ - err = register_framebuffer(info); - if (err < 0) { - pr_err("efifb: cannot register framebuffer\n"); -- goto err_fb_dealoc; -+ goto err_put_rpm_ref; - } - fb_info(info, "%s frame buffer device\n", info->fix.id); -- if (efifb_pci_dev) -- pm_runtime_get_sync(&efifb_pci_dev->dev); - return 0; - --err_fb_dealoc: -+err_put_rpm_ref: -+ if (efifb_pci_dev) -+ pm_runtime_put(&efifb_pci_dev->dev); -+ - fb_dealloc_cmap(&info->cmap); - err_groups: - sysfs_remove_groups(&dev->dev.kobj, efifb_groups); -@@ -603,8 +623,6 @@ static int efifb_remove(struct platform_device *pdev) - unregister_framebuffer(info); - sysfs_remove_groups(&pdev->dev.kobj, efifb_groups); - framebuffer_release(info); -- if (efifb_pci_dev) -- pm_runtime_put(&efifb_pci_dev->dev); - - return 0; - } -diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c -index 62f0ded706815..b63074fd892e5 100644 ---- a/drivers/video/fbdev/simplefb.c -+++ b/drivers/video/fbdev/simplefb.c -@@ -407,6 +407,17 @@ static int simplefb_probe(struct platform_device *pdev) - struct simplefb_par *par; - struct resource *mem; - -+ /* -+ * Generic drivers must not be registered if a framebuffer exists. -+ * If a native driver was probed, the display hardware was already -+ * taken and attempting to use the system framebuffer is dangerous. -+ */ -+ if (num_registered_fb > 0) { -+ dev_err(&pdev->dev, -+ "simplefb: a framebuffer is already registered\n"); -+ return -EINVAL; -+ } -+ - if (fb_get_options("simplefb", NULL)) - return -ENODEV; - -diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c -index 3035bb6f54585..9919407973cd5 100644 ---- a/drivers/virtio/virtio_ring.c -+++ b/drivers/virtio/virtio_ring.c -@@ -268,7 +268,7 @@ size_t virtio_max_dma_size(struct virtio_device *vdev) - size_t max_segment_size = SIZE_MAX; - - if (vring_use_dma_api(vdev)) -- max_segment_size = dma_max_mapping_size(&vdev->dev); -+ max_segment_size = dma_max_mapping_size(vdev->dev.parent); - - return max_segment_size; - } -@@ -1065,6 +1065,8 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, - - head = vq->packed.next_avail_idx; - desc = alloc_indirect_packed(total_sg, gfp); -+ if (!desc) -+ return -ENOMEM; - - if (unlikely(vq->vq.num_free < 1)) { - pr_debug("Can't add buf len 1 - avail = 0\n"); -@@ -1176,6 +1178,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, - unsigned int i, n, c, descs_used, err_idx; - __le16 head_flags, flags; - u16 head, id, prev, curr, avail_used_flags; -+ int err; - - START_USE(vq); - -@@ -1191,9 +1194,14 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, - - BUG_ON(total_sg == 0); - -- if (virtqueue_use_indirect(_vq, total_sg)) -- return virtqueue_add_indirect_packed(vq, sgs, total_sg, -- out_sgs, in_sgs, data, gfp); -+ if (virtqueue_use_indirect(_vq, total_sg)) { -+ err = virtqueue_add_indirect_packed(vq, sgs, total_sg, out_sgs, -+ in_sgs, data, gfp); -+ if (err != -ENOMEM) -+ return err; -+ -+ /* fall back on direct */ -+ } - - head = vq->packed.next_avail_idx; - avail_used_flags = vq->packed.avail_used_flags; -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index bf59faeb3de1b..d937f957f8df8 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1679,7 +1679,7 @@ config SIBYTE_WDOG - - config AR7_WDT - tristate "TI AR7 Watchdog Timer" -- depends on AR7 || (MIPS && COMPILE_TEST) -+ depends on AR7 || (MIPS && 32BIT && COMPILE_TEST) - help - Hardware driver for the TI AR7 Watchdog Timer. - -diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c -index f60beec1bbaea..f7d82d2619133 100644 ---- a/drivers/watchdog/f71808e_wdt.c -+++ b/drivers/watchdog/f71808e_wdt.c -@@ -228,15 +228,17 @@ static int watchdog_set_timeout(int timeout) - - mutex_lock(&watchdog.lock); - -- watchdog.timeout = timeout; - if (timeout > 0xff) { - watchdog.timer_val = DIV_ROUND_UP(timeout, 60); - watchdog.minutes_mode = true; -+ timeout = watchdog.timer_val * 60; - } else { - watchdog.timer_val = timeout; - watchdog.minutes_mode = false; - } - -+ watchdog.timeout = timeout; -+ - mutex_unlock(&watchdog.lock); - - return 0; -diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c -index 3a50f097ed3ed..8db96b5e72536 100644 ---- a/drivers/xen/balloon.c -+++ b/drivers/xen/balloon.c -@@ -58,6 +58,7 @@ - #include <linux/percpu-defs.h> - #include <linux/slab.h> - #include <linux/sysctl.h> -+#include <linux/moduleparam.h> - - #include <asm/page.h> - #include <asm/tlb.h> -@@ -73,6 +74,12 @@ - #include <xen/page.h> - #include <xen/mem-reservation.h> - -+#undef MODULE_PARAM_PREFIX -+#define MODULE_PARAM_PREFIX "xen." -+ -+static uint __read_mostly balloon_boot_timeout = 180; -+module_param(balloon_boot_timeout, uint, 0444); -+ - static int xen_hotplug_unpopulated; - - #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG -@@ -125,12 +132,12 @@ static struct ctl_table xen_root[] = { - * BP_ECANCELED: error, balloon operation canceled. - */ - --enum bp_state { -+static enum bp_state { - BP_DONE, - BP_WAIT, - BP_EAGAIN, - BP_ECANCELED --}; -+} balloon_state = BP_DONE; - - /* Main waiting point for xen-balloon thread. */ - static DECLARE_WAIT_QUEUE_HEAD(balloon_thread_wq); -@@ -199,18 +206,15 @@ static struct page *balloon_next_page(struct page *page) - return list_entry(next, struct page, lru); - } - --static enum bp_state update_schedule(enum bp_state state) -+static void update_schedule(void) - { -- if (state == BP_WAIT) -- return BP_WAIT; -- -- if (state == BP_ECANCELED) -- return BP_ECANCELED; -+ if (balloon_state == BP_WAIT || balloon_state == BP_ECANCELED) -+ return; - -- if (state == BP_DONE) { -+ if (balloon_state == BP_DONE) { - balloon_stats.schedule_delay = 1; - balloon_stats.retry_count = 1; -- return BP_DONE; -+ return; - } - - ++balloon_stats.retry_count; -@@ -219,7 +223,8 @@ static enum bp_state update_schedule(enum bp_state state) - balloon_stats.retry_count > balloon_stats.max_retry_count) { - balloon_stats.schedule_delay = 1; - balloon_stats.retry_count = 1; -- return BP_ECANCELED; -+ balloon_state = BP_ECANCELED; -+ return; - } - - balloon_stats.schedule_delay <<= 1; -@@ -227,7 +232,7 @@ static enum bp_state update_schedule(enum bp_state state) - if (balloon_stats.schedule_delay > balloon_stats.max_schedule_delay) - balloon_stats.schedule_delay = balloon_stats.max_schedule_delay; - -- return BP_EAGAIN; -+ balloon_state = BP_EAGAIN; - } - - #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG -@@ -494,9 +499,9 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) - * Stop waiting if either state is BP_DONE and ballooning action is - * needed, or if the credit has changed while state is not BP_DONE. - */ --static bool balloon_thread_cond(enum bp_state state, long credit) -+static bool balloon_thread_cond(long credit) - { -- if (state == BP_DONE) -+ if (balloon_state == BP_DONE) - credit = 0; - - return current_credit() != credit || kthread_should_stop(); -@@ -510,13 +515,12 @@ static bool balloon_thread_cond(enum bp_state state, long credit) - */ - static int balloon_thread(void *unused) - { -- enum bp_state state = BP_DONE; - long credit; - unsigned long timeout; - - set_freezable(); - for (;;) { -- switch (state) { -+ switch (balloon_state) { - case BP_DONE: - case BP_ECANCELED: - timeout = 3600 * HZ; -@@ -532,7 +536,7 @@ static int balloon_thread(void *unused) - credit = current_credit(); - - wait_event_freezable_timeout(balloon_thread_wq, -- balloon_thread_cond(state, credit), timeout); -+ balloon_thread_cond(credit), timeout); - - if (kthread_should_stop()) - return 0; -@@ -543,22 +547,23 @@ static int balloon_thread(void *unused) - - if (credit > 0) { - if (balloon_is_inflated()) -- state = increase_reservation(credit); -+ balloon_state = increase_reservation(credit); - else -- state = reserve_additional_memory(); -+ balloon_state = reserve_additional_memory(); - } - - if (credit < 0) { - long n_pages; - - n_pages = min(-credit, si_mem_available()); -- state = decrease_reservation(n_pages, GFP_BALLOON); -- if (state == BP_DONE && n_pages != -credit && -+ balloon_state = decrease_reservation(n_pages, -+ GFP_BALLOON); -+ if (balloon_state == BP_DONE && n_pages != -credit && - n_pages < totalreserve_pages) -- state = BP_EAGAIN; -+ balloon_state = BP_EAGAIN; - } - -- state = update_schedule(state); -+ update_schedule(); - - mutex_unlock(&balloon_mutex); - -@@ -765,3 +770,38 @@ static int __init balloon_init(void) - return 0; - } - subsys_initcall(balloon_init); -+ -+static int __init balloon_wait_finish(void) -+{ -+ long credit, last_credit = 0; -+ unsigned long last_changed = 0; -+ -+ if (!xen_domain()) -+ return -ENODEV; -+ -+ /* PV guests don't need to wait. */ -+ if (xen_pv_domain() || !current_credit()) -+ return 0; -+ -+ pr_notice("Waiting for initial ballooning down having finished.\n"); -+ -+ while ((credit = current_credit()) < 0) { -+ if (credit != last_credit) { -+ last_changed = jiffies; -+ last_credit = credit; -+ } -+ if (balloon_state == BP_ECANCELED) { -+ pr_warn_once("Initial ballooning failed, %ld pages need to be freed.\n", -+ -credit); -+ if (jiffies - last_changed >= HZ * balloon_boot_timeout) -+ panic("Initial ballooning failed!\n"); -+ } -+ -+ schedule_timeout_interruptible(HZ / 10); -+ } -+ -+ pr_notice("Initial ballooning down finished.\n"); -+ -+ return 0; -+} -+late_initcall_sync(balloon_wait_finish); -diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c -index a78704ae36186..46d9295d9a6e4 100644 ---- a/drivers/xen/events/events_base.c -+++ b/drivers/xen/events/events_base.c -@@ -1251,6 +1251,12 @@ int bind_evtchn_to_irq(evtchn_port_t evtchn) - } - EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); - -+int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn) -+{ -+ return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL); -+} -+EXPORT_SYMBOL_GPL(bind_evtchn_to_irq_lateeoi); -+ - static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) - { - struct evtchn_bind_ipi bind_ipi; -diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c -index 22f13abbe9130..5e53b4817f167 100644 ---- a/drivers/xen/xen-pciback/conf_space_capability.c -+++ b/drivers/xen/xen-pciback/conf_space_capability.c -@@ -160,7 +160,7 @@ static void *pm_ctrl_init(struct pci_dev *dev, int offset) - } - - out: -- return ERR_PTR(err); -+ return err ? ERR_PTR(err) : NULL; - } - - static const struct config_field caplist_pm[] = { -diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c -index bd003ca8acbe9..fe360c33ce717 100644 ---- a/drivers/xen/xenbus/xenbus_probe.c -+++ b/drivers/xen/xenbus/xenbus_probe.c -@@ -909,7 +909,7 @@ static struct notifier_block xenbus_resume_nb = { - - static int __init xenbus_init(void) - { -- int err = 0; -+ int err; - uint64_t v = 0; - xen_store_domain_type = XS_UNKNOWN; - -@@ -949,6 +949,29 @@ static int __init xenbus_init(void) - err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); - if (err) - goto out_error; -+ /* -+ * Uninitialized hvm_params are zero and return no error. -+ * Although it is theoretically possible to have -+ * HVM_PARAM_STORE_PFN set to zero on purpose, in reality it is -+ * not zero when valid. If zero, it means that Xenstore hasn't -+ * been properly initialized. Instead of attempting to map a -+ * wrong guest physical address return error. -+ * -+ * Also recognize all bits set as an invalid value. -+ */ -+ if (!v || !~v) { -+ err = -ENOENT; -+ goto out_error; -+ } -+ /* Avoid truncation on 32-bit. */ -+#if BITS_PER_LONG == 32 -+ if (v > ULONG_MAX) { -+ pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n", -+ __func__, v); -+ err = -EINVAL; -+ goto out_error; -+ } -+#endif - xen_store_gfn = (unsigned long)v; - xen_store_interface = - xen_remap(xen_store_gfn << XEN_PAGE_SHIFT, -@@ -983,8 +1006,10 @@ static int __init xenbus_init(void) - */ - proc_create_mount_point("xen"); - #endif -+ return 0; - - out_error: -+ xen_store_domain_type = XS_UNKNOWN; - return err; - } - -diff --git a/fs/afs/file.c b/fs/afs/file.c -index e6c447ae91f38..b165377179c3c 100644 ---- a/fs/afs/file.c -+++ b/fs/afs/file.c -@@ -502,8 +502,9 @@ static void afs_add_open_mmap(struct afs_vnode *vnode) - if (atomic_inc_return(&vnode->cb_nr_mmap) == 1) { - down_write(&vnode->volume->cell->fs_open_mmaps_lock); - -- list_add_tail(&vnode->cb_mmap_link, -- &vnode->volume->cell->fs_open_mmaps); -+ if (list_empty(&vnode->cb_mmap_link)) -+ list_add_tail(&vnode->cb_mmap_link, -+ &vnode->volume->cell->fs_open_mmaps); - - up_write(&vnode->volume->cell->fs_open_mmaps_lock); - } -diff --git a/fs/afs/super.c b/fs/afs/super.c -index d110def8aa8eb..34c68724c98be 100644 ---- a/fs/afs/super.c -+++ b/fs/afs/super.c -@@ -667,6 +667,7 @@ static void afs_i_init_once(void *_vnode) - INIT_LIST_HEAD(&vnode->pending_locks); - INIT_LIST_HEAD(&vnode->granted_locks); - INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work); -+ INIT_LIST_HEAD(&vnode->cb_mmap_link); - seqlock_init(&vnode->cb_lock); - } - -diff --git a/fs/aio.c b/fs/aio.c -index 51b08ab01dffc..1a78979663dca 100644 ---- a/fs/aio.c -+++ b/fs/aio.c -@@ -181,8 +181,9 @@ struct poll_iocb { - struct file *file; - struct wait_queue_head *head; - __poll_t events; -- bool done; - bool cancelled; -+ bool work_scheduled; -+ bool work_need_resched; - struct wait_queue_entry wait; - struct work_struct work; - }; -@@ -1620,6 +1621,51 @@ static void aio_poll_put_work(struct work_struct *work) - iocb_put(iocb); - } - -+/* -+ * Safely lock the waitqueue which the request is on, synchronizing with the -+ * case where the ->poll() provider decides to free its waitqueue early. -+ * -+ * Returns true on success, meaning that req->head->lock was locked, req->wait -+ * is on req->head, and an RCU read lock was taken. Returns false if the -+ * request was already removed from its waitqueue (which might no longer exist). -+ */ -+static bool poll_iocb_lock_wq(struct poll_iocb *req) -+{ -+ wait_queue_head_t *head; -+ -+ /* -+ * While we hold the waitqueue lock and the waitqueue is nonempty, -+ * wake_up_pollfree() will wait for us. However, taking the waitqueue -+ * lock in the first place can race with the waitqueue being freed. -+ * -+ * We solve this as eventpoll does: by taking advantage of the fact that -+ * all users of wake_up_pollfree() will RCU-delay the actual free. If -+ * we enter rcu_read_lock() and see that the pointer to the queue is -+ * non-NULL, we can then lock it without the memory being freed out from -+ * under us, then check whether the request is still on the queue. -+ * -+ * Keep holding rcu_read_lock() as long as we hold the queue lock, in -+ * case the caller deletes the entry from the queue, leaving it empty. -+ * In that case, only RCU prevents the queue memory from being freed. -+ */ -+ rcu_read_lock(); -+ head = smp_load_acquire(&req->head); -+ if (head) { -+ spin_lock(&head->lock); -+ if (!list_empty(&req->wait.entry)) -+ return true; -+ spin_unlock(&head->lock); -+ } -+ rcu_read_unlock(); -+ return false; -+} -+ -+static void poll_iocb_unlock_wq(struct poll_iocb *req) -+{ -+ spin_unlock(&req->head->lock); -+ rcu_read_unlock(); -+} -+ - static void aio_poll_complete_work(struct work_struct *work) - { - struct poll_iocb *req = container_of(work, struct poll_iocb, work); -@@ -1639,14 +1685,27 @@ static void aio_poll_complete_work(struct work_struct *work) - * avoid further branches in the fast path. - */ - spin_lock_irq(&ctx->ctx_lock); -- if (!mask && !READ_ONCE(req->cancelled)) { -- add_wait_queue(req->head, &req->wait); -- spin_unlock_irq(&ctx->ctx_lock); -- return; -- } -+ if (poll_iocb_lock_wq(req)) { -+ if (!mask && !READ_ONCE(req->cancelled)) { -+ /* -+ * The request isn't actually ready to be completed yet. -+ * Reschedule completion if another wakeup came in. -+ */ -+ if (req->work_need_resched) { -+ schedule_work(&req->work); -+ req->work_need_resched = false; -+ } else { -+ req->work_scheduled = false; -+ } -+ poll_iocb_unlock_wq(req); -+ spin_unlock_irq(&ctx->ctx_lock); -+ return; -+ } -+ list_del_init(&req->wait.entry); -+ poll_iocb_unlock_wq(req); -+ } /* else, POLLFREE has freed the waitqueue, so we must complete */ - list_del_init(&iocb->ki_list); - iocb->ki_res.res = mangle_poll(mask); -- req->done = true; - spin_unlock_irq(&ctx->ctx_lock); - - iocb_put(iocb); -@@ -1658,13 +1717,14 @@ static int aio_poll_cancel(struct kiocb *iocb) - struct aio_kiocb *aiocb = container_of(iocb, struct aio_kiocb, rw); - struct poll_iocb *req = &aiocb->poll; - -- spin_lock(&req->head->lock); -- WRITE_ONCE(req->cancelled, true); -- if (!list_empty(&req->wait.entry)) { -- list_del_init(&req->wait.entry); -- schedule_work(&aiocb->poll.work); -- } -- spin_unlock(&req->head->lock); -+ if (poll_iocb_lock_wq(req)) { -+ WRITE_ONCE(req->cancelled, true); -+ if (!req->work_scheduled) { -+ schedule_work(&aiocb->poll.work); -+ req->work_scheduled = true; -+ } -+ poll_iocb_unlock_wq(req); -+ } /* else, the request was force-cancelled by POLLFREE already */ - - return 0; - } -@@ -1681,21 +1741,27 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, - if (mask && !(mask & req->events)) - return 0; - -- list_del_init(&req->wait.entry); -- -- if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { -+ /* -+ * Complete the request inline if possible. This requires that three -+ * conditions be met: -+ * 1. An event mask must have been passed. If a plain wakeup was done -+ * instead, then mask == 0 and we have to call vfs_poll() to get -+ * the events, so inline completion isn't possible. -+ * 2. The completion work must not have already been scheduled. -+ * 3. ctx_lock must not be busy. We have to use trylock because we -+ * already hold the waitqueue lock, so this inverts the normal -+ * locking order. Use irqsave/irqrestore because not all -+ * filesystems (e.g. fuse) call this function with IRQs disabled, -+ * yet IRQs have to be disabled before ctx_lock is obtained. -+ */ -+ if (mask && !req->work_scheduled && -+ spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { - struct kioctx *ctx = iocb->ki_ctx; - -- /* -- * Try to complete the iocb inline if we can. Use -- * irqsave/irqrestore because not all filesystems (e.g. fuse) -- * call this function with IRQs disabled and because IRQs -- * have to be disabled before ctx_lock is obtained. -- */ -+ list_del_init(&req->wait.entry); - list_del(&iocb->ki_list); - iocb->ki_res.res = mangle_poll(mask); -- req->done = true; -- if (iocb->ki_eventfd && eventfd_signal_allowed()) { -+ if (iocb->ki_eventfd && !eventfd_signal_allowed()) { - iocb = NULL; - INIT_WORK(&req->work, aio_poll_put_work); - schedule_work(&req->work); -@@ -1704,7 +1770,43 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, - if (iocb) - iocb_put(iocb); - } else { -- schedule_work(&req->work); -+ /* -+ * Schedule the completion work if needed. If it was already -+ * scheduled, record that another wakeup came in. -+ * -+ * Don't remove the request from the waitqueue here, as it might -+ * not actually be complete yet (we won't know until vfs_poll() -+ * is called), and we must not miss any wakeups. POLLFREE is an -+ * exception to this; see below. -+ */ -+ if (req->work_scheduled) { -+ req->work_need_resched = true; -+ } else { -+ schedule_work(&req->work); -+ req->work_scheduled = true; -+ } -+ -+ /* -+ * If the waitqueue is being freed early but we can't complete -+ * the request inline, we have to tear down the request as best -+ * we can. That means immediately removing the request from its -+ * waitqueue and preventing all further accesses to the -+ * waitqueue via the request. We also need to schedule the -+ * completion work (done above). Also mark the request as -+ * cancelled, to potentially skip an unneeded call to ->poll(). -+ */ -+ if (mask & POLLFREE) { -+ WRITE_ONCE(req->cancelled, true); -+ list_del_init(&req->wait.entry); -+ -+ /* -+ * Careful: this *must* be the last step, since as soon -+ * as req->head is NULL'ed out, the request can be -+ * completed and freed, since aio_poll_complete_work() -+ * will no longer need to take the waitqueue lock. -+ */ -+ smp_store_release(&req->head, NULL); -+ } - } - return 1; - } -@@ -1712,6 +1814,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, - struct aio_poll_table { - struct poll_table_struct pt; - struct aio_kiocb *iocb; -+ bool queued; - int error; - }; - -@@ -1722,11 +1825,12 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head, - struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt); - - /* multiple wait queues per file are not supported */ -- if (unlikely(pt->iocb->poll.head)) { -+ if (unlikely(pt->queued)) { - pt->error = -EINVAL; - return; - } - -+ pt->queued = true; - pt->error = 0; - pt->iocb->poll.head = head; - add_wait_queue(head, &pt->iocb->poll.wait); -@@ -1751,12 +1855,14 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) - req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP; - - req->head = NULL; -- req->done = false; - req->cancelled = false; -+ req->work_scheduled = false; -+ req->work_need_resched = false; - - apt.pt._qproc = aio_poll_queue_proc; - apt.pt._key = req->events; - apt.iocb = aiocb; -+ apt.queued = false; - apt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */ - - /* initialized the list so that we can do list_empty checks */ -@@ -1765,23 +1871,35 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) - - mask = vfs_poll(req->file, &apt.pt) & req->events; - spin_lock_irq(&ctx->ctx_lock); -- if (likely(req->head)) { -- spin_lock(&req->head->lock); -- if (unlikely(list_empty(&req->wait.entry))) { -- if (apt.error) -+ if (likely(apt.queued)) { -+ bool on_queue = poll_iocb_lock_wq(req); -+ -+ if (!on_queue || req->work_scheduled) { -+ /* -+ * aio_poll_wake() already either scheduled the async -+ * completion work, or completed the request inline. -+ */ -+ if (apt.error) /* unsupported case: multiple queues */ - cancel = true; - apt.error = 0; - mask = 0; - } - if (mask || apt.error) { -+ /* Steal to complete synchronously. */ - list_del_init(&req->wait.entry); - } else if (cancel) { -+ /* Cancel if possible (may be too late though). */ - WRITE_ONCE(req->cancelled, true); -- } else if (!req->done) { /* actually waiting for an event */ -+ } else if (on_queue) { -+ /* -+ * Actually waiting for an event, so add the request to -+ * active_reqs so that it can be cancelled if needed. -+ */ - list_add_tail(&aiocb->ki_list, &ctx->active_reqs); - aiocb->ki_cancel = aio_poll_cancel; - } -- spin_unlock(&req->head->lock); -+ if (on_queue) -+ poll_iocb_unlock_wq(req); - } - if (mask) { /* no async, we'd stolen it */ - aiocb->ki_res.res = mangle_poll(mask); -diff --git a/fs/attr.c b/fs/attr.c -index 473d21b3a86de..66899b6e9bd86 100644 ---- a/fs/attr.c -+++ b/fs/attr.c -@@ -35,7 +35,7 @@ static bool chown_ok(struct user_namespace *mnt_userns, - kuid_t uid) - { - kuid_t kuid = i_uid_into_mnt(mnt_userns, inode); -- if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, kuid)) -+ if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, inode->i_uid)) - return true; - if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN)) - return true; -@@ -62,7 +62,7 @@ static bool chgrp_ok(struct user_namespace *mnt_userns, - { - kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); - if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode)) && -- (in_group_p(gid) || gid_eq(gid, kgid))) -+ (in_group_p(gid) || gid_eq(gid, inode->i_gid))) - return true; - if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN)) - return true; -diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c -index 309516e6a9682..43c89952b7d25 100644 ---- a/fs/btrfs/async-thread.c -+++ b/fs/btrfs/async-thread.c -@@ -234,6 +234,13 @@ static void run_ordered_work(struct __btrfs_workqueue *wq, - ordered_list); - if (!test_bit(WORK_DONE_BIT, &work->flags)) - break; -+ /* -+ * Orders all subsequent loads after reading WORK_DONE_BIT, -+ * paired with the smp_mb__before_atomic in btrfs_work_helper -+ * this guarantees that the ordered function will see all -+ * updates from ordinary work function. -+ */ -+ smp_rmb(); - - /* - * we are going to call the ordered done function, but -@@ -317,6 +324,13 @@ static void btrfs_work_helper(struct work_struct *normal_work) - thresh_exec_hook(wq); - work->func(work); - if (need_order) { -+ /* -+ * Ensures all memory accesses done in the work function are -+ * ordered before setting the WORK_DONE_BIT. Ensuring the thread -+ * which is going to executed the ordered work sees them. -+ * Pairs with the smp_rmb in run_ordered_work. -+ */ -+ smp_mb__before_atomic(); - set_bit(WORK_DONE_BIT, &work->flags); - run_ordered_work(wq, work); - } else { -diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c -index a3b830b8410a8..a53ebc52bd51f 100644 ---- a/fs/btrfs/block-group.c -+++ b/fs/btrfs/block-group.c -@@ -902,6 +902,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, - spin_unlock(&cluster->refill_lock); - - btrfs_clear_treelog_bg(block_group); -+ btrfs_clear_data_reloc_bg(block_group); - - path = btrfs_alloc_path(); - if (!path) { -diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h -index c0cebcf745cef..ae06ad5593535 100644 ---- a/fs/btrfs/ctree.h -+++ b/fs/btrfs/ctree.h -@@ -1017,6 +1017,13 @@ struct btrfs_fs_info { - spinlock_t treelog_bg_lock; - u64 treelog_bg; - -+ /* -+ * Start of the dedicated data relocation block group, protected by -+ * relocation_bg_lock. -+ */ -+ spinlock_t relocation_bg_lock; -+ u64 data_reloc_bg; -+ - #ifdef CONFIG_BTRFS_FS_REF_VERIFY - spinlock_t ref_verify_lock; - struct rb_root block_tree; -@@ -3842,6 +3849,11 @@ static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info) - return fs_info->zoned != 0; - } - -+static inline bool btrfs_is_data_reloc_root(const struct btrfs_root *root) -+{ -+ return root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID; -+} -+ - /* - * We use page status Private2 to indicate there is an ordered extent with - * unfinished IO. -diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c -index 2059d1504149a..40c4d6ba3fb9a 100644 ---- a/fs/btrfs/delalloc-space.c -+++ b/fs/btrfs/delalloc-space.c -@@ -143,10 +143,13 @@ int btrfs_check_data_free_space(struct btrfs_inode *inode, - - /* Use new btrfs_qgroup_reserve_data to reserve precious data space. */ - ret = btrfs_qgroup_reserve_data(inode, reserved, start, len); -- if (ret < 0) -+ if (ret < 0) { - btrfs_free_reserved_data_space_noquota(fs_info, len); -- else -+ extent_changeset_free(*reserved); -+ *reserved = NULL; -+ } else { - ret = 0; -+ } - return ret; - } - -@@ -452,8 +455,11 @@ int btrfs_delalloc_reserve_space(struct btrfs_inode *inode, - if (ret < 0) - return ret; - ret = btrfs_delalloc_reserve_metadata(inode, len); -- if (ret < 0) -+ if (ret < 0) { - btrfs_free_reserved_data_space(inode, *reserved, start, len); -+ extent_changeset_free(*reserved); -+ *reserved = NULL; -+ } - return ret; - } - -diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c -index 355ea88d5c5f7..e1a262120e021 100644 ---- a/fs/btrfs/disk-io.c -+++ b/fs/btrfs/disk-io.c -@@ -1500,7 +1500,7 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev) - goto fail; - - if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID && -- root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { -+ !btrfs_is_data_reloc_root(root)) { - set_bit(BTRFS_ROOT_SHAREABLE, &root->state); - btrfs_check_and_init_root_item(&root->root_item); - } -@@ -1731,6 +1731,14 @@ again: - } - return root; - fail: -+ /* -+ * If our caller provided us an anonymous device, then it's his -+ * responsability to free it in case we fail. So we have to set our -+ * root's anon_dev to 0 to avoid a double free, once by btrfs_put_root() -+ * and once again by our caller. -+ */ -+ if (anon_dev) -+ root->anon_dev = 0; - btrfs_put_root(root); - return ERR_PTR(ret); - } -@@ -2883,6 +2891,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info) - spin_lock_init(&fs_info->buffer_lock); - spin_lock_init(&fs_info->unused_bgs_lock); - spin_lock_init(&fs_info->treelog_bg_lock); -+ spin_lock_init(&fs_info->relocation_bg_lock); - rwlock_init(&fs_info->tree_mod_log_lock); - mutex_init(&fs_info->unused_bg_unpin_mutex); - mutex_init(&fs_info->reclaim_bgs_lock); -@@ -3228,12 +3237,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device - mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); - btrfs_init_btree_inode(fs_info); - -- invalidate_bdev(fs_devices->latest_bdev); -+ invalidate_bdev(fs_devices->latest_dev->bdev); - - /* - * Read super block and check the signature bytes only - */ -- disk_super = btrfs_read_dev_super(fs_devices->latest_bdev); -+ disk_super = btrfs_read_dev_super(fs_devices->latest_dev->bdev); - if (IS_ERR(disk_super)) { - err = PTR_ERR(disk_super); - goto fail_alloc; -@@ -3465,7 +3474,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device - * below in btrfs_init_dev_replace(). - */ - btrfs_free_extra_devids(fs_devices); -- if (!fs_devices->latest_bdev) { -+ if (!fs_devices->latest_dev->bdev) { - btrfs_err(fs_info, "failed to read devices"); - goto fail_tree_roots; - } -@@ -3556,7 +3565,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device - goto fail_sysfs; - } - -- if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info, NULL)) { -+ if (!sb_rdonly(sb) && fs_info->fs_devices->missing_devices && -+ !btrfs_check_rw_degradable(fs_info, NULL)) { - btrfs_warn(fs_info, - "writable mount is not allowed due to too many missing devices"); - goto fail_sysfs; -@@ -3968,11 +3978,23 @@ static void btrfs_end_empty_barrier(struct bio *bio) - */ - static void write_dev_flush(struct btrfs_device *device) - { -- struct request_queue *q = bdev_get_queue(device->bdev); - struct bio *bio = device->flush_bio; - -+#ifndef CONFIG_BTRFS_FS_CHECK_INTEGRITY -+ /* -+ * When a disk has write caching disabled, we skip submission of a bio -+ * with flush and sync requests before writing the superblock, since -+ * it's not needed. However when the integrity checker is enabled, this -+ * results in reports that there are metadata blocks referred by a -+ * superblock that were not properly flushed. So don't skip the bio -+ * submission only when the integrity checker is enabled for the sake -+ * of simplicity, since this is a debug tool and not meant for use in -+ * non-debug builds. -+ */ -+ struct request_queue *q = bdev_get_queue(device->bdev); - if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) - return; -+#endif - - bio_reset(bio); - bio->bi_end_io = btrfs_end_empty_barrier; -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index 0ab456cb4bf80..87c23c5c0f26d 100644 ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -2376,7 +2376,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset, - - out: - btrfs_free_path(path); -- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) -+ if (btrfs_is_data_reloc_root(root)) - WARN_ON(ret > 0); - return ret; - } -@@ -3495,6 +3495,9 @@ struct find_free_extent_ctl { - /* Allocation is called for tree-log */ - bool for_treelog; - -+ /* Allocation is called for data relocation */ -+ bool for_data_reloc; -+ - /* RAID index, converted from flags */ - int index; - -@@ -3756,6 +3759,7 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, - u64 avail; - u64 bytenr = block_group->start; - u64 log_bytenr; -+ u64 data_reloc_bytenr; - int ret = 0; - bool skip; - -@@ -3773,13 +3777,31 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, - if (skip) - return 1; - -+ /* -+ * Do not allow non-relocation blocks in the dedicated relocation block -+ * group, and vice versa. -+ */ -+ spin_lock(&fs_info->relocation_bg_lock); -+ data_reloc_bytenr = fs_info->data_reloc_bg; -+ if (data_reloc_bytenr && -+ ((ffe_ctl->for_data_reloc && bytenr != data_reloc_bytenr) || -+ (!ffe_ctl->for_data_reloc && bytenr == data_reloc_bytenr))) -+ skip = true; -+ spin_unlock(&fs_info->relocation_bg_lock); -+ if (skip) -+ return 1; -+ - spin_lock(&space_info->lock); - spin_lock(&block_group->lock); - spin_lock(&fs_info->treelog_bg_lock); -+ spin_lock(&fs_info->relocation_bg_lock); - - ASSERT(!ffe_ctl->for_treelog || - block_group->start == fs_info->treelog_bg || - fs_info->treelog_bg == 0); -+ ASSERT(!ffe_ctl->for_data_reloc || -+ block_group->start == fs_info->data_reloc_bg || -+ fs_info->data_reloc_bg == 0); - - if (block_group->ro) { - ret = 1; -@@ -3796,6 +3818,16 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, - goto out; - } - -+ /* -+ * Do not allow currently used block group to be the data relocation -+ * dedicated block group. -+ */ -+ if (ffe_ctl->for_data_reloc && !fs_info->data_reloc_bg && -+ (block_group->used || block_group->reserved)) { -+ ret = 1; -+ goto out; -+ } -+ - avail = block_group->length - block_group->alloc_offset; - if (avail < num_bytes) { - if (ffe_ctl->max_extent_size < avail) { -@@ -3813,6 +3845,9 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, - if (ffe_ctl->for_treelog && !fs_info->treelog_bg) - fs_info->treelog_bg = block_group->start; - -+ if (ffe_ctl->for_data_reloc && !fs_info->data_reloc_bg) -+ fs_info->data_reloc_bg = block_group->start; -+ - ffe_ctl->found_offset = start + block_group->alloc_offset; - block_group->alloc_offset += num_bytes; - spin_lock(&ctl->tree_lock); -@@ -3829,6 +3864,9 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, - out: - if (ret && ffe_ctl->for_treelog) - fs_info->treelog_bg = 0; -+ if (ret && ffe_ctl->for_data_reloc) -+ fs_info->data_reloc_bg = 0; -+ spin_unlock(&fs_info->relocation_bg_lock); - spin_unlock(&fs_info->treelog_bg_lock); - spin_unlock(&block_group->lock); - spin_unlock(&space_info->lock); -@@ -4085,6 +4123,12 @@ static int prepare_allocation(struct btrfs_fs_info *fs_info, - ffe_ctl->hint_byte = fs_info->treelog_bg; - spin_unlock(&fs_info->treelog_bg_lock); - } -+ if (ffe_ctl->for_data_reloc) { -+ spin_lock(&fs_info->relocation_bg_lock); -+ if (fs_info->data_reloc_bg) -+ ffe_ctl->hint_byte = fs_info->data_reloc_bg; -+ spin_unlock(&fs_info->relocation_bg_lock); -+ } - return 0; - default: - BUG(); -@@ -4129,6 +4173,8 @@ static noinline int find_free_extent(struct btrfs_root *root, - struct btrfs_space_info *space_info; - bool full_search = false; - bool for_treelog = (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); -+ bool for_data_reloc = (btrfs_is_data_reloc_root(root) && -+ flags & BTRFS_BLOCK_GROUP_DATA); - - WARN_ON(num_bytes < fs_info->sectorsize); - -@@ -4143,6 +4189,7 @@ static noinline int find_free_extent(struct btrfs_root *root, - ffe_ctl.found_offset = 0; - ffe_ctl.hint_byte = hint_byte_orig; - ffe_ctl.for_treelog = for_treelog; -+ ffe_ctl.for_data_reloc = for_data_reloc; - ffe_ctl.policy = BTRFS_EXTENT_ALLOC_CLUSTERED; - - /* For clustered allocation */ -@@ -4220,6 +4267,8 @@ search: - if (unlikely(block_group->ro)) { - if (for_treelog) - btrfs_clear_treelog_bg(block_group); -+ if (ffe_ctl.for_data_reloc) -+ btrfs_clear_data_reloc_bg(block_group); - continue; - } - -@@ -4408,6 +4457,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, - u64 flags; - int ret; - bool for_treelog = (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); -+ bool for_data_reloc = (btrfs_is_data_reloc_root(root) && is_data); - - flags = get_alloc_profile_by_root(root, is_data); - again: -@@ -4431,8 +4481,8 @@ again: - - sinfo = btrfs_find_space_info(fs_info, flags); - btrfs_err(fs_info, -- "allocation failed flags %llu, wanted %llu tree-log %d", -- flags, num_bytes, for_treelog); -+ "allocation failed flags %llu, wanted %llu tree-log %d, relocation: %d", -+ flags, num_bytes, for_treelog, for_data_reloc); - if (sinfo) - btrfs_dump_space_info(fs_info, sinfo, - num_bytes, 1); -diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c -index aaddd72253481..250fd3c146ac9 100644 ---- a/fs/btrfs/extent_io.c -+++ b/fs/btrfs/extent_io.c -@@ -3327,7 +3327,7 @@ static int alloc_new_bio(struct btrfs_inode *inode, - if (wbc) { - struct block_device *bdev; - -- bdev = fs_info->fs_devices->latest_bdev; -+ bdev = fs_info->fs_devices->latest_dev->bdev; - bio_set_dev(bio, bdev); - wbc_init_bio(wbc, bio); - } -@@ -4284,6 +4284,12 @@ static void set_btree_ioerr(struct page *page, struct extent_buffer *eb) - if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) - return; - -+ /* -+ * A read may stumble upon this buffer later, make sure that it gets an -+ * error and knows there was an error. -+ */ -+ clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); -+ - /* - * If we error out, we should add back the dirty_metadata_bytes - * to make it consistent. -@@ -5120,6 +5126,9 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end, - int extent_writepages(struct address_space *mapping, - struct writeback_control *wbc) - { -+ struct inode *inode = mapping->host; -+ const bool data_reloc = btrfs_is_data_reloc_root(BTRFS_I(inode)->root); -+ const bool zoned = btrfs_is_zoned(BTRFS_I(inode)->root->fs_info); - int ret = 0; - struct extent_page_data epd = { - .bio_ctrl = { 0 }, -@@ -5127,7 +5136,15 @@ int extent_writepages(struct address_space *mapping, - .sync_io = wbc->sync_mode == WB_SYNC_ALL, - }; - -+ /* -+ * Allow only a single thread to do the reloc work in zoned mode to -+ * protect the write pointer updates. -+ */ -+ if (data_reloc && zoned) -+ btrfs_inode_lock(inode, 0); - ret = extent_write_cache_pages(mapping, wbc, &epd); -+ if (data_reloc && zoned) -+ btrfs_inode_unlock(inode, 0); - ASSERT(ret <= 0); - if (ret < 0) { - end_write_bio(&epd, ret); -@@ -6530,6 +6547,14 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num) - if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) - return 0; - -+ /* -+ * We could have had EXTENT_BUFFER_UPTODATE cleared by the write -+ * operation, which could potentially still be in flight. In this case -+ * we simply want to return an error. -+ */ -+ if (unlikely(test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))) -+ return -EIO; -+ - if (eb->fs_info->sectorsize < PAGE_SIZE) - return read_extent_buffer_subpage(eb, wait, mirror_num); - -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 7c096ab9bb5eb..4af74b62e7d97 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -1151,7 +1151,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, - * fails during the stage where it updates the bytenr of file extent - * items. - */ -- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) -+ if (btrfs_is_data_reloc_root(root)) - min_alloc_size = num_bytes; - else - min_alloc_size = fs_info->sectorsize; -@@ -1187,8 +1187,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, - if (ret) - goto out_drop_extent_cache; - -- if (root->root_key.objectid == -- BTRFS_DATA_RELOC_TREE_OBJECTID) { -+ if (btrfs_is_data_reloc_root(root)) { - ret = btrfs_reloc_clone_csums(inode, start, - cur_alloc_size); - /* -@@ -1504,8 +1503,7 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page, - int *page_started, unsigned long *nr_written) - { - const bool is_space_ino = btrfs_is_free_space_inode(inode); -- const bool is_reloc_ino = (inode->root->root_key.objectid == -- BTRFS_DATA_RELOC_TREE_OBJECTID); -+ const bool is_reloc_ino = btrfs_is_data_reloc_root(inode->root); - const u64 range_bytes = end + 1 - start; - struct extent_io_tree *io_tree = &inode->io_tree; - u64 range_start = start; -@@ -1867,8 +1865,7 @@ out_check: - btrfs_dec_nocow_writers(fs_info, disk_bytenr); - nocow = false; - -- if (root->root_key.objectid == -- BTRFS_DATA_RELOC_TREE_OBJECTID) -+ if (btrfs_is_data_reloc_root(root)) - /* - * Error handled later, as we must prevent - * extent_clear_unlock_delalloc() in error handler -@@ -1948,7 +1945,15 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page - const bool zoned = btrfs_is_zoned(inode->root->fs_info); - - if (should_nocow(inode, start, end)) { -- ASSERT(!zoned); -+ /* -+ * Normally on a zoned device we're only doing COW writes, but -+ * in case of relocation on a zoned filesystem we have taken -+ * precaution, that we're only writing sequentially. It's safe -+ * to use run_delalloc_nocow() here, like for regular -+ * preallocated inodes. -+ */ -+ ASSERT(!zoned || -+ (zoned && btrfs_is_data_reloc_root(inode->root))); - ret = run_delalloc_nocow(inode, locked_page, start, end, - page_started, nr_written); - } else if (!inode_can_compress(inode) || -@@ -2207,7 +2212,7 @@ void btrfs_clear_delalloc_extent(struct inode *vfs_inode, - if (btrfs_is_testing(fs_info)) - return; - -- if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID && -+ if (!btrfs_is_data_reloc_root(root) && - do_list && !(state->state & EXTENT_NORESERVE) && - (*bits & EXTENT_CLEAR_DATA_RESV)) - btrfs_free_reserved_data_space_noquota(fs_info, len); -@@ -2532,7 +2537,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio, - goto mapit; - } else if (async && !skip_sum) { - /* csum items have already been cloned */ -- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) -+ if (btrfs_is_data_reloc_root(root)) - goto mapit; - /* we're doing a write, do the async checksumming */ - ret = btrfs_wq_submit_bio(inode, bio, mirror_num, bio_flags, -@@ -3304,7 +3309,7 @@ unsigned int btrfs_verify_data_csum(struct btrfs_io_bio *io_bio, u32 bio_offset, - u64 file_offset = pg_off + page_offset(page); - int ret; - -- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && -+ if (btrfs_is_data_reloc_root(root) && - test_range_bit(io_tree, file_offset, - file_offset + sectorsize - 1, - EXTENT_NODATASUM, 1, NULL)) { -@@ -4005,7 +4010,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, - * without delay - */ - if (!btrfs_is_free_space_inode(inode) -- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID -+ && !btrfs_is_data_reloc_root(root) - && !test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) { - btrfs_update_root_times(trans, root); - -@@ -7962,7 +7967,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start, - iomap->type = IOMAP_MAPPED; - } - iomap->offset = start; -- iomap->bdev = fs_info->fs_devices->latest_bdev; -+ iomap->bdev = fs_info->fs_devices->latest_dev->bdev; - iomap->length = len; - - if (write && btrfs_use_zone_append(BTRFS_I(inode), em->block_start)) -diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c -index 3dbe6eb5fda75..295bbc13ace6a 100644 ---- a/fs/btrfs/lzo.c -+++ b/fs/btrfs/lzo.c -@@ -357,9 +357,10 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) - ASSERT(cur_in / sectorsize == - (cur_in + LZO_LEN - 1) / sectorsize); - cur_page = cb->compressed_pages[cur_in / PAGE_SIZE]; -- kaddr = kmap(cur_page); - ASSERT(cur_page); -+ kaddr = kmap(cur_page); - seg_len = read_compress_length(kaddr + offset_in_page(cur_in)); -+ kunmap(cur_page); - cur_in += LZO_LEN; - - /* Copy the compressed segment payload into workspace */ -diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c -index 9b0814318e726..c71e49782e86d 100644 ---- a/fs/btrfs/reflink.c -+++ b/fs/btrfs/reflink.c -@@ -649,7 +649,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len, - static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, - struct inode *dst, u64 dst_loff) - { -- int ret; -+ int ret = 0; - u64 i, tail_len, chunk_count; - struct btrfs_root *root_dst = BTRFS_I(dst)->root; - -diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c -index 914d403b4415d..d81bee621d373 100644 ---- a/fs/btrfs/relocation.c -+++ b/fs/btrfs/relocation.c -@@ -2852,31 +2852,6 @@ static noinline_for_stack int prealloc_file_extent_cluster( - if (ret) - return ret; - -- /* -- * On a zoned filesystem, we cannot preallocate the file region. -- * Instead, we dirty and fiemap_write the region. -- */ -- if (btrfs_is_zoned(inode->root->fs_info)) { -- struct btrfs_root *root = inode->root; -- struct btrfs_trans_handle *trans; -- -- end = cluster->end - offset + 1; -- trans = btrfs_start_transaction(root, 1); -- if (IS_ERR(trans)) -- return PTR_ERR(trans); -- -- inode->vfs_inode.i_ctime = current_time(&inode->vfs_inode); -- i_size_write(&inode->vfs_inode, end); -- ret = btrfs_update_inode(trans, root, inode); -- if (ret) { -- btrfs_abort_transaction(trans, ret); -- btrfs_end_transaction(trans); -- return ret; -- } -- -- return btrfs_end_transaction(trans); -- } -- - btrfs_inode_lock(&inode->vfs_inode, 0); - for (nr = 0; nr < cluster->nr; nr++) { - start = cluster->boundary[nr] - offset; -@@ -3084,7 +3059,6 @@ release_page: - static int relocate_file_extent_cluster(struct inode *inode, - struct file_extent_cluster *cluster) - { -- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); - u64 offset = BTRFS_I(inode)->index_cnt; - unsigned long index; - unsigned long last_index; -@@ -3114,8 +3088,6 @@ static int relocate_file_extent_cluster(struct inode *inode, - for (index = (cluster->start - offset) >> PAGE_SHIFT; - index <= last_index && !ret; index++) - ret = relocate_one_page(inode, ra, cluster, &cluster_nr, index); -- if (btrfs_is_zoned(fs_info) && !ret) -- ret = btrfs_wait_ordered_range(inode, 0, (u64)-1); - if (ret == 0) - WARN_ON(cluster_nr != cluster->nr); - out: -@@ -3770,12 +3742,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, - struct btrfs_path *path; - struct btrfs_inode_item *item; - struct extent_buffer *leaf; -- u64 flags = BTRFS_INODE_NOCOMPRESS | BTRFS_INODE_PREALLOC; - int ret; - -- if (btrfs_is_zoned(trans->fs_info)) -- flags &= ~BTRFS_INODE_PREALLOC; -- - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; -@@ -3790,7 +3758,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, - btrfs_set_inode_generation(leaf, item, 1); - btrfs_set_inode_size(leaf, item, 0); - btrfs_set_inode_mode(leaf, item, S_IFREG | 0600); -- btrfs_set_inode_flags(leaf, item, flags); -+ btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS | -+ BTRFS_INODE_PREALLOC); - btrfs_mark_buffer_dirty(leaf); - out: - btrfs_free_path(path); -@@ -4386,8 +4355,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, - if (!rc) - return 0; - -- BUG_ON(rc->stage == UPDATE_DATA_PTRS && -- root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); -+ BUG_ON(rc->stage == UPDATE_DATA_PTRS && btrfs_is_data_reloc_root(root)); - - level = btrfs_header_level(buf); - if (btrfs_header_generation(buf) <= -diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c -index 702dc5441f039..db37a37996497 100644 ---- a/fs/btrfs/root-tree.c -+++ b/fs/btrfs/root-tree.c -@@ -336,7 +336,8 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, - key.offset = ref_id; - again: - ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); -- BUG_ON(ret < 0); -+ if (ret < 0) -+ goto out; - if (ret == 0) { - leaf = path->nodes[0]; - ref = btrfs_item_ptr(leaf, path->slots[0], -diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c -index 088641ba7a8e6..62f4bafbe54bb 100644 ---- a/fs/btrfs/scrub.c -+++ b/fs/btrfs/scrub.c -@@ -73,8 +73,8 @@ struct scrub_page { - u64 physical_for_dev_replace; - atomic_t refs; - u8 mirror_num; -- int have_csum:1; -- int io_error:1; -+ unsigned int have_csum:1; -+ unsigned int io_error:1; - u8 csum[BTRFS_CSUM_SIZE]; - - struct scrub_recover *recover; -diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c -index 537d90bf5d844..7f91d62c2225a 100644 ---- a/fs/btrfs/super.c -+++ b/fs/btrfs/super.c -@@ -1705,7 +1705,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, - goto error_close_devices; - } - -- bdev = fs_devices->latest_bdev; -+ bdev = fs_devices->latest_dev->bdev; - s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | SB_NOSEC, - fs_info); - if (IS_ERR(s)) { -@@ -2463,30 +2463,16 @@ static int btrfs_unfreeze(struct super_block *sb) - static int btrfs_show_devname(struct seq_file *m, struct dentry *root) - { - struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb); -- struct btrfs_device *dev, *first_dev = NULL; - - /* -- * Lightweight locking of the devices. We should not need -- * device_list_mutex here as we only read the device data and the list -- * is protected by RCU. Even if a device is deleted during the list -- * traversals, we'll get valid data, the freeing callback will wait at -- * least until the rcu_read_unlock. -+ * There should be always a valid pointer in latest_dev, it may be stale -+ * for a short moment in case it's being deleted but still valid until -+ * the end of RCU grace period. - */ - rcu_read_lock(); -- list_for_each_entry_rcu(dev, &fs_info->fs_devices->devices, dev_list) { -- if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state)) -- continue; -- if (!dev->name) -- continue; -- if (!first_dev || dev->devid < first_dev->devid) -- first_dev = dev; -- } -- -- if (first_dev) -- seq_escape(m, rcu_str_deref(first_dev->name), " \t\n\\"); -- else -- WARN_ON(1); -+ seq_escape(m, rcu_str_deref(fs_info->fs_devices->latest_dev->name), " \t\n\\"); - rcu_read_unlock(); -+ - return 0; - } - -diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c -index b415c5ec03ea0..b79da8917cbfa 100644 ---- a/fs/btrfs/tree-log.c -+++ b/fs/btrfs/tree-log.c -@@ -1153,6 +1153,7 @@ again: - parent_objectid, victim_name, - victim_name_len); - if (ret < 0) { -+ kfree(victim_name); - return ret; - } else if (!ret) { - ret = -ENOENT; -@@ -2500,7 +2501,9 @@ again: - else { - ret = find_dir_range(log, path, dirid, key_type, - &range_start, &range_end); -- if (ret != 0) -+ if (ret < 0) -+ goto out; -+ else if (ret > 0) - break; - } - -@@ -2877,6 +2880,8 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, - path->nodes[*level]->len); - if (ret) - return ret; -+ btrfs_redirty_list_add(trans->transaction, -+ next); - } else { - if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) - clear_extent_buffer_dirty(next); -@@ -2957,6 +2962,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, - next->start, next->len); - if (ret) - goto out; -+ btrfs_redirty_list_add(trans->transaction, next); - } else { - if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) - clear_extent_buffer_dirty(next); -@@ -3410,8 +3416,6 @@ static void free_log_tree(struct btrfs_trans_handle *trans, - EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT); - extent_io_tree_release(&log->log_csum_range); - -- if (trans && log->node) -- btrfs_redirty_list_add(trans->transaction, log->node); - btrfs_put_root(log); - } - -diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c -index 2ec3b8ac8fa35..c34efdc1ecddb 100644 ---- a/fs/btrfs/volumes.c -+++ b/fs/btrfs/volumes.c -@@ -14,6 +14,7 @@ - #include <linux/semaphore.h> - #include <linux/uuid.h> - #include <linux/list_sort.h> -+#include <linux/namei.h> - #include "misc.h" - #include "ctree.h" - #include "extent_map.h" -@@ -1091,7 +1092,7 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices) - list_for_each_entry(seed_dev, &fs_devices->seed_list, seed_list) - __btrfs_free_extra_devids(seed_dev, &latest_dev); - -- fs_devices->latest_bdev = latest_dev->bdev; -+ fs_devices->latest_dev = latest_dev; - - mutex_unlock(&uuid_mutex); - } -@@ -1122,8 +1123,10 @@ static void btrfs_close_one_device(struct btrfs_device *device) - if (device->devid == BTRFS_DEV_REPLACE_DEVID) - clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); - -- if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) -+ if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) { -+ clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); - fs_devices->missing_devices--; -+ } - - btrfs_close_bdev(device); - if (device->bdev) { -@@ -1222,7 +1225,7 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices, - return -EINVAL; - - fs_devices->opened = 1; -- fs_devices->latest_bdev = latest_dev->bdev; -+ fs_devices->latest_dev = latest_dev; - fs_devices->total_rw_bytes = 0; - fs_devices->chunk_alloc_policy = BTRFS_CHUNK_ALLOC_REGULAR; - fs_devices->read_policy = BTRFS_READ_POLICY_PID; -@@ -1363,8 +1366,10 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags, - - bytenr_orig = btrfs_sb_offset(0); - ret = btrfs_sb_log_location_bdev(bdev, 0, READ, &bytenr); -- if (ret) -- return ERR_PTR(ret); -+ if (ret) { -+ device = ERR_PTR(ret); -+ goto error_bdev_put; -+ } - - disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr_orig); - if (IS_ERR(disk_super)) { -@@ -1882,18 +1887,22 @@ out: - /* - * Function to update ctime/mtime for a given device path. - * Mainly used for ctime/mtime based probe like libblkid. -+ * -+ * We don't care about errors here, this is just to be kind to userspace. - */ --static void update_dev_time(struct block_device *bdev) -+static void update_dev_time(const char *device_path) - { -- struct inode *inode = bdev->bd_inode; -+ struct path path; - struct timespec64 now; -+ int ret; - -- /* Shouldn't happen but just in case. */ -- if (!inode) -+ ret = kern_path(device_path, LOOKUP_FOLLOW, &path); -+ if (ret) - return; - -- now = current_time(inode); -- generic_update_time(inode, &now, S_MTIME | S_CTIME); -+ now = current_time(d_inode(path.dentry)); -+ inode_update_time(d_inode(path.dentry), &now, S_MTIME | S_CTIME); -+ path_put(&path); - } - - static int btrfs_rm_dev_item(struct btrfs_device *device) -@@ -1986,7 +1995,7 @@ static struct btrfs_device * btrfs_find_next_active_device( - } - - /* -- * Helper function to check if the given device is part of s_bdev / latest_bdev -+ * Helper function to check if the given device is part of s_bdev / latest_dev - * and replace it with the provided or the next active device, in the context - * where this function called, there should be always be another device (or - * this_dev) which is active. -@@ -2005,8 +2014,8 @@ void __cold btrfs_assign_next_active_device(struct btrfs_device *device, - (fs_info->sb->s_bdev == device->bdev)) - fs_info->sb->s_bdev = next_device->bdev; - -- if (fs_info->fs_devices->latest_bdev == device->bdev) -- fs_info->fs_devices->latest_bdev = next_device->bdev; -+ if (fs_info->fs_devices->latest_dev->bdev == device->bdev) -+ fs_info->fs_devices->latest_dev = next_device; - } - - /* -@@ -2069,7 +2078,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info, - btrfs_kobject_uevent(bdev, KOBJ_CHANGE); - - /* Update ctime/mtime for device path for libblkid */ -- update_dev_time(bdev); -+ update_dev_time(device_path); - } - - int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, -@@ -2081,8 +2090,11 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, - u64 num_devices; - int ret = 0; - -- mutex_lock(&uuid_mutex); -- -+ /* -+ * The device list in fs_devices is accessed without locks (neither -+ * uuid_mutex nor device_list_mutex) as it won't change on a mounted -+ * filesystem and another device rm cannot run. -+ */ - num_devices = btrfs_num_devices(fs_info); - - ret = btrfs_check_raid_min_devices(fs_info, num_devices - 1); -@@ -2126,11 +2138,9 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, - mutex_unlock(&fs_info->chunk_mutex); - } - -- mutex_unlock(&uuid_mutex); - ret = btrfs_shrink_device(device, 0); - if (!ret) - btrfs_reada_remove_dev(device); -- mutex_lock(&uuid_mutex); - if (ret) - goto error_undo; - -@@ -2217,7 +2227,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, - } - - out: -- mutex_unlock(&uuid_mutex); - return ret; - - error_undo: -@@ -2305,13 +2314,6 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev) - - mutex_unlock(&fs_devices->device_list_mutex); - -- /* -- * The update_dev_time() with in btrfs_scratch_superblocks() -- * may lead to a call to btrfs_show_devname() which will try -- * to hold device_list_mutex. And here this device -- * is already out of device list, so we don't have to hold -- * the device_list_mutex lock. -- */ - btrfs_scratch_superblocks(tgtdev->fs_info, tgtdev->bdev, - tgtdev->name->str); - -@@ -2627,6 +2629,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path - btrfs_abort_transaction(trans, ret); - goto error_trans; - } -+ btrfs_assign_next_active_device(fs_info->fs_devices->latest_dev, -+ device); - } - - device->fs_devices = fs_devices; -@@ -2733,7 +2737,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path - btrfs_forget_devices(device_path); - - /* Update ctime/mtime for blkid or udev */ -- update_dev_time(bdev); -+ update_dev_time(device_path); - - return ret; - -@@ -7481,6 +7485,19 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) - */ - fs_info->fs_devices->total_rw_bytes = 0; - -+ /* -+ * Lockdep complains about possible circular locking dependency between -+ * a disk's open_mutex (struct gendisk.open_mutex), the rw semaphores -+ * used for freeze procection of a fs (struct super_block.s_writers), -+ * which we take when starting a transaction, and extent buffers of the -+ * chunk tree if we call read_one_dev() while holding a lock on an -+ * extent buffer of the chunk tree. Since we are mounting the filesystem -+ * and at this point there can't be any concurrent task modifying the -+ * chunk tree, to keep it simple, just skip locking on the chunk tree. -+ */ -+ ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags)); -+ path->skip_locking = 1; -+ - /* - * Read all device items, and then all the chunk items. All - * device items are found before any chunk item (their object id -@@ -7506,10 +7523,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) - goto error; - break; - } -- /* -- * The nodes on level 1 are not locked but we don't need to do -- * that during mount time as nothing else can access the tree -- */ - node = path->nodes[1]; - if (node) { - if (last_ra_node != node->start) { -@@ -7537,7 +7550,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) - * requirement for chunk allocation, see the comment on - * top of btrfs_chunk_alloc() for details. - */ -- ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags)); - chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); - ret = read_one_chunk(&found_key, leaf, chunk); - if (ret) -diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h -index 2183361db614d..4db10d071d67f 100644 ---- a/fs/btrfs/volumes.h -+++ b/fs/btrfs/volumes.h -@@ -246,7 +246,11 @@ struct btrfs_fs_devices { - /* Highest generation number of seen devices */ - u64 latest_generation; - -- struct block_device *latest_bdev; -+ /* -+ * The mount device or a device with highest generation after removal -+ * or replace. -+ */ -+ struct btrfs_device *latest_dev; - - /* all of the devices in the FS, protected by a mutex - * so we can safely walk it to write out the supers without -diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c -index 47af1ab3bf120..5672c24a2d582 100644 ---- a/fs/btrfs/zoned.c -+++ b/fs/btrfs/zoned.c -@@ -1304,6 +1304,17 @@ bool btrfs_use_zone_append(struct btrfs_inode *inode, u64 start) - if (!is_data_inode(&inode->vfs_inode)) - return false; - -+ /* -+ * Using REQ_OP_ZONE_APPNED for relocation can break assumptions on the -+ * extent layout the relocation code has. -+ * Furthermore we have set aside own block-group from which only the -+ * relocation "process" can allocate and make sure only one process at a -+ * time can add pages to an extent that gets relocated, so it's safe to -+ * use regular REQ_OP_WRITE for this special case. -+ */ -+ if (btrfs_is_data_reloc_root(inode->root)) -+ return false; -+ - cache = btrfs_lookup_block_group(fs_info, start); - ASSERT(cache); - if (!cache) -@@ -1530,3 +1541,13 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info, - - return device; - } -+ -+void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) -+{ -+ struct btrfs_fs_info *fs_info = bg->fs_info; -+ -+ spin_lock(&fs_info->relocation_bg_lock); -+ if (fs_info->data_reloc_bg == bg->start) -+ fs_info->data_reloc_bg = 0; -+ spin_unlock(&fs_info->relocation_bg_lock); -+} -diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h -index 4b299705bb12b..70b3be517599f 100644 ---- a/fs/btrfs/zoned.h -+++ b/fs/btrfs/zoned.h -@@ -66,6 +66,7 @@ int btrfs_sync_zone_write_pointer(struct btrfs_device *tgt_dev, u64 logical, - u64 physical_start, u64 physical_pos); - struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info, - u64 logical, u64 length); -+void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg); - #else /* CONFIG_BLK_DEV_ZONED */ - static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, - struct blk_zone *zone) -@@ -199,6 +200,8 @@ static inline struct btrfs_device *btrfs_zoned_get_device( - return ERR_PTR(-EOPNOTSUPP); - } - -+static inline void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) { } -+ - #endif - - static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos) -diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c -index 8f537f1d9d1d3..8be4da2e2b826 100644 ---- a/fs/ceph/caps.c -+++ b/fs/ceph/caps.c -@@ -4349,7 +4349,7 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count) - { - struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(ci->vfs_inode.i_sb); - int bits = (fmode << 1) | 1; -- bool is_opened = false; -+ bool already_opened = false; - int i; - - if (count == 1) -@@ -4357,19 +4357,19 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count) - - spin_lock(&ci->i_ceph_lock); - for (i = 0; i < CEPH_FILE_MODE_BITS; i++) { -- if (bits & (1 << i)) -- ci->i_nr_by_mode[i] += count; -- - /* -- * If any of the mode ref is larger than 1, -+ * If any of the mode ref is larger than 0, - * that means it has been already opened by - * others. Just skip checking the PIN ref. - */ -- if (i && ci->i_nr_by_mode[i] > 1) -- is_opened = true; -+ if (i && ci->i_nr_by_mode[i]) -+ already_opened = true; -+ -+ if (bits & (1 << i)) -+ ci->i_nr_by_mode[i] += count; - } - -- if (!is_opened) -+ if (!already_opened) - percpu_counter_inc(&mdsc->metric.opened_inodes); - spin_unlock(&ci->i_ceph_lock); - } -diff --git a/fs/ceph/file.c b/fs/ceph/file.c -index e61018d9764ee..e873c2ba7a7ff 100644 ---- a/fs/ceph/file.c -+++ b/fs/ceph/file.c -@@ -603,13 +603,25 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, - in.cap.realm = cpu_to_le64(ci->i_snap_realm->ino); - in.cap.flags = CEPH_CAP_FLAG_AUTH; - in.ctime = in.mtime = in.atime = iinfo.btime; -- in.mode = cpu_to_le32((u32)mode); - in.truncate_seq = cpu_to_le32(1); - in.truncate_size = cpu_to_le64(-1ULL); - in.xattr_version = cpu_to_le64(1); - in.uid = cpu_to_le32(from_kuid(&init_user_ns, current_fsuid())); -- in.gid = cpu_to_le32(from_kgid(&init_user_ns, dir->i_mode & S_ISGID ? -- dir->i_gid : current_fsgid())); -+ if (dir->i_mode & S_ISGID) { -+ in.gid = cpu_to_le32(from_kgid(&init_user_ns, dir->i_gid)); -+ -+ /* Directories always inherit the setgid bit. */ -+ if (S_ISDIR(mode)) -+ mode |= S_ISGID; -+ else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && -+ !in_group_p(dir->i_gid) && -+ !capable_wrt_inode_uidgid(&init_user_ns, dir, CAP_FSETID)) -+ mode &= ~S_ISGID; -+ } else { -+ in.gid = cpu_to_le32(from_kgid(&init_user_ns, current_fsgid())); -+ } -+ in.mode = cpu_to_le32((u32)mode); -+ - in.nlink = cpu_to_le32(1); - in.max_size = cpu_to_le64(lo->stripe_unit); - -diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c -index d64413adc0fd2..e9409c460acd0 100644 ---- a/fs/ceph/mds_client.c -+++ b/fs/ceph/mds_client.c -@@ -3772,7 +3772,7 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap, - struct ceph_pagelist *pagelist = recon_state->pagelist; - struct dentry *dentry; - char *path; -- int pathlen, err; -+ int pathlen = 0, err; - u64 pathbase; - u64 snap_follows; - -@@ -3792,7 +3792,6 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap, - } - } else { - path = NULL; -- pathlen = 0; - pathbase = 0; - } - -diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c -index 61d67cbcb3671..30387733765d5 100644 ---- a/fs/ceph/mdsmap.c -+++ b/fs/ceph/mdsmap.c -@@ -263,10 +263,6 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end, bool msgr2) - goto nomem; - for (j = 0; j < num_export_targets; j++) { - target = ceph_decode_32(&pexport_targets); -- if (target >= m->possible_max_rank) { -- err = -EIO; -- goto corrupt; -- } - info->export_targets[j] = target; - } - } else { -diff --git a/fs/ceph/super.c b/fs/ceph/super.c -index fd8742bae8471..202ddde3d62ad 100644 ---- a/fs/ceph/super.c -+++ b/fs/ceph/super.c -@@ -52,8 +52,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) - struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry)); - struct ceph_mon_client *monc = &fsc->client->monc; - struct ceph_statfs st; -- u64 fsid; -- int err; -+ int i, err; - u64 data_pool; - - if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) { -@@ -99,12 +98,14 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) - buf->f_namelen = NAME_MAX; - - /* Must convert the fsid, for consistent values across arches */ -+ buf->f_fsid.val[0] = 0; - mutex_lock(&monc->mutex); -- fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^ -- le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1)); -+ for (i = 0 ; i < sizeof(monc->monmap->fsid) / sizeof(__le32) ; ++i) -+ buf->f_fsid.val[0] ^= le32_to_cpu(((__le32 *)&monc->monmap->fsid)[i]); - mutex_unlock(&monc->mutex); - -- buf->f_fsid = u64_to_fsid(fsid); -+ /* fold the fs_cluster_id into the upper bits */ -+ buf->f_fsid.val[1] = monc->fs_cluster_id; - - return 0; - } -diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c -index de2c12bcfa4bc..905a901f7f80b 100644 ---- a/fs/cifs/cifs_debug.c -+++ b/fs/cifs/cifs_debug.c -@@ -358,6 +358,8 @@ skip_rdma: - seq_printf(m, " signed"); - if (server->posix_ext_supported) - seq_printf(m, " posix"); -+ if (server->nosharesock) -+ seq_printf(m, " nosharesock"); - - if (server->rdma) - seq_printf(m, "\nRDMA "); -diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h -index e916470468ea9..3e5b8e177cfa7 100644 ---- a/fs/cifs/cifsglob.h -+++ b/fs/cifs/cifsglob.h -@@ -74,7 +74,8 @@ - #define SMB_ECHO_INTERVAL_MAX 600 - #define SMB_ECHO_INTERVAL_DEFAULT 60 - --/* dns resolution interval in seconds */ -+/* dns resolution intervals in seconds */ -+#define SMB_DNS_RESOLVE_INTERVAL_MIN 120 - #define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600 - - /* maximum number of PDUs in one compound */ -@@ -591,6 +592,7 @@ struct TCP_Server_Info { - struct list_head pending_mid_q; - bool noblocksnd; /* use blocking sendmsg */ - bool noautotune; /* do not autotune send buf sizes */ -+ bool nosharesock; - bool tcp_nodelay; - unsigned int credits; /* send no more requests at once */ - unsigned int max_credits; /* can override large 32000 default at mnt */ -diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c -index c3b94c1e45913..439f02f1886c1 100644 ---- a/fs/cifs/connect.c -+++ b/fs/cifs/connect.c -@@ -115,7 +115,7 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) - * To make sure we don't use the cached entry, retry 1s - * after expiry. - */ -- ttl = (expiry - now + 1); -+ ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1; - } - rc = !rc ? -1 : 0; - -@@ -794,7 +794,6 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) - */ - } - -- kfree(server->hostname); - kfree(server); - - length = atomic_dec_return(&tcpSesAllocCount); -@@ -1221,6 +1220,10 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context * - if (ctx->nosharesock) - return 0; - -+ /* this server does not share socket */ -+ if (server->nosharesock) -+ return 0; -+ - /* If multidialect negotiation see if existing sessions match one */ - if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { - if (server->vals->protocol_id < SMB30_PROT_ID) -@@ -1235,6 +1238,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context * - if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) - return 0; - -+ if (strcasecmp(server->hostname, ctx->server_hostname)) -+ return 0; -+ - if (!match_address(server, addr, - (struct sockaddr *)&ctx->srcaddr)) - return 0; -@@ -1336,6 +1342,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) - kfree(server->session_key.response); - server->session_key.response = NULL; - server->session_key.len = 0; -+ kfree(server->hostname); - - task = xchg(&server->tsk, NULL); - if (task) -@@ -1361,14 +1368,18 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx) - goto out_err; - } - -+ tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL); -+ if (!tcp_ses->hostname) { -+ rc = -ENOMEM; -+ goto out_err; -+ } -+ -+ if (ctx->nosharesock) -+ tcp_ses->nosharesock = true; -+ - tcp_ses->ops = ctx->ops; - tcp_ses->vals = ctx->vals; - cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); -- tcp_ses->hostname = extract_hostname(ctx->UNC); -- if (IS_ERR(tcp_ses->hostname)) { -- rc = PTR_ERR(tcp_ses->hostname); -- goto out_err_crypto_release; -- } - - tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId); - tcp_ses->noblockcnt = ctx->rootfs; -@@ -1497,8 +1508,7 @@ out_err_crypto_release: - - out_err: - if (tcp_ses) { -- if (!IS_ERR(tcp_ses->hostname)) -- kfree(tcp_ses->hostname); -+ kfree(tcp_ses->hostname); - if (tcp_ses->ssocket) - sock_release(tcp_ses->ssocket); - kfree(tcp_ses); -diff --git a/fs/cifs/file.c b/fs/cifs/file.c -index 13f3182cf7969..82bbaf8e92b79 100644 ---- a/fs/cifs/file.c -+++ b/fs/cifs/file.c -@@ -2692,12 +2692,23 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, - tcon = tlink_tcon(smbfile->tlink); - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { - server = tcon->ses->server; -- if (server->ops->flush) -- rc = server->ops->flush(xid, tcon, &smbfile->fid); -- else -+ if (server->ops->flush == NULL) { - rc = -ENOSYS; -+ goto strict_fsync_exit; -+ } -+ -+ if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { -+ smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); -+ if (smbfile) { -+ rc = server->ops->flush(xid, tcon, &smbfile->fid); -+ cifsFileInfo_put(smbfile); -+ } else -+ cifs_dbg(FYI, "ignore fsync for file not open for write\n"); -+ } else -+ rc = server->ops->flush(xid, tcon, &smbfile->fid); - } - -+strict_fsync_exit: - free_xid(xid); - return rc; - } -@@ -2709,6 +2720,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) - struct cifs_tcon *tcon; - struct TCP_Server_Info *server; - struct cifsFileInfo *smbfile = file->private_data; -+ struct inode *inode = file_inode(file); - struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); - - rc = file_write_and_wait_range(file, start, end); -@@ -2725,12 +2737,23 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) - tcon = tlink_tcon(smbfile->tlink); - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { - server = tcon->ses->server; -- if (server->ops->flush) -- rc = server->ops->flush(xid, tcon, &smbfile->fid); -- else -+ if (server->ops->flush == NULL) { - rc = -ENOSYS; -+ goto fsync_exit; -+ } -+ -+ if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { -+ smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); -+ if (smbfile) { -+ rc = server->ops->flush(xid, tcon, &smbfile->fid); -+ cifsFileInfo_put(smbfile); -+ } else -+ cifs_dbg(FYI, "ignore fsync for file not open for write\n"); -+ } else -+ rc = server->ops->flush(xid, tcon, &smbfile->fid); - } - -+fsync_exit: - free_xid(xid); - return rc; - } -diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c -index 3109def8e1998..0a2542286552f 100644 ---- a/fs/cifs/fs_context.c -+++ b/fs/cifs/fs_context.c -@@ -307,6 +307,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx - new_ctx->nodename = NULL; - new_ctx->username = NULL; - new_ctx->password = NULL; -+ new_ctx->server_hostname = NULL; - new_ctx->domainname = NULL; - new_ctx->UNC = NULL; - new_ctx->source = NULL; -@@ -318,6 +319,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx - DUP_CTX_STR(mount_options); - DUP_CTX_STR(username); - DUP_CTX_STR(password); -+ DUP_CTX_STR(server_hostname); - DUP_CTX_STR(UNC); - DUP_CTX_STR(source); - DUP_CTX_STR(domainname); -@@ -429,6 +431,42 @@ out: - return rc; - } - -+/* -+ * Remove duplicate path delimiters. Windows is supposed to do that -+ * but there are some bugs that prevent rename from working if there are -+ * multiple delimiters. -+ * -+ * Returns a sanitized duplicate of @path. The caller is responsible for -+ * cleaning up the original. -+ */ -+#define IS_DELIM(c) ((c) == '/' || (c) == '\\') -+static char *sanitize_path(char *path) -+{ -+ char *cursor1 = path, *cursor2 = path; -+ -+ /* skip all prepended delimiters */ -+ while (IS_DELIM(*cursor1)) -+ cursor1++; -+ -+ /* copy the first letter */ -+ *cursor2 = *cursor1; -+ -+ /* copy the remainder... */ -+ while (*(cursor1++)) { -+ /* ... skipping all duplicated delimiters */ -+ if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2)) -+ continue; -+ *(++cursor2) = *cursor1; -+ } -+ -+ /* if the last character is a delimiter, skip it */ -+ if (IS_DELIM(*(cursor2 - 1))) -+ cursor2--; -+ -+ *(cursor2) = '\0'; -+ return kstrdup(path, GFP_KERNEL); -+} -+ - /* - * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath - * fields with the result. Returns 0 on success and an error otherwise -@@ -456,6 +494,12 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) - if (!pos) - return -EINVAL; - -+ /* record the server hostname */ -+ kfree(ctx->server_hostname); -+ ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL); -+ if (!ctx->server_hostname) -+ return -ENOMEM; -+ - /* skip past delimiter */ - ++pos; - -@@ -482,7 +526,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) - if (!*pos) - return 0; - -- ctx->prepath = kstrdup(pos, GFP_KERNEL); -+ ctx->prepath = sanitize_path(pos); - if (!ctx->prepath) - return -ENOMEM; - -@@ -1496,6 +1540,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) - ctx->username = NULL; - kfree_sensitive(ctx->password); - ctx->password = NULL; -+ kfree(ctx->server_hostname); -+ ctx->server_hostname = NULL; - kfree(ctx->UNC); - ctx->UNC = NULL; - kfree(ctx->source); -diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h -index a42ba71d7a81f..29601a4eb4116 100644 ---- a/fs/cifs/fs_context.h -+++ b/fs/cifs/fs_context.h -@@ -166,6 +166,7 @@ struct smb3_fs_context { - char *password; - char *domainname; - char *source; -+ char *server_hostname; - char *UNC; - char *nodename; - char *iocharset; /* local code page for mapping to and from Unicode */ -diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h -index 3fa965eb3336d..cb25ef0cdf1f3 100644 ---- a/fs/crypto/fscrypt_private.h -+++ b/fs/crypto/fscrypt_private.h -@@ -549,8 +549,9 @@ int __init fscrypt_init_keyring(void); - struct fscrypt_mode { - const char *friendly_name; - const char *cipher_str; -- int keysize; -- int ivsize; -+ int keysize; /* key size in bytes */ -+ int security_strength; /* security strength in bytes */ -+ int ivsize; /* IV size in bytes */ - int logged_impl_name; - enum blk_crypto_mode_num blk_crypto_mode; - }; -diff --git a/fs/crypto/hkdf.c b/fs/crypto/hkdf.c -index e0ec210555053..7607d18b35fc0 100644 ---- a/fs/crypto/hkdf.c -+++ b/fs/crypto/hkdf.c -@@ -16,9 +16,14 @@ - - /* - * HKDF supports any unkeyed cryptographic hash algorithm, but fscrypt uses -- * SHA-512 because it is reasonably secure and efficient; and since it produces -- * a 64-byte digest, deriving an AES-256-XTS key preserves all 64 bytes of -- * entropy from the master key and requires only one iteration of HKDF-Expand. -+ * SHA-512 because it is well-established, secure, and reasonably efficient. -+ * -+ * HKDF-SHA256 was also considered, as its 256-bit security strength would be -+ * sufficient here. A 512-bit security strength is "nice to have", though. -+ * Also, on 64-bit CPUs, SHA-512 is usually just as fast as SHA-256. In the -+ * common case of deriving an AES-256-XTS key (512 bits), that can result in -+ * HKDF-SHA512 being much faster than HKDF-SHA256, as the longer digest size of -+ * SHA-512 causes HKDF-Expand to only need to do one iteration rather than two. - */ - #define HKDF_HMAC_ALG "hmac(sha512)" - #define HKDF_HASHLEN SHA512_DIGEST_SIZE -diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c -index bca9c6658a7c5..89cd533a88bff 100644 ---- a/fs/crypto/keysetup.c -+++ b/fs/crypto/keysetup.c -@@ -19,6 +19,7 @@ struct fscrypt_mode fscrypt_modes[] = { - .friendly_name = "AES-256-XTS", - .cipher_str = "xts(aes)", - .keysize = 64, -+ .security_strength = 32, - .ivsize = 16, - .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS, - }, -@@ -26,12 +27,14 @@ struct fscrypt_mode fscrypt_modes[] = { - .friendly_name = "AES-256-CTS-CBC", - .cipher_str = "cts(cbc(aes))", - .keysize = 32, -+ .security_strength = 32, - .ivsize = 16, - }, - [FSCRYPT_MODE_AES_128_CBC] = { - .friendly_name = "AES-128-CBC-ESSIV", - .cipher_str = "essiv(cbc(aes),sha256)", - .keysize = 16, -+ .security_strength = 16, - .ivsize = 16, - .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV, - }, -@@ -39,12 +42,14 @@ struct fscrypt_mode fscrypt_modes[] = { - .friendly_name = "AES-128-CTS-CBC", - .cipher_str = "cts(cbc(aes))", - .keysize = 16, -+ .security_strength = 16, - .ivsize = 16, - }, - [FSCRYPT_MODE_ADIANTUM] = { - .friendly_name = "Adiantum", - .cipher_str = "adiantum(xchacha12,aes)", - .keysize = 32, -+ .security_strength = 32, - .ivsize = 32, - .blk_crypto_mode = BLK_ENCRYPTION_MODE_ADIANTUM, - }, -@@ -357,6 +362,45 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, - return 0; - } - -+/* -+ * Check whether the size of the given master key (@mk) is appropriate for the -+ * encryption settings which a particular file will use (@ci). -+ * -+ * If the file uses a v1 encryption policy, then the master key must be at least -+ * as long as the derived key, as this is a requirement of the v1 KDF. -+ * -+ * Otherwise, the KDF can accept any size key, so we enforce a slightly looser -+ * requirement: we require that the size of the master key be at least the -+ * maximum security strength of any algorithm whose key will be derived from it -+ * (but in practice we only need to consider @ci->ci_mode, since any other -+ * possible subkeys such as DIRHASH and INODE_HASH will never increase the -+ * required key size over @ci->ci_mode). This allows AES-256-XTS keys to be -+ * derived from a 256-bit master key, which is cryptographically sufficient, -+ * rather than requiring a 512-bit master key which is unnecessarily long. (We -+ * still allow 512-bit master keys if the user chooses to use them, though.) -+ */ -+static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk, -+ const struct fscrypt_info *ci) -+{ -+ unsigned int min_keysize; -+ -+ if (ci->ci_policy.version == FSCRYPT_POLICY_V1) -+ min_keysize = ci->ci_mode->keysize; -+ else -+ min_keysize = ci->ci_mode->security_strength; -+ -+ if (mk->mk_secret.size < min_keysize) { -+ fscrypt_warn(NULL, -+ "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", -+ master_key_spec_type(&mk->mk_spec), -+ master_key_spec_len(&mk->mk_spec), -+ (u8 *)&mk->mk_spec.u, -+ mk->mk_secret.size, min_keysize); -+ return false; -+ } -+ return true; -+} -+ - /* - * Find the master key, then set up the inode's actual encryption key. - * -@@ -422,18 +466,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, - goto out_release_key; - } - -- /* -- * Require that the master key be at least as long as the derived key. -- * Otherwise, the derived key cannot possibly contain as much entropy as -- * that required by the encryption mode it will be used for. For v1 -- * policies it's also required for the KDF to work at all. -- */ -- if (mk->mk_secret.size < ci->ci_mode->keysize) { -- fscrypt_warn(NULL, -- "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", -- master_key_spec_type(&mk_spec), -- master_key_spec_len(&mk_spec), (u8 *)&mk_spec.u, -- mk->mk_secret.size, ci->ci_mode->keysize); -+ if (!fscrypt_valid_master_key_size(mk, ci)) { - err = -ENOKEY; - goto out_release_key; - } -diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c -index a5bc4b1b7813e..ad3f31380e6b2 100644 ---- a/fs/erofs/decompressor.c -+++ b/fs/erofs/decompressor.c -@@ -233,7 +233,6 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) - erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", - ret, rq->inputsize, inputmargin, rq->outputsize); - -- WARN_ON(1); - print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, - 16, 1, src + inputmargin, rq->inputsize, true); - print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, -diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c -index bd86067a63f7f..3ca703cd5b24a 100644 ---- a/fs/erofs/utils.c -+++ b/fs/erofs/utils.c -@@ -141,7 +141,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - * however in order to avoid some race conditions, add a - * DBG_BUGON to observe this in advance. - */ -- DBG_BUGON(xa_erase(&sbi->managed_pslots, grp->index) != grp); -+ DBG_BUGON(__xa_erase(&sbi->managed_pslots, grp->index) != grp); - - /* last refcount should be connected with its managed pslot. */ - erofs_workgroup_unfreeze(grp, 0); -@@ -156,15 +156,19 @@ static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned int freed = 0; - unsigned long index; - -+ xa_lock(&sbi->managed_pslots); - xa_for_each(&sbi->managed_pslots, index, grp) { - /* try to shrink each valid workgroup */ - if (!erofs_try_to_release_workgroup(sbi, grp)) - continue; -+ xa_unlock(&sbi->managed_pslots); - - ++freed; - if (!--nr_shrink) -- break; -+ return freed; -+ xa_lock(&sbi->managed_pslots); - } -+ xa_unlock(&sbi->managed_pslots); - return freed; - } - -diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c -index 11c7a1aaebade..eb51df4a9f770 100644 ---- a/fs/erofs/zdata.c -+++ b/fs/erofs/zdata.c -@@ -373,8 +373,8 @@ static bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, - - /* callers must be with collection lock held */ - static int z_erofs_attach_page(struct z_erofs_collector *clt, -- struct page *page, -- enum z_erofs_page_type type) -+ struct page *page, enum z_erofs_page_type type, -+ bool pvec_safereuse) - { - int ret; - -@@ -384,9 +384,9 @@ static int z_erofs_attach_page(struct z_erofs_collector *clt, - z_erofs_try_inplace_io(clt, page)) - return 0; - -- ret = z_erofs_pagevec_enqueue(&clt->vector, page, type); -+ ret = z_erofs_pagevec_enqueue(&clt->vector, page, type, -+ pvec_safereuse); - clt->cl->vcnt += (unsigned int)ret; -- - return ret ? 0 : -EAGAIN; - } - -@@ -729,7 +729,8 @@ hitted: - tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); - - retry: -- err = z_erofs_attach_page(clt, page, page_type); -+ err = z_erofs_attach_page(clt, page, page_type, -+ clt->mode >= COLLECT_PRIMARY_FOLLOWED); - /* should allocate an additional short-lived page for pagevec */ - if (err == -EAGAIN) { - struct page *const newpage = -@@ -737,7 +738,7 @@ retry: - - set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE); - err = z_erofs_attach_page(clt, newpage, -- Z_EROFS_PAGE_TYPE_EXCLUSIVE); -+ Z_EROFS_PAGE_TYPE_EXCLUSIVE, true); - if (!err) - goto retry; - } -diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h -index dfd7fe0503bb1..b05464f4a8083 100644 ---- a/fs/erofs/zpvec.h -+++ b/fs/erofs/zpvec.h -@@ -106,11 +106,18 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, - - static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, - struct page *page, -- enum z_erofs_page_type type) -+ enum z_erofs_page_type type, -+ bool pvec_safereuse) - { -- if (!ctor->next && type) -- if (ctor->index + 1 == ctor->nr) -+ if (!ctor->next) { -+ /* some pages cannot be reused as pvec safely without I/O */ -+ if (type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && !pvec_safereuse) -+ type = Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED; -+ -+ if (type != Z_EROFS_PAGE_TYPE_EXCLUSIVE && -+ ctor->index + 1 == ctor->nr) - return false; -+ } - - if (ctor->index >= ctor->nr) - z_erofs_pagevec_ctor_pagedown(ctor, false); -diff --git a/fs/exec.c b/fs/exec.c -index a098c133d8d74..ac7b51b51f38a 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -1852,7 +1852,7 @@ out: - * SIGSEGV. - */ - if (bprm->point_of_no_return && !fatal_signal_pending(current)) -- force_sigsegv(SIGSEGV); -+ force_fatal_sig(SIGSEGV); - - out_unmark: - current->fs->in_exec = 0; -diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c -index ca37d43443612..1c7aa1ea4724c 100644 ---- a/fs/exfat/inode.c -+++ b/fs/exfat/inode.c -@@ -604,7 +604,7 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) - exfat_save_attr(inode, info->attr); - - inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & -- ~(sbi->cluster_size - 1)) >> inode->i_blkbits; -+ ~((loff_t)sbi->cluster_size - 1)) >> inode->i_blkbits; - inode->i_mtime = info->mtime; - inode->i_ctime = info->mtime; - ei->i_crtime = info->crtime; -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 0e02571f2f828..01c00ae8e06d6 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4977,36 +4977,6 @@ int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo, - return ext4_fill_es_cache_info(inode, start_blk, len_blks, fieinfo); - } - --/* -- * ext4_access_path: -- * Function to access the path buffer for marking it dirty. -- * It also checks if there are sufficient credits left in the journal handle -- * to update path. -- */ --static int --ext4_access_path(handle_t *handle, struct inode *inode, -- struct ext4_ext_path *path) --{ -- int credits, err; -- -- if (!ext4_handle_valid(handle)) -- return 0; -- -- /* -- * Check if need to extend journal credits -- * 3 for leaf, sb, and inode plus 2 (bmap and group -- * descriptor) for each block group; assume two block -- * groups -- */ -- credits = ext4_writepage_trans_blocks(inode); -- err = ext4_datasem_ensure_credits(handle, inode, 7, credits, 0); -- if (err < 0) -- return err; -- -- err = ext4_ext_get_access(handle, inode, path); -- return err; --} -- - /* - * ext4_ext_shift_path_extents: - * Shift the extents of a path structure lying between path[depth].p_ext -@@ -5021,6 +4991,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, - int depth, err = 0; - struct ext4_extent *ex_start, *ex_last; - bool update = false; -+ int credits, restart_credits; - depth = path->p_depth; - - while (depth >= 0) { -@@ -5030,13 +5001,26 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, - return -EFSCORRUPTED; - - ex_last = EXT_LAST_EXTENT(path[depth].p_hdr); -+ /* leaf + sb + inode */ -+ credits = 3; -+ if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr)) { -+ update = true; -+ /* extent tree + sb + inode */ -+ credits = depth + 2; -+ } - -- err = ext4_access_path(handle, inode, path + depth); -- if (err) -+ restart_credits = ext4_writepage_trans_blocks(inode); -+ err = ext4_datasem_ensure_credits(handle, inode, credits, -+ restart_credits, 0); -+ if (err) { -+ if (err > 0) -+ err = -EAGAIN; - goto out; -+ } - -- if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr)) -- update = true; -+ err = ext4_ext_get_access(handle, inode, path + depth); -+ if (err) -+ goto out; - - while (ex_start <= ex_last) { - if (SHIFT == SHIFT_LEFT) { -@@ -5067,7 +5051,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, - } - - /* Update index too */ -- err = ext4_access_path(handle, inode, path + depth); -+ err = ext4_ext_get_access(handle, inode, path + depth); - if (err) - goto out; - -@@ -5106,6 +5090,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, - int ret = 0, depth; - struct ext4_extent *extent; - ext4_lblk_t stop, *iterator, ex_start, ex_end; -+ ext4_lblk_t tmp = EXT_MAX_BLOCKS; - - /* Let path point to the last extent */ - path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, -@@ -5159,11 +5144,15 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, - * till we reach stop. In case of right shift, iterator points to stop - * and it is decreased till we reach start. - */ -+again: - if (SHIFT == SHIFT_LEFT) - iterator = &start; - else - iterator = &stop; - -+ if (tmp != EXT_MAX_BLOCKS) -+ *iterator = tmp; -+ - /* - * Its safe to start updating extents. Start and stop are unsigned, so - * in case of right shift if extent with 0 block is reached, iterator -@@ -5192,6 +5181,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, - } - } - -+ tmp = *iterator; - if (SHIFT == SHIFT_LEFT) { - extent = EXT_LAST_EXTENT(path[depth].p_hdr); - *iterator = le32_to_cpu(extent->ee_block) + -@@ -5210,6 +5200,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, - } - ret = ext4_ext_shift_path_extents(path, shift, inode, - handle, SHIFT); -+ /* iterator can be NULL which means we should break */ -+ if (ret == -EAGAIN) -+ goto again; - if (ret) - break; - } -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 0f06305167d5a..9097fccdc6889 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -1711,16 +1711,13 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, - } - - /* -- * the buffer head associated with a delayed and not unwritten -- * block found in the extent status cache must contain an -- * invalid block number and have its BH_New and BH_Delay bits -- * set, reflecting the state assigned when the block was -- * initially delayed allocated -+ * Delayed extent could be allocated by fallocate. -+ * So we need to check it. - */ -- if (ext4_es_is_delonly(&es)) { -- BUG_ON(bh->b_blocknr != invalid_block); -- BUG_ON(!buffer_new(bh)); -- BUG_ON(!buffer_delay(bh)); -+ if (ext4_es_is_delayed(&es) && !ext4_es_is_unwritten(&es)) { -+ map_bh(bh, inode->i_sb, invalid_block); -+ set_buffer_new(bh); -+ set_buffer_delay(bh); - return 0; - } - -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 88d5d274a8684..8a67e5f3f5763 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -3263,9 +3263,9 @@ static int ext4_run_li_request(struct ext4_li_request *elr) - struct super_block *sb = elr->lr_super; - ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; - ext4_group_t group = elr->lr_next_group; -- unsigned long timeout = 0; - unsigned int prefetch_ios = 0; - int ret = 0; -+ u64 start_time; - - if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) { - elr->lr_next_group = ext4_mb_prefetch(sb, group, -@@ -3302,14 +3302,13 @@ static int ext4_run_li_request(struct ext4_li_request *elr) - ret = 1; - - if (!ret) { -- timeout = jiffies; -+ start_time = ktime_get_real_ns(); - ret = ext4_init_inode_table(sb, group, - elr->lr_timeout ? 0 : 1); - trace_ext4_lazy_itable_init(sb, group); - if (elr->lr_timeout == 0) { -- timeout = (jiffies - timeout) * -- EXT4_SB(elr->lr_super)->s_li_wait_mult; -- elr->lr_timeout = timeout; -+ elr->lr_timeout = nsecs_to_jiffies((ktime_get_real_ns() - start_time) * -+ EXT4_SB(elr->lr_super)->s_li_wait_mult); - } - elr->lr_next_sched = jiffies + elr->lr_timeout; - elr->lr_next_group = group + 1; -diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c -index 83e9bc0f91ffd..7b02827242312 100644 ---- a/fs/f2fs/checkpoint.c -+++ b/fs/f2fs/checkpoint.c -@@ -1162,7 +1162,8 @@ static bool __need_flush_quota(struct f2fs_sb_info *sbi) - if (!is_journalled_quota(sbi)) - return false; - -- down_write(&sbi->quota_sem); -+ if (!down_write_trylock(&sbi->quota_sem)) -+ return true; - if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) { - ret = false; - } else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) { -diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c -index c1bf9ad4c2207..9b663eaf48057 100644 ---- a/fs/f2fs/compress.c -+++ b/fs/f2fs/compress.c -@@ -1530,6 +1530,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc, - if (cluster_may_compress(cc)) { - err = f2fs_compress_pages(cc); - if (err == -EAGAIN) { -+ add_compr_block_stat(cc->inode, cc->cluster_size); - goto write; - } else if (err) { - f2fs_put_rpages_wbc(cc, wbc, true, 1); -diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h -index b339ae89c1ad1..c242274e3479b 100644 ---- a/fs/f2fs/f2fs.h -+++ b/fs/f2fs/f2fs.h -@@ -4152,8 +4152,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode) - - if (!f2fs_compressed_file(inode)) - return true; -- if (S_ISREG(inode->i_mode) && -- (get_dirty_pages(inode) || atomic_read(&fi->i_compr_blocks))) -+ if (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode)) - return false; - - fi->i_flags &= ~F2FS_COMPR_FL; -diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c -index 9141147b5bb00..1213f15ffd68c 100644 ---- a/fs/f2fs/inode.c -+++ b/fs/f2fs/inode.c -@@ -527,7 +527,7 @@ make_now: - inode->i_op = &f2fs_dir_inode_operations; - inode->i_fop = &f2fs_dir_operations; - inode->i_mapping->a_ops = &f2fs_dblock_aops; -- inode_nohighmem(inode); -+ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); - } else if (S_ISLNK(inode->i_mode)) { - if (file_is_encrypt(inode)) - inode->i_op = &f2fs_encrypted_symlink_inode_operations; -diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c -index 9c528e583c9d5..ae0838001480a 100644 ---- a/fs/f2fs/namei.c -+++ b/fs/f2fs/namei.c -@@ -757,7 +757,7 @@ static int f2fs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, - inode->i_op = &f2fs_dir_inode_operations; - inode->i_fop = &f2fs_dir_operations; - inode->i_mapping->a_ops = &f2fs_dblock_aops; -- inode_nohighmem(inode); -+ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); - - set_inode_flag(inode, FI_INC_LINK); - f2fs_lock_op(sbi); -diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c -index e863136081b47..556fcd8457f3f 100644 ---- a/fs/f2fs/node.c -+++ b/fs/f2fs/node.c -@@ -1443,6 +1443,7 @@ page_hit: - nid, nid_of_node(page), ino_of_node(page), - ofs_of_node(page), cpver_of_node(page), - next_blkaddr_of_node(page)); -+ set_sbi_flag(sbi, SBI_NEED_FSCK); - err = -EINVAL; - out_err: - ClearPageUptodate(page); -diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c -index a135d22474154..d716553bdc025 100644 ---- a/fs/f2fs/segment.c -+++ b/fs/f2fs/segment.c -@@ -561,7 +561,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg) - goto do_sync; - - /* checkpoint is the only way to shrink partial cached entries */ -- if (f2fs_available_free_memory(sbi, NAT_ENTRIES) || -+ if (f2fs_available_free_memory(sbi, NAT_ENTRIES) && - f2fs_available_free_memory(sbi, INO_ENTRIES)) - return; - -diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c -index 78ebc306ee2b5..8795a5a8d4e89 100644 ---- a/fs/f2fs/super.c -+++ b/fs/f2fs/super.c -@@ -1292,7 +1292,7 @@ default_check: - /* Not pass down write hints if the number of active logs is lesser - * than NR_CURSEG_PERSIST_TYPE. - */ -- if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE) -+ if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_PERSIST_TYPE) - F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; - - if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) { -@@ -3487,7 +3487,7 @@ skip_cross: - NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) { - f2fs_warn(sbi, "Insane cp_payload: %u, nat_bits_blocks: %u)", - cp_payload, nat_bits_blocks); -- return -EFSCORRUPTED; -+ return 1; - } - - if (unlikely(f2fs_cp_error(sbi))) { -@@ -4352,6 +4352,8 @@ free_node_inode: - free_stats: - f2fs_destroy_stats(sbi); - free_nm: -+ /* stop discard thread before destroying node manager */ -+ f2fs_stop_discard_thread(sbi); - f2fs_destroy_node_manager(sbi); - free_sm: - f2fs_destroy_segment_manager(sbi); -diff --git a/fs/file.c b/fs/file.c -index 8627dacfc4246..ad4a8bf3cf109 100644 ---- a/fs/file.c -+++ b/fs/file.c -@@ -858,6 +858,10 @@ loop: - file = NULL; - else if (!get_file_rcu_many(file, refs)) - goto loop; -+ else if (files_lookup_fd_raw(files, fd) != file) { -+ fput_many(file, refs); -+ goto loop; -+ } - } - rcu_read_unlock(); - -diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c -index dde341a6388a1..a9d21b33da9c4 100644 ---- a/fs/fuse/dev.c -+++ b/fs/fuse/dev.c -@@ -852,6 +852,12 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) - if (!(buf->flags & PIPE_BUF_FLAG_LRU)) - lru_cache_add(newpage); - -+ /* -+ * Release while we have extra ref on stolen page. Otherwise -+ * anon_pipe_buf_release() might think the page can be reused. -+ */ -+ pipe_buf_release(cs->pipe, buf); -+ - err = 0; - spin_lock(&cs->req->waitq.lock); - if (test_bit(FR_ABORTED, &cs->req->flags)) -@@ -2031,8 +2037,12 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, - - pipe_lock(pipe); - out_free: -- for (idx = 0; idx < nbuf; idx++) -- pipe_buf_release(pipe, &bufs[idx]); -+ for (idx = 0; idx < nbuf; idx++) { -+ struct pipe_buffer *buf = &bufs[idx]; -+ -+ if (buf->ops) -+ pipe_buf_release(pipe, buf); -+ } - pipe_unlock(pipe); - - kvfree(bufs); -diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c -index d9b977c0f38dc..80a2181b402b2 100644 ---- a/fs/fuse/dir.c -+++ b/fs/fuse/dir.c -@@ -738,11 +738,19 @@ static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir, - return create_new_entry(fm, &args, dir, entry, S_IFLNK); - } - -+void fuse_flush_time_update(struct inode *inode) -+{ -+ int err = sync_inode_metadata(inode, 1); -+ -+ mapping_set_error(inode->i_mapping, err); -+} -+ - void fuse_update_ctime(struct inode *inode) - { - if (!IS_NOCMTIME(inode)) { - inode->i_ctime = current_time(inode); - mark_inode_dirty_sync(inode); -+ fuse_flush_time_update(inode); - } - } - -@@ -1071,7 +1079,7 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, - if (!parent) - return -ENOENT; - -- inode_lock(parent); -+ inode_lock_nested(parent, I_MUTEX_PARENT); - if (!S_ISDIR(parent->i_mode)) - goto unlock; - -diff --git a/fs/fuse/file.c b/fs/fuse/file.c -index 11404f8c21c75..5c5ed58d91a73 100644 ---- a/fs/fuse/file.c -+++ b/fs/fuse/file.c -@@ -1848,6 +1848,17 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc) - struct fuse_file *ff; - int err; - -+ /* -+ * Inode is always written before the last reference is dropped and -+ * hence this should not be reached from reclaim. -+ * -+ * Writing back the inode from reclaim can deadlock if the request -+ * processing itself needs an allocation. Allocations triggering -+ * reclaim while serving a request can't be prevented, because it can -+ * involve any number of unrelated userspace processes. -+ */ -+ WARN_ON(wbc->for_reclaim); -+ - ff = __fuse_write_file_get(fi); - err = fuse_flush_times(inode, ff); - if (ff) -@@ -3002,6 +3013,8 @@ out: - if (lock_inode) - inode_unlock(inode); - -+ fuse_flush_time_update(inode); -+ - return err; - } - -@@ -3111,6 +3124,8 @@ out: - inode_unlock(inode_out); - file_accessed(file_in); - -+ fuse_flush_time_update(inode_out); -+ - return err; - } - -diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h -index f55f9f94b1a4f..a59e36c7deaea 100644 ---- a/fs/fuse/fuse_i.h -+++ b/fs/fuse/fuse_i.h -@@ -1148,6 +1148,7 @@ int fuse_allow_current_process(struct fuse_conn *fc); - - u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); - -+void fuse_flush_time_update(struct inode *inode); - void fuse_update_ctime(struct inode *inode); - - int fuse_update_attributes(struct inode *inode, struct file *file); -diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c -index 12d49a1914e84..2f999d38c9b4a 100644 ---- a/fs/fuse/inode.c -+++ b/fs/fuse/inode.c -@@ -118,6 +118,9 @@ static void fuse_evict_inode(struct inode *inode) - { - struct fuse_inode *fi = get_fuse_inode(inode); - -+ /* Will write inode on close/munmap and in all other dirtiers */ -+ WARN_ON(inode->i_state & I_DIRTY_INODE); -+ - truncate_inode_pages_final(&inode->i_data); - clear_inode(inode); - if (inode->i_sb->s_flags & SB_ACTIVE) { -diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c -index 5414c2c335809..fba32141a651b 100644 ---- a/fs/gfs2/bmap.c -+++ b/fs/gfs2/bmap.c -@@ -940,7 +940,7 @@ do_alloc: - else if (height == ip->i_height) - ret = gfs2_hole_size(inode, lblock, len, mp, iomap); - else -- iomap->length = size - pos; -+ iomap->length = size - iomap->offset; - } else if (flags & IOMAP_WRITE) { - u64 alloc_size; - -diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c -index e0eaa9cf9fb6f..02cd0ae98208d 100644 ---- a/fs/gfs2/glock.c -+++ b/fs/gfs2/glock.c -@@ -1893,10 +1893,10 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) - do { - rhashtable_walk_start(&iter); - -- while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl)) -- if (gl->gl_name.ln_sbd == sdp && -- lockref_get_not_dead(&gl->gl_lockref)) -+ while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl)) { -+ if (gl->gl_name.ln_sbd == sdp) - examiner(gl); -+ } - - rhashtable_walk_stop(&iter); - } while (cond_resched(), gl == ERR_PTR(-EAGAIN)); -@@ -1919,7 +1919,7 @@ bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay) - - void gfs2_cancel_delete_work(struct gfs2_glock *gl) - { -- if (cancel_delayed_work_sync(&gl->gl_delete)) { -+ if (cancel_delayed_work(&gl->gl_delete)) { - clear_bit(GLF_PENDING_DELETE, &gl->gl_flags); - gfs2_glock_put(gl); - } -@@ -1938,7 +1938,6 @@ static void flush_delete_work(struct gfs2_glock *gl) - &gl->gl_delete, 0); - } - } -- gfs2_glock_queue_work(gl, 0); - } - - void gfs2_flush_delete_work(struct gfs2_sbd *sdp) -@@ -1955,10 +1954,10 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp) - - static void thaw_glock(struct gfs2_glock *gl) - { -- if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) { -- gfs2_glock_put(gl); -+ if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) -+ return; -+ if (!lockref_get_not_dead(&gl->gl_lockref)) - return; -- } - set_bit(GLF_REPLY_PENDING, &gl->gl_flags); - gfs2_glock_queue_work(gl, 0); - } -@@ -1974,9 +1973,12 @@ static void clear_glock(struct gfs2_glock *gl) - gfs2_glock_remove_from_lru(gl); - - spin_lock(&gl->gl_lockref.lock); -- if (gl->gl_state != LM_ST_UNLOCKED) -- handle_callback(gl, LM_ST_UNLOCKED, 0, false); -- __gfs2_glock_queue_work(gl, 0); -+ if (!__lockref_is_dead(&gl->gl_lockref)) { -+ gl->gl_lockref.count++; -+ if (gl->gl_state != LM_ST_UNLOCKED) -+ handle_callback(gl, LM_ST_UNLOCKED, 0, false); -+ __gfs2_glock_queue_work(gl, 0); -+ } - spin_unlock(&gl->gl_lockref.lock); - } - -diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c -index 6e00d15ef0a82..cc51b5f5f52d8 100644 ---- a/fs/gfs2/super.c -+++ b/fs/gfs2/super.c -@@ -1402,13 +1402,6 @@ out: - gfs2_ordered_del_inode(ip); - clear_inode(inode); - gfs2_dir_hash_inval(ip); -- if (ip->i_gl) { -- glock_clear_object(ip->i_gl, ip); -- wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); -- gfs2_glock_add_to_lru(ip->i_gl); -- gfs2_glock_put_eventually(ip->i_gl); -- ip->i_gl = NULL; -- } - if (gfs2_holder_initialized(&ip->i_iopen_gh)) { - struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; - -@@ -1421,6 +1414,13 @@ out: - gfs2_holder_uninit(&ip->i_iopen_gh); - gfs2_glock_put_eventually(gl); - } -+ if (ip->i_gl) { -+ glock_clear_object(ip->i_gl, ip); -+ wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); -+ gfs2_glock_add_to_lru(ip->i_gl); -+ gfs2_glock_put_eventually(ip->i_gl); -+ ip->i_gl = NULL; -+ } - } - - static struct inode *gfs2_alloc_inode(struct super_block *sb) -diff --git a/fs/inode.c b/fs/inode.c -index ed0cab8a32db1..9abc88d7959cb 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1782,12 +1782,13 @@ EXPORT_SYMBOL(generic_update_time); - * This does the actual work of updating an inodes time or version. Must have - * had called mnt_want_write() before calling this. - */ --static int update_time(struct inode *inode, struct timespec64 *time, int flags) -+int inode_update_time(struct inode *inode, struct timespec64 *time, int flags) - { - if (inode->i_op->update_time) - return inode->i_op->update_time(inode, time, flags); - return generic_update_time(inode, time, flags); - } -+EXPORT_SYMBOL(inode_update_time); - - /** - * atime_needs_update - update the access time -@@ -1857,7 +1858,7 @@ void touch_atime(const struct path *path) - * of the fs read only, e.g. subvolumes in Btrfs. - */ - now = current_time(inode); -- update_time(inode, &now, S_ATIME); -+ inode_update_time(inode, &now, S_ATIME); - __mnt_drop_write(mnt); - skip_update: - sb_end_write(inode->i_sb); -@@ -2002,7 +2003,7 @@ int file_update_time(struct file *file) - if (__mnt_want_write_file(file)) - return 0; - -- ret = update_time(inode, &now, sync_it); -+ ret = inode_update_time(inode, &now, sync_it); - __mnt_drop_write_file(file); - - return ret; -diff --git a/fs/io-wq.c b/fs/io-wq.c -index 422a7ed6a9bdb..01d4e3ff3170d 100644 ---- a/fs/io-wq.c -+++ b/fs/io-wq.c -@@ -140,6 +140,8 @@ static void io_wqe_dec_running(struct io_worker *worker); - static bool io_acct_cancel_pending_work(struct io_wqe *wqe, - struct io_wqe_acct *acct, - struct io_cb_cancel_data *match); -+static void create_worker_cb(struct callback_head *cb); -+static void io_wq_cancel_tw_create(struct io_wq *wq); - - static bool io_worker_get(struct io_worker *worker) - { -@@ -174,9 +176,44 @@ static void io_worker_ref_put(struct io_wq *wq) - complete(&wq->worker_done); - } - -+static void io_worker_cancel_cb(struct io_worker *worker) -+{ -+ struct io_wqe_acct *acct = io_wqe_get_acct(worker); -+ struct io_wqe *wqe = worker->wqe; -+ struct io_wq *wq = wqe->wq; -+ -+ atomic_dec(&acct->nr_running); -+ raw_spin_lock(&worker->wqe->lock); -+ acct->nr_workers--; -+ raw_spin_unlock(&worker->wqe->lock); -+ io_worker_ref_put(wq); -+ clear_bit_unlock(0, &worker->create_state); -+ io_worker_release(worker); -+} -+ -+static bool io_task_worker_match(struct callback_head *cb, void *data) -+{ -+ struct io_worker *worker; -+ -+ if (cb->func != create_worker_cb) -+ return false; -+ worker = container_of(cb, struct io_worker, create_work); -+ return worker == data; -+} -+ - static void io_worker_exit(struct io_worker *worker) - { - struct io_wqe *wqe = worker->wqe; -+ struct io_wq *wq = wqe->wq; -+ -+ while (1) { -+ struct callback_head *cb = task_work_cancel_match(wq->task, -+ io_task_worker_match, worker); -+ -+ if (!cb) -+ break; -+ io_worker_cancel_cb(worker); -+ } - - if (refcount_dec_and_test(&worker->ref)) - complete(&worker->ref_done); -@@ -321,10 +358,22 @@ static bool io_queue_worker_create(struct io_worker *worker, - test_and_set_bit_lock(0, &worker->create_state)) - goto fail_release; - -+ atomic_inc(&wq->worker_refs); - init_task_work(&worker->create_work, func); - worker->create_index = acct->index; -- if (!task_work_add(wq->task, &worker->create_work, TWA_SIGNAL)) -+ if (!task_work_add(wq->task, &worker->create_work, TWA_SIGNAL)) { -+ /* -+ * EXIT may have been set after checking it above, check after -+ * adding the task_work and remove any creation item if it is -+ * now set. wq exit does that too, but we can have added this -+ * work item after we canceled in io_wq_exit_workers(). -+ */ -+ if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) -+ io_wq_cancel_tw_create(wq); -+ io_worker_ref_put(wq); - return true; -+ } -+ io_worker_ref_put(wq); - clear_bit_unlock(0, &worker->create_state); - fail_release: - io_worker_release(worker); -@@ -346,7 +395,9 @@ static void io_wqe_dec_running(struct io_worker *worker) - if (atomic_dec_and_test(&acct->nr_running) && io_acct_run_queue(acct)) { - atomic_inc(&acct->nr_running); - atomic_inc(&wqe->wq->worker_refs); -+ raw_spin_unlock(&wqe->lock); - io_queue_worker_create(worker, acct, create_worker_cb); -+ raw_spin_lock(&wqe->lock); - } - } - -@@ -385,9 +436,10 @@ static inline unsigned int io_get_work_hash(struct io_wq_work *work) - return work->flags >> IO_WQ_HASH_SHIFT; - } - --static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) -+static bool io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) - { - struct io_wq *wq = wqe->wq; -+ bool ret = false; - - spin_lock_irq(&wq->hash->wait.lock); - if (list_empty(&wqe->wait.entry)) { -@@ -395,9 +447,11 @@ static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) - if (!test_bit(hash, &wq->hash->map)) { - __set_current_state(TASK_RUNNING); - list_del_init(&wqe->wait.entry); -+ ret = true; - } - } - spin_unlock_irq(&wq->hash->wait.lock); -+ return ret; - } - - static struct io_wq_work *io_get_next_work(struct io_wqe_acct *acct, -@@ -437,14 +491,21 @@ static struct io_wq_work *io_get_next_work(struct io_wqe_acct *acct, - } - - if (stall_hash != -1U) { -+ bool unstalled; -+ - /* - * Set this before dropping the lock to avoid racing with new - * work being added and clearing the stalled bit. - */ - set_bit(IO_ACCT_STALLED_BIT, &acct->flags); - raw_spin_unlock(&wqe->lock); -- io_wait_on_hash(wqe, stall_hash); -+ unstalled = io_wait_on_hash(wqe, stall_hash); - raw_spin_lock(&wqe->lock); -+ if (unstalled) { -+ clear_bit(IO_ACCT_STALLED_BIT, &acct->flags); -+ if (wq_has_sleeper(&wqe->wq->hash->wait)) -+ wake_up(&wqe->wq->hash->wait); -+ } - } - - return NULL; -@@ -526,8 +587,11 @@ get_next: - io_wqe_enqueue(wqe, linked); - - if (hash != -1U && !next_hashed) { -+ /* serialize hash clear with wake_up() */ -+ spin_lock_irq(&wq->hash->wait.lock); - clear_bit(hash, &wq->hash->map); - clear_bit(IO_ACCT_STALLED_BIT, &acct->flags); -+ spin_unlock_irq(&wq->hash->wait.lock); - if (wq_has_sleeper(&wq->hash->wait)) - wake_up(&wq->hash->wait); - raw_spin_lock(&wqe->lock); -@@ -660,6 +724,13 @@ static bool io_wq_work_match_all(struct io_wq_work *work, void *data) - - static inline bool io_should_retry_thread(long err) - { -+ /* -+ * Prevent perpetual task_work retry, if the task (or its group) is -+ * exiting. -+ */ -+ if (fatal_signal_pending(current)) -+ return false; -+ - switch (err) { - case -EAGAIN: - case -ERESTARTSYS: -@@ -716,11 +787,8 @@ static void io_workqueue_create(struct work_struct *work) - struct io_worker *worker = container_of(work, struct io_worker, work); - struct io_wqe_acct *acct = io_wqe_get_acct(worker); - -- if (!io_queue_worker_create(worker, acct, create_worker_cont)) { -- clear_bit_unlock(0, &worker->create_state); -- io_worker_release(worker); -+ if (!io_queue_worker_create(worker, acct, create_worker_cont)) - kfree(worker); -- } - } - - static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index) -@@ -1140,28 +1208,26 @@ void io_wq_exit_start(struct io_wq *wq) - set_bit(IO_WQ_BIT_EXIT, &wq->state); - } - --static void io_wq_exit_workers(struct io_wq *wq) -+static void io_wq_cancel_tw_create(struct io_wq *wq) - { - struct callback_head *cb; -- int node; -- -- if (!wq->task) -- return; - - while ((cb = task_work_cancel_match(wq->task, io_task_work_match, wq)) != NULL) { - struct io_worker *worker; -- struct io_wqe_acct *acct; - - worker = container_of(cb, struct io_worker, create_work); -- acct = io_wqe_get_acct(worker); -- atomic_dec(&acct->nr_running); -- raw_spin_lock(&worker->wqe->lock); -- acct->nr_workers--; -- raw_spin_unlock(&worker->wqe->lock); -- io_worker_ref_put(wq); -- clear_bit_unlock(0, &worker->create_state); -- io_worker_release(worker); -+ io_worker_cancel_cb(worker); - } -+} -+ -+static void io_wq_exit_workers(struct io_wq *wq) -+{ -+ int node; -+ -+ if (!wq->task) -+ return; -+ -+ io_wq_cancel_tw_create(wq); - - rcu_read_lock(); - for_each_node(node) { -@@ -1278,7 +1344,9 @@ int io_wq_cpu_affinity(struct io_wq *wq, cpumask_var_t mask) - */ - int io_wq_max_workers(struct io_wq *wq, int *new_count) - { -- int i, node, prev = 0; -+ int prev[IO_WQ_ACCT_NR]; -+ bool first_node = true; -+ int i, node; - - BUILD_BUG_ON((int) IO_WQ_ACCT_BOUND != (int) IO_WQ_BOUND); - BUILD_BUG_ON((int) IO_WQ_ACCT_UNBOUND != (int) IO_WQ_UNBOUND); -@@ -1289,6 +1357,9 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count) - new_count[i] = task_rlimit(current, RLIMIT_NPROC); - } - -+ for (i = 0; i < IO_WQ_ACCT_NR; i++) -+ prev[i] = 0; -+ - rcu_read_lock(); - for_each_node(node) { - struct io_wqe *wqe = wq->wqes[node]; -@@ -1297,14 +1368,19 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count) - raw_spin_lock(&wqe->lock); - for (i = 0; i < IO_WQ_ACCT_NR; i++) { - acct = &wqe->acct[i]; -- prev = max_t(int, acct->max_workers, prev); -+ if (first_node) -+ prev[i] = max_t(int, acct->max_workers, prev[i]); - if (new_count[i]) - acct->max_workers = new_count[i]; -- new_count[i] = prev; - } - raw_spin_unlock(&wqe->lock); -+ first_node = false; - } - rcu_read_unlock(); -+ -+ for (i = 0; i < IO_WQ_ACCT_NR; i++) -+ new_count[i] = prev[i]; -+ - return 0; - } - -diff --git a/fs/io_uring.c b/fs/io_uring.c -index bc18af5e0a934..e9b06e339c4b0 100644 ---- a/fs/io_uring.c -+++ b/fs/io_uring.c -@@ -1204,6 +1204,7 @@ static void io_refs_resurrect(struct percpu_ref *ref, struct completion *compl) - - static bool io_match_task(struct io_kiocb *head, struct task_struct *task, - bool cancel_all) -+ __must_hold(&req->ctx->timeout_lock) - { - struct io_kiocb *req; - -@@ -1219,6 +1220,44 @@ static bool io_match_task(struct io_kiocb *head, struct task_struct *task, - return false; - } - -+static bool io_match_linked(struct io_kiocb *head) -+{ -+ struct io_kiocb *req; -+ -+ io_for_each_link(req, head) { -+ if (req->flags & REQ_F_INFLIGHT) -+ return true; -+ } -+ return false; -+} -+ -+/* -+ * As io_match_task() but protected against racing with linked timeouts. -+ * User must not hold timeout_lock. -+ */ -+static bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task, -+ bool cancel_all) -+{ -+ bool matched; -+ -+ if (task && head->task != task) -+ return false; -+ if (cancel_all) -+ return true; -+ -+ if (head->flags & REQ_F_LINK_TIMEOUT) { -+ struct io_ring_ctx *ctx = head->ctx; -+ -+ /* protect against races with linked timeouts */ -+ spin_lock_irq(&ctx->timeout_lock); -+ matched = io_match_linked(head); -+ spin_unlock_irq(&ctx->timeout_lock); -+ } else { -+ matched = io_match_linked(head); -+ } -+ return matched; -+} -+ - static inline void req_set_fail(struct io_kiocb *req) - { - req->flags |= REQ_F_FAIL; -@@ -1430,10 +1469,10 @@ static void io_prep_async_link(struct io_kiocb *req) - if (req->flags & REQ_F_LINK_TIMEOUT) { - struct io_ring_ctx *ctx = req->ctx; - -- spin_lock(&ctx->completion_lock); -+ spin_lock_irq(&ctx->timeout_lock); - io_for_each_link(cur, req) - io_prep_async_work(cur); -- spin_unlock(&ctx->completion_lock); -+ spin_unlock_irq(&ctx->timeout_lock); - } else { - io_for_each_link(cur, req) - io_prep_async_work(cur); -@@ -4304,6 +4343,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf, - kfree(nxt); - if (++i == nbufs) - return i; -+ cond_resched(); - } - i++; - kfree(buf); -@@ -5702,7 +5742,7 @@ static bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk, - - list = &ctx->cancel_hash[i]; - hlist_for_each_entry_safe(req, tmp, list, hash_node) { -- if (io_match_task(req, tsk, cancel_all)) -+ if (io_match_task_safe(req, tsk, cancel_all)) - posted += io_poll_remove_one(req); - } - } -@@ -6884,10 +6924,11 @@ static inline struct file *io_file_get(struct io_ring_ctx *ctx, - static void io_req_task_link_timeout(struct io_kiocb *req, bool *locked) - { - struct io_kiocb *prev = req->timeout.prev; -- int ret; -+ int ret = -ENOENT; - - if (prev) { -- ret = io_try_cancel_userdata(req, prev->user_data); -+ if (!(req->task->flags & PF_EXITING)) -+ ret = io_try_cancel_userdata(req, prev->user_data); - io_req_complete_post(req, ret ?: -ETIME, 0); - io_put_req(prev); - } else { -@@ -9209,10 +9250,8 @@ static void io_destroy_buffers(struct io_ring_ctx *ctx) - struct io_buffer *buf; - unsigned long index; - -- xa_for_each(&ctx->io_buffers, index, buf) { -+ xa_for_each(&ctx->io_buffers, index, buf) - __io_remove_buffers(ctx, buf, index, -1U); -- cond_resched(); -- } - } - - static void io_req_cache_free(struct list_head *list) -@@ -9517,19 +9556,8 @@ static bool io_cancel_task_cb(struct io_wq_work *work, void *data) - { - struct io_kiocb *req = container_of(work, struct io_kiocb, work); - struct io_task_cancel *cancel = data; -- bool ret; -- -- if (!cancel->all && (req->flags & REQ_F_LINK_TIMEOUT)) { -- struct io_ring_ctx *ctx = req->ctx; - -- /* protect against races with linked timeouts */ -- spin_lock(&ctx->completion_lock); -- ret = io_match_task(req, cancel->task, cancel->all); -- spin_unlock(&ctx->completion_lock); -- } else { -- ret = io_match_task(req, cancel->task, cancel->all); -- } -- return ret; -+ return io_match_task_safe(req, cancel->task, cancel->all); - } - - static bool io_cancel_defer_files(struct io_ring_ctx *ctx, -@@ -9540,7 +9568,7 @@ static bool io_cancel_defer_files(struct io_ring_ctx *ctx, - - spin_lock(&ctx->completion_lock); - list_for_each_entry_reverse(de, &ctx->defer_list, list) { -- if (io_match_task(de->req, task, cancel_all)) { -+ if (io_match_task_safe(de->req, task, cancel_all)) { - list_cut_position(&list, &ctx->defer_list, &de->list); - break; - } -@@ -9747,7 +9775,7 @@ static void io_uring_drop_tctx_refs(struct task_struct *task) - - /* - * Find any io_uring ctx that this task has registered or done IO on, and cancel -- * requests. @sqd should be not-null IIF it's an SQPOLL thread cancellation. -+ * requests. @sqd should be not-null IFF it's an SQPOLL thread cancellation. - */ - static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) - { -@@ -9788,8 +9816,10 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) - cancel_all); - } - -- prepare_to_wait(&tctx->wait, &wait, TASK_UNINTERRUPTIBLE); -+ prepare_to_wait(&tctx->wait, &wait, TASK_INTERRUPTIBLE); -+ io_run_task_work(); - io_uring_drop_tctx_refs(current); -+ - /* - * If we've seen completions, retry without waiting. This - * avoids a race where a completion comes in before we did -@@ -10684,7 +10714,9 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx, - - BUILD_BUG_ON(sizeof(new_count) != sizeof(ctx->iowq_limits)); - -- memcpy(ctx->iowq_limits, new_count, sizeof(new_count)); -+ for (i = 0; i < ARRAY_SIZE(new_count); i++) -+ if (new_count[i]) -+ ctx->iowq_limits[i] = new_count[i]; - ctx->iowq_limits_set = true; - - ret = -EINVAL; -diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c -index 9cc5798423d12..97119ec3b8503 100644 ---- a/fs/iomap/buffered-io.c -+++ b/fs/iomap/buffered-io.c -@@ -256,8 +256,13 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, - unsigned poff, plen; - sector_t sector; - -- if (iomap->type == IOMAP_INLINE) -- return min(iomap_read_inline_data(iter, page), length); -+ if (iomap->type == IOMAP_INLINE) { -+ loff_t ret = iomap_read_inline_data(iter, page); -+ -+ if (ret < 0) -+ return ret; -+ return 0; -+ } - - /* zero post-eof blocks as the page may be mapped */ - iop = iomap_page_create(iter->inode, page); -@@ -370,6 +375,8 @@ static loff_t iomap_readahead_iter(const struct iomap_iter *iter, - ctx->cur_page_in_bio = false; - } - ret = iomap_readpage_iter(iter, ctx, done); -+ if (ret <= 0) -+ return ret; - } - - return done; -diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c -index 678e2c51b855c..0c6eacfcbeef1 100644 ---- a/fs/isofs/inode.c -+++ b/fs/isofs/inode.c -@@ -1322,6 +1322,8 @@ static int isofs_read_inode(struct inode *inode, int relocated) - - de = (struct iso_directory_record *) (bh->b_data + offset); - de_len = *(unsigned char *) de; -+ if (de_len < sizeof(struct iso_directory_record)) -+ goto fail; - - if (offset + de_len > bufsize) { - int frag1 = bufsize - offset; -diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c -index 5d7d7170c03c0..aa4ff7bcaff23 100644 ---- a/fs/jfs/jfs_mount.c -+++ b/fs/jfs/jfs_mount.c -@@ -81,14 +81,14 @@ int jfs_mount(struct super_block *sb) - * (initialize mount inode from the superblock) - */ - if ((rc = chkSuper(sb))) { -- goto errout20; -+ goto out; - } - - ipaimap = diReadSpecial(sb, AGGREGATE_I, 0); - if (ipaimap == NULL) { - jfs_err("jfs_mount: Failed to read AGGREGATE_I"); - rc = -EIO; -- goto errout20; -+ goto out; - } - sbi->ipaimap = ipaimap; - -@@ -99,7 +99,7 @@ int jfs_mount(struct super_block *sb) - */ - if ((rc = diMount(ipaimap))) { - jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc); -- goto errout21; -+ goto err_ipaimap; - } - - /* -@@ -108,7 +108,7 @@ int jfs_mount(struct super_block *sb) - ipbmap = diReadSpecial(sb, BMAP_I, 0); - if (ipbmap == NULL) { - rc = -EIO; -- goto errout22; -+ goto err_umount_ipaimap; - } - - jfs_info("jfs_mount: ipbmap:0x%p", ipbmap); -@@ -120,7 +120,7 @@ int jfs_mount(struct super_block *sb) - */ - if ((rc = dbMount(ipbmap))) { - jfs_err("jfs_mount: dbMount failed w/rc = %d", rc); -- goto errout22; -+ goto err_ipbmap; - } - - /* -@@ -139,7 +139,7 @@ int jfs_mount(struct super_block *sb) - if (!ipaimap2) { - jfs_err("jfs_mount: Failed to read AGGREGATE_I"); - rc = -EIO; -- goto errout35; -+ goto err_umount_ipbmap; - } - sbi->ipaimap2 = ipaimap2; - -@@ -151,7 +151,7 @@ int jfs_mount(struct super_block *sb) - if ((rc = diMount(ipaimap2))) { - jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d", - rc); -- goto errout35; -+ goto err_ipaimap2; - } - } else - /* Secondary aggregate inode table is not valid */ -@@ -168,7 +168,7 @@ int jfs_mount(struct super_block *sb) - jfs_err("jfs_mount: Failed to read FILESYSTEM_I"); - /* open fileset secondary inode allocation map */ - rc = -EIO; -- goto errout40; -+ goto err_umount_ipaimap2; - } - jfs_info("jfs_mount: ipimap:0x%p", ipimap); - -@@ -178,41 +178,34 @@ int jfs_mount(struct super_block *sb) - /* initialize fileset inode allocation map */ - if ((rc = diMount(ipimap))) { - jfs_err("jfs_mount: diMount failed w/rc = %d", rc); -- goto errout41; -+ goto err_ipimap; - } - -- goto out; -+ return rc; - - /* - * unwind on error - */ -- errout41: /* close fileset inode allocation map inode */ -+err_ipimap: -+ /* close fileset inode allocation map inode */ - diFreeSpecial(ipimap); -- -- errout40: /* fileset closed */ -- -+err_umount_ipaimap2: - /* close secondary aggregate inode allocation map */ -- if (ipaimap2) { -+ if (ipaimap2) - diUnmount(ipaimap2, 1); -+err_ipaimap2: -+ /* close aggregate inodes */ -+ if (ipaimap2) - diFreeSpecial(ipaimap2); -- } -- -- errout35: -- -- /* close aggregate block allocation map */ -+err_umount_ipbmap: /* close aggregate block allocation map */ - dbUnmount(ipbmap, 1); -+err_ipbmap: /* close aggregate inodes */ - diFreeSpecial(ipbmap); -- -- errout22: /* close aggregate inode allocation map */ -- -+err_umount_ipaimap: /* close aggregate inode allocation map */ - diUnmount(ipaimap, 1); -- -- errout21: /* close aggregate inodes */ -+err_ipaimap: /* close aggregate inodes */ - diFreeSpecial(ipaimap); -- errout20: /* aggregate closed */ -- -- out: -- -+out: - if (rc) - jfs_err("Mount JFS Failure: %d", rc); - -diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig -index b83cbd756ae50..6af339cfdc041 100644 ---- a/fs/ksmbd/Kconfig -+++ b/fs/ksmbd/Kconfig -@@ -19,6 +19,7 @@ config SMB_SERVER - select CRYPTO_GCM - select ASN1 - select OID_REGISTRY -+ select CRC32 - default n - help - Choose Y here if you want to allow SMB3 compliant clients -diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c -index 2a2b2135bfded..36d368e59a640 100644 ---- a/fs/ksmbd/server.c -+++ b/fs/ksmbd/server.c -@@ -632,5 +632,6 @@ MODULE_SOFTDEP("pre: sha512"); - MODULE_SOFTDEP("pre: aead2"); - MODULE_SOFTDEP("pre: ccm"); - MODULE_SOFTDEP("pre: gcm"); -+MODULE_SOFTDEP("pre: crc32"); - module_init(ksmbd_server_init) - module_exit(ksmbd_server_exit) -diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c -index 030ca57c37849..9f516f73bd1b6 100644 ---- a/fs/ksmbd/smb2misc.c -+++ b/fs/ksmbd/smb2misc.c -@@ -358,12 +358,10 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) - hdr = &pdu->hdr; - } - -- if (le32_to_cpu(hdr->NextCommand) > 0) { -+ if (le32_to_cpu(hdr->NextCommand) > 0) - len = le32_to_cpu(hdr->NextCommand); -- } else if (work->next_smb2_rcv_hdr_off) { -+ else if (work->next_smb2_rcv_hdr_off) - len -= work->next_smb2_rcv_hdr_off; -- len = round_up(len, 8); -- } - - if (check_smb2_hdr(hdr)) - return 1; -diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c -index 7e448df3f8474..ad0ea5d36f2ee 100644 ---- a/fs/ksmbd/smb2pdu.c -+++ b/fs/ksmbd/smb2pdu.c -@@ -1700,8 +1700,10 @@ int smb2_sess_setup(struct ksmbd_work *work) - negblob_off = le16_to_cpu(req->SecurityBufferOffset); - negblob_len = le16_to_cpu(req->SecurityBufferLength); - if (negblob_off < (offsetof(struct smb2_sess_setup_req, Buffer) - 4) || -- negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) -- return -EINVAL; -+ negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { -+ rc = -EINVAL; -+ goto out_err; -+ } - - negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId + - negblob_off); -@@ -4450,6 +4452,12 @@ static void get_file_stream_info(struct ksmbd_work *work, - &stat); - file_info = (struct smb2_file_stream_info *)rsp->Buffer; - -+ buf_free_len = -+ smb2_calc_max_out_buf_len(work, 8, -+ le32_to_cpu(req->OutputBufferLength)); -+ if (buf_free_len < 0) -+ goto out; -+ - xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); - if (xattr_list_len < 0) { - goto out; -@@ -4458,12 +4466,6 @@ static void get_file_stream_info(struct ksmbd_work *work, - goto out; - } - -- buf_free_len = -- smb2_calc_max_out_buf_len(work, 8, -- le32_to_cpu(req->OutputBufferLength)); -- if (buf_free_len < 0) -- goto out; -- - while (idx < xattr_list_len) { - stream_name = xattr_list + idx; - streamlen = strlen(stream_name); -@@ -4489,8 +4491,10 @@ static void get_file_stream_info(struct ksmbd_work *work, - ":%s", &stream_name[XATTR_NAME_STREAM_LEN]); - - next = sizeof(struct smb2_file_stream_info) + streamlen * 2; -- if (next > buf_free_len) -+ if (next > buf_free_len) { -+ kfree(stream_buf); - break; -+ } - - file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes]; - streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName, -@@ -4507,6 +4511,7 @@ static void get_file_stream_info(struct ksmbd_work *work, - file_info->NextEntryOffset = cpu_to_le32(next); - } - -+out: - if (!S_ISDIR(stat.mode) && - buf_free_len >= sizeof(struct smb2_file_stream_info) + 7 * 2) { - file_info = (struct smb2_file_stream_info *) -@@ -4515,14 +4520,13 @@ static void get_file_stream_info(struct ksmbd_work *work, - "::$DATA", 7, conn->local_nls, 0); - streamlen *= 2; - file_info->StreamNameLength = cpu_to_le32(streamlen); -- file_info->StreamSize = 0; -- file_info->StreamAllocationSize = 0; -+ file_info->StreamSize = cpu_to_le64(stat.size); -+ file_info->StreamAllocationSize = cpu_to_le64(stat.blocks << 9); - nbytes += sizeof(struct smb2_file_stream_info) + streamlen; - } - - /* last entry offset should be 0 */ - file_info->NextEntryOffset = 0; --out: - kvfree(xattr_list); - - rsp->OutputBufferLength = cpu_to_le32(nbytes); -@@ -4891,11 +4895,18 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, - { - struct filesystem_vol_info *info; - size_t sz; -+ unsigned int serial_crc = 0; - - info = (struct filesystem_vol_info *)(rsp->Buffer); - info->VolumeCreationTime = 0; -+ serial_crc = crc32_le(serial_crc, share->name, -+ strlen(share->name)); -+ serial_crc = crc32_le(serial_crc, share->path, -+ strlen(share->path)); -+ serial_crc = crc32_le(serial_crc, ksmbd_netbios_name(), -+ strlen(ksmbd_netbios_name())); - /* Taking dummy value of serial number*/ -- info->SerialNumber = cpu_to_le32(0xbc3ac512); -+ info->SerialNumber = cpu_to_le32(serial_crc); - len = smbConvertToUTF16((__le16 *)info->VolumeLabel, - share->name, PATH_MAX, - conn->local_nls, 0); -@@ -5053,7 +5064,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work, - if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | - PROTECTED_DACL_SECINFO | - UNPROTECTED_DACL_SECINFO)) { -- pr_err("Unsupported addition info: 0x%x)\n", -+ ksmbd_debug(SMB, "Unsupported addition info: 0x%x)\n", - addition_info); - - pntsd->revision = cpu_to_le16(1); -@@ -7312,7 +7323,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn, - int ret = 0; - int dialect; - -- if (in_buf_len < sizeof(struct validate_negotiate_info_req) + -+ if (in_buf_len < offsetof(struct validate_negotiate_info_req, Dialects) + - le16_to_cpu(neg_req->DialectCount) * sizeof(__le16)) - return -EINVAL; - -diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c -index 994ec22d40402..4b54529f8176b 100644 ---- a/fs/netfs/read_helper.c -+++ b/fs/netfs/read_helper.c -@@ -354,16 +354,11 @@ static void netfs_rreq_write_to_cache_work(struct work_struct *work) - netfs_rreq_do_write_to_cache(rreq); - } - --static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq, -- bool was_async) -+static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq) - { -- if (was_async) { -- rreq->work.func = netfs_rreq_write_to_cache_work; -- if (!queue_work(system_unbound_wq, &rreq->work)) -- BUG(); -- } else { -- netfs_rreq_do_write_to_cache(rreq); -- } -+ rreq->work.func = netfs_rreq_write_to_cache_work; -+ if (!queue_work(system_unbound_wq, &rreq->work)) -+ BUG(); - } - - /* -@@ -560,7 +555,7 @@ again: - wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); - - if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags)) -- return netfs_rreq_write_to_cache(rreq, was_async); -+ return netfs_rreq_write_to_cache(rreq); - - netfs_rreq_completed(rreq, was_async); - } -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index 1a6d2867fba4f..5b68c44848caf 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -1269,13 +1269,12 @@ static bool nfs_verifier_is_delegated(struct dentry *dentry) - static void nfs_set_verifier_locked(struct dentry *dentry, unsigned long verf) - { - struct inode *inode = d_inode(dentry); -+ struct inode *dir = d_inode(dentry->d_parent); - -- if (!nfs_verifier_is_delegated(dentry) && -- !nfs_verify_change_attribute(d_inode(dentry->d_parent), verf)) -- goto out; -+ if (!nfs_verify_change_attribute(dir, verf)) -+ return; - if (inode && NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) - nfs_set_verifier_delegated(&verf); --out: - dentry->d_time = verf; - } - -@@ -1413,7 +1412,7 @@ out_force: - static void nfs_mark_dir_for_revalidate(struct inode *inode) - { - spin_lock(&inode->i_lock); -- nfs_set_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE); -+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE); - spin_unlock(&inode->i_lock); - } - -diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c -index 2e894fec036b0..3c0335c15a730 100644 ---- a/fs/nfs/direct.c -+++ b/fs/nfs/direct.c -@@ -620,7 +620,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data) - nfs_unlock_and_release_request(req); - } - -- if (atomic_dec_and_test(&cinfo.mds->rpcs_out)) -+ if (nfs_commit_end(cinfo.mds)) - nfs_direct_write_complete(dreq); - } - -diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c -index c9b61b818ec11..bfa7202ca7be1 100644 ---- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c -+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c -@@ -378,10 +378,10 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, - goto noconnect; - - ds = mirror->mirror_ds->ds; -+ if (READ_ONCE(ds->ds_clp)) -+ goto out; - /* matching smp_wmb() in _nfs4_pnfs_v3/4_ds_connect */ - smp_rmb(); -- if (ds->ds_clp) -- goto out; - - /* FIXME: For now we assume the server sent only one version of NFS - * to use for the DS. -diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c -index 853213b3a2095..f9d3ad3acf114 100644 ---- a/fs/nfs/inode.c -+++ b/fs/nfs/inode.c -@@ -210,10 +210,15 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) - flags &= ~NFS_INO_INVALID_XATTR; - if (flags & NFS_INO_INVALID_DATA) - nfs_fscache_invalidate(inode); -- if (inode->i_mapping->nrpages == 0) -- flags &= ~(NFS_INO_INVALID_DATA|NFS_INO_DATA_INVAL_DEFER); - flags &= ~(NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED); -+ - nfsi->cache_validity |= flags; -+ -+ if (inode->i_mapping->nrpages == 0) -+ nfsi->cache_validity &= ~(NFS_INO_INVALID_DATA | -+ NFS_INO_DATA_INVAL_DEFER); -+ else if (nfsi->cache_validity & NFS_INO_INVALID_DATA) -+ nfsi->cache_validity &= ~NFS_INO_DATA_INVAL_DEFER; - } - EXPORT_SYMBOL_GPL(nfs_set_cache_invalid); - -@@ -1777,8 +1782,10 @@ static int nfs_inode_finish_partial_attr_update(const struct nfs_fattr *fattr, - NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_OTHER | - NFS_INO_INVALID_NLINK; - unsigned long cache_validity = NFS_I(inode)->cache_validity; -+ enum nfs4_change_attr_type ctype = NFS_SERVER(inode)->change_attr_type; - -- if (!(cache_validity & NFS_INO_INVALID_CHANGE) && -+ if (ctype != NFS4_CHANGE_TYPE_IS_UNDEFINED && -+ !(cache_validity & NFS_INO_INVALID_CHANGE) && - (cache_validity & check_valid) != 0 && - (fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && - nfs_inode_attrs_cmp_monotonic(fattr, inode) == 0) -diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c -index e6eca1d7481b8..9274c9c5efea6 100644 ---- a/fs/nfs/nfs3xdr.c -+++ b/fs/nfs/nfs3xdr.c -@@ -2227,7 +2227,7 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr, - - /* ignore properties */ - result->lease_time = 0; -- result->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA; -+ result->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED; - return 0; - } - -diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c -index a24349512ffe9..9865b5c37d889 100644 ---- a/fs/nfs/nfs42proc.c -+++ b/fs/nfs/nfs42proc.c -@@ -285,7 +285,9 @@ static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len) - loff_t newsize = pos + len; - loff_t end = newsize - 1; - -- truncate_pagecache_range(inode, pos, end); -+ WARN_ON_ONCE(invalidate_inode_pages2_range(inode->i_mapping, -+ pos >> PAGE_SHIFT, end >> PAGE_SHIFT)); -+ - spin_lock(&inode->i_lock); - if (newsize > i_size_read(inode)) - i_size_write(inode, newsize); -diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c -index c8bad735e4c19..271e5f92ed019 100644 ---- a/fs/nfs/nfs42xdr.c -+++ b/fs/nfs/nfs42xdr.c -@@ -1434,8 +1434,7 @@ static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, - status = decode_clone(xdr); - if (status) - goto out; -- status = decode_getfattr(xdr, res->dst_fattr, res->server); -- -+ decode_getfattr(xdr, res->dst_fattr, res->server); - out: - res->rpc_status = status; - return status; -diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c -index 8d8aba305ecca..f331866dd4182 100644 ---- a/fs/nfs/nfs4idmap.c -+++ b/fs/nfs/nfs4idmap.c -@@ -487,7 +487,7 @@ nfs_idmap_new(struct nfs_client *clp) - err_destroy_pipe: - rpc_destroy_pipe_data(idmap->idmap_pipe); - err: -- get_user_ns(idmap->user_ns); -+ put_user_ns(idmap->user_ns); - kfree(idmap); - return error; - } -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index e1214bb6b7ee5..1f38f8cd8c3ce 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -1609,15 +1609,16 @@ static bool nfs_stateid_is_sequential(struct nfs4_state *state, - { - if (test_bit(NFS_OPEN_STATE, &state->flags)) { - /* The common case - we're updating to a new sequence number */ -- if (nfs4_stateid_match_other(stateid, &state->open_stateid) && -- nfs4_stateid_is_next(&state->open_stateid, stateid)) { -- return true; -+ if (nfs4_stateid_match_other(stateid, &state->open_stateid)) { -+ if (nfs4_stateid_is_next(&state->open_stateid, stateid)) -+ return true; -+ return false; - } -- } else { -- /* This is the first OPEN in this generation */ -- if (stateid->seqid == cpu_to_be32(1)) -- return true; -+ /* The server returned a new stateid */ - } -+ /* This is the first OPEN in this generation */ -+ if (stateid->seqid == cpu_to_be32(1)) -+ return true; - return false; - } - -diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h -index d810ae674f4e8..a0f6ff094b3a4 100644 ---- a/fs/nfs/pnfs.h -+++ b/fs/nfs/pnfs.h -@@ -517,7 +517,7 @@ pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg, - { - struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; - -- if (!lseg || !fl_cinfo->ops->mark_request_commit) -+ if (!lseg || !fl_cinfo->ops || !fl_cinfo->ops->mark_request_commit) - return false; - fl_cinfo->ops->mark_request_commit(req, lseg, cinfo, ds_commit_idx); - return true; -diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c -index cf19914fec817..316f68f96e573 100644 ---- a/fs/nfs/pnfs_nfs.c -+++ b/fs/nfs/pnfs_nfs.c -@@ -468,7 +468,6 @@ pnfs_bucket_alloc_ds_commits(struct list_head *list, - goto out_error; - data->ds_commit_index = i; - list_add_tail(&data->list, list); -- atomic_inc(&cinfo->mds->rpcs_out); - nreq++; - } - mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex); -@@ -520,7 +519,6 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages, - data->ds_commit_index = -1; - list_splice_init(mds_pages, &data->pages); - list_add_tail(&data->list, &list); -- atomic_inc(&cinfo->mds->rpcs_out); - nreq++; - } - -@@ -895,7 +893,7 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv, - } - - smp_wmb(); -- ds->ds_clp = clp; -+ WRITE_ONCE(ds->ds_clp, clp); - dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); - out: - return status; -@@ -973,7 +971,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv, - } - - smp_wmb(); -- ds->ds_clp = clp; -+ WRITE_ONCE(ds->ds_clp, clp); - dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); - out: - return status; -diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c -index ea19dbf123014..ecc4e717808c4 100644 ---- a/fs/nfs/proc.c -+++ b/fs/nfs/proc.c -@@ -91,7 +91,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, - info->dtpref = fsinfo.tsize; - info->maxfilesize = 0x7FFFFFFF; - info->lease_time = 0; -- info->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA; -+ info->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED; - return 0; - } - -diff --git a/fs/nfs/write.c b/fs/nfs/write.c -index eae9bf1140417..7dce3e735fc53 100644 ---- a/fs/nfs/write.c -+++ b/fs/nfs/write.c -@@ -1038,25 +1038,11 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst, - struct nfs_page *req, *tmp; - int ret = 0; - --restart: - list_for_each_entry_safe(req, tmp, src, wb_list) { - kref_get(&req->wb_kref); - if (!nfs_lock_request(req)) { -- int status; -- -- /* Prevent deadlock with nfs_lock_and_join_requests */ -- if (!list_empty(dst)) { -- nfs_release_request(req); -- continue; -- } -- /* Ensure we make progress to prevent livelock */ -- mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex); -- status = nfs_wait_on_request(req); - nfs_release_request(req); -- mutex_lock(&NFS_I(cinfo->inode)->commit_mutex); -- if (status < 0) -- break; -- goto restart; -+ continue; - } - nfs_request_remove_commit_list(req, cinfo); - clear_bit(PG_COMMIT_TO_DS, &req->wb_flags); -@@ -1671,10 +1657,13 @@ static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) - atomic_inc(&cinfo->rpcs_out); - } - --static void nfs_commit_end(struct nfs_mds_commit_info *cinfo) -+bool nfs_commit_end(struct nfs_mds_commit_info *cinfo) - { -- if (atomic_dec_and_test(&cinfo->rpcs_out)) -+ if (atomic_dec_and_test(&cinfo->rpcs_out)) { - wake_up_var(&cinfo->rpcs_out); -+ return true; -+ } -+ return false; - } - - void nfs_commitdata_release(struct nfs_commit_data *data) -@@ -1774,6 +1763,7 @@ void nfs_init_commit(struct nfs_commit_data *data, - data->res.fattr = &data->fattr; - data->res.verf = &data->verf; - nfs_fattr_init(&data->fattr); -+ nfs_commit_begin(cinfo->mds); - } - EXPORT_SYMBOL_GPL(nfs_init_commit); - -@@ -1820,7 +1810,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how, - - /* Set up the argument struct */ - nfs_init_commit(data, head, NULL, cinfo); -- atomic_inc(&cinfo->mds->rpcs_out); - if (NFS_SERVER(inode)->nfs_client->cl_minorversion) - task_flags = RPC_TASK_MOVEABLE; - return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode), -@@ -1936,6 +1925,7 @@ static int __nfs_commit_inode(struct inode *inode, int how, - int may_wait = how & FLUSH_SYNC; - int ret, nscan; - -+ how &= ~FLUSH_SYNC; - nfs_init_cinfo_from_inode(&cinfo, inode); - nfs_commit_begin(cinfo.mds); - for (;;) { -diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c -index 6fedc49726bf7..c634483d85d2a 100644 ---- a/fs/nfsd/nfs4recover.c -+++ b/fs/nfsd/nfs4recover.c -@@ -2156,6 +2156,7 @@ static struct notifier_block nfsd4_cld_block = { - int - register_cld_notifier(void) - { -+ WARN_ON(!nfsd_net_id); - return rpc_pipefs_notifier_register(&nfsd4_cld_block); - } - -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index 3f4027a5de883..61301affb4c1b 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -1207,6 +1207,11 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) - return 0; - } - -+static bool delegation_hashed(struct nfs4_delegation *dp) -+{ -+ return !(list_empty(&dp->dl_perfile)); -+} -+ - static bool - unhash_delegation_locked(struct nfs4_delegation *dp) - { -@@ -1214,7 +1219,7 @@ unhash_delegation_locked(struct nfs4_delegation *dp) - - lockdep_assert_held(&state_lock); - -- if (list_empty(&dp->dl_perfile)) -+ if (!delegation_hashed(dp)) - return false; - - dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID; -@@ -4598,7 +4603,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) - * queued for a lease break. Don't queue it again. - */ - spin_lock(&state_lock); -- if (dp->dl_time == 0) { -+ if (delegation_hashed(dp) && dp->dl_time == 0) { - dp->dl_time = ktime_get_boottime_seconds(); - list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru); - } -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index cf030ebe28275..266d5152c3216 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -288,11 +288,8 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen) - p = xdr_inline_decode(argp->xdr, count << 2); - if (!p) - return nfserr_bad_xdr; -- i = 0; -- while (i < count) -- bmval[i++] = be32_to_cpup(p++); -- while (i < bmlen) -- bmval[i++] = 0; -+ for (i = 0; i < bmlen; i++) -+ bmval[i] = (i < count) ? be32_to_cpup(p++) : 0; - - return nfs_ok; - } -diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c -index 070e5dd03e26f..5ed04d6be9a59 100644 ---- a/fs/nfsd/nfsctl.c -+++ b/fs/nfsd/nfsctl.c -@@ -1521,12 +1521,9 @@ static int __init init_nfsd(void) - int retval; - printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); - -- retval = register_cld_notifier(); -- if (retval) -- return retval; - retval = nfsd4_init_slabs(); - if (retval) -- goto out_unregister_notifier; -+ return retval; - retval = nfsd4_init_pnfs(); - if (retval) - goto out_free_slabs; -@@ -1545,9 +1542,14 @@ static int __init init_nfsd(void) - goto out_free_exports; - retval = register_pernet_subsys(&nfsd_net_ops); - if (retval < 0) -+ goto out_free_filesystem; -+ retval = register_cld_notifier(); -+ if (retval) - goto out_free_all; - return 0; - out_free_all: -+ unregister_pernet_subsys(&nfsd_net_ops); -+out_free_filesystem: - unregister_filesystem(&nfsd_fs_type); - out_free_exports: - remove_proc_entry("fs/nfs/exports", NULL); -@@ -1561,13 +1563,12 @@ out_free_pnfs: - nfsd4_exit_pnfs(); - out_free_slabs: - nfsd4_free_slabs(); --out_unregister_notifier: -- unregister_cld_notifier(); - return retval; - } - - static void __exit exit_nfsd(void) - { -+ unregister_cld_notifier(); - unregister_pernet_subsys(&nfsd_net_ops); - nfsd_drc_slab_free(); - remove_proc_entry("fs/nfs/exports", NULL); -@@ -1577,7 +1578,6 @@ static void __exit exit_nfsd(void) - nfsd4_free_slabs(); - nfsd4_exit_pnfs(); - unregister_filesystem(&nfsd_fs_type); -- unregister_cld_notifier(); - } - - MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); -diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c -index 54d7843c02114..fc5f780fa2355 100644 ---- a/fs/ocfs2/file.c -+++ b/fs/ocfs2/file.c -@@ -476,10 +476,11 @@ int ocfs2_truncate_file(struct inode *inode, - * greater than page size, so we have to truncate them - * anyway. - */ -- unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); -- truncate_inode_pages(inode->i_mapping, new_i_size); - - if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { -+ unmap_mapping_range(inode->i_mapping, -+ new_i_size + PAGE_SIZE - 1, 0, 1); -+ truncate_inode_pages(inode->i_mapping, new_i_size); - status = ocfs2_truncate_inline(inode, di_bh, new_i_size, - i_size_read(inode), 1); - if (status) -@@ -498,6 +499,9 @@ int ocfs2_truncate_file(struct inode *inode, - goto bail_unlock_sem; - } - -+ unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); -+ truncate_inode_pages(inode->i_mapping, new_i_size); -+ - status = ocfs2_commit_truncate(osb, inode, di_bh); - if (status < 0) { - mlog_errno(status); -diff --git a/fs/open.c b/fs/open.c -index daa324606a41f..e0df1536eb69f 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -856,8 +856,20 @@ static int do_dentry_open(struct file *f, - * of THPs into the page cache will fail. - */ - smp_mb(); -- if (filemap_nr_thps(inode->i_mapping)) -- truncate_pagecache(inode, 0); -+ if (filemap_nr_thps(inode->i_mapping)) { -+ struct address_space *mapping = inode->i_mapping; -+ -+ filemap_invalidate_lock(inode->i_mapping); -+ /* -+ * unmap_mapping_range just need to be called once -+ * here, because the private pages is not need to be -+ * unmapped mapping (e.g. data segment of dynamic -+ * shared libraries here). -+ */ -+ unmap_mapping_range(mapping, 0, 0, 0); -+ truncate_inode_pages(mapping, 0); -+ filemap_invalidate_unlock(inode->i_mapping); -+ } - } - - return 0; -diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c -index fe484cf93e5cd..8bbe9486e3a62 100644 ---- a/fs/orangefs/dcache.c -+++ b/fs/orangefs/dcache.c -@@ -26,8 +26,10 @@ static int orangefs_revalidate_lookup(struct dentry *dentry) - gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__); - - new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP); -- if (!new_op) -+ if (!new_op) { -+ ret = -ENOMEM; - goto out_put_parent; -+ } - - new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW; - new_op->upcall.req.lookup.parent_refn = parent->refn; -diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c -index 4e7d5bfa2949f..b193d08a3dc36 100644 ---- a/fs/overlayfs/copy_up.c -+++ b/fs/overlayfs/copy_up.c -@@ -140,12 +140,14 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old, - int err; - - err = ovl_real_fileattr_get(old, &oldfa); -- if (err) -- return err; -- -- err = ovl_real_fileattr_get(new, &newfa); -- if (err) -+ if (err) { -+ /* Ntfs-3g returns -EINVAL for "no fileattr support" */ -+ if (err == -ENOTTY || err == -EINVAL) -+ return 0; -+ pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n", -+ old, err); - return err; -+ } - - /* - * We cannot set immutable and append-only flags on upper inode, -@@ -159,6 +161,17 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old, - return err; - } - -+ /* Don't bother copying flags if none are set */ -+ if (!(oldfa.flags & OVL_COPY_FS_FLAGS_MASK)) -+ return 0; -+ -+ err = ovl_real_fileattr_get(new, &newfa); -+ if (err) { -+ pr_warn("failed to retrieve upper fileattr (%pd2, err=%i)\n", -+ new, err); -+ return err; -+ } -+ - BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL); - newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK; - newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK); -diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c -index 93c7c267de934..f18490813170a 100644 ---- a/fs/overlayfs/dir.c -+++ b/fs/overlayfs/dir.c -@@ -137,8 +137,7 @@ kill_whiteout: - goto out; - } - --static int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, -- umode_t mode) -+int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) - { - int err; - struct dentry *d, *dentry = *newdentry; -diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c -index c88ac571593dc..44fea16751f1d 100644 ---- a/fs/overlayfs/file.c -+++ b/fs/overlayfs/file.c -@@ -17,6 +17,7 @@ - - struct ovl_aio_req { - struct kiocb iocb; -+ refcount_t ref; - struct kiocb *orig_iocb; - struct fd fd; - }; -@@ -252,6 +253,14 @@ static rwf_t ovl_iocb_to_rwf(int ifl) - return flags; - } - -+static inline void ovl_aio_put(struct ovl_aio_req *aio_req) -+{ -+ if (refcount_dec_and_test(&aio_req->ref)) { -+ fdput(aio_req->fd); -+ kmem_cache_free(ovl_aio_request_cachep, aio_req); -+ } -+} -+ - static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) - { - struct kiocb *iocb = &aio_req->iocb; -@@ -268,8 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) - } - - orig_iocb->ki_pos = iocb->ki_pos; -- fdput(aio_req->fd); -- kmem_cache_free(ovl_aio_request_cachep, aio_req); -+ ovl_aio_put(aio_req); - } - - static void ovl_aio_rw_complete(struct kiocb *iocb, long res, long res2) -@@ -319,7 +327,9 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) - aio_req->orig_iocb = iocb; - kiocb_clone(&aio_req->iocb, iocb, real.file); - aio_req->iocb.ki_complete = ovl_aio_rw_complete; -+ refcount_set(&aio_req->ref, 2); - ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter); -+ ovl_aio_put(aio_req); - if (ret != -EIOCBQUEUED) - ovl_aio_cleanup_handler(aio_req); - } -@@ -390,7 +400,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) - kiocb_clone(&aio_req->iocb, iocb, real.file); - aio_req->iocb.ki_flags = ifl; - aio_req->iocb.ki_complete = ovl_aio_rw_complete; -+ refcount_set(&aio_req->ref, 2); - ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter); -+ ovl_aio_put(aio_req); - if (ret != -EIOCBQUEUED) - ovl_aio_cleanup_handler(aio_req); - } -diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c -index 832b17589733a..1f36158c7dbe2 100644 ---- a/fs/overlayfs/inode.c -+++ b/fs/overlayfs/inode.c -@@ -610,7 +610,10 @@ int ovl_real_fileattr_get(struct path *realpath, struct fileattr *fa) - if (err) - return err; - -- return vfs_fileattr_get(realpath->dentry, fa); -+ err = vfs_fileattr_get(realpath->dentry, fa); -+ if (err == -ENOIOCTLCMD) -+ err = -ENOTTY; -+ return err; - } - - int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa) -diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h -index 3894f33479552..2cd5741c873b6 100644 ---- a/fs/overlayfs/overlayfs.h -+++ b/fs/overlayfs/overlayfs.h -@@ -570,6 +570,7 @@ struct ovl_cattr { - - #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) }) - -+int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode); - struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, - struct ovl_cattr *attr); - int ovl_cleanup(struct inode *dir, struct dentry *dentry); -diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c -index 178daa5e82c9d..265181c110ae2 100644 ---- a/fs/overlayfs/super.c -+++ b/fs/overlayfs/super.c -@@ -787,10 +787,14 @@ retry: - goto retry; - } - -- work = ovl_create_real(dir, work, OVL_CATTR(attr.ia_mode)); -- err = PTR_ERR(work); -- if (IS_ERR(work)) -- goto out_err; -+ err = ovl_mkdir_real(dir, &work, attr.ia_mode); -+ if (err) -+ goto out_dput; -+ -+ /* Weird filesystem returning with hashed negative (kernfs)? */ -+ err = -EINVAL; -+ if (d_really_is_negative(work)) -+ goto out_dput; - - /* - * Try to remove POSIX ACL xattrs from workdir. We are good if: -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 533d5836eb9a4..1f394095eb880 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -67,6 +67,7 @@ - #include <linux/mm.h> - #include <linux/swap.h> - #include <linux/rcupdate.h> -+#include <linux/kallsyms.h> - #include <linux/stacktrace.h> - #include <linux/resource.h> - #include <linux/module.h> -@@ -386,17 +387,19 @@ static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns, - struct pid *pid, struct task_struct *task) - { - unsigned long wchan; -+ char symname[KSYM_NAME_LEN]; - -- if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) -- wchan = get_wchan(task); -- else -- wchan = 0; -+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) -+ goto print0; - -- if (wchan) -- seq_printf(m, "%ps", (void *) wchan); -- else -- seq_putc(m, '0'); -+ wchan = get_wchan(task); -+ if (wchan && !lookup_symbol_name(wchan, symname)) { -+ seq_puts(m, symname); -+ return 0; -+ } - -+print0: -+ seq_putc(m, '0'); - return 0; - } - #endif /* CONFIG_KALLSYMS */ -diff --git a/fs/proc/stat.c b/fs/proc/stat.c -index 6561a06ef9059..4fb8729a68d4e 100644 ---- a/fs/proc/stat.c -+++ b/fs/proc/stat.c -@@ -24,7 +24,7 @@ - - #ifdef arch_idle_time - --static u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) -+u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) - { - u64 idle; - -@@ -46,7 +46,7 @@ static u64 get_iowait_time(struct kernel_cpustat *kcs, int cpu) - - #else - --static u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) -+u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) - { - u64 idle, idle_usecs = -1ULL; - -diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c -index 5a1b228964fb7..deb99bc9b7e6b 100644 ---- a/fs/proc/uptime.c -+++ b/fs/proc/uptime.c -@@ -12,18 +12,22 @@ static int uptime_proc_show(struct seq_file *m, void *v) - { - struct timespec64 uptime; - struct timespec64 idle; -- u64 nsec; -+ u64 idle_nsec; - u32 rem; - int i; - -- nsec = 0; -- for_each_possible_cpu(i) -- nsec += (__force u64) kcpustat_cpu(i).cpustat[CPUTIME_IDLE]; -+ idle_nsec = 0; -+ for_each_possible_cpu(i) { -+ struct kernel_cpustat kcs; -+ -+ kcpustat_cpu_fetch(&kcs, i); -+ idle_nsec += get_idle_time(&kcs, i); -+ } - - ktime_get_boottime_ts64(&uptime); - timens_add_boottime(&uptime); - -- idle.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem); -+ idle.tv_sec = div_u64_rem(idle_nsec, NSEC_PER_SEC, &rem); - idle.tv_nsec = rem; - seq_printf(m, "%lu.%02lu %lu.%02lu\n", - (unsigned long) uptime.tv_sec, -diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c -index 9a15334da2086..e5730986758fa 100644 ---- a/fs/proc/vmcore.c -+++ b/fs/proc/vmcore.c -@@ -124,9 +124,13 @@ ssize_t read_from_oldmem(char *buf, size_t count, - nr_bytes = count; - - /* If pfn is not ram, return zeros for sparse dump files */ -- if (pfn_is_ram(pfn) == 0) -- memset(buf, 0, nr_bytes); -- else { -+ if (pfn_is_ram(pfn) == 0) { -+ tmp = 0; -+ if (!userbuf) -+ memset(buf, 0, nr_bytes); -+ else if (clear_user(buf, nr_bytes)) -+ tmp = -EFAULT; -+ } else { - if (encrypted) - tmp = copy_oldmem_page_encrypted(pfn, buf, - nr_bytes, -@@ -135,10 +139,10 @@ ssize_t read_from_oldmem(char *buf, size_t count, - else - tmp = copy_oldmem_page(pfn, buf, nr_bytes, - offset, userbuf); -- -- if (tmp < 0) -- return tmp; - } -+ if (tmp < 0) -+ return tmp; -+ - *ppos += nr_bytes; - count -= nr_bytes; - buf += nr_bytes; -diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig -index 328da35da3908..8adabde685f13 100644 ---- a/fs/pstore/Kconfig -+++ b/fs/pstore/Kconfig -@@ -173,7 +173,6 @@ config PSTORE_BLK - tristate "Log panic/oops to a block device" - depends on PSTORE - depends on BLOCK -- depends on BROKEN - select PSTORE_ZONE - default n - help -diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c -index 04ce58c939a0b..6093088de49fd 100644 ---- a/fs/pstore/blk.c -+++ b/fs/pstore/blk.c -@@ -311,7 +311,7 @@ static int __init __best_effort_init(void) - if (ret) - kfree(best_effort_dev); - else -- pr_info("attached %s (%zu) (no dedicated panic_write!)\n", -+ pr_info("attached %s (%lu) (no dedicated panic_write!)\n", - blkdev, best_effort_dev->zone.total_size); - - return ret; -diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c -index d3e995e1046fb..5f2405994280a 100644 ---- a/fs/quota/quota_tree.c -+++ b/fs/quota/quota_tree.c -@@ -414,6 +414,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, - quota_error(dquot->dq_sb, "Quota structure has offset to " - "other block (%u) than it should (%u)", blk, - (uint)(dquot->dq_off >> info->dqi_blocksize_bits)); -+ ret = -EIO; - goto out_buf; - } - ret = read_blk(info, blk, buf); -@@ -479,6 +480,13 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, - goto out_buf; - } - newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); -+ if (newblk < QT_TREEOFF || newblk >= info->dqi_blocks) { -+ quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)", -+ newblk, info->dqi_blocks); -+ ret = -EUCLEAN; -+ goto out_buf; -+ } -+ - if (depth == info->dqi_qtree_depth - 1) { - ret = free_dqentry(info, dquot, newblk); - newblk = 0; -@@ -578,6 +586,13 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, - blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); - if (!blk) /* No reference? */ - goto out_buf; -+ if (blk < QT_TREEOFF || blk >= info->dqi_blocks) { -+ quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)", -+ blk, info->dqi_blocks); -+ ret = -EUCLEAN; -+ goto out_buf; -+ } -+ - if (depth < info->dqi_qtree_depth - 1) - ret = find_tree_dqentry(info, dquot, blk, depth+1); - else -diff --git a/fs/signalfd.c b/fs/signalfd.c -index 040e1cf905282..65ce0e72e7b95 100644 ---- a/fs/signalfd.c -+++ b/fs/signalfd.c -@@ -35,17 +35,7 @@ - - void signalfd_cleanup(struct sighand_struct *sighand) - { -- wait_queue_head_t *wqh = &sighand->signalfd_wqh; -- /* -- * The lockless check can race with remove_wait_queue() in progress, -- * but in this case its caller should run under rcu_read_lock() and -- * sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return. -- */ -- if (likely(!waitqueue_active(wqh))) -- return; -- -- /* wait_queue_entry_t->func(POLLFREE) should do remove_wait_queue() */ -- wake_up_poll(wqh, EPOLLHUP | POLLFREE); -+ wake_up_pollfree(&sighand->signalfd_wqh); - } - - struct signalfd_ctx { -diff --git a/fs/smbfs_common/cifs_arc4.c b/fs/smbfs_common/cifs_arc4.c -index 85ba15a60b13b..043e4cb839fa2 100644 ---- a/fs/smbfs_common/cifs_arc4.c -+++ b/fs/smbfs_common/cifs_arc4.c -@@ -72,16 +72,3 @@ void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int l - ctx->y = y; - } - EXPORT_SYMBOL_GPL(cifs_arc4_crypt); -- --static int __init --init_smbfs_common(void) --{ -- return 0; --} --static void __init --exit_smbfs_common(void) --{ --} -- --module_init(init_smbfs_common) --module_exit(exit_smbfs_common) -diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c -index 1261e8b41edb4..3616839c5c4b6 100644 ---- a/fs/tracefs/inode.c -+++ b/fs/tracefs/inode.c -@@ -161,6 +161,77 @@ struct tracefs_fs_info { - struct tracefs_mount_opts mount_opts; - }; - -+static void change_gid(struct dentry *dentry, kgid_t gid) -+{ -+ if (!dentry->d_inode) -+ return; -+ dentry->d_inode->i_gid = gid; -+} -+ -+/* -+ * Taken from d_walk, but without he need for handling renames. -+ * Nothing can be renamed while walking the list, as tracefs -+ * does not support renames. This is only called when mounting -+ * or remounting the file system, to set all the files to -+ * the given gid. -+ */ -+static void set_gid(struct dentry *parent, kgid_t gid) -+{ -+ struct dentry *this_parent; -+ struct list_head *next; -+ -+ this_parent = parent; -+ spin_lock(&this_parent->d_lock); -+ -+ change_gid(this_parent, gid); -+repeat: -+ next = this_parent->d_subdirs.next; -+resume: -+ while (next != &this_parent->d_subdirs) { -+ struct list_head *tmp = next; -+ struct dentry *dentry = list_entry(tmp, struct dentry, d_child); -+ next = tmp->next; -+ -+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); -+ -+ change_gid(dentry, gid); -+ -+ if (!list_empty(&dentry->d_subdirs)) { -+ spin_unlock(&this_parent->d_lock); -+ spin_release(&dentry->d_lock.dep_map, _RET_IP_); -+ this_parent = dentry; -+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_); -+ goto repeat; -+ } -+ spin_unlock(&dentry->d_lock); -+ } -+ /* -+ * All done at this level ... ascend and resume the search. -+ */ -+ rcu_read_lock(); -+ascend: -+ if (this_parent != parent) { -+ struct dentry *child = this_parent; -+ this_parent = child->d_parent; -+ -+ spin_unlock(&child->d_lock); -+ spin_lock(&this_parent->d_lock); -+ -+ /* go into the first sibling still alive */ -+ do { -+ next = child->d_child.next; -+ if (next == &this_parent->d_subdirs) -+ goto ascend; -+ child = list_entry(next, struct dentry, d_child); -+ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); -+ rcu_read_unlock(); -+ goto resume; -+ } -+ rcu_read_unlock(); -+ spin_unlock(&this_parent->d_lock); -+ return; -+} -+ - static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) - { - substring_t args[MAX_OPT_ARGS]; -@@ -193,6 +264,7 @@ static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) - if (!gid_valid(gid)) - return -EINVAL; - opts->gid = gid; -+ set_gid(tracefs_mount->mnt_root, gid); - break; - case Opt_mode: - if (match_octal(&args[0], &option)) -@@ -414,6 +486,8 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode, - inode->i_mode = mode; - inode->i_fop = fops ? fops : &tracefs_file_operations; - inode->i_private = data; -+ inode->i_uid = d_inode(dentry->d_parent)->i_uid; -+ inode->i_gid = d_inode(dentry->d_parent)->i_gid; - d_instantiate(dentry, inode); - fsnotify_create(dentry->d_parent->d_inode, dentry); - return end_creating(dentry); -@@ -432,9 +506,12 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent, - if (unlikely(!inode)) - return failed_creating(dentry); - -- inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; -+ /* Do not set bits for OTH */ -+ inode->i_mode = S_IFDIR | S_IRWXU | S_IRUSR| S_IRGRP | S_IXUSR | S_IXGRP; - inode->i_op = ops; - inode->i_fop = &simple_dir_operations; -+ inode->i_uid = d_inode(dentry->d_parent)->i_uid; -+ inode->i_gid = d_inode(dentry->d_parent)->i_gid; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); -diff --git a/fs/udf/dir.c b/fs/udf/dir.c -index 70abdfad2df17..42e3e551fa4c3 100644 ---- a/fs/udf/dir.c -+++ b/fs/udf/dir.c -@@ -31,6 +31,7 @@ - #include <linux/mm.h> - #include <linux/slab.h> - #include <linux/bio.h> -+#include <linux/iversion.h> - - #include "udf_i.h" - #include "udf_sb.h" -@@ -43,7 +44,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) - struct fileIdentDesc *fi = NULL; - struct fileIdentDesc cfi; - udf_pblk_t block, iblock; -- loff_t nf_pos; -+ loff_t nf_pos, emit_pos = 0; - int flen; - unsigned char *fname = NULL, *copy_name = NULL; - unsigned char *nameptr; -@@ -57,6 +58,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) - int i, num, ret = 0; - struct extent_position epos = { NULL, 0, {0, 0} }; - struct super_block *sb = dir->i_sb; -+ bool pos_valid = false; - - if (ctx->pos == 0) { - if (!dir_emit_dot(file, ctx)) -@@ -67,6 +69,21 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) - if (nf_pos >= size) - goto out; - -+ /* -+ * Something changed since last readdir (either lseek was called or dir -+ * changed)? We need to verify the position correctly points at the -+ * beginning of some dir entry so that the directory parsing code does -+ * not get confused. Since UDF does not have any reliable way of -+ * identifying beginning of dir entry (names are under user control), -+ * we need to scan the directory from the beginning. -+ */ -+ if (!inode_eq_iversion(dir, file->f_version)) { -+ emit_pos = nf_pos; -+ nf_pos = 0; -+ } else { -+ pos_valid = true; -+ } -+ - fname = kmalloc(UDF_NAME_LEN, GFP_NOFS); - if (!fname) { - ret = -ENOMEM; -@@ -122,13 +139,21 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) - - while (nf_pos < size) { - struct kernel_lb_addr tloc; -+ loff_t cur_pos = nf_pos; - -- ctx->pos = (nf_pos >> 2) + 1; -+ /* Update file position only if we got past the current one */ -+ if (nf_pos >= emit_pos) { -+ ctx->pos = (nf_pos >> 2) + 1; -+ pos_valid = true; -+ } - - fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, - &elen, &offset); - if (!fi) - goto out; -+ /* Still not at offset where user asked us to read from? */ -+ if (cur_pos < emit_pos) -+ continue; - - liu = le16_to_cpu(cfi.lengthOfImpUse); - lfi = cfi.lengthFileIdent; -@@ -186,8 +211,11 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) - } /* end while */ - - ctx->pos = (nf_pos >> 2) + 1; -+ pos_valid = true; - - out: -+ if (pos_valid) -+ file->f_version = inode_query_iversion(dir); - if (fibh.sbh != fibh.ebh) - brelse(fibh.ebh); - brelse(fibh.sbh); -diff --git a/fs/udf/namei.c b/fs/udf/namei.c -index caeef08efed23..0ed4861b038f6 100644 ---- a/fs/udf/namei.c -+++ b/fs/udf/namei.c -@@ -30,6 +30,7 @@ - #include <linux/sched.h> - #include <linux/crc-itu-t.h> - #include <linux/exportfs.h> -+#include <linux/iversion.h> - - static inline int udf_match(int len1, const unsigned char *name1, int len2, - const unsigned char *name2) -@@ -134,6 +135,8 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, - mark_buffer_dirty_inode(fibh->ebh, inode); - mark_buffer_dirty_inode(fibh->sbh, inode); - } -+ inode_inc_iversion(inode); -+ - return 0; - } - -diff --git a/fs/udf/super.c b/fs/udf/super.c -index b2d7c57d06881..aa2f6093d3f6f 100644 ---- a/fs/udf/super.c -+++ b/fs/udf/super.c -@@ -57,6 +57,7 @@ - #include <linux/crc-itu-t.h> - #include <linux/log2.h> - #include <asm/byteorder.h> -+#include <linux/iversion.h> - - #include "udf_sb.h" - #include "udf_i.h" -@@ -149,6 +150,7 @@ static struct inode *udf_alloc_inode(struct super_block *sb) - init_rwsem(&ei->i_data_sem); - ei->cached_extent.lstart = -1; - spin_lock_init(&ei->i_extent_cache_lock); -+ inode_set_iversion(&ei->vfs_inode, 1); - - return &ei->vfs_inode; - } -diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c -index ddc346a9df9ba..807f33553a8eb 100644 ---- a/fs/zonefs/super.c -+++ b/fs/zonefs/super.c -@@ -1787,5 +1787,6 @@ static void __exit zonefs_exit(void) - MODULE_AUTHOR("Damien Le Moal"); - MODULE_DESCRIPTION("Zone file system for zoned block devices"); - MODULE_LICENSE("GPL"); -+MODULE_ALIAS_FS("zonefs"); - module_init(zonefs_init); - module_exit(zonefs_exit); -diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h -index f681bbdbc6982..36f7eb9d06639 100644 ---- a/include/drm/ttm/ttm_bo_api.h -+++ b/include/drm/ttm/ttm_bo_api.h -@@ -594,8 +594,7 @@ vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, - - vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, - pgprot_t prot, -- pgoff_t num_prefault, -- pgoff_t fault_page_size); -+ pgoff_t num_prefault); - - vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf); - -diff --git a/include/linux/acpi.h b/include/linux/acpi.h -index 974d497a897dc..6224b1e32681c 100644 ---- a/include/linux/acpi.h -+++ b/include/linux/acpi.h -@@ -976,6 +976,15 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr) - return -ENODEV; - } - -+static inline int acpi_register_wakeup_handler(int wake_irq, -+ bool (*wakeup)(void *context), void *context) -+{ -+ return -ENXIO; -+} -+ -+static inline void acpi_unregister_wakeup_handler( -+ bool (*wakeup)(void *context), void *context) { } -+ - #endif /* !CONFIG_ACPI */ - - #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index 12b9dbcc980ee..0a9fdcbbab83d 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -235,6 +235,14 @@ struct request { - void *end_io_data; - }; - -+static inline int blk_validate_block_size(unsigned int bsize) -+{ -+ if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) -+ return -EINVAL; -+ -+ return 0; -+} -+ - static inline bool blk_op_is_passthrough(unsigned int op) - { - op &= REQ_OP_MASK; -@@ -1198,8 +1206,6 @@ struct blk_plug { - bool multiple_queues; - bool nowait; - }; --#define BLK_MAX_REQUEST_COUNT 16 --#define BLK_PLUG_FLUSH_SIZE (128 * 1024) - - struct blk_plug_cb; - typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *, bool); -diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h -index 2746fd8042162..3536ab432b30c 100644 ---- a/include/linux/bpf-cgroup.h -+++ b/include/linux/bpf-cgroup.h -@@ -517,6 +517,7 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map, - - #define cgroup_bpf_enabled(atype) (0) - #define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) ({ 0; }) -+#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) ({ 0; }) - #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0) - #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) - #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; }) -diff --git a/include/linux/bpf.h b/include/linux/bpf.h -index 3db6f6c95489e..6c4640526f741 100644 ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -190,7 +190,7 @@ struct bpf_map { - atomic64_t usercnt; - struct work_struct work; - struct mutex freeze_mutex; -- u64 writecnt; /* writable mmap cnt; protected by freeze_mutex */ -+ atomic64_t writecnt; - }; - - static inline bool map_value_has_spin_lock(const struct bpf_map *map) -@@ -723,6 +723,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr) - struct bpf_trampoline *bpf_trampoline_get(u64 key, - struct bpf_attach_target_info *tgt_info); - void bpf_trampoline_put(struct bpf_trampoline *tr); -+int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs); - #define BPF_DISPATCHER_INIT(_name) { \ - .mutex = __MUTEX_INITIALIZER(_name.mutex), \ - .func = &_name##_func, \ -@@ -1320,28 +1321,16 @@ extern struct mutex bpf_stats_enabled_mutex; - * kprobes, tracepoints) to prevent deadlocks on map operations as any of - * these events can happen inside a region which holds a map bucket lock - * and can deadlock on it. -- * -- * Use the preemption safe inc/dec variants on RT because migrate disable -- * is preemptible on RT and preemption in the middle of the RMW operation -- * might lead to inconsistent state. Use the raw variants for non RT -- * kernels as migrate_disable() maps to preempt_disable() so the slightly -- * more expensive save operation can be avoided. - */ - static inline void bpf_disable_instrumentation(void) - { - migrate_disable(); -- if (IS_ENABLED(CONFIG_PREEMPT_RT)) -- this_cpu_inc(bpf_prog_active); -- else -- __this_cpu_inc(bpf_prog_active); -+ this_cpu_inc(bpf_prog_active); - } - - static inline void bpf_enable_instrumentation(void) - { -- if (IS_ENABLED(CONFIG_PREEMPT_RT)) -- this_cpu_dec(bpf_prog_active); -- else -- __this_cpu_dec(bpf_prog_active); -+ this_cpu_dec(bpf_prog_active); - migrate_enable(); - } - -@@ -1387,6 +1376,7 @@ void bpf_map_put(struct bpf_map *map); - void *bpf_map_area_alloc(u64 size, int numa_node); - void *bpf_map_area_mmapable_alloc(u64 size, int numa_node); - void bpf_map_area_free(void *base); -+bool bpf_map_write_active(const struct bpf_map *map); - void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr); - int generic_map_lookup_batch(struct bpf_map *map, - const union bpf_attr *attr, -diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h -new file mode 100644 -index 0000000000000..a075b70b9a70c ---- /dev/null -+++ b/include/linux/cc_platform.h -@@ -0,0 +1,88 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Confidential Computing Platform Capability checks -+ * -+ * Copyright (C) 2021 Advanced Micro Devices, Inc. -+ * -+ * Author: Tom Lendacky <thomas.lendacky@amd.com> -+ */ -+ -+#ifndef _LINUX_CC_PLATFORM_H -+#define _LINUX_CC_PLATFORM_H -+ -+#include <linux/types.h> -+#include <linux/stddef.h> -+ -+/** -+ * enum cc_attr - Confidential computing attributes -+ * -+ * These attributes represent confidential computing features that are -+ * currently active. -+ */ -+enum cc_attr { -+ /** -+ * @CC_ATTR_MEM_ENCRYPT: Memory encryption is active -+ * -+ * The platform/OS is running with active memory encryption. This -+ * includes running either as a bare-metal system or a hypervisor -+ * and actively using memory encryption or as a guest/virtual machine -+ * and actively using memory encryption. -+ * -+ * Examples include SME, SEV and SEV-ES. -+ */ -+ CC_ATTR_MEM_ENCRYPT, -+ -+ /** -+ * @CC_ATTR_HOST_MEM_ENCRYPT: Host memory encryption is active -+ * -+ * The platform/OS is running as a bare-metal system or a hypervisor -+ * and actively using memory encryption. -+ * -+ * Examples include SME. -+ */ -+ CC_ATTR_HOST_MEM_ENCRYPT, -+ -+ /** -+ * @CC_ATTR_GUEST_MEM_ENCRYPT: Guest memory encryption is active -+ * -+ * The platform/OS is running as a guest/virtual machine and actively -+ * using memory encryption. -+ * -+ * Examples include SEV and SEV-ES. -+ */ -+ CC_ATTR_GUEST_MEM_ENCRYPT, -+ -+ /** -+ * @CC_ATTR_GUEST_STATE_ENCRYPT: Guest state encryption is active -+ * -+ * The platform/OS is running as a guest/virtual machine and actively -+ * using memory encryption and register state encryption. -+ * -+ * Examples include SEV-ES. -+ */ -+ CC_ATTR_GUEST_STATE_ENCRYPT, -+}; -+ -+#ifdef CONFIG_ARCH_HAS_CC_PLATFORM -+ -+/** -+ * cc_platform_has() - Checks if the specified cc_attr attribute is active -+ * @attr: Confidential computing attribute to check -+ * -+ * The cc_platform_has() function will return an indicator as to whether the -+ * specified Confidential Computing attribute is currently active. -+ * -+ * Context: Any context -+ * Return: -+ * * TRUE - Specified Confidential Computing attribute is active -+ * * FALSE - Specified Confidential Computing attribute is not active -+ */ -+bool cc_platform_has(enum cc_attr attr); -+ -+#else /* !CONFIG_ARCH_HAS_CC_PLATFORM */ -+ -+static inline bool cc_platform_has(enum cc_attr attr) { return false; } -+ -+#endif /* CONFIG_ARCH_HAS_CC_PLATFORM */ -+ -+#endif /* _LINUX_CC_PLATFORM_H */ -diff --git a/include/linux/console.h b/include/linux/console.h -index 20874db50bc8a..a97f277cfdfa3 100644 ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -149,6 +149,8 @@ struct console { - short flags; - short index; - int cflag; -+ uint ispeed; -+ uint ospeed; - void *data; - struct console *next; - }; -diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h -index ff88bb3e44fca..66a1f495f01a6 100644 ---- a/include/linux/cpufreq.h -+++ b/include/linux/cpufreq.h -@@ -1041,7 +1041,7 @@ static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_ - if (cpu == pcpu) - continue; - -- ret = parse_perf_domain(pcpu, list_name, cell_name); -+ ret = parse_perf_domain(cpu, list_name, cell_name); - if (ret < 0) - continue; - -diff --git a/include/linux/delay.h b/include/linux/delay.h -index 1d0e2ce6b6d9f..e8607992c68a5 100644 ---- a/include/linux/delay.h -+++ b/include/linux/delay.h -@@ -20,6 +20,7 @@ - */ - - #include <linux/kernel.h> -+#include <linux/sched.h> - - extern unsigned long loops_per_jiffy; - -@@ -58,7 +59,18 @@ void calibrate_delay(void); - void __attribute__((weak)) calibration_delay_done(void); - void msleep(unsigned int msecs); - unsigned long msleep_interruptible(unsigned int msecs); --void usleep_range(unsigned long min, unsigned long max); -+void usleep_range_state(unsigned long min, unsigned long max, -+ unsigned int state); -+ -+static inline void usleep_range(unsigned long min, unsigned long max) -+{ -+ usleep_range_state(min, max, TASK_UNINTERRUPTIBLE); -+} -+ -+static inline void usleep_idle_range(unsigned long min, unsigned long max) -+{ -+ usleep_range_state(min, max, TASK_IDLE); -+} - - static inline void ssleep(unsigned int seconds) - { -diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h -index 8b32b4bdd5908..3ad636a13b8e9 100644 ---- a/include/linux/dma-buf.h -+++ b/include/linux/dma-buf.h -@@ -433,7 +433,7 @@ struct dma_buf { - wait_queue_head_t *poll; - - __poll_t active; -- } cb_excl, cb_shared; -+ } cb_in, cb_out; - #ifdef CONFIG_DMABUF_SYSFS_STATS - /** - * @sysfs_entry: -diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h -index e5c2c9e71bf10..9000f3ffce8b3 100644 ---- a/include/linux/dmaengine.h -+++ b/include/linux/dmaengine.h -@@ -944,10 +944,8 @@ struct dma_device { - void (*device_issue_pending)(struct dma_chan *chan); - void (*device_release)(struct dma_device *dev); - /* debugfs support */ --#ifdef CONFIG_DEBUG_FS - void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); - struct dentry *dbg_dev_root; --#endif - }; - - static inline int dmaengine_slave_config(struct dma_chan *chan, -diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h -index 8ae999f587c48..289064b51fa9a 100644 ---- a/include/linux/dsa/ocelot.h -+++ b/include/linux/dsa/ocelot.h -@@ -12,6 +12,7 @@ - struct ocelot_skb_cb { - struct sk_buff *clone; - unsigned int ptp_class; /* valid only for clones */ -+ u32 tstamp_lo; - u8 ptp_cmd; - u8 ts_id; - }; -diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h -index 1e7bf78cb3829..aba348d58ff61 100644 ---- a/include/linux/ethtool_netlink.h -+++ b/include/linux/ethtool_netlink.h -@@ -10,6 +10,9 @@ - #define __ETHTOOL_LINK_MODE_MASK_NWORDS \ - DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32) - -+#define ETHTOOL_PAUSE_STAT_CNT (__ETHTOOL_A_PAUSE_STAT_CNT - \ -+ ETHTOOL_A_PAUSE_STAT_TX_FRAMES) -+ - enum ethtool_multicast_groups { - ETHNL_MCGRP_MONITOR, - }; -diff --git a/include/linux/filter.h b/include/linux/filter.h -index ef03ff34234d8..1611dc9d44207 100644 ---- a/include/linux/filter.h -+++ b/include/linux/filter.h -@@ -613,13 +613,14 @@ static __always_inline u32 __bpf_prog_run(const struct bpf_prog *prog, - if (static_branch_unlikely(&bpf_stats_enabled_key)) { - struct bpf_prog_stats *stats; - u64 start = sched_clock(); -+ unsigned long flags; - - ret = dfunc(ctx, prog->insnsi, prog->bpf_func); - stats = this_cpu_ptr(prog->stats); -- u64_stats_update_begin(&stats->syncp); -+ flags = u64_stats_update_begin_irqsave(&stats->syncp); - stats->cnt++; - stats->nsecs += sched_clock() - start; -- u64_stats_update_end(&stats->syncp); -+ u64_stats_update_end_irqrestore(&stats->syncp, flags); - } else { - ret = dfunc(ctx, prog->insnsi, prog->bpf_func); - } -@@ -638,9 +639,6 @@ static __always_inline u32 bpf_prog_run(const struct bpf_prog *prog, const void - * This uses migrate_disable/enable() explicitly to document that the - * invocation of a BPF program does not require reentrancy protection - * against a BPF program which is invoked from a preempting task. -- * -- * For non RT enabled kernels migrate_disable/enable() maps to -- * preempt_disable/enable(), i.e. it disables also preemption. - */ - static inline u32 bpf_prog_run_pin_on_cpu(const struct bpf_prog *prog, - const void *ctx) -diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h -index c1be37437e778..0c70febd03e95 100644 ---- a/include/linux/fortify-string.h -+++ b/include/linux/fortify-string.h -@@ -280,7 +280,10 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) - if (p_size == (size_t)-1 && q_size == (size_t)-1) - return __underlying_strcpy(p, q); - size = strlen(q) + 1; -- /* test here to use the more stringent object size */ -+ /* Compile-time check for const size overflow. */ -+ if (__builtin_constant_p(size) && p_size < size) -+ __write_overflow(); -+ /* Run-time check for dynamic size overflow. */ - if (p_size < size) - fortify_panic(__func__); - memcpy(p, q, size); -diff --git a/include/linux/fs.h b/include/linux/fs.h -index e7a633353fd20..56eba723477e3 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -2498,6 +2498,8 @@ enum file_time_flags { - - extern bool atime_needs_update(const struct path *, struct inode *); - extern void touch_atime(const struct path *); -+int inode_update_time(struct inode *inode, struct timespec64 *time, int flags); -+ - static inline void file_accessed(struct file *file) - { - if (!(file->f_flags & O_NOATIME)) -diff --git a/include/linux/hid.h b/include/linux/hid.h -index 9e067f937dbc2..f453be385bd47 100644 ---- a/include/linux/hid.h -+++ b/include/linux/hid.h -@@ -840,6 +840,11 @@ static inline bool hid_is_using_ll_driver(struct hid_device *hdev, - return hdev->ll_driver == driver; - } - -+static inline bool hid_is_usb(struct hid_device *hdev) -+{ -+ return hid_is_using_ll_driver(hdev, &usb_hid_driver); -+} -+ - #define PM_HINT_FULLON 1<<5 - #define PM_HINT_NORMAL 1<<1 - -diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h -index 05e22770af517..b75395ec8d521 100644 ---- a/include/linux/ipc_namespace.h -+++ b/include/linux/ipc_namespace.h -@@ -131,6 +131,16 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) - return ns; - } - -+static inline struct ipc_namespace *get_ipc_ns_not_zero(struct ipc_namespace *ns) -+{ -+ if (ns) { -+ if (refcount_inc_not_zero(&ns->ns.count)) -+ return ns; -+ } -+ -+ return NULL; -+} -+ - extern void put_ipc_ns(struct ipc_namespace *ns); - #else - static inline struct ipc_namespace *copy_ipcs(unsigned long flags, -@@ -147,6 +157,11 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) - return ns; - } - -+static inline struct ipc_namespace *get_ipc_ns_not_zero(struct ipc_namespace *ns) -+{ -+ return ns; -+} -+ - static inline void put_ipc_ns(struct ipc_namespace *ns) - { - } -diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h -index 44ae1a7eb9e39..69ae6b2784645 100644 ---- a/include/linux/kernel_stat.h -+++ b/include/linux/kernel_stat.h -@@ -102,6 +102,7 @@ extern void account_system_index_time(struct task_struct *, u64, - enum cpu_usage_stat); - extern void account_steal_time(u64); - extern void account_idle_time(u64); -+extern u64 get_idle_time(struct kernel_cpustat *kcs, int cpu); - - #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE - static inline void account_process_tick(struct task_struct *tsk, int user) -diff --git a/include/linux/kfence.h b/include/linux/kfence.h -index 3fe6dd8a18c19..4b5e3679a72c7 100644 ---- a/include/linux/kfence.h -+++ b/include/linux/kfence.h -@@ -14,6 +14,9 @@ - - #ifdef CONFIG_KFENCE - -+#include <linux/atomic.h> -+#include <linux/static_key.h> -+ - /* - * We allocate an even number of pages, as it simplifies calculations to map - * address to metadata indices; effectively, the very first page serves as an -@@ -22,13 +25,8 @@ - #define KFENCE_POOL_SIZE ((CONFIG_KFENCE_NUM_OBJECTS + 1) * 2 * PAGE_SIZE) - extern char *__kfence_pool; - --#ifdef CONFIG_KFENCE_STATIC_KEYS --#include <linux/static_key.h> - DECLARE_STATIC_KEY_FALSE(kfence_allocation_key); --#else --#include <linux/atomic.h> - extern atomic_t kfence_allocation_gate; --#endif - - /** - * is_kfence_address() - check if an address belongs to KFENCE pool -@@ -116,13 +114,16 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags); - */ - static __always_inline void *kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) - { --#ifdef CONFIG_KFENCE_STATIC_KEYS -- if (static_branch_unlikely(&kfence_allocation_key)) -+#if defined(CONFIG_KFENCE_STATIC_KEYS) || CONFIG_KFENCE_SAMPLE_INTERVAL == 0 -+ if (!static_branch_unlikely(&kfence_allocation_key)) -+ return NULL; - #else -- if (unlikely(!atomic_read(&kfence_allocation_gate))) -+ if (!static_branch_likely(&kfence_allocation_key)) -+ return NULL; - #endif -- return __kfence_alloc(s, size, flags); -- return NULL; -+ if (likely(atomic_read(&kfence_allocation_gate))) -+ return NULL; -+ return __kfence_alloc(s, size, flags); - } - - /** -diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h -index e4f3bfe087570..ef8c7accbc689 100644 ---- a/include/linux/kprobes.h -+++ b/include/linux/kprobes.h -@@ -154,6 +154,8 @@ struct kretprobe { - struct kretprobe_holder *rph; - }; - -+#define KRETPROBE_MAX_DATA_SIZE 4096 -+ - struct kretprobe_instance { - union { - struct freelist_node freelist; -diff --git a/include/linux/libata.h b/include/linux/libata.h -index c0c64f03e1074..a64e12605d31d 100644 ---- a/include/linux/libata.h -+++ b/include/linux/libata.h -@@ -394,7 +394,7 @@ enum { - /* This should match the actual table size of - * ata_eh_cmd_timeout_table in libata-eh.c. - */ -- ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 6, -+ ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 7, - - /* Horkage types. May be set by libata or controller on drives - (some horkage may be drive/controller pair dependent */ -diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h -index 2adeea44c0d53..61590c1f2d333 100644 ---- a/include/linux/lsm_hook_defs.h -+++ b/include/linux/lsm_hook_defs.h -@@ -26,13 +26,13 @@ - * #undef LSM_HOOK - * }; - */ --LSM_HOOK(int, 0, binder_set_context_mgr, struct task_struct *mgr) --LSM_HOOK(int, 0, binder_transaction, struct task_struct *from, -- struct task_struct *to) --LSM_HOOK(int, 0, binder_transfer_binder, struct task_struct *from, -- struct task_struct *to) --LSM_HOOK(int, 0, binder_transfer_file, struct task_struct *from, -- struct task_struct *to, struct file *file) -+LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) -+LSM_HOOK(int, 0, binder_transaction, const struct cred *from, -+ const struct cred *to) -+LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from, -+ const struct cred *to) -+LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from, -+ const struct cred *to, struct file *file) - LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child, - unsigned int mode) - LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent) -diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h -index 5c4c5c0602cb7..59024618554e2 100644 ---- a/include/linux/lsm_hooks.h -+++ b/include/linux/lsm_hooks.h -@@ -1313,22 +1313,22 @@ - * - * @binder_set_context_mgr: - * Check whether @mgr is allowed to be the binder context manager. -- * @mgr contains the task_struct for the task being registered. -+ * @mgr contains the struct cred for the current binder process. - * Return 0 if permission is granted. - * @binder_transaction: - * Check whether @from is allowed to invoke a binder transaction call - * to @to. -- * @from contains the task_struct for the sending task. -- * @to contains the task_struct for the receiving task. -+ * @from contains the struct cred for the sending process. -+ * @to contains the struct cred for the receiving process. - * @binder_transfer_binder: - * Check whether @from is allowed to transfer a binder reference to @to. -- * @from contains the task_struct for the sending task. -- * @to contains the task_struct for the receiving task. -+ * @from contains the struct cred for the sending process. -+ * @to contains the struct cred for the receiving process. - * @binder_transfer_file: - * Check whether @from is allowed to transfer @file to @to. -- * @from contains the task_struct for the sending task. -+ * @from contains the struct cred for the sending process. - * @file contains the struct file being transferred. -- * @to contains the task_struct for the receiving task. -+ * @to contains the struct cred for the receiving process. - * - * @ptrace_access_check: - * Check permission before allowing the current process to trace the -diff --git a/include/linux/mhi.h b/include/linux/mhi.h -index 7239858790353..a5cc4cdf9cc86 100644 ---- a/include/linux/mhi.h -+++ b/include/linux/mhi.h -@@ -663,6 +663,19 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); - */ - int mhi_pm_resume(struct mhi_controller *mhi_cntrl); - -+/** -+ * mhi_pm_resume_force - Force resume MHI from suspended state -+ * @mhi_cntrl: MHI controller -+ * -+ * Resume the device irrespective of its MHI state. As per the MHI spec, devices -+ * has to be in M3 state during resume. But some devices seem to be in a -+ * different MHI state other than M3 but they continue working fine if allowed. -+ * This API is intented to be used for such devices. -+ * -+ * Return: 0 if the resume succeeds, a negative error code otherwise -+ */ -+int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl); -+ - /** - * mhi_download_rddm_image - Download ramdump image from device for - * debugging purpose. -diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h -index 4ab5c1fc1270d..a09ed4c8361b6 100644 ---- a/include/linux/mlx5/eswitch.h -+++ b/include/linux/mlx5/eswitch.h -@@ -136,13 +136,13 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw, - ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT) - #define ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK ESW_TUN_OPTS_MASK - --u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev); -+u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev); - u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); - struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw); - - #else /* CONFIG_MLX5_ESWITCH */ - --static inline u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev) -+static inline u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) - { - return MLX5_ESWITCH_NONE; - } -diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h -index 993204a6c1a13..25d775764a5ac 100644 ---- a/include/linux/mlx5/mlx5_ifc.h -+++ b/include/linux/mlx5/mlx5_ifc.h -@@ -3309,8 +3309,8 @@ enum { - }; - - enum { -- MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO = 0x1, -- MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO = 0x2, -+ MLX5_TIRC_PACKET_MERGE_MASK_IPV4_LRO = BIT(0), -+ MLX5_TIRC_PACKET_MERGE_MASK_IPV6_LRO = BIT(1), - }; - - enum { -@@ -3335,7 +3335,7 @@ struct mlx5_ifc_tirc_bits { - - u8 reserved_at_80[0x4]; - u8 lro_timeout_period_usecs[0x10]; -- u8 lro_enable_mask[0x4]; -+ u8 packet_merge_mask[0x4]; - u8 lro_max_ip_payload_size[0x8]; - - u8 reserved_at_a0[0x40]; -@@ -6369,7 +6369,7 @@ struct mlx5_ifc_modify_tir_bitmask_bits { - u8 reserved_at_3c[0x1]; - u8 hash[0x1]; - u8 reserved_at_3e[0x1]; -- u8 lro[0x1]; -+ u8 packet_merge[0x1]; - }; - - struct mlx5_ifc_modify_tir_out_bits { -diff --git a/include/linux/msi.h b/include/linux/msi.h -index 49cf6eb222e76..e616f94c7c585 100644 ---- a/include/linux/msi.h -+++ b/include/linux/msi.h -@@ -148,7 +148,7 @@ struct msi_desc { - u8 is_msix : 1; - u8 multiple : 3; - u8 multi_cap : 3; -- u8 maskbit : 1; -+ u8 can_mask : 1; - u8 is_64 : 1; - u8 is_virtual : 1; - u16 entry_nr; -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index d79163208dfdb..ce81cc96a98d9 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -4403,7 +4403,8 @@ static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) - static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu) - { - spin_lock(&txq->_xmit_lock); -- txq->xmit_lock_owner = cpu; -+ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ -+ WRITE_ONCE(txq->xmit_lock_owner, cpu); - } - - static inline bool __netif_tx_acquire(struct netdev_queue *txq) -@@ -4420,26 +4421,32 @@ static inline void __netif_tx_release(struct netdev_queue *txq) - static inline void __netif_tx_lock_bh(struct netdev_queue *txq) - { - spin_lock_bh(&txq->_xmit_lock); -- txq->xmit_lock_owner = smp_processor_id(); -+ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ -+ WRITE_ONCE(txq->xmit_lock_owner, smp_processor_id()); - } - - static inline bool __netif_tx_trylock(struct netdev_queue *txq) - { - bool ok = spin_trylock(&txq->_xmit_lock); -- if (likely(ok)) -- txq->xmit_lock_owner = smp_processor_id(); -+ -+ if (likely(ok)) { -+ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ -+ WRITE_ONCE(txq->xmit_lock_owner, smp_processor_id()); -+ } - return ok; - } - - static inline void __netif_tx_unlock(struct netdev_queue *txq) - { -- txq->xmit_lock_owner = -1; -+ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ -+ WRITE_ONCE(txq->xmit_lock_owner, -1); - spin_unlock(&txq->_xmit_lock); - } - - static inline void __netif_tx_unlock_bh(struct netdev_queue *txq) - { -- txq->xmit_lock_owner = -1; -+ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ -+ WRITE_ONCE(txq->xmit_lock_owner, -1); - spin_unlock_bh(&txq->_xmit_lock); - } - -diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h -index b9a8b925db430..4d95cc999d121 100644 ---- a/include/linux/nfs_fs.h -+++ b/include/linux/nfs_fs.h -@@ -569,6 +569,7 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); - extern int nfs_commit_inode(struct inode *, int); - extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail); - extern void nfs_commit_free(struct nfs_commit_data *data); -+bool nfs_commit_end(struct nfs_mds_commit_info *cinfo); - - static inline int - nfs_have_writebacks(struct inode *inode) -diff --git a/include/linux/pci.h b/include/linux/pci.h -index cd8aa6fce2041..152a4d74f87f0 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -233,6 +233,8 @@ enum pci_dev_flags { - PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), - /* Don't use Relaxed Ordering for TLPs directed at this device */ - PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11), -+ /* Device does honor MSI masking despite saying otherwise */ -+ PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12), - }; - - enum pci_irq_reroute_variant { -diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h -index 9837fb011f2fb..989aa30c598dc 100644 ---- a/include/linux/platform_data/ti-sysc.h -+++ b/include/linux/platform_data/ti-sysc.h -@@ -50,6 +50,7 @@ struct sysc_regbits { - s8 emufree_shift; - }; - -+#define SYSC_QUIRK_REINIT_ON_CTX_LOST BIT(28) - #define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) - #define SYSC_QUIRK_GPMC_DEBUG BIT(26) - #define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) -diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h -index 222da43b7096d..eddd66d426caf 100644 ---- a/include/linux/pm_runtime.h -+++ b/include/linux/pm_runtime.h -@@ -129,7 +129,7 @@ static inline bool pm_runtime_suspended(struct device *dev) - * pm_runtime_active - Check whether or not a device is runtime-active. - * @dev: Target device. - * -- * Return %true if runtime PM is enabled for @dev and its runtime PM status is -+ * Return %true if runtime PM is disabled for @dev or its runtime PM status is - * %RPM_ACTIVE, or %false otherwise. - * - * Note that the return value of this function can only be trusted if it is -diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h -index 00fef0064355f..5bbcd280bfd26 100644 ---- a/include/linux/posix-timers.h -+++ b/include/linux/posix-timers.h -@@ -184,8 +184,10 @@ static inline void posix_cputimers_group_init(struct posix_cputimers *pct, - #endif - - #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK -+void clear_posix_cputimers_work(struct task_struct *p); - void posix_cputimers_init_work(void); - #else -+static inline void clear_posix_cputimers_work(struct task_struct *p) { } - static inline void posix_cputimers_init_work(void) { } - #endif - -diff --git a/include/linux/printk.h b/include/linux/printk.h -index 85b656f82d752..9497f6b983399 100644 ---- a/include/linux/printk.h -+++ b/include/linux/printk.h -@@ -198,6 +198,7 @@ void dump_stack_print_info(const char *log_lvl); - void show_regs_print_info(const char *log_lvl); - extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold; - extern asmlinkage void dump_stack(void) __cold; -+void printk_trigger_flush(void); - #else - static inline __printf(1, 0) - int vprintk(const char *s, va_list args) -@@ -274,6 +275,9 @@ static inline void dump_stack_lvl(const char *log_lvl) - static inline void dump_stack(void) - { - } -+static inline void printk_trigger_flush(void) -+{ -+} - #endif - - #ifdef CONFIG_SMP -diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h -index d97dcd049f18f..a8dcf8a9ae885 100644 ---- a/include/linux/rpmsg.h -+++ b/include/linux/rpmsg.h -@@ -231,7 +231,7 @@ static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev - /* This shouldn't be possible */ - WARN_ON(1); - -- return ERR_PTR(-ENXIO); -+ return NULL; - } - - static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) -diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h -index e5f4ce622ee61..9a707b555b0a0 100644 ---- a/include/linux/sched/signal.h -+++ b/include/linux/sched/signal.h -@@ -338,6 +338,8 @@ extern int kill_pid(struct pid *pid, int sig, int priv); - extern __must_check bool do_notify_parent(struct task_struct *, int); - extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); - extern void force_sig(int); -+extern void force_fatal_sig(int); -+extern void force_exit_sig(int); - extern int send_sig(int, struct task_struct *, int); - extern int zap_other_threads(struct task_struct *p); - extern struct sigqueue *sigqueue_alloc(void); -diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h -index ef02be869cf28..058d7f371e25a 100644 ---- a/include/linux/sched/task.h -+++ b/include/linux/sched/task.h -@@ -54,7 +54,8 @@ extern asmlinkage void schedule_tail(struct task_struct *prev); - extern void init_idle(struct task_struct *idle, int cpu); - - extern int sched_fork(unsigned long clone_flags, struct task_struct *p); --extern void sched_post_fork(struct task_struct *p); -+extern void sched_post_fork(struct task_struct *p, -+ struct kernel_clone_args *kargs); - extern void sched_dead(struct task_struct *p); - - void __noreturn do_task_dead(void); -@@ -157,7 +158,7 @@ static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) - * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring - * subscriptions and synchronises with wait4(). Also used in procfs. Also - * pins the final release of task.io_context. Also protects ->cpuset and -- * ->cgroup.subsys[]. And ->vfork_done. -+ * ->cgroup.subsys[]. And ->vfork_done. And ->sysvshm.shm_clist. - * - * Nests both inside and outside of read_lock(&tasklist_lock). - * It must not be nested with write_lock_irq(&tasklist_lock), -diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h -index 2413427e439c7..d10150587d819 100644 ---- a/include/linux/sched/task_stack.h -+++ b/include/linux/sched/task_stack.h -@@ -25,7 +25,11 @@ static inline void *task_stack_page(const struct task_struct *task) - - static inline unsigned long *end_of_stack(const struct task_struct *task) - { -+#ifdef CONFIG_STACK_GROWSUP -+ return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1; -+#else - return task->stack; -+#endif - } - - #elif !defined(__HAVE_THREAD_FUNCTIONS) -diff --git a/include/linux/security.h b/include/linux/security.h -index 5b7288521300b..46a02ce34d00b 100644 ---- a/include/linux/security.h -+++ b/include/linux/security.h -@@ -258,13 +258,13 @@ extern int security_init(void); - extern int early_security_init(void); - - /* Security operations */ --int security_binder_set_context_mgr(struct task_struct *mgr); --int security_binder_transaction(struct task_struct *from, -- struct task_struct *to); --int security_binder_transfer_binder(struct task_struct *from, -- struct task_struct *to); --int security_binder_transfer_file(struct task_struct *from, -- struct task_struct *to, struct file *file); -+int security_binder_set_context_mgr(const struct cred *mgr); -+int security_binder_transaction(const struct cred *from, -+ const struct cred *to); -+int security_binder_transfer_binder(const struct cred *from, -+ const struct cred *to); -+int security_binder_transfer_file(const struct cred *from, -+ const struct cred *to, struct file *file); - int security_ptrace_access_check(struct task_struct *child, unsigned int mode); - int security_ptrace_traceme(struct task_struct *parent); - int security_capget(struct task_struct *target, -@@ -508,25 +508,25 @@ static inline int early_security_init(void) - return 0; - } - --static inline int security_binder_set_context_mgr(struct task_struct *mgr) -+static inline int security_binder_set_context_mgr(const struct cred *mgr) - { - return 0; - } - --static inline int security_binder_transaction(struct task_struct *from, -- struct task_struct *to) -+static inline int security_binder_transaction(const struct cred *from, -+ const struct cred *to) - { - return 0; - } - --static inline int security_binder_transfer_binder(struct task_struct *from, -- struct task_struct *to) -+static inline int security_binder_transfer_binder(const struct cred *from, -+ const struct cred *to) - { - return 0; - } - --static inline int security_binder_transfer_file(struct task_struct *from, -- struct task_struct *to, -+static inline int security_binder_transfer_file(const struct cred *from, -+ const struct cred *to, - struct file *file) - { - return 0; -@@ -1041,6 +1041,11 @@ static inline void security_transfer_creds(struct cred *new, - { - } - -+static inline void security_cred_getsecid(const struct cred *c, u32 *secid) -+{ -+ *secid = 0; -+} -+ - static inline int security_kernel_act_as(struct cred *cred, u32 secid) - { - return 0; -diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h -index dd99569595fd3..5733890df64f5 100644 ---- a/include/linux/seq_file.h -+++ b/include/linux/seq_file.h -@@ -194,7 +194,7 @@ static const struct file_operations __name ## _fops = { \ - #define DEFINE_PROC_SHOW_ATTRIBUTE(__name) \ - static int __name ## _open(struct inode *inode, struct file *file) \ - { \ -- return single_open(file, __name ## _show, inode->i_private); \ -+ return single_open(file, __name ## _show, PDE_DATA(inode)); \ - } \ - \ - static const struct proc_ops __name ## _proc_ops = { \ -diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h -index 34cb28b8f16ca..a70b2bdbf4d96 100644 ---- a/include/linux/signal_types.h -+++ b/include/linux/signal_types.h -@@ -70,6 +70,9 @@ struct ksignal { - int sig; - }; - -+/* Used to kill the race between sigaction and forced signals */ -+#define SA_IMMUTABLE 0x00800000 -+ - #ifndef __ARCH_UAPI_SA_FLAGS - #ifdef SA_RESTORER - #define __ARCH_UAPI_SA_FLAGS SA_RESTORER -diff --git a/include/linux/siphash.h b/include/linux/siphash.h -index bf21591a9e5e6..0cda61855d907 100644 ---- a/include/linux/siphash.h -+++ b/include/linux/siphash.h -@@ -27,9 +27,7 @@ static inline bool siphash_key_is_zero(const siphash_key_t *key) - } - - u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key); --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key); --#endif - - u64 siphash_1u64(const u64 a, const siphash_key_t *key); - u64 siphash_2u64(const u64 a, const u64 b, const siphash_key_t *key); -@@ -82,10 +80,9 @@ static inline u64 ___siphash_aligned(const __le64 *data, size_t len, - static inline u64 siphash(const void *data, size_t len, - const siphash_key_t *key) - { --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -- if (!IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) -+ if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || -+ !IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) - return __siphash_unaligned(data, len, key); --#endif - return ___siphash_aligned(data, len, key); - } - -@@ -96,10 +93,8 @@ typedef struct { - - u32 __hsiphash_aligned(const void *data, size_t len, - const hsiphash_key_t *key); --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u32 __hsiphash_unaligned(const void *data, size_t len, - const hsiphash_key_t *key); --#endif - - u32 hsiphash_1u32(const u32 a, const hsiphash_key_t *key); - u32 hsiphash_2u32(const u32 a, const u32 b, const hsiphash_key_t *key); -@@ -135,10 +130,9 @@ static inline u32 ___hsiphash_aligned(const __le32 *data, size_t len, - static inline u32 hsiphash(const void *data, size_t len, - const hsiphash_key_t *key) - { --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -- if (!IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) -+ if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || -+ !IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) - return __hsiphash_unaligned(data, len, key); --#endif - return ___hsiphash_aligned(data, len, key); - } - -diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index 841e2f0f5240b..b8c273af2910c 100644 ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -1671,6 +1671,22 @@ static inline int skb_unclone(struct sk_buff *skb, gfp_t pri) - return 0; - } - -+/* This variant of skb_unclone() makes sure skb->truesize is not changed */ -+static inline int skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri) -+{ -+ might_sleep_if(gfpflags_allow_blocking(pri)); -+ -+ if (skb_cloned(skb)) { -+ unsigned int save = skb->truesize; -+ int res; -+ -+ res = pskb_expand_head(skb, 0, 0, pri); -+ skb->truesize = save; -+ return res; -+ } -+ return 0; -+} -+ - /** - * skb_header_cloned - is the header a clone - * @skb: buffer to check -diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h -index 1ce9a9eb223b6..b4256847c7079 100644 ---- a/include/linux/skmsg.h -+++ b/include/linux/skmsg.h -@@ -509,8 +509,22 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock) - - #if IS_ENABLED(CONFIG_NET_SOCK_MSG) - --/* We only have one bit so far. */ --#define BPF_F_PTR_MASK ~(BPF_F_INGRESS) -+#define BPF_F_STRPARSER (1UL << 1) -+ -+/* We only have two bits so far. */ -+#define BPF_F_PTR_MASK ~(BPF_F_INGRESS | BPF_F_STRPARSER) -+ -+static inline bool skb_bpf_strparser(const struct sk_buff *skb) -+{ -+ unsigned long sk_redir = skb->_sk_redir; -+ -+ return sk_redir & BPF_F_STRPARSER; -+} -+ -+static inline void skb_bpf_set_strparser(struct sk_buff *skb) -+{ -+ skb->_sk_redir |= BPF_F_STRPARSER; -+} - - static inline bool skb_bpf_ingress(const struct sk_buff *skb) - { -diff --git a/include/linux/string.h b/include/linux/string.h -index 5e96d656be7ae..d68097b4f600b 100644 ---- a/include/linux/string.h -+++ b/include/linux/string.h -@@ -262,23 +262,8 @@ void __write_overflow(void) __compiletime_error("detected write beyond size of o - #include <linux/fortify-string.h> - #endif - --/** -- * memcpy_and_pad - Copy one buffer to another with padding -- * @dest: Where to copy to -- * @dest_len: The destination buffer size -- * @src: Where to copy from -- * @count: The number of bytes to copy -- * @pad: Character to use for padding if space is left in destination. -- */ --static inline void memcpy_and_pad(void *dest, size_t dest_len, -- const void *src, size_t count, int pad) --{ -- if (dest_len > count) { -- memcpy(dest, src, count); -- memset(dest + count, pad, dest_len - count); -- } else -- memcpy(dest, src, dest_len); --} -+void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, -+ int pad); - - /** - * str_has_prefix - Test if a string has a given prefix -diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h -index 068e1982ad371..74bfdffaf7b0e 100644 ---- a/include/linux/surface_aggregator/controller.h -+++ b/include/linux/surface_aggregator/controller.h -@@ -792,8 +792,8 @@ enum ssam_event_mask { - #define SSAM_EVENT_REGISTRY_KIP \ - SSAM_EVENT_REGISTRY(SSAM_SSH_TC_KIP, 0x02, 0x27, 0x28) - --#define SSAM_EVENT_REGISTRY_REG \ -- SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02) -+#define SSAM_EVENT_REGISTRY_REG(tid)\ -+ SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, tid, 0x01, 0x02) - - /** - * enum ssam_event_notifier_flags - Flags for event notifiers. -diff --git a/include/linux/tpm.h b/include/linux/tpm.h -index aa11fe323c56b..12d827734686d 100644 ---- a/include/linux/tpm.h -+++ b/include/linux/tpm.h -@@ -269,6 +269,7 @@ enum tpm2_cc_attrs { - #define TPM_VID_INTEL 0x8086 - #define TPM_VID_WINBOND 0x1050 - #define TPM_VID_STM 0x104A -+#define TPM_VID_ATML 0x1114 - - enum tpm_chip_flags { - TPM_CHIP_FLAG_TPM2 = BIT(1), -diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h -index 3e475eeb5a995..57113190448c6 100644 ---- a/include/linux/trace_events.h -+++ b/include/linux/trace_events.h -@@ -673,7 +673,7 @@ struct trace_event_file { - - #define PERF_MAX_TRACE_SIZE 2048 - --#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ -+#define MAX_FILTER_STR_VAL 256U /* Should handle KSYM_SYMBOL_LEN */ - - enum event_trigger_type { - ETT_NONE = (0), -diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h -index 2c1fc9212cf28..548a028f2dabb 100644 ---- a/include/linux/usb/hcd.h -+++ b/include/linux/usb/hcd.h -@@ -124,7 +124,6 @@ struct usb_hcd { - #define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ - #define HCD_FLAG_DEAD 6 /* controller has died? */ - #define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */ --#define HCD_FLAG_DEFER_RH_REGISTER 8 /* Defer roothub registration */ - - /* The flags can be tested using these macros; they are likely to - * be slightly faster than test_bit(). -@@ -135,7 +134,6 @@ struct usb_hcd { - #define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING)) - #define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING)) - #define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD)) --#define HCD_DEFER_RH_REGISTER(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEFER_RH_REGISTER)) - - /* - * Specifies if interfaces are authorized by default -diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h -index b465f8f3e554f..04e87f4b9417c 100644 ---- a/include/linux/virtio_net.h -+++ b/include/linux/virtio_net.h -@@ -120,10 +120,15 @@ retry: - - if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { - u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); -+ unsigned int nh_off = p_off; - struct skb_shared_info *shinfo = skb_shinfo(skb); - -+ /* UFO may not include transport header in gso_size. */ -+ if (gso_type & SKB_GSO_UDP) -+ nh_off -= thlen; -+ - /* Too small packets are not really GSO ones. */ -- if (skb->len - p_off > gso_size) { -+ if (skb->len - nh_off > gso_size) { - shinfo->gso_size = gso_size; - shinfo->gso_type = gso_type; - -diff --git a/include/linux/wait.h b/include/linux/wait.h -index 93dab0e9580f8..d22cf2985b8fd 100644 ---- a/include/linux/wait.h -+++ b/include/linux/wait.h -@@ -217,6 +217,7 @@ void __wake_up_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void - void __wake_up_locked_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void *key); - void __wake_up_locked(struct wait_queue_head *wq_head, unsigned int mode, int nr); - void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); -+void __wake_up_pollfree(struct wait_queue_head *wq_head); - - #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) - #define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL) -@@ -245,6 +246,31 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); - #define wake_up_interruptible_sync_poll_locked(x, m) \ - __wake_up_locked_sync_key((x), TASK_INTERRUPTIBLE, poll_to_key(m)) - -+/** -+ * wake_up_pollfree - signal that a polled waitqueue is going away -+ * @wq_head: the wait queue head -+ * -+ * In the very rare cases where a ->poll() implementation uses a waitqueue whose -+ * lifetime is tied to a task rather than to the 'struct file' being polled, -+ * this function must be called before the waitqueue is freed so that -+ * non-blocking polls (e.g. epoll) are notified that the queue is going away. -+ * -+ * The caller must also RCU-delay the freeing of the wait_queue_head, e.g. via -+ * an explicit synchronize_rcu() or call_rcu(), or via SLAB_TYPESAFE_BY_RCU. -+ */ -+static inline void wake_up_pollfree(struct wait_queue_head *wq_head) -+{ -+ /* -+ * For performance reasons, we don't always take the queue lock here. -+ * Therefore, we might race with someone removing the last entry from -+ * the queue, and proceed while they still hold the queue lock. -+ * However, rcu_read_lock() is required to be held in such cases, so we -+ * can safely proceed with an RCU-delayed free. -+ */ -+ if (waitqueue_active(wq_head)) -+ __wake_up_pollfree(wq_head); -+} -+ - #define ___wait_cond_timeout(condition) \ - ({ \ - bool __cond = (condition); \ -diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h -index 12955cb460d23..3b5986cee0739 100644 ---- a/include/media/videobuf2-core.h -+++ b/include/media/videobuf2-core.h -@@ -46,6 +46,7 @@ enum vb2_memory { - - struct vb2_fileio_data; - struct vb2_threadio_data; -+struct vb2_buffer; - - /** - * struct vb2_mem_ops - memory handling/memory allocator operations. -@@ -53,10 +54,8 @@ struct vb2_threadio_data; - * return ERR_PTR() on failure or a pointer to allocator private, - * per-buffer data on success; the returned private structure - * will then be passed as @buf_priv argument to other ops in this -- * structure. Additional gfp_flags to use when allocating the -- * are also passed to this operation. These flags are from the -- * gfp_flags field of vb2_queue. The size argument to this function -- * shall be *page aligned*. -+ * structure. The size argument to this function shall be -+ * *page aligned*. - * @put: inform the allocator that the buffer will no longer be used; - * usually will result in the allocator freeing the buffer (if - * no other users of this buffer are present); the @buf_priv -@@ -117,31 +116,33 @@ struct vb2_threadio_data; - * map_dmabuf, unmap_dmabuf. - */ - struct vb2_mem_ops { -- void *(*alloc)(struct device *dev, unsigned long attrs, -- unsigned long size, -- enum dma_data_direction dma_dir, -- gfp_t gfp_flags); -+ void *(*alloc)(struct vb2_buffer *vb, -+ struct device *dev, -+ unsigned long size); - void (*put)(void *buf_priv); -- struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags); -- -- void *(*get_userptr)(struct device *dev, unsigned long vaddr, -- unsigned long size, -- enum dma_data_direction dma_dir); -+ struct dma_buf *(*get_dmabuf)(struct vb2_buffer *vb, -+ void *buf_priv, -+ unsigned long flags); -+ -+ void *(*get_userptr)(struct vb2_buffer *vb, -+ struct device *dev, -+ unsigned long vaddr, -+ unsigned long size); - void (*put_userptr)(void *buf_priv); - - void (*prepare)(void *buf_priv); - void (*finish)(void *buf_priv); - -- void *(*attach_dmabuf)(struct device *dev, -+ void *(*attach_dmabuf)(struct vb2_buffer *vb, -+ struct device *dev, - struct dma_buf *dbuf, -- unsigned long size, -- enum dma_data_direction dma_dir); -+ unsigned long size); - void (*detach_dmabuf)(void *buf_priv); - int (*map_dmabuf)(void *buf_priv); - void (*unmap_dmabuf)(void *buf_priv); - -- void *(*vaddr)(void *buf_priv); -- void *(*cookie)(void *buf_priv); -+ void *(*vaddr)(struct vb2_buffer *vb, void *buf_priv); -+ void *(*cookie)(struct vb2_buffer *vb, void *buf_priv); - - unsigned int (*num_users)(void *buf_priv); - -diff --git a/include/memory/renesas-rpc-if.h b/include/memory/renesas-rpc-if.h -index e3e770f76f349..77c694a19149d 100644 ---- a/include/memory/renesas-rpc-if.h -+++ b/include/memory/renesas-rpc-if.h -@@ -59,6 +59,7 @@ struct rpcif_op { - - struct rpcif { - struct device *dev; -+ void __iomem *base; - void __iomem *dirmap; - struct regmap *regmap; - struct reset_control *rstc; -diff --git a/include/net/bond_alb.h b/include/net/bond_alb.h -index f6af76c87a6c3..191c36afa1f4a 100644 ---- a/include/net/bond_alb.h -+++ b/include/net/bond_alb.h -@@ -126,7 +126,7 @@ struct tlb_slave_info { - struct alb_bond_info { - struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */ - u32 unbalanced_load; -- int tx_rebalance_counter; -+ atomic_t tx_rebalance_counter; - int lp_counter; - /* -------- rlb parameters -------- */ - int rlb_enabled; -diff --git a/include/net/dst_cache.h b/include/net/dst_cache.h -index 67634675e9197..df6622a5fe98f 100644 ---- a/include/net/dst_cache.h -+++ b/include/net/dst_cache.h -@@ -79,6 +79,17 @@ static inline void dst_cache_reset(struct dst_cache *dst_cache) - dst_cache->reset_ts = jiffies; - } - -+/** -+ * dst_cache_reset_now - invalidate the cache contents immediately -+ * @dst_cache: the cache -+ * -+ * The caller must be sure there are no concurrent users, as this frees -+ * all dst_cache users immediately, rather than waiting for the next -+ * per-cpu usage like dst_cache_reset does. Most callers should use the -+ * higher speed lazily-freed dst_cache_reset function instead. -+ */ -+void dst_cache_reset_now(struct dst_cache *dst_cache); -+ - /** - * dst_cache_init - initialize the cache, allocating the required storage - * @dst_cache: the cache -diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h -index 4b10676c69d19..bd07484ab9dd5 100644 ---- a/include/net/fib_rules.h -+++ b/include/net/fib_rules.h -@@ -69,7 +69,7 @@ struct fib_rules_ops { - int (*action)(struct fib_rule *, - struct flowi *, int, - struct fib_lookup_arg *); -- bool (*suppress)(struct fib_rule *, -+ bool (*suppress)(struct fib_rule *, int, - struct fib_lookup_arg *); - int (*match)(struct fib_rule *, - struct flowi *, int); -@@ -218,7 +218,9 @@ INDIRECT_CALLABLE_DECLARE(int fib4_rule_action(struct fib_rule *rule, - struct fib_lookup_arg *arg)); - - INDIRECT_CALLABLE_DECLARE(bool fib6_rule_suppress(struct fib_rule *rule, -+ int flags, - struct fib_lookup_arg *arg)); - INDIRECT_CALLABLE_DECLARE(bool fib4_rule_suppress(struct fib_rule *rule, -+ int flags, - struct fib_lookup_arg *arg)); - #endif -diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h -index b06c2d02ec84e..fa6a87246a7b8 100644 ---- a/include/net/inet_connection_sock.h -+++ b/include/net/inet_connection_sock.h -@@ -289,7 +289,7 @@ static inline void inet_csk_prepare_for_destroy_sock(struct sock *sk) - { - /* The below has to be done to allow calling inet_csk_destroy_sock */ - sock_set_flag(sk, SOCK_DEAD); -- percpu_counter_inc(sk->sk_prot->orphan_count); -+ this_cpu_inc(*sk->sk_prot->orphan_count); - } - - void inet_csk_destroy_sock(struct sock *sk); -diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h -index c412dde4d67dc..83b8070d1cc93 100644 ---- a/include/net/ip6_fib.h -+++ b/include/net/ip6_fib.h -@@ -485,6 +485,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, - struct fib6_config *cfg, gfp_t gfp_flags, - struct netlink_ext_ack *extack); - void fib6_nh_release(struct fib6_nh *fib6_nh); -+void fib6_nh_release_dsts(struct fib6_nh *fib6_nh); - - int call_fib6_entry_notifiers(struct net *net, - enum fib_event_type event_type, -diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h -index ab5348e57db1a..3417ba2d27ad6 100644 ---- a/include/net/ip_fib.h -+++ b/include/net/ip_fib.h -@@ -438,7 +438,7 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, - #ifdef CONFIG_IP_ROUTE_CLASSID - static inline int fib_num_tclassid_users(struct net *net) - { -- return net->ipv4.fib_num_tclassid_users; -+ return atomic_read(&net->ipv4.fib_num_tclassid_users); - } - #else - static inline int fib_num_tclassid_users(struct net *net) -diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h -index afbce90c44808..45e0339be6fa4 100644 ---- a/include/net/ipv6_stubs.h -+++ b/include/net/ipv6_stubs.h -@@ -47,6 +47,7 @@ struct ipv6_stub { - struct fib6_config *cfg, gfp_t gfp_flags, - struct netlink_ext_ack *extack); - void (*fib6_nh_release)(struct fib6_nh *fib6_nh); -+ void (*fib6_nh_release_dsts)(struct fib6_nh *fib6_nh); - void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt); - int (*ip6_del_rt)(struct net *net, struct fib6_info *rt, bool skip_notify); - void (*fib6_rt_update)(struct net *net, struct fib6_info *rt, -diff --git a/include/net/llc.h b/include/net/llc.h -index df282d9b40170..9c10b121b49b0 100644 ---- a/include/net/llc.h -+++ b/include/net/llc.h -@@ -72,7 +72,9 @@ struct llc_sap { - static inline - struct hlist_head *llc_sk_dev_hash(struct llc_sap *sap, int ifindex) - { -- return &sap->sk_dev_hash[ifindex % LLC_SK_DEV_HASH_ENTRIES]; -+ u32 bucket = hash_32(ifindex, LLC_SK_DEV_HASH_BITS); -+ -+ return &sap->sk_dev_hash[bucket]; - } - - static inline -diff --git a/include/net/neighbour.h b/include/net/neighbour.h -index 22ced1381ede5..d5767e25509cc 100644 ---- a/include/net/neighbour.h -+++ b/include/net/neighbour.h -@@ -253,6 +253,7 @@ static inline void *neighbour_priv(const struct neighbour *n) - #define NEIGH_UPDATE_F_OVERRIDE 0x00000001 - #define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002 - #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004 -+#define NEIGH_UPDATE_F_USE 0x10000000 - #define NEIGH_UPDATE_F_EXT_LEARNED 0x20000000 - #define NEIGH_UPDATE_F_ISROUTER 0x40000000 - #define NEIGH_UPDATE_F_ADMIN 0x80000000 -@@ -504,10 +505,15 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, - { - const struct hh_cache *hh = &n->hh; - -- if ((n->nud_state & NUD_CONNECTED) && hh->hh_len && !skip_cache) -+ /* n->nud_state and hh->hh_len could be changed under us. -+ * neigh_hh_output() is taking care of the race later. -+ */ -+ if (!skip_cache && -+ (READ_ONCE(n->nud_state) & NUD_CONNECTED) && -+ READ_ONCE(hh->hh_len)) - return neigh_hh_output(hh, skb); -- else -- return n->output(n, skb); -+ -+ return n->output(n, skb); - } - - static inline struct neighbour * -diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h -index cc663c68ddc4b..d24b0a34c8f0c 100644 ---- a/include/net/netfilter/nf_conntrack.h -+++ b/include/net/netfilter/nf_conntrack.h -@@ -276,14 +276,14 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) - /* jiffies until ct expires, 0 if already expired */ - static inline unsigned long nf_ct_expires(const struct nf_conn *ct) - { -- s32 timeout = ct->timeout - nfct_time_stamp; -+ s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; - - return timeout > 0 ? timeout : 0; - } - - static inline bool nf_ct_is_expired(const struct nf_conn *ct) - { -- return (__s32)(ct->timeout - nfct_time_stamp) <= 0; -+ return (__s32)(READ_ONCE(ct->timeout) - nfct_time_stamp) <= 0; - } - - /* use after obtaining a reference count */ -@@ -302,7 +302,7 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct) - static inline void nf_ct_offload_timeout(struct nf_conn *ct) - { - if (nf_ct_expires(ct) < NF_CT_DAY / 2) -- ct->timeout = nfct_time_stamp + NF_CT_DAY; -+ WRITE_ONCE(ct->timeout, nfct_time_stamp + NF_CT_DAY); - } - - struct kernel_param; -diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h -index 2f65701a43c95..6c5b2efc4f17d 100644 ---- a/include/net/netns/ipv4.h -+++ b/include/net/netns/ipv4.h -@@ -65,7 +65,7 @@ struct netns_ipv4 { - bool fib_has_custom_local_routes; - bool fib_offload_disabled; - #ifdef CONFIG_IP_ROUTE_CLASSID -- int fib_num_tclassid_users; -+ atomic_t fib_num_tclassid_users; - #endif - struct hlist_head *fib_table_hash; - struct sock *fibnl; -diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h -index a964daedc17b6..ea8595651c384 100644 ---- a/include/net/nfc/nci_core.h -+++ b/include/net/nfc/nci_core.h -@@ -30,6 +30,7 @@ enum nci_flag { - NCI_UP, - NCI_DATA_EXCHANGE, - NCI_DATA_EXCHANGE_TO, -+ NCI_UNREG, - }; - - /* NCI device states */ -diff --git a/include/net/nl802154.h b/include/net/nl802154.h -index ddcee128f5d9a..145acb8f25095 100644 ---- a/include/net/nl802154.h -+++ b/include/net/nl802154.h -@@ -19,6 +19,8 @@ - * - */ - -+#include <linux/types.h> -+ - #define NL802154_GENL_NAME "nl802154" - - enum nl802154_commands { -@@ -150,10 +152,9 @@ enum nl802154_attrs { - }; - - enum nl802154_iftype { -- /* for backwards compatibility TODO */ -- NL802154_IFTYPE_UNSPEC = -1, -+ NL802154_IFTYPE_UNSPEC = (~(__u32)0), - -- NL802154_IFTYPE_NODE, -+ NL802154_IFTYPE_NODE = 0, - NL802154_IFTYPE_MONITOR, - NL802154_IFTYPE_COORD, - -diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h -index c0069ac00e62d..8c2d611639fca 100644 ---- a/include/net/sch_generic.h -+++ b/include/net/sch_generic.h -@@ -308,6 +308,8 @@ struct Qdisc_ops { - struct netlink_ext_ack *extack); - void (*attach)(struct Qdisc *sch); - int (*change_tx_queue_len)(struct Qdisc *, unsigned int); -+ void (*change_real_num_tx)(struct Qdisc *sch, -+ unsigned int new_real_tx); - - int (*dump)(struct Qdisc *, struct sk_buff *); - int (*dump_stats)(struct Qdisc *, struct gnet_dump *); -@@ -684,6 +686,8 @@ void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); - void qdisc_class_hash_destroy(struct Qdisc_class_hash *); - - int dev_qdisc_change_tx_queue_len(struct net_device *dev); -+void dev_qdisc_change_real_num_tx(struct net_device *dev, -+ unsigned int new_real_tx); - void dev_init_scheduler(struct net_device *dev); - void dev_shutdown(struct net_device *dev); - void dev_activate(struct net_device *dev); -diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h -index 69bab88ad66b1..189fdb9db1622 100644 ---- a/include/net/sctp/sctp.h -+++ b/include/net/sctp/sctp.h -@@ -626,7 +626,8 @@ static inline __u32 sctp_min_frag_point(struct sctp_sock *sp, __u16 datasize) - - static inline int sctp_transport_pl_hlen(struct sctp_transport *t) - { -- return __sctp_mtu_payload(sctp_sk(t->asoc->base.sk), t, 0, 0); -+ return __sctp_mtu_payload(sctp_sk(t->asoc->base.sk), t, 0, 0) - -+ sizeof(struct sctphdr); - } - - static inline void sctp_transport_pl_reset(struct sctp_transport *t) -@@ -653,12 +654,10 @@ static inline void sctp_transport_pl_update(struct sctp_transport *t) - if (t->pl.state == SCTP_PL_DISABLED) - return; - -- if (del_timer(&t->probe_timer)) -- sctp_transport_put(t); -- - t->pl.state = SCTP_PL_BASE; - t->pl.pmtu = SCTP_BASE_PLPMTU; - t->pl.probe_size = SCTP_BASE_PLPMTU; -+ sctp_transport_reset_probe_timer(t); - } - - static inline bool sctp_transport_pl_enabled(struct sctp_transport *t) -diff --git a/include/net/sock.h b/include/net/sock.h -index 463f390d90b3e..7ac5075f9c18a 100644 ---- a/include/net/sock.h -+++ b/include/net/sock.h -@@ -1237,7 +1237,7 @@ struct proto { - unsigned int useroffset; /* Usercopy region offset */ - unsigned int usersize; /* Usercopy region size */ - -- struct percpu_counter *orphan_count; -+ unsigned int __percpu *orphan_count; - - struct request_sock_ops *rsk_prot; - struct timewait_sock_ops *twsk_prot; -@@ -2400,19 +2400,22 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, - * @sk: socket - * - * Use the per task page_frag instead of the per socket one for -- * optimization when we know that we're in the normal context and owns -+ * optimization when we know that we're in process context and own - * everything that's associated with %current. - * -- * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest -- * inside other socket operations and end up recursing into sk_page_frag() -- * while it's already in use. -+ * Both direct reclaim and page faults can nest inside other -+ * socket operations and end up recursing into sk_page_frag() -+ * while it's already in use: explicitly avoid task page_frag -+ * usage if the caller is potentially doing any of them. -+ * This assumes that page fault handlers use the GFP_NOFS flags. - * - * Return: a per task page_frag if context allows that, - * otherwise a per socket one. - */ - static inline struct page_frag *sk_page_frag(struct sock *sk) - { -- if (gfpflags_normal_context(sk->sk_allocation)) -+ if ((sk->sk_allocation & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC | __GFP_FS)) == -+ (__GFP_DIRECT_RECLAIM | __GFP_FS)) - return ¤t->task_frag; - - return &sk->sk_frag; -diff --git a/include/net/strparser.h b/include/net/strparser.h -index 1d20b98493a10..732b7097d78e4 100644 ---- a/include/net/strparser.h -+++ b/include/net/strparser.h -@@ -54,10 +54,28 @@ struct strp_msg { - int offset; - }; - -+struct _strp_msg { -+ /* Internal cb structure. struct strp_msg must be first for passing -+ * to upper layer. -+ */ -+ struct strp_msg strp; -+ int accum_len; -+}; -+ -+struct sk_skb_cb { -+#define SK_SKB_CB_PRIV_LEN 20 -+ unsigned char data[SK_SKB_CB_PRIV_LEN]; -+ struct _strp_msg strp; -+ /* temp_reg is a temporary register used for bpf_convert_data_end_access -+ * when dst_reg == src_reg. -+ */ -+ u64 temp_reg; -+}; -+ - static inline struct strp_msg *strp_msg(struct sk_buff *skb) - { - return (struct strp_msg *)((void *)skb->cb + -- offsetof(struct qdisc_skb_cb, data)); -+ offsetof(struct sk_skb_cb, strp)); - } - - /* Structure for an attached lower socket */ -diff --git a/include/net/tcp.h b/include/net/tcp.h -index 60c384569e9cd..31d384c3778a1 100644 ---- a/include/net/tcp.h -+++ b/include/net/tcp.h -@@ -48,7 +48,9 @@ - - extern struct inet_hashinfo tcp_hashinfo; - --extern struct percpu_counter tcp_orphan_count; -+DECLARE_PER_CPU(unsigned int, tcp_orphan_count); -+int tcp_orphan_count_sum(void); -+ - void tcp_time_wait(struct sock *sk, int state, int timeo); - - #define MAX_TCP_HEADER L1_CACHE_ALIGN(128 + MAX_HEADER) -@@ -290,19 +292,6 @@ static inline bool tcp_out_of_memory(struct sock *sk) - - void sk_forced_mem_schedule(struct sock *sk, int size); - --static inline bool tcp_too_many_orphans(struct sock *sk, int shift) --{ -- struct percpu_counter *ocp = sk->sk_prot->orphan_count; -- int orphans = percpu_counter_read_positive(ocp); -- -- if (orphans << shift > sysctl_tcp_max_orphans) { -- orphans = percpu_counter_sum_positive(ocp); -- if (orphans << shift > sysctl_tcp_max_orphans) -- return true; -- } -- return false; --} -- - bool tcp_check_oom(struct sock *sk, int shift); - - -diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h -index 4b50d9a3018a6..4ba642fc8a19a 100644 ---- a/include/rdma/ib_verbs.h -+++ b/include/rdma/ib_verbs.h -@@ -4097,8 +4097,13 @@ static inline int ib_dma_map_sgtable_attrs(struct ib_device *dev, - enum dma_data_direction direction, - unsigned long dma_attrs) - { -+ int nents; -+ - if (ib_uses_virt_dma(dev)) { -- ib_dma_virt_map_sg(dev, sgt->sgl, sgt->orig_nents); -+ nents = ib_dma_virt_map_sg(dev, sgt->sgl, sgt->orig_nents); -+ if (!nents) -+ return -EIO; -+ sgt->nents = nents; - return 0; - } - return dma_map_sgtable(dev->dma_device, sgt, direction, dma_attrs); -diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h -index 2758d9df71ee9..c2a79aeee113c 100644 ---- a/include/rdma/rdma_netlink.h -+++ b/include/rdma/rdma_netlink.h -@@ -30,7 +30,7 @@ enum rdma_nl_flags { - * constant as well and the compiler checks they are the same. - */ - #define MODULE_ALIAS_RDMA_NETLINK(_index, _val) \ -- static inline void __chk_##_index(void) \ -+ static inline void __maybe_unused __chk_##_index(void) \ - { \ - BUILD_BUG_ON(_index != _val); \ - } \ -diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h -index eaf04c9a1dfcb..59afe8787cf7c 100644 ---- a/include/scsi/scsi_cmnd.h -+++ b/include/scsi/scsi_cmnd.h -@@ -68,7 +68,7 @@ struct scsi_pointer { - struct scsi_cmnd { - struct scsi_request req; - struct scsi_device *device; -- struct list_head eh_entry; /* entry for the host eh_cmd_q */ -+ struct list_head eh_entry; /* entry for the host eh_abort_list/eh_cmd_q */ - struct delayed_work abort_work; - - struct rcu_head rcu; -diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h -index 75363707b73f9..1a02e58eb4e44 100644 ---- a/include/scsi/scsi_host.h -+++ b/include/scsi/scsi_host.h -@@ -556,6 +556,7 @@ struct Scsi_Host { - - struct mutex scan_mutex;/* serialize scanning activity */ - -+ struct list_head eh_abort_list; - struct list_head eh_cmd_q; - struct task_struct * ehandler; /* Error recovery thread. */ - struct completion * eh_action; /* Wait for specific actions on the -diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h -index 375581634143c..d4e31ea16aba3 100644 ---- a/include/sound/hdaudio_ext.h -+++ b/include/sound/hdaudio_ext.h -@@ -88,6 +88,8 @@ struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, - struct snd_pcm_substream *substream, - int type); - void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type); -+void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, -+ struct hdac_ext_stream *azx_dev, bool decouple); - void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, - struct hdac_ext_stream *azx_dev, bool decouple); - void snd_hdac_ext_stop_streams(struct hdac_bus *bus); -diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h -index 4afd667e124c2..3e8a85e1e8094 100644 ---- a/include/sound/soc-topology.h -+++ b/include/sound/soc-topology.h -@@ -188,8 +188,7 @@ int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, - - #else - --static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp, -- u32 index) -+static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp) - { - return 0; - } -diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h -index fb11c7693b257..2121a323fd6c3 100644 ---- a/include/target/target_core_base.h -+++ b/include/target/target_core_base.h -@@ -812,8 +812,9 @@ struct se_device { - atomic_long_t read_bytes; - atomic_long_t write_bytes; - /* Active commands on this virtual SE device */ -- atomic_t simple_cmds; -- atomic_t dev_ordered_sync; -+ atomic_t non_ordered; -+ bool ordered_sync_in_progress; -+ atomic_t delayed_cmd_count; - atomic_t dev_qf_count; - u32 export_count; - spinlock_t delayed_cmd_lock; -@@ -834,6 +835,7 @@ struct se_device { - struct list_head dev_sep_list; - struct list_head dev_tmr_list; - struct work_struct qf_work_queue; -+ struct work_struct delayed_cmd_work; - struct list_head delayed_cmd_list; - struct list_head qf_cmd_list; - /* Pointer to associated SE HBA */ -diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h -index 4e881d91c8744..4cb055af1ec0b 100644 ---- a/include/trace/events/f2fs.h -+++ b/include/trace/events/f2fs.h -@@ -807,20 +807,20 @@ TRACE_EVENT(f2fs_lookup_start, - TP_STRUCT__entry( - __field(dev_t, dev) - __field(ino_t, ino) -- __field(const char *, name) -+ __string(name, dentry->d_name.name) - __field(unsigned int, flags) - ), - - TP_fast_assign( - __entry->dev = dir->i_sb->s_dev; - __entry->ino = dir->i_ino; -- __entry->name = dentry->d_name.name; -+ __assign_str(name, dentry->d_name.name); - __entry->flags = flags; - ), - - TP_printk("dev = (%d,%d), pino = %lu, name:%s, flags:%u", - show_dev_ino(__entry), -- __entry->name, -+ __get_str(name), - __entry->flags) - ); - -@@ -834,7 +834,7 @@ TRACE_EVENT(f2fs_lookup_end, - TP_STRUCT__entry( - __field(dev_t, dev) - __field(ino_t, ino) -- __field(const char *, name) -+ __string(name, dentry->d_name.name) - __field(nid_t, cino) - __field(int, err) - ), -@@ -842,14 +842,14 @@ TRACE_EVENT(f2fs_lookup_end, - TP_fast_assign( - __entry->dev = dir->i_sb->s_dev; - __entry->ino = dir->i_ino; -- __entry->name = dentry->d_name.name; -+ __assign_str(name, dentry->d_name.name); - __entry->cino = ino; - __entry->err = err; - ), - - TP_printk("dev = (%d,%d), pino = %lu, name:%s, ino:%u, err:%d", - show_dev_ino(__entry), -- __entry->name, -+ __get_str(name), - __entry->cino, - __entry->err) - ); -diff --git a/include/uapi/asm-generic/poll.h b/include/uapi/asm-generic/poll.h -index 41b509f410bf9..f9c520ce4bf4e 100644 ---- a/include/uapi/asm-generic/poll.h -+++ b/include/uapi/asm-generic/poll.h -@@ -29,7 +29,7 @@ - #define POLLRDHUP 0x2000 - #endif - --#define POLLFREE (__force __poll_t)0x4000 /* currently only for epoll */ -+#define POLLFREE (__force __poll_t)0x4000 - - #define POLL_BUSY_LOOP (__force __poll_t)0x8000 - -diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h -index fe929e7b77ca1..7572f2f46ee89 100644 ---- a/include/uapi/asm-generic/signal-defs.h -+++ b/include/uapi/asm-generic/signal-defs.h -@@ -45,6 +45,7 @@ - #define SA_UNSUPPORTED 0x00000400 - #define SA_EXPOSE_TAGBITS 0x00000800 - /* 0x00010000 used on mips */ -+/* 0x00800000 used for internal SA_IMMUTABLE */ - /* 0x01000000 used on x86 */ - /* 0x02000000 used on x86 */ - /* -diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h -index 5545f1ca9237c..f7204bdfe8db1 100644 ---- a/include/uapi/linux/ethtool_netlink.h -+++ b/include/uapi/linux/ethtool_netlink.h -@@ -407,7 +407,9 @@ enum { - ETHTOOL_A_PAUSE_STAT_TX_FRAMES, - ETHTOOL_A_PAUSE_STAT_RX_FRAMES, - -- /* add new constants above here */ -+ /* add new constants above here -+ * adjust ETHTOOL_PAUSE_STAT_CNT if adding non-stats! -+ */ - __ETHTOOL_A_PAUSE_STAT_CNT, - ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1) - }; -diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h -index f66038b9551fa..80c40194e2977 100644 ---- a/include/uapi/linux/mptcp.h -+++ b/include/uapi/linux/mptcp.h -@@ -129,19 +129,21 @@ struct mptcp_info { - * MPTCP_EVENT_REMOVED: token, rem_id - * An address has been lost by the peer. - * -- * MPTCP_EVENT_SUB_ESTABLISHED: token, family, saddr4 | saddr6, -- * daddr4 | daddr6, sport, dport, backup, -- * if_idx [, error] -+ * MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id, -+ * saddr4 | saddr6, daddr4 | daddr6, sport, -+ * dport, backup, if_idx [, error] - * A new subflow has been established. 'error' should not be set. - * -- * MPTCP_EVENT_SUB_CLOSED: token, family, saddr4 | saddr6, daddr4 | daddr6, -- * sport, dport, backup, if_idx [, error] -+ * MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6, -+ * daddr4 | daddr6, sport, dport, backup, if_idx -+ * [, error] - * A subflow has been closed. An error (copy of sk_err) could be set if an - * error has been detected for this subflow. - * -- * MPTCP_EVENT_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6, -- * sport, dport, backup, if_idx [, error] -- * The priority of a subflow has changed. 'error' should not be set. -+ * MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6, -+ * daddr4 | daddr6, sport, dport, backup, if_idx -+ * [, error] -+ * The priority of a subflow has changed. 'error' should not be set. - */ - enum mptcp_event_type { - MPTCP_EVENT_UNSPEC = 0, -diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h -index e709ae8235e7f..ff6ccbc6efe96 100644 ---- a/include/uapi/linux/pci_regs.h -+++ b/include/uapi/linux/pci_regs.h -@@ -504,6 +504,12 @@ - #define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ - #define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ - #define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ -+#define PCI_EXP_DEVCTL_PAYLOAD_128B 0x0000 /* 128 Bytes */ -+#define PCI_EXP_DEVCTL_PAYLOAD_256B 0x0020 /* 256 Bytes */ -+#define PCI_EXP_DEVCTL_PAYLOAD_512B 0x0040 /* 512 Bytes */ -+#define PCI_EXP_DEVCTL_PAYLOAD_1024B 0x0060 /* 1024 Bytes */ -+#define PCI_EXP_DEVCTL_PAYLOAD_2048B 0x0080 /* 2048 Bytes */ -+#define PCI_EXP_DEVCTL_PAYLOAD_4096B 0x00a0 /* 4096 Bytes */ - #define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ - #define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ - #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ -diff --git a/include/xen/events.h b/include/xen/events.h -index c204262d9fc24..344081e71584b 100644 ---- a/include/xen/events.h -+++ b/include/xen/events.h -@@ -17,6 +17,7 @@ struct xenbus_device; - unsigned xen_evtchn_nr_channels(void); - - int bind_evtchn_to_irq(evtchn_port_t evtchn); -+int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn); - int bind_evtchn_to_irqhandler(evtchn_port_t evtchn, - irq_handler_t handler, - unsigned long irqflags, const char *devname, -diff --git a/init/main.c b/init/main.c -index 3c4054a955458..bcd132d4e7bdd 100644 ---- a/init/main.c -+++ b/init/main.c -@@ -924,7 +924,9 @@ static void __init print_unknown_bootoptions(void) - for (p = &envp_init[2]; *p; p++) - end += sprintf(end, " %s", *p); - -- pr_notice("Unknown command line parameters:%s\n", unknown_options); -+ /* Start at unknown_options[1] to skip the initial space */ -+ pr_notice("Unknown kernel command line parameters \"%s\", will be passed to user space.\n", -+ &unknown_options[1]); - memblock_free_ptr(unknown_options, len); - } - -diff --git a/ipc/shm.c b/ipc/shm.c -index ab749be6d8b71..048eb183b24b9 100644 ---- a/ipc/shm.c -+++ b/ipc/shm.c -@@ -62,9 +62,18 @@ struct shmid_kernel /* private to the kernel */ - struct pid *shm_lprid; - struct ucounts *mlock_ucounts; - -- /* The task created the shm object. NULL if the task is dead. */ -+ /* -+ * The task created the shm object, for -+ * task_lock(shp->shm_creator) -+ */ - struct task_struct *shm_creator; -- struct list_head shm_clist; /* list by creator */ -+ -+ /* -+ * List by creator. task_lock(->shm_creator) required for read/write. -+ * If list_empty(), then the creator is dead already. -+ */ -+ struct list_head shm_clist; -+ struct ipc_namespace *ns; - } __randomize_layout; - - /* shm_mode upper byte flags */ -@@ -115,6 +124,7 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) - struct shmid_kernel *shp; - - shp = container_of(ipcp, struct shmid_kernel, shm_perm); -+ WARN_ON(ns != shp->ns); - - if (shp->shm_nattch) { - shp->shm_perm.mode |= SHM_DEST; -@@ -225,10 +235,43 @@ static void shm_rcu_free(struct rcu_head *head) - kfree(shp); - } - --static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) -+/* -+ * It has to be called with shp locked. -+ * It must be called before ipc_rmid() -+ */ -+static inline void shm_clist_rm(struct shmid_kernel *shp) - { -- list_del(&s->shm_clist); -- ipc_rmid(&shm_ids(ns), &s->shm_perm); -+ struct task_struct *creator; -+ -+ /* ensure that shm_creator does not disappear */ -+ rcu_read_lock(); -+ -+ /* -+ * A concurrent exit_shm may do a list_del_init() as well. -+ * Just do nothing if exit_shm already did the work -+ */ -+ if (!list_empty(&shp->shm_clist)) { -+ /* -+ * shp->shm_creator is guaranteed to be valid *only* -+ * if shp->shm_clist is not empty. -+ */ -+ creator = shp->shm_creator; -+ -+ task_lock(creator); -+ /* -+ * list_del_init() is a nop if the entry was already removed -+ * from the list. -+ */ -+ list_del_init(&shp->shm_clist); -+ task_unlock(creator); -+ } -+ rcu_read_unlock(); -+} -+ -+static inline void shm_rmid(struct shmid_kernel *s) -+{ -+ shm_clist_rm(s); -+ ipc_rmid(&shm_ids(s->ns), &s->shm_perm); - } - - -@@ -283,7 +326,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) - shm_file = shp->shm_file; - shp->shm_file = NULL; - ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; -- shm_rmid(ns, shp); -+ shm_rmid(shp); - shm_unlock(shp); - if (!is_file_hugepages(shm_file)) - shmem_lock(shm_file, 0, shp->mlock_ucounts); -@@ -306,10 +349,10 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) - * - * 2) sysctl kernel.shm_rmid_forced is set to 1. - */ --static bool shm_may_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) -+static bool shm_may_destroy(struct shmid_kernel *shp) - { - return (shp->shm_nattch == 0) && -- (ns->shm_rmid_forced || -+ (shp->ns->shm_rmid_forced || - (shp->shm_perm.mode & SHM_DEST)); - } - -@@ -340,7 +383,7 @@ static void shm_close(struct vm_area_struct *vma) - ipc_update_pid(&shp->shm_lprid, task_tgid(current)); - shp->shm_dtim = ktime_get_real_seconds(); - shp->shm_nattch--; -- if (shm_may_destroy(ns, shp)) -+ if (shm_may_destroy(shp)) - shm_destroy(ns, shp); - else - shm_unlock(shp); -@@ -361,10 +404,10 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data) - * - * As shp->* are changed under rwsem, it's safe to skip shp locking. - */ -- if (shp->shm_creator != NULL) -+ if (!list_empty(&shp->shm_clist)) - return 0; - -- if (shm_may_destroy(ns, shp)) { -+ if (shm_may_destroy(shp)) { - shm_lock_by_ptr(shp); - shm_destroy(ns, shp); - } -@@ -382,48 +425,97 @@ void shm_destroy_orphaned(struct ipc_namespace *ns) - /* Locking assumes this will only be called with task == current */ - void exit_shm(struct task_struct *task) - { -- struct ipc_namespace *ns = task->nsproxy->ipc_ns; -- struct shmid_kernel *shp, *n; -+ for (;;) { -+ struct shmid_kernel *shp; -+ struct ipc_namespace *ns; - -- if (list_empty(&task->sysvshm.shm_clist)) -- return; -+ task_lock(task); -+ -+ if (list_empty(&task->sysvshm.shm_clist)) { -+ task_unlock(task); -+ break; -+ } -+ -+ shp = list_first_entry(&task->sysvshm.shm_clist, struct shmid_kernel, -+ shm_clist); - -- /* -- * If kernel.shm_rmid_forced is not set then only keep track of -- * which shmids are orphaned, so that a later set of the sysctl -- * can clean them up. -- */ -- if (!ns->shm_rmid_forced) { -- down_read(&shm_ids(ns).rwsem); -- list_for_each_entry(shp, &task->sysvshm.shm_clist, shm_clist) -- shp->shm_creator = NULL; - /* -- * Only under read lock but we are only called on current -- * so no entry on the list will be shared. -+ * 1) Get pointer to the ipc namespace. It is worth to say -+ * that this pointer is guaranteed to be valid because -+ * shp lifetime is always shorter than namespace lifetime -+ * in which shp lives. -+ * We taken task_lock it means that shp won't be freed. - */ -- list_del(&task->sysvshm.shm_clist); -- up_read(&shm_ids(ns).rwsem); -- return; -- } -+ ns = shp->ns; - -- /* -- * Destroy all already created segments, that were not yet mapped, -- * and mark any mapped as orphan to cover the sysctl toggling. -- * Destroy is skipped if shm_may_destroy() returns false. -- */ -- down_write(&shm_ids(ns).rwsem); -- list_for_each_entry_safe(shp, n, &task->sysvshm.shm_clist, shm_clist) { -- shp->shm_creator = NULL; -+ /* -+ * 2) If kernel.shm_rmid_forced is not set then only keep track of -+ * which shmids are orphaned, so that a later set of the sysctl -+ * can clean them up. -+ */ -+ if (!ns->shm_rmid_forced) -+ goto unlink_continue; - -- if (shm_may_destroy(ns, shp)) { -- shm_lock_by_ptr(shp); -- shm_destroy(ns, shp); -+ /* -+ * 3) get a reference to the namespace. -+ * The refcount could be already 0. If it is 0, then -+ * the shm objects will be free by free_ipc_work(). -+ */ -+ ns = get_ipc_ns_not_zero(ns); -+ if (!ns) { -+unlink_continue: -+ list_del_init(&shp->shm_clist); -+ task_unlock(task); -+ continue; - } -- } - -- /* Remove the list head from any segments still attached. */ -- list_del(&task->sysvshm.shm_clist); -- up_write(&shm_ids(ns).rwsem); -+ /* -+ * 4) get a reference to shp. -+ * This cannot fail: shm_clist_rm() is called before -+ * ipc_rmid(), thus the refcount cannot be 0. -+ */ -+ WARN_ON(!ipc_rcu_getref(&shp->shm_perm)); -+ -+ /* -+ * 5) unlink the shm segment from the list of segments -+ * created by current. -+ * This must be done last. After unlinking, -+ * only the refcounts obtained above prevent IPC_RMID -+ * from destroying the segment or the namespace. -+ */ -+ list_del_init(&shp->shm_clist); -+ -+ task_unlock(task); -+ -+ /* -+ * 6) we have all references -+ * Thus lock & if needed destroy shp. -+ */ -+ down_write(&shm_ids(ns).rwsem); -+ shm_lock_by_ptr(shp); -+ /* -+ * rcu_read_lock was implicitly taken in shm_lock_by_ptr, it's -+ * safe to call ipc_rcu_putref here -+ */ -+ ipc_rcu_putref(&shp->shm_perm, shm_rcu_free); -+ -+ if (ipc_valid_object(&shp->shm_perm)) { -+ if (shm_may_destroy(shp)) -+ shm_destroy(ns, shp); -+ else -+ shm_unlock(shp); -+ } else { -+ /* -+ * Someone else deleted the shp from namespace -+ * idr/kht while we have waited. -+ * Just unlock and continue. -+ */ -+ shm_unlock(shp); -+ } -+ -+ up_write(&shm_ids(ns).rwsem); -+ put_ipc_ns(ns); /* paired with get_ipc_ns_not_zero */ -+ } - } - - static vm_fault_t shm_fault(struct vm_fault *vmf) -@@ -680,7 +772,11 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) - if (error < 0) - goto no_id; - -+ shp->ns = ns; -+ -+ task_lock(current); - list_add(&shp->shm_clist, ¤t->sysvshm.shm_clist); -+ task_unlock(current); - - /* - * shmid gets reported as "inode#" in /proc/pid/maps. -@@ -1573,7 +1669,8 @@ out_nattch: - down_write(&shm_ids(ns).rwsem); - shp = shm_lock(ns, shmid); - shp->shm_nattch--; -- if (shm_may_destroy(ns, shp)) -+ -+ if (shm_may_destroy(shp)) - shm_destroy(ns, shp); - else - shm_unlock(shp); -diff --git a/ipc/util.c b/ipc/util.c -index d48d8cfa1f3fa..fa2d86ef3fb80 100644 ---- a/ipc/util.c -+++ b/ipc/util.c -@@ -447,8 +447,8 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, - static void ipc_kht_remove(struct ipc_ids *ids, struct kern_ipc_perm *ipcp) - { - if (ipcp->key != IPC_PRIVATE) -- rhashtable_remove_fast(&ids->key_ht, &ipcp->khtnode, -- ipc_kht_params); -+ WARN_ON_ONCE(rhashtable_remove_fast(&ids->key_ht, &ipcp->khtnode, -+ ipc_kht_params)); - } - - /** -@@ -498,7 +498,7 @@ void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp) - { - int idx = ipcid_to_idx(ipcp->id); - -- idr_remove(&ids->ipcs_idr, idx); -+ WARN_ON_ONCE(idr_remove(&ids->ipcs_idr, idx) != ipcp); - ipc_kht_remove(ids, ipcp); - ids->in_use--; - ipcp->deleted = true; -diff --git a/kernel/audit.c b/kernel/audit.c -index 121d37e700a62..4cebadb5f30db 100644 ---- a/kernel/audit.c -+++ b/kernel/audit.c -@@ -718,7 +718,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, - { - int rc = 0; - struct sk_buff *skb; -- static unsigned int failed = 0; -+ unsigned int failed = 0; - - /* NOTE: kauditd_thread takes care of all our locking, we just use - * the netlink info passed to us (e.g. sk and portid) */ -@@ -735,32 +735,30 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, - continue; - } - -+retry: - /* grab an extra skb reference in case of error */ - skb_get(skb); - rc = netlink_unicast(sk, skb, portid, 0); - if (rc < 0) { -- /* fatal failure for our queue flush attempt? */ -+ /* send failed - try a few times unless fatal error */ - if (++failed >= retry_limit || - rc == -ECONNREFUSED || rc == -EPERM) { -- /* yes - error processing for the queue */ - sk = NULL; - if (err_hook) - (*err_hook)(skb); -- if (!skb_hook) -- goto out; -- /* keep processing with the skb_hook */ -+ if (rc == -EAGAIN) -+ rc = 0; -+ /* continue to drain the queue */ - continue; - } else -- /* no - requeue to preserve ordering */ -- skb_queue_head(queue, skb); -+ goto retry; - } else { -- /* it worked - drop the extra reference and continue */ -+ /* skb sent - drop the extra reference and continue */ - consume_skb(skb); - failed = 0; - } - } - --out: - return (rc >= 0 ? 0 : rc); - } - -@@ -1609,7 +1607,8 @@ static int __net_init audit_net_init(struct net *net) - audit_panic("cannot initialize netlink socket in namespace"); - return -ENOMEM; - } -- aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; -+ /* limit the timeout in case auditd is blocked/stopped */ -+ aunet->sk->sk_sndtimeo = HZ / 10; - - return 0; - } -diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c -index 03145d45e3d5b..7dbd68195a2b0 100644 ---- a/kernel/bpf/cgroup.c -+++ b/kernel/bpf/cgroup.c -@@ -1773,6 +1773,8 @@ sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) - return &bpf_sysctl_get_new_value_proto; - case BPF_FUNC_sysctl_set_new_value: - return &bpf_sysctl_set_new_value_proto; -+ case BPF_FUNC_ktime_get_coarse_ns: -+ return &bpf_ktime_get_coarse_ns_proto; - default: - return cgroup_base_func_proto(func_id, prog); - } -diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c -index 9aabf84afd4b2..6f600cc95ccda 100644 ---- a/kernel/bpf/helpers.c -+++ b/kernel/bpf/helpers.c -@@ -1367,8 +1367,6 @@ bpf_base_func_proto(enum bpf_func_id func_id) - return &bpf_ktime_get_ns_proto; - case BPF_FUNC_ktime_get_boot_ns: - return &bpf_ktime_get_boot_ns_proto; -- case BPF_FUNC_ktime_get_coarse_ns: -- return &bpf_ktime_get_coarse_ns_proto; - case BPF_FUNC_ringbuf_output: - return &bpf_ringbuf_output_proto; - case BPF_FUNC_ringbuf_reserve: -diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c -index 1cad6979a0d0f..ecd51a8a8680c 100644 ---- a/kernel/bpf/syscall.c -+++ b/kernel/bpf/syscall.c -@@ -132,6 +132,21 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) - return map; - } - -+static void bpf_map_write_active_inc(struct bpf_map *map) -+{ -+ atomic64_inc(&map->writecnt); -+} -+ -+static void bpf_map_write_active_dec(struct bpf_map *map) -+{ -+ atomic64_dec(&map->writecnt); -+} -+ -+bool bpf_map_write_active(const struct bpf_map *map) -+{ -+ return atomic64_read(&map->writecnt) != 0; -+} -+ - static u32 bpf_map_value_size(const struct bpf_map *map) - { - if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || -@@ -596,11 +611,8 @@ static void bpf_map_mmap_open(struct vm_area_struct *vma) - { - struct bpf_map *map = vma->vm_file->private_data; - -- if (vma->vm_flags & VM_MAYWRITE) { -- mutex_lock(&map->freeze_mutex); -- map->writecnt++; -- mutex_unlock(&map->freeze_mutex); -- } -+ if (vma->vm_flags & VM_MAYWRITE) -+ bpf_map_write_active_inc(map); - } - - /* called for all unmapped memory region (including initial) */ -@@ -608,11 +620,8 @@ static void bpf_map_mmap_close(struct vm_area_struct *vma) - { - struct bpf_map *map = vma->vm_file->private_data; - -- if (vma->vm_flags & VM_MAYWRITE) { -- mutex_lock(&map->freeze_mutex); -- map->writecnt--; -- mutex_unlock(&map->freeze_mutex); -- } -+ if (vma->vm_flags & VM_MAYWRITE) -+ bpf_map_write_active_dec(map); - } - - static const struct vm_operations_struct bpf_map_default_vmops = { -@@ -663,7 +672,7 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) - goto out; - - if (vma->vm_flags & VM_MAYWRITE) -- map->writecnt++; -+ bpf_map_write_active_inc(map); - out: - mutex_unlock(&map->freeze_mutex); - return err; -@@ -1122,6 +1131,7 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr) - map = __bpf_map_get(f); - if (IS_ERR(map)) - return PTR_ERR(map); -+ bpf_map_write_active_inc(map); - if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { - err = -EPERM; - goto err_put; -@@ -1157,6 +1167,7 @@ free_value: - free_key: - kvfree(key); - err_put: -+ bpf_map_write_active_dec(map); - fdput(f); - return err; - } -@@ -1179,6 +1190,7 @@ static int map_delete_elem(union bpf_attr *attr) - map = __bpf_map_get(f); - if (IS_ERR(map)) - return PTR_ERR(map); -+ bpf_map_write_active_inc(map); - if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { - err = -EPERM; - goto err_put; -@@ -1209,6 +1221,7 @@ static int map_delete_elem(union bpf_attr *attr) - out: - kvfree(key); - err_put: -+ bpf_map_write_active_dec(map); - fdput(f); - return err; - } -@@ -1516,6 +1529,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr) - map = __bpf_map_get(f); - if (IS_ERR(map)) - return PTR_ERR(map); -+ bpf_map_write_active_inc(map); - if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) || - !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { - err = -EPERM; -@@ -1580,6 +1594,7 @@ free_value: - free_key: - kvfree(key); - err_put: -+ bpf_map_write_active_dec(map); - fdput(f); - return err; - } -@@ -1607,8 +1622,7 @@ static int map_freeze(const union bpf_attr *attr) - } - - mutex_lock(&map->freeze_mutex); -- -- if (map->writecnt) { -+ if (bpf_map_write_active(map)) { - err = -EBUSY; - goto err_put; - } -@@ -4143,6 +4157,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr, - union bpf_attr __user *uattr, - int cmd) - { -+ bool has_read = cmd == BPF_MAP_LOOKUP_BATCH || -+ cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH; -+ bool has_write = cmd != BPF_MAP_LOOKUP_BATCH; - struct bpf_map *map; - int err, ufd; - struct fd f; -@@ -4155,16 +4172,13 @@ static int bpf_map_do_batch(const union bpf_attr *attr, - map = __bpf_map_get(f); - if (IS_ERR(map)) - return PTR_ERR(map); -- -- if ((cmd == BPF_MAP_LOOKUP_BATCH || -- cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH) && -- !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { -+ if (has_write) -+ bpf_map_write_active_inc(map); -+ if (has_read && !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { - err = -EPERM; - goto err_put; - } -- -- if (cmd != BPF_MAP_LOOKUP_BATCH && -- !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { -+ if (has_write && !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { - err = -EPERM; - goto err_put; - } -@@ -4177,8 +4191,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr, - BPF_DO_BATCH(map->ops->map_update_batch); - else - BPF_DO_BATCH(map->ops->map_delete_batch); -- - err_put: -+ if (has_write) -+ bpf_map_write_active_dec(map); - fdput(f); - return err; - } -diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c -index fe1e857324e66..d3a307a8c42b9 100644 ---- a/kernel/bpf/trampoline.c -+++ b/kernel/bpf/trampoline.c -@@ -585,11 +585,13 @@ static void notrace update_prog_stats(struct bpf_prog *prog, - * Hence check that 'start' is valid. - */ - start > NO_START_TIME) { -+ unsigned long flags; -+ - stats = this_cpu_ptr(prog->stats); -- u64_stats_update_begin(&stats->syncp); -+ flags = u64_stats_update_begin_irqsave(&stats->syncp); - stats->cnt++; - stats->nsecs += sched_clock() - start; -- u64_stats_update_end(&stats->syncp); -+ u64_stats_update_end_irqrestore(&stats->syncp, flags); - } - } - -diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c -index e76b559179054..93c3a332e8536 100644 ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -1143,7 +1143,8 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg) - /* transfer reg's id which is unique for every map_lookup_elem - * as UID of the inner map. - */ -- reg->map_uid = reg->id; -+ if (map_value_has_timer(map->inner_map_meta)) -+ reg->map_uid = reg->id; - } else if (map->map_type == BPF_MAP_TYPE_XSKMAP) { - reg->type = PTR_TO_XDP_SOCK; - } else if (map->map_type == BPF_MAP_TYPE_SOCKMAP || -@@ -1357,22 +1358,28 @@ static void __reg_bound_offset(struct bpf_reg_state *reg) - reg->var_off = tnum_or(tnum_clear_subreg(var64_off), var32_off); - } - -+static bool __reg32_bound_s64(s32 a) -+{ -+ return a >= 0 && a <= S32_MAX; -+} -+ - static void __reg_assign_32_into_64(struct bpf_reg_state *reg) - { - reg->umin_value = reg->u32_min_value; - reg->umax_value = reg->u32_max_value; -- /* Attempt to pull 32-bit signed bounds into 64-bit bounds -- * but must be positive otherwise set to worse case bounds -- * and refine later from tnum. -+ -+ /* Attempt to pull 32-bit signed bounds into 64-bit bounds but must -+ * be positive otherwise set to worse case bounds and refine later -+ * from tnum. - */ -- if (reg->s32_min_value >= 0 && reg->s32_max_value >= 0) -- reg->smax_value = reg->s32_max_value; -- else -- reg->smax_value = U32_MAX; -- if (reg->s32_min_value >= 0) -+ if (__reg32_bound_s64(reg->s32_min_value) && -+ __reg32_bound_s64(reg->s32_max_value)) { - reg->smin_value = reg->s32_min_value; -- else -+ reg->smax_value = reg->s32_max_value; -+ } else { - reg->smin_value = 0; -+ reg->smax_value = U32_MAX; -+ } - } - - static void __reg_combine_32_into_64(struct bpf_reg_state *reg) -@@ -1406,12 +1413,12 @@ static void __reg_combine_32_into_64(struct bpf_reg_state *reg) - - static bool __reg64_bound_s32(s64 a) - { -- return a > S32_MIN && a < S32_MAX; -+ return a >= S32_MIN && a <= S32_MAX; - } - - static bool __reg64_bound_u32(u64 a) - { -- return a > U32_MIN && a < U32_MAX; -+ return a >= U32_MIN && a <= U32_MAX; - } - - static void __reg_combine_64_into_32(struct bpf_reg_state *reg) -@@ -3884,7 +3891,22 @@ static void coerce_reg_to_size(struct bpf_reg_state *reg, int size) - - static bool bpf_map_is_rdonly(const struct bpf_map *map) - { -- return (map->map_flags & BPF_F_RDONLY_PROG) && map->frozen; -+ /* A map is considered read-only if the following condition are true: -+ * -+ * 1) BPF program side cannot change any of the map content. The -+ * BPF_F_RDONLY_PROG flag is throughout the lifetime of a map -+ * and was set at map creation time. -+ * 2) The map value(s) have been initialized from user space by a -+ * loader and then "frozen", such that no new map update/delete -+ * operations from syscall side are possible for the rest of -+ * the map's lifetime from that point onwards. -+ * 3) Any parallel/pending map update/delete operations from syscall -+ * side have been completed. Only after that point, it's safe to -+ * assume that map value(s) are immutable. -+ */ -+ return (map->map_flags & BPF_F_RDONLY_PROG) && -+ READ_ONCE(map->frozen) && -+ !bpf_map_write_active(map); - } - - static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val) -@@ -4364,9 +4386,16 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i - - if (insn->imm == BPF_CMPXCHG) { - /* Check comparison of R0 with memory location */ -- err = check_reg_arg(env, BPF_REG_0, SRC_OP); -+ const u32 aux_reg = BPF_REG_0; -+ -+ err = check_reg_arg(env, aux_reg, SRC_OP); - if (err) - return err; -+ -+ if (is_pointer_value(env, aux_reg)) { -+ verbose(env, "R%d leaks addr into mem\n", aux_reg); -+ return -EACCES; -+ } - } - - if (is_pointer_value(env, insn->src_reg)) { -@@ -4401,13 +4430,19 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i - load_reg = -1; - } - -- /* check whether we can read the memory */ -+ /* Check whether we can read the memory, with second call for fetch -+ * case to simulate the register fill. -+ */ - err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, -- BPF_SIZE(insn->code), BPF_READ, load_reg, true); -+ BPF_SIZE(insn->code), BPF_READ, -1, true); -+ if (!err && load_reg >= 0) -+ err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, -+ BPF_SIZE(insn->code), BPF_READ, load_reg, -+ true); - if (err) - return err; - -- /* check whether we can write into the same memory */ -+ /* Check whether we can write into the same memory. */ - err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, - BPF_SIZE(insn->code), BPF_WRITE, -1, true); - if (err) -@@ -8098,6 +8133,10 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) - insn->dst_reg); - } - zext_32_to_64(dst_reg); -+ -+ __update_reg_bounds(dst_reg); -+ __reg_deduce_bounds(dst_reg); -+ __reg_bound_offset(dst_reg); - } - } else { - /* case: R = imm -@@ -8212,7 +8251,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate, - - new_range = dst_reg->off; - if (range_right_open) -- new_range--; -+ new_range++; - - /* Examples for register markings: - * -@@ -11435,6 +11474,13 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env, - } - } - -+ if (map_value_has_timer(map)) { -+ if (is_tracing_prog_type(prog_type)) { -+ verbose(env, "tracing progs cannot use bpf_timer yet\n"); -+ return -EINVAL; -+ } -+ } -+ - if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) && - !bpf_offload_prog_map_match(prog, map)) { - verbose(env, "offload device mismatch between prog and map\n"); -diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c -index ea08f01d0111a..d6ea872b23aad 100644 ---- a/kernel/cgroup/cgroup.c -+++ b/kernel/cgroup/cgroup.c -@@ -1740,6 +1740,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) - struct cgroup *dcgrp = &dst_root->cgrp; - struct cgroup_subsys *ss; - int ssid, i, ret; -+ u16 dfl_disable_ss_mask = 0; - - lockdep_assert_held(&cgroup_mutex); - -@@ -1756,8 +1757,28 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) - /* can't move between two non-dummy roots either */ - if (ss->root != &cgrp_dfl_root && dst_root != &cgrp_dfl_root) - return -EBUSY; -+ -+ /* -+ * Collect ssid's that need to be disabled from default -+ * hierarchy. -+ */ -+ if (ss->root == &cgrp_dfl_root) -+ dfl_disable_ss_mask |= 1 << ssid; -+ - } while_each_subsys_mask(); - -+ if (dfl_disable_ss_mask) { -+ struct cgroup *scgrp = &cgrp_dfl_root.cgrp; -+ -+ /* -+ * Controllers from default hierarchy that need to be rebound -+ * are all disabled together in one go. -+ */ -+ cgrp_dfl_root.subsys_mask &= ~dfl_disable_ss_mask; -+ WARN_ON(cgroup_apply_control(scgrp)); -+ cgroup_finalize_control(scgrp, 0); -+ } -+ - do_each_subsys_mask(ss, ssid, ss_mask) { - struct cgroup_root *src_root = ss->root; - struct cgroup *scgrp = &src_root->cgrp; -@@ -1766,10 +1787,12 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) - - WARN_ON(!css || cgroup_css(dcgrp, ss)); - -- /* disable from the source */ -- src_root->subsys_mask &= ~(1 << ssid); -- WARN_ON(cgroup_apply_control(scgrp)); -- cgroup_finalize_control(scgrp, 0); -+ if (src_root != &cgrp_dfl_root) { -+ /* disable from the source */ -+ src_root->subsys_mask &= ~(1 << ssid); -+ WARN_ON(cgroup_apply_control(scgrp)); -+ cgroup_finalize_control(scgrp, 0); -+ } - - /* rebind */ - RCU_INIT_POINTER(scgrp->subsys[ssid], NULL); -diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c -index b264ab5652ba9..1486768f23185 100644 ---- a/kernel/cgroup/rstat.c -+++ b/kernel/cgroup/rstat.c -@@ -433,8 +433,6 @@ static void root_cgroup_cputime(struct task_cputime *cputime) - cputime->sum_exec_runtime += user; - cputime->sum_exec_runtime += sys; - cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL]; -- cputime->sum_exec_runtime += cpustat[CPUTIME_GUEST]; -- cputime->sum_exec_runtime += cpustat[CPUTIME_GUEST_NICE]; - } - } - -diff --git a/kernel/cpu.c b/kernel/cpu.c -index 192e43a874076..407a2568f35eb 100644 ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -31,6 +31,7 @@ - #include <linux/smpboot.h> - #include <linux/relay.h> - #include <linux/slab.h> -+#include <linux/scs.h> - #include <linux/percpu-rwsem.h> - #include <linux/cpuset.h> - -@@ -587,6 +588,12 @@ static int bringup_cpu(unsigned int cpu) - struct task_struct *idle = idle_thread_get(cpu); - int ret; - -+ /* -+ * Reset stale stack state from the last time this CPU was online. -+ */ -+ scs_task_reset(idle); -+ kasan_unpoison_task_stack(idle); -+ - /* - * Some architectures have to walk the irq descriptors to - * setup the vector space for the cpu which comes online. -diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c -index 1f9f0e47aedaa..10b454554ab03 100644 ---- a/kernel/debug/kdb/kdb_bt.c -+++ b/kernel/debug/kdb/kdb_bt.c -@@ -46,7 +46,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr) - * btp <pid> Kernel stack for <pid> - * btt <address-expression> Kernel stack for task structure at - * <address-expression> -- * bta [DRSTCZEUIMA] All useful processes, optionally -+ * bta [state_chars>|A] All useful processes, optionally - * filtered by state - * btc [<cpu>] The current process on one cpu, - * default is all cpus -@@ -74,7 +74,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr) - */ - - static int --kdb_bt1(struct task_struct *p, unsigned long mask, bool btaprompt) -+kdb_bt1(struct task_struct *p, const char *mask, bool btaprompt) - { - char ch; - -@@ -120,7 +120,7 @@ kdb_bt_cpu(unsigned long cpu) - return; - } - -- kdb_bt1(kdb_tsk, ~0UL, false); -+ kdb_bt1(kdb_tsk, "A", false); - } - - int -@@ -138,8 +138,8 @@ kdb_bt(int argc, const char **argv) - if (strcmp(argv[0], "bta") == 0) { - struct task_struct *g, *p; - unsigned long cpu; -- unsigned long mask = kdb_task_state_string(argc ? argv[1] : -- NULL); -+ const char *mask = argc ? argv[1] : kdbgetenv("PS"); -+ - if (argc == 0) - kdb_ps_suppressed(); - /* Run the active tasks first */ -@@ -167,7 +167,7 @@ kdb_bt(int argc, const char **argv) - return diag; - p = find_task_by_pid_ns(pid, &init_pid_ns); - if (p) -- return kdb_bt1(p, ~0UL, false); -+ return kdb_bt1(p, "A", false); - kdb_printf("No process with pid == %ld found\n", pid); - return 0; - } else if (strcmp(argv[0], "btt") == 0) { -@@ -176,7 +176,7 @@ kdb_bt(int argc, const char **argv) - diag = kdbgetularg((char *)argv[1], &addr); - if (diag) - return diag; -- return kdb_bt1((struct task_struct *)addr, ~0UL, false); -+ return kdb_bt1((struct task_struct *)addr, "A", false); - } else if (strcmp(argv[0], "btc") == 0) { - unsigned long cpu = ~0; - if (argc > 1) -@@ -212,7 +212,7 @@ kdb_bt(int argc, const char **argv) - kdb_show_stack(kdb_current_task, (void *)addr); - return 0; - } else { -- return kdb_bt1(kdb_current_task, ~0UL, false); -+ return kdb_bt1(kdb_current_task, "A", false); - } - } - -diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c -index fa6deda894a17..0852a537dad4c 100644 ---- a/kernel/debug/kdb/kdb_main.c -+++ b/kernel/debug/kdb/kdb_main.c -@@ -2203,8 +2203,8 @@ static void kdb_cpu_status(void) - state = 'D'; /* cpu is online but unresponsive */ - } else { - state = ' '; /* cpu is responding to kdb */ -- if (kdb_task_state_char(KDB_TSK(i)) == 'I') -- state = 'I'; /* idle task */ -+ if (kdb_task_state_char(KDB_TSK(i)) == '-') -+ state = '-'; /* idle task */ - } - if (state != prev_state) { - if (prev_state != '?') { -@@ -2271,37 +2271,30 @@ static int kdb_cpu(int argc, const char **argv) - void kdb_ps_suppressed(void) - { - int idle = 0, daemon = 0; -- unsigned long mask_I = kdb_task_state_string("I"), -- mask_M = kdb_task_state_string("M"); - unsigned long cpu; - const struct task_struct *p, *g; - for_each_online_cpu(cpu) { - p = kdb_curr_task(cpu); -- if (kdb_task_state(p, mask_I)) -+ if (kdb_task_state(p, "-")) - ++idle; - } - for_each_process_thread(g, p) { -- if (kdb_task_state(p, mask_M)) -+ if (kdb_task_state(p, "ims")) - ++daemon; - } - if (idle || daemon) { - if (idle) -- kdb_printf("%d idle process%s (state I)%s\n", -+ kdb_printf("%d idle process%s (state -)%s\n", - idle, idle == 1 ? "" : "es", - daemon ? " and " : ""); - if (daemon) -- kdb_printf("%d sleeping system daemon (state M) " -+ kdb_printf("%d sleeping system daemon (state [ims]) " - "process%s", daemon, - daemon == 1 ? "" : "es"); - kdb_printf(" suppressed,\nuse 'ps A' to see all.\n"); - } - } - --/* -- * kdb_ps - This function implements the 'ps' command which shows a -- * list of the active processes. -- * ps [DRSTCZEUIMA] All processes, optionally filtered by state -- */ - void kdb_ps1(const struct task_struct *p) - { - int cpu; -@@ -2330,17 +2323,25 @@ void kdb_ps1(const struct task_struct *p) - } - } - -+/* -+ * kdb_ps - This function implements the 'ps' command which shows a -+ * list of the active processes. -+ * -+ * ps [<state_chars>] Show processes, optionally selecting only those whose -+ * state character is found in <state_chars>. -+ */ - static int kdb_ps(int argc, const char **argv) - { - struct task_struct *g, *p; -- unsigned long mask, cpu; -+ const char *mask; -+ unsigned long cpu; - - if (argc == 0) - kdb_ps_suppressed(); - kdb_printf("%-*s Pid Parent [*] cpu State %-*s Command\n", - (int)(2*sizeof(void *))+2, "Task Addr", - (int)(2*sizeof(void *))+2, "Thread"); -- mask = kdb_task_state_string(argc ? argv[1] : NULL); -+ mask = argc ? argv[1] : kdbgetenv("PS"); - /* Run the active tasks first */ - for_each_online_cpu(cpu) { - if (KDB_FLAG(CMD_INTERRUPT)) -@@ -2742,8 +2743,8 @@ static kdbtab_t maintab[] = { - }, - { .name = "bta", - .func = kdb_bt, -- .usage = "[D|R|S|T|C|Z|E|U|I|M|A]", -- .help = "Backtrace all processes matching state flag", -+ .usage = "[<state_chars>|A]", -+ .help = "Backtrace all processes whose state matches", - .flags = KDB_ENABLE_INSPECT, - }, - { .name = "btc", -@@ -2797,7 +2798,7 @@ static kdbtab_t maintab[] = { - }, - { .name = "ps", - .func = kdb_ps, -- .usage = "[<flags>|A]", -+ .usage = "[<state_chars>|A]", - .help = "Display active task list", - .flags = KDB_ENABLE_INSPECT, - }, -diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h -index 629590084a0dc..0d2f9feea0a46 100644 ---- a/kernel/debug/kdb/kdb_private.h -+++ b/kernel/debug/kdb/kdb_private.h -@@ -190,10 +190,8 @@ extern char kdb_grep_string[]; - extern int kdb_grep_leading; - extern int kdb_grep_trailing; - extern char *kdb_cmds[]; --extern unsigned long kdb_task_state_string(const char *); - extern char kdb_task_state_char (const struct task_struct *); --extern unsigned long kdb_task_state(const struct task_struct *p, -- unsigned long mask); -+extern bool kdb_task_state(const struct task_struct *p, const char *mask); - extern void kdb_ps_suppressed(void); - extern void kdb_ps1(const struct task_struct *p); - extern void kdb_send_sig(struct task_struct *p, int sig); -diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c -index 7507d9a8dc6ac..df2bface866ef 100644 ---- a/kernel/debug/kdb/kdb_support.c -+++ b/kernel/debug/kdb/kdb_support.c -@@ -24,6 +24,7 @@ - #include <linux/uaccess.h> - #include <linux/kdb.h> - #include <linux/slab.h> -+#include <linux/ctype.h> - #include "kdb_private.h" - - /* -@@ -473,82 +474,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size) - return diag; - } - --/* -- * kdb_task_state_string - Convert a string containing any of the -- * letters DRSTCZEUIMA to a mask for the process state field and -- * return the value. If no argument is supplied, return the mask -- * that corresponds to environment variable PS, DRSTCZEU by -- * default. -- * Inputs: -- * s String to convert -- * Returns: -- * Mask for process state. -- * Notes: -- * The mask folds data from several sources into a single long value, so -- * be careful not to overlap the bits. TASK_* bits are in the LSB, -- * special cases like UNRUNNABLE are in the MSB. As of 2.6.10-rc1 there -- * is no overlap between TASK_* and EXIT_* but that may not always be -- * true, so EXIT_* bits are shifted left 16 bits before being stored in -- * the mask. -- */ -- --/* unrunnable is < 0 */ --#define UNRUNNABLE (1UL << (8*sizeof(unsigned long) - 1)) --#define RUNNING (1UL << (8*sizeof(unsigned long) - 2)) --#define IDLE (1UL << (8*sizeof(unsigned long) - 3)) --#define DAEMON (1UL << (8*sizeof(unsigned long) - 4)) - --unsigned long kdb_task_state_string(const char *s) --{ -- long res = 0; -- if (!s) { -- s = kdbgetenv("PS"); -- if (!s) -- s = "DRSTCZEU"; /* default value for ps */ -- } -- while (*s) { -- switch (*s) { -- case 'D': -- res |= TASK_UNINTERRUPTIBLE; -- break; -- case 'R': -- res |= RUNNING; -- break; -- case 'S': -- res |= TASK_INTERRUPTIBLE; -- break; -- case 'T': -- res |= TASK_STOPPED; -- break; -- case 'C': -- res |= TASK_TRACED; -- break; -- case 'Z': -- res |= EXIT_ZOMBIE << 16; -- break; -- case 'E': -- res |= EXIT_DEAD << 16; -- break; -- case 'U': -- res |= UNRUNNABLE; -- break; -- case 'I': -- res |= IDLE; -- break; -- case 'M': -- res |= DAEMON; -- break; -- case 'A': -- res = ~0UL; -- break; -- default: -- kdb_func_printf("unknown flag '%c' ignored\n", *s); -- break; -- } -- ++s; -- } -- return res; --} - - /* - * kdb_task_state_char - Return the character that represents the task state. -@@ -559,7 +485,6 @@ unsigned long kdb_task_state_string(const char *s) - */ - char kdb_task_state_char (const struct task_struct *p) - { -- unsigned int p_state; - unsigned long tmp; - char state; - int cpu; -@@ -568,25 +493,18 @@ char kdb_task_state_char (const struct task_struct *p) - copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long))) - return 'E'; - -- cpu = kdb_process_cpu(p); -- p_state = READ_ONCE(p->__state); -- state = (p_state == 0) ? 'R' : -- (p_state < 0) ? 'U' : -- (p_state & TASK_UNINTERRUPTIBLE) ? 'D' : -- (p_state & TASK_STOPPED) ? 'T' : -- (p_state & TASK_TRACED) ? 'C' : -- (p->exit_state & EXIT_ZOMBIE) ? 'Z' : -- (p->exit_state & EXIT_DEAD) ? 'E' : -- (p_state & TASK_INTERRUPTIBLE) ? 'S' : '?'; -+ state = task_state_to_char((struct task_struct *) p); -+ - if (is_idle_task(p)) { - /* Idle task. Is it really idle, apart from the kdb - * interrupt? */ -+ cpu = kdb_process_cpu(p); - if (!kdb_task_has_cpu(p) || kgdb_info[cpu].irq_depth == 1) { - if (cpu != kdb_initial_cpu) -- state = 'I'; /* idle task */ -+ state = '-'; /* idle task */ - } -- } else if (!p->mm && state == 'S') { -- state = 'M'; /* sleeping system daemon */ -+ } else if (!p->mm && strchr("IMS", state)) { -+ state = tolower(state); /* sleeping system daemon */ - } - return state; - } -@@ -596,14 +514,28 @@ char kdb_task_state_char (const struct task_struct *p) - * given by the mask. - * Inputs: - * p struct task for the process -- * mask mask from kdb_task_state_string to select processes -+ * mask set of characters used to select processes; both NULL -+ * and the empty string mean adopt a default filter, which -+ * is to suppress sleeping system daemons and the idle tasks - * Returns: - * True if the process matches at least one criteria defined by the mask. - */ --unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask) -+bool kdb_task_state(const struct task_struct *p, const char *mask) - { -- char state[] = { kdb_task_state_char(p), '\0' }; -- return (mask & kdb_task_state_string(state)) != 0; -+ char state = kdb_task_state_char(p); -+ -+ /* If there is no mask, then we will filter code that runs when the -+ * scheduler is idling and any system daemons that are currently -+ * sleeping. -+ */ -+ if (!mask || mask[0] == '\0') -+ return !strchr("-ims", state); -+ -+ /* A is a special case that matches all states */ -+ if (strchr(mask, 'A')) -+ return true; -+ -+ return strchr(mask, state); - } - - /* Maintain a small stack of kdb_flags to allow recursion without disturbing -diff --git a/kernel/entry/syscall_user_dispatch.c b/kernel/entry/syscall_user_dispatch.c -index c240302f56e23..0b6379adff6bd 100644 ---- a/kernel/entry/syscall_user_dispatch.c -+++ b/kernel/entry/syscall_user_dispatch.c -@@ -47,14 +47,18 @@ bool syscall_user_dispatch(struct pt_regs *regs) - * access_ok() is performed once, at prctl time, when - * the selector is loaded by userspace. - */ -- if (unlikely(__get_user(state, sd->selector))) -- do_exit(SIGSEGV); -+ if (unlikely(__get_user(state, sd->selector))) { -+ force_exit_sig(SIGSEGV); -+ return true; -+ } - - if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW)) - return false; - -- if (state != SYSCALL_DISPATCH_FILTER_BLOCK) -- do_exit(SIGSYS); -+ if (state != SYSCALL_DISPATCH_FILTER_BLOCK) { -+ force_exit_sig(SIGSYS); -+ return true; -+ } - } - - sd->on_dispatch = true; -diff --git a/kernel/events/core.c b/kernel/events/core.c -index f23ca260307f0..2931faf92a76f 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -7154,7 +7154,6 @@ void perf_output_sample(struct perf_output_handle *handle, - static u64 perf_virt_to_phys(u64 virt) - { - u64 phys_addr = 0; -- struct page *p = NULL; - - if (!virt) - return 0; -@@ -7173,14 +7172,15 @@ static u64 perf_virt_to_phys(u64 virt) - * If failed, leave phys_addr as 0. - */ - if (current->mm != NULL) { -+ struct page *p; -+ - pagefault_disable(); -- if (get_user_page_fast_only(virt, 0, &p)) -+ if (get_user_page_fast_only(virt, 0, &p)) { - phys_addr = page_to_phys(p) + virt % PAGE_SIZE; -+ put_page(p); -+ } - pagefault_enable(); - } -- -- if (p) -- put_page(p); - } - - return phys_addr; -@@ -9729,6 +9729,9 @@ void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, - continue; - if (event->attr.config != entry->type) - continue; -+ /* Cannot deliver synchronous signal to other task. */ -+ if (event->attr.sigtrap) -+ continue; - if (perf_tp_event_match(event, &data, regs)) - perf_swevent_event(event, count, &data, regs); - } -diff --git a/kernel/fork.c b/kernel/fork.c -index 38681ad44c76b..10885c649ca42 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -2280,6 +2280,7 @@ static __latent_entropy struct task_struct *copy_process( - p->pdeath_signal = 0; - INIT_LIST_HEAD(&p->thread_group); - p->task_works = NULL; -+ clear_posix_cputimers_work(p); - - #ifdef CONFIG_KRETPROBES - p->kretprobe_instances.first = NULL; -@@ -2405,7 +2406,7 @@ static __latent_entropy struct task_struct *copy_process( - write_unlock_irq(&tasklist_lock); - - proc_fork_connector(p); -- sched_post_fork(p); -+ sched_post_fork(p, args); - cgroup_post_fork(p, args); - perf_event_fork(p); - -diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c -index 6a5ecee6e5674..7f350ae59c5fd 100644 ---- a/kernel/irq/msi.c -+++ b/kernel/irq/msi.c -@@ -529,10 +529,10 @@ static bool msi_check_reservation_mode(struct irq_domain *domain, - - /* - * Checking the first MSI descriptor is sufficient. MSIX supports -- * masking and MSI does so when the maskbit is set. -+ * masking and MSI does so when the can_mask attribute is set. - */ - desc = first_msi_entry(dev); -- return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit; -+ return desc->msi_attrib.is_msix || desc->msi_attrib.can_mask; - } - - int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, -diff --git a/kernel/kprobes.c b/kernel/kprobes.c -index 790a573bbe00c..2ef90d15699fb 100644 ---- a/kernel/kprobes.c -+++ b/kernel/kprobes.c -@@ -2006,6 +2006,9 @@ int register_kretprobe(struct kretprobe *rp) - } - } - -+ if (rp->data_size > KRETPROBE_MAX_DATA_SIZE) -+ return -E2BIG; -+ - rp->kp.pre_handler = pre_handler_kretprobe; - rp->kp.post_handler = NULL; - -@@ -2809,13 +2812,12 @@ static const struct file_operations fops_kp = { - static int __init debugfs_kprobe_init(void) - { - struct dentry *dir; -- unsigned int value = 1; - - dir = debugfs_create_dir("kprobes", NULL); - - debugfs_create_file("list", 0400, dir, NULL, &kprobes_fops); - -- debugfs_create_file("enabled", 0600, dir, &value, &fops_kp); -+ debugfs_create_file("enabled", 0600, dir, NULL, &fops_kp); - - debugfs_create_file("blacklist", 0400, dir, NULL, - &kprobe_blacklist_fops); -diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c -index bf1c00c881e48..d624231eab2bb 100644 ---- a/kernel/locking/lockdep.c -+++ b/kernel/locking/lockdep.c -@@ -888,7 +888,7 @@ look_up_lock_class(const struct lockdep_map *lock, unsigned int subclass) - if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) - return NULL; - -- hlist_for_each_entry_rcu(class, hash_head, hash_entry) { -+ hlist_for_each_entry_rcu_notrace(class, hash_head, hash_entry) { - if (class->key == key) { - /* - * Huh! same key, different name? Did someone trample -@@ -5366,7 +5366,7 @@ int __lock_is_held(const struct lockdep_map *lock, int read) - struct held_lock *hlock = curr->held_locks + i; - - if (match_held_lock(hlock, lock)) { -- if (read == -1 || hlock->read == read) -+ if (read == -1 || !!hlock->read == read) - return LOCK_STATE_HELD; - - return LOCK_STATE_NOT_HELD; -diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c -index 6bb116c559b4a..ea5a701ab2408 100644 ---- a/kernel/locking/rtmutex.c -+++ b/kernel/locking/rtmutex.c -@@ -1373,7 +1373,7 @@ static bool rtmutex_spin_on_owner(struct rt_mutex_base *lock, - * - the VCPU on which owner runs is preempted - */ - if (!owner->on_cpu || need_resched() || -- rt_mutex_waiter_is_top_waiter(lock, waiter) || -+ !rt_mutex_waiter_is_top_waiter(lock, waiter) || - vcpu_is_preempted(task_cpu(owner))) { - res = false; - break; -diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c -index 000e8d5a28841..e63f740c2cc84 100644 ---- a/kernel/locking/rwsem.c -+++ b/kernel/locking/rwsem.c -@@ -106,9 +106,9 @@ - * atomic_long_cmpxchg() will be used to obtain writer lock. - * - * There are three places where the lock handoff bit may be set or cleared. -- * 1) rwsem_mark_wake() for readers. -- * 2) rwsem_try_write_lock() for writers. -- * 3) Error path of rwsem_down_write_slowpath(). -+ * 1) rwsem_mark_wake() for readers -- set, clear -+ * 2) rwsem_try_write_lock() for writers -- set, clear -+ * 3) rwsem_del_waiter() -- clear - * - * For all the above cases, wait_lock will be held. A writer must also - * be the first one in the wait_list to be eligible for setting the handoff -@@ -335,6 +335,9 @@ struct rwsem_waiter { - struct task_struct *task; - enum rwsem_waiter_type type; - unsigned long timeout; -+ -+ /* Writer only, not initialized in reader */ -+ bool handoff_set; - }; - #define rwsem_first_waiter(sem) \ - list_first_entry(&sem->wait_list, struct rwsem_waiter, list) -@@ -345,12 +348,6 @@ enum rwsem_wake_type { - RWSEM_WAKE_READ_OWNED /* Waker thread holds the read lock */ - }; - --enum writer_wait_state { -- WRITER_NOT_FIRST, /* Writer is not first in wait list */ -- WRITER_FIRST, /* Writer is first in wait list */ -- WRITER_HANDOFF /* Writer is first & handoff needed */ --}; -- - /* - * The typical HZ value is either 250 or 1000. So set the minimum waiting - * time to at least 4ms or 1 jiffy (if it is higher than 4ms) in the wait -@@ -366,6 +363,31 @@ enum writer_wait_state { - */ - #define MAX_READERS_WAKEUP 0x100 - -+static inline void -+rwsem_add_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter) -+{ -+ lockdep_assert_held(&sem->wait_lock); -+ list_add_tail(&waiter->list, &sem->wait_list); -+ /* caller will set RWSEM_FLAG_WAITERS */ -+} -+ -+/* -+ * Remove a waiter from the wait_list and clear flags. -+ * -+ * Both rwsem_mark_wake() and rwsem_try_write_lock() contain a full 'copy' of -+ * this function. Modify with care. -+ */ -+static inline void -+rwsem_del_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter) -+{ -+ lockdep_assert_held(&sem->wait_lock); -+ list_del(&waiter->list); -+ if (likely(!list_empty(&sem->wait_list))) -+ return; -+ -+ atomic_long_andnot(RWSEM_FLAG_HANDOFF | RWSEM_FLAG_WAITERS, &sem->count); -+} -+ - /* - * handle the lock release when processes blocked on it that can now run - * - if we come here from up_xxxx(), then the RWSEM_FLAG_WAITERS bit must -@@ -377,6 +399,8 @@ enum writer_wait_state { - * preferably when the wait_lock is released - * - woken process blocks are discarded from the list after having task zeroed - * - writers are only marked woken if downgrading is false -+ * -+ * Implies rwsem_del_waiter() for all woken readers. - */ - static void rwsem_mark_wake(struct rw_semaphore *sem, - enum rwsem_wake_type wake_type, -@@ -491,18 +515,25 @@ static void rwsem_mark_wake(struct rw_semaphore *sem, - - adjustment = woken * RWSEM_READER_BIAS - adjustment; - lockevent_cond_inc(rwsem_wake_reader, woken); -+ -+ oldcount = atomic_long_read(&sem->count); - if (list_empty(&sem->wait_list)) { -- /* hit end of list above */ -+ /* -+ * Combined with list_move_tail() above, this implies -+ * rwsem_del_waiter(). -+ */ - adjustment -= RWSEM_FLAG_WAITERS; -+ if (oldcount & RWSEM_FLAG_HANDOFF) -+ adjustment -= RWSEM_FLAG_HANDOFF; -+ } else if (woken) { -+ /* -+ * When we've woken a reader, we no longer need to force -+ * writers to give up the lock and we can clear HANDOFF. -+ */ -+ if (oldcount & RWSEM_FLAG_HANDOFF) -+ adjustment -= RWSEM_FLAG_HANDOFF; - } - -- /* -- * When we've woken a reader, we no longer need to force writers -- * to give up the lock and we can clear HANDOFF. -- */ -- if (woken && (atomic_long_read(&sem->count) & RWSEM_FLAG_HANDOFF)) -- adjustment -= RWSEM_FLAG_HANDOFF; -- - if (adjustment) - atomic_long_add(adjustment, &sem->count); - -@@ -533,12 +564,12 @@ static void rwsem_mark_wake(struct rw_semaphore *sem, - * race conditions between checking the rwsem wait list and setting the - * sem->count accordingly. - * -- * If wstate is WRITER_HANDOFF, it will make sure that either the handoff -- * bit is set or the lock is acquired with handoff bit cleared. -+ * Implies rwsem_del_waiter() on success. - */ - static inline bool rwsem_try_write_lock(struct rw_semaphore *sem, -- enum writer_wait_state wstate) -+ struct rwsem_waiter *waiter) - { -+ bool first = rwsem_first_waiter(sem) == waiter; - long count, new; - - lockdep_assert_held(&sem->wait_lock); -@@ -547,13 +578,19 @@ static inline bool rwsem_try_write_lock(struct rw_semaphore *sem, - do { - bool has_handoff = !!(count & RWSEM_FLAG_HANDOFF); - -- if (has_handoff && wstate == WRITER_NOT_FIRST) -- return false; -+ if (has_handoff) { -+ if (!first) -+ return false; -+ -+ /* First waiter inherits a previously set handoff bit */ -+ waiter->handoff_set = true; -+ } - - new = count; - - if (count & RWSEM_LOCK_MASK) { -- if (has_handoff || (wstate != WRITER_HANDOFF)) -+ if (has_handoff || (!rt_task(waiter->task) && -+ !time_after(jiffies, waiter->timeout))) - return false; - - new |= RWSEM_FLAG_HANDOFF; -@@ -570,13 +607,39 @@ static inline bool rwsem_try_write_lock(struct rw_semaphore *sem, - * We have either acquired the lock with handoff bit cleared or - * set the handoff bit. - */ -- if (new & RWSEM_FLAG_HANDOFF) -+ if (new & RWSEM_FLAG_HANDOFF) { -+ waiter->handoff_set = true; -+ lockevent_inc(rwsem_wlock_handoff); - return false; -+ } - -+ /* -+ * Have rwsem_try_write_lock() fully imply rwsem_del_waiter() on -+ * success. -+ */ -+ list_del(&waiter->list); - rwsem_set_owner(sem); - return true; - } - -+/* -+ * The rwsem_spin_on_owner() function returns the following 4 values -+ * depending on the lock owner state. -+ * OWNER_NULL : owner is currently NULL -+ * OWNER_WRITER: when owner changes and is a writer -+ * OWNER_READER: when owner changes and the new owner may be a reader. -+ * OWNER_NONSPINNABLE: -+ * when optimistic spinning has to stop because either the -+ * owner stops running, is unknown, or its timeslice has -+ * been used up. -+ */ -+enum owner_state { -+ OWNER_NULL = 1 << 0, -+ OWNER_WRITER = 1 << 1, -+ OWNER_READER = 1 << 2, -+ OWNER_NONSPINNABLE = 1 << 3, -+}; -+ - #ifdef CONFIG_RWSEM_SPIN_ON_OWNER - /* - * Try to acquire write lock before the writer has been put on wait queue. -@@ -632,23 +695,6 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) - return ret; - } - --/* -- * The rwsem_spin_on_owner() function returns the following 4 values -- * depending on the lock owner state. -- * OWNER_NULL : owner is currently NULL -- * OWNER_WRITER: when owner changes and is a writer -- * OWNER_READER: when owner changes and the new owner may be a reader. -- * OWNER_NONSPINNABLE: -- * when optimistic spinning has to stop because either the -- * owner stops running, is unknown, or its timeslice has -- * been used up. -- */ --enum owner_state { -- OWNER_NULL = 1 << 0, -- OWNER_WRITER = 1 << 1, -- OWNER_READER = 1 << 2, -- OWNER_NONSPINNABLE = 1 << 3, --}; - #define OWNER_SPINNABLE (OWNER_NULL | OWNER_WRITER | OWNER_READER) - - static inline enum owner_state -@@ -878,12 +924,11 @@ static inline bool rwsem_optimistic_spin(struct rw_semaphore *sem) - - static inline void clear_nonspinnable(struct rw_semaphore *sem) { } - --static inline int -+static inline enum owner_state - rwsem_spin_on_owner(struct rw_semaphore *sem) - { -- return 0; -+ return OWNER_NONSPINNABLE; - } --#define OWNER_NULL 1 - #endif - - /* -@@ -953,7 +998,7 @@ queue: - } - adjustment += RWSEM_FLAG_WAITERS; - } -- list_add_tail(&waiter.list, &sem->wait_list); -+ rwsem_add_waiter(sem, &waiter); - - /* we're now waiting on the lock, but no longer actively locking */ - count = atomic_long_add_return(adjustment, &sem->count); -@@ -999,11 +1044,7 @@ queue: - return sem; - - out_nolock: -- list_del(&waiter.list); -- if (list_empty(&sem->wait_list)) { -- atomic_long_andnot(RWSEM_FLAG_WAITERS|RWSEM_FLAG_HANDOFF, -- &sem->count); -- } -+ rwsem_del_waiter(sem, &waiter); - raw_spin_unlock_irq(&sem->wait_lock); - __set_current_state(TASK_RUNNING); - lockevent_inc(rwsem_rlock_fail); -@@ -1017,9 +1058,7 @@ static struct rw_semaphore * - rwsem_down_write_slowpath(struct rw_semaphore *sem, int state) - { - long count; -- enum writer_wait_state wstate; - struct rwsem_waiter waiter; -- struct rw_semaphore *ret = sem; - DEFINE_WAKE_Q(wake_q); - - /* do optimistic spinning and steal lock if possible */ -@@ -1035,16 +1074,13 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state) - waiter.task = current; - waiter.type = RWSEM_WAITING_FOR_WRITE; - waiter.timeout = jiffies + RWSEM_WAIT_TIMEOUT; -+ waiter.handoff_set = false; - - raw_spin_lock_irq(&sem->wait_lock); -- -- /* account for this before adding a new element to the list */ -- wstate = list_empty(&sem->wait_list) ? WRITER_FIRST : WRITER_NOT_FIRST; -- -- list_add_tail(&waiter.list, &sem->wait_list); -+ rwsem_add_waiter(sem, &waiter); - - /* we're now waiting on the lock */ -- if (wstate == WRITER_NOT_FIRST) { -+ if (rwsem_first_waiter(sem) != &waiter) { - count = atomic_long_read(&sem->count); - - /* -@@ -1080,13 +1116,16 @@ wait: - /* wait until we successfully acquire the lock */ - set_current_state(state); - for (;;) { -- if (rwsem_try_write_lock(sem, wstate)) { -+ if (rwsem_try_write_lock(sem, &waiter)) { - /* rwsem_try_write_lock() implies ACQUIRE on success */ - break; - } - - raw_spin_unlock_irq(&sem->wait_lock); - -+ if (signal_pending_state(state, current)) -+ goto out_nolock; -+ - /* - * After setting the handoff bit and failing to acquire - * the lock, attempt to spin on owner to accelerate lock -@@ -1095,70 +1134,37 @@ wait: - * In this case, we attempt to acquire the lock again - * without sleeping. - */ -- if (wstate == WRITER_HANDOFF && -- rwsem_spin_on_owner(sem) == OWNER_NULL) -- goto trylock_again; -- -- /* Block until there are no active lockers. */ -- for (;;) { -- if (signal_pending_state(state, current)) -- goto out_nolock; -- -- schedule(); -- lockevent_inc(rwsem_sleep_writer); -- set_current_state(state); -- /* -- * If HANDOFF bit is set, unconditionally do -- * a trylock. -- */ -- if (wstate == WRITER_HANDOFF) -- break; -- -- if ((wstate == WRITER_NOT_FIRST) && -- (rwsem_first_waiter(sem) == &waiter)) -- wstate = WRITER_FIRST; -+ if (waiter.handoff_set) { -+ enum owner_state owner_state; - -- count = atomic_long_read(&sem->count); -- if (!(count & RWSEM_LOCK_MASK)) -- break; -+ preempt_disable(); -+ owner_state = rwsem_spin_on_owner(sem); -+ preempt_enable(); - -- /* -- * The setting of the handoff bit is deferred -- * until rwsem_try_write_lock() is called. -- */ -- if ((wstate == WRITER_FIRST) && (rt_task(current) || -- time_after(jiffies, waiter.timeout))) { -- wstate = WRITER_HANDOFF; -- lockevent_inc(rwsem_wlock_handoff); -- break; -- } -+ if (owner_state == OWNER_NULL) -+ goto trylock_again; - } -+ -+ schedule(); -+ lockevent_inc(rwsem_sleep_writer); -+ set_current_state(state); - trylock_again: - raw_spin_lock_irq(&sem->wait_lock); - } - __set_current_state(TASK_RUNNING); -- list_del(&waiter.list); - raw_spin_unlock_irq(&sem->wait_lock); - lockevent_inc(rwsem_wlock); -- -- return ret; -+ return sem; - - out_nolock: - __set_current_state(TASK_RUNNING); - raw_spin_lock_irq(&sem->wait_lock); -- list_del(&waiter.list); -- -- if (unlikely(wstate == WRITER_HANDOFF)) -- atomic_long_add(-RWSEM_FLAG_HANDOFF, &sem->count); -- -- if (list_empty(&sem->wait_list)) -- atomic_long_andnot(RWSEM_FLAG_WAITERS, &sem->count); -- else -+ rwsem_del_waiter(sem, &waiter); -+ if (!list_empty(&sem->wait_list)) - rwsem_mark_wake(sem, RWSEM_WAKE_ANY, &wake_q); - raw_spin_unlock_irq(&sem->wait_lock); - wake_up_q(&wake_q); - lockevent_inc(rwsem_wlock_fail); -- - return ERR_PTR(-EINTR); - } - -diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c -index a332ccd829e24..97e62469a6b32 100644 ---- a/kernel/power/energy_model.c -+++ b/kernel/power/energy_model.c -@@ -107,8 +107,7 @@ static void em_debug_remove_pd(struct device *dev) {} - static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd, - int nr_states, struct em_data_callback *cb) - { -- unsigned long opp_eff, prev_opp_eff = ULONG_MAX; -- unsigned long power, freq, prev_freq = 0; -+ unsigned long power, freq, prev_freq = 0, prev_cost = ULONG_MAX; - struct em_perf_state *table; - int i, ret; - u64 fmax; -@@ -153,27 +152,21 @@ static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd, - - table[i].power = power; - table[i].frequency = prev_freq = freq; -- -- /* -- * The hertz/watts efficiency ratio should decrease as the -- * frequency grows on sane platforms. But this isn't always -- * true in practice so warn the user if a higher OPP is more -- * power efficient than a lower one. -- */ -- opp_eff = freq / power; -- if (opp_eff >= prev_opp_eff) -- dev_dbg(dev, "EM: hertz/watts ratio non-monotonically decreasing: em_perf_state %d >= em_perf_state%d\n", -- i, i - 1); -- prev_opp_eff = opp_eff; - } - - /* Compute the cost of each performance state. */ - fmax = (u64) table[nr_states - 1].frequency; -- for (i = 0; i < nr_states; i++) { -+ for (i = nr_states - 1; i >= 0; i--) { - unsigned long power_res = em_scale_power(table[i].power); - - table[i].cost = div64_u64(fmax * power_res, - table[i].frequency); -+ if (table[i].cost >= prev_cost) { -+ dev_dbg(dev, "EM: OPP:%lu is inefficient\n", -+ table[i].frequency); -+ } else { -+ prev_cost = table[i].cost; -+ } - } - - pd->table = table; -diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c -index 559acef3fddb8..b0888e9224da3 100644 ---- a/kernel/power/hibernate.c -+++ b/kernel/power/hibernate.c -@@ -691,7 +691,7 @@ static int load_image_and_restore(void) - goto Unlock; - - error = swsusp_read(&flags); -- swsusp_close(FMODE_READ); -+ swsusp_close(FMODE_READ | FMODE_EXCL); - if (!error) - error = hibernation_restore(flags & SF_PLATFORM_MODE); - -@@ -981,7 +981,7 @@ static int software_resume(void) - /* The snapshot device should not be opened while we're running */ - if (!hibernate_acquire()) { - error = -EBUSY; -- swsusp_close(FMODE_READ); -+ swsusp_close(FMODE_READ | FMODE_EXCL); - goto Unlock; - } - -@@ -1016,7 +1016,7 @@ static int software_resume(void) - pm_pr_dbg("Hibernation image not present or could not be loaded.\n"); - return error; - Close_Finish: -- swsusp_close(FMODE_READ); -+ swsusp_close(FMODE_READ | FMODE_EXCL); - goto Finish; - } - -diff --git a/kernel/power/swap.c b/kernel/power/swap.c -index 3cb89baebc796..f3a1086f7cdb2 100644 ---- a/kernel/power/swap.c -+++ b/kernel/power/swap.c -@@ -299,7 +299,7 @@ static int hib_submit_io(int op, int op_flags, pgoff_t page_off, void *addr, - return error; - } - --static blk_status_t hib_wait_io(struct hib_bio_batch *hb) -+static int hib_wait_io(struct hib_bio_batch *hb) - { - /* - * We are relying on the behavior of blk_plug that a thread with -@@ -1521,9 +1521,10 @@ end: - int swsusp_check(void) - { - int error; -+ void *holder; - - hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device, -- FMODE_READ, NULL); -+ FMODE_READ | FMODE_EXCL, &holder); - if (!IS_ERR(hib_resume_bdev)) { - set_blocksize(hib_resume_bdev, PAGE_SIZE); - clear_page(swsusp_header); -@@ -1545,7 +1546,7 @@ int swsusp_check(void) - - put: - if (error) -- blkdev_put(hib_resume_bdev, FMODE_READ); -+ blkdev_put(hib_resume_bdev, FMODE_READ | FMODE_EXCL); - else - pr_debug("Image signature found, resuming\n"); - } else { -diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c -index a8d0a58deebc7..99221b016c68b 100644 ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3252,6 +3252,11 @@ void defer_console_output(void) - preempt_enable(); - } - -+void printk_trigger_flush(void) -+{ -+ defer_console_output(); -+} -+ - int vprintk_deferred(const char *fmt, va_list args) - { - int r; -diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c -index ab4215266ebee..968696ace8f3f 100644 ---- a/kernel/rcu/rcutorture.c -+++ b/kernel/rcu/rcutorture.c -@@ -1432,28 +1432,34 @@ static void rcutorture_one_extend(int *readstate, int newstate, - /* First, put new protection in place to avoid critical-section gap. */ - if (statesnew & RCUTORTURE_RDR_BH) - local_bh_disable(); -+ if (statesnew & RCUTORTURE_RDR_RBH) -+ rcu_read_lock_bh(); - if (statesnew & RCUTORTURE_RDR_IRQ) - local_irq_disable(); - if (statesnew & RCUTORTURE_RDR_PREEMPT) - preempt_disable(); -- if (statesnew & RCUTORTURE_RDR_RBH) -- rcu_read_lock_bh(); - if (statesnew & RCUTORTURE_RDR_SCHED) - rcu_read_lock_sched(); - if (statesnew & RCUTORTURE_RDR_RCU) - idxnew = cur_ops->readlock() << RCUTORTURE_RDR_SHIFT; - -- /* Next, remove old protection, irq first due to bh conflict. */ -+ /* -+ * Next, remove old protection, in decreasing order of strength -+ * to avoid unlock paths that aren't safe in the stronger -+ * context. Namely: BH can not be enabled with disabled interrupts. -+ * Additionally PREEMPT_RT requires that BH is enabled in preemptible -+ * context. -+ */ - if (statesold & RCUTORTURE_RDR_IRQ) - local_irq_enable(); -- if (statesold & RCUTORTURE_RDR_BH) -- local_bh_enable(); - if (statesold & RCUTORTURE_RDR_PREEMPT) - preempt_enable(); -- if (statesold & RCUTORTURE_RDR_RBH) -- rcu_read_unlock_bh(); - if (statesold & RCUTORTURE_RDR_SCHED) - rcu_read_unlock_sched(); -+ if (statesold & RCUTORTURE_RDR_BH) -+ local_bh_enable(); -+ if (statesold & RCUTORTURE_RDR_RBH) -+ rcu_read_unlock_bh(); - if (statesold & RCUTORTURE_RDR_RCU) { - bool lockit = !statesnew && !(torture_random(trsp) & 0xffff); - -@@ -1496,6 +1502,9 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp) - int mask = rcutorture_extend_mask_max(); - unsigned long randmask1 = torture_random(trsp) >> 8; - unsigned long randmask2 = randmask1 >> 3; -+ unsigned long preempts = RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED; -+ unsigned long preempts_irq = preempts | RCUTORTURE_RDR_IRQ; -+ unsigned long bhs = RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH; - - WARN_ON_ONCE(mask >> RCUTORTURE_RDR_SHIFT); - /* Mostly only one bit (need preemption!), sometimes lots of bits. */ -@@ -1503,11 +1512,26 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp) - mask = mask & randmask2; - else - mask = mask & (1 << (randmask2 % RCUTORTURE_RDR_NBITS)); -- /* Can't enable bh w/irq disabled. */ -- if ((mask & RCUTORTURE_RDR_IRQ) && -- ((!(mask & RCUTORTURE_RDR_BH) && (oldmask & RCUTORTURE_RDR_BH)) || -- (!(mask & RCUTORTURE_RDR_RBH) && (oldmask & RCUTORTURE_RDR_RBH)))) -- mask |= RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH; -+ -+ /* -+ * Can't enable bh w/irq disabled. -+ */ -+ if (mask & RCUTORTURE_RDR_IRQ) -+ mask |= oldmask & bhs; -+ -+ /* -+ * Ideally these sequences would be detected in debug builds -+ * (regardless of RT), but until then don't stop testing -+ * them on non-RT. -+ */ -+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { -+ /* Can't modify BH in atomic context */ -+ if (oldmask & preempts_irq) -+ mask &= ~bhs; -+ if ((oldmask | mask) & preempts_irq) -+ mask |= oldmask & bhs; -+ } -+ - return mask ?: RCUTORTURE_RDR_RCU; - } - -diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h -index 806160c44b172..6591914af4864 100644 ---- a/kernel/rcu/tasks.h -+++ b/kernel/rcu/tasks.h -@@ -197,6 +197,7 @@ static int __noreturn rcu_tasks_kthread(void *arg) - * This loop is terminated by the system going down. ;-) - */ - for (;;) { -+ set_tasks_gp_state(rtp, RTGS_WAIT_CBS); - - /* Pick up any new callbacks. */ - raw_spin_lock_irqsave(&rtp->cbs_lock, flags); -@@ -236,8 +237,6 @@ static int __noreturn rcu_tasks_kthread(void *arg) - } - /* Paranoid sleep to keep this from entering a tight loop */ - schedule_timeout_idle(rtp->gp_sleep); -- -- set_tasks_gp_state(rtp, RTGS_WAIT_CBS); - } - } - -diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c -index bce848e50512e..7ae10fab68b8f 100644 ---- a/kernel/rcu/tree.c -+++ b/kernel/rcu/tree.c -@@ -327,7 +327,7 @@ static void rcu_dynticks_eqs_online(void) - */ - static __always_inline bool rcu_dynticks_curr_cpu_in_eqs(void) - { -- return !(atomic_read(this_cpu_ptr(&rcu_data.dynticks)) & 0x1); -+ return !(arch_atomic_read(this_cpu_ptr(&rcu_data.dynticks)) & 0x1); - } - - /* -@@ -1907,7 +1907,7 @@ static void rcu_gp_fqs(bool first_time) - struct rcu_node *rnp = rcu_get_root(); - - WRITE_ONCE(rcu_state.gp_activity, jiffies); -- rcu_state.n_force_qs++; -+ WRITE_ONCE(rcu_state.n_force_qs, rcu_state.n_force_qs + 1); - if (first_time) { - /* Collect dyntick-idle snapshots. */ - force_qs_rnp(dyntick_save_progress_counter); -@@ -2550,7 +2550,7 @@ static void rcu_do_batch(struct rcu_data *rdp) - /* Reset ->qlen_last_fqs_check trigger if enough CBs have drained. */ - if (count == 0 && rdp->qlen_last_fqs_check != 0) { - rdp->qlen_last_fqs_check = 0; -- rdp->n_force_qs_snap = rcu_state.n_force_qs; -+ rdp->n_force_qs_snap = READ_ONCE(rcu_state.n_force_qs); - } else if (count < rdp->qlen_last_fqs_check - qhimark) - rdp->qlen_last_fqs_check = count; - -@@ -2898,10 +2898,10 @@ static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head, - } else { - /* Give the grace period a kick. */ - rdp->blimit = DEFAULT_MAX_RCU_BLIMIT; -- if (rcu_state.n_force_qs == rdp->n_force_qs_snap && -+ if (READ_ONCE(rcu_state.n_force_qs) == rdp->n_force_qs_snap && - rcu_segcblist_first_pend_cb(&rdp->cblist) != head) - rcu_force_quiescent_state(); -- rdp->n_force_qs_snap = rcu_state.n_force_qs; -+ rdp->n_force_qs_snap = READ_ONCE(rcu_state.n_force_qs); - rdp->qlen_last_fqs_check = rcu_segcblist_n_cbs(&rdp->cblist); - } - } -@@ -4128,7 +4128,7 @@ int rcutree_prepare_cpu(unsigned int cpu) - /* Set up local state, ensuring consistent view of global state. */ - raw_spin_lock_irqsave_rcu_node(rnp, flags); - rdp->qlen_last_fqs_check = 0; -- rdp->n_force_qs_snap = rcu_state.n_force_qs; -+ rdp->n_force_qs_snap = READ_ONCE(rcu_state.n_force_qs); - rdp->blimit = blimit; - rdp->dynticks_nesting = 1; /* CPU not up, no tearing. */ - rcu_dynticks_eqs_online(); -diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h -index 2796084ef85a5..454b516ea566e 100644 ---- a/kernel/rcu/tree_exp.h -+++ b/kernel/rcu/tree_exp.h -@@ -760,7 +760,7 @@ static void sync_sched_exp_online_cleanup(int cpu) - my_cpu = get_cpu(); - /* Quiescent state either not needed or already requested, leave. */ - if (!(READ_ONCE(rnp->expmask) & rdp->grpmask) || -- __this_cpu_read(rcu_data.cpu_no_qs.b.exp)) { -+ rdp->cpu_no_qs.b.exp) { - put_cpu(); - return; - } -diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h -index d070059163d70..0d21a5cdc7247 100644 ---- a/kernel/rcu/tree_plugin.h -+++ b/kernel/rcu/tree_plugin.h -@@ -1480,7 +1480,7 @@ static void rcu_bind_gp_kthread(void) - } - - /* Record the current task on dyntick-idle entry. */ --static void noinstr rcu_dynticks_task_enter(void) -+static __always_inline void rcu_dynticks_task_enter(void) - { - #if defined(CONFIG_TASKS_RCU) && defined(CONFIG_NO_HZ_FULL) - WRITE_ONCE(current->rcu_tasks_idle_cpu, smp_processor_id()); -@@ -1488,7 +1488,7 @@ static void noinstr rcu_dynticks_task_enter(void) - } - - /* Record no current task on dyntick-idle exit. */ --static void noinstr rcu_dynticks_task_exit(void) -+static __always_inline void rcu_dynticks_task_exit(void) - { - #if defined(CONFIG_TASKS_RCU) && defined(CONFIG_NO_HZ_FULL) - WRITE_ONCE(current->rcu_tasks_idle_cpu, -1); -@@ -1496,7 +1496,7 @@ static void noinstr rcu_dynticks_task_exit(void) - } - - /* Turn on heavyweight RCU tasks trace readers on idle/user entry. */ --static void rcu_dynticks_task_trace_enter(void) -+static __always_inline void rcu_dynticks_task_trace_enter(void) - { - #ifdef CONFIG_TASKS_TRACE_RCU - if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB)) -@@ -1505,7 +1505,7 @@ static void rcu_dynticks_task_trace_enter(void) - } - - /* Turn off heavyweight RCU tasks trace readers on idle/user exit. */ --static void rcu_dynticks_task_trace_exit(void) -+static __always_inline void rcu_dynticks_task_trace_exit(void) - { - #ifdef CONFIG_TASKS_TRACE_RCU - if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB)) -diff --git a/kernel/sched/autogroup.c b/kernel/sched/autogroup.c -index 2067080bb2358..8629b37d118e7 100644 ---- a/kernel/sched/autogroup.c -+++ b/kernel/sched/autogroup.c -@@ -31,7 +31,7 @@ static inline void autogroup_destroy(struct kref *kref) - ag->tg->rt_se = NULL; - ag->tg->rt_rq = NULL; - #endif -- sched_offline_group(ag->tg); -+ sched_release_group(ag->tg); - sched_destroy_group(ag->tg); - } - -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index f21714ea3db85..0d12ec7be3017 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -1914,7 +1914,7 @@ static void __init init_uclamp_rq(struct rq *rq) - }; - } - -- rq->uclamp_flags = 0; -+ rq->uclamp_flags = UCLAMP_FLAG_IDLE; - } - - static void __init init_uclamp(void) -@@ -3707,6 +3707,9 @@ out: - - bool cpus_share_cache(int this_cpu, int that_cpu) - { -+ if (this_cpu == that_cpu) -+ return true; -+ - return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); - } - -@@ -4328,8 +4331,6 @@ int sysctl_schedstats(struct ctl_table *table, int write, void *buffer, - */ - int sched_fork(unsigned long clone_flags, struct task_struct *p) - { -- unsigned long flags; -- - __sched_fork(clone_flags, p); - /* - * We mark the process as NEW here. This guarantees that -@@ -4375,24 +4376,6 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) - - init_entity_runnable_average(&p->se); - -- /* -- * The child is not yet in the pid-hash so no cgroup attach races, -- * and the cgroup is pinned to this child due to cgroup_fork() -- * is ran before sched_fork(). -- * -- * Silence PROVE_RCU. -- */ -- raw_spin_lock_irqsave(&p->pi_lock, flags); -- rseq_migrate(p); -- /* -- * We're setting the CPU for the first time, we don't migrate, -- * so use __set_task_cpu(). -- */ -- __set_task_cpu(p, smp_processor_id()); -- if (p->sched_class->task_fork) -- p->sched_class->task_fork(p); -- raw_spin_unlock_irqrestore(&p->pi_lock, flags); -- - #ifdef CONFIG_SCHED_INFO - if (likely(sched_info_on())) - memset(&p->sched_info, 0, sizeof(p->sched_info)); -@@ -4408,8 +4391,29 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) - return 0; - } - --void sched_post_fork(struct task_struct *p) -+void sched_post_fork(struct task_struct *p, struct kernel_clone_args *kargs) - { -+ unsigned long flags; -+#ifdef CONFIG_CGROUP_SCHED -+ struct task_group *tg; -+#endif -+ -+ raw_spin_lock_irqsave(&p->pi_lock, flags); -+#ifdef CONFIG_CGROUP_SCHED -+ tg = container_of(kargs->cset->subsys[cpu_cgrp_id], -+ struct task_group, css); -+ p->sched_task_group = autogroup_task_group(p, tg); -+#endif -+ rseq_migrate(p); -+ /* -+ * We're setting the CPU for the first time, we don't migrate, -+ * so use __set_task_cpu(). -+ */ -+ __set_task_cpu(p, smp_processor_id()); -+ if (p->sched_class->task_fork) -+ p->sched_class->task_fork(p); -+ raw_spin_unlock_irqrestore(&p->pi_lock, flags); -+ - uclamp_post_fork(p); - } - -@@ -6656,11 +6660,11 @@ static int __init setup_preempt_mode(char *str) - int mode = sched_dynamic_mode(str); - if (mode < 0) { - pr_warn("Dynamic Preempt: unsupported mode: %s\n", str); -- return 1; -+ return 0; - } - - sched_dynamic_update(mode); -- return 0; -+ return 1; - } - __setup("preempt=", setup_preempt_mode); - -@@ -8637,9 +8641,6 @@ void __init init_idle(struct task_struct *idle, int cpu) - idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY; - kthread_set_per_cpu(idle, cpu); - -- scs_task_reset(idle); -- kasan_unpoison_task_stack(idle); -- - #ifdef CONFIG_SMP - /* - * It's possible that init_idle() gets called multiple times on a task, -@@ -8795,7 +8796,6 @@ void idle_task_exit(void) - finish_arch_post_lock_switch(); - } - -- scs_task_reset(current); - /* finish_cpu(), as ran on the BP, will clean up the active_mm state */ - } - -@@ -9716,6 +9716,22 @@ static void sched_free_group(struct task_group *tg) - kmem_cache_free(task_group_cache, tg); - } - -+static void sched_free_group_rcu(struct rcu_head *rcu) -+{ -+ sched_free_group(container_of(rcu, struct task_group, rcu)); -+} -+ -+static void sched_unregister_group(struct task_group *tg) -+{ -+ unregister_fair_sched_group(tg); -+ unregister_rt_sched_group(tg); -+ /* -+ * We have to wait for yet another RCU grace period to expire, as -+ * print_cfs_stats() might run concurrently. -+ */ -+ call_rcu(&tg->rcu, sched_free_group_rcu); -+} -+ - /* allocate runqueue etc for a new task group */ - struct task_group *sched_create_group(struct task_group *parent) - { -@@ -9759,25 +9775,35 @@ void sched_online_group(struct task_group *tg, struct task_group *parent) - } - - /* rcu callback to free various structures associated with a task group */ --static void sched_free_group_rcu(struct rcu_head *rhp) -+static void sched_unregister_group_rcu(struct rcu_head *rhp) - { - /* Now it should be safe to free those cfs_rqs: */ -- sched_free_group(container_of(rhp, struct task_group, rcu)); -+ sched_unregister_group(container_of(rhp, struct task_group, rcu)); - } - - void sched_destroy_group(struct task_group *tg) - { - /* Wait for possible concurrent references to cfs_rqs complete: */ -- call_rcu(&tg->rcu, sched_free_group_rcu); -+ call_rcu(&tg->rcu, sched_unregister_group_rcu); - } - --void sched_offline_group(struct task_group *tg) -+void sched_release_group(struct task_group *tg) - { - unsigned long flags; - -- /* End participation in shares distribution: */ -- unregister_fair_sched_group(tg); -- -+ /* -+ * Unlink first, to avoid walk_tg_tree_from() from finding us (via -+ * sched_cfs_period_timer()). -+ * -+ * For this to be effective, we have to wait for all pending users of -+ * this task group to leave their RCU critical section to ensure no new -+ * user will see our dying task group any more. Specifically ensure -+ * that tg_unthrottle_up() won't add decayed cfs_rq's to it. -+ * -+ * We therefore defer calling unregister_fair_sched_group() to -+ * sched_unregister_group() which is guarantied to get called only after the -+ * current RCU grace period has expired. -+ */ - spin_lock_irqsave(&task_group_lock, flags); - list_del_rcu(&tg->list); - list_del_rcu(&tg->siblings); -@@ -9896,7 +9922,7 @@ static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) - { - struct task_group *tg = css_tg(css); - -- sched_offline_group(tg); -+ sched_release_group(tg); - } - - static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) -@@ -9906,7 +9932,7 @@ static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) - /* - * Relies on the RCU grace period between css_released() and this. - */ -- sched_free_group(tg); -+ sched_unregister_group(tg); - } - - /* -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index f6a05d9b54436..6f16dfb742462 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -11358,8 +11358,6 @@ void free_fair_sched_group(struct task_group *tg) - { - int i; - -- destroy_cfs_bandwidth(tg_cfs_bandwidth(tg)); -- - for_each_possible_cpu(i) { - if (tg->cfs_rq) - kfree(tg->cfs_rq[i]); -@@ -11436,6 +11434,8 @@ void unregister_fair_sched_group(struct task_group *tg) - struct rq *rq; - int cpu; - -+ destroy_cfs_bandwidth(tg_cfs_bandwidth(tg)); -+ - for_each_possible_cpu(cpu) { - if (tg->se[cpu]) - remove_entity_load_avg(tg->se[cpu]); -diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c -index 3daf42a0f4623..bfef3f39b5552 100644 ---- a/kernel/sched/rt.c -+++ b/kernel/sched/rt.c -@@ -137,13 +137,17 @@ static inline struct rq *rq_of_rt_se(struct sched_rt_entity *rt_se) - return rt_rq->rq; - } - --void free_rt_sched_group(struct task_group *tg) -+void unregister_rt_sched_group(struct task_group *tg) - { -- int i; -- - if (tg->rt_se) - destroy_rt_bandwidth(&tg->rt_bandwidth); - -+} -+ -+void free_rt_sched_group(struct task_group *tg) -+{ -+ int i; -+ - for_each_possible_cpu(i) { - if (tg->rt_rq) - kfree(tg->rt_rq[i]); -@@ -250,6 +254,8 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) - return &rq->rt; - } - -+void unregister_rt_sched_group(struct task_group *tg) { } -+ - void free_rt_sched_group(struct task_group *tg) { } - - int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 3d3e5793e1172..4f432826933da 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -486,6 +486,7 @@ extern void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b); - extern void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b); - extern void unthrottle_cfs_rq(struct cfs_rq *cfs_rq); - -+extern void unregister_rt_sched_group(struct task_group *tg); - extern void free_rt_sched_group(struct task_group *tg); - extern int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent); - extern void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, -@@ -501,7 +502,7 @@ extern struct task_group *sched_create_group(struct task_group *parent); - extern void sched_online_group(struct task_group *tg, - struct task_group *parent); - extern void sched_destroy_group(struct task_group *tg); --extern void sched_offline_group(struct task_group *tg); -+extern void sched_release_group(struct task_group *tg); - - extern void sched_move_task(struct task_struct *tsk); - -diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c -index 76577d1642a5d..eca38107b32f1 100644 ---- a/kernel/sched/wait.c -+++ b/kernel/sched/wait.c -@@ -238,6 +238,13 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode) - } - EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ - -+void __wake_up_pollfree(struct wait_queue_head *wq_head) -+{ -+ __wake_up(wq_head, TASK_NORMAL, 0, poll_to_key(EPOLLHUP | POLLFREE)); -+ /* POLLFREE must have cleared the queue. */ -+ WARN_ON_ONCE(waitqueue_active(wq_head)); -+} -+ - /* - * Note: we use "set_current_state()" _after_ the wait-queue add, - * because we need a memory barrier there on SMP, so that any -diff --git a/kernel/scs.c b/kernel/scs.c -index e2a71fc82fa06..579841be88646 100644 ---- a/kernel/scs.c -+++ b/kernel/scs.c -@@ -78,6 +78,7 @@ void scs_free(void *s) - if (this_cpu_cmpxchg(scs_cache[i], 0, s) == NULL) - return; - -+ kasan_unpoison_vmalloc(s, SCS_SIZE); - vfree_atomic(s); - } - -diff --git a/kernel/signal.c b/kernel/signal.c -index 487bf4f5dadf4..5892c91696f84 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -1298,6 +1298,12 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p - return ret; - } - -+enum sig_handler { -+ HANDLER_CURRENT, /* If reachable use the current handler */ -+ HANDLER_SIG_DFL, /* Always use SIG_DFL handler semantics */ -+ HANDLER_EXIT, /* Only visible as the process exit code */ -+}; -+ - /* - * Force a signal that the process can't ignore: if necessary - * we unblock the signal and change any SIG_IGN to SIG_DFL. -@@ -1310,7 +1316,8 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p - * that is why we also clear SIGNAL_UNKILLABLE. - */ - static int --force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl) -+force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, -+ enum sig_handler handler) - { - unsigned long int flags; - int ret, blocked, ignored; -@@ -1321,8 +1328,10 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool - action = &t->sighand->action[sig-1]; - ignored = action->sa.sa_handler == SIG_IGN; - blocked = sigismember(&t->blocked, sig); -- if (blocked || ignored || sigdfl) { -+ if (blocked || ignored || (handler != HANDLER_CURRENT)) { - action->sa.sa_handler = SIG_DFL; -+ if (handler == HANDLER_EXIT) -+ action->sa.sa_flags |= SA_IMMUTABLE; - if (blocked) { - sigdelset(&t->blocked, sig); - recalc_sigpending_and_wake(t); -@@ -1342,7 +1351,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool - - int force_sig_info(struct kernel_siginfo *info) - { -- return force_sig_info_to_task(info, current, false); -+ return force_sig_info_to_task(info, current, HANDLER_CURRENT); - } - - /* -@@ -1649,6 +1658,32 @@ void force_sig(int sig) - } - EXPORT_SYMBOL(force_sig); - -+void force_fatal_sig(int sig) -+{ -+ struct kernel_siginfo info; -+ -+ clear_siginfo(&info); -+ info.si_signo = sig; -+ info.si_errno = 0; -+ info.si_code = SI_KERNEL; -+ info.si_pid = 0; -+ info.si_uid = 0; -+ force_sig_info_to_task(&info, current, HANDLER_SIG_DFL); -+} -+ -+void force_exit_sig(int sig) -+{ -+ struct kernel_siginfo info; -+ -+ clear_siginfo(&info); -+ info.si_signo = sig; -+ info.si_errno = 0; -+ info.si_code = SI_KERNEL; -+ info.si_pid = 0; -+ info.si_uid = 0; -+ force_sig_info_to_task(&info, current, HANDLER_EXIT); -+} -+ - /* - * When things go south during signal handling, we - * will force a SIGSEGV. And if the signal that caused -@@ -1657,15 +1692,10 @@ EXPORT_SYMBOL(force_sig); - */ - void force_sigsegv(int sig) - { -- struct task_struct *p = current; -- -- if (sig == SIGSEGV) { -- unsigned long flags; -- spin_lock_irqsave(&p->sighand->siglock, flags); -- p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; -- spin_unlock_irqrestore(&p->sighand->siglock, flags); -- } -- force_sig(SIGSEGV); -+ if (sig == SIGSEGV) -+ force_fatal_sig(SIGSEGV); -+ else -+ force_sig(SIGSEGV); - } - - int force_sig_fault_to_task(int sig, int code, void __user *addr -@@ -1684,7 +1714,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr - info.si_flags = flags; - info.si_isr = isr; - #endif -- return force_sig_info_to_task(&info, t, false); -+ return force_sig_info_to_task(&info, t, HANDLER_CURRENT); - } - - int force_sig_fault(int sig, int code, void __user *addr -@@ -1804,7 +1834,8 @@ int force_sig_seccomp(int syscall, int reason, bool force_coredump) - info.si_errno = reason; - info.si_arch = syscall_get_arch(current); - info.si_syscall = syscall; -- return force_sig_info_to_task(&info, current, force_coredump); -+ return force_sig_info_to_task(&info, current, -+ force_coredump ? HANDLER_EXIT : HANDLER_CURRENT); - } - - /* For the crazy architectures that include trap information in -@@ -2169,15 +2200,6 @@ static inline bool may_ptrace_stop(void) - return true; - } - --/* -- * Return non-zero if there is a SIGKILL that should be waking us up. -- * Called with the siglock held. -- */ --static bool sigkill_pending(struct task_struct *tsk) --{ -- return sigismember(&tsk->pending.signal, SIGKILL) || -- sigismember(&tsk->signal->shared_pending.signal, SIGKILL); --} - - /* - * This must be called with current->sighand->siglock held. -@@ -2204,17 +2226,16 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t - * calling arch_ptrace_stop, so we must release it now. - * To preserve proper semantics, we must do this before - * any signal bookkeeping like checking group_stop_count. -- * Meanwhile, a SIGKILL could come in before we retake the -- * siglock. That must prevent us from sleeping in TASK_TRACED. -- * So after regaining the lock, we must check for SIGKILL. - */ - spin_unlock_irq(¤t->sighand->siglock); - arch_ptrace_stop(exit_code, info); - spin_lock_irq(¤t->sighand->siglock); -- if (sigkill_pending(current)) -- return; - } - -+ /* -+ * schedule() will not sleep if there is a pending signal that -+ * can awaken the task. -+ */ - set_special_state(TASK_TRACED); - - /* -@@ -2739,7 +2760,8 @@ relock: - if (!signr) - break; /* will return 0 */ - -- if (unlikely(current->ptrace) && signr != SIGKILL) { -+ if (unlikely(current->ptrace) && (signr != SIGKILL) && -+ !(sighand->action[signr -1].sa.sa_flags & SA_IMMUTABLE)) { - signr = ptrace_signal(signr, &ksig->info); - if (!signr) - continue; -@@ -4089,6 +4111,10 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) - k = &p->sighand->action[sig-1]; - - spin_lock_irq(&p->sighand->siglock); -+ if (k->sa.sa_flags & SA_IMMUTABLE) { -+ spin_unlock_irq(&p->sighand->siglock); -+ return -EINVAL; -+ } - if (oact) - *oact = *k; - -diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c -index 643d412ac6235..96b4e78104266 100644 ---- a/kernel/time/posix-cpu-timers.c -+++ b/kernel/time/posix-cpu-timers.c -@@ -1158,14 +1158,29 @@ static void posix_cpu_timers_work(struct callback_head *work) - handle_posix_cpu_timers(current); - } - -+/* -+ * Clear existing posix CPU timers task work. -+ */ -+void clear_posix_cputimers_work(struct task_struct *p) -+{ -+ /* -+ * A copied work entry from the old task is not meaningful, clear it. -+ * N.B. init_task_work will not do this. -+ */ -+ memset(&p->posix_cputimers_work.work, 0, -+ sizeof(p->posix_cputimers_work.work)); -+ init_task_work(&p->posix_cputimers_work.work, -+ posix_cpu_timers_work); -+ p->posix_cputimers_work.scheduled = false; -+} -+ - /* - * Initialize posix CPU timers task work in init task. Out of line to - * keep the callback static and to avoid header recursion hell. - */ - void __init posix_cputimers_init_work(void) - { -- init_task_work(¤t->posix_cputimers_work.work, -- posix_cpu_timers_work); -+ clear_posix_cputimers_work(current); - } - - /* -diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c -index b348749a9fc62..dcdcb85121e40 100644 ---- a/kernel/time/timekeeping.c -+++ b/kernel/time/timekeeping.c -@@ -1306,8 +1306,7 @@ int do_settimeofday64(const struct timespec64 *ts) - timekeeping_forward_now(tk); - - xt = tk_xtime(tk); -- ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; -- ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; -+ ts_delta = timespec64_sub(*ts, xt); - - if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { - ret = -EINVAL; -diff --git a/kernel/time/timer.c b/kernel/time/timer.c -index e3d2c23c413d4..85f1021ad4595 100644 ---- a/kernel/time/timer.c -+++ b/kernel/time/timer.c -@@ -2054,26 +2054,28 @@ unsigned long msleep_interruptible(unsigned int msecs) - EXPORT_SYMBOL(msleep_interruptible); - - /** -- * usleep_range - Sleep for an approximate time -- * @min: Minimum time in usecs to sleep -- * @max: Maximum time in usecs to sleep -+ * usleep_range_state - Sleep for an approximate time in a given state -+ * @min: Minimum time in usecs to sleep -+ * @max: Maximum time in usecs to sleep -+ * @state: State of the current task that will be while sleeping - * - * In non-atomic context where the exact wakeup time is flexible, use -- * usleep_range() instead of udelay(). The sleep improves responsiveness -+ * usleep_range_state() instead of udelay(). The sleep improves responsiveness - * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces - * power usage by allowing hrtimers to take advantage of an already- - * scheduled interrupt instead of scheduling a new one just for this sleep. - */ --void __sched usleep_range(unsigned long min, unsigned long max) -+void __sched usleep_range_state(unsigned long min, unsigned long max, -+ unsigned int state) - { - ktime_t exp = ktime_add_us(ktime_get(), min); - u64 delta = (u64)(max - min) * NSEC_PER_USEC; - - for (;;) { -- __set_current_state(TASK_UNINTERRUPTIBLE); -+ __set_current_state(state); - /* Do not return before the requested sleep time has elapsed */ - if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS)) - break; - } - } --EXPORT_SYMBOL(usleep_range); -+EXPORT_SYMBOL(usleep_range_state); -diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c -index 8e2eb950aa829..6c1038526d1fc 100644 ---- a/kernel/trace/bpf_trace.c -+++ b/kernel/trace/bpf_trace.c -@@ -1037,8 +1037,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) - return &bpf_ktime_get_ns_proto; - case BPF_FUNC_ktime_get_boot_ns: - return &bpf_ktime_get_boot_ns_proto; -- case BPF_FUNC_ktime_get_coarse_ns: -- return &bpf_ktime_get_coarse_ns_proto; - case BPF_FUNC_tail_call: - return &bpf_tail_call_proto; - case BPF_FUNC_get_current_pid_tgid: -diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index feebf57c64588..c672040142e98 100644 ---- a/kernel/trace/ftrace.c -+++ b/kernel/trace/ftrace.c -@@ -988,8 +988,9 @@ static __init void ftrace_profile_tracefs(struct dentry *d_tracer) - } - } - -- entry = tracefs_create_file("function_profile_enabled", 0644, -- d_tracer, NULL, &ftrace_profile_fops); -+ entry = tracefs_create_file("function_profile_enabled", -+ TRACE_MODE_WRITE, d_tracer, NULL, -+ &ftrace_profile_fops); - if (!entry) - pr_warn("Could not create tracefs 'function_profile_enabled' entry\n"); - } -@@ -6109,10 +6110,10 @@ void ftrace_create_filter_files(struct ftrace_ops *ops, - struct dentry *parent) - { - -- trace_create_file("set_ftrace_filter", 0644, parent, -+ trace_create_file("set_ftrace_filter", TRACE_MODE_WRITE, parent, - ops, &ftrace_filter_fops); - -- trace_create_file("set_ftrace_notrace", 0644, parent, -+ trace_create_file("set_ftrace_notrace", TRACE_MODE_WRITE, parent, - ops, &ftrace_notrace_fops); - } - -@@ -6139,19 +6140,19 @@ void ftrace_destroy_filter_files(struct ftrace_ops *ops) - static __init int ftrace_init_dyn_tracefs(struct dentry *d_tracer) - { - -- trace_create_file("available_filter_functions", 0444, -+ trace_create_file("available_filter_functions", TRACE_MODE_READ, - d_tracer, NULL, &ftrace_avail_fops); - -- trace_create_file("enabled_functions", 0444, -+ trace_create_file("enabled_functions", TRACE_MODE_READ, - d_tracer, NULL, &ftrace_enabled_fops); - - ftrace_create_filter_files(&global_ops, d_tracer); - - #ifdef CONFIG_FUNCTION_GRAPH_TRACER -- trace_create_file("set_graph_function", 0644, d_tracer, -+ trace_create_file("set_graph_function", TRACE_MODE_WRITE, d_tracer, - NULL, - &ftrace_graph_fops); -- trace_create_file("set_graph_notrace", 0644, d_tracer, -+ trace_create_file("set_graph_notrace", TRACE_MODE_WRITE, d_tracer, - NULL, - &ftrace_graph_notrace_fops); - #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -@@ -7494,10 +7495,10 @@ static const struct file_operations ftrace_no_pid_fops = { - - void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer) - { -- trace_create_file("set_ftrace_pid", 0644, d_tracer, -+ trace_create_file("set_ftrace_pid", TRACE_MODE_WRITE, d_tracer, - tr, &ftrace_pid_fops); -- trace_create_file("set_ftrace_notrace_pid", 0644, d_tracer, -- tr, &ftrace_no_pid_fops); -+ trace_create_file("set_ftrace_notrace_pid", TRACE_MODE_WRITE, -+ d_tracer, tr, &ftrace_no_pid_fops); - } - - void __init ftrace_init_tracefs_toplevel(struct trace_array *tr, -diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c -index c5a3fbf19617e..46ae72095c1e2 100644 ---- a/kernel/trace/ring_buffer.c -+++ b/kernel/trace/ring_buffer.c -@@ -5233,6 +5233,9 @@ void ring_buffer_reset(struct trace_buffer *buffer) - struct ring_buffer_per_cpu *cpu_buffer; - int cpu; - -+ /* prevent another thread from changing buffer sizes */ -+ mutex_lock(&buffer->mutex); -+ - for_each_buffer_cpu(buffer, cpu) { - cpu_buffer = buffer->buffers[cpu]; - -@@ -5251,6 +5254,8 @@ void ring_buffer_reset(struct trace_buffer *buffer) - atomic_dec(&cpu_buffer->record_disabled); - atomic_dec(&cpu_buffer->resize_disabled); - } -+ -+ mutex_unlock(&buffer->mutex); - } - EXPORT_SYMBOL_GPL(ring_buffer_reset); - -diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index bc677cd642240..18db461f77cdf 100644 ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -1714,7 +1714,8 @@ static void trace_create_maxlat_file(struct trace_array *tr, - { - INIT_WORK(&tr->fsnotify_work, latency_fsnotify_workfn); - init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq); -- tr->d_max_latency = trace_create_file("tracing_max_latency", 0644, -+ tr->d_max_latency = trace_create_file("tracing_max_latency", -+ TRACE_MODE_WRITE, - d_tracer, &tr->max_latency, - &tracing_max_lat_fops); - } -@@ -1748,8 +1749,8 @@ void latency_fsnotify(struct trace_array *tr) - || defined(CONFIG_OSNOISE_TRACER) - - #define trace_create_maxlat_file(tr, d_tracer) \ -- trace_create_file("tracing_max_latency", 0644, d_tracer, \ -- &tr->max_latency, &tracing_max_lat_fops) -+ trace_create_file("tracing_max_latency", TRACE_MODE_WRITE, \ -+ d_tracer, &tr->max_latency, &tracing_max_lat_fops) - - #else - #define trace_create_maxlat_file(tr, d_tracer) do { } while (0) -@@ -3835,6 +3836,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, - iter->fmt[i] = '\0'; - trace_seq_vprintf(&iter->seq, iter->fmt, ap); - -+ /* -+ * If iter->seq is full, the above call no longer guarantees -+ * that ap is in sync with fmt processing, and further calls -+ * to va_arg() can return wrong positional arguments. -+ * -+ * Ensure that ap is no longer used in this case. -+ */ -+ if (iter->seq.full) { -+ p = ""; -+ break; -+ } -+ - if (star) - len = va_arg(ap, int); - -@@ -6077,7 +6090,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start, - - static void trace_create_eval_file(struct dentry *d_tracer) - { -- trace_create_file("eval_map", 0444, d_tracer, -+ trace_create_file("eval_map", TRACE_MODE_READ, d_tracer, - NULL, &tracing_eval_map_fops); - } - -@@ -8590,27 +8603,27 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu) - } - - /* per cpu trace_pipe */ -- trace_create_cpu_file("trace_pipe", 0444, d_cpu, -+ trace_create_cpu_file("trace_pipe", TRACE_MODE_READ, d_cpu, - tr, cpu, &tracing_pipe_fops); - - /* per cpu trace */ -- trace_create_cpu_file("trace", 0644, d_cpu, -+ trace_create_cpu_file("trace", TRACE_MODE_WRITE, d_cpu, - tr, cpu, &tracing_fops); - -- trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu, -+ trace_create_cpu_file("trace_pipe_raw", TRACE_MODE_READ, d_cpu, - tr, cpu, &tracing_buffers_fops); - -- trace_create_cpu_file("stats", 0444, d_cpu, -+ trace_create_cpu_file("stats", TRACE_MODE_READ, d_cpu, - tr, cpu, &tracing_stats_fops); - -- trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, -+ trace_create_cpu_file("buffer_size_kb", TRACE_MODE_READ, d_cpu, - tr, cpu, &tracing_entries_fops); - - #ifdef CONFIG_TRACER_SNAPSHOT -- trace_create_cpu_file("snapshot", 0644, d_cpu, -+ trace_create_cpu_file("snapshot", TRACE_MODE_WRITE, d_cpu, - tr, cpu, &snapshot_fops); - -- trace_create_cpu_file("snapshot_raw", 0444, d_cpu, -+ trace_create_cpu_file("snapshot_raw", TRACE_MODE_READ, d_cpu, - tr, cpu, &snapshot_raw_fops); - #endif - } -@@ -8816,8 +8829,8 @@ create_trace_option_file(struct trace_array *tr, - topt->opt = opt; - topt->tr = tr; - -- topt->entry = trace_create_file(opt->name, 0644, t_options, topt, -- &trace_options_fops); -+ topt->entry = trace_create_file(opt->name, TRACE_MODE_WRITE, -+ t_options, topt, &trace_options_fops); - - } - -@@ -8892,7 +8905,7 @@ create_trace_option_core_file(struct trace_array *tr, - if (!t_options) - return NULL; - -- return trace_create_file(option, 0644, t_options, -+ return trace_create_file(option, TRACE_MODE_WRITE, t_options, - (void *)&tr->trace_flags_index[index], - &trace_options_core_fops); - } -@@ -9417,28 +9430,28 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) - struct trace_event_file *file; - int cpu; - -- trace_create_file("available_tracers", 0444, d_tracer, -+ trace_create_file("available_tracers", TRACE_MODE_READ, d_tracer, - tr, &show_traces_fops); - -- trace_create_file("current_tracer", 0644, d_tracer, -+ trace_create_file("current_tracer", TRACE_MODE_WRITE, d_tracer, - tr, &set_tracer_fops); - -- trace_create_file("tracing_cpumask", 0644, d_tracer, -+ trace_create_file("tracing_cpumask", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_cpumask_fops); - -- trace_create_file("trace_options", 0644, d_tracer, -+ trace_create_file("trace_options", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_iter_fops); - -- trace_create_file("trace", 0644, d_tracer, -+ trace_create_file("trace", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_fops); - -- trace_create_file("trace_pipe", 0444, d_tracer, -+ trace_create_file("trace_pipe", TRACE_MODE_READ, d_tracer, - tr, &tracing_pipe_fops); - -- trace_create_file("buffer_size_kb", 0644, d_tracer, -+ trace_create_file("buffer_size_kb", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_entries_fops); - -- trace_create_file("buffer_total_size_kb", 0444, d_tracer, -+ trace_create_file("buffer_total_size_kb", TRACE_MODE_READ, d_tracer, - tr, &tracing_total_entries_fops); - - trace_create_file("free_buffer", 0200, d_tracer, -@@ -9449,25 +9462,25 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) - - file = __find_event_file(tr, "ftrace", "print"); - if (file && file->dir) -- trace_create_file("trigger", 0644, file->dir, file, -- &event_trigger_fops); -+ trace_create_file("trigger", TRACE_MODE_WRITE, file->dir, -+ file, &event_trigger_fops); - tr->trace_marker_file = file; - - trace_create_file("trace_marker_raw", 0220, d_tracer, - tr, &tracing_mark_raw_fops); - -- trace_create_file("trace_clock", 0644, d_tracer, tr, -+ trace_create_file("trace_clock", TRACE_MODE_WRITE, d_tracer, tr, - &trace_clock_fops); - -- trace_create_file("tracing_on", 0644, d_tracer, -+ trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer, - tr, &rb_simple_fops); - -- trace_create_file("timestamp_mode", 0444, d_tracer, tr, -+ trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr, - &trace_time_stamp_mode_fops); - - tr->buffer_percent = 50; - -- trace_create_file("buffer_percent", 0444, d_tracer, -+ trace_create_file("buffer_percent", TRACE_MODE_READ, d_tracer, - tr, &buffer_percent_fops); - - create_trace_options_dir(tr); -@@ -9478,11 +9491,11 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) - MEM_FAIL(1, "Could not allocate function filter files"); - - #ifdef CONFIG_TRACER_SNAPSHOT -- trace_create_file("snapshot", 0644, d_tracer, -+ trace_create_file("snapshot", TRACE_MODE_WRITE, d_tracer, - tr, &snapshot_fops); - #endif - -- trace_create_file("error_log", 0644, d_tracer, -+ trace_create_file("error_log", TRACE_MODE_WRITE, d_tracer, - tr, &tracing_err_log_fops); - - for_each_tracing_cpu(cpu) -@@ -9675,19 +9688,19 @@ static __init int tracer_init_tracefs(void) - init_tracer_tracefs(&global_trace, NULL); - ftrace_init_tracefs_toplevel(&global_trace, NULL); - -- trace_create_file("tracing_thresh", 0644, NULL, -+ trace_create_file("tracing_thresh", TRACE_MODE_WRITE, NULL, - &global_trace, &tracing_thresh_fops); - -- trace_create_file("README", 0444, NULL, -+ trace_create_file("README", TRACE_MODE_READ, NULL, - NULL, &tracing_readme_fops); - -- trace_create_file("saved_cmdlines", 0444, NULL, -+ trace_create_file("saved_cmdlines", TRACE_MODE_READ, NULL, - NULL, &tracing_saved_cmdlines_fops); - -- trace_create_file("saved_cmdlines_size", 0644, NULL, -+ trace_create_file("saved_cmdlines_size", TRACE_MODE_WRITE, NULL, - NULL, &tracing_saved_cmdlines_size_fops); - -- trace_create_file("saved_tgids", 0444, NULL, -+ trace_create_file("saved_tgids", TRACE_MODE_READ, NULL, - NULL, &tracing_saved_tgids_fops); - - trace_eval_init(); -@@ -9699,7 +9712,7 @@ static __init int tracer_init_tracefs(void) - #endif - - #ifdef CONFIG_DYNAMIC_FTRACE -- trace_create_file("dyn_ftrace_total_info", 0444, NULL, -+ trace_create_file("dyn_ftrace_total_info", TRACE_MODE_READ, NULL, - NULL, &tracing_dyn_info_fops); - #endif - -diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h -index b7c0f8e160fb4..421374c304fc0 100644 ---- a/kernel/trace/trace.h -+++ b/kernel/trace/trace.h -@@ -27,6 +27,9 @@ - #include <asm/syscall.h> /* some archs define it here */ - #endif - -+#define TRACE_MODE_WRITE 0640 -+#define TRACE_MODE_READ 0440 -+ - enum trace_type { - __TRACE_FIRST_TYPE = 0, - -@@ -1357,14 +1360,26 @@ __event_trigger_test_discard(struct trace_event_file *file, - if (eflags & EVENT_FILE_FL_TRIGGER_COND) - *tt = event_triggers_call(file, buffer, entry, event); - -- if (test_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags) || -- (unlikely(file->flags & EVENT_FILE_FL_FILTERED) && -- !filter_match_preds(file->filter, entry))) { -- __trace_event_discard_commit(buffer, event); -- return true; -- } -+ if (likely(!(file->flags & (EVENT_FILE_FL_SOFT_DISABLED | -+ EVENT_FILE_FL_FILTERED | -+ EVENT_FILE_FL_PID_FILTER)))) -+ return false; -+ -+ if (file->flags & EVENT_FILE_FL_SOFT_DISABLED) -+ goto discard; -+ -+ if (file->flags & EVENT_FILE_FL_FILTERED && -+ !filter_match_preds(file->filter, entry)) -+ goto discard; -+ -+ if ((file->flags & EVENT_FILE_FL_PID_FILTER) && -+ trace_event_ignore_this_pid(file)) -+ goto discard; - - return false; -+ discard: -+ __trace_event_discard_commit(buffer, event); -+ return true; - } - - /** -diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c -index 8d252f63cd784..0580287d7a0d1 100644 ---- a/kernel/trace/trace_boot.c -+++ b/kernel/trace/trace_boot.c -@@ -430,6 +430,8 @@ trace_boot_init_histograms(struct trace_event_file *file, - /* All digit started node should be instances. */ - if (trace_boot_compose_hist_cmd(node, buf, size) == 0) { - tmp = kstrdup(buf, GFP_KERNEL); -+ if (!tmp) -+ return; - if (trigger_process_regex(file, buf) < 0) - pr_err("Failed to apply hist trigger: %s\n", tmp); - kfree(tmp); -@@ -439,6 +441,8 @@ trace_boot_init_histograms(struct trace_event_file *file, - if (xbc_node_find_subkey(hnode, "keys")) { - if (trace_boot_compose_hist_cmd(hnode, buf, size) == 0) { - tmp = kstrdup(buf, GFP_KERNEL); -+ if (!tmp) -+ return; - if (trigger_process_regex(file, buf) < 0) - pr_err("Failed to apply hist trigger: %s\n", tmp); - kfree(tmp); -diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c -index 1110112e55bd7..e34e8182ee4b5 100644 ---- a/kernel/trace/trace_dynevent.c -+++ b/kernel/trace/trace_dynevent.c -@@ -262,7 +262,7 @@ static __init int init_dynamic_event(void) - if (ret) - return 0; - -- entry = tracefs_create_file("dynamic_events", 0644, NULL, -+ entry = tracefs_create_file("dynamic_events", TRACE_MODE_WRITE, NULL, - NULL, &dynamic_events_ops); - - /* Event list interface */ -diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c -index 6aed10e2f7ce0..fba8cb77a73af 100644 ---- a/kernel/trace/trace_event_perf.c -+++ b/kernel/trace/trace_event_perf.c -@@ -441,13 +441,13 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, - if (!rcu_is_watching()) - return; - -- if ((unsigned long)ops->private != smp_processor_id()) -- return; -- - bit = ftrace_test_recursion_trylock(ip, parent_ip); - if (bit < 0) - return; - -+ if ((unsigned long)ops->private != smp_processor_id()) -+ goto out; -+ - event = container_of(ops, struct perf_event, ftrace_ops); - - /* -diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c -index 830b3b9940f4c..44d031ffe5112 100644 ---- a/kernel/trace/trace_events.c -+++ b/kernel/trace/trace_events.c -@@ -2312,7 +2312,8 @@ event_subsystem_dir(struct trace_array *tr, const char *name, - /* the ftrace system is special, do not create enable or filter files */ - if (strcmp(name, "ftrace") != 0) { - -- entry = tracefs_create_file("filter", 0644, dir->entry, dir, -+ entry = tracefs_create_file("filter", TRACE_MODE_WRITE, -+ dir->entry, dir, - &ftrace_subsystem_filter_fops); - if (!entry) { - kfree(system->filter); -@@ -2320,7 +2321,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name, - pr_warn("Could not create tracefs '%s/filter' entry\n", name); - } - -- trace_create_file("enable", 0644, dir->entry, dir, -+ trace_create_file("enable", TRACE_MODE_WRITE, dir->entry, dir, - &ftrace_system_enable_fops); - } - -@@ -2402,12 +2403,12 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) - } - - if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) -- trace_create_file("enable", 0644, file->dir, file, -+ trace_create_file("enable", TRACE_MODE_WRITE, file->dir, file, - &ftrace_enable_fops); - - #ifdef CONFIG_PERF_EVENTS - if (call->event.type && call->class->reg) -- trace_create_file("id", 0444, file->dir, -+ trace_create_file("id", TRACE_MODE_READ, file->dir, - (void *)(long)call->event.type, - &ftrace_event_id_fops); - #endif -@@ -2423,22 +2424,22 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) - * triggers or filters. - */ - if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) { -- trace_create_file("filter", 0644, file->dir, file, -- &ftrace_event_filter_fops); -+ trace_create_file("filter", TRACE_MODE_WRITE, file->dir, -+ file, &ftrace_event_filter_fops); - -- trace_create_file("trigger", 0644, file->dir, file, -- &event_trigger_fops); -+ trace_create_file("trigger", TRACE_MODE_WRITE, file->dir, -+ file, &event_trigger_fops); - } - - #ifdef CONFIG_HIST_TRIGGERS -- trace_create_file("hist", 0444, file->dir, file, -+ trace_create_file("hist", TRACE_MODE_READ, file->dir, file, - &event_hist_fops); - #endif - #ifdef CONFIG_HIST_TRIGGERS_DEBUG -- trace_create_file("hist_debug", 0444, file->dir, file, -+ trace_create_file("hist_debug", TRACE_MODE_READ, file->dir, file, - &event_hist_debug_fops); - #endif -- trace_create_file("format", 0444, file->dir, call, -+ trace_create_file("format", TRACE_MODE_READ, file->dir, call, - &ftrace_event_format_fops); - - #ifdef CONFIG_TRACE_EVENT_INJECT -@@ -2677,12 +2678,22 @@ static struct trace_event_file * - trace_create_new_event(struct trace_event_call *call, - struct trace_array *tr) - { -+ struct trace_pid_list *no_pid_list; -+ struct trace_pid_list *pid_list; - struct trace_event_file *file; - - file = kmem_cache_alloc(file_cachep, GFP_TRACE); - if (!file) - return NULL; - -+ pid_list = rcu_dereference_protected(tr->filtered_pids, -+ lockdep_is_held(&event_mutex)); -+ no_pid_list = rcu_dereference_protected(tr->filtered_no_pids, -+ lockdep_is_held(&event_mutex)); -+ -+ if (pid_list || no_pid_list) -+ file->flags |= EVENT_FILE_FL_PID_FILTER; -+ - file->event_call = call; - file->tr = tr; - atomic_set(&file->sm_ref, 0); -@@ -3433,7 +3444,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) - struct dentry *d_events; - struct dentry *entry; - -- entry = tracefs_create_file("set_event", 0644, parent, -+ entry = tracefs_create_file("set_event", TRACE_MODE_WRITE, parent, - tr, &ftrace_set_event_fops); - if (!entry) { - pr_warn("Could not create tracefs 'set_event' entry\n"); -@@ -3446,7 +3457,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) - return -ENOMEM; - } - -- entry = trace_create_file("enable", 0644, d_events, -+ entry = trace_create_file("enable", TRACE_MODE_WRITE, d_events, - tr, &ftrace_tr_enable_fops); - if (!entry) { - pr_warn("Could not create tracefs 'enable' entry\n"); -@@ -3455,24 +3466,25 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) - - /* There are not as crucial, just warn if they are not created */ - -- entry = tracefs_create_file("set_event_pid", 0644, parent, -+ entry = tracefs_create_file("set_event_pid", TRACE_MODE_WRITE, parent, - tr, &ftrace_set_event_pid_fops); - if (!entry) - pr_warn("Could not create tracefs 'set_event_pid' entry\n"); - -- entry = tracefs_create_file("set_event_notrace_pid", 0644, parent, -- tr, &ftrace_set_event_notrace_pid_fops); -+ entry = tracefs_create_file("set_event_notrace_pid", -+ TRACE_MODE_WRITE, parent, tr, -+ &ftrace_set_event_notrace_pid_fops); - if (!entry) - pr_warn("Could not create tracefs 'set_event_notrace_pid' entry\n"); - - /* ring buffer internal formats */ -- entry = trace_create_file("header_page", 0444, d_events, -+ entry = trace_create_file("header_page", TRACE_MODE_READ, d_events, - ring_buffer_print_page_header, - &ftrace_show_header_fops); - if (!entry) - pr_warn("Could not create tracefs 'header_page' entry\n"); - -- entry = trace_create_file("header_event", 0444, d_events, -+ entry = trace_create_file("header_event", TRACE_MODE_READ, d_events, - ring_buffer_print_entry_header, - &ftrace_show_header_fops); - if (!entry) -@@ -3689,8 +3701,8 @@ __init int event_trace_init(void) - if (!tr) - return -ENODEV; - -- entry = tracefs_create_file("available_events", 0444, NULL, -- tr, &ftrace_avail_fops); -+ entry = tracefs_create_file("available_events", TRACE_MODE_READ, -+ NULL, tr, &ftrace_avail_fops); - if (!entry) - pr_warn("Could not create tracefs 'available_events' entry\n"); - -diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c -index f01e442716e2f..12a735bd90a56 100644 ---- a/kernel/trace/trace_events_hist.c -+++ b/kernel/trace/trace_events_hist.c -@@ -1733,9 +1733,10 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data, - if (!hist_field->type) - goto free; - -- if (field->filter_type == FILTER_STATIC_STRING) -+ if (field->filter_type == FILTER_STATIC_STRING) { - hist_field->fn = hist_field_string; -- else if (field->filter_type == FILTER_DYN_STRING) -+ hist_field->size = field->size; -+ } else if (field->filter_type == FILTER_DYN_STRING) - hist_field->fn = hist_field_dynstring; - else - hist_field->fn = hist_field_pstring; -@@ -2690,8 +2691,10 @@ static inline void __update_field_vars(struct tracing_map_elt *elt, - if (val->flags & HIST_FIELD_FL_STRING) { - char *str = elt_data->field_var_str[j++]; - char *val_str = (char *)(uintptr_t)var_val; -+ unsigned int size; - -- strscpy(str, val_str, STR_VAR_LEN_MAX); -+ size = min(val->size, STR_VAR_LEN_MAX); -+ strscpy(str, val_str, size); - var_val = (u64)(uintptr_t)str; - } - tracing_map_set_var(elt, var_idx, var_val); -@@ -3416,7 +3419,7 @@ static int check_synth_field(struct synth_event *event, - - if (strcmp(field->type, hist_field->type) != 0) { - if (field->size != hist_field->size || -- field->is_signed != hist_field->is_signed) -+ (!field->is_string && field->is_signed != hist_field->is_signed)) - return -EINVAL; - } - -@@ -4578,6 +4581,7 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, - if (hist_field->flags & HIST_FIELD_FL_STRING) { - unsigned int str_start, var_str_idx, idx; - char *str, *val_str; -+ unsigned int size; - - str_start = hist_data->n_field_var_str + - hist_data->n_save_var_str; -@@ -4586,7 +4590,9 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, - - str = elt_data->field_var_str[idx]; - val_str = (char *)(uintptr_t)hist_val; -- strscpy(str, val_str, STR_VAR_LEN_MAX); -+ -+ size = min(hist_field->size, STR_VAR_LEN_MAX); -+ strscpy(str, val_str, size); - - hist_val = (u64)(uintptr_t)str; - } -diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c -index d54094b7a9d75..22db3ce95e74f 100644 ---- a/kernel/trace/trace_events_synth.c -+++ b/kernel/trace/trace_events_synth.c -@@ -2227,8 +2227,8 @@ static __init int trace_events_synth_init(void) - if (err) - goto err; - -- entry = tracefs_create_file("synthetic_events", 0644, NULL, -- NULL, &synth_events_fops); -+ entry = tracefs_create_file("synthetic_events", TRACE_MODE_WRITE, -+ NULL, NULL, &synth_events_fops); - if (!entry) { - err = -ENODEV; - goto err; -diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c -index 0de6837722da5..6b5ff3ba4251f 100644 ---- a/kernel/trace/trace_functions_graph.c -+++ b/kernel/trace/trace_functions_graph.c -@@ -1340,7 +1340,7 @@ static __init int init_graph_tracefs(void) - if (ret) - return 0; - -- trace_create_file("max_graph_depth", 0644, NULL, -+ trace_create_file("max_graph_depth", TRACE_MODE_WRITE, NULL, - NULL, &graph_depth_fops); - - return 0; -diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c -index 1b83d75eb103b..d0a730d99a331 100644 ---- a/kernel/trace/trace_hwlat.c -+++ b/kernel/trace/trace_hwlat.c -@@ -782,21 +782,21 @@ static int init_tracefs(void) - if (!top_dir) - return -ENOMEM; - -- hwlat_sample_window = tracefs_create_file("window", 0640, -+ hwlat_sample_window = tracefs_create_file("window", TRACE_MODE_WRITE, - top_dir, - &hwlat_window, - &trace_min_max_fops); - if (!hwlat_sample_window) - goto err; - -- hwlat_sample_width = tracefs_create_file("width", 0644, -+ hwlat_sample_width = tracefs_create_file("width", TRACE_MODE_WRITE, - top_dir, - &hwlat_width, - &trace_min_max_fops); - if (!hwlat_sample_width) - goto err; - -- hwlat_thread_mode = trace_create_file("mode", 0644, -+ hwlat_thread_mode = trace_create_file("mode", TRACE_MODE_WRITE, - top_dir, - NULL, - &thread_mode_fops); -diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c -index 3a64ba4bbad6f..92caef33b68c2 100644 ---- a/kernel/trace/trace_kprobe.c -+++ b/kernel/trace/trace_kprobe.c -@@ -1925,16 +1925,16 @@ static __init int init_kprobe_trace(void) - if (ret) - return 0; - -- entry = tracefs_create_file("kprobe_events", 0644, NULL, -- NULL, &kprobe_events_ops); -+ entry = tracefs_create_file("kprobe_events", TRACE_MODE_WRITE, -+ NULL, NULL, &kprobe_events_ops); - - /* Event list interface */ - if (!entry) - pr_warn("Could not create tracefs 'kprobe_events' entry\n"); - - /* Profile interface */ -- entry = tracefs_create_file("kprobe_profile", 0444, NULL, -- NULL, &kprobe_profile_ops); -+ entry = tracefs_create_file("kprobe_profile", TRACE_MODE_READ, -+ NULL, NULL, &kprobe_profile_ops); - - if (!entry) - pr_warn("Could not create tracefs 'kprobe_profile' entry\n"); -diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c -index ce053619f289e..c4f14fb98aaac 100644 ---- a/kernel/trace/trace_osnoise.c -+++ b/kernel/trace/trace_osnoise.c -@@ -1856,38 +1856,38 @@ static int init_tracefs(void) - if (!top_dir) - return 0; - -- tmp = tracefs_create_file("period_us", 0640, top_dir, -+ tmp = tracefs_create_file("period_us", TRACE_MODE_WRITE, top_dir, - &osnoise_period, &trace_min_max_fops); - if (!tmp) - goto err; - -- tmp = tracefs_create_file("runtime_us", 0644, top_dir, -+ tmp = tracefs_create_file("runtime_us", TRACE_MODE_WRITE, top_dir, - &osnoise_runtime, &trace_min_max_fops); - if (!tmp) - goto err; - -- tmp = tracefs_create_file("stop_tracing_us", 0640, top_dir, -+ tmp = tracefs_create_file("stop_tracing_us", TRACE_MODE_WRITE, top_dir, - &osnoise_stop_tracing_in, &trace_min_max_fops); - if (!tmp) - goto err; - -- tmp = tracefs_create_file("stop_tracing_total_us", 0640, top_dir, -+ tmp = tracefs_create_file("stop_tracing_total_us", TRACE_MODE_WRITE, top_dir, - &osnoise_stop_tracing_total, &trace_min_max_fops); - if (!tmp) - goto err; - -- tmp = trace_create_file("cpus", 0644, top_dir, NULL, &cpus_fops); -+ tmp = trace_create_file("cpus", TRACE_MODE_WRITE, top_dir, NULL, &cpus_fops); - if (!tmp) - goto err; - #ifdef CONFIG_TIMERLAT_TRACER - #ifdef CONFIG_STACKTRACE -- tmp = tracefs_create_file("print_stack", 0640, top_dir, -+ tmp = tracefs_create_file("print_stack", TRACE_MODE_WRITE, top_dir, - &osnoise_print_stack, &trace_min_max_fops); - if (!tmp) - goto err; - #endif - -- tmp = tracefs_create_file("timerlat_period_us", 0640, top_dir, -+ tmp = tracefs_create_file("timerlat_period_us", TRACE_MODE_WRITE, top_dir, - &timerlat_period, &trace_min_max_fops); - if (!tmp) - goto err; -diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c -index 4b320fe7df704..29f6e95439b67 100644 ---- a/kernel/trace/trace_printk.c -+++ b/kernel/trace/trace_printk.c -@@ -384,7 +384,7 @@ static __init int init_trace_printk_function_export(void) - if (ret) - return 0; - -- trace_create_file("printk_formats", 0444, NULL, -+ trace_create_file("printk_formats", TRACE_MODE_READ, NULL, - NULL, &ftrace_formats_fops); - - return 0; -diff --git a/kernel/trace/trace_recursion_record.c b/kernel/trace/trace_recursion_record.c -index b2edac1fe156e..4d4b78c8ca257 100644 ---- a/kernel/trace/trace_recursion_record.c -+++ b/kernel/trace/trace_recursion_record.c -@@ -226,8 +226,8 @@ __init static int create_recursed_functions(void) - { - struct dentry *dentry; - -- dentry = trace_create_file("recursed_functions", 0644, NULL, NULL, -- &recursed_functions_fops); -+ dentry = trace_create_file("recursed_functions", TRACE_MODE_WRITE, -+ NULL, NULL, &recursed_functions_fops); - if (!dentry) - pr_warn("WARNING: Failed to create recursed_functions\n"); - return 0; -diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c -index 63c2850420516..5a48dba912eae 100644 ---- a/kernel/trace/trace_stack.c -+++ b/kernel/trace/trace_stack.c -@@ -559,14 +559,14 @@ static __init int stack_trace_init(void) - if (ret) - return 0; - -- trace_create_file("stack_max_size", 0644, NULL, -+ trace_create_file("stack_max_size", TRACE_MODE_WRITE, NULL, - &stack_trace_max_size, &stack_max_size_fops); - -- trace_create_file("stack_trace", 0444, NULL, -+ trace_create_file("stack_trace", TRACE_MODE_READ, NULL, - NULL, &stack_trace_fops); - - #ifdef CONFIG_DYNAMIC_FTRACE -- trace_create_file("stack_trace_filter", 0644, NULL, -+ trace_create_file("stack_trace_filter", TRACE_MODE_WRITE, NULL, - &trace_ops, &stack_trace_filter_fops); - #endif - -diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c -index 8d141c3825a94..bb247beec4470 100644 ---- a/kernel/trace/trace_stat.c -+++ b/kernel/trace/trace_stat.c -@@ -297,9 +297,9 @@ static int init_stat_file(struct stat_session *session) - if (!stat_dir && (ret = tracing_stat_init())) - return ret; - -- session->file = tracefs_create_file(session->ts->name, 0644, -- stat_dir, -- session, &tracing_stat_fops); -+ session->file = tracefs_create_file(session->ts->name, TRACE_MODE_WRITE, -+ stat_dir, session, -+ &tracing_stat_fops); - if (!session->file) - return -ENOMEM; - return 0; -diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c -index 225ce569bf8f8..f5f0039d31e5a 100644 ---- a/kernel/trace/trace_uprobe.c -+++ b/kernel/trace/trace_uprobe.c -@@ -1313,6 +1313,7 @@ static int uprobe_perf_open(struct trace_event_call *call, - return 0; - - list_for_each_entry(pos, trace_probe_probe_list(tp), list) { -+ tu = container_of(pos, struct trace_uprobe, tp); - err = uprobe_apply(tu->inode, tu->offset, &tu->consumer, true); - if (err) { - uprobe_perf_close(call, event); -@@ -1655,10 +1656,10 @@ static __init int init_uprobe_trace(void) - if (ret) - return 0; - -- trace_create_file("uprobe_events", 0644, NULL, -+ trace_create_file("uprobe_events", TRACE_MODE_WRITE, NULL, - NULL, &uprobe_events_ops); - /* Profile interface */ -- trace_create_file("uprobe_profile", 0444, NULL, -+ trace_create_file("uprobe_profile", TRACE_MODE_READ, NULL, - NULL, &uprobe_profile_ops); - return 0; - } -diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c -index d6bddb157ef20..9628b55718468 100644 ---- a/kernel/trace/tracing_map.c -+++ b/kernel/trace/tracing_map.c -@@ -15,6 +15,7 @@ - #include <linux/jhash.h> - #include <linux/slab.h> - #include <linux/sort.h> -+#include <linux/kmemleak.h> - - #include "tracing_map.h" - #include "trace.h" -@@ -307,6 +308,7 @@ static void tracing_map_array_free(struct tracing_map_array *a) - for (i = 0; i < a->n_pages; i++) { - if (!a->pages[i]) - break; -+ kmemleak_free(a->pages[i]); - free_page((unsigned long)a->pages[i]); - } - -@@ -342,6 +344,7 @@ static struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, - a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL); - if (!a->pages[i]) - goto free; -+ kmemleak_alloc(a->pages[i], PAGE_SIZE, 1, GFP_KERNEL); - } - out: - return a; -@@ -834,29 +837,35 @@ int tracing_map_init(struct tracing_map *map) - return err; - } - --static int cmp_entries_dup(const struct tracing_map_sort_entry **a, -- const struct tracing_map_sort_entry **b) -+static int cmp_entries_dup(const void *A, const void *B) - { -+ const struct tracing_map_sort_entry *a, *b; - int ret = 0; - -- if (memcmp((*a)->key, (*b)->key, (*a)->elt->map->key_size)) -+ a = *(const struct tracing_map_sort_entry **)A; -+ b = *(const struct tracing_map_sort_entry **)B; -+ -+ if (memcmp(a->key, b->key, a->elt->map->key_size)) - ret = 1; - - return ret; - } - --static int cmp_entries_sum(const struct tracing_map_sort_entry **a, -- const struct tracing_map_sort_entry **b) -+static int cmp_entries_sum(const void *A, const void *B) - { - const struct tracing_map_elt *elt_a, *elt_b; -+ const struct tracing_map_sort_entry *a, *b; - struct tracing_map_sort_key *sort_key; - struct tracing_map_field *field; - tracing_map_cmp_fn_t cmp_fn; - void *val_a, *val_b; - int ret = 0; - -- elt_a = (*a)->elt; -- elt_b = (*b)->elt; -+ a = *(const struct tracing_map_sort_entry **)A; -+ b = *(const struct tracing_map_sort_entry **)B; -+ -+ elt_a = a->elt; -+ elt_b = b->elt; - - sort_key = &elt_a->map->sort_key; - -@@ -873,18 +882,21 @@ static int cmp_entries_sum(const struct tracing_map_sort_entry **a, - return ret; - } - --static int cmp_entries_key(const struct tracing_map_sort_entry **a, -- const struct tracing_map_sort_entry **b) -+static int cmp_entries_key(const void *A, const void *B) - { - const struct tracing_map_elt *elt_a, *elt_b; -+ const struct tracing_map_sort_entry *a, *b; - struct tracing_map_sort_key *sort_key; - struct tracing_map_field *field; - tracing_map_cmp_fn_t cmp_fn; - void *val_a, *val_b; - int ret = 0; - -- elt_a = (*a)->elt; -- elt_b = (*b)->elt; -+ a = *(const struct tracing_map_sort_entry **)A; -+ b = *(const struct tracing_map_sort_entry **)B; -+ -+ elt_a = a->elt; -+ elt_b = b->elt; - - sort_key = &elt_a->map->sort_key; - -@@ -989,10 +1001,8 @@ static void sort_secondary(struct tracing_map *map, - struct tracing_map_sort_key *primary_key, - struct tracing_map_sort_key *secondary_key) - { -- int (*primary_fn)(const struct tracing_map_sort_entry **, -- const struct tracing_map_sort_entry **); -- int (*secondary_fn)(const struct tracing_map_sort_entry **, -- const struct tracing_map_sort_entry **); -+ int (*primary_fn)(const void *, const void *); -+ int (*secondary_fn)(const void *, const void *); - unsigned i, start = 0, n_sub = 1; - - if (is_key(map, primary_key->field_idx)) -@@ -1061,8 +1071,7 @@ int tracing_map_sort_entries(struct tracing_map *map, - unsigned int n_sort_keys, - struct tracing_map_sort_entry ***sort_entries) - { -- int (*cmp_entries_fn)(const struct tracing_map_sort_entry **, -- const struct tracing_map_sort_entry **); -+ int (*cmp_entries_fn)(const void *, const void *); - struct tracing_map_sort_entry *sort_entry, **entries; - int i, n_entries, ret; - -diff --git a/kernel/workqueue.c b/kernel/workqueue.c -index 1b3eb1e9531f4..76988f39ed5ac 100644 ---- a/kernel/workqueue.c -+++ b/kernel/workqueue.c -@@ -5384,9 +5384,6 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) - int ret = -EINVAL; - cpumask_var_t saved_cpumask; - -- if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) -- return -ENOMEM; -- - /* - * Not excluding isolated cpus on purpose. - * If the user wishes to include them, we allow that. -@@ -5394,6 +5391,15 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) - cpumask_and(cpumask, cpumask, cpu_possible_mask); - if (!cpumask_empty(cpumask)) { - apply_wqattrs_lock(); -+ if (cpumask_equal(cpumask, wq_unbound_cpumask)) { -+ ret = 0; -+ goto out_unlock; -+ } -+ -+ if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) { -+ ret = -ENOMEM; -+ goto out_unlock; -+ } - - /* save the old wq_unbound_cpumask. */ - cpumask_copy(saved_cpumask, wq_unbound_cpumask); -@@ -5406,10 +5412,11 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) - if (ret < 0) - cpumask_copy(wq_unbound_cpumask, saved_cpumask); - -+ free_cpumask_var(saved_cpumask); -+out_unlock: - apply_wqattrs_unlock(); - } - -- free_cpumask_var(saved_cpumask); - return ret; - } - -diff --git a/lib/Kconfig.kfence b/lib/Kconfig.kfence -index e641add339475..912f252a41fc6 100644 ---- a/lib/Kconfig.kfence -+++ b/lib/Kconfig.kfence -@@ -25,17 +25,6 @@ menuconfig KFENCE - - if KFENCE - --config KFENCE_STATIC_KEYS -- bool "Use static keys to set up allocations" -- default y -- depends on JUMP_LABEL # To ensure performance, require jump labels -- help -- Use static keys (static branches) to set up KFENCE allocations. Using -- static keys is normally recommended, because it avoids a dynamic -- branch in the allocator's fast path. However, with very low sample -- intervals, or on systems that do not support jump labels, a dynamic -- branch may still be an acceptable performance trade-off. -- - config KFENCE_SAMPLE_INTERVAL - int "Default sample interval in milliseconds" - default 100 -@@ -56,6 +45,21 @@ config KFENCE_NUM_OBJECTS - pages are required; with one containing the object and two adjacent - ones used as guard pages. - -+config KFENCE_STATIC_KEYS -+ bool "Use static keys to set up allocations" if EXPERT -+ depends on JUMP_LABEL -+ help -+ Use static keys (static branches) to set up KFENCE allocations. This -+ option is only recommended when using very large sample intervals, or -+ performance has carefully been evaluated with this option. -+ -+ Using static keys comes with trade-offs that need to be carefully -+ evaluated given target workloads and system architectures. Notably, -+ enabling and disabling static keys invoke IPI broadcasts, the latency -+ and impact of which is much harder to predict than a dynamic branch. -+ -+ Say N if you are unsure. -+ - config KFENCE_STRESS_TEST_FAULTS - int "Stress testing of fault handling and error reporting" if EXPERT - default 0 -diff --git a/lib/crypto/sm4.c b/lib/crypto/sm4.c -index 633b59fed9db8..284e62576d0c6 100644 ---- a/lib/crypto/sm4.c -+++ b/lib/crypto/sm4.c -@@ -15,7 +15,7 @@ static const u32 fk[4] = { - 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc - }; - --static const u32 __cacheline_aligned ck[32] = { -+static const u32 ____cacheline_aligned ck[32] = { - 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, - 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, - 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, -@@ -26,7 +26,7 @@ static const u32 __cacheline_aligned ck[32] = { - 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 - }; - --static const u8 __cacheline_aligned sbox[256] = { -+static const u8 ____cacheline_aligned sbox[256] = { - 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, - 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, - 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, -diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c -index a2f38e23004aa..f7a3dc13316a3 100644 ---- a/lib/decompress_unxz.c -+++ b/lib/decompress_unxz.c -@@ -167,7 +167,7 @@ - * memeq and memzero are not used much and any remotely sane implementation - * is fast enough. memcpy/memmove speed matters in multi-call mode, but - * the kernel image is decompressed in single-call mode, in which only -- * memcpy speed can matter and only if there is a lot of uncompressible data -+ * memmove speed can matter and only if there is a lot of uncompressible data - * (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the - * functions below should just be kept small; it's probably not worth - * optimizing for speed. -diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c -index cb5abb42c16a2..84c16309cc637 100644 ---- a/lib/dynamic_debug.c -+++ b/lib/dynamic_debug.c -@@ -761,6 +761,18 @@ static __init int ddebug_setup_query(char *str) - - __setup("ddebug_query=", ddebug_setup_query); - -+/* -+ * Install a noop handler to make dyndbg look like a normal kernel cli param. -+ * This avoids warnings about dyndbg being an unknown cli param when supplied -+ * by a user. -+ */ -+static __init int dyndbg_setup(char *str) -+{ -+ return 1; -+} -+ -+__setup("dyndbg=", dyndbg_setup); -+ - /* - * File_ops->write method for <debugfs>/dynamic_debug/control. Gathers the - * command text from userspace, parses and executes it. -diff --git a/lib/iov_iter.c b/lib/iov_iter.c -index 755c10c5138cd..60b5e6edfbaa7 100644 ---- a/lib/iov_iter.c -+++ b/lib/iov_iter.c -@@ -1488,7 +1488,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, - res = get_user_pages_fast(addr, n, - iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, - pages); -- if (unlikely(res < 0)) -+ if (unlikely(res <= 0)) - return res; - return (res == n ? len : res * PAGE_SIZE) - *start; - } -@@ -1612,8 +1612,9 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, - return -ENOMEM; - res = get_user_pages_fast(addr, n, - iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p); -- if (unlikely(res < 0)) { -+ if (unlikely(res <= 0)) { - kvfree(p); -+ *pages = NULL; - return res; - } - *pages = p; -diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c -index f9e89001b52eb..199ab201d5019 100644 ---- a/lib/nmi_backtrace.c -+++ b/lib/nmi_backtrace.c -@@ -75,6 +75,12 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask, - touch_softlockup_watchdog(); - } - -+ /* -+ * Force flush any remote buffers that might be stuck in IRQ context -+ * and therefore could not run their irq_work. -+ */ -+ printk_trigger_flush(); -+ - clear_bit_unlock(0, &backtrace_flag); - put_cpu(); - } -diff --git a/lib/siphash.c b/lib/siphash.c -index a90112ee72a1f..72b9068ab57bf 100644 ---- a/lib/siphash.c -+++ b/lib/siphash.c -@@ -49,6 +49,7 @@ - SIPROUND; \ - return (v0 ^ v1) ^ (v2 ^ v3); - -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) - { - const u8 *end = data + len - (len % sizeof(u64)); -@@ -80,8 +81,8 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) - POSTAMBLE - } - EXPORT_SYMBOL(__siphash_aligned); -+#endif - --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) - { - const u8 *end = data + len - (len % sizeof(u64)); -@@ -113,7 +114,6 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) - POSTAMBLE - } - EXPORT_SYMBOL(__siphash_unaligned); --#endif - - /** - * siphash_1u64 - compute 64-bit siphash PRF value of a u64 -@@ -250,6 +250,7 @@ EXPORT_SYMBOL(siphash_3u32); - HSIPROUND; \ - return (v0 ^ v1) ^ (v2 ^ v3); - -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) - { - const u8 *end = data + len - (len % sizeof(u64)); -@@ -280,8 +281,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) - HPOSTAMBLE - } - EXPORT_SYMBOL(__hsiphash_aligned); -+#endif - --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u32 __hsiphash_unaligned(const void *data, size_t len, - const hsiphash_key_t *key) - { -@@ -313,7 +314,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len, - HPOSTAMBLE - } - EXPORT_SYMBOL(__hsiphash_unaligned); --#endif - - /** - * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32 -@@ -418,6 +418,7 @@ EXPORT_SYMBOL(hsiphash_4u32); - HSIPROUND; \ - return v1 ^ v3; - -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) - { - const u8 *end = data + len - (len % sizeof(u32)); -@@ -438,8 +439,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) - HPOSTAMBLE - } - EXPORT_SYMBOL(__hsiphash_aligned); -+#endif - --#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS - u32 __hsiphash_unaligned(const void *data, size_t len, - const hsiphash_key_t *key) - { -@@ -461,7 +462,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len, - HPOSTAMBLE - } - EXPORT_SYMBOL(__hsiphash_unaligned); --#endif - - /** - * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32 -diff --git a/lib/string_helpers.c b/lib/string_helpers.c -index 3806a52ce697a..2ddc10bd9add6 100644 ---- a/lib/string_helpers.c -+++ b/lib/string_helpers.c -@@ -696,3 +696,23 @@ void kfree_strarray(char **array, size_t n) - kfree(array); - } - EXPORT_SYMBOL_GPL(kfree_strarray); -+ -+/** -+ * memcpy_and_pad - Copy one buffer to another with padding -+ * @dest: Where to copy to -+ * @dest_len: The destination buffer size -+ * @src: Where to copy from -+ * @count: The number of bytes to copy -+ * @pad: Character to use for padding if space is left in destination. -+ */ -+void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, -+ int pad) -+{ -+ if (dest_len > count) { -+ memcpy(dest, src, count); -+ memset(dest + count, pad, dest_len - count); -+ } else { -+ memcpy(dest, src, dest_len); -+ } -+} -+EXPORT_SYMBOL(memcpy_and_pad); -diff --git a/lib/test_bpf.c b/lib/test_bpf.c -index 830a18ecffc88..68d125b409f20 100644 ---- a/lib/test_bpf.c -+++ b/lib/test_bpf.c -@@ -8992,10 +8992,15 @@ static __init int test_bpf(void) - struct tail_call_test { - const char *descr; - struct bpf_insn insns[MAX_INSNS]; -+ int flags; - int result; - int stack_depth; - }; - -+/* Flags that can be passed to tail call test cases */ -+#define FLAG_NEED_STATE BIT(0) -+#define FLAG_RESULT_IN_STATE BIT(1) -+ - /* - * Magic marker used in test snippets for tail calls below. - * BPF_LD/MOV to R2 and R2 with this immediate value is replaced -@@ -9065,32 +9070,38 @@ static struct tail_call_test tail_call_tests[] = { - { - "Tail call error path, max count reached", - .insns = { -- BPF_ALU64_IMM(BPF_ADD, R1, 1), -- BPF_ALU64_REG(BPF_MOV, R0, R1), -+ BPF_LDX_MEM(BPF_W, R2, R1, 0), -+ BPF_ALU64_IMM(BPF_ADD, R2, 1), -+ BPF_STX_MEM(BPF_W, R1, R2, 0), - TAIL_CALL(0), - BPF_EXIT_INSN(), - }, -- .result = MAX_TAIL_CALL_CNT + 1, -+ .flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, -+ .result = (MAX_TAIL_CALL_CNT + 1 + 1) * MAX_TESTRUNS, - }, - { - "Tail call error path, NULL target", - .insns = { -- BPF_ALU64_IMM(BPF_MOV, R0, -1), -+ BPF_LDX_MEM(BPF_W, R2, R1, 0), -+ BPF_ALU64_IMM(BPF_ADD, R2, 1), -+ BPF_STX_MEM(BPF_W, R1, R2, 0), - TAIL_CALL(TAIL_CALL_NULL), -- BPF_ALU64_IMM(BPF_MOV, R0, 1), - BPF_EXIT_INSN(), - }, -- .result = 1, -+ .flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, -+ .result = MAX_TESTRUNS, - }, - { - "Tail call error path, index out of range", - .insns = { -- BPF_ALU64_IMM(BPF_MOV, R0, -1), -+ BPF_LDX_MEM(BPF_W, R2, R1, 0), -+ BPF_ALU64_IMM(BPF_ADD, R2, 1), -+ BPF_STX_MEM(BPF_W, R1, R2, 0), - TAIL_CALL(TAIL_CALL_INVALID), -- BPF_ALU64_IMM(BPF_MOV, R0, 1), - BPF_EXIT_INSN(), - }, -- .result = 1, -+ .flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, -+ .result = MAX_TESTRUNS, - }, - }; - -@@ -9196,6 +9207,8 @@ static __init int test_tail_calls(struct bpf_array *progs) - for (i = 0; i < ARRAY_SIZE(tail_call_tests); i++) { - struct tail_call_test *test = &tail_call_tests[i]; - struct bpf_prog *fp = progs->ptrs[i]; -+ int *data = NULL; -+ int state = 0; - u64 duration; - int ret; - -@@ -9212,7 +9225,11 @@ static __init int test_tail_calls(struct bpf_array *progs) - if (fp->jited) - jit_cnt++; - -- ret = __run_one(fp, NULL, MAX_TESTRUNS, &duration); -+ if (test->flags & FLAG_NEED_STATE) -+ data = &state; -+ ret = __run_one(fp, data, MAX_TESTRUNS, &duration); -+ if (test->flags & FLAG_RESULT_IN_STATE) -+ ret = state; - if (ret == test->result) { - pr_cont("%lld PASS", duration); - pass_cnt++; -diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c -index 7a6781e3f47b6..d548cf0e59fe6 100644 ---- a/lib/xz/xz_dec_lzma2.c -+++ b/lib/xz/xz_dec_lzma2.c -@@ -387,7 +387,14 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, - - *left -= copy_size; - -- memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); -+ /* -+ * If doing in-place decompression in single-call mode and the -+ * uncompressed size of the file is larger than the caller -+ * thought (i.e. it is invalid input!), the buffers below may -+ * overlap and cause undefined behavior with memcpy(). -+ * With valid inputs memcpy() would be fine here. -+ */ -+ memmove(dict->buf + dict->pos, b->in + b->in_pos, copy_size); - dict->pos += copy_size; - - if (dict->full < dict->pos) -@@ -397,7 +404,11 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, - if (dict->pos == dict->end) - dict->pos = 0; - -- memcpy(b->out + b->out_pos, b->in + b->in_pos, -+ /* -+ * Like above but for multi-call mode: use memmove() -+ * to avoid undefined behavior with invalid input. -+ */ -+ memmove(b->out + b->out_pos, b->in + b->in_pos, - copy_size); - } - -@@ -421,6 +432,12 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) - if (dict->pos == dict->end) - dict->pos = 0; - -+ /* -+ * These buffers cannot overlap even if doing in-place -+ * decompression because in multi-call mode dict->buf -+ * has been allocated by us in this file; it's not -+ * provided by the caller like in single-call mode. -+ */ - memcpy(b->out + b->out_pos, dict->buf + dict->start, - copy_size); - } -diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c -index fea86deaaa01d..683570b93a8c4 100644 ---- a/lib/xz/xz_dec_stream.c -+++ b/lib/xz/xz_dec_stream.c -@@ -402,12 +402,12 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) - * we will accept other check types too, but then the check won't - * be verified and a warning (XZ_UNSUPPORTED_CHECK) will be given. - */ -+ if (s->temp.buf[HEADER_MAGIC_SIZE + 1] > XZ_CHECK_MAX) -+ return XZ_OPTIONS_ERROR; -+ - s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; - - #ifdef XZ_DEC_ANY_CHECK -- if (s->check_type > XZ_CHECK_MAX) -- return XZ_OPTIONS_ERROR; -- - if (s->check_type > XZ_CHECK_CRC32) - return XZ_UNSUPPORTED_CHECK; - #else -diff --git a/mm/Kconfig b/mm/Kconfig -index d16ba9249bc53..c048dea7e3420 100644 ---- a/mm/Kconfig -+++ b/mm/Kconfig -@@ -887,6 +887,9 @@ config MAPPING_DIRTY_HELPERS - config KMAP_LOCAL - bool - -+config KMAP_LOCAL_NON_LINEAR_PTE_ARRAY -+ bool -+ - # struct io_mapping based helper. Selected by drivers that need them - config IO_MAPPING - bool -diff --git a/mm/backing-dev.c b/mm/backing-dev.c -index 4a9d4e27d0d9b..02ff66f863587 100644 ---- a/mm/backing-dev.c -+++ b/mm/backing-dev.c -@@ -947,6 +947,13 @@ void bdi_unregister(struct backing_dev_info *bdi) - wb_shutdown(&bdi->wb); - cgwb_bdi_unregister(bdi); - -+ /* -+ * If this BDI's min ratio has been set, use bdi_set_min_ratio() to -+ * update the global bdi_min_ratio. -+ */ -+ if (bdi->min_ratio) -+ bdi_set_min_ratio(bdi, 0); -+ - if (bdi->dev) { - bdi_debug_unregister(bdi); - device_unregister(bdi->dev); -diff --git a/mm/damon/core.c b/mm/damon/core.c -index 30e9211f494a7..7a4912d6e65f2 100644 ---- a/mm/damon/core.c -+++ b/mm/damon/core.c -@@ -357,6 +357,15 @@ int damon_start(struct damon_ctx **ctxs, int nr_ctxs) - return err; - } - -+static void kdamond_usleep(unsigned long usecs) -+{ -+ /* See Documentation/timers/timers-howto.rst for the thresholds */ -+ if (usecs > 20 * 1000) -+ schedule_timeout_idle(usecs_to_jiffies(usecs)); -+ else -+ usleep_idle_range(usecs, usecs + 1); -+} -+ - /* - * __damon_stop() - Stops monitoring of given context. - * @ctx: monitoring context -@@ -370,8 +379,7 @@ static int __damon_stop(struct damon_ctx *ctx) - ctx->kdamond_stop = true; - mutex_unlock(&ctx->kdamond_lock); - while (damon_kdamond_running(ctx)) -- usleep_range(ctx->sample_interval, -- ctx->sample_interval * 2); -+ kdamond_usleep(ctx->sample_interval); - return 0; - } - mutex_unlock(&ctx->kdamond_lock); -@@ -670,7 +678,7 @@ static int kdamond_fn(void *data) - ctx->callback.after_sampling(ctx)) - set_kdamond_stop(ctx); - -- usleep_range(ctx->sample_interval, ctx->sample_interval + 1); -+ kdamond_usleep(ctx->sample_interval); - - if (ctx->primitive.check_accesses) - max_nr_accesses = ctx->primitive.check_accesses(ctx); -diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c -index faee070977d80..f94d19a690dfa 100644 ---- a/mm/damon/dbgfs.c -+++ b/mm/damon/dbgfs.c -@@ -32,7 +32,7 @@ static char *user_input_str(const char __user *buf, size_t count, loff_t *ppos) - if (*ppos) - return ERR_PTR(-EINVAL); - -- kbuf = kmalloc(count + 1, GFP_KERNEL); -+ kbuf = kmalloc(count + 1, GFP_KERNEL | __GFP_NOWARN); - if (!kbuf) - return ERR_PTR(-ENOMEM); - -@@ -247,7 +247,7 @@ static ssize_t dbgfs_kdamond_pid_read(struct file *file, - char *kbuf; - ssize_t len; - -- kbuf = kmalloc(count, GFP_KERNEL); -+ kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); - if (!kbuf) - return -ENOMEM; - -@@ -538,12 +538,14 @@ static ssize_t dbgfs_monitor_on_write(struct file *file, - return -EINVAL; - } - -+ mutex_lock(&damon_dbgfs_lock); - if (!strncmp(kbuf, "on", count)) - err = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs); - else if (!strncmp(kbuf, "off", count)) - err = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs); - else - err = -EINVAL; -+ mutex_unlock(&damon_dbgfs_lock); - - if (err) - ret = err; -@@ -596,15 +598,16 @@ static int __init __damon_dbgfs_init(void) - - static int __init damon_dbgfs_init(void) - { -- int rc; -+ int rc = -ENOMEM; - -+ mutex_lock(&damon_dbgfs_lock); - dbgfs_ctxs = kmalloc(sizeof(*dbgfs_ctxs), GFP_KERNEL); - if (!dbgfs_ctxs) -- return -ENOMEM; -+ goto out; - dbgfs_ctxs[0] = dbgfs_new_ctx(); - if (!dbgfs_ctxs[0]) { - kfree(dbgfs_ctxs); -- return -ENOMEM; -+ goto out; - } - dbgfs_nr_ctxs = 1; - -@@ -615,6 +618,8 @@ static int __init damon_dbgfs_init(void) - pr_err("%s: dbgfs init failed\n", __func__); - } - -+out: -+ mutex_unlock(&damon_dbgfs_lock); - return rc; - } - -diff --git a/mm/filemap.c b/mm/filemap.c -index dae481293b5d9..82a17c35eb96b 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -2093,7 +2093,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t start, - if (!xa_is_value(page)) { - if (page->index < start) - goto put; -- VM_BUG_ON_PAGE(page->index != xas.xa_index, page); - if (page->index + thp_nr_pages(page) - 1 > end) - goto put; - if (!trylock_page(page)) -diff --git a/mm/highmem.c b/mm/highmem.c -index 4212ad0e4a195..1f0c8a52fd807 100644 ---- a/mm/highmem.c -+++ b/mm/highmem.c -@@ -504,16 +504,22 @@ static inline int kmap_local_calc_idx(int idx) - - static pte_t *__kmap_pte; - --static pte_t *kmap_get_pte(void) -+static pte_t *kmap_get_pte(unsigned long vaddr, int idx) - { -+ if (IS_ENABLED(CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY)) -+ /* -+ * Set by the arch if __kmap_pte[-idx] does not produce -+ * the correct entry. -+ */ -+ return virt_to_kpte(vaddr); - if (!__kmap_pte) - __kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); -- return __kmap_pte; -+ return &__kmap_pte[-idx]; - } - - void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot) - { -- pte_t pteval, *kmap_pte = kmap_get_pte(); -+ pte_t pteval, *kmap_pte; - unsigned long vaddr; - int idx; - -@@ -525,9 +531,10 @@ void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot) - preempt_disable(); - idx = arch_kmap_local_map_idx(kmap_local_idx_push(), pfn); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -- BUG_ON(!pte_none(*(kmap_pte - idx))); -+ kmap_pte = kmap_get_pte(vaddr, idx); -+ BUG_ON(!pte_none(*kmap_pte)); - pteval = pfn_pte(pfn, prot); -- arch_kmap_local_set_pte(&init_mm, vaddr, kmap_pte - idx, pteval); -+ arch_kmap_local_set_pte(&init_mm, vaddr, kmap_pte, pteval); - arch_kmap_local_post_map(vaddr, pteval); - current->kmap_ctrl.pteval[kmap_local_idx()] = pteval; - preempt_enable(); -@@ -560,7 +567,7 @@ EXPORT_SYMBOL(__kmap_local_page_prot); - void kunmap_local_indexed(void *vaddr) - { - unsigned long addr = (unsigned long) vaddr & PAGE_MASK; -- pte_t *kmap_pte = kmap_get_pte(); -+ pte_t *kmap_pte; - int idx; - - if (addr < __fix_to_virt(FIX_KMAP_END) || -@@ -585,8 +592,9 @@ void kunmap_local_indexed(void *vaddr) - idx = arch_kmap_local_unmap_idx(kmap_local_idx(), addr); - WARN_ON_ONCE(addr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); - -+ kmap_pte = kmap_get_pte(addr, idx); - arch_kmap_local_pre_unmap(addr); -- pte_clear(&init_mm, addr, kmap_pte - idx); -+ pte_clear(&init_mm, addr, kmap_pte); - arch_kmap_local_post_unmap(addr); - current->kmap_ctrl.pteval[kmap_local_idx()] = __pte(0); - kmap_local_idx_pop(); -@@ -608,7 +616,7 @@ EXPORT_SYMBOL(kunmap_local_indexed); - void __kmap_local_sched_out(void) - { - struct task_struct *tsk = current; -- pte_t *kmap_pte = kmap_get_pte(); -+ pte_t *kmap_pte; - int i; - - /* Clear kmaps */ -@@ -635,8 +643,9 @@ void __kmap_local_sched_out(void) - idx = arch_kmap_local_map_idx(i, pte_pfn(pteval)); - - addr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -+ kmap_pte = kmap_get_pte(addr, idx); - arch_kmap_local_pre_unmap(addr); -- pte_clear(&init_mm, addr, kmap_pte - idx); -+ pte_clear(&init_mm, addr, kmap_pte); - arch_kmap_local_post_unmap(addr); - } - } -@@ -644,7 +653,7 @@ void __kmap_local_sched_out(void) - void __kmap_local_sched_in(void) - { - struct task_struct *tsk = current; -- pte_t *kmap_pte = kmap_get_pte(); -+ pte_t *kmap_pte; - int i; - - /* Restore kmaps */ -@@ -664,7 +673,8 @@ void __kmap_local_sched_in(void) - /* See comment in __kmap_local_sched_out() */ - idx = arch_kmap_local_map_idx(i, pte_pfn(pteval)); - addr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -- set_pte_at(&init_mm, addr, kmap_pte - idx, pteval); -+ kmap_pte = kmap_get_pte(addr, idx); -+ set_pte_at(&init_mm, addr, kmap_pte, pteval); - arch_kmap_local_post_map(addr, pteval); - } - } -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 95dc7b83381f9..f5ed98843557b 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -4439,6 +4439,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, - struct hstate *h = hstate_vma(vma); - unsigned long sz = huge_page_size(h); - struct mmu_notifier_range range; -+ bool force_flush = false; - - WARN_ON(!is_vm_hugetlb_page(vma)); - BUG_ON(start & ~huge_page_mask(h)); -@@ -4467,10 +4468,8 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, - ptl = huge_pte_lock(h, mm, ptep); - if (huge_pmd_unshare(mm, vma, &address, ptep)) { - spin_unlock(ptl); -- /* -- * We just unmapped a page of PMDs by clearing a PUD. -- * The caller's TLB flush range should cover this area. -- */ -+ tlb_flush_pmd_range(tlb, address & PUD_MASK, PUD_SIZE); -+ force_flush = true; - continue; - } - -@@ -4527,6 +4526,22 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, - } - mmu_notifier_invalidate_range_end(&range); - tlb_end_vma(tlb, vma); -+ -+ /* -+ * If we unshared PMDs, the TLB flush was not recorded in mmu_gather. We -+ * could defer the flush until now, since by holding i_mmap_rwsem we -+ * guaranteed that the last refernece would not be dropped. But we must -+ * do the flushing before we return, as otherwise i_mmap_rwsem will be -+ * dropped and the last reference to the shared PMDs page might be -+ * dropped as well. -+ * -+ * In theory we could defer the freeing of the PMD pages as well, but -+ * huge_pmd_unshare() relies on the exact page_count for the PMD page to -+ * detect sharing, so we cannot defer the release of the page either. -+ * Instead, do flush now. -+ */ -+ if (force_flush) -+ tlb_flush_mmu_tlbonly(tlb); - } - - void __unmap_hugepage_range_final(struct mmu_gather *tlb, -@@ -5236,13 +5251,14 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, - int ret = -ENOMEM; - struct page *page; - int writable; -- bool new_pagecache_page = false; -+ bool page_in_pagecache = false; - - if (is_continue) { - ret = -EFAULT; - page = find_lock_page(mapping, idx); - if (!page) - goto out; -+ page_in_pagecache = true; - } else if (!*pagep) { - /* If a page already exists, then it's UFFDIO_COPY for - * a non-missing case. Return -EEXIST. -@@ -5330,7 +5346,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, - ret = huge_add_to_page_cache(page, mapping, idx); - if (ret) - goto out_release_nounlock; -- new_pagecache_page = true; -+ page_in_pagecache = true; - } - - ptl = huge_pte_lockptr(h, dst_mm, dst_pte); -@@ -5394,7 +5410,7 @@ out_release_unlock: - if (vm_shared || is_continue) - unlock_page(page); - out_release_nounlock: -- if (!new_pagecache_page) -+ if (!page_in_pagecache) - restore_reserve_on_error(h, dst_vma, dst_addr, page); - put_page(page); - goto out; -diff --git a/mm/kfence/core.c b/mm/kfence/core.c -index 7a97db8bc8e75..4b69236aea722 100644 ---- a/mm/kfence/core.c -+++ b/mm/kfence/core.c -@@ -97,10 +97,11 @@ struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS]; - static struct list_head kfence_freelist = LIST_HEAD_INIT(kfence_freelist); - static DEFINE_RAW_SPINLOCK(kfence_freelist_lock); /* Lock protecting freelist. */ - --#ifdef CONFIG_KFENCE_STATIC_KEYS --/* The static key to set up a KFENCE allocation. */ -+/* -+ * The static key to set up a KFENCE allocation; or if static keys are not used -+ * to gate allocations, to avoid a load and compare if KFENCE is disabled. -+ */ - DEFINE_STATIC_KEY_FALSE(kfence_allocation_key); --#endif - - /* Gates the allocation, ensuring only one succeeds in a given period. */ - atomic_t kfence_allocation_gate = ATOMIC_INIT(1); -@@ -668,6 +669,8 @@ void __init kfence_init(void) - return; - } - -+ if (!IS_ENABLED(CONFIG_KFENCE_STATIC_KEYS)) -+ static_branch_enable(&kfence_allocation_key); - WRITE_ONCE(kfence_enabled, true); - queue_delayed_work(system_unbound_wq, &kfence_timer, 0); - pr_info("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n", KFENCE_POOL_SIZE, -@@ -752,12 +755,7 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) - (s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32))) - return NULL; - -- /* -- * allocation_gate only needs to become non-zero, so it doesn't make -- * sense to continue writing to it and pay the associated contention -- * cost, in case we have a large number of concurrent allocations. -- */ -- if (atomic_read(&kfence_allocation_gate) || atomic_inc_return(&kfence_allocation_gate) > 1) -+ if (atomic_inc_return(&kfence_allocation_gate) > 1) - return NULL; - #ifdef CONFIG_KFENCE_STATIC_KEYS - /* -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index 6da5020a8656d..87e41c3cac101 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -239,7 +239,7 @@ enum res_type { - iter != NULL; \ - iter = mem_cgroup_iter(NULL, iter, NULL)) - --static inline bool should_force_charge(void) -+static inline bool task_is_dying(void) - { - return tsk_is_oom_victim(current) || fatal_signal_pending(current) || - (current->flags & PF_EXITING); -@@ -1575,7 +1575,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, - * A few threads which were not waiting at mutex_lock_killable() can - * fail to bail out. Therefore, check again after holding oom_lock. - */ -- ret = should_force_charge() || out_of_memory(&oc); -+ ret = task_is_dying() || out_of_memory(&oc); - - unlock: - mutex_unlock(&oom_lock); -@@ -2530,6 +2530,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask, - struct page_counter *counter; - enum oom_status oom_status; - unsigned long nr_reclaimed; -+ bool passed_oom = false; - bool may_swap = true; - bool drained = false; - unsigned long pflags; -@@ -2564,15 +2565,6 @@ retry: - if (gfp_mask & __GFP_ATOMIC) - goto force; - -- /* -- * Unlike in global OOM situations, memcg is not in a physical -- * memory shortage. Allow dying and OOM-killed tasks to -- * bypass the last charges so that they can exit quickly and -- * free their memory. -- */ -- if (unlikely(should_force_charge())) -- goto force; -- - /* - * Prevent unbounded recursion when reclaim operations need to - * allocate memory. This might exceed the limits temporarily, -@@ -2630,8 +2622,9 @@ retry: - if (gfp_mask & __GFP_RETRY_MAYFAIL) - goto nomem; - -- if (fatal_signal_pending(current)) -- goto force; -+ /* Avoid endless loop for tasks bypassed by the oom killer */ -+ if (passed_oom && task_is_dying()) -+ goto nomem; - - /* - * keep retrying as long as the memcg oom killer is able to make -@@ -2640,14 +2633,10 @@ retry: - */ - oom_status = mem_cgroup_oom(mem_over_limit, gfp_mask, - get_order(nr_pages * PAGE_SIZE)); -- switch (oom_status) { -- case OOM_SUCCESS: -+ if (oom_status == OOM_SUCCESS) { -+ passed_oom = true; - nr_retries = MAX_RECLAIM_RETRIES; - goto retry; -- case OOM_FAILED: -- goto force; -- default: -- goto nomem; - } - nomem: - if (!(gfp_mask & __GFP_NOFAIL)) -diff --git a/mm/oom_kill.c b/mm/oom_kill.c -index 989f35a2bbb1d..bfa9e348c3a3a 100644 ---- a/mm/oom_kill.c -+++ b/mm/oom_kill.c -@@ -1120,27 +1120,24 @@ bool out_of_memory(struct oom_control *oc) - } - - /* -- * The pagefault handler calls here because it is out of memory, so kill a -- * memory-hogging task. If oom_lock is held by somebody else, a parallel oom -- * killing is already in progress so do nothing. -+ * The pagefault handler calls here because some allocation has failed. We have -+ * to take care of the memcg OOM here because this is the only safe context without -+ * any locks held but let the oom killer triggered from the allocation context care -+ * about the global OOM. - */ - void pagefault_out_of_memory(void) - { -- struct oom_control oc = { -- .zonelist = NULL, -- .nodemask = NULL, -- .memcg = NULL, -- .gfp_mask = 0, -- .order = 0, -- }; -+ static DEFINE_RATELIMIT_STATE(pfoom_rs, DEFAULT_RATELIMIT_INTERVAL, -+ DEFAULT_RATELIMIT_BURST); - - if (mem_cgroup_oom_synchronize(true)) - return; - -- if (!mutex_trylock(&oom_lock)) -+ if (fatal_signal_pending(current)) - return; -- out_of_memory(&oc); -- mutex_unlock(&oom_lock); -+ -+ if (__ratelimit(&pfoom_rs)) -+ pr_warn("Huh VM_FAULT_OOM leaked out to the #PF handler. Retrying PF\n"); - } - - SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags) -diff --git a/mm/slab.h b/mm/slab.h -index 58c01a34e5b86..56ad7eea3ddfb 100644 ---- a/mm/slab.h -+++ b/mm/slab.h -@@ -147,7 +147,7 @@ static inline slab_flags_t kmem_cache_flags(unsigned int object_size, - #define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE | SLAB_RECLAIM_ACCOUNT | \ - SLAB_TEMPORARY | SLAB_ACCOUNT) - #else --#define SLAB_CACHE_FLAGS (0) -+#define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE) - #endif - - /* Common flags available with current configuration */ -diff --git a/mm/slub.c b/mm/slub.c -index d8f77346376d8..ca6ba6bdf27b1 100644 ---- a/mm/slub.c -+++ b/mm/slub.c -@@ -5072,6 +5072,7 @@ struct loc_track { - unsigned long max; - unsigned long count; - struct location *loc; -+ loff_t idx; - }; - - static struct dentry *slab_debugfs_root; -@@ -6035,11 +6036,11 @@ __initcall(slab_sysfs_init); - #if defined(CONFIG_SLUB_DEBUG) && defined(CONFIG_DEBUG_FS) - static int slab_debugfs_show(struct seq_file *seq, void *v) - { -- -- struct location *l; -- unsigned int idx = *(unsigned int *)v; - struct loc_track *t = seq->private; -+ struct location *l; -+ unsigned long idx; - -+ idx = (unsigned long) t->idx; - if (idx < t->count) { - l = &t->loc[idx]; - -@@ -6088,16 +6089,18 @@ static void *slab_debugfs_next(struct seq_file *seq, void *v, loff_t *ppos) - { - struct loc_track *t = seq->private; - -- v = ppos; -- ++*ppos; -+ t->idx = ++(*ppos); - if (*ppos <= t->count) -- return v; -+ return ppos; - - return NULL; - } - - static void *slab_debugfs_start(struct seq_file *seq, loff_t *ppos) - { -+ struct loc_track *t = seq->private; -+ -+ t->idx = *ppos; - return ppos; - } - -diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c -index 68e8831068f4b..b897ce3b399a1 100644 ---- a/mm/zsmalloc.c -+++ b/mm/zsmalloc.c -@@ -1830,10 +1830,11 @@ static inline void zs_pool_dec_isolated(struct zs_pool *pool) - VM_BUG_ON(atomic_long_read(&pool->isolated_pages) <= 0); - atomic_long_dec(&pool->isolated_pages); - /* -- * There's no possibility of racing, since wait_for_isolated_drain() -- * checks the isolated count under &class->lock after enqueuing -- * on migration_wait. -+ * Checking pool->destroying must happen after atomic_long_dec() -+ * for pool->isolated_pages above. Paired with the smp_mb() in -+ * zs_unregister_migration(). - */ -+ smp_mb__after_atomic(); - if (atomic_long_read(&pool->isolated_pages) == 0 && pool->destroying) - wake_up_all(&pool->migration_wait); - } -diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c -index 55275ef9a31a7..abaa5d96ded24 100644 ---- a/net/8021q/vlan.c -+++ b/net/8021q/vlan.c -@@ -123,9 +123,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) - } - - vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); -- -- /* Get rid of the vlan's reference to real_dev */ -- dev_put(real_dev); - } - - int vlan_check_real_dev(struct net_device *real_dev, -@@ -187,9 +184,6 @@ int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack) - if (err) - goto out_unregister_netdev; - -- /* Account for reference in struct vlan_dev_priv */ -- dev_hold(real_dev); -- - vlan_stacked_transfer_operstate(real_dev, dev, vlan); - linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ - -diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c -index 0c21d1fec8522..8602885c8a8e0 100644 ---- a/net/8021q/vlan_dev.c -+++ b/net/8021q/vlan_dev.c -@@ -615,6 +615,9 @@ static int vlan_dev_init(struct net_device *dev) - if (!vlan->vlan_pcpu_stats) - return -ENOMEM; - -+ /* Get vlan's reference to real_dev */ -+ dev_hold(real_dev); -+ - return 0; - } - -@@ -843,6 +846,9 @@ static void vlan_dev_free(struct net_device *dev) - - free_percpu(vlan->vlan_pcpu_stats); - vlan->vlan_pcpu_stats = NULL; -+ -+ /* Get rid of the vlan's reference to real_dev */ -+ dev_put(vlan->real_dev); - } - - void vlan_setup(struct net_device *dev) -diff --git a/net/9p/client.c b/net/9p/client.c -index 213f12ed76cd8..7973267ec8464 100644 ---- a/net/9p/client.c -+++ b/net/9p/client.c -@@ -541,6 +541,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) - kfree(ename); - } else { - err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode); -+ if (err) -+ goto out_err; - err = -ecode; - - p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); -diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c -index c99d65ef13b1e..160c016a5dfb9 100644 ---- a/net/bluetooth/l2cap_sock.c -+++ b/net/bluetooth/l2cap_sock.c -@@ -1508,6 +1508,9 @@ static void l2cap_sock_close_cb(struct l2cap_chan *chan) - { - struct sock *sk = chan->data; - -+ if (!sk) -+ return; -+ - l2cap_sock_kill(sk); - } - -@@ -1516,6 +1519,9 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) - struct sock *sk = chan->data; - struct sock *parent; - -+ if (!sk) -+ return; -+ - BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); - - /* This callback can be called both for server (BT_LISTEN) -@@ -1707,8 +1713,10 @@ static void l2cap_sock_destruct(struct sock *sk) - { - BT_DBG("sk %p", sk); - -- if (l2cap_pi(sk)->chan) -+ if (l2cap_pi(sk)->chan) { -+ l2cap_pi(sk)->chan->data = NULL; - l2cap_chan_put(l2cap_pi(sk)->chan); -+ } - - if (l2cap_pi(sk)->rx_busy_skb) { - kfree_skb(l2cap_pi(sk)->rx_busy_skb); -diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c -index 98a8815865128..6e047e178c0ab 100644 ---- a/net/bluetooth/sco.c -+++ b/net/bluetooth/sco.c -@@ -133,6 +133,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) - return NULL; - - spin_lock_init(&conn->lock); -+ INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout); - - hcon->sco_data = conn; - conn->hcon = hcon; -@@ -187,20 +188,21 @@ static void sco_conn_del(struct hci_conn *hcon, int err) - /* Kill socket */ - sco_conn_lock(conn); - sk = conn->sk; -+ if (sk) -+ sock_hold(sk); - sco_conn_unlock(conn); - - if (sk) { -- sock_hold(sk); - lock_sock(sk); - sco_sock_clear_timer(sk); - sco_chan_del(sk, err); - release_sock(sk); - sock_put(sk); -- -- /* Ensure no more work items will run before freeing conn. */ -- cancel_delayed_work_sync(&conn->timeout_work); - } - -+ /* Ensure no more work items will run before freeing conn. */ -+ cancel_delayed_work_sync(&conn->timeout_work); -+ - hcon->sco_data = NULL; - kfree(conn); - } -@@ -213,8 +215,6 @@ static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, - sco_pi(sk)->conn = conn; - conn->sk = sk; - -- INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout); -- - if (parent) - bt_accept_enqueue(parent, sk, true); - } -@@ -280,7 +280,8 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk) - return err; - } - --static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) -+static int sco_send_frame(struct sock *sk, void *buf, int len, -+ unsigned int msg_flags) - { - struct sco_conn *conn = sco_pi(sk)->conn; - struct sk_buff *skb; -@@ -292,15 +293,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) - - BT_DBG("sk %p len %d", sk, len); - -- skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); -+ skb = bt_skb_send_alloc(sk, len, msg_flags & MSG_DONTWAIT, &err); - if (!skb) - return err; - -- if (memcpy_from_msg(skb_put(skb, len), msg, len)) { -- kfree_skb(skb); -- return -EFAULT; -- } -- -+ memcpy(skb_put(skb, len), buf, len); - hci_send_sco(conn->hcon, skb); - - return len; -@@ -725,6 +722,7 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg, - size_t len) - { - struct sock *sk = sock->sk; -+ void *buf; - int err; - - BT_DBG("sock %p, sk %p", sock, sk); -@@ -736,14 +734,24 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg, - if (msg->msg_flags & MSG_OOB) - return -EOPNOTSUPP; - -+ buf = kmalloc(len, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ if (memcpy_from_msg(buf, msg, len)) { -+ kfree(buf); -+ return -EFAULT; -+ } -+ - lock_sock(sk); - - if (sk->sk_state == BT_CONNECTED) -- err = sco_send_frame(sk, msg, len); -+ err = sco_send_frame(sk, buf, len, msg->msg_flags); - else - err = -ENOTCONN; - - release_sock(sk); -+ kfree(buf); - return err; - } - -diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h -index 37ca76406f1e8..fd5e7e74573ce 100644 ---- a/net/bridge/br_private.h -+++ b/net/bridge/br_private.h -@@ -1911,11 +1911,13 @@ static inline int br_cfm_status_fill_info(struct sk_buff *skb, - - static inline int br_cfm_mep_count(struct net_bridge *br, u32 *count) - { -+ *count = 0; - return -EOPNOTSUPP; - } - - static inline int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count) - { -+ *count = 0; - return -EOPNOTSUPP; - } - #endif -diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c -index 9bc55ecb37f9f..8452b0fbb78c9 100644 ---- a/net/can/j1939/main.c -+++ b/net/can/j1939/main.c -@@ -75,6 +75,13 @@ static void j1939_can_recv(struct sk_buff *iskb, void *data) - skcb->addr.pgn = (cf->can_id >> 8) & J1939_PGN_MAX; - /* set default message type */ - skcb->addr.type = J1939_TP; -+ -+ if (!j1939_address_is_valid(skcb->addr.sa)) { -+ netdev_err_once(priv->ndev, "%s: sa is broadcast address, ignoring!\n", -+ __func__); -+ goto done; -+ } -+ - if (j1939_pgn_is_pdu1(skcb->addr.pgn)) { - /* Type 1: with destination address */ - skcb->addr.da = skcb->addr.pgn; -diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c -index 6c0a0ebdd024c..a271688780a2c 100644 ---- a/net/can/j1939/transport.c -+++ b/net/can/j1939/transport.c -@@ -2023,6 +2023,11 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) - extd = J1939_ETP; - fallthrough; - case J1939_TP_CMD_BAM: -+ if (cmd == J1939_TP_CMD_BAM && !j1939_cb_is_broadcast(skcb)) { -+ netdev_err_once(priv->ndev, "%s: BAM to unicast (%02x), ignoring!\n", -+ __func__, skcb->addr.sa); -+ return; -+ } - fallthrough; - case J1939_TP_CMD_RTS: - if (skcb->addr.type != extd) -@@ -2085,6 +2090,12 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) - break; - - case J1939_ETP_CMD_ABORT: /* && J1939_TP_CMD_ABORT */ -+ if (j1939_cb_is_broadcast(skcb)) { -+ netdev_err_once(priv->ndev, "%s: abort to broadcast (%02x), ignoring!\n", -+ __func__, skcb->addr.sa); -+ return; -+ } -+ - if (j1939_tp_im_transmitter(skcb)) - j1939_xtp_rx_abort(priv, skb, true); - -diff --git a/net/core/dev.c b/net/core/dev.c -index eb3a366bf212c..91f53eeb0e79f 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2921,6 +2921,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) - if (dev->num_tc) - netif_setup_tc(dev, txq); - -+ dev_qdisc_change_real_num_tx(dev, txq); -+ - dev->real_num_tx_queues = txq; - - if (disabling) { -@@ -4193,7 +4195,10 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) - if (dev->flags & IFF_UP) { - int cpu = smp_processor_id(); /* ok because BHs are off */ - -- if (txq->xmit_lock_owner != cpu) { -+ /* Other cpus might concurrently change txq->xmit_lock_owner -+ * to -1 or to their cpu id, but not to our id. -+ */ -+ if (READ_ONCE(txq->xmit_lock_owner) != cpu) { - if (dev_xmit_recursion()) - goto recursion_alert; - -diff --git a/net/core/devlink.c b/net/core/devlink.c -index a856ae401ea5c..6931713e363fd 100644 ---- a/net/core/devlink.c -+++ b/net/core/devlink.c -@@ -4031,14 +4031,6 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) - return err; - } - -- if (info->attrs[DEVLINK_ATTR_NETNS_PID] || -- info->attrs[DEVLINK_ATTR_NETNS_FD] || -- info->attrs[DEVLINK_ATTR_NETNS_ID]) { -- dest_net = devlink_netns_get(skb, info); -- if (IS_ERR(dest_net)) -- return PTR_ERR(dest_net); -- } -- - if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION]) - action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]); - else -@@ -4081,6 +4073,14 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) - return -EINVAL; - } - } -+ if (info->attrs[DEVLINK_ATTR_NETNS_PID] || -+ info->attrs[DEVLINK_ATTR_NETNS_FD] || -+ info->attrs[DEVLINK_ATTR_NETNS_ID]) { -+ dest_net = devlink_netns_get(skb, info); -+ if (IS_ERR(dest_net)) -+ return PTR_ERR(dest_net); -+ } -+ - err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack); - - if (dest_net) -diff --git a/net/core/dst_cache.c b/net/core/dst_cache.c -index be74ab4551c20..0ccfd5fa5cb9b 100644 ---- a/net/core/dst_cache.c -+++ b/net/core/dst_cache.c -@@ -162,3 +162,22 @@ void dst_cache_destroy(struct dst_cache *dst_cache) - free_percpu(dst_cache->cache); - } - EXPORT_SYMBOL_GPL(dst_cache_destroy); -+ -+void dst_cache_reset_now(struct dst_cache *dst_cache) -+{ -+ int i; -+ -+ if (!dst_cache->cache) -+ return; -+ -+ dst_cache->reset_ts = jiffies; -+ for_each_possible_cpu(i) { -+ struct dst_cache_pcpu *idst = per_cpu_ptr(dst_cache->cache, i); -+ struct dst_entry *dst = idst->dst; -+ -+ idst->cookie = 0; -+ idst->dst = NULL; -+ dst_release(dst); -+ } -+} -+EXPORT_SYMBOL_GPL(dst_cache_reset_now); -diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c -index 79df7cd9dbc16..1bb567a3b329c 100644 ---- a/net/core/fib_rules.c -+++ b/net/core/fib_rules.c -@@ -323,7 +323,7 @@ jumped: - if (!err && ops->suppress && INDIRECT_CALL_MT(ops->suppress, - fib6_rule_suppress, - fib4_rule_suppress, -- rule, arg)) -+ rule, flags, arg)) - continue; - - if (err != -EAGAIN) { -diff --git a/net/core/filter.c b/net/core/filter.c -index 2e32cee2c4690..1e6831880d1fd 100644 ---- a/net/core/filter.c -+++ b/net/core/filter.c -@@ -7162,6 +7162,8 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) - #endif - case BPF_FUNC_sk_storage_get: - return &bpf_sk_storage_get_cg_sock_proto; -+ case BPF_FUNC_ktime_get_coarse_ns: -+ return &bpf_ktime_get_coarse_ns_proto; - default: - return bpf_base_func_proto(func_id); - } -@@ -9735,22 +9737,46 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, - static struct bpf_insn *bpf_convert_data_end_access(const struct bpf_insn *si, - struct bpf_insn *insn) - { -- /* si->dst_reg = skb->data */ -+ int reg; -+ int temp_reg_off = offsetof(struct sk_buff, cb) + -+ offsetof(struct sk_skb_cb, temp_reg); -+ -+ if (si->src_reg == si->dst_reg) { -+ /* We need an extra register, choose and save a register. */ -+ reg = BPF_REG_9; -+ if (si->src_reg == reg || si->dst_reg == reg) -+ reg--; -+ if (si->src_reg == reg || si->dst_reg == reg) -+ reg--; -+ *insn++ = BPF_STX_MEM(BPF_DW, si->src_reg, reg, temp_reg_off); -+ } else { -+ reg = si->dst_reg; -+ } -+ -+ /* reg = skb->data */ - *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data), -- si->dst_reg, si->src_reg, -+ reg, si->src_reg, - offsetof(struct sk_buff, data)); - /* AX = skb->len */ - *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, len), - BPF_REG_AX, si->src_reg, - offsetof(struct sk_buff, len)); -- /* si->dst_reg = skb->data + skb->len */ -- *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX); -+ /* reg = skb->data + skb->len */ -+ *insn++ = BPF_ALU64_REG(BPF_ADD, reg, BPF_REG_AX); - /* AX = skb->data_len */ - *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data_len), - BPF_REG_AX, si->src_reg, - offsetof(struct sk_buff, data_len)); -- /* si->dst_reg = skb->data + skb->len - skb->data_len */ -- *insn++ = BPF_ALU64_REG(BPF_SUB, si->dst_reg, BPF_REG_AX); -+ -+ /* reg = skb->data + skb->len - skb->data_len */ -+ *insn++ = BPF_ALU64_REG(BPF_SUB, reg, BPF_REG_AX); -+ -+ if (si->src_reg == si->dst_reg) { -+ /* Restore the saved register */ -+ *insn++ = BPF_MOV64_REG(BPF_REG_AX, si->src_reg); -+ *insn++ = BPF_MOV64_REG(si->dst_reg, reg); -+ *insn++ = BPF_LDX_MEM(BPF_DW, reg, BPF_REG_AX, temp_reg_off); -+ } - - return insn; - } -@@ -9761,11 +9787,33 @@ static u32 sk_skb_convert_ctx_access(enum bpf_access_type type, - struct bpf_prog *prog, u32 *target_size) - { - struct bpf_insn *insn = insn_buf; -+ int off; - - switch (si->off) { - case offsetof(struct __sk_buff, data_end): - insn = bpf_convert_data_end_access(si, insn); - break; -+ case offsetof(struct __sk_buff, cb[0]) ... -+ offsetofend(struct __sk_buff, cb[4]) - 1: -+ BUILD_BUG_ON(sizeof_field(struct sk_skb_cb, data) < 20); -+ BUILD_BUG_ON((offsetof(struct sk_buff, cb) + -+ offsetof(struct sk_skb_cb, data)) % -+ sizeof(__u64)); -+ -+ prog->cb_access = 1; -+ off = si->off; -+ off -= offsetof(struct __sk_buff, cb[0]); -+ off += offsetof(struct sk_buff, cb); -+ off += offsetof(struct sk_skb_cb, data); -+ if (type == BPF_WRITE) -+ *insn++ = BPF_STX_MEM(BPF_SIZE(si->code), si->dst_reg, -+ si->src_reg, off); -+ else -+ *insn++ = BPF_LDX_MEM(BPF_SIZE(si->code), si->dst_reg, -+ si->src_reg, off); -+ break; -+ -+ - default: - return bpf_convert_ctx_access(type, si, insn_buf, prog, - target_size); -@@ -10260,6 +10308,8 @@ sk_reuseport_func_proto(enum bpf_func_id func_id, - return &sk_reuseport_load_bytes_relative_proto; - case BPF_FUNC_get_socket_cookie: - return &bpf_get_socket_ptr_cookie_proto; -+ case BPF_FUNC_ktime_get_coarse_ns: -+ return &bpf_ktime_get_coarse_ns_proto; - default: - return bpf_base_func_proto(func_id); - } -@@ -10741,6 +10791,8 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id) - case BPF_FUNC_skc_to_udp6_sock: - func = &bpf_skc_to_udp6_sock_proto; - break; -+ case BPF_FUNC_ktime_get_coarse_ns: -+ return &bpf_ktime_get_coarse_ns_proto; - default: - return bpf_base_func_proto(func_id); - } -diff --git a/net/core/neighbour.c b/net/core/neighbour.c -index 2d5bc3a75faec..ff049733cceeb 100644 ---- a/net/core/neighbour.c -+++ b/net/core/neighbour.c -@@ -379,7 +379,7 @@ EXPORT_SYMBOL(neigh_ifdown); - - static struct neighbour *neigh_alloc(struct neigh_table *tbl, - struct net_device *dev, -- bool exempt_from_gc) -+ u8 flags, bool exempt_from_gc) - { - struct neighbour *n = NULL; - unsigned long now = jiffies; -@@ -412,6 +412,7 @@ do_alloc: - n->updated = n->used = now; - n->nud_state = NUD_NONE; - n->output = neigh_blackhole; -+ n->flags = flags; - seqlock_init(&n->hh.hh_lock); - n->parms = neigh_parms_clone(&tbl->parms); - timer_setup(&n->timer, neigh_timer_handler, 0); -@@ -575,19 +576,18 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, - } - EXPORT_SYMBOL(neigh_lookup_nodev); - --static struct neighbour *___neigh_create(struct neigh_table *tbl, -- const void *pkey, -- struct net_device *dev, -- bool exempt_from_gc, bool want_ref) -+static struct neighbour * -+___neigh_create(struct neigh_table *tbl, const void *pkey, -+ struct net_device *dev, u8 flags, -+ bool exempt_from_gc, bool want_ref) - { -- struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, exempt_from_gc); -- u32 hash_val; -- unsigned int key_len = tbl->key_len; -- int error; -+ u32 hash_val, key_len = tbl->key_len; -+ struct neighbour *n1, *rc, *n; - struct neigh_hash_table *nht; -+ int error; - -+ n = neigh_alloc(tbl, dev, flags, exempt_from_gc); - trace_neigh_create(tbl, dev, pkey, n, exempt_from_gc); -- - if (!n) { - rc = ERR_PTR(-ENOBUFS); - goto out; -@@ -674,7 +674,7 @@ out_neigh_release: - struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, - struct net_device *dev, bool want_ref) - { -- return ___neigh_create(tbl, pkey, dev, false, want_ref); -+ return ___neigh_create(tbl, pkey, dev, 0, false, want_ref); - } - EXPORT_SYMBOL(__neigh_create); - -@@ -733,11 +733,10 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, - - ASSERT_RTNL(); - -- n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); -+ n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL); - if (!n) - goto out; - -- n->protocol = 0; - write_pnet(&n->net, net); - memcpy(n->key, pkey, key_len); - n->dev = dev; -@@ -1217,7 +1216,7 @@ static void neigh_update_hhs(struct neighbour *neigh) - lladdr instead of overriding it - if it is different. - NEIGH_UPDATE_F_ADMIN means that the change is administrative. -- -+ NEIGH_UPDATE_F_USE means that the entry is user triggered. - NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing - NTF_ROUTER flag. - NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as -@@ -1255,6 +1254,12 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, - goto out; - - ext_learn_change = neigh_update_ext_learned(neigh, flags, ¬ify); -+ if (flags & NEIGH_UPDATE_F_USE) { -+ new = old & ~NUD_PERMANENT; -+ neigh->nud_state = new; -+ err = 0; -+ goto out; -+ } - - if (!(new & NUD_VALID)) { - neigh_del_timer(neigh); -@@ -1942,7 +1947,9 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, - - exempt_from_gc = ndm->ndm_state & NUD_PERMANENT || - ndm->ndm_flags & NTF_EXT_LEARNED; -- neigh = ___neigh_create(tbl, dst, dev, exempt_from_gc, true); -+ neigh = ___neigh_create(tbl, dst, dev, -+ ndm->ndm_flags & NTF_EXT_LEARNED, -+ exempt_from_gc, true); - if (IS_ERR(neigh)) { - err = PTR_ERR(neigh); - goto out; -@@ -1961,22 +1968,20 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, - - if (protocol) - neigh->protocol = protocol; -- - if (ndm->ndm_flags & NTF_EXT_LEARNED) - flags |= NEIGH_UPDATE_F_EXT_LEARNED; -- - if (ndm->ndm_flags & NTF_ROUTER) - flags |= NEIGH_UPDATE_F_ISROUTER; -+ if (ndm->ndm_flags & NTF_USE) -+ flags |= NEIGH_UPDATE_F_USE; - -- if (ndm->ndm_flags & NTF_USE) { -+ err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, -+ NETLINK_CB(skb).portid, extack); -+ if (!err && ndm->ndm_flags & NTF_USE) { - neigh_event_send(neigh, NULL); - err = 0; -- } else -- err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, -- NETLINK_CB(skb).portid, extack); -- -+ } - neigh_release(neigh); -- - out: - return err; - } -diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c -index b2e49eb7001d6..dfa5ecff7f738 100644 ---- a/net/core/net-sysfs.c -+++ b/net/core/net-sysfs.c -@@ -175,6 +175,14 @@ static int change_carrier(struct net_device *dev, unsigned long new_carrier) - static ssize_t carrier_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) - { -+ struct net_device *netdev = to_net_dev(dev); -+ -+ /* The check is also done in change_carrier; this helps returning early -+ * without hitting the trylock/restart in netdev_store. -+ */ -+ if (!netdev->netdev_ops->ndo_change_carrier) -+ return -EOPNOTSUPP; -+ - return netdev_store(dev, attr, buf, len, change_carrier); - } - -@@ -196,6 +204,12 @@ static ssize_t speed_show(struct device *dev, - struct net_device *netdev = to_net_dev(dev); - int ret = -EINVAL; - -+ /* The check is also done in __ethtool_get_link_ksettings; this helps -+ * returning early without hitting the trylock/restart below. -+ */ -+ if (!netdev->ethtool_ops->get_link_ksettings) -+ return ret; -+ - if (!rtnl_trylock()) - return restart_syscall(); - -@@ -216,6 +230,12 @@ static ssize_t duplex_show(struct device *dev, - struct net_device *netdev = to_net_dev(dev); - int ret = -EINVAL; - -+ /* The check is also done in __ethtool_get_link_ksettings; this helps -+ * returning early without hitting the trylock/restart below. -+ */ -+ if (!netdev->ethtool_ops->get_link_ksettings) -+ return ret; -+ - if (!rtnl_trylock()) - return restart_syscall(); - -@@ -468,6 +488,14 @@ static ssize_t proto_down_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) - { -+ struct net_device *netdev = to_net_dev(dev); -+ -+ /* The check is also done in change_proto_down; this helps returning -+ * early without hitting the trylock/restart in netdev_store. -+ */ -+ if (!netdev->netdev_ops->ndo_change_proto_down) -+ return -EOPNOTSUPP; -+ - return netdev_store(dev, attr, buf, len, change_proto_down); - } - NETDEVICE_SHOW_RW(proto_down, fmt_dec); -@@ -478,6 +506,12 @@ static ssize_t phys_port_id_show(struct device *dev, - struct net_device *netdev = to_net_dev(dev); - ssize_t ret = -EINVAL; - -+ /* The check is also done in dev_get_phys_port_id; this helps returning -+ * early without hitting the trylock/restart below. -+ */ -+ if (!netdev->netdev_ops->ndo_get_phys_port_id) -+ return -EOPNOTSUPP; -+ - if (!rtnl_trylock()) - return restart_syscall(); - -@@ -500,6 +534,13 @@ static ssize_t phys_port_name_show(struct device *dev, - struct net_device *netdev = to_net_dev(dev); - ssize_t ret = -EINVAL; - -+ /* The checks are also done in dev_get_phys_port_name; this helps -+ * returning early without hitting the trylock/restart below. -+ */ -+ if (!netdev->netdev_ops->ndo_get_phys_port_name && -+ !netdev->netdev_ops->ndo_get_devlink_port) -+ return -EOPNOTSUPP; -+ - if (!rtnl_trylock()) - return restart_syscall(); - -@@ -522,6 +563,14 @@ static ssize_t phys_switch_id_show(struct device *dev, - struct net_device *netdev = to_net_dev(dev); - ssize_t ret = -EINVAL; - -+ /* The checks are also done in dev_get_phys_port_name; this helps -+ * returning early without hitting the trylock/restart below. This works -+ * because recurse is false when calling dev_get_port_parent_id. -+ */ -+ if (!netdev->netdev_ops->ndo_get_port_parent_id && -+ !netdev->netdev_ops->ndo_get_devlink_port) -+ return -EOPNOTSUPP; -+ - if (!rtnl_trylock()) - return restart_syscall(); - -@@ -1226,6 +1275,12 @@ static ssize_t tx_maxrate_store(struct netdev_queue *queue, - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - -+ /* The check is also done later; this helps returning early without -+ * hitting the trylock/restart below. -+ */ -+ if (!dev->netdev_ops->ndo_set_tx_maxrate) -+ return -EOPNOTSUPP; -+ - err = kstrtou32(buf, 10, &rate); - if (err < 0) - return err; -diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c -index a448a9b5bb2d6..202fa5eacd0f9 100644 ---- a/net/core/net_namespace.c -+++ b/net/core/net_namespace.c -@@ -473,7 +473,9 @@ struct net *copy_net_ns(unsigned long flags, - - if (rv < 0) { - put_userns: -+#ifdef CONFIG_KEYS - key_remove_domain(net->key_domain); -+#endif - put_user_ns(user_ns); - net_free(net); - dec_ucounts: -@@ -605,7 +607,9 @@ static void cleanup_net(struct work_struct *work) - list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { - list_del_init(&net->exit_list); - dec_net_namespaces(net->ucounts); -+#ifdef CONFIG_KEYS - key_remove_domain(net->key_domain); -+#endif - put_user_ns(net->user_ns); - net_free(net); - } -diff --git a/net/core/skbuff.c b/net/core/skbuff.c -index fe9358437380c..f7e003571a356 100644 ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -832,7 +832,7 @@ void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt) - ntohs(skb->protocol), skb->pkt_type, skb->skb_iif); - - if (dev) -- printk("%sdev name=%s feat=0x%pNF\n", -+ printk("%sdev name=%s feat=%pNF\n", - level, dev->name, &dev->features); - if (sk) - printk("%ssk family=%hu type=%u proto=%u\n", -@@ -3449,19 +3449,7 @@ EXPORT_SYMBOL(skb_split); - */ - static int skb_prepare_for_shift(struct sk_buff *skb) - { -- int ret = 0; -- -- if (skb_cloned(skb)) { -- /* Save and restore truesize: pskb_expand_head() may reallocate -- * memory where ksize(kmalloc(S)) != ksize(kmalloc(S)), but we -- * cannot change truesize at this point. -- */ -- unsigned int save_truesize = skb->truesize; -- -- ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -- skb->truesize = save_truesize; -- } -- return ret; -+ return skb_unclone_keeptruesize(skb, GFP_ATOMIC); - } - - /** -diff --git a/net/core/skmsg.c b/net/core/skmsg.c -index a86ef7e844f8c..8eb671c827f90 100644 ---- a/net/core/skmsg.c -+++ b/net/core/skmsg.c -@@ -508,6 +508,7 @@ static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk, - } - - static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, -+ u32 off, u32 len, - struct sk_psock *psock, - struct sock *sk, - struct sk_msg *msg) -@@ -521,11 +522,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, - */ - if (skb_linearize(skb)) - return -EAGAIN; -- num_sge = skb_to_sgvec(skb, msg->sg.data, 0, skb->len); -+ num_sge = skb_to_sgvec(skb, msg->sg.data, off, len); - if (unlikely(num_sge < 0)) - return num_sge; - -- copied = skb->len; -+ copied = len; - msg->sg.start = 0; - msg->sg.size = copied; - msg->sg.end = num_sge; -@@ -536,9 +537,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, - return copied; - } - --static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb); -+static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb, -+ u32 off, u32 len); - --static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) -+static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb, -+ u32 off, u32 len) - { - struct sock *sk = psock->sk; - struct sk_msg *msg; -@@ -549,7 +552,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) - * correctly. - */ - if (unlikely(skb->sk == sk)) -- return sk_psock_skb_ingress_self(psock, skb); -+ return sk_psock_skb_ingress_self(psock, skb, off, len); - msg = sk_psock_create_ingress_msg(sk, skb); - if (!msg) - return -EAGAIN; -@@ -561,7 +564,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) - * into user buffers. - */ - skb_set_owner_r(skb, sk); -- err = sk_psock_skb_ingress_enqueue(skb, psock, sk, msg); -+ err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg); - if (err < 0) - kfree(msg); - return err; -@@ -571,7 +574,8 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) - * skb. In this case we do not need to check memory limits or skb_set_owner_r - * because the skb is already accounted for here. - */ --static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb) -+static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb, -+ u32 off, u32 len) - { - struct sk_msg *msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC); - struct sock *sk = psock->sk; -@@ -581,7 +585,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb - return -EAGAIN; - sk_msg_init(msg); - skb_set_owner_r(skb, sk); -- err = sk_psock_skb_ingress_enqueue(skb, psock, sk, msg); -+ err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg); - if (err < 0) - kfree(msg); - return err; -@@ -595,7 +599,7 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb, - return -EAGAIN; - return skb_send_sock(psock->sk, skb, off, len); - } -- return sk_psock_skb_ingress(psock, skb); -+ return sk_psock_skb_ingress(psock, skb, off, len); - } - - static void sk_psock_skb_state(struct sk_psock *psock, -@@ -638,6 +642,12 @@ static void sk_psock_backlog(struct work_struct *work) - while ((skb = skb_dequeue(&psock->ingress_skb))) { - len = skb->len; - off = 0; -+ if (skb_bpf_strparser(skb)) { -+ struct strp_msg *stm = strp_msg(skb); -+ -+ off = stm->offset; -+ len = stm->full_len; -+ } - start: - ingress = skb_bpf_ingress(skb); - skb_bpf_redirect_clear(skb); -@@ -877,6 +887,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb) - * return code, but then didn't set a redirect interface. - */ - if (unlikely(!sk_other)) { -+ skb_bpf_redirect_clear(skb); - sock_drop(from->sk, skb); - return -EIO; - } -@@ -944,6 +955,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, - { - struct sock *sk_other; - int err = 0; -+ u32 len, off; - - switch (verdict) { - case __SK_PASS: -@@ -951,6 +963,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, - sk_other = psock->sk; - if (sock_flag(sk_other, SOCK_DEAD) || - !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { -+ skb_bpf_redirect_clear(skb); - goto out_free; - } - -@@ -963,7 +976,15 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, - * retrying later from workqueue. - */ - if (skb_queue_empty(&psock->ingress_skb)) { -- err = sk_psock_skb_ingress_self(psock, skb); -+ len = skb->len; -+ off = 0; -+ if (skb_bpf_strparser(skb)) { -+ struct strp_msg *stm = strp_msg(skb); -+ -+ off = stm->offset; -+ len = stm->full_len; -+ } -+ err = sk_psock_skb_ingress_self(psock, skb, off, len); - } - if (err < 0) { - spin_lock_bh(&psock->ingress_lock); -@@ -1029,6 +1050,8 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb) - skb_dst_drop(skb); - skb_bpf_redirect_clear(skb); - ret = bpf_prog_run_pin_on_cpu(prog, skb); -+ if (ret == SK_PASS) -+ skb_bpf_set_strparser(skb); - ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb)); - skb->sk = NULL; - } -@@ -1101,6 +1124,8 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) - - void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) - { -+ psock_set_prog(&psock->progs.stream_parser, NULL); -+ - if (!psock->saved_data_ready) - return; - -@@ -1189,6 +1214,9 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) - - void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) - { -+ psock_set_prog(&psock->progs.stream_verdict, NULL); -+ psock_set_prog(&psock->progs.skb_verdict, NULL); -+ - if (!psock->saved_data_ready) - return; - -diff --git a/net/core/sock.c b/net/core/sock.c -index c1601f75ec4b3..1b31e10181629 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -2043,8 +2043,10 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) - newsk->sk_prot_creator = prot; - - /* SANITY */ -- if (likely(newsk->sk_net_refcnt)) -+ if (likely(newsk->sk_net_refcnt)) { - get_net(sock_net(newsk)); -+ sock_inuse_add(sock_net(newsk), 1); -+ } - sk_node_init(&newsk->sk_node); - sock_lock_init(newsk); - bh_lock_sock(newsk); -@@ -2115,8 +2117,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) - newsk->sk_err_soft = 0; - newsk->sk_priority = 0; - newsk->sk_incoming_cpu = raw_smp_processor_id(); -- if (likely(newsk->sk_net_refcnt)) -- sock_inuse_add(sock_net(newsk), 1); - - /* Before updating sk_refcnt, we must commit prior changes to memory - * (Documentation/RCU/rculist_nulls.rst for details) -diff --git a/net/core/sock_map.c b/net/core/sock_map.c -index e252b8ec2b85e..c89f527411e84 100644 ---- a/net/core/sock_map.c -+++ b/net/core/sock_map.c -@@ -167,8 +167,11 @@ static void sock_map_del_link(struct sock *sk, - write_lock_bh(&sk->sk_callback_lock); - if (strp_stop) - sk_psock_stop_strp(sk, psock); -- else -+ if (verdict_stop) - sk_psock_stop_verdict(sk, psock); -+ -+ if (psock->psock_update_sk_prot) -+ psock->psock_update_sk_prot(sk, psock, false); - write_unlock_bh(&sk->sk_callback_lock); - } - } -@@ -282,6 +285,12 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk) - - if (msg_parser) - psock_set_prog(&psock->progs.msg_parser, msg_parser); -+ if (stream_parser) -+ psock_set_prog(&psock->progs.stream_parser, stream_parser); -+ if (stream_verdict) -+ psock_set_prog(&psock->progs.stream_verdict, stream_verdict); -+ if (skb_verdict) -+ psock_set_prog(&psock->progs.skb_verdict, skb_verdict); - - ret = sock_map_init_proto(sk, psock); - if (ret < 0) -@@ -292,14 +301,10 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk) - ret = sk_psock_init_strp(sk, psock); - if (ret) - goto out_unlock_drop; -- psock_set_prog(&psock->progs.stream_verdict, stream_verdict); -- psock_set_prog(&psock->progs.stream_parser, stream_parser); - sk_psock_start_strp(sk, psock); - } else if (!stream_parser && stream_verdict && !psock->saved_data_ready) { -- psock_set_prog(&psock->progs.stream_verdict, stream_verdict); - sk_psock_start_verdict(sk,psock); - } else if (!stream_verdict && skb_verdict && !psock->saved_data_ready) { -- psock_set_prog(&psock->progs.skb_verdict, skb_verdict); - sk_psock_start_verdict(sk, psock); - } - write_unlock_bh(&sk->sk_callback_lock); -diff --git a/net/core/stream.c b/net/core/stream.c -index 4f1d4aa5fb38d..a166a32b411fa 100644 ---- a/net/core/stream.c -+++ b/net/core/stream.c -@@ -195,9 +195,6 @@ void sk_stream_kill_queues(struct sock *sk) - /* First the read buffer. */ - __skb_queue_purge(&sk->sk_receive_queue); - -- /* Next, the error queue. */ -- __skb_queue_purge(&sk->sk_error_queue); -- - /* Next, the write queue. */ - WARN_ON(!skb_queue_empty(&sk->sk_write_queue)); - -diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h -index c5c1d2b8045e8..5183e627468d8 100644 ---- a/net/dccp/dccp.h -+++ b/net/dccp/dccp.h -@@ -48,7 +48,7 @@ extern bool dccp_debug; - - extern struct inet_hashinfo dccp_hashinfo; - --extern struct percpu_counter dccp_orphan_count; -+DECLARE_PER_CPU(unsigned int, dccp_orphan_count); - - void dccp_time_wait(struct sock *sk, int state, int timeo); - -diff --git a/net/dccp/proto.c b/net/dccp/proto.c -index abb5c596a8176..fc44dadc778bb 100644 ---- a/net/dccp/proto.c -+++ b/net/dccp/proto.c -@@ -42,8 +42,8 @@ DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; - - EXPORT_SYMBOL_GPL(dccp_statistics); - --struct percpu_counter dccp_orphan_count; --EXPORT_SYMBOL_GPL(dccp_orphan_count); -+DEFINE_PER_CPU(unsigned int, dccp_orphan_count); -+EXPORT_PER_CPU_SYMBOL_GPL(dccp_orphan_count); - - struct inet_hashinfo dccp_hashinfo; - EXPORT_SYMBOL_GPL(dccp_hashinfo); -@@ -1055,7 +1055,7 @@ adjudge_to_death: - bh_lock_sock(sk); - WARN_ON(sock_owned_by_user(sk)); - -- percpu_counter_inc(sk->sk_prot->orphan_count); -+ this_cpu_inc(dccp_orphan_count); - - /* Have we already been destroyed by a softirq or backlog? */ - if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED) -@@ -1115,13 +1115,10 @@ static int __init dccp_init(void) - - BUILD_BUG_ON(sizeof(struct dccp_skb_cb) > - sizeof_field(struct sk_buff, cb)); -- rc = percpu_counter_init(&dccp_orphan_count, 0, GFP_KERNEL); -- if (rc) -- goto out_fail; - inet_hashinfo_init(&dccp_hashinfo); - rc = inet_hashinfo2_init_mod(&dccp_hashinfo); - if (rc) -- goto out_free_percpu; -+ goto out_fail; - rc = -ENOBUFS; - dccp_hashinfo.bind_bucket_cachep = - kmem_cache_create("dccp_bind_bucket", -@@ -1226,8 +1223,6 @@ out_free_bind_bucket_cachep: - kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); - out_free_hashinfo2: - inet_hashinfo2_free_mod(&dccp_hashinfo); --out_free_percpu: -- percpu_counter_destroy(&dccp_orphan_count); - out_fail: - dccp_hashinfo.bhash = NULL; - dccp_hashinfo.ehash = NULL; -@@ -1250,7 +1245,6 @@ static void __exit dccp_fini(void) - dccp_ackvec_exit(); - dccp_sysctl_exit(); - inet_hashinfo2_free_mod(&dccp_hashinfo); -- percpu_counter_destroy(&dccp_orphan_count); - } - - module_init(dccp_init); -diff --git a/net/dsa/switch.c b/net/dsa/switch.c -index 6466d0539af9f..44558fbdc65b3 100644 ---- a/net/dsa/switch.c -+++ b/net/dsa/switch.c -@@ -264,7 +264,7 @@ static int dsa_switch_do_mdb_del(struct dsa_switch *ds, int port, - - err = ds->ops->port_mdb_del(ds, port, mdb); - if (err) { -- refcount_inc(&a->refcount); -+ refcount_set(&a->refcount, 1); - return err; - } - -@@ -329,7 +329,7 @@ static int dsa_switch_do_fdb_del(struct dsa_switch *ds, int port, - - err = ds->ops->port_fdb_del(ds, port, addr, vid); - if (err) { -- refcount_inc(&a->refcount); -+ refcount_set(&a->refcount, 1); - return err; - } - -diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c -index 605b51ca69210..6e0518aa3a4d2 100644 ---- a/net/dsa/tag_ocelot.c -+++ b/net/dsa/tag_ocelot.c -@@ -62,6 +62,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, - struct dsa_port *dp; - u8 *extraction; - u16 vlan_tpid; -+ u64 rew_val; - - /* Revert skb->data by the amount consumed by the DSA master, - * so it points to the beginning of the frame. -@@ -91,6 +92,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, - ocelot_xfh_get_qos_class(extraction, &qos_class); - ocelot_xfh_get_tag_type(extraction, &tag_type); - ocelot_xfh_get_vlan_tci(extraction, &vlan_tci); -+ ocelot_xfh_get_rew_val(extraction, &rew_val); - - skb->dev = dsa_master_find_slave(netdev, 0, src_port); - if (!skb->dev) -@@ -104,6 +106,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, - - dsa_default_offload_fwd_mark(skb); - skb->priority = qos_class; -+ OCELOT_SKB_CB(skb)->tstamp_lo = rew_val; - - /* Ocelot switches copy frames unmodified to the CPU. However, it is - * possible for the user to request a VLAN modification through -diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c -index f2abc31528883..e4983f473a3c5 100644 ---- a/net/ethtool/ioctl.c -+++ b/net/ethtool/ioctl.c -@@ -1697,7 +1697,7 @@ static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, - struct ethtool_coalesce coalesce; - int ret; - -- if (!dev->ethtool_ops->set_coalesce && !dev->ethtool_ops->get_coalesce) -+ if (!dev->ethtool_ops->set_coalesce || !dev->ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - ret = dev->ethtool_ops->get_coalesce(dev, &coalesce, &kernel_coalesce, -diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c -index 1797a0a900195..b3729bdafb602 100644 ---- a/net/ethtool/netlink.c -+++ b/net/ethtool/netlink.c -@@ -40,7 +40,8 @@ int ethnl_ops_begin(struct net_device *dev) - if (dev->dev.parent) - pm_runtime_get_sync(dev->dev.parent); - -- if (!netif_device_present(dev)) { -+ if (!netif_device_present(dev) || -+ dev->reg_state == NETREG_UNREGISTERING) { - ret = -ENODEV; - goto err; - } -diff --git a/net/ethtool/pause.c b/net/ethtool/pause.c -index 9009f412151e7..ee1e5806bc93a 100644 ---- a/net/ethtool/pause.c -+++ b/net/ethtool/pause.c -@@ -56,8 +56,7 @@ static int pause_reply_size(const struct ethnl_req_info *req_base, - - if (req_base->flags & ETHTOOL_FLAG_STATS) - n += nla_total_size(0) + /* _PAUSE_STATS */ -- nla_total_size_64bit(sizeof(u64)) * -- (ETHTOOL_A_PAUSE_STAT_MAX - 2); -+ nla_total_size_64bit(sizeof(u64)) * ETHTOOL_PAUSE_STAT_CNT; - return n; - } - -diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c -index 1d816a5fd3eb9..64062b7ce61df 100644 ---- a/net/ipv4/af_inet.c -+++ b/net/ipv4/af_inet.c -@@ -773,26 +773,28 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr, - DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr); - - sin->sin_family = AF_INET; -+ lock_sock(sk); - if (peer) { - if (!inet->inet_dport || - (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && -- peer == 1)) -+ peer == 1)) { -+ release_sock(sk); - return -ENOTCONN; -+ } - sin->sin_port = inet->inet_dport; - sin->sin_addr.s_addr = inet->inet_daddr; -- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, -- CGROUP_INET4_GETPEERNAME, -- NULL); -+ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, -+ CGROUP_INET4_GETPEERNAME); - } else { - __be32 addr = inet->inet_rcv_saddr; - if (!addr) - addr = inet->inet_saddr; - sin->sin_port = inet->inet_sport; - sin->sin_addr.s_addr = addr; -- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, -- CGROUP_INET4_GETSOCKNAME, -- NULL); -+ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, -+ CGROUP_INET4_GETSOCKNAME); - } -+ release_sock(sk); - memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); - return sizeof(*sin); - } -diff --git a/net/ipv4/bpf_tcp_ca.c b/net/ipv4/bpf_tcp_ca.c -index 0dcee9df13268..d3a2dbd13ea6b 100644 ---- a/net/ipv4/bpf_tcp_ca.c -+++ b/net/ipv4/bpf_tcp_ca.c -@@ -212,6 +212,8 @@ bpf_tcp_ca_get_func_proto(enum bpf_func_id func_id, - offsetof(struct tcp_congestion_ops, release)) - return &bpf_sk_getsockopt_proto; - return NULL; -+ case BPF_FUNC_ktime_get_coarse_ns: -+ return &bpf_ktime_get_coarse_ns_proto; - default: - return bpf_base_func_proto(func_id); - } -diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c -index f4468980b6757..4744c7839de53 100644 ---- a/net/ipv4/devinet.c -+++ b/net/ipv4/devinet.c -@@ -2587,7 +2587,7 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, - free: - kfree(t); - out: -- return -ENOBUFS; -+ return -ENOMEM; - } - - static void __devinet_sysctl_unregister(struct net *net, -diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c -index 9fe13e4f5d08a..4d61ddd8a0ecf 100644 ---- a/net/ipv4/fib_frontend.c -+++ b/net/ipv4/fib_frontend.c -@@ -1582,7 +1582,7 @@ static int __net_init fib_net_init(struct net *net) - int error; - - #ifdef CONFIG_IP_ROUTE_CLASSID -- net->ipv4.fib_num_tclassid_users = 0; -+ atomic_set(&net->ipv4.fib_num_tclassid_users, 0); - #endif - error = ip_fib_net_init(net); - if (error < 0) -diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c -index ce54a30c2ef1e..d279cb8ac1584 100644 ---- a/net/ipv4/fib_rules.c -+++ b/net/ipv4/fib_rules.c -@@ -141,6 +141,7 @@ INDIRECT_CALLABLE_SCOPE int fib4_rule_action(struct fib_rule *rule, - } - - INDIRECT_CALLABLE_SCOPE bool fib4_rule_suppress(struct fib_rule *rule, -+ int flags, - struct fib_lookup_arg *arg) - { - struct fib_result *result = (struct fib_result *) arg->result; -@@ -263,7 +264,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - if (tb[FRA_FLOW]) { - rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); - if (rule4->tclassid) -- net->ipv4.fib_num_tclassid_users++; -+ atomic_inc(&net->ipv4.fib_num_tclassid_users); - } - #endif - -@@ -295,7 +296,7 @@ static int fib4_rule_delete(struct fib_rule *rule) - - #ifdef CONFIG_IP_ROUTE_CLASSID - if (((struct fib4_rule *)rule)->tclassid) -- net->ipv4.fib_num_tclassid_users--; -+ atomic_dec(&net->ipv4.fib_num_tclassid_users); - #endif - net->ipv4.fib_has_custom_rules = true; - -diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c -index 3364cb9c67e01..fde7797b58069 100644 ---- a/net/ipv4/fib_semantics.c -+++ b/net/ipv4/fib_semantics.c -@@ -220,7 +220,7 @@ void fib_nh_release(struct net *net, struct fib_nh *fib_nh) - { - #ifdef CONFIG_IP_ROUTE_CLASSID - if (fib_nh->nh_tclassid) -- net->ipv4.fib_num_tclassid_users--; -+ atomic_dec(&net->ipv4.fib_num_tclassid_users); - #endif - fib_nh_common_release(&fib_nh->nh_common); - } -@@ -632,7 +632,7 @@ int fib_nh_init(struct net *net, struct fib_nh *nh, - #ifdef CONFIG_IP_ROUTE_CLASSID - nh->nh_tclassid = cfg->fc_flow; - if (nh->nh_tclassid) -- net->ipv4.fib_num_tclassid_users++; -+ atomic_inc(&net->ipv4.fib_num_tclassid_users); - #endif - #ifdef CONFIG_IP_ROUTE_MULTIPATH - nh->fib_nh_weight = nh_weight; -diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c -index f25d02ad4a8af..62a67fdc344cd 100644 ---- a/net/ipv4/inet_connection_sock.c -+++ b/net/ipv4/inet_connection_sock.c -@@ -721,7 +721,7 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req, - - sk_node_init(&nreq_sk->sk_node); - nreq_sk->sk_tx_queue_mapping = req_sk->sk_tx_queue_mapping; --#ifdef CONFIG_XPS -+#ifdef CONFIG_SOCK_RX_QUEUE_MAPPING - nreq_sk->sk_rx_queue_mapping = req_sk->sk_rx_queue_mapping; - #endif - nreq_sk->sk_incoming_cpu = req_sk->sk_incoming_cpu; -@@ -1015,7 +1015,7 @@ void inet_csk_destroy_sock(struct sock *sk) - - sk_refcnt_debug_release(sk); - -- percpu_counter_dec(sk->sk_prot->orphan_count); -+ this_cpu_dec(*sk->sk_prot->orphan_count); - - sock_put(sk); - } -@@ -1074,7 +1074,7 @@ static void inet_child_forget(struct sock *sk, struct request_sock *req, - - sock_orphan(child); - -- percpu_counter_inc(sk->sk_prot->orphan_count); -+ this_cpu_inc(*sk->sk_prot->orphan_count); - - if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(req)->tfo_listener) { - BUG_ON(rcu_access_pointer(tcp_sk(child)->fastopen_rsk) != req); -diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c -index ef7897226f08e..ae70e07c52445 100644 ---- a/net/ipv4/inet_diag.c -+++ b/net/ipv4/inet_diag.c -@@ -261,6 +261,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, - r->idiag_state = sk->sk_state; - r->idiag_timer = 0; - r->idiag_retrans = 0; -+ r->idiag_expires = 0; - - if (inet_diag_msg_attrs_fill(sk, skb, r, ext, - sk_user_ns(NETLINK_CB(cb->skb).sk), -@@ -314,9 +315,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, - r->idiag_retrans = icsk->icsk_probes_out; - r->idiag_expires = - jiffies_delta_to_msecs(sk->sk_timer.expires - jiffies); -- } else { -- r->idiag_timer = 0; -- r->idiag_expires = 0; - } - - if ((ext & (1 << (INET_DIAG_INFO - 1))) && handler->idiag_info_size) { -diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c -index bfb522e513461..75737267746f8 100644 ---- a/net/ipv4/inet_hashtables.c -+++ b/net/ipv4/inet_hashtables.c -@@ -598,7 +598,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, bool *found_dup_sk) - if (ok) { - sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); - } else { -- percpu_counter_inc(sk->sk_prot->orphan_count); -+ this_cpu_inc(*sk->sk_prot->orphan_count); - inet_sk_set_state(sk, TCP_CLOSE); - sock_set_flag(sk, SOCK_DEAD); - inet_csk_destroy_sock(sk); -diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c -index 9e8100728d464..5dbd4b5505eba 100644 ---- a/net/ipv4/nexthop.c -+++ b/net/ipv4/nexthop.c -@@ -1899,15 +1899,36 @@ static void remove_nexthop(struct net *net, struct nexthop *nh, - /* if any FIB entries reference this nexthop, any dst entries - * need to be regenerated - */ --static void nh_rt_cache_flush(struct net *net, struct nexthop *nh) -+static void nh_rt_cache_flush(struct net *net, struct nexthop *nh, -+ struct nexthop *replaced_nh) - { - struct fib6_info *f6i; -+ struct nh_group *nhg; -+ int i; - - if (!list_empty(&nh->fi_list)) - rt_cache_flush(net); - - list_for_each_entry(f6i, &nh->f6i_list, nh_list) - ipv6_stub->fib6_update_sernum(net, f6i); -+ -+ /* if an IPv6 group was replaced, we have to release all old -+ * dsts to make sure all refcounts are released -+ */ -+ if (!replaced_nh->is_group) -+ return; -+ -+ /* new dsts must use only the new nexthop group */ -+ synchronize_net(); -+ -+ nhg = rtnl_dereference(replaced_nh->nh_grp); -+ for (i = 0; i < nhg->num_nh; i++) { -+ struct nh_grp_entry *nhge = &nhg->nh_entries[i]; -+ struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info); -+ -+ if (nhi->family == AF_INET6) -+ ipv6_stub->fib6_nh_release_dsts(&nhi->fib6_nh); -+ } - } - - static int replace_nexthop_grp(struct net *net, struct nexthop *old, -@@ -2247,7 +2268,7 @@ static int replace_nexthop(struct net *net, struct nexthop *old, - err = replace_nexthop_single(net, old, new, extack); - - if (!err) { -- nh_rt_cache_flush(net, old); -+ nh_rt_cache_flush(net, old, new); - - __remove_nexthop(net, new, NULL); - nexthop_put(new); -@@ -2544,11 +2565,15 @@ static int nh_create_ipv6(struct net *net, struct nexthop *nh, - /* sets nh_dev if successful */ - err = ipv6_stub->fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL, - extack); -- if (err) -+ if (err) { -+ /* IPv6 is not enabled, don't call fib6_nh_release */ -+ if (err == -EAFNOSUPPORT) -+ goto out; - ipv6_stub->fib6_nh_release(fib6_nh); -- else -+ } else { - nh->nh_flags = fib6_nh->fib_nh_flags; -- -+ } -+out: - return err; - } - -diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c -index b0d3a09dc84e7..f30273afb5399 100644 ---- a/net/ipv4/proc.c -+++ b/net/ipv4/proc.c -@@ -53,7 +53,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) - struct net *net = seq->private; - int orphans, sockets; - -- orphans = percpu_counter_sum_positive(&tcp_orphan_count); -+ orphans = tcp_orphan_count_sum(); - sockets = proto_sockets_allocated_sum_positive(&tcp_prot); - - socket_seq_show(seq); -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index f5c336f8b0c8e..844c6e5a82891 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -287,8 +287,8 @@ enum { - TCP_CMSG_TS = 2 - }; - --struct percpu_counter tcp_orphan_count; --EXPORT_SYMBOL_GPL(tcp_orphan_count); -+DEFINE_PER_CPU(unsigned int, tcp_orphan_count); -+EXPORT_PER_CPU_SYMBOL_GPL(tcp_orphan_count); - - long sysctl_tcp_mem[3] __read_mostly; - EXPORT_SYMBOL(sysctl_tcp_mem); -@@ -952,7 +952,7 @@ int tcp_send_mss(struct sock *sk, int *size_goal, int flags) - */ - void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb) - { -- if (skb && !skb->len) { -+ if (skb && TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) { - tcp_unlink_write_queue(skb, sk); - if (tcp_write_queue_empty(sk)) - tcp_chrono_stop(sk, TCP_CHRONO_BUSY); -@@ -1776,6 +1776,9 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb, - { - skb_frag_t *frag; - -+ if (unlikely(offset_skb >= skb->len)) -+ return NULL; -+ - offset_skb -= skb_headlen(skb); - if ((int)offset_skb < 0 || skb_has_frag_list(skb)) - return NULL; -@@ -2687,11 +2690,36 @@ void tcp_shutdown(struct sock *sk, int how) - } - EXPORT_SYMBOL(tcp_shutdown); - -+int tcp_orphan_count_sum(void) -+{ -+ int i, total = 0; -+ -+ for_each_possible_cpu(i) -+ total += per_cpu(tcp_orphan_count, i); -+ -+ return max(total, 0); -+} -+ -+static int tcp_orphan_cache; -+static struct timer_list tcp_orphan_timer; -+#define TCP_ORPHAN_TIMER_PERIOD msecs_to_jiffies(100) -+ -+static void tcp_orphan_update(struct timer_list *unused) -+{ -+ WRITE_ONCE(tcp_orphan_cache, tcp_orphan_count_sum()); -+ mod_timer(&tcp_orphan_timer, jiffies + TCP_ORPHAN_TIMER_PERIOD); -+} -+ -+static bool tcp_too_many_orphans(int shift) -+{ -+ return READ_ONCE(tcp_orphan_cache) << shift > sysctl_tcp_max_orphans; -+} -+ - bool tcp_check_oom(struct sock *sk, int shift) - { - bool too_many_orphans, out_of_socket_memory; - -- too_many_orphans = tcp_too_many_orphans(sk, shift); -+ too_many_orphans = tcp_too_many_orphans(shift); - out_of_socket_memory = tcp_out_of_memory(sk); - - if (too_many_orphans) -@@ -2800,7 +2828,7 @@ adjudge_to_death: - /* remove backlog if any, without releasing ownership. */ - __release_sock(sk); - -- percpu_counter_inc(sk->sk_prot->orphan_count); -+ this_cpu_inc(tcp_orphan_count); - - /* Have we already been destroyed by a softirq or backlog? */ - if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) -@@ -4502,7 +4530,10 @@ void __init tcp_init(void) - sizeof_field(struct sk_buff, cb)); - - percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL); -- percpu_counter_init(&tcp_orphan_count, 0, GFP_KERNEL); -+ -+ timer_setup(&tcp_orphan_timer, tcp_orphan_update, TIMER_DEFERRABLE); -+ mod_timer(&tcp_orphan_timer, jiffies + TCP_ORPHAN_TIMER_PERIOD); -+ - inet_hashinfo_init(&tcp_hashinfo); - inet_hashinfo2_init(&tcp_hashinfo, "tcp_listen_portaddr_hash", - thash_entries, 21, /* one slot per 2 MB*/ -diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c -index 5f4d6f45d87f7..f70aa0932bd6c 100644 ---- a/net/ipv4/tcp_bpf.c -+++ b/net/ipv4/tcp_bpf.c -@@ -172,6 +172,41 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock, - return ret; - } - -+static int tcp_bpf_recvmsg_parser(struct sock *sk, -+ struct msghdr *msg, -+ size_t len, -+ int nonblock, -+ int flags, -+ int *addr_len) -+{ -+ struct sk_psock *psock; -+ int copied; -+ -+ if (unlikely(flags & MSG_ERRQUEUE)) -+ return inet_recv_error(sk, msg, len, addr_len); -+ -+ psock = sk_psock_get(sk); -+ if (unlikely(!psock)) -+ return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len); -+ -+ lock_sock(sk); -+msg_bytes_ready: -+ copied = sk_msg_recvmsg(sk, psock, msg, len, flags); -+ if (!copied) { -+ long timeo; -+ int data; -+ -+ timeo = sock_rcvtimeo(sk, nonblock); -+ data = tcp_msg_wait_data(sk, psock, timeo); -+ if (data && !sk_psock_queue_empty(psock)) -+ goto msg_bytes_ready; -+ copied = -EAGAIN; -+ } -+ release_sock(sk); -+ sk_psock_put(sk, psock); -+ return copied; -+} -+ - static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, - int nonblock, int flags, int *addr_len) - { -@@ -464,6 +499,8 @@ enum { - enum { - TCP_BPF_BASE, - TCP_BPF_TX, -+ TCP_BPF_RX, -+ TCP_BPF_TXRX, - TCP_BPF_NUM_CFGS, - }; - -@@ -475,7 +512,6 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], - struct proto *base) - { - prot[TCP_BPF_BASE] = *base; -- prot[TCP_BPF_BASE].unhash = sock_map_unhash; - prot[TCP_BPF_BASE].close = sock_map_close; - prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg; - prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable; -@@ -483,6 +519,12 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], - prot[TCP_BPF_TX] = prot[TCP_BPF_BASE]; - prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg; - prot[TCP_BPF_TX].sendpage = tcp_bpf_sendpage; -+ -+ prot[TCP_BPF_RX] = prot[TCP_BPF_BASE]; -+ prot[TCP_BPF_RX].recvmsg = tcp_bpf_recvmsg_parser; -+ -+ prot[TCP_BPF_TXRX] = prot[TCP_BPF_TX]; -+ prot[TCP_BPF_TXRX].recvmsg = tcp_bpf_recvmsg_parser; - } - - static void tcp_bpf_check_v6_needs_rebuild(struct proto *ops) -@@ -520,6 +562,10 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) - int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; - int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE; - -+ if (psock->progs.stream_verdict || psock->progs.skb_verdict) { -+ config = (config == TCP_BPF_TX) ? TCP_BPF_TXRX : TCP_BPF_RX; -+ } -+ - if (restore) { - if (inet_csk_has_ulp(sk)) { - /* TLS does not have an unhash proto in SW cases, -diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c -index 4a30deaa9a37f..8d2d4d652f6d4 100644 ---- a/net/ipv4/tcp_cubic.c -+++ b/net/ipv4/tcp_cubic.c -@@ -328,8 +328,6 @@ static void cubictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) - return; - - if (tcp_in_slow_start(tp)) { -- if (hystart && after(ack, ca->end_seq)) -- bictcp_hystart_reset(sk); - acked = tcp_slow_start(tp, acked); - if (!acked) - return; -@@ -389,6 +387,9 @@ static void hystart_update(struct sock *sk, u32 delay) - struct bictcp *ca = inet_csk_ca(sk); - u32 threshold; - -+ if (after(tp->snd_una, ca->end_seq)) -+ bictcp_hystart_reset(sk); -+ - if (hystart_detect & HYSTART_ACK_TRAIN) { - u32 now = bictcp_clock_us(sk); - -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index 6d72f3ea48c4e..0492f6942778d 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -1562,7 +1562,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, - return -ENOMEM; - } - -- if (skb_unclone(skb, gfp)) -+ if (skb_unclone_keeptruesize(skb, gfp)) - return -ENOMEM; - - /* Get a new skb... force flag on. */ -@@ -1672,7 +1672,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) - { - u32 delta_truesize; - -- if (skb_unclone(skb, GFP_ATOMIC)) -+ if (skb_unclone_keeptruesize(skb, GFP_ATOMIC)) - return -ENOMEM; - - delta_truesize = __pskb_trim_head(skb, len); -@@ -3184,7 +3184,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) - cur_mss, GFP_ATOMIC)) - return -ENOMEM; /* We'll try again later. */ - } else { -- if (skb_unclone(skb, GFP_ATOMIC)) -+ if (skb_unclone_keeptruesize(skb, GFP_ATOMIC)) - return -ENOMEM; - - diff = tcp_skb_pcount(skb); -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 2fffcf2b54f3f..3f6823bdd31e5 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -917,7 +917,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4, - kfree_skb(skb); - return -EINVAL; - } -- if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { -+ if (datalen > cork->gso_size * UDP_MAX_SEGMENTS) { - kfree_skb(skb); - return -EINVAL; - } -@@ -1808,6 +1808,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc, - skb = skb_recv_udp(sk, 0, 1, &err); - if (!skb) - return err; -+ -+ if (udp_lib_checksum_complete(skb)) { -+ __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, -+ IS_UDPLITE(sk)); -+ __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, -+ IS_UDPLITE(sk)); -+ atomic_inc(&sk->sk_drops); -+ kfree_skb(skb); -+ continue; -+ } -+ - used = recv_actor(desc, skb, 0, skb->len); - if (used <= 0) { - if (!copied) -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index c6a90b7bbb70e..846037e73723f 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -3110,6 +3110,9 @@ static void add_v4_addrs(struct inet6_dev *idev) - memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4); - - if (idev->dev->flags&IFF_POINTOPOINT) { -+ if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE) -+ return; -+ - addr.s6_addr32[0] = htonl(0xfe800000); - scope = IFA_LINK; - plen = 64; -diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c -index b5878bb8e419d..dab4a047590b7 100644 ---- a/net/ipv6/af_inet6.c -+++ b/net/ipv6/af_inet6.c -@@ -521,31 +521,32 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, - sin->sin6_family = AF_INET6; - sin->sin6_flowinfo = 0; - sin->sin6_scope_id = 0; -+ lock_sock(sk); - if (peer) { -- if (!inet->inet_dport) -- return -ENOTCONN; -- if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && -- peer == 1) -+ if (!inet->inet_dport || -+ (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && -+ peer == 1)) { -+ release_sock(sk); - return -ENOTCONN; -+ } - sin->sin6_port = inet->inet_dport; - sin->sin6_addr = sk->sk_v6_daddr; - if (np->sndflow) - sin->sin6_flowinfo = np->flow_label; -- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, -- CGROUP_INET6_GETPEERNAME, -- NULL); -+ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, -+ CGROUP_INET6_GETPEERNAME); - } else { - if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) - sin->sin6_addr = np->saddr; - else - sin->sin6_addr = sk->sk_v6_rcv_saddr; - sin->sin6_port = inet->inet_sport; -- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, -- CGROUP_INET6_GETSOCKNAME, -- NULL); -+ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, -+ CGROUP_INET6_GETSOCKNAME); - } - sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr, - sk->sk_bound_dev_if); -+ release_sock(sk); - return sizeof(*sin); - } - EXPORT_SYMBOL(inet6_getname); -@@ -1025,6 +1026,7 @@ static const struct ipv6_stub ipv6_stub_impl = { - .ip6_mtu_from_fib6 = ip6_mtu_from_fib6, - .fib6_nh_init = fib6_nh_init, - .fib6_nh_release = fib6_nh_release, -+ .fib6_nh_release_dsts = fib6_nh_release_dsts, - .fib6_update_sernum = fib6_update_sernum_stub, - .fib6_rt_update = fib6_rt_update, - .ip6_del_rt = ip6_del_rt, -diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c -index ed2f061b87685..f0bac6f7ab6bb 100644 ---- a/net/ipv6/esp6.c -+++ b/net/ipv6/esp6.c -@@ -808,6 +808,12 @@ int esp6_input_done2(struct sk_buff *skb, int err) - struct tcphdr *th; - - offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off); -+ -+ if (offset < 0) { -+ err = -EINVAL; -+ goto out; -+ } -+ - uh = (void *)(skb->data + offset); - th = (void *)(skb->data + offset); - hdr_len += offset; -diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c -index 40f3e4f9f33a2..dcedfe29d9d93 100644 ---- a/net/ipv6/fib6_rules.c -+++ b/net/ipv6/fib6_rules.c -@@ -267,6 +267,7 @@ INDIRECT_CALLABLE_SCOPE int fib6_rule_action(struct fib_rule *rule, - } - - INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, -+ int flags, - struct fib_lookup_arg *arg) - { - struct fib6_result *res = arg->result; -@@ -294,8 +295,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, - return false; - - suppress_route: -- if (!(arg->flags & FIB_LOOKUP_NOREF)) -- ip6_rt_put(rt); -+ ip6_rt_put_flags(rt, flags); - return true; - } - -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 2f044a49afa8c..ff4e83e2a5068 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -174,7 +174,7 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff - #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) - /* Policy lookup after SNAT yielded a new policy */ - if (skb_dst(skb)->xfrm) { -- IPCB(skb)->flags |= IPSKB_REROUTED; -+ IP6CB(skb)->flags |= IP6SKB_REROUTED; - return dst_output(net, sk, skb); - } - #endif -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 9b9ef09382ab9..79cb5e5a4948b 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -3680,6 +3680,25 @@ void fib6_nh_release(struct fib6_nh *fib6_nh) - fib_nh_common_release(&fib6_nh->nh_common); - } - -+void fib6_nh_release_dsts(struct fib6_nh *fib6_nh) -+{ -+ int cpu; -+ -+ if (!fib6_nh->rt6i_pcpu) -+ return; -+ -+ for_each_possible_cpu(cpu) { -+ struct rt6_info *pcpu_rt, **ppcpu_rt; -+ -+ ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu); -+ pcpu_rt = xchg(ppcpu_rt, NULL); -+ if (pcpu_rt) { -+ dst_dev_put(&pcpu_rt->dst); -+ dst_release(&pcpu_rt->dst); -+ } -+ } -+} -+ - static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, - gfp_t gfp_flags, - struct netlink_ext_ack *extack) -diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c -index 3adc5d9211ad6..d64855010948d 100644 ---- a/net/ipv6/seg6_iptunnel.c -+++ b/net/ipv6/seg6_iptunnel.c -@@ -161,6 +161,14 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) - hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); - - memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); -+ -+ /* the control block has been erased, so we have to set the -+ * iif once again. -+ * We read the receiving interface index directly from the -+ * skb->skb_iif as it is done in the IPv4 receiving path (i.e.: -+ * ip_rcv_core(...)). -+ */ -+ IP6CB(skb)->iif = skb->skb_iif; - } - - hdr->nexthdr = NEXTHDR_ROUTING; -diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c -index ef0c7a7c18e23..626cb53aa57ab 100644 ---- a/net/ipv6/sit.c -+++ b/net/ipv6/sit.c -@@ -1933,7 +1933,6 @@ static int __net_init sit_init_net(struct net *net) - return 0; - - err_reg_dev: -- ipip6_dev_free(sitn->fb_tunnel_dev); - free_netdev(sitn->fb_tunnel_dev); - err_alloc_dev: - return err; -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index 8d785232b4796..be6dc64ece29f 100644 ---- a/net/ipv6/udp.c -+++ b/net/ipv6/udp.c -@@ -1435,7 +1435,6 @@ do_udp_sendmsg: - if (!fl6.flowi6_oif) - fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; - -- fl6.flowi6_mark = ipc6.sockc.mark; - fl6.flowi6_uid = sk->sk_uid; - - if (msg->msg_controllen) { -@@ -1471,6 +1470,7 @@ do_udp_sendmsg: - ipc6.opt = opt; - - fl6.flowi6_proto = sk->sk_protocol; -+ fl6.flowi6_mark = ipc6.sockc.mark; - fl6.daddr = *daddr; - if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) - fl6.saddr = np->saddr; -diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c -index cce28e3b22323..ef729b1e39ea3 100644 ---- a/net/mac80211/agg-rx.c -+++ b/net/mac80211/agg-rx.c -@@ -9,7 +9,7 @@ - * Copyright 2007, Michael Wu <flamingice@sourmilk.net> - * Copyright 2007-2010, Intel Corporation - * Copyright(c) 2015-2017 Intel Deutschland GmbH -- * Copyright (C) 2018-2020 Intel Corporation -+ * Copyright (C) 2018-2021 Intel Corporation - */ - - /** -@@ -191,7 +191,8 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, - sband = ieee80211_get_sband(sdata); - if (!sband) - return; -- he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type); -+ he_cap = ieee80211_get_he_iftype_cap(sband, -+ ieee80211_vif_type_p2p(&sdata->vif)); - if (!he_cap) - return; - -diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c -index 430a585875388..74a878f213d3e 100644 ---- a/net/mac80211/agg-tx.c -+++ b/net/mac80211/agg-tx.c -@@ -9,7 +9,7 @@ - * Copyright 2007, Michael Wu <flamingice@sourmilk.net> - * Copyright 2007-2010, Intel Corporation - * Copyright(c) 2015-2017 Intel Deutschland GmbH -- * Copyright (C) 2018 - 2020 Intel Corporation -+ * Copyright (C) 2018 - 2021 Intel Corporation - */ - - #include <linux/ieee80211.h> -@@ -106,7 +106,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, - mgmt->u.action.u.addba_req.start_seq_num = - cpu_to_le16(start_seq_num << 4); - -- ieee80211_tx_skb(sdata, skb); -+ ieee80211_tx_skb_tid(sdata, skb, tid); - } - - void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) -@@ -213,6 +213,8 @@ ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable) - struct ieee80211_txq *txq = sta->sta.txq[tid]; - struct txq_info *txqi; - -+ lockdep_assert_held(&sta->ampdu_mlme.mtx); -+ - if (!txq) - return; - -@@ -290,7 +292,6 @@ static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid) - ieee80211_assign_tid_tx(sta, tid, NULL); - - ieee80211_agg_splice_finish(sta->sdata, tid); -- ieee80211_agg_start_txq(sta, tid, false); - - kfree_rcu(tid_tx, rcu_head); - } -@@ -480,8 +481,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, - - /* send AddBA request */ - ieee80211_send_addba_request(sdata, sta->sta.addr, tid, -- tid_tx->dialog_token, -- sta->tid_seq[tid] >> 4, -+ tid_tx->dialog_token, tid_tx->ssn, - buf_size, tid_tx->timeout); - - WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); -@@ -523,6 +523,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) - - params.ssn = sta->tid_seq[tid] >> 4; - ret = drv_ampdu_action(local, sdata, ¶ms); -+ tid_tx->ssn = params.ssn; - if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) { - return; - } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { -@@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, - { - struct ieee80211_sub_if_data *sdata = sta->sdata; - bool send_delba = false; -+ bool start_txq = false; - - ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", - sta->sta.addr, tid); -@@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, - send_delba = true; - - ieee80211_remove_tid_tx(sta, tid); -+ start_txq = true; - - unlock_sta: - spin_unlock_bh(&sta->lock); - -+ if (start_txq) -+ ieee80211_agg_start_txq(sta, tid, false); -+ - if (send_delba) - ieee80211_send_delba(sdata, sta->sta.addr, tid, - WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); -diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c -index d69b31c20fe28..d3f62fd12f0b5 100644 ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -80,7 +80,8 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, - } - - /* also validate MU-MIMO change */ -- monitor_sdata = rtnl_dereference(local->monitor_sdata); -+ monitor_sdata = wiphy_dereference(local->hw.wiphy, -+ local->monitor_sdata); - - if (!monitor_sdata && - (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) -@@ -810,7 +811,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, - - mutex_lock(&local->mtx); - if (local->use_chanctx) { -- sdata = rtnl_dereference(local->monitor_sdata); -+ sdata = wiphy_dereference(local->hw.wiphy, -+ local->monitor_sdata); - if (sdata) { - ieee80211_vif_release_channel(sdata); - ret = ieee80211_vif_use_channel(sdata, chandef, -@@ -2669,7 +2671,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, - sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); - - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { -- sdata = rtnl_dereference(local->monitor_sdata); -+ sdata = wiphy_dereference(local->hw.wiphy, -+ local->monitor_sdata); - if (!sdata) - return -EOPNOTSUPP; - } -@@ -2729,7 +2732,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, - mutex_unlock(&local->iflist_mtx); - - if (has_monitor) { -- sdata = rtnl_dereference(local->monitor_sdata); -+ sdata = wiphy_dereference(local->hw.wiphy, -+ local->monitor_sdata); - if (sdata) { - sdata->user_power_level = local->user_power_level; - if (txp_type != sdata->vif.bss_conf.txpower_type) -diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h -index cd3731cbf6c68..c336267f4599c 100644 ---- a/net/mac80211/driver-ops.h -+++ b/net/mac80211/driver-ops.h -@@ -1219,8 +1219,11 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local, - { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); - -- if (local->in_reconfig) -+ /* In reconfig don't transmit now, but mark for waking later */ -+ if (local->in_reconfig) { -+ set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txq->flags); - return; -+ } - - if (!check_sdata_in_driver(sdata)) - return; -diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c -index 62c95597704b4..041859b5b71d0 100644 ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -588,7 +588,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do - */ - if (local->suspended) { - WARN_ON(local->wowlan); -- WARN_ON(rtnl_dereference(local->monitor_sdata)); -+ WARN_ON(rcu_access_pointer(local->monitor_sdata)); - return; - } - -@@ -932,6 +932,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) - return 0; - - ASSERT_RTNL(); -+ lockdep_assert_wiphy(local->hw.wiphy); - - if (local->monitor_sdata) - return 0; -@@ -999,6 +1000,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) - return; - - ASSERT_RTNL(); -+ lockdep_assert_wiphy(local->hw.wiphy); - - mutex_lock(&local->iflist_mtx); - -diff --git a/net/mac80211/led.h b/net/mac80211/led.h -index fb3aaa3c56069..b71a1428d883c 100644 ---- a/net/mac80211/led.h -+++ b/net/mac80211/led.h -@@ -72,19 +72,19 @@ static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, - #endif - - static inline void --ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) -+ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, int bytes) - { - #ifdef CONFIG_MAC80211_LEDS -- if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active)) -+ if (atomic_read(&local->tpt_led_active)) - local->tpt_led_trigger->tx_bytes += bytes; - #endif - } - - static inline void --ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) -+ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, int bytes) - { - #ifdef CONFIG_MAC80211_LEDS -- if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active)) -+ if (atomic_read(&local->tpt_led_active)) - local->tpt_led_trigger->rx_bytes += bytes; - #endif - } -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index c0ea3b1aa9e1c..dd42d83dbe33e 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -2446,11 +2446,18 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata, - u16 tx_time) - { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; -- u16 tid = ieee80211_get_tid(hdr); -- int ac = ieee80211_ac_from_tid(tid); -- struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac]; -+ u16 tid; -+ int ac; -+ struct ieee80211_sta_tx_tspec *tx_tspec; - unsigned long now = jiffies; - -+ if (!ieee80211_is_data_qos(hdr->frame_control)) -+ return; -+ -+ tid = ieee80211_get_tid(hdr); -+ ac = ieee80211_ac_from_tid(tid); -+ tx_tspec = &ifmgd->tx_tspec[ac]; -+ - if (likely(!tx_tspec->admitted_time)) - return; - -diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c -index c4071b015c188..1958e4d59b524 100644 ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -364,7 +364,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, - * the compiler to think we have walked past the end of the - * struct member. - */ -- pos = (void *)&rthdr->it_optional[it_present - rthdr->it_optional]; -+ pos = (void *)&rthdr->it_optional[it_present + 1 - rthdr->it_optional]; - - /* the order of the following fields is important */ - -@@ -1952,7 +1952,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) - int keyid = rx->sta->ptk_idx; - sta_ptk = rcu_dereference(rx->sta->ptk[keyid]); - -- if (ieee80211_has_protected(fc)) { -+ if (ieee80211_has_protected(fc) && -+ !(status->flag & RX_FLAG_IV_STRIPPED)) { - cs = rx->sta->cipher_scheme; - keyid = ieee80211_get_keyid(rx->skb, cs); - -@@ -4873,6 +4874,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, - struct ieee80211_rate *rate = NULL; - struct ieee80211_supported_band *sband; - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - WARN_ON_ONCE(softirq_count() == 0); - -@@ -4969,9 +4971,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, - if (!(status->flag & RX_FLAG_8023)) - skb = ieee80211_rx_monitor(local, skb, rate); - if (skb) { -- ieee80211_tpt_led_trig_rx(local, -- ((struct ieee80211_hdr *)skb->data)->frame_control, -- skb->len); -+ if ((status->flag & RX_FLAG_8023) || -+ ieee80211_is_data_present(hdr->frame_control)) -+ ieee80211_tpt_led_trig_rx(local, skb->len); - - if (status->flag & RX_FLAG_8023) - __ieee80211_rx_handle_8023(hw, pubsta, skb, list); -diff --git a/net/mac80211/s1g.c b/net/mac80211/s1g.c -index 7e35ab5b61664..4141bc80cdfd6 100644 ---- a/net/mac80211/s1g.c -+++ b/net/mac80211/s1g.c -@@ -104,9 +104,11 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata, - - /* broadcast TWT not supported yet */ - if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) { -- le16p_replace_bits(&twt_agrt->req_type, -- TWT_SETUP_CMD_REJECT, -- IEEE80211_TWT_REQTYPE_SETUP_CMD); -+ twt_agrt->req_type &= -+ ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); -+ twt_agrt->req_type |= -+ le16_encode_bits(TWT_SETUP_CMD_REJECT, -+ IEEE80211_TWT_REQTYPE_SETUP_CMD); - goto out; - } - -diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h -index ba27967820084..e7443fc4669c8 100644 ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -199,6 +199,7 @@ struct tid_ampdu_tx { - u8 stop_initiator; - bool tx_stop; - u16 buf_size; -+ u16 ssn; - - u16 failed_bar_ssn; - bool bar_pending; -diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c -index 8921088a5df65..a499b07fee336 100644 ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1720,21 +1720,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, - * Returns false if the frame couldn't be transmitted but was queued instead. - */ - static bool __ieee80211_tx(struct ieee80211_local *local, -- struct sk_buff_head *skbs, int led_len, -- struct sta_info *sta, bool txpending) -+ struct sk_buff_head *skbs, struct sta_info *sta, -+ bool txpending) - { - struct ieee80211_tx_info *info; - struct ieee80211_sub_if_data *sdata; - struct ieee80211_vif *vif; - struct sk_buff *skb; - bool result; -- __le16 fc; - - if (WARN_ON(skb_queue_empty(skbs))) - return true; - - skb = skb_peek(skbs); -- fc = ((struct ieee80211_hdr *)skb->data)->frame_control; - info = IEEE80211_SKB_CB(skb); - sdata = vif_to_sdata(info->control.vif); - if (sta && !sta->uploaded) -@@ -1768,8 +1766,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local, - - result = ieee80211_tx_frags(local, vif, sta, skbs, txpending); - -- ieee80211_tpt_led_trig_tx(local, fc, led_len); -- - WARN_ON_ONCE(!skb_queue_empty(skbs)); - - return result; -@@ -1825,15 +1821,15 @@ static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx) - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - ieee80211_tx_result res = TX_CONTINUE; - -+ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) -+ CALL_TXH(ieee80211_tx_h_rate_ctrl); -+ - if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) { - __skb_queue_tail(&tx->skbs, tx->skb); - tx->skb = NULL; - goto txh_done; - } - -- if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) -- CALL_TXH(ieee80211_tx_h_rate_ctrl); -- - CALL_TXH(ieee80211_tx_h_michael_mic_add); - CALL_TXH(ieee80211_tx_h_sequence); - CALL_TXH(ieee80211_tx_h_fragment); -@@ -1919,7 +1915,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, - ieee80211_tx_result res_prepare; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - bool result = true; -- int led_len; - - if (unlikely(skb->len < 10)) { - dev_kfree_skb(skb); -@@ -1927,7 +1922,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, - } - - /* initialises tx */ -- led_len = skb->len; - res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); - - if (unlikely(res_prepare == TX_DROP)) { -@@ -1950,8 +1944,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, - return true; - - if (!invoke_tx_handlers_late(&tx)) -- result = __ieee80211_tx(local, &tx.skbs, led_len, -- tx.sta, txpending); -+ result = __ieee80211_tx(local, &tx.skbs, tx.sta, txpending); - - return result; - } -@@ -4174,6 +4167,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - struct sk_buff *next; -+ int len = skb->len; - - if (unlikely(skb->len < ETH_HLEN)) { - kfree_skb(skb); -@@ -4220,10 +4214,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, - } - } else { - /* we cannot process non-linear frames on this path */ -- if (skb_linearize(skb)) { -- kfree_skb(skb); -- goto out; -- } -+ if (skb_linearize(skb)) -+ goto out_free; - - /* the frame could be fragmented, software-encrypted, and other - * things so we cannot really handle checksum offload with it - -@@ -4257,7 +4249,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, - goto out; - out_free: - kfree_skb(skb); -+ len = 0; - out: -+ if (len) -+ ieee80211_tpt_led_trig_tx(local, len); - rcu_read_unlock(); - } - -@@ -4395,8 +4390,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, - } - - static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, -- struct sk_buff *skb, int led_len, -- struct sta_info *sta, -+ struct sk_buff *skb, struct sta_info *sta, - bool txpending) - { - struct ieee80211_local *local = sdata->local; -@@ -4409,6 +4403,8 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, - if (sta) - sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift); - -+ ieee80211_tpt_led_trig_tx(local, skb->len); -+ - if (ieee80211_queue_skb(local, sdata, sta, skb)) - return true; - -@@ -4497,7 +4493,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, - if (key) - info->control.hw_key = &key->conf; - -- ieee80211_tx_8023(sdata, skb, skb->len, sta, false); -+ ieee80211_tx_8023(sdata, skb, sta, false); - - return; - -@@ -4636,7 +4632,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, - if (IS_ERR(sta) || (sta && !sta->uploaded)) - sta = NULL; - -- result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true); -+ result = ieee80211_tx_8023(sdata, skb, sta, true); - } else { - struct sk_buff_head skbs; - -@@ -4646,7 +4642,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, - hdr = (struct ieee80211_hdr *)skb->data; - sta = sta_info_get(sdata, hdr->addr1); - -- result = __ieee80211_tx(local, &skbs, skb->len, sta, true); -+ result = __ieee80211_tx(local, &skbs, sta, true); - } - - return result; -diff --git a/net/mac80211/util.c b/net/mac80211/util.c -index 49cb96d251695..2fe71ed9137b0 100644 ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -796,7 +796,7 @@ static void __iterate_interfaces(struct ieee80211_local *local, - - sdata = rcu_dereference_check(local->monitor_sdata, - lockdep_is_held(&local->iflist_mtx) || -- lockdep_rtnl_is_held()); -+ lockdep_is_held(&local->hw.wiphy->mtx)); - if (sdata && - (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only || - sdata->flags & IEEE80211_SDATA_IN_DRIVER)) -@@ -943,7 +943,12 @@ static void ieee80211_parse_extension_element(u32 *crc, - struct ieee802_11_elems *elems) - { - const void *data = elem->data + 1; -- u8 len = elem->datalen - 1; -+ u8 len; -+ -+ if (!elem->datalen) -+ return; -+ -+ len = elem->datalen - 1; - - switch (elem->data[0]) { - case WLAN_EID_EXT_HE_MU_EDCA: -@@ -2379,7 +2384,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) - IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); - - /* add interfaces */ -- sdata = rtnl_dereference(local->monitor_sdata); -+ sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); - if (sdata) { - /* in HW restart it exists already */ - WARN_ON(local->resuming); -@@ -2424,7 +2429,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) - WARN_ON(drv_add_chanctx(local, ctx)); - mutex_unlock(&local->chanctx_mtx); - -- sdata = rtnl_dereference(local->monitor_sdata); -+ sdata = wiphy_dereference(local->hw.wiphy, -+ local->monitor_sdata); - if (sdata && ieee80211_sdata_running(sdata)) - ieee80211_assign_chanctx(local, sdata); - } -diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c -index 9ea6004abe1be..62c6733e07923 100644 ---- a/net/mac80211/wme.c -+++ b/net/mac80211/wme.c -@@ -143,7 +143,6 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata, - u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, - struct sta_info *sta, struct sk_buff *skb) - { -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct mac80211_qos_map *qos_map; - bool qos; - -@@ -156,7 +155,7 @@ u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, - else - qos = false; - -- if (!qos || (info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER)) { -+ if (!qos) { - skb->priority = 0; /* required for correct WPA/11i MIC */ - return IEEE80211_AC_BE; - } -diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c -index a9526ac29dffe..85cc1a28cbe9f 100644 ---- a/net/mctp/af_mctp.c -+++ b/net/mctp/af_mctp.c -@@ -30,6 +30,12 @@ static int mctp_release(struct socket *sock) - return 0; - } - -+/* Generic sockaddr checks, padding checks only so far */ -+static bool mctp_sockaddr_is_ok(const struct sockaddr_mctp *addr) -+{ -+ return !addr->__smctp_pad0 && !addr->__smctp_pad1; -+} -+ - static int mctp_bind(struct socket *sock, struct sockaddr *addr, int addrlen) - { - struct sock *sk = sock->sk; -@@ -49,6 +55,9 @@ static int mctp_bind(struct socket *sock, struct sockaddr *addr, int addrlen) - /* it's a valid sockaddr for MCTP, cast and do protocol checks */ - smctp = (struct sockaddr_mctp *)addr; - -+ if (!mctp_sockaddr_is_ok(smctp)) -+ return -EINVAL; -+ - lock_sock(sk); - - /* TODO: allow rebind */ -@@ -83,6 +92,8 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) - return -EINVAL; - if (addr->smctp_family != AF_MCTP) - return -EINVAL; -+ if (!mctp_sockaddr_is_ok(addr)) -+ return -EINVAL; - if (addr->smctp_tag & ~(MCTP_TAG_MASK | MCTP_TAG_OWNER)) - return -EINVAL; - -@@ -172,11 +183,13 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, - - addr = msg->msg_name; - addr->smctp_family = AF_MCTP; -+ addr->__smctp_pad0 = 0; - addr->smctp_network = cb->net; - addr->smctp_addr.s_addr = hdr->src; - addr->smctp_type = type; - addr->smctp_tag = hdr->flags_seq_tag & - (MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO); -+ addr->__smctp_pad1 = 0; - msg->msg_namelen = sizeof(*addr); - } - -diff --git a/net/mctp/route.c b/net/mctp/route.c -index 5ca186d53cb0f..fb1bf4ec85296 100644 ---- a/net/mctp/route.c -+++ b/net/mctp/route.c -@@ -760,7 +760,7 @@ static int mctp_route_add(struct mctp_dev *mdev, mctp_eid_t daddr_start, - } - - static int mctp_route_remove(struct mctp_dev *mdev, mctp_eid_t daddr_start, -- unsigned int daddr_extent) -+ unsigned int daddr_extent, unsigned char type) - { - struct net *net = dev_net(mdev->dev); - struct mctp_route *rt, *tmp; -@@ -777,7 +777,8 @@ static int mctp_route_remove(struct mctp_dev *mdev, mctp_eid_t daddr_start, - - list_for_each_entry_safe(rt, tmp, &net->mctp.routes, list) { - if (rt->dev == mdev && -- rt->min == daddr_start && rt->max == daddr_end) { -+ rt->min == daddr_start && rt->max == daddr_end && -+ rt->type == type) { - list_del_rcu(&rt->list); - /* TODO: immediate RTM_DELROUTE */ - mctp_route_release(rt); -@@ -795,7 +796,7 @@ int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr) - - int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr) - { -- return mctp_route_remove(mdev, addr, 0); -+ return mctp_route_remove(mdev, addr, 0, RTN_LOCAL); - } - - /* removes all entries for a given device */ -@@ -975,7 +976,7 @@ static int mctp_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, - if (rtm->rtm_type != RTN_UNICAST) - return -EINVAL; - -- rc = mctp_route_remove(mdev, daddr_start, rtm->rtm_dst_len); -+ rc = mctp_route_remove(mdev, daddr_start, rtm->rtm_dst_len, RTN_UNICAST); - return rc; - } - -diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c -index ffeb2df8be7ae..6e587feb705c4 100644 ---- a/net/mpls/af_mpls.c -+++ b/net/mpls/af_mpls.c -@@ -1491,22 +1491,52 @@ static void mpls_dev_destroy_rcu(struct rcu_head *head) - kfree(mdev); - } - --static void mpls_ifdown(struct net_device *dev, int event) -+static int mpls_ifdown(struct net_device *dev, int event) - { - struct mpls_route __rcu **platform_label; - struct net *net = dev_net(dev); -- u8 alive, deleted; - unsigned index; - - platform_label = rtnl_dereference(net->mpls.platform_label); - for (index = 0; index < net->mpls.platform_labels; index++) { - struct mpls_route *rt = rtnl_dereference(platform_label[index]); -+ bool nh_del = false; -+ u8 alive = 0; - - if (!rt) - continue; - -- alive = 0; -- deleted = 0; -+ if (event == NETDEV_UNREGISTER) { -+ u8 deleted = 0; -+ -+ for_nexthops(rt) { -+ struct net_device *nh_dev = -+ rtnl_dereference(nh->nh_dev); -+ -+ if (!nh_dev || nh_dev == dev) -+ deleted++; -+ if (nh_dev == dev) -+ nh_del = true; -+ } endfor_nexthops(rt); -+ -+ /* if there are no more nexthops, delete the route */ -+ if (deleted == rt->rt_nhn) { -+ mpls_route_update(net, index, NULL, NULL); -+ continue; -+ } -+ -+ if (nh_del) { -+ size_t size = sizeof(*rt) + rt->rt_nhn * -+ rt->rt_nh_size; -+ struct mpls_route *orig = rt; -+ -+ rt = kmalloc(size, GFP_KERNEL); -+ if (!rt) -+ return -ENOMEM; -+ memcpy(rt, orig, size); -+ } -+ } -+ - change_nexthops(rt) { - unsigned int nh_flags = nh->nh_flags; - -@@ -1530,16 +1560,15 @@ static void mpls_ifdown(struct net_device *dev, int event) - next: - if (!(nh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN))) - alive++; -- if (!rtnl_dereference(nh->nh_dev)) -- deleted++; - } endfor_nexthops(rt); - - WRITE_ONCE(rt->rt_nhn_alive, alive); - -- /* if there are no more nexthops, delete the route */ -- if (event == NETDEV_UNREGISTER && deleted == rt->rt_nhn) -- mpls_route_update(net, index, NULL, NULL); -+ if (nh_del) -+ mpls_route_update(net, index, rt, NULL); - } -+ -+ return 0; - } - - static void mpls_ifup(struct net_device *dev, unsigned int flags) -@@ -1597,8 +1626,12 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, - return NOTIFY_OK; - - switch (event) { -+ int err; -+ - case NETDEV_DOWN: -- mpls_ifdown(dev, event); -+ err = mpls_ifdown(dev, event); -+ if (err) -+ return notifier_from_errno(err); - break; - case NETDEV_UP: - flags = dev_get_flags(dev); -@@ -1609,13 +1642,18 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, - break; - case NETDEV_CHANGE: - flags = dev_get_flags(dev); -- if (flags & (IFF_RUNNING | IFF_LOWER_UP)) -+ if (flags & (IFF_RUNNING | IFF_LOWER_UP)) { - mpls_ifup(dev, RTNH_F_DEAD | RTNH_F_LINKDOWN); -- else -- mpls_ifdown(dev, event); -+ } else { -+ err = mpls_ifdown(dev, event); -+ if (err) -+ return notifier_from_errno(err); -+ } - break; - case NETDEV_UNREGISTER: -- mpls_ifdown(dev, event); -+ err = mpls_ifdown(dev, event); -+ if (err) -+ return notifier_from_errno(err); - mdev = mpls_dev_get(dev); - if (mdev) { - mpls_dev_sysctl_unregister(dev, mdev); -@@ -1626,8 +1664,6 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, - case NETDEV_CHANGENAME: - mdev = mpls_dev_get(dev); - if (mdev) { -- int err; -- - mpls_dev_sysctl_unregister(dev, mdev); - err = mpls_dev_sysctl_register(dev, mdev); - if (err) -diff --git a/net/mptcp/options.c b/net/mptcp/options.c -index f0f22eb4fd5f7..0966855a7c251 100644 ---- a/net/mptcp/options.c -+++ b/net/mptcp/options.c -@@ -422,28 +422,6 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, - return false; - } - --/* MP_JOIN client subflow must wait for 4th ack before sending any data: -- * TCP can't schedule delack timer before the subflow is fully established. -- * MPTCP uses the delack timer to do 3rd ack retransmissions -- */ --static void schedule_3rdack_retransmission(struct sock *sk) --{ -- struct inet_connection_sock *icsk = inet_csk(sk); -- struct tcp_sock *tp = tcp_sk(sk); -- unsigned long timeout; -- -- /* reschedule with a timeout above RTT, as we must look only for drop */ -- if (tp->srtt_us) -- timeout = tp->srtt_us << 1; -- else -- timeout = TCP_TIMEOUT_INIT; -- -- WARN_ON_ONCE(icsk->icsk_ack.pending & ICSK_ACK_TIMER); -- icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER; -- icsk->icsk_ack.timeout = timeout; -- sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout); --} -- - static void clear_3rdack_retransmission(struct sock *sk) - { - struct inet_connection_sock *icsk = inet_csk(sk); -@@ -526,7 +504,15 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb, - *size = TCPOLEN_MPTCP_MPJ_ACK; - pr_debug("subflow=%p", subflow); - -- schedule_3rdack_retransmission(sk); -+ /* we can use the full delegate action helper only from BH context -+ * If we are in process context - sk is flushing the backlog at -+ * socket lock release time - just set the appropriate flag, will -+ * be handled by the release callback -+ */ -+ if (sock_owned_by_user(sk)) -+ set_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status); -+ else -+ mptcp_subflow_delegate(subflow, MPTCP_DELEGATE_ACK); - return true; - } - return false; -@@ -1019,11 +1005,9 @@ static void ack_update_msk(struct mptcp_sock *msk, - old_snd_una = msk->snd_una; - new_snd_una = mptcp_expand_seq(old_snd_una, mp_opt->data_ack, mp_opt->ack64); - -- /* ACK for data not even sent yet and even above recovery bound? Ignore.*/ -- if (unlikely(after64(new_snd_una, snd_nxt))) { -- if (!msk->recovery || after64(new_snd_una, msk->recovery_snd_nxt)) -- new_snd_una = old_snd_una; -- } -+ /* ACK for data not even sent yet? Ignore.*/ -+ if (unlikely(after64(new_snd_una, snd_nxt))) -+ new_snd_una = old_snd_una; - - new_wnd_end = new_snd_una + tcp_sk(ssk)->snd_wnd; - -diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c -index 050eea231528b..b79251a36dcbc 100644 ---- a/net/mptcp/pm_netlink.c -+++ b/net/mptcp/pm_netlink.c -@@ -700,6 +700,9 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, - - msk_owned_by_me(msk); - -+ if (sk->sk_state == TCP_LISTEN) -+ return; -+ - if (!rm_list->nr) - return; - -diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c -index d073b21113828..4c889552cde77 100644 ---- a/net/mptcp/protocol.c -+++ b/net/mptcp/protocol.c -@@ -1505,6 +1505,32 @@ static void mptcp_push_release(struct sock *sk, struct sock *ssk, - release_sock(ssk); - } - -+static void mptcp_update_post_push(struct mptcp_sock *msk, -+ struct mptcp_data_frag *dfrag, -+ u32 sent) -+{ -+ u64 snd_nxt_new = dfrag->data_seq; -+ -+ dfrag->already_sent += sent; -+ -+ msk->snd_burst -= sent; -+ msk->tx_pending_data -= sent; -+ -+ snd_nxt_new += dfrag->already_sent; -+ -+ /* snd_nxt_new can be smaller than snd_nxt in case mptcp -+ * is recovering after a failover. In that event, this re-sends -+ * old segments. -+ * -+ * Thus compute snd_nxt_new candidate based on -+ * the dfrag->data_seq that was sent and the data -+ * that has been handed to the subflow for transmission -+ * and skip update in case it was old dfrag. -+ */ -+ if (likely(after64(snd_nxt_new, msk->snd_nxt))) -+ msk->snd_nxt = snd_nxt_new; -+} -+ - void __mptcp_push_pending(struct sock *sk, unsigned int flags) - { - struct sock *prev_ssk = NULL, *ssk = NULL; -@@ -1523,7 +1549,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags) - int ret = 0; - - prev_ssk = ssk; -- mptcp_flush_join_list(msk); -+ __mptcp_flush_join_list(msk); - ssk = mptcp_subflow_get_send(msk); - - /* First check. If the ssk has changed since -@@ -1548,12 +1574,10 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags) - } - - info.sent += ret; -- dfrag->already_sent += ret; -- msk->snd_nxt += ret; -- msk->snd_burst -= ret; -- msk->tx_pending_data -= ret; - copied += ret; - len -= ret; -+ -+ mptcp_update_post_push(msk, dfrag, ret); - } - WRITE_ONCE(msk->first_pending, mptcp_send_next(sk)); - } -@@ -1597,7 +1621,8 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk) - if (!xmit_ssk) - goto out; - if (xmit_ssk != ssk) { -- mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk)); -+ mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), -+ MPTCP_DELEGATE_SEND); - goto out; - } - -@@ -1606,13 +1631,11 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk) - goto out; - - info.sent += ret; -- dfrag->already_sent += ret; -- msk->snd_nxt += ret; -- msk->snd_burst -= ret; -- msk->tx_pending_data -= ret; - copied += ret; - len -= ret; - first = false; -+ -+ mptcp_update_post_push(msk, dfrag, ret); - } - WRITE_ONCE(msk->first_pending, mptcp_send_next(sk)); - } -@@ -2183,15 +2206,12 @@ bool __mptcp_retransmit_pending_data(struct sock *sk) - return false; - } - -- /* will accept ack for reijected data before re-sending them */ -- if (!msk->recovery || after64(msk->snd_nxt, msk->recovery_snd_nxt)) -- msk->recovery_snd_nxt = msk->snd_nxt; -+ msk->recovery_snd_nxt = msk->snd_nxt; - msk->recovery = true; - mptcp_data_unlock(sk); - - msk->first_pending = rtx_head; - msk->tx_pending_data += msk->snd_nxt - rtx_head->data_seq; -- msk->snd_nxt = rtx_head->data_seq; - msk->snd_burst = 0; - - /* be sure to clear the "sent status" on all re-injected fragments */ -@@ -2881,7 +2901,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err, - */ - if (WARN_ON_ONCE(!new_mptcp_sock)) { - tcp_sk(newsk)->is_mptcp = 0; -- return newsk; -+ goto out; - } - - /* acquire the 2nd reference for the owning socket */ -@@ -2893,6 +2913,8 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err, - MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK); - } - -+out: -+ newsk->sk_kern_sock = kern; - return newsk; - } - -@@ -2940,7 +2962,7 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk) - if (xmit_ssk == ssk) - __mptcp_subflow_push_pending(sk, ssk); - else if (xmit_ssk) -- mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk)); -+ mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), MPTCP_DELEGATE_SEND); - } else { - set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags); - } -@@ -2994,18 +3016,50 @@ static void mptcp_release_cb(struct sock *sk) - __mptcp_update_rmem(sk); - } - -+/* MP_JOIN client subflow must wait for 4th ack before sending any data: -+ * TCP can't schedule delack timer before the subflow is fully established. -+ * MPTCP uses the delack timer to do 3rd ack retransmissions -+ */ -+static void schedule_3rdack_retransmission(struct sock *ssk) -+{ -+ struct inet_connection_sock *icsk = inet_csk(ssk); -+ struct tcp_sock *tp = tcp_sk(ssk); -+ unsigned long timeout; -+ -+ if (mptcp_subflow_ctx(ssk)->fully_established) -+ return; -+ -+ /* reschedule with a timeout above RTT, as we must look only for drop */ -+ if (tp->srtt_us) -+ timeout = usecs_to_jiffies(tp->srtt_us >> (3 - 1)); -+ else -+ timeout = TCP_TIMEOUT_INIT; -+ timeout += jiffies; -+ -+ WARN_ON_ONCE(icsk->icsk_ack.pending & ICSK_ACK_TIMER); -+ icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER; -+ icsk->icsk_ack.timeout = timeout; -+ sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); -+} -+ - void mptcp_subflow_process_delegated(struct sock *ssk) - { - struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); - struct sock *sk = subflow->conn; - -- mptcp_data_lock(sk); -- if (!sock_owned_by_user(sk)) -- __mptcp_subflow_push_pending(sk, ssk); -- else -- set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags); -- mptcp_data_unlock(sk); -- mptcp_subflow_delegated_done(subflow); -+ if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { -+ mptcp_data_lock(sk); -+ if (!sock_owned_by_user(sk)) -+ __mptcp_subflow_push_pending(sk, ssk); -+ else -+ set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags); -+ mptcp_data_unlock(sk); -+ mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND); -+ } -+ if (test_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status)) { -+ schedule_3rdack_retransmission(ssk); -+ mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK); -+ } - } - - static int mptcp_hash(struct sock *sk) -diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h -index dc984676c5eb1..82c5dc4d6b49d 100644 ---- a/net/mptcp/protocol.h -+++ b/net/mptcp/protocol.h -@@ -401,6 +401,7 @@ struct mptcp_delegated_action { - DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); - - #define MPTCP_DELEGATE_SEND 0 -+#define MPTCP_DELEGATE_ACK 1 - - /* MPTCP subflow context */ - struct mptcp_subflow_context { -@@ -506,23 +507,23 @@ static inline void mptcp_add_pending_subflow(struct mptcp_sock *msk, - - void mptcp_subflow_process_delegated(struct sock *ssk); - --static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow) -+static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) - { - struct mptcp_delegated_action *delegated; - bool schedule; - -+ /* the caller held the subflow bh socket lock */ -+ lockdep_assert_in_softirq(); -+ - /* The implied barrier pairs with mptcp_subflow_delegated_done(), and - * ensures the below list check sees list updates done prior to status - * bit changes - */ -- if (!test_and_set_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { -+ if (!test_and_set_bit(action, &subflow->delegated_status)) { - /* still on delegated list from previous scheduling */ - if (!list_empty(&subflow->delegated_node)) - return; - -- /* the caller held the subflow bh socket lock */ -- lockdep_assert_in_softirq(); -- - delegated = this_cpu_ptr(&mptcp_delegated_actions); - schedule = list_empty(&delegated->head); - list_add_tail(&subflow->delegated_node, &delegated->head); -@@ -547,16 +548,16 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated) - - static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow) - { -- return test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status); -+ return !!READ_ONCE(subflow->delegated_status); - } - --static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow) -+static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow, int action) - { - /* pairs with mptcp_subflow_delegate, ensures delegate_node is updated before - * touching the status bit - */ - smp_wmb(); -- clear_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status); -+ clear_bit(action, &subflow->delegated_status); - } - - int mptcp_is_enabled(const struct net *net); -diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c -index 8c03afac5ca03..4bb305342fcc7 100644 ---- a/net/mptcp/sockopt.c -+++ b/net/mptcp/sockopt.c -@@ -523,7 +523,6 @@ static bool mptcp_supported_sockopt(int level, int optname) - case TCP_NODELAY: - case TCP_THIN_LINEAR_TIMEOUTS: - case TCP_CONGESTION: -- case TCP_ULP: - case TCP_CORK: - case TCP_KEEPIDLE: - case TCP_KEEPINTVL: -diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c -index ba9ae482141b0..dda8b76b77988 100644 ---- a/net/ncsi/ncsi-cmd.c -+++ b/net/ncsi/ncsi-cmd.c -@@ -18,6 +18,8 @@ - #include "internal.h" - #include "ncsi-pkt.h" - -+static const int padding_bytes = 26; -+ - u32 ncsi_calculate_checksum(unsigned char *data, int len) - { - u32 checksum = 0; -@@ -213,12 +215,17 @@ static int ncsi_cmd_handler_oem(struct sk_buff *skb, - { - struct ncsi_cmd_oem_pkt *cmd; - unsigned int len; -+ int payload; -+ /* NC-SI spec DSP_0222_1.2.0, section 8.2.2.2 -+ * requires payload to be padded with 0 to -+ * 32-bit boundary before the checksum field. -+ * Ensure the padding bytes are accounted for in -+ * skb allocation -+ */ - -+ payload = ALIGN(nca->payload, 4); - len = sizeof(struct ncsi_cmd_pkt_hdr) + 4; -- if (nca->payload < 26) -- len += 26; -- else -- len += nca->payload; -+ len += max(payload, padding_bytes); - - cmd = skb_put_zero(skb, len); - memcpy(&cmd->mfr_id, nca->data, nca->payload); -@@ -272,6 +279,7 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca) - struct net_device *dev = nd->dev; - int hlen = LL_RESERVED_SPACE(dev); - int tlen = dev->needed_tailroom; -+ int payload; - int len = hlen + tlen; - struct sk_buff *skb; - struct ncsi_request *nr; -@@ -281,14 +289,14 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca) - return NULL; - - /* NCSI command packet has 16-bytes header, payload, 4 bytes checksum. -+ * Payload needs padding so that the checksum field following payload is -+ * aligned to 32-bit boundary. - * The packet needs padding if its payload is less than 26 bytes to - * meet 64 bytes minimal ethernet frame length. - */ - len += sizeof(struct ncsi_cmd_pkt_hdr) + 4; -- if (nca->payload < 26) -- len += 26; -- else -- len += nca->payload; -+ payload = ALIGN(nca->payload, 4); -+ len += max(payload, padding_bytes); - - /* Allocate skb */ - skb = alloc_skb(len, GFP_ATOMIC); -diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c -index 128690c512dff..393058a43aa73 100644 ---- a/net/netfilter/ipvs/ip_vs_core.c -+++ b/net/netfilter/ipvs/ip_vs_core.c -@@ -1964,7 +1964,6 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int - struct ip_vs_proto_data *pd; - struct ip_vs_conn *cp; - int ret, pkts; -- int conn_reuse_mode; - struct sock *sk; - - /* Already marked as IPVS request or reply? */ -@@ -2041,15 +2040,16 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int - cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto, - ipvs, af, skb, &iph); - -- conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); -- if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { -+ if (!iph.fragoffs && is_new_conn(skb, &iph) && cp) { -+ int conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); - bool old_ct = false, resched = false; - - if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && - unlikely(!atomic_read(&cp->dest->weight))) { - resched = true; - old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); -- } else if (is_new_conn_expected(cp, conn_reuse_mode)) { -+ } else if (conn_reuse_mode && -+ is_new_conn_expected(cp, conn_reuse_mode)) { - old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); - if (!atomic_read(&cp->n_control)) { - resched = true; -diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c -index 770a63103c7a4..4712a90a1820c 100644 ---- a/net/netfilter/nf_conntrack_core.c -+++ b/net/netfilter/nf_conntrack_core.c -@@ -684,7 +684,7 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) - - tstamp = nf_conn_tstamp_find(ct); - if (tstamp) { -- s32 timeout = ct->timeout - nfct_time_stamp; -+ s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; - - tstamp->stop = ktime_get_real_ns(); - if (timeout < 0) -@@ -1036,7 +1036,7 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx) - } - - /* We want the clashing entry to go away real soon: 1 second timeout. */ -- loser_ct->timeout = nfct_time_stamp + HZ; -+ WRITE_ONCE(loser_ct->timeout, nfct_time_stamp + HZ); - - /* IPS_NAT_CLASH removes the entry automatically on the first - * reply. Also prevents UDP tracker from moving the entry to -@@ -1560,7 +1560,7 @@ __nf_conntrack_alloc(struct net *net, - /* save hash for reusing when confirming */ - *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; - ct->status = 0; -- ct->timeout = 0; -+ WRITE_ONCE(ct->timeout, 0); - write_pnet(&ct->ct_net, net); - memset(&ct->__nfct_init_offset, 0, - offsetof(struct nf_conn, proto) - -diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c -index f1e5443fe7c74..81d03acf68d4d 100644 ---- a/net/netfilter/nf_conntrack_netlink.c -+++ b/net/netfilter/nf_conntrack_netlink.c -@@ -1011,11 +1011,9 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) - CTA_TUPLE_REPLY, - filter->family, - &filter->zone, -- filter->orig_flags); -- if (err < 0) { -- err = -EINVAL; -+ filter->reply_flags); -+ if (err < 0) - goto err_filter; -- } - } - - return filter; -@@ -2000,7 +1998,7 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, - - if (timeout > INT_MAX) - timeout = INT_MAX; -- ct->timeout = nfct_time_stamp + (u32)timeout; -+ WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout); - - if (test_bit(IPS_DYING_BIT, &ct->status)) - return -ETIME; -diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c -index f8e3c0d2602f6..3b516cffc779b 100644 ---- a/net/netfilter/nf_conntrack_proto_udp.c -+++ b/net/netfilter/nf_conntrack_proto_udp.c -@@ -104,10 +104,13 @@ int nf_conntrack_udp_packet(struct nf_conn *ct, - */ - if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { - unsigned long extra = timeouts[UDP_CT_UNREPLIED]; -+ bool stream = false; - - /* Still active after two seconds? Extend timeout. */ -- if (time_after(jiffies, ct->proto.udp.stream_ts)) -+ if (time_after(jiffies, ct->proto.udp.stream_ts)) { - extra = timeouts[UDP_CT_REPLIED]; -+ stream = true; -+ } - - nf_ct_refresh_acct(ct, ctinfo, skb, extra); - -@@ -116,7 +119,7 @@ int nf_conntrack_udp_packet(struct nf_conn *ct, - return NF_ACCEPT; - - /* Also, more likely to be important, and not a probe */ -- if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) -+ if (stream && !test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) - nf_conntrack_event_cache(IPCT_ASSURED, ct); - } else { - nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]); -diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c -index 87a7388b6c894..ed37bb9b4e588 100644 ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -201,8 +201,8 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) - if (timeout < 0) - timeout = 0; - -- if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout) -- ct->timeout = nfct_time_stamp + timeout; -+ if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout) -+ WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout); - } - - static void flow_offload_fixup_ct_state(struct nf_conn *ct) -diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c -index d6bf1b2cd541b..b561e0a44a45f 100644 ---- a/net/netfilter/nf_flow_table_offload.c -+++ b/net/netfilter/nf_flow_table_offload.c -@@ -65,11 +65,11 @@ static void nf_flow_rule_lwt_match(struct nf_flow_match *match, - sizeof(struct in6_addr)); - if (memcmp(&key->enc_ipv6.src, &in6addr_any, - sizeof(struct in6_addr))) -- memset(&key->enc_ipv6.src, 0xff, -+ memset(&mask->enc_ipv6.src, 0xff, - sizeof(struct in6_addr)); - if (memcmp(&key->enc_ipv6.dst, &in6addr_any, - sizeof(struct in6_addr))) -- memset(&key->enc_ipv6.dst, 0xff, -+ memset(&mask->enc_ipv6.dst, 0xff, - sizeof(struct in6_addr)); - enc_keys |= BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS); - key->enc_control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index 4c3fbaaeb1030..4acc4b8e9fe5a 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -560,7 +560,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, - goto nla_put_failure; - - if (indev && entskb->dev && -- entskb->mac_header != entskb->network_header) { -+ skb_mac_header_was_set(entskb)) { - struct nfqnl_msg_packet_hw phw; - int len; - -diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c -index 6ba3256fa8449..87f3af4645d9c 100644 ---- a/net/netfilter/nft_dynset.c -+++ b/net/netfilter/nft_dynset.c -@@ -198,17 +198,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx, - return -EBUSY; - - priv->op = ntohl(nla_get_be32(tb[NFTA_DYNSET_OP])); -- switch (priv->op) { -- case NFT_DYNSET_OP_ADD: -- case NFT_DYNSET_OP_DELETE: -- break; -- case NFT_DYNSET_OP_UPDATE: -- if (!(set->flags & NFT_SET_TIMEOUT)) -- return -EOPNOTSUPP; -- break; -- default: -+ if (priv->op > NFT_DYNSET_OP_DELETE) - return -EOPNOTSUPP; -- } - - timeout = 0; - if (tb[NFTA_DYNSET_TIMEOUT] != NULL) { -diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c -index af4ee874a067c..dbe1f2e7dd9ed 100644 ---- a/net/netfilter/nft_exthdr.c -+++ b/net/netfilter/nft_exthdr.c -@@ -236,7 +236,7 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, - - tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, &tcphdr_len); - if (!tcph) -- return; -+ goto err; - - opt = (u8 *)tcph; - for (i = sizeof(*tcph); i < tcphdr_len - 1; i += optl) { -@@ -251,16 +251,16 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, - continue; - - if (i + optl > tcphdr_len || priv->len + priv->offset > optl) -- return; -+ goto err; - - if (skb_ensure_writable(pkt->skb, - nft_thoff(pkt) + i + priv->len)) -- return; -+ goto err; - - tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, - &tcphdr_len); - if (!tcph) -- return; -+ goto err; - - offset = i + priv->offset; - -@@ -303,6 +303,9 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, - - return; - } -+ return; -+err: -+ regs->verdict.code = NFT_BREAK; - } - - static void nft_exthdr_sctp_eval(const struct nft_expr *expr, -diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c -index e517663e0cd17..6f4116e729581 100644 ---- a/net/netfilter/nft_set_pipapo_avx2.c -+++ b/net/netfilter/nft_set_pipapo_avx2.c -@@ -886,7 +886,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill, - NFT_PIPAPO_AVX2_BUCKET_LOAD8(4, lt, 4, pkt[4], bsize); - - NFT_PIPAPO_AVX2_AND(5, 0, 1); -- NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 6, pkt[5], bsize); -+ NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 5, pkt[5], bsize); - NFT_PIPAPO_AVX2_AND(7, 2, 3); - - /* Stall */ -diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c -index ada47e59647a0..81ba8e51e01ff 100644 ---- a/net/netlink/af_netlink.c -+++ b/net/netlink/af_netlink.c -@@ -1871,6 +1871,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) - if (msg->msg_flags & MSG_OOB) - return -EOPNOTSUPP; - -+ if (len == 0) { -+ pr_warn_once("Zero length message leads to an empty skb\n"); -+ return -ENODATA; -+ } -+ - err = scm_send(sock, msg, &scm, true); - if (err < 0) - return err; -diff --git a/net/nfc/core.c b/net/nfc/core.c -index 3c645c1d99c9b..dc7a2404efdf9 100644 ---- a/net/nfc/core.c -+++ b/net/nfc/core.c -@@ -94,13 +94,13 @@ int nfc_dev_up(struct nfc_dev *dev) - - device_lock(&dev->dev); - -- if (dev->rfkill && rfkill_blocked(dev->rfkill)) { -- rc = -ERFKILL; -+ if (!device_is_registered(&dev->dev)) { -+ rc = -ENODEV; - goto error; - } - -- if (!device_is_registered(&dev->dev)) { -- rc = -ENODEV; -+ if (dev->rfkill && rfkill_blocked(dev->rfkill)) { -+ rc = -ERFKILL; - goto error; - } - -@@ -1125,11 +1125,7 @@ int nfc_register_device(struct nfc_dev *dev) - if (rc) - pr_err("Could not register llcp device\n"); - -- rc = nfc_genl_device_added(dev); -- if (rc) -- pr_debug("The userspace won't be notified that the device %s was added\n", -- dev_name(&dev->dev)); -- -+ device_lock(&dev->dev); - dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev, - RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev); - if (dev->rfkill) { -@@ -1138,6 +1134,12 @@ int nfc_register_device(struct nfc_dev *dev) - dev->rfkill = NULL; - } - } -+ device_unlock(&dev->dev); -+ -+ rc = nfc_genl_device_added(dev); -+ if (rc) -+ pr_debug("The userspace won't be notified that the device %s was added\n", -+ dev_name(&dev->dev)); - - return 0; - } -@@ -1154,10 +1156,17 @@ void nfc_unregister_device(struct nfc_dev *dev) - - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); - -+ rc = nfc_genl_device_removed(dev); -+ if (rc) -+ pr_debug("The userspace won't be notified that the device %s " -+ "was removed\n", dev_name(&dev->dev)); -+ -+ device_lock(&dev->dev); - if (dev->rfkill) { - rfkill_unregister(dev->rfkill); - rfkill_destroy(dev->rfkill); - } -+ device_unlock(&dev->dev); - - if (dev->ops->check_presence) { - device_lock(&dev->dev); -@@ -1167,11 +1176,6 @@ void nfc_unregister_device(struct nfc_dev *dev) - cancel_work_sync(&dev->check_pres_work); - } - -- rc = nfc_genl_device_removed(dev); -- if (rc) -- pr_debug("The userspace won't be notified that the device %s " -- "was removed\n", dev_name(&dev->dev)); -- - nfc_llcp_unregister_device(dev); - - mutex_lock(&nfc_devlist_mutex); -diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c -index 82ab39d80726e..e41e2e9e54984 100644 ---- a/net/nfc/nci/core.c -+++ b/net/nfc/nci/core.c -@@ -144,12 +144,15 @@ inline int nci_request(struct nci_dev *ndev, - { - int rc; - -- if (!test_bit(NCI_UP, &ndev->flags)) -- return -ENETDOWN; -- - /* Serialize all requests */ - mutex_lock(&ndev->req_lock); -- rc = __nci_request(ndev, req, opt, timeout); -+ /* check the state after obtaing the lock against any races -+ * from nci_close_device when the device gets removed. -+ */ -+ if (test_bit(NCI_UP, &ndev->flags)) -+ rc = __nci_request(ndev, req, opt, timeout); -+ else -+ rc = -ENETDOWN; - mutex_unlock(&ndev->req_lock); - - return rc; -@@ -473,6 +476,11 @@ static int nci_open_device(struct nci_dev *ndev) - - mutex_lock(&ndev->req_lock); - -+ if (test_bit(NCI_UNREG, &ndev->flags)) { -+ rc = -ENODEV; -+ goto done; -+ } -+ - if (test_bit(NCI_UP, &ndev->flags)) { - rc = -EALREADY; - goto done; -@@ -545,6 +553,10 @@ done: - static int nci_close_device(struct nci_dev *ndev) - { - nci_req_cancel(ndev, ENODEV); -+ -+ /* This mutex needs to be held as a barrier for -+ * caller nci_unregister_device -+ */ - mutex_lock(&ndev->req_lock); - - if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { -@@ -582,8 +594,8 @@ static int nci_close_device(struct nci_dev *ndev) - - del_timer_sync(&ndev->cmd_timer); - -- /* Clear flags */ -- ndev->flags = 0; -+ /* Clear flags except NCI_UNREG */ -+ ndev->flags &= BIT(NCI_UNREG); - - mutex_unlock(&ndev->req_lock); - -@@ -1270,6 +1282,12 @@ void nci_unregister_device(struct nci_dev *ndev) - { - struct nci_conn_info *conn_info, *n; - -+ /* This set_bit is not protected with specialized barrier, -+ * However, it is fine because the mutex_lock(&ndev->req_lock); -+ * in nci_close_device() will help to emit one. -+ */ -+ set_bit(NCI_UNREG, &ndev->flags); -+ - nci_close_device(ndev); - - destroy_workqueue(ndev->cmd_wq); -diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c -index 49089c50872e6..8048a3dcc5f8b 100644 ---- a/net/nfc/netlink.c -+++ b/net/nfc/netlink.c -@@ -636,8 +636,10 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) - { - struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; - -- nfc_device_iter_exit(iter); -- kfree(iter); -+ if (iter) { -+ nfc_device_iter_exit(iter); -+ kfree(iter); -+ } - - return 0; - } -@@ -1392,8 +1394,10 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) - { - struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; - -- nfc_device_iter_exit(iter); -- kfree(iter); -+ if (iter) { -+ nfc_device_iter_exit(iter); -+ kfree(iter); -+ } - - return 0; - } -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index 2a2bc64f75cfd..1bc7ef49e1487 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -4457,9 +4457,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, - } - - out_free_pg_vec: -- bitmap_free(rx_owner_map); -- if (pg_vec) -+ if (pg_vec) { -+ bitmap_free(rx_owner_map); - free_pg_vec(pg_vec, order, req->tp_block_nr); -+ } - out: - return err; - } -diff --git a/net/rds/connection.c b/net/rds/connection.c -index a3bc4b54d4910..b4cc699c5fad3 100644 ---- a/net/rds/connection.c -+++ b/net/rds/connection.c -@@ -253,6 +253,7 @@ static struct rds_connection *__rds_conn_create(struct net *net, - * should end up here, but if it - * does, reset/destroy the connection. - */ -+ kfree(conn->c_path); - kmem_cache_free(rds_conn_slab, conn); - conn = ERR_PTR(-EOPNOTSUPP); - goto out; -diff --git a/net/rds/tcp.c b/net/rds/tcp.c -index abf19c0e3ba0b..5327d130c4b56 100644 ---- a/net/rds/tcp.c -+++ b/net/rds/tcp.c -@@ -500,7 +500,7 @@ void rds_tcp_tune(struct socket *sock) - sk->sk_userlocks |= SOCK_SNDBUF_LOCK; - } - if (rtn->rcvbuf_size > 0) { -- sk->sk_sndbuf = rtn->rcvbuf_size; -+ sk->sk_rcvbuf = rtn->rcvbuf_size; - sk->sk_userlocks |= SOCK_RCVBUF_LOCK; - } - release_sock(sk); -diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c -index dbea0bfee48e9..8120138dac018 100644 ---- a/net/rxrpc/conn_client.c -+++ b/net/rxrpc/conn_client.c -@@ -135,16 +135,20 @@ struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle) - return bundle; - } - -+static void rxrpc_free_bundle(struct rxrpc_bundle *bundle) -+{ -+ rxrpc_put_peer(bundle->params.peer); -+ kfree(bundle); -+} -+ - void rxrpc_put_bundle(struct rxrpc_bundle *bundle) - { - unsigned int d = bundle->debug_id; - unsigned int u = atomic_dec_return(&bundle->usage); - - _debug("PUT B=%x %u", d, u); -- if (u == 0) { -- rxrpc_put_peer(bundle->params.peer); -- kfree(bundle); -- } -+ if (u == 0) -+ rxrpc_free_bundle(bundle); - } - - /* -@@ -328,7 +332,7 @@ static struct rxrpc_bundle *rxrpc_look_up_bundle(struct rxrpc_conn_parameters *c - return candidate; - - found_bundle_free: -- kfree(candidate); -+ rxrpc_free_bundle(candidate); - found_bundle: - rxrpc_get_bundle(bundle); - spin_unlock(&local->client_bundles_lock); -diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c -index 68396d0520525..0298fe2ad6d32 100644 ---- a/net/rxrpc/peer_object.c -+++ b/net/rxrpc/peer_object.c -@@ -299,6 +299,12 @@ static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_sock *rx, - return peer; - } - -+static void rxrpc_free_peer(struct rxrpc_peer *peer) -+{ -+ rxrpc_put_local(peer->local); -+ kfree_rcu(peer, rcu); -+} -+ - /* - * Set up a new incoming peer. There shouldn't be any other matching peers - * since we've already done a search in the list from the non-reentrant context -@@ -365,7 +371,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx, - spin_unlock_bh(&rxnet->peer_hash_lock); - - if (peer) -- kfree(candidate); -+ rxrpc_free_peer(candidate); - else - peer = candidate; - } -@@ -420,8 +426,7 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer) - list_del_init(&peer->keepalive_link); - spin_unlock_bh(&rxnet->peer_hash_lock); - -- rxrpc_put_local(peer->local); -- kfree_rcu(peer, rcu); -+ rxrpc_free_peer(peer); - } - - /* -@@ -457,8 +462,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *peer) - if (n == 0) { - hash_del_rcu(&peer->hash_link); - list_del_init(&peer->keepalive_link); -- rxrpc_put_local(peer->local); -- kfree_rcu(peer, rcu); -+ rxrpc_free_peer(peer); - } - } - -diff --git a/net/rxrpc/rtt.c b/net/rxrpc/rtt.c -index 4e565eeab4260..be61d6f5be8d1 100644 ---- a/net/rxrpc/rtt.c -+++ b/net/rxrpc/rtt.c -@@ -22,7 +22,7 @@ static u32 rxrpc_rto_min_us(struct rxrpc_peer *peer) - - static u32 __rxrpc_set_rto(const struct rxrpc_peer *peer) - { -- return _usecs_to_jiffies((peer->srtt_us >> 3) + peer->rttvar_us); -+ return usecs_to_jiffies((peer->srtt_us >> 3) + peer->rttvar_us); - } - - static u32 rxrpc_bound_rto(u32 rto) -diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c -index d64b0eeccbe4d..efc963ab995a3 100644 ---- a/net/sched/act_mirred.c -+++ b/net/sched/act_mirred.c -@@ -19,6 +19,7 @@ - #include <linux/if_arp.h> - #include <net/net_namespace.h> - #include <net/netlink.h> -+#include <net/dst.h> - #include <net/pkt_sched.h> - #include <net/pkt_cls.h> - #include <linux/tc_act/tc_mirred.h> -@@ -228,6 +229,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, - bool want_ingress; - bool is_redirect; - bool expects_nh; -+ bool at_ingress; - int m_eaction; - int mac_len; - bool at_nh; -@@ -263,7 +265,8 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, - * ingress - that covers the TC S/W datapath. - */ - is_redirect = tcf_mirred_is_act_redirect(m_eaction); -- use_reinsert = skb_at_tc_ingress(skb) && is_redirect && -+ at_ingress = skb_at_tc_ingress(skb); -+ use_reinsert = at_ingress && is_redirect && - tcf_mirred_can_reinsert(retval); - if (!use_reinsert) { - skb2 = skb_clone(skb, GFP_ATOMIC); -@@ -271,10 +274,12 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, - goto out; - } - -+ want_ingress = tcf_mirred_act_wants_ingress(m_eaction); -+ - /* All mirred/redirected skbs should clear previous ct info */ - nf_reset_ct(skb2); -- -- want_ingress = tcf_mirred_act_wants_ingress(m_eaction); -+ if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */ -+ skb_dst_drop(skb2); - - expects_nh = want_ingress || !m_mac_header_xmit; - at_nh = skb->data == skb_network_header(skb); -diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c -index 2ef8f5a6205a9..e54f0a42270c1 100644 ---- a/net/sched/cls_api.c -+++ b/net/sched/cls_api.c -@@ -3687,6 +3687,7 @@ int tc_setup_flow_action(struct flow_action *flow_action, - entry->mpls_mangle.ttl = tcf_mpls_ttl(act); - break; - default: -+ err = -EOPNOTSUPP; - goto err_out_locked; - } - } else if (is_tcf_skbedit_ptype(act)) { -diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c -index 3c2300d144681..857aaebd49f43 100644 ---- a/net/sched/sch_cake.c -+++ b/net/sched/sch_cake.c -@@ -2736,7 +2736,7 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt, - q->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), - GFP_KERNEL); - if (!q->tins) -- goto nomem; -+ return -ENOMEM; - - for (i = 0; i < CAKE_MAX_TINS; i++) { - struct cake_tin_data *b = q->tins + i; -@@ -2766,10 +2766,6 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt, - q->min_netlen = ~0; - q->min_adjlen = ~0; - return 0; -- --nomem: -- cake_destroy(sch); -- return -ENOMEM; - } - - static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) -diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c -index 1f857ffd1ac23..44fa2532a87c0 100644 ---- a/net/sched/sch_ets.c -+++ b/net/sched/sch_ets.c -@@ -667,12 +667,14 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, - q->classes[i].deficit = quanta[i]; - } - } -+ for (i = q->nbands; i < oldbands; i++) { -+ if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) -+ list_del(&q->classes[i].alist); -+ qdisc_tree_flush_backlog(q->classes[i].qdisc); -+ } - q->nstrict = nstrict; - memcpy(q->prio2band, priomap, sizeof(priomap)); - -- for (i = q->nbands; i < oldbands; i++) -- qdisc_tree_flush_backlog(q->classes[i].qdisc); -- - for (i = 0; i < q->nbands; i++) - q->classes[i].quantum = quanta[i]; - -diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c -index 830f3559f727a..d6aba6edd16e5 100644 ---- a/net/sched/sch_fq_pie.c -+++ b/net/sched/sch_fq_pie.c -@@ -531,6 +531,7 @@ static void fq_pie_destroy(struct Qdisc *sch) - struct fq_pie_sched_data *q = qdisc_priv(sch); - - tcf_block_put(q->block); -+ q->p_params.tupdate = 0; - del_timer_sync(&q->adapt_timer); - kvfree(q->flows); - } -diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c -index a8dd06c74e318..66d2fbe9ef501 100644 ---- a/net/sched/sch_generic.c -+++ b/net/sched/sch_generic.c -@@ -1330,6 +1330,15 @@ static int qdisc_change_tx_queue_len(struct net_device *dev, - return 0; - } - -+void dev_qdisc_change_real_num_tx(struct net_device *dev, -+ unsigned int new_real_tx) -+{ -+ struct Qdisc *qdisc = dev->qdisc; -+ -+ if (qdisc->ops->change_real_num_tx) -+ qdisc->ops->change_real_num_tx(qdisc, new_real_tx); -+} -+ - int dev_qdisc_change_tx_queue_len(struct net_device *dev) - { - bool up = dev->flags & IFF_UP; -diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c -index e79f1afe0cfd6..db18d8a860f9c 100644 ---- a/net/sched/sch_mq.c -+++ b/net/sched/sch_mq.c -@@ -125,6 +125,29 @@ static void mq_attach(struct Qdisc *sch) - priv->qdiscs = NULL; - } - -+static void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx) -+{ -+#ifdef CONFIG_NET_SCHED -+ struct net_device *dev = qdisc_dev(sch); -+ struct Qdisc *qdisc; -+ unsigned int i; -+ -+ for (i = new_real_tx; i < dev->real_num_tx_queues; i++) { -+ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; -+ /* Only update the default qdiscs we created, -+ * qdiscs with handles are always hashed. -+ */ -+ if (qdisc != &noop_qdisc && !qdisc->handle) -+ qdisc_hash_del(qdisc); -+ } -+ for (i = dev->real_num_tx_queues; i < new_real_tx; i++) { -+ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; -+ if (qdisc != &noop_qdisc && !qdisc->handle) -+ qdisc_hash_add(qdisc, false); -+ } -+#endif -+} -+ - static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) - { - struct net_device *dev = qdisc_dev(sch); -@@ -288,6 +311,7 @@ struct Qdisc_ops mq_qdisc_ops __read_mostly = { - .init = mq_init, - .destroy = mq_destroy, - .attach = mq_attach, -+ .change_real_num_tx = mq_change_real_num_tx, - .dump = mq_dump, - .owner = THIS_MODULE, - }; -diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c -index 5eb3b1b7ae5e7..50e15add6068f 100644 ---- a/net/sched/sch_mqprio.c -+++ b/net/sched/sch_mqprio.c -@@ -306,6 +306,28 @@ static void mqprio_attach(struct Qdisc *sch) - priv->qdiscs = NULL; - } - -+static void mqprio_change_real_num_tx(struct Qdisc *sch, -+ unsigned int new_real_tx) -+{ -+ struct net_device *dev = qdisc_dev(sch); -+ struct Qdisc *qdisc; -+ unsigned int i; -+ -+ for (i = new_real_tx; i < dev->real_num_tx_queues; i++) { -+ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; -+ /* Only update the default qdiscs we created, -+ * qdiscs with handles are always hashed. -+ */ -+ if (qdisc != &noop_qdisc && !qdisc->handle) -+ qdisc_hash_del(qdisc); -+ } -+ for (i = dev->real_num_tx_queues; i < new_real_tx; i++) { -+ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; -+ if (qdisc != &noop_qdisc && !qdisc->handle) -+ qdisc_hash_add(qdisc, false); -+ } -+} -+ - static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch, - unsigned long cl) - { -@@ -629,6 +651,7 @@ static struct Qdisc_ops mqprio_qdisc_ops __read_mostly = { - .init = mqprio_init, - .destroy = mqprio_destroy, - .attach = mqprio_attach, -+ .change_real_num_tx = mqprio_change_real_num_tx, - .dump = mqprio_dump, - .owner = THIS_MODULE, - }; -diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c -index b9fd18d986464..a66398fb2d6d0 100644 ---- a/net/sched/sch_taprio.c -+++ b/net/sched/sch_taprio.c -@@ -95,18 +95,22 @@ static ktime_t sched_base_time(const struct sched_gate_list *sched) - return ns_to_ktime(sched->base_time); - } - --static ktime_t taprio_get_time(struct taprio_sched *q) -+static ktime_t taprio_mono_to_any(const struct taprio_sched *q, ktime_t mono) - { -- ktime_t mono = ktime_get(); -+ /* This pairs with WRITE_ONCE() in taprio_parse_clockid() */ -+ enum tk_offsets tk_offset = READ_ONCE(q->tk_offset); - -- switch (q->tk_offset) { -+ switch (tk_offset) { - case TK_OFFS_MAX: - return mono; - default: -- return ktime_mono_to_any(mono, q->tk_offset); -+ return ktime_mono_to_any(mono, tk_offset); - } -+} - -- return KTIME_MAX; -+static ktime_t taprio_get_time(const struct taprio_sched *q) -+{ -+ return taprio_mono_to_any(q, ktime_get()); - } - - static void taprio_free_sched_cb(struct rcu_head *head) -@@ -319,7 +323,7 @@ static ktime_t get_tcp_tstamp(struct taprio_sched *q, struct sk_buff *skb) - return 0; - } - -- return ktime_mono_to_any(skb->skb_mstamp_ns, q->tk_offset); -+ return taprio_mono_to_any(q, skb->skb_mstamp_ns); - } - - /* There are a few scenarios where we will have to modify the txtime from -@@ -1352,6 +1356,7 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb, - } - } else if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]) { - int clockid = nla_get_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]); -+ enum tk_offsets tk_offset; - - /* We only support static clockids and we don't allow - * for it to be modified after the first init. -@@ -1366,22 +1371,24 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb, - - switch (clockid) { - case CLOCK_REALTIME: -- q->tk_offset = TK_OFFS_REAL; -+ tk_offset = TK_OFFS_REAL; - break; - case CLOCK_MONOTONIC: -- q->tk_offset = TK_OFFS_MAX; -+ tk_offset = TK_OFFS_MAX; - break; - case CLOCK_BOOTTIME: -- q->tk_offset = TK_OFFS_BOOT; -+ tk_offset = TK_OFFS_BOOT; - break; - case CLOCK_TAI: -- q->tk_offset = TK_OFFS_TAI; -+ tk_offset = TK_OFFS_TAI; - break; - default: - NL_SET_ERR_MSG(extack, "Invalid 'clockid'"); - err = -EINVAL; - goto out; - } -+ /* This pairs with READ_ONCE() in taprio_mono_to_any */ -+ WRITE_ONCE(q->tk_offset, tk_offset); - - q->clockid = clockid; - } else { -diff --git a/net/sctp/output.c b/net/sctp/output.c -index 4dfb5ea82b05b..cdfdbd353c678 100644 ---- a/net/sctp/output.c -+++ b/net/sctp/output.c -@@ -581,13 +581,16 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) - chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list); - sk = chunk->skb->sk; - -- /* check gso */ - if (packet->size > tp->pathmtu && !packet->ipfragok && !chunk->pmtu_probe) { -- if (!sk_can_gso(sk)) { -- pr_err_once("Trying to GSO but underlying device doesn't support it."); -- goto out; -+ if (tp->pl.state == SCTP_PL_ERROR) { /* do IP fragmentation if in Error state */ -+ packet->ipfragok = 1; -+ } else { -+ if (!sk_can_gso(sk)) { /* check gso */ -+ pr_err_once("Trying to GSO but underlying device doesn't support it."); -+ goto out; -+ } -+ gso = 1; - } -- gso = 1; - } - - /* alloc head skb */ -diff --git a/net/sctp/transport.c b/net/sctp/transport.c -index a3d3ca6dd63dd..133f1719bf1b7 100644 ---- a/net/sctp/transport.c -+++ b/net/sctp/transport.c -@@ -269,7 +269,7 @@ bool sctp_transport_pl_send(struct sctp_transport *t) - if (t->pl.probe_size == SCTP_BASE_PLPMTU) { /* BASE_PLPMTU Confirmation Failed */ - t->pl.state = SCTP_PL_ERROR; /* Base -> Error */ - -- t->pl.pmtu = SCTP_MIN_PLPMTU; -+ t->pl.pmtu = SCTP_BASE_PLPMTU; - t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); - sctp_assoc_sync_pmtu(t->asoc); - } -@@ -366,8 +366,9 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu) - if (pmtu >= SCTP_MIN_PLPMTU && pmtu < SCTP_BASE_PLPMTU) { - t->pl.state = SCTP_PL_ERROR; /* Base -> Error */ - -- t->pl.pmtu = SCTP_MIN_PLPMTU; -+ t->pl.pmtu = SCTP_BASE_PLPMTU; - t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); -+ return true; - } - } else if (t->pl.state == SCTP_PL_SEARCH) { - if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) { -@@ -378,11 +379,10 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu) - t->pl.probe_high = 0; - t->pl.pmtu = SCTP_BASE_PLPMTU; - t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); -+ return true; - } else if (pmtu > t->pl.pmtu && pmtu < t->pl.probe_size) { - t->pl.probe_size = pmtu; - t->pl.probe_count = 0; -- -- return false; - } - } else if (t->pl.state == SCTP_PL_COMPLETE) { - if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) { -@@ -393,10 +393,11 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu) - t->pl.probe_high = 0; - t->pl.pmtu = SCTP_BASE_PLPMTU; - t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); -+ return true; - } - } - -- return true; -+ return false; - } - - bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) -diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c -index 78b663dbfa1f9..eea6d4a854e90 100644 ---- a/net/smc/af_smc.c -+++ b/net/smc/af_smc.c -@@ -148,14 +148,18 @@ static int __smc_release(struct smc_sock *smc) - sock_set_flag(sk, SOCK_DEAD); - sk->sk_shutdown |= SHUTDOWN_MASK; - } else { -- if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT) -- sock_put(sk); /* passive closing */ -- if (sk->sk_state == SMC_LISTEN) { -- /* wake up clcsock accept */ -- rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); -+ if (sk->sk_state != SMC_CLOSED) { -+ if (sk->sk_state != SMC_LISTEN && -+ sk->sk_state != SMC_INIT) -+ sock_put(sk); /* passive closing */ -+ if (sk->sk_state == SMC_LISTEN) { -+ /* wake up clcsock accept */ -+ rc = kernel_sock_shutdown(smc->clcsock, -+ SHUT_RDWR); -+ } -+ sk->sk_state = SMC_CLOSED; -+ sk->sk_state_change(sk); - } -- sk->sk_state = SMC_CLOSED; -- sk->sk_state_change(sk); - smc_restore_fallback_changes(smc); - } - -@@ -189,7 +193,9 @@ static int smc_release(struct socket *sock) - /* cleanup for a dangling non-blocking connect */ - if (smc->connect_nonblock && sk->sk_state == SMC_INIT) - tcp_abort(smc->clcsock->sk, ECONNABORTED); -- flush_work(&smc->connect_work); -+ -+ if (cancel_work_sync(&smc->connect_work)) -+ sock_put(&smc->sk); /* sock_hold in smc_connect for passive closing */ - - if (sk->sk_state == SMC_LISTEN) - /* smc_close_non_accepted() is called and acquires -@@ -544,6 +550,10 @@ static void smc_stat_fallback(struct smc_sock *smc) - - static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code) - { -+ wait_queue_head_t *smc_wait = sk_sleep(&smc->sk); -+ wait_queue_head_t *clc_wait = sk_sleep(smc->clcsock->sk); -+ unsigned long flags; -+ - smc->use_fallback = true; - smc->fallback_rsn = reason_code; - smc_stat_fallback(smc); -@@ -552,6 +562,16 @@ static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code) - smc->clcsock->file->private_data = smc->clcsock; - smc->clcsock->wq.fasync_list = - smc->sk.sk_socket->wq.fasync_list; -+ -+ /* There may be some entries remaining in -+ * smc socket->wq, which should be removed -+ * to clcsocket->wq during the fallback. -+ */ -+ spin_lock_irqsave(&smc_wait->lock, flags); -+ spin_lock_nested(&clc_wait->lock, SINGLE_DEPTH_NESTING); -+ list_splice_init(&smc_wait->head, &clc_wait->head); -+ spin_unlock(&clc_wait->lock); -+ spin_unlock_irqrestore(&smc_wait->lock, flags); - } - } - -@@ -1914,8 +1934,10 @@ static int smc_listen(struct socket *sock, int backlog) - smc->clcsock->sk->sk_user_data = - (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); - rc = kernel_listen(smc->clcsock, backlog); -- if (rc) -+ if (rc) { -+ smc->clcsock->sk->sk_data_ready = smc->clcsk_data_ready; - goto out; -+ } - sk->sk_max_ack_backlog = backlog; - sk->sk_ack_backlog = 0; - sk->sk_state = SMC_LISTEN; -@@ -2148,8 +2170,10 @@ static __poll_t smc_poll(struct file *file, struct socket *sock, - static int smc_shutdown(struct socket *sock, int how) - { - struct sock *sk = sock->sk; -+ bool do_shutdown = true; - struct smc_sock *smc; - int rc = -EINVAL; -+ int old_state; - int rc1 = 0; - - smc = smc_sk(sk); -@@ -2176,7 +2200,11 @@ static int smc_shutdown(struct socket *sock, int how) - } - switch (how) { - case SHUT_RDWR: /* shutdown in both directions */ -+ old_state = sk->sk_state; - rc = smc_close_active(smc); -+ if (old_state == SMC_ACTIVE && -+ sk->sk_state == SMC_PEERCLOSEWAIT1) -+ do_shutdown = false; - break; - case SHUT_WR: - rc = smc_close_shutdown_write(smc); -@@ -2186,7 +2214,7 @@ static int smc_shutdown(struct socket *sock, int how) - /* nothing more to do because peer is not involved */ - break; - } -- if (smc->clcsock) -+ if (do_shutdown && smc->clcsock) - rc1 = kernel_sock_shutdown(smc->clcsock, how); - /* map sock_shutdown_cmd constants to sk_shutdown value range */ - sk->sk_shutdown |= how + 1; -diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c -index 0f9ffba07d268..84102db5bb314 100644 ---- a/net/smc/smc_close.c -+++ b/net/smc/smc_close.c -@@ -195,6 +195,7 @@ int smc_close_active(struct smc_sock *smc) - int old_state; - long timeout; - int rc = 0; -+ int rc1 = 0; - - timeout = current->flags & PF_EXITING ? - 0 : sock_flag(sk, SOCK_LINGER) ? -@@ -228,6 +229,15 @@ again: - /* send close request */ - rc = smc_close_final(conn); - sk->sk_state = SMC_PEERCLOSEWAIT1; -+ -+ /* actively shutdown clcsock before peer close it, -+ * prevent peer from entering TIME_WAIT state. -+ */ -+ if (smc->clcsock && smc->clcsock->sk) { -+ rc1 = kernel_sock_shutdown(smc->clcsock, -+ SHUT_RDWR); -+ rc = rc ? rc : rc1; -+ } - } else { - /* peer event has changed the state */ - goto again; -diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c -index d2206743dc714..5a9c22ee75fa4 100644 ---- a/net/smc/smc_core.c -+++ b/net/smc/smc_core.c -@@ -582,18 +582,17 @@ int smcd_nl_get_lgr(struct sk_buff *skb, struct netlink_callback *cb) - void smc_lgr_cleanup_early(struct smc_connection *conn) - { - struct smc_link_group *lgr = conn->lgr; -- struct list_head *lgr_list; - spinlock_t *lgr_lock; - - if (!lgr) - return; - - smc_conn_free(conn); -- lgr_list = smc_lgr_list_head(lgr, &lgr_lock); -+ smc_lgr_list_head(lgr, &lgr_lock); - spin_lock_bh(lgr_lock); - /* do not use this link group for new connections */ -- if (!list_empty(lgr_list)) -- list_del_init(lgr_list); -+ if (!list_empty(&lgr->list)) -+ list_del_init(&lgr->list); - spin_unlock_bh(lgr_lock); - __smc_lgr_terminate(lgr, true); - } -@@ -665,13 +664,14 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr) - int i; - - while (1) { -+again: - link_id = ++lgr->next_link_id; - if (!link_id) /* skip zero as link_id */ - link_id = ++lgr->next_link_id; - for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (smc_link_usable(&lgr->lnk[i]) && - lgr->lnk[i].link_id == link_id) -- continue; -+ goto again; - } - break; - } -@@ -1595,14 +1595,26 @@ static void smc_link_down_work(struct work_struct *work) - mutex_unlock(&lgr->llc_conf_mutex); - } - --/* Determine vlan of internal TCP socket. -- * @vlan_id: address to store the determined vlan id into -- */ -+static int smc_vlan_by_tcpsk_walk(struct net_device *lower_dev, -+ struct netdev_nested_priv *priv) -+{ -+ unsigned short *vlan_id = (unsigned short *)priv->data; -+ -+ if (is_vlan_dev(lower_dev)) { -+ *vlan_id = vlan_dev_vlan_id(lower_dev); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* Determine vlan of internal TCP socket. */ - int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini) - { - struct dst_entry *dst = sk_dst_get(clcsock->sk); -+ struct netdev_nested_priv priv; - struct net_device *ndev; -- int i, nest_lvl, rc = 0; -+ int rc = 0; - - ini->vlan_id = 0; - if (!dst) { -@@ -1620,20 +1632,9 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini) - goto out_rel; - } - -+ priv.data = (void *)&ini->vlan_id; - rtnl_lock(); -- nest_lvl = ndev->lower_level; -- for (i = 0; i < nest_lvl; i++) { -- struct list_head *lower = &ndev->adj_list.lower; -- -- if (list_empty(lower)) -- break; -- lower = lower->next; -- ndev = (struct net_device *)netdev_lower_get_next(ndev, &lower); -- if (is_vlan_dev(ndev)) { -- ini->vlan_id = vlan_dev_vlan_id(ndev); -- break; -- } -- } -+ netdev_walk_all_lower_dev(ndev, smc_vlan_by_tcpsk_walk, &priv); - rtnl_unlock(); - - out_rel: -diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c -index 9c0343568d2a0..1a72c67afed5e 100644 ---- a/net/strparser/strparser.c -+++ b/net/strparser/strparser.c -@@ -27,18 +27,10 @@ - - static struct workqueue_struct *strp_wq; - --struct _strp_msg { -- /* Internal cb structure. struct strp_msg must be first for passing -- * to upper layer. -- */ -- struct strp_msg strp; -- int accum_len; --}; -- - static inline struct _strp_msg *_strp_msg(struct sk_buff *skb) - { - return (struct _strp_msg *)((void *)skb->cb + -- offsetof(struct qdisc_skb_cb, data)); -+ offsetof(struct sk_skb_cb, strp)); - } - - /* Lower lock held */ -diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c -index 6e4dbd577a39f..d435bffc61999 100644 ---- a/net/sunrpc/addr.c -+++ b/net/sunrpc/addr.c -@@ -162,8 +162,10 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, - const size_t buflen, const char *delim, - struct sockaddr_in6 *sin6) - { -- char *p; -+ char p[IPV6_SCOPE_ID_LEN + 1]; - size_t len; -+ u32 scope_id = 0; -+ struct net_device *dev; - - if ((buf + buflen) == delim) - return 1; -@@ -175,29 +177,23 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, - return 0; - - len = (buf + buflen) - delim - 1; -- p = kmemdup_nul(delim + 1, len, GFP_KERNEL); -- if (p) { -- u32 scope_id = 0; -- struct net_device *dev; -- -- dev = dev_get_by_name(net, p); -- if (dev != NULL) { -- scope_id = dev->ifindex; -- dev_put(dev); -- } else { -- if (kstrtou32(p, 10, &scope_id) != 0) { -- kfree(p); -- return 0; -- } -- } -- -- kfree(p); -- -- sin6->sin6_scope_id = scope_id; -- return 1; -+ if (len > IPV6_SCOPE_ID_LEN) -+ return 0; -+ -+ memcpy(p, delim + 1, len); -+ p[len] = 0; -+ -+ dev = dev_get_by_name(net, p); -+ if (dev != NULL) { -+ scope_id = dev->ifindex; -+ dev_put(dev); -+ } else { -+ if (kstrtou32(p, 10, &scope_id) != 0) -+ return 0; - } - -- return 0; -+ sin6->sin6_scope_id = scope_id; -+ return 1; - } - - static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, -diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c -index cfd681700d1a1..d4aeee83763e6 100644 ---- a/net/sunrpc/xprt.c -+++ b/net/sunrpc/xprt.c -@@ -1603,15 +1603,14 @@ xprt_transmit(struct rpc_task *task) - { - struct rpc_rqst *next, *req = task->tk_rqstp; - struct rpc_xprt *xprt = req->rq_xprt; -- int counter, status; -+ int status; - - spin_lock(&xprt->queue_lock); -- counter = 0; -- while (!list_empty(&xprt->xmit_queue)) { -- if (++counter == 20) -+ for (;;) { -+ next = list_first_entry_or_null(&xprt->xmit_queue, -+ struct rpc_rqst, rq_xmit); -+ if (!next) - break; -- next = list_first_entry(&xprt->xmit_queue, -- struct rpc_rqst, rq_xmit); - xprt_pin_rqst(next); - spin_unlock(&xprt->queue_lock); - status = xprt_request_transmit(next, task); -@@ -1619,13 +1618,16 @@ xprt_transmit(struct rpc_task *task) - status = 0; - spin_lock(&xprt->queue_lock); - xprt_unpin_rqst(next); -- if (status == 0) { -- if (!xprt_request_data_received(task) || -- test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) -- continue; -- } else if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) -- task->tk_status = status; -- break; -+ if (status < 0) { -+ if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) -+ task->tk_status = status; -+ break; -+ } -+ /* Was @task transmitted, and has it received a reply? */ -+ if (xprt_request_data_received(task) && -+ !test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) -+ break; -+ cond_resched_lock(&xprt->queue_lock); - } - spin_unlock(&xprt->queue_lock); - } -diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c -index dc60c32bb70df..d293614d5fc65 100644 ---- a/net/tipc/crypto.c -+++ b/net/tipc/crypto.c -@@ -597,6 +597,10 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey, - tmp->cloned = NULL; - tmp->authsize = TIPC_AES_GCM_TAG_SIZE; - tmp->key = kmemdup(ukey, tipc_aead_key_size(ukey), GFP_KERNEL); -+ if (!tmp->key) { -+ tipc_aead_free(&tmp->rcu); -+ return -ENOMEM; -+ } - memcpy(&tmp->salt, ukey->key + keylen, TIPC_AES_GCM_SALT_SIZE); - atomic_set(&tmp->users, 0); - atomic64_set(&tmp->seqno, 0); -diff --git a/net/tipc/link.c b/net/tipc/link.c -index 1b7a487c88419..09ae8448f394f 100644 ---- a/net/tipc/link.c -+++ b/net/tipc/link.c -@@ -1298,8 +1298,11 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb, - return false; - #ifdef CONFIG_TIPC_CRYPTO - case MSG_CRYPTO: -- tipc_crypto_msg_rcv(l->net, skb); -- return true; -+ if (TIPC_SKB_CB(skb)->decrypted) { -+ tipc_crypto_msg_rcv(l->net, skb); -+ return true; -+ } -+ fallthrough; - #endif - default: - pr_warn("Dropping received illegal msg type\n"); -diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c -index 9ab81db8a6545..9aac9c60d786d 100644 ---- a/net/tls/tls_main.c -+++ b/net/tls/tls_main.c -@@ -61,7 +61,7 @@ static DEFINE_MUTEX(tcpv6_prot_mutex); - static const struct proto *saved_tcpv4_prot; - static DEFINE_MUTEX(tcpv4_prot_mutex); - static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG]; --static struct proto_ops tls_sw_proto_ops; -+static struct proto_ops tls_proto_ops[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG]; - static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], - const struct proto *base); - -@@ -71,6 +71,8 @@ void update_sk_prot(struct sock *sk, struct tls_context *ctx) - - WRITE_ONCE(sk->sk_prot, - &tls_prots[ip_ver][ctx->tx_conf][ctx->rx_conf]); -+ WRITE_ONCE(sk->sk_socket->ops, -+ &tls_proto_ops[ip_ver][ctx->tx_conf][ctx->rx_conf]); - } - - int wait_on_pending_writer(struct sock *sk, long *timeo) -@@ -581,8 +583,6 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, - if (tx) { - ctx->sk_write_space = sk->sk_write_space; - sk->sk_write_space = tls_write_space; -- } else { -- sk->sk_socket->ops = &tls_sw_proto_ops; - } - goto out; - -@@ -640,6 +640,39 @@ struct tls_context *tls_ctx_create(struct sock *sk) - return ctx; - } - -+static void build_proto_ops(struct proto_ops ops[TLS_NUM_CONFIG][TLS_NUM_CONFIG], -+ const struct proto_ops *base) -+{ -+ ops[TLS_BASE][TLS_BASE] = *base; -+ -+ ops[TLS_SW ][TLS_BASE] = ops[TLS_BASE][TLS_BASE]; -+ ops[TLS_SW ][TLS_BASE].sendpage_locked = tls_sw_sendpage_locked; -+ -+ ops[TLS_BASE][TLS_SW ] = ops[TLS_BASE][TLS_BASE]; -+ ops[TLS_BASE][TLS_SW ].splice_read = tls_sw_splice_read; -+ -+ ops[TLS_SW ][TLS_SW ] = ops[TLS_SW ][TLS_BASE]; -+ ops[TLS_SW ][TLS_SW ].splice_read = tls_sw_splice_read; -+ -+#ifdef CONFIG_TLS_DEVICE -+ ops[TLS_HW ][TLS_BASE] = ops[TLS_BASE][TLS_BASE]; -+ ops[TLS_HW ][TLS_BASE].sendpage_locked = NULL; -+ -+ ops[TLS_HW ][TLS_SW ] = ops[TLS_BASE][TLS_SW ]; -+ ops[TLS_HW ][TLS_SW ].sendpage_locked = NULL; -+ -+ ops[TLS_BASE][TLS_HW ] = ops[TLS_BASE][TLS_SW ]; -+ -+ ops[TLS_SW ][TLS_HW ] = ops[TLS_SW ][TLS_SW ]; -+ -+ ops[TLS_HW ][TLS_HW ] = ops[TLS_HW ][TLS_SW ]; -+ ops[TLS_HW ][TLS_HW ].sendpage_locked = NULL; -+#endif -+#ifdef CONFIG_TLS_TOE -+ ops[TLS_HW_RECORD][TLS_HW_RECORD] = *base; -+#endif -+} -+ - static void tls_build_proto(struct sock *sk) - { - int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; -@@ -651,6 +684,8 @@ static void tls_build_proto(struct sock *sk) - mutex_lock(&tcpv6_prot_mutex); - if (likely(prot != saved_tcpv6_prot)) { - build_protos(tls_prots[TLSV6], prot); -+ build_proto_ops(tls_proto_ops[TLSV6], -+ sk->sk_socket->ops); - smp_store_release(&saved_tcpv6_prot, prot); - } - mutex_unlock(&tcpv6_prot_mutex); -@@ -661,6 +696,8 @@ static void tls_build_proto(struct sock *sk) - mutex_lock(&tcpv4_prot_mutex); - if (likely(prot != saved_tcpv4_prot)) { - build_protos(tls_prots[TLSV4], prot); -+ build_proto_ops(tls_proto_ops[TLSV4], -+ sk->sk_socket->ops); - smp_store_release(&saved_tcpv4_prot, prot); - } - mutex_unlock(&tcpv4_prot_mutex); -@@ -871,10 +908,6 @@ static int __init tls_register(void) - if (err) - return err; - -- tls_sw_proto_ops = inet_stream_ops; -- tls_sw_proto_ops.splice_read = tls_sw_splice_read; -- tls_sw_proto_ops.sendpage_locked = tls_sw_sendpage_locked; -- - tls_device_init(); - tcp_register_ulp(&tcp_tls_ulp_ops); - -diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c -index 1b08b877a8900..bd96ec26f4f99 100644 ---- a/net/tls/tls_sw.c -+++ b/net/tls/tls_sw.c -@@ -515,7 +515,7 @@ static int tls_do_encryption(struct sock *sk, - memcpy(&rec->iv_data[iv_offset], tls_ctx->tx.iv, - prot->iv_size + prot->salt_size); - -- xor_iv_with_seq(prot, rec->iv_data, tls_ctx->tx.rec_seq); -+ xor_iv_with_seq(prot, rec->iv_data + iv_offset, tls_ctx->tx.rec_seq); - - sge->offset += prot->prepend_size; - sge->length -= prot->prepend_size; -@@ -1487,7 +1487,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb, - else - memcpy(iv + iv_offset, tls_ctx->rx.iv, prot->salt_size); - -- xor_iv_with_seq(prot, iv, tls_ctx->rx.rec_seq); -+ xor_iv_with_seq(prot, iv + iv_offset, tls_ctx->rx.rec_seq); - - /* Prepare AAD */ - tls_make_aad(aad, rxm->full_len - prot->overhead_size + -@@ -1993,6 +1993,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, - struct sock *sk = sock->sk; - struct sk_buff *skb; - ssize_t copied = 0; -+ bool from_queue; - int err = 0; - long timeo; - int chunk; -@@ -2002,25 +2003,28 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, - - timeo = sock_rcvtimeo(sk, flags & SPLICE_F_NONBLOCK); - -- skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo, &err); -- if (!skb) -- goto splice_read_end; -- -- if (!ctx->decrypted) { -- err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc, false); -- -- /* splice does not support reading control messages */ -- if (ctx->control != TLS_RECORD_TYPE_DATA) { -- err = -EINVAL; -+ from_queue = !skb_queue_empty(&ctx->rx_list); -+ if (from_queue) { -+ skb = __skb_dequeue(&ctx->rx_list); -+ } else { -+ skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo, -+ &err); -+ if (!skb) - goto splice_read_end; -- } - -+ err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc, false); - if (err < 0) { - tls_err_abort(sk, -EBADMSG); - goto splice_read_end; - } -- ctx->decrypted = 1; - } -+ -+ /* splice does not support reading control messages */ -+ if (ctx->control != TLS_RECORD_TYPE_DATA) { -+ err = -EINVAL; -+ goto splice_read_end; -+ } -+ - rxm = strp_msg(skb); - - chunk = min_t(unsigned int, rxm->full_len, len); -@@ -2028,7 +2032,17 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, - if (copied < 0) - goto splice_read_end; - -- tls_sw_advance_skb(sk, skb, copied); -+ if (!from_queue) { -+ ctx->recv_pkt = NULL; -+ __strp_unpause(&ctx->strp); -+ } -+ if (chunk < rxm->full_len) { -+ __skb_queue_head(&ctx->rx_list, skb); -+ rxm->offset += len; -+ rxm->full_len -= len; -+ } else { -+ consume_skb(skb); -+ } - - splice_read_end: - release_sock(sk); -diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c -index 78e08e82c08c4..b0bfc78e421ce 100644 ---- a/net/unix/af_unix.c -+++ b/net/unix/af_unix.c -@@ -2882,9 +2882,6 @@ static int unix_shutdown(struct socket *sock, int mode) - - unix_state_lock(sk); - sk->sk_shutdown |= mode; -- if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && -- mode == SHUTDOWN_MASK) -- sk->sk_state = TCP_CLOSE; - other = unix_peer(sk); - if (other) - sock_hold(other); -diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c -index e2c0cfb334d20..fa8c1b623fa21 100644 ---- a/net/vmw_vsock/af_vsock.c -+++ b/net/vmw_vsock/af_vsock.c -@@ -1322,6 +1322,8 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr, - * non-blocking call. - */ - err = -EALREADY; -+ if (flags & O_NONBLOCK) -+ goto out; - break; - default: - if ((sk->sk_state == TCP_LISTEN) || -diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c -index 59ee1be5a6dd3..ec2c2afbf0d06 100644 ---- a/net/vmw_vsock/virtio_transport_common.c -+++ b/net/vmw_vsock/virtio_transport_common.c -@@ -1299,7 +1299,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, - space_available = virtio_transport_space_update(sk, pkt); - - /* Update CID in case it has changed after a transport reset event */ -- vsk->local_addr.svm_cid = dst.svm_cid; -+ if (vsk->local_addr.svm_cid != VMADDR_CID_ANY) -+ vsk->local_addr.svm_cid = dst.svm_cid; - - if (space_available) - sk->sk_write_space(sk); -diff --git a/net/wireless/core.c b/net/wireless/core.c -index aaba847d79eb2..eb297e1015e05 100644 ---- a/net/wireless/core.c -+++ b/net/wireless/core.c -@@ -1081,6 +1081,16 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) - list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) - cfg80211_put_bss(&rdev->wiphy, &scan->pub); - mutex_destroy(&rdev->wiphy.mtx); -+ -+ /* -+ * The 'regd' can only be non-NULL if we never finished -+ * initializing the wiphy and thus never went through the -+ * unregister path - e.g. in failure scenarios. Thus, it -+ * cannot have been visible to anyone if non-NULL, so we -+ * can just free it here. -+ */ -+ kfree(rcu_dereference_raw(rdev->wiphy.regd)); -+ - kfree(rdev); - } - -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index bf7cd47525472..16b3d0cc0bdb0 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -922,33 +922,37 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { - [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, - }; - --int nl80211_prepare_wdev_dump(struct netlink_callback *cb, -- struct cfg80211_registered_device **rdev, -- struct wireless_dev **wdev) -+static int nl80211_prepare_wdev_dump(struct netlink_callback *cb, -+ struct cfg80211_registered_device **rdev, -+ struct wireless_dev **wdev, -+ struct nlattr **attrbuf) - { - int err; - - if (!cb->args[0]) { -- struct nlattr **attrbuf; -+ struct nlattr **attrbuf_free = NULL; - -- attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), -- GFP_KERNEL); -- if (!attrbuf) -- return -ENOMEM; -+ if (!attrbuf) { -+ attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), -+ GFP_KERNEL); -+ if (!attrbuf) -+ return -ENOMEM; -+ attrbuf_free = attrbuf; -+ } - - err = nlmsg_parse_deprecated(cb->nlh, - GENL_HDRLEN + nl80211_fam.hdrsize, - attrbuf, nl80211_fam.maxattr, - nl80211_policy, NULL); - if (err) { -- kfree(attrbuf); -+ kfree(attrbuf_free); - return err; - } - - rtnl_lock(); - *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk), - attrbuf); -- kfree(attrbuf); -+ kfree(attrbuf_free); - if (IS_ERR(*wdev)) { - rtnl_unlock(); - return PTR_ERR(*wdev); -@@ -6001,7 +6005,7 @@ static int nl80211_dump_station(struct sk_buff *skb, - int sta_idx = cb->args[2]; - int err; - -- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); -+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); - if (err) - return err; - /* nl80211_prepare_wdev_dump acquired it in the successful case */ -@@ -6896,7 +6900,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, - int path_idx = cb->args[2]; - int err; - -- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); -+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); - if (err) - return err; - /* nl80211_prepare_wdev_dump acquired it in the successful case */ -@@ -7096,7 +7100,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, - int path_idx = cb->args[2]; - int err; - -- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); -+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); - if (err) - return err; - /* nl80211_prepare_wdev_dump acquired it in the successful case */ -@@ -9518,7 +9522,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) - int start = cb->args[2], idx = 0; - int err; - -- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); -+ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); - if (err) - return err; - /* nl80211_prepare_wdev_dump acquired it in the successful case */ -@@ -9651,7 +9655,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) - if (!attrbuf) - return -ENOMEM; - -- res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); -+ res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf); - if (res) { - kfree(attrbuf); - return res; -diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h -index a3f387770f1bf..d642e3be4ee78 100644 ---- a/net/wireless/nl80211.h -+++ b/net/wireless/nl80211.h -@@ -1,7 +1,7 @@ - /* SPDX-License-Identifier: GPL-2.0 */ - /* - * Portions of this file -- * Copyright (C) 2018, 2020 Intel Corporation -+ * Copyright (C) 2018, 2020-2021 Intel Corporation - */ - #ifndef __NET_WIRELESS_NL80211_H - #define __NET_WIRELESS_NL80211_H -@@ -22,10 +22,6 @@ static inline u64 wdev_id(struct wireless_dev *wdev) - ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32); - } - --int nl80211_prepare_wdev_dump(struct netlink_callback *cb, -- struct cfg80211_registered_device **rdev, -- struct wireless_dev **wdev); -- - int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, - struct genl_info *info, - struct cfg80211_chan_def *chandef); -diff --git a/net/wireless/reg.c b/net/wireless/reg.c -index df87c7f3a0492..795e86b371bba 100644 ---- a/net/wireless/reg.c -+++ b/net/wireless/reg.c -@@ -2338,6 +2338,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) - struct cfg80211_chan_def chandef = {}; - struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); - enum nl80211_iftype iftype; -+ bool ret; - - wdev_lock(wdev); - iftype = wdev->iftype; -@@ -2387,7 +2388,11 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_ADHOC: -- return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype); -+ wiphy_lock(wiphy); -+ ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype); -+ wiphy_unlock(wiphy); -+ -+ return ret; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - return cfg80211_chandef_usable(wiphy, &chandef, -diff --git a/net/wireless/util.c b/net/wireless/util.c -index a1a99a5749844..4ddc269164f86 100644 ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -1044,6 +1044,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, - - switch (otype) { - case NL80211_IFTYPE_AP: -+ case NL80211_IFTYPE_P2P_GO: - cfg80211_stop_ap(rdev, dev, true); - break; - case NL80211_IFTYPE_ADHOC: -diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c -index 6e25fba64c72b..a81704d3317ba 100644 ---- a/samples/bpf/xdp_redirect_cpu_user.c -+++ b/samples/bpf/xdp_redirect_cpu_user.c -@@ -309,7 +309,6 @@ int main(int argc, char **argv) - const char *mprog_filename = NULL, *mprog_name = NULL; - struct xdp_redirect_cpu *skel; - struct bpf_map_info info = {}; -- char ifname_buf[IF_NAMESIZE]; - struct bpf_cpumap_val value; - __u32 infosz = sizeof(info); - int ret = EXIT_FAIL_OPTION; -@@ -325,7 +324,6 @@ int main(int argc, char **argv) - int add_cpu = -1; - int ifindex = -1; - int *cpu, i, opt; -- char *ifname; - __u32 qsize; - int n_cpus; - -@@ -391,11 +389,10 @@ int main(int argc, char **argv) - case 'd': - if (strlen(optarg) >= IF_NAMESIZE) { - fprintf(stderr, "-d/--dev name too long\n"); -+ usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } -- ifname = (char *)&ifname_buf; -- safe_strncpy(ifname, optarg, sizeof(ifname)); -- ifindex = if_nametoindex(ifname); -+ ifindex = if_nametoindex(optarg); - if (!ifindex) - ifindex = strtoul(optarg, NULL, 0); - if (!ifindex) { -diff --git a/samples/bpf/xdp_sample_user.c b/samples/bpf/xdp_sample_user.c -index b32d821781990..8740838e77679 100644 ---- a/samples/bpf/xdp_sample_user.c -+++ b/samples/bpf/xdp_sample_user.c -@@ -120,7 +120,10 @@ struct sample_output { - __u64 xmit; - } totals; - struct { -- __u64 pps; -+ union { -+ __u64 pps; -+ __u64 num; -+ }; - __u64 drop; - __u64 err; - } rx_cnt; -@@ -1322,7 +1325,7 @@ int sample_install_xdp(struct bpf_program *xdp_prog, int ifindex, bool generic, - - static void sample_summary_print(void) - { -- double period = sample_out.rx_cnt.pps; -+ double num = sample_out.rx_cnt.num; - - if (sample_out.totals.rx) { - double pkts = sample_out.totals.rx; -@@ -1330,7 +1333,7 @@ static void sample_summary_print(void) - print_always(" Packets received : %'-10llu\n", - sample_out.totals.rx); - print_always(" Average packets/s : %'-10.0f\n", -- sample_round(pkts / period)); -+ sample_round(pkts / num)); - } - if (sample_out.totals.redir) { - double pkts = sample_out.totals.redir; -@@ -1338,7 +1341,7 @@ static void sample_summary_print(void) - print_always(" Packets redirected : %'-10llu\n", - sample_out.totals.redir); - print_always(" Average redir/s : %'-10.0f\n", -- sample_round(pkts / period)); -+ sample_round(pkts / num)); - } - if (sample_out.totals.drop) - print_always(" Rx dropped : %'-10llu\n", -@@ -1355,7 +1358,7 @@ static void sample_summary_print(void) - print_always(" Packets transmitted : %'-10llu\n", - sample_out.totals.xmit); - print_always(" Average transmit/s : %'-10.0f\n", -- sample_round(pkts / period)); -+ sample_round(pkts / num)); - } - } - -@@ -1422,7 +1425,7 @@ static int sample_stats_collect(struct stats_record *rec) - return 0; - } - --static void sample_summary_update(struct sample_output *out, int interval) -+static void sample_summary_update(struct sample_output *out) - { - sample_out.totals.rx += out->totals.rx; - sample_out.totals.redir += out->totals.redir; -@@ -1430,12 +1433,11 @@ static void sample_summary_update(struct sample_output *out, int interval) - sample_out.totals.drop_xmit += out->totals.drop_xmit; - sample_out.totals.err += out->totals.err; - sample_out.totals.xmit += out->totals.xmit; -- sample_out.rx_cnt.pps += interval; -+ sample_out.rx_cnt.num++; - } - - static void sample_stats_print(int mask, struct stats_record *cur, -- struct stats_record *prev, char *prog_name, -- int interval) -+ struct stats_record *prev, char *prog_name) - { - struct sample_output out = {}; - -@@ -1452,7 +1454,7 @@ static void sample_stats_print(int mask, struct stats_record *cur, - else if (mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI) - stats_get_devmap_xmit_multi(cur, prev, 0, &out, - mask & SAMPLE_DEVMAP_XMIT_CNT); -- sample_summary_update(&out, interval); -+ sample_summary_update(&out); - - stats_print(prog_name, mask, cur, prev, &out); - } -@@ -1495,7 +1497,7 @@ static void swap(struct stats_record **a, struct stats_record **b) - } - - static int sample_timer_cb(int timerfd, struct stats_record **rec, -- struct stats_record **prev, int interval) -+ struct stats_record **prev) - { - char line[64] = "Summary"; - int ret; -@@ -1524,7 +1526,7 @@ static int sample_timer_cb(int timerfd, struct stats_record **rec, - snprintf(line, sizeof(line), "%s->%s", f ?: "?", t ?: "?"); - } - -- sample_stats_print(sample_mask, *rec, *prev, line, interval); -+ sample_stats_print(sample_mask, *rec, *prev, line); - return 0; - } - -@@ -1579,7 +1581,7 @@ int sample_run(int interval, void (*post_cb)(void *), void *ctx) - if (pfd[0].revents & POLLIN) - ret = sample_signal_cb(); - else if (pfd[1].revents & POLLIN) -- ret = sample_timer_cb(timerfd, &rec, &prev, interval); -+ ret = sample_timer_cb(timerfd, &rec, &prev); - - if (ret) - break; -diff --git a/samples/kprobes/kretprobe_example.c b/samples/kprobes/kretprobe_example.c -index 5dc1bf3baa98b..228321ecb1616 100644 ---- a/samples/kprobes/kretprobe_example.c -+++ b/samples/kprobes/kretprobe_example.c -@@ -86,7 +86,7 @@ static int __init kretprobe_init(void) - ret = register_kretprobe(&my_kretprobe); - if (ret < 0) { - pr_err("register_kretprobe failed, returned %d\n", ret); -- return -1; -+ return ret; - } - pr_info("Planted return probe at %s: %p\n", - my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr); -diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl -index b2d8b8aa2d99e..8f636a23bc3f2 100755 ---- a/scripts/leaking_addresses.pl -+++ b/scripts/leaking_addresses.pl -@@ -455,8 +455,9 @@ sub parse_file - - open my $fh, "<", $file or return; - while ( <$fh> ) { -+ chomp; - if (may_leak_address($_)) { -- print $file . ': ' . $_; -+ printf("$file: $_\n"); - } - } - close $fh; -diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl -index 7d631aaa0ae11..52a000b057a57 100755 ---- a/scripts/recordmcount.pl -+++ b/scripts/recordmcount.pl -@@ -219,7 +219,7 @@ if ($arch eq "x86_64") { - - } elsif ($arch eq "s390" && $bits == 64) { - if ($cc =~ /-DCC_USING_HOTPATCH/) { -- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$"; -+ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*(bcrl\\s*0,|jgnop\\s*)[0-9a-f]+ <([^\+]*)>\$"; - $mcount_adjust = 0; - } - $alignment = 8; -diff --git a/security/Kconfig b/security/Kconfig -index 0ced7fd33e4d0..fe6c0395fa025 100644 ---- a/security/Kconfig -+++ b/security/Kconfig -@@ -191,6 +191,9 @@ config HARDENED_USERCOPY_PAGESPAN - config FORTIFY_SOURCE - bool "Harden common str/mem functions against buffer overflows" - depends on ARCH_HAS_FORTIFY_SOURCE -+ # https://bugs.llvm.org/show_bug.cgi?id=50322 -+ # https://bugs.llvm.org/show_bug.cgi?id=41459 -+ depends on !CC_IS_CLANG - help - Detect overflows of buffers in common string and memory functions - where the compiler can determine and validate the buffer sizes. -diff --git a/security/apparmor/label.c b/security/apparmor/label.c -index e68bcedca976b..6222fdfebe4e5 100644 ---- a/security/apparmor/label.c -+++ b/security/apparmor/label.c -@@ -1454,7 +1454,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp) - if (label->hname || labels_ns(label) != ns) - return res; - -- if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) == -1) -+ if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) < 0) - return res; - - ls = labels_set(label); -@@ -1704,7 +1704,7 @@ int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, - - /** - * aa_label_acntsxprint - allocate a __counted string buffer and print label -- * @strp: buffer to write to. (MAY BE NULL if @size == 0) -+ * @strp: buffer to write to. - * @ns: namespace profile is being viewed from - * @label: label to view (NOT NULL) - * @flags: flags controlling what label info is printed -diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c -index 1c8435dfabeea..08f907382c618 100644 ---- a/security/integrity/evm/evm_main.c -+++ b/security/integrity/evm/evm_main.c -@@ -78,7 +78,7 @@ static struct xattr_list evm_config_default_xattrnames[] = { - - LIST_HEAD(evm_config_xattrnames); - --static int evm_fixmode; -+static int evm_fixmode __ro_after_init; - static int __init evm_set_fixmode(char *str) - { - if (strncmp(str, "fix", 3) == 0) -diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c -index 87b9b71cb8201..12e8adcd80a2a 100644 ---- a/security/integrity/ima/ima_policy.c -+++ b/security/integrity/ima/ima_policy.c -@@ -228,7 +228,7 @@ static struct ima_rule_entry *arch_policy_entry __ro_after_init; - static LIST_HEAD(ima_default_rules); - static LIST_HEAD(ima_policy_rules); - static LIST_HEAD(ima_temp_rules); --static struct list_head *ima_rules = &ima_default_rules; -+static struct list_head __rcu *ima_rules = (struct list_head __rcu *)(&ima_default_rules); - - static int ima_policy __initdata; - -@@ -675,12 +675,14 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, - { - struct ima_rule_entry *entry; - int action = 0, actmask = flags | (flags << 1); -+ struct list_head *ima_rules_tmp; - - if (template_desc && !*template_desc) - *template_desc = ima_template_desc_current(); - - rcu_read_lock(); -- list_for_each_entry_rcu(entry, ima_rules, list) { -+ ima_rules_tmp = rcu_dereference(ima_rules); -+ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { - - if (!(entry->action & actmask)) - continue; -@@ -741,9 +743,11 @@ void ima_update_policy_flags(void) - { - struct ima_rule_entry *entry; - int new_policy_flag = 0; -+ struct list_head *ima_rules_tmp; - - rcu_read_lock(); -- list_for_each_entry(entry, ima_rules, list) { -+ ima_rules_tmp = rcu_dereference(ima_rules); -+ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { - /* - * SETXATTR_CHECK rules do not implement a full policy check - * because rule checking would probably have an important -@@ -968,10 +972,10 @@ void ima_update_policy(void) - - list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu); - -- if (ima_rules != policy) { -+ if (ima_rules != (struct list_head __rcu *)policy) { - ima_policy_flag = 0; -- ima_rules = policy; - -+ rcu_assign_pointer(ima_rules, policy); - /* - * IMA architecture specific policy rules are specified - * as strings and converted to an array of ima_entry_rules -@@ -1061,7 +1065,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, - pr_warn("rule for LSM \'%s\' is undefined\n", - entry->lsm[lsm_rule].args_p); - -- if (ima_rules == &ima_default_rules) { -+ if (ima_rules == (struct list_head __rcu *)(&ima_default_rules)) { - kfree(entry->lsm[lsm_rule].args_p); - entry->lsm[lsm_rule].args_p = NULL; - result = -EINVAL; -@@ -1768,9 +1772,11 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) - { - loff_t l = *pos; - struct ima_rule_entry *entry; -+ struct list_head *ima_rules_tmp; - - rcu_read_lock(); -- list_for_each_entry_rcu(entry, ima_rules, list) { -+ ima_rules_tmp = rcu_dereference(ima_rules); -+ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { - if (!l--) { - rcu_read_unlock(); - return entry; -@@ -1789,7 +1795,8 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) - rcu_read_unlock(); - (*pos)++; - -- return (&entry->list == ima_rules) ? NULL : entry; -+ return (&entry->list == &ima_default_rules || -+ &entry->list == &ima_policy_rules) ? NULL : entry; - } - - void ima_policy_stop(struct seq_file *m, void *v) -@@ -2014,6 +2021,7 @@ bool ima_appraise_signature(enum kernel_read_file_id id) - struct ima_rule_entry *entry; - bool found = false; - enum ima_hooks func; -+ struct list_head *ima_rules_tmp; - - if (id >= READING_MAX_ID) - return false; -@@ -2021,7 +2029,8 @@ bool ima_appraise_signature(enum kernel_read_file_id id) - func = read_idmap[id] ?: FILE_CHECK; - - rcu_read_lock(); -- list_for_each_entry_rcu(entry, ima_rules, list) { -+ ima_rules_tmp = rcu_dereference(ima_rules); -+ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { - if (entry->action != APPRAISE) - continue; - -diff --git a/security/security.c b/security/security.c -index 9ffa9e9c5c554..67264cb08fb31 100644 ---- a/security/security.c -+++ b/security/security.c -@@ -747,25 +747,25 @@ static int lsm_superblock_alloc(struct super_block *sb) - - /* Security operations */ - --int security_binder_set_context_mgr(struct task_struct *mgr) -+int security_binder_set_context_mgr(const struct cred *mgr) - { - return call_int_hook(binder_set_context_mgr, 0, mgr); - } - --int security_binder_transaction(struct task_struct *from, -- struct task_struct *to) -+int security_binder_transaction(const struct cred *from, -+ const struct cred *to) - { - return call_int_hook(binder_transaction, 0, from, to); - } - --int security_binder_transfer_binder(struct task_struct *from, -- struct task_struct *to) -+int security_binder_transfer_binder(const struct cred *from, -+ const struct cred *to) - { - return call_int_hook(binder_transfer_binder, 0, from, to); - } - --int security_binder_transfer_file(struct task_struct *from, -- struct task_struct *to, struct file *file) -+int security_binder_transfer_file(const struct cred *from, -+ const struct cred *to, struct file *file) - { - return call_int_hook(binder_transfer_file, 0, from, to, file); - } -diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c -index e7ebd45ca3457..51432ea74044e 100644 ---- a/security/selinux/hooks.c -+++ b/security/selinux/hooks.c -@@ -255,29 +255,6 @@ static inline u32 task_sid_obj(const struct task_struct *task) - return sid; - } - --/* -- * get the security ID of a task for use with binder -- */ --static inline u32 task_sid_binder(const struct task_struct *task) --{ -- /* -- * In many case where this function is used we should be using the -- * task's subjective SID, but we can't reliably access the subjective -- * creds of a task other than our own so we must use the objective -- * creds/SID, which are safe to access. The downside is that if a task -- * is temporarily overriding it's creds it will not be reflected here; -- * however, it isn't clear that binder would handle that case well -- * anyway. -- * -- * If this ever changes and we can safely reference the subjective -- * creds/SID of another task, this function will make it easier to -- * identify the various places where we make use of the task SIDs in -- * the binder code. It is also likely that we will need to adjust -- * the main drivers/android binder code as well. -- */ -- return task_sid_obj(task); --} -- - static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); - - /* -@@ -634,10 +611,11 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, - return 0; - } - --static int parse_sid(struct super_block *sb, const char *s, u32 *sid) -+static int parse_sid(struct super_block *sb, const char *s, u32 *sid, -+ gfp_t gfp) - { - int rc = security_context_str_to_sid(&selinux_state, s, -- sid, GFP_KERNEL); -+ sid, gfp); - if (rc) - pr_warn("SELinux: security_context_str_to_sid" - "(%s) failed for (dev %s, type %s) errno=%d\n", -@@ -708,7 +686,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, - */ - if (opts) { - if (opts->fscontext) { -- rc = parse_sid(sb, opts->fscontext, &fscontext_sid); -+ rc = parse_sid(sb, opts->fscontext, &fscontext_sid, -+ GFP_KERNEL); - if (rc) - goto out; - if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, -@@ -717,7 +696,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, - sbsec->flags |= FSCONTEXT_MNT; - } - if (opts->context) { -- rc = parse_sid(sb, opts->context, &context_sid); -+ rc = parse_sid(sb, opts->context, &context_sid, -+ GFP_KERNEL); - if (rc) - goto out; - if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, -@@ -726,7 +706,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, - sbsec->flags |= CONTEXT_MNT; - } - if (opts->rootcontext) { -- rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid); -+ rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid, -+ GFP_KERNEL); - if (rc) - goto out; - if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, -@@ -735,7 +716,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, - sbsec->flags |= ROOTCONTEXT_MNT; - } - if (opts->defcontext) { -- rc = parse_sid(sb, opts->defcontext, &defcontext_sid); -+ rc = parse_sid(sb, opts->defcontext, &defcontext_sid, -+ GFP_KERNEL); - if (rc) - goto out; - if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, -@@ -2066,18 +2048,19 @@ static inline u32 open_file_to_av(struct file *file) - - /* Hook functions begin here. */ - --static int selinux_binder_set_context_mgr(struct task_struct *mgr) -+static int selinux_binder_set_context_mgr(const struct cred *mgr) - { - return avc_has_perm(&selinux_state, -- current_sid(), task_sid_binder(mgr), SECCLASS_BINDER, -+ current_sid(), cred_sid(mgr), SECCLASS_BINDER, - BINDER__SET_CONTEXT_MGR, NULL); - } - --static int selinux_binder_transaction(struct task_struct *from, -- struct task_struct *to) -+static int selinux_binder_transaction(const struct cred *from, -+ const struct cred *to) - { - u32 mysid = current_sid(); -- u32 fromsid = task_sid_binder(from); -+ u32 fromsid = cred_sid(from); -+ u32 tosid = cred_sid(to); - int rc; - - if (mysid != fromsid) { -@@ -2088,24 +2071,24 @@ static int selinux_binder_transaction(struct task_struct *from, - return rc; - } - -- return avc_has_perm(&selinux_state, fromsid, task_sid_binder(to), -+ return avc_has_perm(&selinux_state, fromsid, tosid, - SECCLASS_BINDER, BINDER__CALL, NULL); - } - --static int selinux_binder_transfer_binder(struct task_struct *from, -- struct task_struct *to) -+static int selinux_binder_transfer_binder(const struct cred *from, -+ const struct cred *to) - { - return avc_has_perm(&selinux_state, -- task_sid_binder(from), task_sid_binder(to), -+ cred_sid(from), cred_sid(to), - SECCLASS_BINDER, BINDER__TRANSFER, - NULL); - } - --static int selinux_binder_transfer_file(struct task_struct *from, -- struct task_struct *to, -+static int selinux_binder_transfer_file(const struct cred *from, -+ const struct cred *to, - struct file *file) - { -- u32 sid = task_sid_binder(to); -+ u32 sid = cred_sid(to); - struct file_security_struct *fsec = selinux_file(file); - struct dentry *dentry = file->f_path.dentry; - struct inode_security_struct *isec; -@@ -2723,14 +2706,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) - return (sbsec->flags & SE_MNTMASK) ? 1 : 0; - - if (opts->fscontext) { -- rc = parse_sid(sb, opts->fscontext, &sid); -+ rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT); - if (rc) - return 1; - if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) - return 1; - } - if (opts->context) { -- rc = parse_sid(sb, opts->context, &sid); -+ rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT); - if (rc) - return 1; - if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) -@@ -2740,14 +2723,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) - struct inode_security_struct *root_isec; - - root_isec = backing_inode_security(sb->s_root); -- rc = parse_sid(sb, opts->rootcontext, &sid); -+ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT); - if (rc) - return 1; - if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) - return 1; - } - if (opts->defcontext) { -- rc = parse_sid(sb, opts->defcontext, &sid); -+ rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT); - if (rc) - return 1; - if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) -@@ -2770,14 +2753,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) - return 0; - - if (opts->fscontext) { -- rc = parse_sid(sb, opts->fscontext, &sid); -+ rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL); - if (rc) - return rc; - if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) - goto out_bad_option; - } - if (opts->context) { -- rc = parse_sid(sb, opts->context, &sid); -+ rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL); - if (rc) - return rc; - if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) -@@ -2786,14 +2769,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) - if (opts->rootcontext) { - struct inode_security_struct *root_isec; - root_isec = backing_inode_security(sb->s_root); -- rc = parse_sid(sb, opts->rootcontext, &sid); -+ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL); - if (rc) - return rc; - if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) - goto out_bad_option; - } - if (opts->defcontext) { -- rc = parse_sid(sb, opts->defcontext, &sid); -+ rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL); - if (rc) - return rc; - if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) -diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c -index b8f6b3e0a9219..a91fb0ed00de3 100644 ---- a/security/selinux/ss/hashtab.c -+++ b/security/selinux/ss/hashtab.c -@@ -30,13 +30,20 @@ static u32 hashtab_compute_size(u32 nel) - - int hashtab_init(struct hashtab *h, u32 nel_hint) - { -- h->size = hashtab_compute_size(nel_hint); -+ u32 size = hashtab_compute_size(nel_hint); -+ -+ /* should already be zeroed, but better be safe */ - h->nel = 0; -- if (!h->size) -- return 0; -+ h->size = 0; -+ h->htable = NULL; - -- h->htable = kcalloc(h->size, sizeof(*h->htable), GFP_KERNEL); -- return h->htable ? 0 : -ENOMEM; -+ if (size) { -+ h->htable = kcalloc(size, sizeof(*h->htable), GFP_KERNEL); -+ if (!h->htable) -+ return -ENOMEM; -+ h->size = size; -+ } -+ return 0; - } - - int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, -diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c -index e5f1b2757a83a..c4931bf6f92a4 100644 ---- a/security/selinux/ss/services.c -+++ b/security/selinux/ss/services.c -@@ -2376,6 +2376,43 @@ err_policy: - return rc; - } - -+/** -+ * ocontext_to_sid - Helper to safely get sid for an ocontext -+ * @sidtab: SID table -+ * @c: ocontext structure -+ * @index: index of the context entry (0 or 1) -+ * @out_sid: pointer to the resulting SID value -+ * -+ * For all ocontexts except OCON_ISID the SID fields are populated -+ * on-demand when needed. Since updating the SID value is an SMP-sensitive -+ * operation, this helper must be used to do that safely. -+ * -+ * WARNING: This function may return -ESTALE, indicating that the caller -+ * must retry the operation after re-acquiring the policy pointer! -+ */ -+static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c, -+ size_t index, u32 *out_sid) -+{ -+ int rc; -+ u32 sid; -+ -+ /* Ensure the associated sidtab entry is visible to this thread. */ -+ sid = smp_load_acquire(&c->sid[index]); -+ if (!sid) { -+ rc = sidtab_context_to_sid(sidtab, &c->context[index], &sid); -+ if (rc) -+ return rc; -+ -+ /* -+ * Ensure the new sidtab entry is visible to other threads -+ * when they see the SID. -+ */ -+ smp_store_release(&c->sid[index], sid); -+ } -+ *out_sid = sid; -+ return 0; -+} -+ - /** - * security_port_sid - Obtain the SID for a port. - * @state: SELinux state -@@ -2414,17 +2451,13 @@ retry: - } - - if (c) { -- if (!c->sid[0]) { -- rc = sidtab_context_to_sid(sidtab, &c->context[0], -- &c->sid[0]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -+ rc = ocontext_to_sid(sidtab, c, 0, out_sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ goto retry; - } -- *out_sid = c->sid[0]; -+ if (rc) -+ goto out; - } else { - *out_sid = SECINITSID_PORT; - } -@@ -2473,18 +2506,13 @@ retry: - } - - if (c) { -- if (!c->sid[0]) { -- rc = sidtab_context_to_sid(sidtab, -- &c->context[0], -- &c->sid[0]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -+ rc = ocontext_to_sid(sidtab, c, 0, out_sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ goto retry; - } -- *out_sid = c->sid[0]; -+ if (rc) -+ goto out; - } else - *out_sid = SECINITSID_UNLABELED; - -@@ -2533,17 +2561,13 @@ retry: - } - - if (c) { -- if (!c->sid[0]) { -- rc = sidtab_context_to_sid(sidtab, &c->context[0], -- &c->sid[0]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -+ rc = ocontext_to_sid(sidtab, c, 0, out_sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ goto retry; - } -- *out_sid = c->sid[0]; -+ if (rc) -+ goto out; - } else - *out_sid = SECINITSID_UNLABELED; - -@@ -2587,25 +2611,13 @@ retry: - } - - if (c) { -- if (!c->sid[0] || !c->sid[1]) { -- rc = sidtab_context_to_sid(sidtab, &c->context[0], -- &c->sid[0]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -- rc = sidtab_context_to_sid(sidtab, &c->context[1], -- &c->sid[1]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -+ rc = ocontext_to_sid(sidtab, c, 0, if_sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ goto retry; - } -- *if_sid = c->sid[0]; -+ if (rc) -+ goto out; - } else - *if_sid = SECINITSID_NETIF; - -@@ -2697,18 +2709,13 @@ retry: - } - - if (c) { -- if (!c->sid[0]) { -- rc = sidtab_context_to_sid(sidtab, -- &c->context[0], -- &c->sid[0]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -+ rc = ocontext_to_sid(sidtab, c, 0, out_sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ goto retry; - } -- *out_sid = c->sid[0]; -+ if (rc) -+ goto out; - } else { - *out_sid = SECINITSID_NODE; - } -@@ -2873,7 +2880,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, - u16 sclass; - struct genfs *genfs; - struct ocontext *c; -- int rc, cmp = 0; -+ int cmp = 0; - - while (path[0] == '/' && path[1] == '/') - path++; -@@ -2887,9 +2894,8 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, - break; - } - -- rc = -ENOENT; - if (!genfs || cmp) -- goto out; -+ return -ENOENT; - - for (c = genfs->head; c; c = c->next) { - len = strlen(c->u.name); -@@ -2898,20 +2904,10 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, - break; - } - -- rc = -ENOENT; - if (!c) -- goto out; -- -- if (!c->sid[0]) { -- rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); -- if (rc) -- goto out; -- } -+ return -ENOENT; - -- *sid = c->sid[0]; -- rc = 0; --out: -- return rc; -+ return ocontext_to_sid(sidtab, c, 0, sid); - } - - /** -@@ -2996,17 +2992,13 @@ retry: - - if (c) { - sbsec->behavior = c->v.behavior; -- if (!c->sid[0]) { -- rc = sidtab_context_to_sid(sidtab, &c->context[0], -- &c->sid[0]); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- goto retry; -- } -- if (rc) -- goto out; -+ rc = ocontext_to_sid(sidtab, c, 0, &sbsec->sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ goto retry; - } -- sbsec->sid = c->sid[0]; -+ if (rc) -+ goto out; - } else { - rc = __security_genfs_sid(policy, fstype, "/", - SECCLASS_DIR, &sbsec->sid); -diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c -index 3a75d2a8f5178..658eab05599e6 100644 ---- a/security/smack/smackfs.c -+++ b/security/smack/smackfs.c -@@ -693,9 +693,7 @@ static void smk_cipso_doi(void) - printk(KERN_WARNING "%s:%d remove rc = %d\n", - __func__, __LINE__, rc); - -- doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL); -- if (doip == NULL) -- panic("smack: Failed to initialize cipso DOI.\n"); -+ doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL | __GFP_NOFAIL); - doip->map.std = NULL; - doip->doi = smk_cipso_doi_value; - doip->type = CIPSO_V4_MAP_PASS; -@@ -714,7 +712,7 @@ static void smk_cipso_doi(void) - if (rc != 0) { - printk(KERN_WARNING "%s:%d map add rc = %d\n", - __func__, __LINE__, rc); -- kfree(doip); -+ netlbl_cfg_cipsov4_del(doip->doi, &nai); - return; - } - } -@@ -831,6 +829,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file) - static ssize_t smk_set_cipso(struct file *file, const char __user *buf, - size_t count, loff_t *ppos, int format) - { -+ struct netlbl_lsm_catmap *old_cat; - struct smack_known *skp; - struct netlbl_lsm_secattr ncats; - char mapcatset[SMK_CIPSOLEN]; -@@ -920,9 +919,11 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, - - rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); - if (rc >= 0) { -- netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat); -+ old_cat = skp->smk_netlabel.attr.mls.cat; - 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); - rc = count; - /* - * This mapping may have been cached, so clear the cache. -diff --git a/sound/core/Makefile b/sound/core/Makefile -index d774792850f31..79e1407cd0de7 100644 ---- a/sound/core/Makefile -+++ b/sound/core/Makefile -@@ -9,7 +9,9 @@ ifneq ($(CONFIG_SND_PROC_FS),) - snd-y += info.o - snd-$(CONFIG_SND_OSSEMUL) += info_oss.o - endif -+ifneq ($(CONFIG_M68K),y) - snd-$(CONFIG_ISA_DMA_API) += isadma.o -+endif - snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o - snd-$(CONFIG_SND_VMASTER) += vmaster.o - snd-$(CONFIG_SND_JACK) += ctljack.o jack.o -diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c -index 470dabc60aa0e..edff063e088d2 100644 ---- a/sound/core/control_compat.c -+++ b/sound/core/control_compat.c -@@ -264,6 +264,7 @@ static int copy_ctl_value_to_user(void __user *userdata, - struct snd_ctl_elem_value *data, - int type, int count) - { -+ struct snd_ctl_elem_value32 __user *data32 = userdata; - int i, size; - - if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || -@@ -280,6 +281,8 @@ static int copy_ctl_value_to_user(void __user *userdata, - if (copy_to_user(valuep, data->value.bytes.data, size)) - return -EFAULT; - } -+ if (copy_to_user(&data32->id, &data->id, sizeof(data32->id))) -+ return -EFAULT; - return 0; - } - -diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c -index c7c943c661e63..2d842982576bb 100644 ---- a/sound/core/memalloc.c -+++ b/sound/core/memalloc.c -@@ -176,8 +176,11 @@ EXPORT_SYMBOL_GPL(snd_devm_alloc_pages); - int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab, - struct vm_area_struct *area) - { -- const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); -+ const struct snd_malloc_ops *ops; - -+ if (!dmab) -+ return -ENOENT; -+ ops = snd_dma_get_ops(dmab); - if (ops && ops->mmap) - return ops->mmap(dmab, area); - else -@@ -491,6 +494,8 @@ static const struct snd_malloc_ops *dma_ops[] = { - - static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab) - { -+ if (WARN_ON_ONCE(!dmab)) -+ return NULL; - if (WARN_ON_ONCE(dmab->dev.type <= SNDRV_DMA_TYPE_UNKNOWN || - dmab->dev.type >= ARRAY_SIZE(dma_ops))) - return NULL; -diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c -index 6a5abdd4271ba..9620115cfdc09 100644 ---- a/sound/core/oss/mixer_oss.c -+++ b/sound/core/oss/mixer_oss.c -@@ -130,11 +130,13 @@ static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer) - - if (mixer == NULL) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->put_volume || pslot->put_recsrc) - result |= 1 << chn; - } -+ mutex_unlock(&mixer->reg_mutex); - return result; - } - -@@ -146,11 +148,13 @@ static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer) - - if (mixer == NULL) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->put_volume && pslot->stereo) - result |= 1 << chn; - } -+ mutex_unlock(&mixer->reg_mutex); - return result; - } - -@@ -161,6 +165,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) - - if (mixer == NULL) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ - result = mixer->mask_recsrc; - } else { -@@ -172,6 +177,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) - result |= 1 << chn; - } - } -+ mutex_unlock(&mixer->reg_mutex); - return result; - } - -@@ -182,12 +188,12 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) - - if (mixer == NULL) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ -- int err; - unsigned int index; -- err = mixer->get_recsrc(fmixer, &index); -- if (err < 0) -- return err; -+ result = mixer->get_recsrc(fmixer, &index); -+ if (result < 0) -+ goto unlock; - result = 1 << index; - } else { - struct snd_mixer_oss_slot *pslot; -@@ -202,7 +208,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) - } - } - } -- return mixer->oss_recsrc = result; -+ mixer->oss_recsrc = result; -+ unlock: -+ mutex_unlock(&mixer->reg_mutex); -+ return result; - } - - static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc) -@@ -215,6 +224,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr - - if (mixer == NULL) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */ - if (recsrc & ~mixer->oss_recsrc) - recsrc &= ~mixer->oss_recsrc; -@@ -240,6 +250,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr - } - } - } -+ mutex_unlock(&mixer->reg_mutex); - return result; - } - -@@ -251,6 +262,7 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) - - if (mixer == NULL || slot > 30) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - pslot = &mixer->slots[slot]; - left = pslot->volume[0]; - right = pslot->volume[1]; -@@ -258,15 +270,21 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) - result = pslot->get_volume(fmixer, pslot, &left, &right); - if (!pslot->stereo) - right = left; -- if (snd_BUG_ON(left < 0 || left > 100)) -- return -EIO; -- if (snd_BUG_ON(right < 0 || right > 100)) -- return -EIO; -+ if (snd_BUG_ON(left < 0 || left > 100)) { -+ result = -EIO; -+ goto unlock; -+ } -+ if (snd_BUG_ON(right < 0 || right > 100)) { -+ result = -EIO; -+ goto unlock; -+ } - if (result >= 0) { - pslot->volume[0] = left; - pslot->volume[1] = right; - result = (left & 0xff) | ((right & 0xff) << 8); - } -+ unlock: -+ mutex_unlock(&mixer->reg_mutex); - return result; - } - -@@ -279,6 +297,7 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, - - if (mixer == NULL || slot > 30) - return -EIO; -+ mutex_lock(&mixer->reg_mutex); - pslot = &mixer->slots[slot]; - if (left > 100) - left = 100; -@@ -289,10 +308,13 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, - if (pslot->put_volume) - result = pslot->put_volume(fmixer, pslot, left, right); - if (result < 0) -- return result; -+ goto unlock; - pslot->volume[0] = left; - pslot->volume[1] = right; -- return (left & 0xff) | ((right & 0xff) << 8); -+ result = (left & 0xff) | ((right & 0xff) << 8); -+ unlock: -+ mutex_unlock(&mixer->reg_mutex); -+ return result; - } - - static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg) -diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c -index 82a818734a5f7..20a0a4771b9a8 100644 ---- a/sound/core/oss/pcm_oss.c -+++ b/sound/core/oss/pcm_oss.c -@@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, - * - * Return the maximum value for field PAR. - */ --static unsigned int -+static int - snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) - { -@@ -682,18 +682,24 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *oss_params, - struct snd_pcm_hw_params *slave_params) - { -- size_t s; -- size_t oss_buffer_size, oss_period_size, oss_periods; -- size_t min_period_size, max_period_size; -+ ssize_t s; -+ ssize_t oss_buffer_size; -+ ssize_t oss_period_size, oss_periods; -+ ssize_t min_period_size, max_period_size; - struct snd_pcm_runtime *runtime = substream->runtime; - size_t oss_frame_size; - - oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * - params_channels(oss_params) / 8; - -+ oss_buffer_size = snd_pcm_hw_param_value_max(slave_params, -+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -+ NULL); -+ if (oss_buffer_size <= 0) -+ return -EINVAL; - oss_buffer_size = snd_pcm_plug_client_size(substream, -- snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; -- if (!oss_buffer_size) -+ oss_buffer_size * oss_frame_size); -+ if (oss_buffer_size <= 0) - return -EINVAL; - oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); - if (atomic_read(&substream->mmap_count)) { -@@ -730,7 +736,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, - - min_period_size = snd_pcm_plug_client_size(substream, - snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); -- if (min_period_size) { -+ if (min_period_size > 0) { - min_period_size *= oss_frame_size; - min_period_size = roundup_pow_of_two(min_period_size); - if (oss_period_size < min_period_size) -@@ -739,7 +745,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, - - max_period_size = snd_pcm_plug_client_size(substream, - snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); -- if (max_period_size) { -+ if (max_period_size > 0) { - max_period_size *= oss_frame_size; - max_period_size = rounddown_pow_of_two(max_period_size); - if (oss_period_size > max_period_size) -@@ -752,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, - oss_periods = substream->oss.setup.periods; - - s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); -- if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) -+ if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags) - s = runtime->oss.maxfrags; - if (oss_periods > s) - oss_periods = s; -@@ -878,8 +884,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) - err = -EINVAL; - goto failure; - } -- choose_rate(substream, sparams, runtime->oss.rate); -- snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); -+ -+ err = choose_rate(substream, sparams, runtime->oss.rate); -+ if (err < 0) -+ goto failure; -+ err = snd_pcm_hw_param_near(substream, sparams, -+ SNDRV_PCM_HW_PARAM_CHANNELS, -+ runtime->oss.channels, NULL); -+ if (err < 0) -+ goto failure; - - format = snd_pcm_oss_format_from(runtime->oss.format); - -@@ -1956,7 +1969,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign - if (runtime->oss.subdivision || runtime->oss.fragshift) - return -EINVAL; - fragshift = val & 0xffff; -- if (fragshift >= 31) -+ if (fragshift >= 25) /* should be large enough */ - return -EINVAL; - runtime->oss.fragshift = fragshift; - runtime->oss.maxfrags = (val >> 16) & 0xffff; -diff --git a/sound/core/timer.c b/sound/core/timer.c -index 92b7008fcdb86..b3214baa89193 100644 ---- a/sound/core/timer.c -+++ b/sound/core/timer.c -@@ -624,13 +624,13 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) - if (!timer) - return -EINVAL; - spin_lock_irqsave(&timer->lock, flags); -+ list_del_init(&timeri->ack_list); -+ list_del_init(&timeri->active_list); - if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | - SNDRV_TIMER_IFLG_START))) { - result = -EBUSY; - goto unlock; - } -- list_del_init(&timeri->ack_list); -- list_del_init(&timeri->active_list); - if (timer->card && timer->card->shutdown) - goto unlock; - if (stop) { -@@ -665,23 +665,22 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) - static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop) - { - unsigned long flags; -+ bool running; - - spin_lock_irqsave(&slave_active_lock, flags); -- if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { -- spin_unlock_irqrestore(&slave_active_lock, flags); -- return -EBUSY; -- } -+ running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING; - timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; - if (timeri->timer) { - spin_lock(&timeri->timer->lock); - list_del_init(&timeri->ack_list); - list_del_init(&timeri->active_list); -- snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : -- SNDRV_TIMER_EVENT_PAUSE); -+ if (running) -+ snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : -+ SNDRV_TIMER_EVENT_PAUSE); - spin_unlock(&timeri->timer->lock); - } - spin_unlock_irqrestore(&slave_active_lock, flags); -- return 0; -+ return running ? 0 : -EBUSY; - } - - /* -diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c -index fff18b5d4e052..f4a702def3979 100644 ---- a/sound/firewire/oxfw/oxfw-stream.c -+++ b/sound/firewire/oxfw/oxfw-stream.c -@@ -9,7 +9,7 @@ - #include <linux/delay.h> - - #define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512 --#define READY_TIMEOUT_MS 200 -+#define READY_TIMEOUT_MS 600 - - /* - * According to datasheet of Oxford Semiconductor: -@@ -367,6 +367,11 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) - // Just after changing sampling transfer frequency, many cycles are - // skipped for packet transmission. - tx_init_skip_cycles = 400; -+ } else if (oxfw->quirks & SND_OXFW_QUIRK_VOLUNTARY_RECOVERY) { -+ // It takes a bit time for target device to adjust event frequency -+ // according to nominal event frequency in isochronous packets from -+ // ALSA oxfw driver. -+ tx_init_skip_cycles = 4000; - } else { - replay_seq = true; - } -diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c -index daf731364695b..b496f87841aec 100644 ---- a/sound/firewire/oxfw/oxfw.c -+++ b/sound/firewire/oxfw/oxfw.c -@@ -25,6 +25,7 @@ - #define MODEL_SATELLITE 0x00200f - #define MODEL_SCS1M 0x001000 - #define MODEL_DUET_FW 0x01dddd -+#define MODEL_ONYX_1640I 0x001640 - - #define SPECIFIER_1394TA 0x00a02d - #define VERSION_AVC 0x010001 -@@ -192,6 +193,13 @@ static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id - // OXFW971-based models may transfer events by blocking method. - if (!(oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD)) - oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; -+ -+ if (model == MODEL_ONYX_1640I) { -+ //Unless receiving packets without NOINFO packet, the device transfers -+ //mostly half of events in packets than expected. -+ oxfw->quirks |= SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET | -+ SND_OXFW_QUIRK_VOLUNTARY_RECOVERY; -+ } - } - - return 0; -diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h -index c13034f6c2ca5..d728e451a25c6 100644 ---- a/sound/firewire/oxfw/oxfw.h -+++ b/sound/firewire/oxfw/oxfw.h -@@ -47,6 +47,11 @@ enum snd_oxfw_quirk { - // the device to process audio data even if the value is invalid in a point of - // IEC 61883-1/6. - SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET = 0x10, -+ // Loud Technologies Mackie Onyx 1640i seems to configure OXFW971 ASIC so that it decides -+ // event frequency according to events in received isochronous packets. The device looks to -+ // performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO -+ // are ignored, thus driver should transfer packets with timestamp. -+ SND_OXFW_QUIRK_VOLUNTARY_RECOVERY = 0x20, - }; - - /* This is an arbitrary number for convinience. */ -diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c -index 0c005d67fa891..37154ed43bd53 100644 ---- a/sound/hda/ext/hdac_ext_stream.c -+++ b/sound/hda/ext/hdac_ext_stream.c -@@ -106,20 +106,14 @@ void snd_hdac_stream_free_all(struct hdac_bus *bus) - } - EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); - --/** -- * snd_hdac_ext_stream_decouple - decouple the hdac stream -- * @bus: HD-audio core bus -- * @stream: HD-audio ext core stream object to initialize -- * @decouple: flag to decouple -- */ --void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, -- struct hdac_ext_stream *stream, bool decouple) -+void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, -+ struct hdac_ext_stream *stream, -+ bool decouple) - { - struct hdac_stream *hstream = &stream->hstream; - u32 val; - int mask = AZX_PPCTL_PROCEN(hstream->index); - -- spin_lock_irq(&bus->reg_lock); - val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask; - - if (decouple && !val) -@@ -128,6 +122,20 @@ void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, - snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0); - - stream->decoupled = decouple; -+} -+EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple_locked); -+ -+/** -+ * snd_hdac_ext_stream_decouple - decouple the hdac stream -+ * @bus: HD-audio core bus -+ * @stream: HD-audio ext core stream object to initialize -+ * @decouple: flag to decouple -+ */ -+void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, -+ struct hdac_ext_stream *stream, bool decouple) -+{ -+ spin_lock_irq(&bus->reg_lock); -+ snd_hdac_ext_stream_decouple_locked(bus, stream, decouple); - spin_unlock_irq(&bus->reg_lock); - } - EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple); -@@ -252,6 +260,7 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus, - return NULL; - } - -+ spin_lock_irq(&bus->reg_lock); - list_for_each_entry(stream, &bus->stream_list, list) { - struct hdac_ext_stream *hstream = container_of(stream, - struct hdac_ext_stream, -@@ -266,17 +275,16 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus, - } - - if (!hstream->link_locked) { -- snd_hdac_ext_stream_decouple(bus, hstream, true); -+ snd_hdac_ext_stream_decouple_locked(bus, hstream, true); - res = hstream; - break; - } - } - if (res) { -- spin_lock_irq(&bus->reg_lock); - res->link_locked = 1; - res->link_substream = substream; -- spin_unlock_irq(&bus->reg_lock); - } -+ spin_unlock_irq(&bus->reg_lock); - return res; - } - -@@ -292,6 +300,7 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus, - return NULL; - } - -+ spin_lock_irq(&bus->reg_lock); - list_for_each_entry(stream, &bus->stream_list, list) { - struct hdac_ext_stream *hstream = container_of(stream, - struct hdac_ext_stream, -@@ -301,18 +310,17 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus, - - if (!stream->opened) { - if (!hstream->decoupled) -- snd_hdac_ext_stream_decouple(bus, hstream, true); -+ snd_hdac_ext_stream_decouple_locked(bus, hstream, true); - res = hstream; - break; - } - } - if (res) { -- spin_lock_irq(&bus->reg_lock); - res->hstream.opened = 1; - res->hstream.running = 0; - res->hstream.substream = substream; -- spin_unlock_irq(&bus->reg_lock); - } -+ spin_unlock_irq(&bus->reg_lock); - - return res; - } -@@ -378,15 +386,17 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) - break; - - case HDAC_EXT_STREAM_TYPE_HOST: -+ spin_lock_irq(&bus->reg_lock); - if (stream->decoupled && !stream->link_locked) -- snd_hdac_ext_stream_decouple(bus, stream, false); -+ snd_hdac_ext_stream_decouple_locked(bus, stream, false); -+ spin_unlock_irq(&bus->reg_lock); - snd_hdac_stream_release(&stream->hstream); - break; - - case HDAC_EXT_STREAM_TYPE_LINK: -- if (stream->decoupled && !stream->hstream.opened) -- snd_hdac_ext_stream_decouple(bus, stream, false); - spin_lock_irq(&bus->reg_lock); -+ if (stream->decoupled && !stream->hstream.opened) -+ snd_hdac_ext_stream_decouple_locked(bus, stream, false); - stream->link_locked = 0; - stream->link_substream = NULL; - spin_unlock_irq(&bus->reg_lock); -diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c -index 1eb8563db2dff..9867555883c34 100644 ---- a/sound/hda/hdac_stream.c -+++ b/sound/hda/hdac_stream.c -@@ -296,6 +296,7 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, - int key = (substream->pcm->device << 16) | (substream->number << 2) | - (substream->stream + 1); - -+ spin_lock_irq(&bus->reg_lock); - list_for_each_entry(azx_dev, &bus->stream_list, list) { - if (azx_dev->direction != substream->stream) - continue; -@@ -309,13 +310,12 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, - res = azx_dev; - } - if (res) { -- spin_lock_irq(&bus->reg_lock); - res->opened = 1; - res->running = 0; - res->assigned_key = key; - res->substream = substream; -- spin_unlock_irq(&bus->reg_lock); - } -+ spin_unlock_irq(&bus->reg_lock); - return res; - } - EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); -diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c -index c9d0ba353463b..4208fa8a4db5b 100644 ---- a/sound/hda/intel-dsp-config.c -+++ b/sound/hda/intel-dsp-config.c -@@ -31,6 +31,7 @@ struct config_entry { - u16 device; - u8 acpi_hid[ACPI_ID_LEN]; - const struct dmi_system_id *dmi_table; -+ u8 codec_hid[ACPI_ID_LEN]; - }; - - /* -@@ -56,7 +57,7 @@ static const struct config_entry config_table[] = { - /* - * Apollolake (Broxton-P) - * the legacy HDAudio driver is used except on Up Squared (SOF) and -- * Chromebooks (SST) -+ * Chromebooks (SST), as well as devices based on the ES8336 codec - */ - #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) - { -@@ -73,6 +74,11 @@ static const struct config_entry config_table[] = { - {} - } - }, -+ { -+ .flags = FLAG_SOF, -+ .device = 0x5a98, -+ .codec_hid = "ESSX8336", -+ }, - #endif - #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) - { -@@ -137,7 +143,7 @@ static const struct config_entry config_table[] = { - - /* - * Geminilake uses legacy HDAudio driver except for Google -- * Chromebooks -+ * Chromebooks and devices based on the ES8336 codec - */ - /* Geminilake */ - #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) -@@ -154,6 +160,11 @@ static const struct config_entry config_table[] = { - {} - } - }, -+ { -+ .flags = FLAG_SOF, -+ .device = 0x3198, -+ .codec_hid = "ESSX8336", -+ }, - #endif - - /* -@@ -241,6 +252,11 @@ static const struct config_entry config_table[] = { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, - .device = 0x02c8, - }, -+ { -+ .flags = FLAG_SOF, -+ .device = 0x02c8, -+ .codec_hid = "ESSX8336", -+ }, - /* Cometlake-H */ - { - .flags = FLAG_SOF, -@@ -265,6 +281,11 @@ static const struct config_entry config_table[] = { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, - .device = 0x06c8, - }, -+ { -+ .flags = FLAG_SOF, -+ .device = 0x06c8, -+ .codec_hid = "ESSX8336", -+ }, - #endif - - /* Icelake */ -@@ -288,6 +309,15 @@ static const struct config_entry config_table[] = { - }, - #endif - -+/* JasperLake */ -+#if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) -+ { -+ .flags = FLAG_SOF, -+ .device = 0x4dc8, -+ .codec_hid = "ESSX8336", -+ }, -+#endif -+ - /* Tigerlake */ - #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) - { -@@ -311,6 +341,11 @@ static const struct config_entry config_table[] = { - .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, - .device = 0x43c8, - }, -+ { -+ .flags = FLAG_SOF, -+ .device = 0xa0c8, -+ .codec_hid = "ESSX8336", -+ }, - #endif - - /* Elkhart Lake */ -@@ -354,6 +389,8 @@ static const struct config_entry *snd_intel_dsp_find_config - continue; - if (table->dmi_table && !dmi_check_system(table->dmi_table)) - continue; -+ if (table->codec_hid[0] && !acpi_dev_present(table->codec_hid, NULL, -1)) -+ continue; - return table; - } - return NULL; -diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig -index 6ffa48dd59830..570b88e0b2018 100644 ---- a/sound/isa/Kconfig -+++ b/sound/isa/Kconfig -@@ -22,7 +22,7 @@ config SND_SB16_DSP - menuconfig SND_ISA - bool "ISA sound devices" - depends on ISA || COMPILE_TEST -- depends on ISA_DMA_API -+ depends on ISA_DMA_API && !M68K - default y - help - Support for sound devices connected via the ISA bus. -diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c -index a1c770d826dda..6d664dd8dde0b 100644 ---- a/sound/isa/gus/gus_dma.c -+++ b/sound/isa/gus/gus_dma.c -@@ -126,6 +126,8 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) - } - block = snd_gf1_dma_next_block(gus); - spin_unlock(&gus->dma_lock); -+ if (!block) -+ return; - snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); - kfree(block); - #if 0 -diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig -index 93bc9bef7641f..41ce125971777 100644 ---- a/sound/pci/Kconfig -+++ b/sound/pci/Kconfig -@@ -279,6 +279,7 @@ config SND_CS46XX_NEW_DSP - config SND_CS5530 - tristate "CS5530 Audio" - depends on ISA_DMA_API && (X86_32 || COMPILE_TEST) -+ depends on !M68K - select SND_SB16_DSP - help - Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips. -diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c -index da6e6350ceafa..d074727c3e21d 100644 ---- a/sound/pci/ctxfi/ctamixer.c -+++ b/sound/pci/ctxfi/ctamixer.c -@@ -23,16 +23,15 @@ - - #define BLANK_SLOT 4094 - --static int amixer_master(struct rsc *rsc) -+static void amixer_master(struct rsc *rsc) - { - rsc->conj = 0; -- return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0]; -+ rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0]; - } - --static int amixer_next_conj(struct rsc *rsc) -+static void amixer_next_conj(struct rsc *rsc) - { - rsc->conj++; -- return container_of(rsc, struct amixer, rsc)->idx[rsc->conj]; - } - - static int amixer_index(const struct rsc *rsc) -@@ -331,16 +330,15 @@ int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr) - - /* SUM resource management */ - --static int sum_master(struct rsc *rsc) -+static void sum_master(struct rsc *rsc) - { - rsc->conj = 0; -- return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0]; -+ rsc->idx = container_of(rsc, struct sum, rsc)->idx[0]; - } - --static int sum_next_conj(struct rsc *rsc) -+static void sum_next_conj(struct rsc *rsc) - { - rsc->conj++; -- return container_of(rsc, struct sum, rsc)->idx[rsc->conj]; - } - - static int sum_index(const struct rsc *rsc) -diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c -index f589da0453424..7fc720046ce29 100644 ---- a/sound/pci/ctxfi/ctdaio.c -+++ b/sound/pci/ctxfi/ctdaio.c -@@ -51,12 +51,12 @@ static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { - [SPDIFIO] = {.left = 0x05, .right = 0x85}, - }; - --static int daio_master(struct rsc *rsc) -+static void daio_master(struct rsc *rsc) - { - /* Actually, this is not the resource index of DAIO. - * For DAO, it is the input mapper index. And, for DAI, - * it is the output time-slot index. */ -- return rsc->conj = rsc->idx; -+ rsc->conj = rsc->idx; - } - - static int daio_index(const struct rsc *rsc) -@@ -64,19 +64,19 @@ static int daio_index(const struct rsc *rsc) - return rsc->conj; - } - --static int daio_out_next_conj(struct rsc *rsc) -+static void daio_out_next_conj(struct rsc *rsc) - { -- return rsc->conj += 2; -+ rsc->conj += 2; - } - --static int daio_in_next_conj_20k1(struct rsc *rsc) -+static void daio_in_next_conj_20k1(struct rsc *rsc) - { -- return rsc->conj += 0x200; -+ rsc->conj += 0x200; - } - --static int daio_in_next_conj_20k2(struct rsc *rsc) -+static void daio_in_next_conj_20k2(struct rsc *rsc) - { -- return rsc->conj += 0x100; -+ rsc->conj += 0x100; - } - - static const struct rsc_ops daio_out_rsc_ops = { -diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c -index 81ad269345182..be1d3e61309ce 100644 ---- a/sound/pci/ctxfi/ctresource.c -+++ b/sound/pci/ctxfi/ctresource.c -@@ -109,18 +109,17 @@ static int audio_ring_slot(const struct rsc *rsc) - return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type]; - } - --static int rsc_next_conj(struct rsc *rsc) -+static void rsc_next_conj(struct rsc *rsc) - { - unsigned int i; - for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); ) - i++; - rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i); -- return rsc->conj; - } - --static int rsc_master(struct rsc *rsc) -+static void rsc_master(struct rsc *rsc) - { -- return rsc->conj = rsc->idx; -+ rsc->conj = rsc->idx; - } - - static const struct rsc_ops rsc_generic_ops = { -diff --git a/sound/pci/ctxfi/ctresource.h b/sound/pci/ctxfi/ctresource.h -index fdbfd808816d3..58553bda44f43 100644 ---- a/sound/pci/ctxfi/ctresource.h -+++ b/sound/pci/ctxfi/ctresource.h -@@ -39,8 +39,8 @@ struct rsc { - }; - - struct rsc_ops { -- int (*master)(struct rsc *rsc); /* Move to master resource */ -- int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */ -+ void (*master)(struct rsc *rsc); /* Move to master resource */ -+ void (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */ - int (*index)(const struct rsc *rsc); /* Return the index of resource */ - /* Return the output slot number */ - int (*output_slot)(const struct rsc *rsc); -diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c -index bd4697b442334..4a94b4708a77e 100644 ---- a/sound/pci/ctxfi/ctsrc.c -+++ b/sound/pci/ctxfi/ctsrc.c -@@ -590,16 +590,15 @@ int src_mgr_destroy(struct src_mgr *src_mgr) - - /* SRCIMP resource manager operations */ - --static int srcimp_master(struct rsc *rsc) -+static void srcimp_master(struct rsc *rsc) - { - rsc->conj = 0; -- return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0]; -+ rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0]; - } - --static int srcimp_next_conj(struct rsc *rsc) -+static void srcimp_next_conj(struct rsc *rsc) - { - rsc->conj++; -- return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj]; - } - - static int srcimp_index(const struct rsc *rsc) -diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c -index 4d22e7adeee8e..21fec82489bd7 100644 ---- a/sound/pci/hda/hda_intel.c -+++ b/sound/pci/hda/hda_intel.c -@@ -335,7 +335,10 @@ enum { - ((pci)->device == 0x0c0c) || \ - ((pci)->device == 0x0d0c) || \ - ((pci)->device == 0x160c) || \ -- ((pci)->device == 0x490d)) -+ ((pci)->device == 0x490d) || \ -+ ((pci)->device == 0x4f90) || \ -+ ((pci)->device == 0x4f91) || \ -+ ((pci)->device == 0x4f92)) - - #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) - -@@ -638,13 +641,17 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) - * the update-IRQ timing. The IRQ is issued before actually the - * data is processed. So, we need to process it afterwords in a - * workqueue. -+ * -+ * Returns 1 if OK to proceed, 0 for delay handling, -1 for skipping update - */ - static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) - { - struct snd_pcm_substream *substream = azx_dev->core.substream; -+ struct snd_pcm_runtime *runtime = substream->runtime; - int stream = substream->stream; - u32 wallclk; - unsigned int pos; -+ snd_pcm_uframes_t hwptr, target; - - wallclk = azx_readl(chip, WALLCLK) - azx_dev->core.start_wallclk; - if (wallclk < (azx_dev->core.period_wallclk * 2) / 3) -@@ -681,6 +688,24 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) - /* NG - it's below the first next period boundary */ - return chip->bdl_pos_adj ? 0 : -1; - azx_dev->core.start_wallclk += wallclk; -+ -+ if (azx_dev->core.no_period_wakeup) -+ return 1; /* OK, no need to check period boundary */ -+ -+ if (runtime->hw_ptr_base != runtime->hw_ptr_interrupt) -+ return 1; /* OK, already in hwptr updating process */ -+ -+ /* check whether the period gets really elapsed */ -+ pos = bytes_to_frames(runtime, pos); -+ hwptr = runtime->hw_ptr_base + pos; -+ if (hwptr < runtime->status->hw_ptr) -+ hwptr += runtime->buffer_size; -+ target = runtime->hw_ptr_interrupt + runtime->period_size; -+ if (hwptr < target) { -+ /* too early wakeup, process it later */ -+ return chip->bdl_pos_adj ? 0 : -1; -+ } -+ - return 1; /* OK, it's fine */ - } - -@@ -859,31 +884,6 @@ static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev, - return substream->runtime->delay; - } - --static unsigned int azx_skl_get_dpib_pos(struct azx *chip, -- struct azx_dev *azx_dev) --{ -- return _snd_hdac_chip_readl(azx_bus(chip), -- AZX_REG_VS_SDXDPIB_XBASE + -- (AZX_REG_VS_SDXDPIB_XINTERVAL * -- azx_dev->core.index)); --} -- --/* get the current DMA position with correction on SKL+ chips */ --static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev) --{ -- /* DPIB register gives a more accurate position for playback */ -- if (azx_dev->core.substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -- return azx_skl_get_dpib_pos(chip, azx_dev); -- -- /* For capture, we need to read posbuf, but it requires a delay -- * for the possible boundary overlap; the read of DPIB fetches the -- * actual posbuf -- */ -- udelay(20); -- azx_skl_get_dpib_pos(chip, azx_dev); -- return azx_get_pos_posbuf(chip, azx_dev); --} -- - static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset) - { - azx_stop_chip(chip); -@@ -1573,7 +1573,7 @@ static void assign_position_fix(struct azx *chip, int fix) - [POS_FIX_POSBUF] = azx_get_pos_posbuf, - [POS_FIX_VIACOMBO] = azx_via_get_position, - [POS_FIX_COMBO] = azx_get_pos_lpib, -- [POS_FIX_SKL] = azx_get_pos_skl, -+ [POS_FIX_SKL] = azx_get_pos_posbuf, - [POS_FIX_FIFO] = azx_get_pos_fifo, - }; - -@@ -2330,7 +2330,8 @@ static int azx_probe_continue(struct azx *chip) - - out_free: - if (err < 0) { -- azx_free(chip); -+ pci_set_drvdata(pci, NULL); -+ snd_card_free(chip->card); - return err; - } - -@@ -2474,6 +2475,13 @@ static const struct pci_device_id azx_ids[] = { - /* DG1 */ - { PCI_DEVICE(0x8086, 0x490d), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, -+ /* DG2 */ -+ { PCI_DEVICE(0x8086, 0x4f90), -+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, -+ { PCI_DEVICE(0x8086, 0x4f91), -+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, -+ { PCI_DEVICE(0x8086, 0x4f92), -+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, - /* Alderlake-S */ - { PCI_DEVICE(0x8086, 0x7ad0), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, -diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h -index ea8ab8b433378..d22c96eb2f8fb 100644 ---- a/sound/pci/hda/hda_local.h -+++ b/sound/pci/hda/hda_local.h -@@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid, - #define for_each_hda_codec_node(nid, codec) \ - for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) - -+/* Set the codec power_state flag to indicate to allow unsol event handling; -+ * see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the -+ * state tracking, so use with care. -+ */ -+static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec) -+{ -+ codec->core.dev.power.power_state = PMSG_ON; -+} -+ - /* - * get widget capabilities - */ -diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c -index 31ff11ab868e1..039b9f2f8e947 100644 ---- a/sound/pci/hda/patch_cs8409.c -+++ b/sound/pci/hda/patch_cs8409.c -@@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42) - if (cs42l42->full_scale_vol) - cs8409_i2c_write(cs42l42, 0x2001, 0x01); - -+ /* we have to explicitly allow unsol event handling even during the -+ * resume phase so that the jack event is processed properly -+ */ -+ snd_hda_codec_allow_unsol_events(cs42l42->codec); -+ - cs42l42_enable_jack_detect(cs42l42); - } - -diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c -index 65d2c55399195..415701bd10ac8 100644 ---- a/sound/pci/hda/patch_hdmi.c -+++ b/sound/pci/hda/patch_hdmi.c -@@ -4380,10 +4380,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), - HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), - HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi), - HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi), --HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi), - HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi), -+HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI", patch_i915_tgl_hdmi), - HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), - HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), -+HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi), - HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), - HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), - HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index 965b096f416f6..3599f4c85ebf7 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -2539,6 +2539,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { - SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS), -+ SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED), -@@ -4355,6 +4356,16 @@ static void alc287_fixup_hp_gpio_led(struct hda_codec *codec, - alc_fixup_hp_gpio_led(codec, action, 0x10, 0); - } - -+static void alc245_fixup_hp_gpio_led(struct hda_codec *codec, -+ const struct hda_fixup *fix, int action) -+{ -+ struct alc_spec *spec = codec->spec; -+ -+ if (action == HDA_FIXUP_ACT_PRE_PROBE) -+ spec->micmute_led_polarity = 1; -+ alc_fixup_hp_gpio_led(codec, action, 0, 0x04); -+} -+ - /* turn on/off mic-mute LED per capture hook via VREF change */ - static int vref_micmute_led_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -@@ -6492,22 +6503,47 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, - /* for alc285_fixup_ideapad_s740_coef() */ - #include "ideapad_s740_helper.c" - --static void alc256_fixup_tongfang_reset_persistent_settings(struct hda_codec *codec, -- const struct hda_fixup *fix, -- int action) -+static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = { -+ WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000), -+ WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000), -+ WRITE_COEF(0x37, 0xfe05), WRITE_COEF(0x45, 0x5089), -+ {} -+}; -+ -+static void alc256_fixup_set_coef_defaults(struct hda_codec *codec, -+ const struct hda_fixup *fix, -+ int action) - { - /* -- * A certain other OS sets these coeffs to different values. On at least one TongFang -- * barebone these settings might survive even a cold reboot. So to restore a clean slate the -- * values are explicitly reset to default here. Without this, the external microphone is -- * always in a plugged-in state, while the internal microphone is always in an unplugged -- * state, breaking the ability to use the internal microphone. -- */ -- alc_write_coef_idx(codec, 0x24, 0x0000); -- alc_write_coef_idx(codec, 0x26, 0x0000); -- alc_write_coef_idx(codec, 0x29, 0x3000); -- alc_write_coef_idx(codec, 0x37, 0xfe05); -- alc_write_coef_idx(codec, 0x45, 0x5089); -+ * A certain other OS sets these coeffs to different values. On at least -+ * one TongFang barebone these settings might survive even a cold -+ * reboot. So to restore a clean slate the values are explicitly reset -+ * to default here. Without this, the external microphone is always in a -+ * plugged-in state, while the internal microphone is always in an -+ * unplugged state, breaking the ability to use the internal microphone. -+ */ -+ alc_process_coef_fw(codec, alc256_fixup_set_coef_defaults_coefs); -+} -+ -+static const struct coef_fw alc233_fixup_no_audio_jack_coefs[] = { -+ WRITE_COEF(0x1a, 0x9003), WRITE_COEF(0x1b, 0x0e2b), WRITE_COEF(0x37, 0xfe06), -+ WRITE_COEF(0x38, 0x4981), WRITE_COEF(0x45, 0xd489), WRITE_COEF(0x46, 0x0074), -+ WRITE_COEF(0x49, 0x0149), -+ {} -+}; -+ -+static void alc233_fixup_no_audio_jack(struct hda_codec *codec, -+ const struct hda_fixup *fix, -+ int action) -+{ -+ /* -+ * The audio jack input and output is not detected on the ASRock NUC Box -+ * 1100 series when cold booting without this fix. Warm rebooting from a -+ * certain other OS makes the audio functional, as COEF settings are -+ * preserved in this case. This fix sets these altered COEF values as -+ * the default. -+ */ -+ alc_process_coef_fw(codec, alc233_fixup_no_audio_jack_coefs); - } - - enum { -@@ -6709,6 +6745,7 @@ enum { - ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, - ALC287_FIXUP_HP_GPIO_LED, - ALC256_FIXUP_HP_HEADSET_MIC, -+ ALC245_FIXUP_HP_GPIO_LED, - ALC236_FIXUP_DELL_AIO_HEADSET_MIC, - ALC282_FIXUP_ACER_DISABLE_LINEOUT, - ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST, -@@ -6726,7 +6763,9 @@ enum { - ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, - ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, - ALC287_FIXUP_13S_GEN2_SPEAKERS, -- ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS, -+ ALC256_FIXUP_SET_COEF_DEFAULTS, -+ ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, -+ ALC233_FIXUP_NO_AUDIO_JACK, - }; - - static const struct hda_fixup alc269_fixups[] = { -@@ -7333,6 +7372,8 @@ static const struct hda_fixup alc269_fixups[] = { - [ALC245_FIXUP_HP_X360_AMP] = { - .type = HDA_FIXUP_FUNC, - .v.func = alc245_fixup_hp_x360_amp, -+ .chained = true, -+ .chain_id = ALC245_FIXUP_HP_GPIO_LED - }, - [ALC288_FIXUP_DELL_HEADSET_MODE] = { - .type = HDA_FIXUP_FUNC, -@@ -8428,9 +8469,26 @@ static const struct hda_fixup alc269_fixups[] = { - .chained = true, - .chain_id = ALC269_FIXUP_HEADSET_MODE, - }, -- [ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS] = { -+ [ALC256_FIXUP_SET_COEF_DEFAULTS] = { -+ .type = HDA_FIXUP_FUNC, -+ .v.func = alc256_fixup_set_coef_defaults, -+ }, -+ [ALC245_FIXUP_HP_GPIO_LED] = { - .type = HDA_FIXUP_FUNC, -- .v.func = alc256_fixup_tongfang_reset_persistent_settings, -+ .v.func = alc245_fixup_hp_gpio_led, -+ }, -+ [ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = { -+ .type = HDA_FIXUP_PINS, -+ .v.pins = (const struct hda_pintbl[]) { -+ { 0x19, 0x03a11120 }, /* use as headset mic, without its own jack detect */ -+ { } -+ }, -+ .chained = true, -+ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, -+ }, -+ [ALC233_FIXUP_NO_AUDIO_JACK] = { -+ .type = HDA_FIXUP_FUNC, -+ .v.func = alc233_fixup_no_audio_jack, - }, - }; - -@@ -8468,6 +8526,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), - SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC), - SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC), -+ SND_PCI_QUIRK(0x1025, 0x141f, "Acer Spin SP513-54N", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC), -@@ -8607,8 +8666,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), - SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), - SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED), -+ SND_PCI_QUIRK(0x103c, 0x8728, "HP EliteBook 840 G7", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), -+ SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), - SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT), - SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED), - SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), -@@ -8617,6 +8678,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - ALC285_FIXUP_HP_GPIO_AMP_INIT), - SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation", - ALC285_FIXUP_HP_GPIO_AMP_INIT), -+ SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), - SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), -@@ -8668,6 +8730,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), - SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC), - SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE), -+ SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401), - SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE), - SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), - SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE), -@@ -8731,11 +8794,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1558, 0x5015, "Clevo NH5[58]H[HJK]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1558, 0x5017, "Clevo NH7[79]H[HJK]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1558, 0x50e1, "Clevo NH5[58]HPQ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1558, 0x50e2, "Clevo NH7[79]HPQ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -@@ -8858,6 +8925,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), - SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), - SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), -+ SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK), - SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), - SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20), - SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI), -@@ -8865,7 +8933,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ - SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), - SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), -- SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS), -+ SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), - SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), - SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), -@@ -10167,6 +10235,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, - } - } - -+static void alc897_hp_automute_hook(struct hda_codec *codec, -+ struct hda_jack_callback *jack) -+{ -+ struct alc_spec *spec = codec->spec; -+ int vref; -+ -+ snd_hda_gen_hp_automute(codec, jack); -+ vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP; -+ snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, -+ vref); -+} -+ -+static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec, -+ const struct hda_fixup *fix, int action) -+{ -+ struct alc_spec *spec = codec->spec; -+ if (action == HDA_FIXUP_ACT_PRE_PROBE) { -+ spec->gen.hp_automute_hook = alc897_hp_automute_hook; -+ } -+} -+ - static const struct coef_fw alc668_coefs[] = { - WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), - WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), -@@ -10247,6 +10336,8 @@ enum { - ALC668_FIXUP_ASUS_NO_HEADSET_MIC, - ALC668_FIXUP_HEADSET_MIC, - ALC668_FIXUP_MIC_DET_COEF, -+ ALC897_FIXUP_LENOVO_HEADSET_MIC, -+ ALC897_FIXUP_HEADSET_MIC_PIN, - }; - - static const struct hda_fixup alc662_fixups[] = { -@@ -10653,6 +10744,19 @@ static const struct hda_fixup alc662_fixups[] = { - {} - }, - }, -+ [ALC897_FIXUP_LENOVO_HEADSET_MIC] = { -+ .type = HDA_FIXUP_FUNC, -+ .v.func = alc897_fixup_lenovo_headset_mic, -+ }, -+ [ALC897_FIXUP_HEADSET_MIC_PIN] = { -+ .type = HDA_FIXUP_PINS, -+ .v.pins = (const struct hda_pintbl[]) { -+ { 0x1a, 0x03a11050 }, -+ { } -+ }, -+ .chained = true, -+ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC -+ }, - }; - - static const struct snd_pci_quirk alc662_fixup_tbl[] = { -@@ -10697,6 +10801,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { - SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), - SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), -+ SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN), -+ SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), -+ SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), -+ SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), - SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), -diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c -index 75aa2ea733a59..96c12dfb24cf9 100644 ---- a/sound/pci/rme9652/hdsp.c -+++ b/sound/pci/rme9652/hdsp.c -@@ -468,8 +468,11 @@ struct hdsp { - unsigned char ss_out_channels; - u32 io_loopback; /* output loopback channel states*/ - -- struct snd_dma_buffer *capture_dma_buf; -- struct snd_dma_buffer *playback_dma_buf; -+ /* DMA buffers; those are copied instances from the original snd_dma_buf -+ * objects (which are managed via devres) for the address alignments -+ */ -+ struct snd_dma_buffer capture_dma_buf; -+ struct snd_dma_buffer playback_dma_buf; - unsigned char *capture_buffer; /* suitably aligned address */ - unsigned char *playback_buffer; /* suitably aligned address */ - -@@ -3764,30 +3767,32 @@ static void snd_hdsp_proc_init(struct hdsp *hdsp) - - static int snd_hdsp_initialize_memory(struct hdsp *hdsp) - { -- unsigned long pb_bus, cb_bus; -+ struct snd_dma_buffer *capture_dma, *playback_dma; - -- hdsp->capture_dma_buf = -- snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); -- hdsp->playback_dma_buf = -- snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); -- if (!hdsp->capture_dma_buf || !hdsp->playback_dma_buf) { -+ capture_dma = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); -+ playback_dma = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); -+ if (!capture_dma || !playback_dma) { - dev_err(hdsp->card->dev, - "%s: no buffers available\n", hdsp->card_name); - return -ENOMEM; - } - -- /* Align to bus-space 64K boundary */ -+ /* copy to the own data for alignment */ -+ hdsp->capture_dma_buf = *capture_dma; -+ hdsp->playback_dma_buf = *playback_dma; - -- cb_bus = ALIGN(hdsp->capture_dma_buf->addr, 0x10000ul); -- pb_bus = ALIGN(hdsp->playback_dma_buf->addr, 0x10000ul); -+ /* Align to bus-space 64K boundary */ -+ hdsp->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul); -+ hdsp->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul); - - /* Tell the card where it is */ -+ hdsp_write(hdsp, HDSP_inputBufferAddress, hdsp->capture_dma_buf.addr); -+ hdsp_write(hdsp, HDSP_outputBufferAddress, hdsp->playback_dma_buf.addr); - -- hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus); -- hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus); -- -- hdsp->capture_buffer = hdsp->capture_dma_buf->area + (cb_bus - hdsp->capture_dma_buf->addr); -- hdsp->playback_buffer = hdsp->playback_dma_buf->area + (pb_bus - hdsp->playback_dma_buf->addr); -+ hdsp->capture_dma_buf.area += hdsp->capture_dma_buf.addr - capture_dma->addr; -+ hdsp->playback_dma_buf.area += hdsp->playback_dma_buf.addr - playback_dma->addr; -+ hdsp->capture_buffer = hdsp->capture_dma_buf.area; -+ hdsp->playback_buffer = hdsp->playback_dma_buf.area; - - return 0; - } -@@ -4507,7 +4512,7 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) - snd_pcm_set_sync(substream); - - runtime->hw = snd_hdsp_playback_subinfo; -- snd_pcm_set_runtime_buffer(substream, hdsp->playback_dma_buf); -+ snd_pcm_set_runtime_buffer(substream, &hdsp->playback_dma_buf); - - hdsp->playback_pid = current->pid; - hdsp->playback_substream = substream; -@@ -4583,7 +4588,7 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream) - snd_pcm_set_sync(substream); - - runtime->hw = snd_hdsp_capture_subinfo; -- snd_pcm_set_runtime_buffer(substream, hdsp->capture_dma_buf); -+ snd_pcm_set_runtime_buffer(substream, &hdsp->capture_dma_buf); - - hdsp->capture_pid = current->pid; - hdsp->capture_substream = substream; -diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c -index e76f737ac9e8e..7755e19aa7761 100644 ---- a/sound/pci/rme9652/rme9652.c -+++ b/sound/pci/rme9652/rme9652.c -@@ -208,8 +208,11 @@ struct snd_rme9652 { - unsigned char ds_channels; - unsigned char ss_channels; /* different for hammerfall/hammerfall-light */ - -- struct snd_dma_buffer *playback_dma_buf; -- struct snd_dma_buffer *capture_dma_buf; -+ /* DMA buffers; those are copied instances from the original snd_dma_buf -+ * objects (which are managed via devres) for the address alignments -+ */ -+ struct snd_dma_buffer playback_dma_buf; -+ struct snd_dma_buffer capture_dma_buf; - - unsigned char *capture_buffer; /* suitably aligned address */ - unsigned char *playback_buffer; /* suitably aligned address */ -@@ -1719,30 +1722,32 @@ static void snd_rme9652_card_free(struct snd_card *card) - - static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652) - { -- unsigned long pb_bus, cb_bus; -+ struct snd_dma_buffer *capture_dma, *playback_dma; - -- rme9652->capture_dma_buf = -- snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); -- rme9652->playback_dma_buf = -- snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); -- if (!rme9652->capture_dma_buf || !rme9652->playback_dma_buf) { -+ capture_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); -+ playback_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); -+ if (!capture_dma || !playback_dma) { - dev_err(rme9652->card->dev, - "%s: no buffers available\n", rme9652->card_name); - return -ENOMEM; - } - -- /* Align to bus-space 64K boundary */ -+ /* copy to the own data for alignment */ -+ rme9652->capture_dma_buf = *capture_dma; -+ rme9652->playback_dma_buf = *playback_dma; - -- cb_bus = ALIGN(rme9652->capture_dma_buf->addr, 0x10000ul); -- pb_bus = ALIGN(rme9652->playback_dma_buf->addr, 0x10000ul); -+ /* Align to bus-space 64K boundary */ -+ rme9652->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul); -+ rme9652->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul); - - /* Tell the card where it is */ -+ rme9652_write(rme9652, RME9652_rec_buffer, rme9652->capture_dma_buf.addr); -+ rme9652_write(rme9652, RME9652_play_buffer, rme9652->playback_dma_buf.addr); - -- rme9652_write(rme9652, RME9652_rec_buffer, cb_bus); -- rme9652_write(rme9652, RME9652_play_buffer, pb_bus); -- -- rme9652->capture_buffer = rme9652->capture_dma_buf->area + (cb_bus - rme9652->capture_dma_buf->addr); -- rme9652->playback_buffer = rme9652->playback_dma_buf->area + (pb_bus - rme9652->playback_dma_buf->addr); -+ rme9652->capture_dma_buf.area += rme9652->capture_dma_buf.addr - capture_dma->addr; -+ rme9652->playback_dma_buf.area += rme9652->playback_dma_buf.addr - playback_dma->addr; -+ rme9652->capture_buffer = rme9652->capture_dma_buf.area; -+ rme9652->playback_buffer = rme9652->playback_dma_buf.area; - - return 0; - } -@@ -2259,7 +2264,7 @@ static int snd_rme9652_playback_open(struct snd_pcm_substream *substream) - snd_pcm_set_sync(substream); - - runtime->hw = snd_rme9652_playback_subinfo; -- snd_pcm_set_runtime_buffer(substream, rme9652->playback_dma_buf); -+ snd_pcm_set_runtime_buffer(substream, &rme9652->playback_dma_buf); - - if (rme9652->capture_substream == NULL) { - rme9652_stop(rme9652); -@@ -2318,7 +2323,7 @@ static int snd_rme9652_capture_open(struct snd_pcm_substream *substream) - snd_pcm_set_sync(substream); - - runtime->hw = snd_rme9652_capture_subinfo; -- snd_pcm_set_runtime_buffer(substream, rme9652->capture_dma_buf); -+ snd_pcm_set_runtime_buffer(substream, &rme9652->capture_dma_buf); - - if (rme9652->playback_substream == NULL) { - rme9652_stop(rme9652); -diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c -index 9a463ab54bddc..762d9de73dbc2 100644 ---- a/sound/soc/codecs/cs42l42.c -+++ b/sound/soc/codecs/cs42l42.c -@@ -93,7 +93,7 @@ static const struct reg_default cs42l42_reg_defaults[] = { - { CS42L42_ASP_RX_INT_MASK, 0x1F }, - { CS42L42_ASP_TX_INT_MASK, 0x0F }, - { CS42L42_CODEC_INT_MASK, 0x03 }, -- { CS42L42_SRCPL_INT_MASK, 0xFF }, -+ { CS42L42_SRCPL_INT_MASK, 0x7F }, - { CS42L42_VPMON_INT_MASK, 0x01 }, - { CS42L42_PLL_LOCK_INT_MASK, 0x01 }, - { CS42L42_TSRS_PLUG_INT_MASK, 0x0F }, -@@ -130,7 +130,7 @@ static const struct reg_default cs42l42_reg_defaults[] = { - { CS42L42_MIXER_CHA_VOL, 0x3F }, - { CS42L42_MIXER_ADC_VOL, 0x3F }, - { CS42L42_MIXER_CHB_VOL, 0x3F }, -- { CS42L42_EQ_COEF_IN0, 0x22 }, -+ { CS42L42_EQ_COEF_IN0, 0x00 }, - { CS42L42_EQ_COEF_IN1, 0x00 }, - { CS42L42_EQ_COEF_IN2, 0x00 }, - { CS42L42_EQ_COEF_IN3, 0x00 }, -@@ -853,11 +853,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, - - switch(substream->stream) { - case SNDRV_PCM_STREAM_CAPTURE: -- if (channels == 2) { -- val |= CS42L42_ASP_TX_CH2_AP_MASK; -- val |= width << CS42L42_ASP_TX_CH2_RES_SHIFT; -- } -- val |= width << CS42L42_ASP_TX_CH1_RES_SHIFT; -+ /* channel 2 on high LRCLK */ -+ val = CS42L42_ASP_TX_CH2_AP_MASK | -+ (width << CS42L42_ASP_TX_CH2_RES_SHIFT) | -+ (width << CS42L42_ASP_TX_CH1_RES_SHIFT); - - snd_soc_component_update_bits(component, CS42L42_ASP_TX_CH_AP_RES, - CS42L42_ASP_TX_CH1_AP_MASK | CS42L42_ASP_TX_CH2_AP_MASK | -@@ -1685,12 +1684,15 @@ static void cs42l42_setup_hs_type_detect(struct cs42l42_private *cs42l42) - (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)); - - /* Enable the tip sense circuit */ -+ regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL, -+ CS42L42_TS_INV_MASK, CS42L42_TS_INV_MASK); -+ - regmap_update_bits(cs42l42->regmap, CS42L42_TIPSENSE_CTL, - CS42L42_TIP_SENSE_CTRL_MASK | - CS42L42_TIP_SENSE_INV_MASK | - CS42L42_TIP_SENSE_DEBOUNCE_MASK, - (3 << CS42L42_TIP_SENSE_CTRL_SHIFT) | -- (0 << CS42L42_TIP_SENSE_INV_SHIFT) | -+ (!cs42l42->ts_inv << CS42L42_TIP_SENSE_INV_SHIFT) | - (2 << CS42L42_TIP_SENSE_DEBOUNCE_SHIFT)); - - /* Save the initial status of the tip sense */ -@@ -1734,10 +1736,6 @@ static int cs42l42_handle_device_data(struct device *dev, - cs42l42->ts_inv = CS42L42_TS_INV_DIS; - } - -- regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL, -- CS42L42_TS_INV_MASK, -- (cs42l42->ts_inv << CS42L42_TS_INV_SHIFT)); -- - ret = device_property_read_u32(dev, "cirrus,ts-dbnc-rise", &val); - if (!ret) { - switch (val) { -@@ -1948,8 +1946,9 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, - NULL, cs42l42_irq_thread, - IRQF_ONESHOT | IRQF_TRIGGER_LOW, - "cs42l42", cs42l42); -- -- if (ret != 0) -+ if (ret == -EPROBE_DEFER) -+ goto err_disable; -+ else if (ret != 0) - dev_err(&i2c_client->dev, - "Failed to request IRQ: %d\n", ret); - -diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c -index 067757d1d70a3..5fb02635c1406 100644 ---- a/sound/soc/codecs/es8316.c -+++ b/sound/soc/codecs/es8316.c -@@ -811,12 +811,9 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client, - mutex_init(&es8316->lock); - - ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, -- IRQF_TRIGGER_HIGH | IRQF_ONESHOT, -+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, - "es8316", es8316); -- if (ret == 0) { -- /* Gets re-enabled by es8316_set_jack() */ -- disable_irq(es8316->irq); -- } else { -+ if (ret) { - dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); - es8316->irq = -ENXIO; - } -diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c -index 196b06898eeb2..07894ec5e7a61 100644 ---- a/sound/soc/codecs/lpass-rx-macro.c -+++ b/sound/soc/codecs/lpass-rx-macro.c -@@ -2188,7 +2188,7 @@ static int rx_macro_config_classh(struct snd_soc_component *component, - snd_soc_component_update_bits(component, - CDC_RX_CLSH_DECAY_CTRL, - CDC_RX_CLSH_DECAY_RATE_MASK, 0x0); -- snd_soc_component_update_bits(component, -+ snd_soc_component_write_field(component, - CDC_RX_RX1_RX_PATH_CFG0, - CDC_RX_RXn_CLSH_EN_MASK, 0x1); - break; -diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c -index f946ef65a4c19..f7018f2dd21fd 100644 ---- a/sound/soc/codecs/nau8824.c -+++ b/sound/soc/codecs/nau8824.c -@@ -8,6 +8,7 @@ - - #include <linux/module.h> - #include <linux/delay.h> -+#include <linux/dmi.h> - #include <linux/init.h> - #include <linux/i2c.h> - #include <linux/regmap.h> -@@ -27,6 +28,12 @@ - - #include "nau8824.h" - -+#define NAU8824_JD_ACTIVE_HIGH BIT(0) -+ -+static int nau8824_quirk; -+static int quirk_override = -1; -+module_param_named(quirk, quirk_override, uint, 0444); -+MODULE_PARM_DESC(quirk, "Board-specific quirk override"); - - static int nau8824_config_sysclk(struct nau8824 *nau8824, - int clk_id, unsigned int freq); -@@ -1845,6 +1852,34 @@ static int nau8824_read_device_properties(struct device *dev, - return 0; - } - -+/* Please keep this list alphabetically sorted */ -+static const struct dmi_system_id nau8824_quirk_table[] = { -+ { -+ /* Cyberbook T116 rugged tablet */ -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"), -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "20170531"), -+ }, -+ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH), -+ }, -+ {} -+}; -+ -+static void nau8824_check_quirks(void) -+{ -+ const struct dmi_system_id *dmi_id; -+ -+ if (quirk_override != -1) { -+ nau8824_quirk = quirk_override; -+ return; -+ } -+ -+ dmi_id = dmi_first_match(nau8824_quirk_table); -+ if (dmi_id) -+ nau8824_quirk = (unsigned long)dmi_id->driver_data; -+} -+ - static int nau8824_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) - { -@@ -1869,6 +1904,11 @@ static int nau8824_i2c_probe(struct i2c_client *i2c, - nau8824->irq = i2c->irq; - sema_init(&nau8824->jd_sem, 1); - -+ nau8824_check_quirks(); -+ -+ if (nau8824_quirk & NAU8824_JD_ACTIVE_HIGH) -+ nau8824->jkdet_polarity = 0; -+ - nau8824_print_device_properties(nau8824); - - ret = regmap_read(nau8824->regmap, NAU8824_REG_I2C_DEVICE_ID, &value); -diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c -index 943d7d933e81b..03f24edfe4f64 100644 ---- a/sound/soc/codecs/rk817_codec.c -+++ b/sound/soc/codecs/rk817_codec.c -@@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver); - MODULE_DESCRIPTION("ASoC RK817 codec driver"); - MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>"); - MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:rk817-codec"); -diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c -index fc0c83b73f099..93820561b9f5d 100644 ---- a/sound/soc/codecs/rt5651.c -+++ b/sound/soc/codecs/rt5651.c -@@ -2261,11 +2261,8 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, - - ret = devm_request_irq(&i2c->dev, rt5651->irq, rt5651_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING -- | IRQF_ONESHOT, "rt5651", rt5651); -- if (ret == 0) { -- /* Gets re-enabled by rt5651_set_jack() */ -- disable_irq(rt5651->irq); -- } else { -+ | IRQF_ONESHOT | IRQF_NO_AUTOEN, "rt5651", rt5651); -+ if (ret) { - dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n", - rt5651->irq, ret); - rt5651->irq = -ENXIO; -diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c -index 4a64cab99c55b..5ac2b1444694d 100644 ---- a/sound/soc/codecs/rt5682.c -+++ b/sound/soc/codecs/rt5682.c -@@ -46,6 +46,8 @@ static const struct reg_sequence patch_list[] = { - {RT5682_SAR_IL_CMD_1, 0x22b7}, - {RT5682_SAR_IL_CMD_3, 0x0365}, - {RT5682_SAR_IL_CMD_6, 0x0110}, -+ {RT5682_CHARGE_PUMP_1, 0x0210}, -+ {RT5682_HP_LOGIC_CTRL_2, 0x0007}, - }; - - void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev) -@@ -1515,21 +1517,29 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: -- snd_soc_component_write(component, -- RT5682_HP_LOGIC_CTRL_2, 0x0012); -- snd_soc_component_write(component, -- RT5682_HP_CTRL_2, 0x6000); -+ snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, -+ RT5682_HP_C2_DAC_AMP_MUTE, 0); -+ snd_soc_component_update_bits(component, RT5682_HP_LOGIC_CTRL_2, -+ RT5682_HP_LC2_SIG_SOUR2_MASK, RT5682_HP_LC2_SIG_SOUR2_REG); - snd_soc_component_update_bits(component, - RT5682_DEPOP_1, 0x60, 0x60); - snd_soc_component_update_bits(component, - RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080); -+ snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, -+ RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, -+ RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN); -+ usleep_range(5000, 10000); -+ snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, -+ RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_L); - break; - - case SND_SOC_DAPM_POST_PMD: -+ snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, -+ RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, 0); -+ snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, -+ RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_M); - snd_soc_component_update_bits(component, - RT5682_DEPOP_1, 0x60, 0x0); -- snd_soc_component_write(component, -- RT5682_HP_CTRL_2, 0x0000); - snd_soc_component_update_bits(component, - RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0000); - break; -@@ -1637,6 +1647,23 @@ static SOC_VALUE_ENUM_SINGLE_DECL(rt5682_adcdat_pin_enum, - static const struct snd_kcontrol_new rt5682_adcdat_pin_ctrl = - SOC_DAPM_ENUM("ADCDAT", rt5682_adcdat_pin_enum); - -+static const unsigned int rt5682_hpo_sig_out_values[] = { -+ 2, -+ 7, -+}; -+ -+static const char * const rt5682_hpo_sig_out_mode[] = { -+ "Legacy", -+ "OneBit", -+}; -+ -+static SOC_VALUE_ENUM_SINGLE_DECL(rt5682_hpo_sig_out_enum, -+ RT5682_HP_LOGIC_CTRL_2, 0, RT5682_HP_LC2_SIG_SOUR1_MASK, -+ rt5682_hpo_sig_out_mode, rt5682_hpo_sig_out_values); -+ -+static const struct snd_kcontrol_new rt5682_hpo_sig_demux = -+ SOC_DAPM_ENUM("HPO Signal Demux", rt5682_hpo_sig_out_enum); -+ - static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { - SND_SOC_DAPM_SUPPLY("LDO2", RT5682_PWR_ANLG_3, RT5682_PWR_LDO2_BIT, - 0, NULL, 0), -@@ -1820,6 +1847,10 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { - SND_SOC_DAPM_SWITCH("HPOR Playback", SND_SOC_NOPM, 0, 0, - &hpor_switch), - -+ SND_SOC_DAPM_OUT_DRV("HPO Legacy", SND_SOC_NOPM, 0, 0, NULL, 0), -+ SND_SOC_DAPM_OUT_DRV("HPO OneBit", SND_SOC_NOPM, 0, 0, NULL, 0), -+ SND_SOC_DAPM_DEMUX("HPO Signal Demux", SND_SOC_NOPM, 0, 0, &rt5682_hpo_sig_demux), -+ - /* CLK DET */ - SND_SOC_DAPM_SUPPLY("CLKDET SYS", RT5682_CLK_DET, - RT5682_SYS_CLK_DET_SFT, 0, NULL, 0), -@@ -1987,10 +2018,19 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { - {"HP Amp", NULL, "Charge Pump"}, - {"HP Amp", NULL, "CLKDET SYS"}, - {"HP Amp", NULL, "Vref1"}, -- {"HPOL Playback", "Switch", "HP Amp"}, -- {"HPOR Playback", "Switch", "HP Amp"}, -+ -+ {"HPO Signal Demux", NULL, "HP Amp"}, -+ -+ {"HPO Legacy", "Legacy", "HPO Signal Demux"}, -+ {"HPO OneBit", "OneBit", "HPO Signal Demux"}, -+ -+ {"HPOL Playback", "Switch", "HPO Legacy"}, -+ {"HPOR Playback", "Switch", "HPO Legacy"}, -+ - {"HPOL", NULL, "HPOL Playback"}, - {"HPOR", NULL, "HPOR Playback"}, -+ {"HPOL", NULL, "HPO OneBit"}, -+ {"HPOR", NULL, "HPO OneBit"}, - }; - - static int rt5682_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, -@@ -2800,6 +2840,8 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) - - for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) { - struct clk_init_data init = { }; -+ struct clk_parent_data parent_data; -+ const struct clk_hw *parent; - - dai_clk_hw = &rt5682->dai_clks_hw[i]; - -@@ -2807,17 +2849,17 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) - case RT5682_DAI_WCLK_IDX: - /* Make MCLK the parent of WCLK */ - if (rt5682->mclk) { -- init.parent_data = &(struct clk_parent_data){ -+ parent_data = (struct clk_parent_data){ - .fw_name = "mclk", - }; -+ init.parent_data = &parent_data; - init.num_parents = 1; - } - break; - case RT5682_DAI_BCLK_IDX: - /* Make WCLK the parent of BCLK */ -- init.parent_hws = &(const struct clk_hw *){ -- &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX] -- }; -+ parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]; -+ init.parent_hws = &parent; - init.num_parents = 1; - break; - default: -diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h -index b59221048ebf9..8e3244a62c160 100644 ---- a/sound/soc/codecs/rt5682.h -+++ b/sound/soc/codecs/rt5682.h -@@ -375,6 +375,14 @@ - #define RT5682_R_VOL_MASK (0x3f) - #define RT5682_R_VOL_SFT 0 - -+/* Headphone Amp Control 2 (0x0003) */ -+#define RT5682_HP_C2_DAC_AMP_MUTE_SFT 15 -+#define RT5682_HP_C2_DAC_AMP_MUTE (0x1 << 15) -+#define RT5682_HP_C2_DAC_L_EN_SFT 14 -+#define RT5682_HP_C2_DAC_L_EN (0x1 << 14) -+#define RT5682_HP_C2_DAC_R_EN_SFT 13 -+#define RT5682_HP_C2_DAC_R_EN (0x1 << 13) -+ - /*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/ - #define RT5682_G_HP (0xf << 8) - #define RT5682_G_HP_SFT 8 -@@ -1265,6 +1273,10 @@ - #define RT5682_HPA_CP_BIAS_6UA (0x3 << 2) - - /* Charge Pump Internal Register1 (0x0125) */ -+#define RT5682_CP_SW_SIZE_MASK (0x7 << 8) -+#define RT5682_CP_SW_SIZE_L (0x4 << 8) -+#define RT5682_CP_SW_SIZE_M (0x2 << 8) -+#define RT5682_CP_SW_SIZE_S (0x1 << 8) - #define RT5682_CP_CLK_HP_MASK (0x3 << 4) - #define RT5682_CP_CLK_HP_100KHZ (0x0 << 4) - #define RT5682_CP_CLK_HP_200KHZ (0x1 << 4) -@@ -1315,6 +1327,14 @@ - #define RT5682_DEB_STO_DAC_MASK (0x7 << 4) - #define RT5682_DEB_80_MS (0x0 << 4) - -+/* HP Behavior Logic Control 2 (0x01db) */ -+#define RT5682_HP_LC2_SIG_SOUR2_MASK (0x1 << 4) -+#define RT5682_HP_LC2_SIG_SOUR2_REG (0x1 << 4) -+#define RT5682_HP_LC2_SIG_SOUR2_DC_CAL (0x0 << 4) -+#define RT5682_HP_LC2_SIG_SOUR1_MASK (0x7) -+#define RT5682_HP_LC2_SIG_SOUR1_1BIT (0x7) -+#define RT5682_HP_LC2_SIG_SOUR1_LEGA (0x2) -+ - /* SAR ADC Inline Command Control 1 (0x0210) */ - #define RT5682_SAR_BUTT_DET_MASK (0x1 << 15) - #define RT5682_SAR_BUTT_DET_EN (0x1 << 15) -diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c -index d885ced34f606..bc5d68c53e5ab 100644 ---- a/sound/soc/codecs/wcd9335.c -+++ b/sound/soc/codecs/wcd9335.c -@@ -4859,7 +4859,7 @@ static int wcd9335_codec_probe(struct snd_soc_component *component) - - snd_soc_component_init_regmap(component, wcd->regmap); - /* Class-H Init*/ -- wcd->clsh_ctrl = wcd_clsh_ctrl_alloc(component, wcd->version); -+ wcd->clsh_ctrl = wcd_clsh_ctrl_alloc(component, WCD9335); - if (IS_ERR(wcd->clsh_ctrl)) - return PTR_ERR(wcd->clsh_ctrl); - -diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c -index c496b359f2f40..e63c6b723d76c 100644 ---- a/sound/soc/codecs/wcd934x.c -+++ b/sound/soc/codecs/wcd934x.c -@@ -1896,9 +1896,8 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream, - } - - wcd->dai[dai->id].sconfig.rate = params_rate(params); -- wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); - -- return 0; -+ return wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); - } - - static int wcd934x_hw_free(struct snd_pcm_substream *substream, -@@ -3257,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, - int value = ucontrol->value.integer.value[0]; - int sel; - -+ if (wcd->comp_enabled[comp] == value) -+ return 0; -+ - wcd->comp_enabled[comp] = value; - sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER : - WCD934X_HPH_GAIN_SRC_SEL_REGISTER; -@@ -3280,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, - case COMPANDER_8: - break; - default: -- break; -+ return 0; - } - -- return 0; -+ return 1; - } - - static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc, -@@ -3327,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc, - return 0; - } - -+static int slim_rx_mux_to_dai_id(int mux) -+{ -+ int aif_id; -+ -+ switch (mux) { -+ case 1: -+ aif_id = AIF1_PB; -+ break; -+ case 2: -+ aif_id = AIF2_PB; -+ break; -+ case 3: -+ aif_id = AIF3_PB; -+ break; -+ case 4: -+ aif_id = AIF4_PB; -+ break; -+ default: -+ aif_id = -1; -+ break; -+ } -+ -+ return aif_id; -+} -+ - static int slim_rx_mux_put(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *ucontrol) - { -@@ -3334,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, - struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev); - struct soc_enum *e = (struct soc_enum *)kc->private_value; - struct snd_soc_dapm_update *update = NULL; -+ struct wcd934x_slim_ch *ch, *c; - u32 port_id = w->shift; -+ bool found = false; -+ int mux_idx; -+ int prev_mux_idx = wcd->rx_port_value[port_id]; -+ int aif_id; - -- if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) -- return 0; -+ mux_idx = ucontrol->value.enumerated.item[0]; - -- wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; -+ if (mux_idx == prev_mux_idx) -+ return 0; - -- switch (wcd->rx_port_value[port_id]) { -+ switch(mux_idx) { - case 0: -- list_del_init(&wcd->rx_chs[port_id].list); -- break; -- case 1: -- list_add_tail(&wcd->rx_chs[port_id].list, -- &wcd->dai[AIF1_PB].slim_ch_list); -- break; -- case 2: -- list_add_tail(&wcd->rx_chs[port_id].list, -- &wcd->dai[AIF2_PB].slim_ch_list); -- break; -- case 3: -- list_add_tail(&wcd->rx_chs[port_id].list, -- &wcd->dai[AIF3_PB].slim_ch_list); -+ aif_id = slim_rx_mux_to_dai_id(prev_mux_idx); -+ if (aif_id < 0) -+ return 0; -+ -+ list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) { -+ if (ch->port == port_id + WCD934X_RX_START) { -+ found = true; -+ list_del_init(&ch->list); -+ break; -+ } -+ } -+ if (!found) -+ return 0; -+ - break; -- case 4: -- list_add_tail(&wcd->rx_chs[port_id].list, -- &wcd->dai[AIF4_PB].slim_ch_list); -+ case 1 ... 4: -+ aif_id = slim_rx_mux_to_dai_id(mux_idx); -+ if (aif_id < 0) -+ return 0; -+ -+ if (list_empty(&wcd->rx_chs[port_id].list)) { -+ list_add_tail(&wcd->rx_chs[port_id].list, -+ &wcd->dai[aif_id].slim_ch_list); -+ } else { -+ dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id); -+ return 0; -+ } - break; -+ - default: -- dev_err(wcd->dev, "Unknown AIF %d\n", -- wcd->rx_port_value[port_id]); -+ dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx); - goto err; - } - -+ wcd->rx_port_value[port_id] = mux_idx; - snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id], - e, update); - -- return 0; -+ return 1; - err: - return -EINVAL; - } -@@ -3816,6 +3859,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, - struct soc_mixer_control *mixer = - (struct soc_mixer_control *)kc->private_value; - int enable = ucontrol->value.integer.value[0]; -+ struct wcd934x_slim_ch *ch, *c; - int dai_id = widget->shift; - int port_id = mixer->shift; - -@@ -3823,17 +3867,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, - if (enable == wcd->tx_port_value[port_id]) - return 0; - -- wcd->tx_port_value[port_id] = enable; -- -- if (enable) -- list_add_tail(&wcd->tx_chs[port_id].list, -- &wcd->dai[dai_id].slim_ch_list); -- else -- list_del_init(&wcd->tx_chs[port_id].list); -+ if (enable) { -+ if (list_empty(&wcd->tx_chs[port_id].list)) { -+ list_add_tail(&wcd->tx_chs[port_id].list, -+ &wcd->dai[dai_id].slim_ch_list); -+ } else { -+ dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id); -+ return 0; -+ } -+ } else { -+ bool found = false; -+ -+ list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) { -+ if (ch->port == port_id) { -+ found = true; -+ list_del_init(&wcd->tx_chs[port_id].list); -+ break; -+ } -+ } -+ if (!found) -+ return 0; -+ } - -+ wcd->tx_port_value[port_id] = enable; - snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update); - -- return 0; -+ return 1; - } - - static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = { -diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c -index 52de7d14b1398..67151c7770c65 100644 ---- a/sound/soc/codecs/wcd938x.c -+++ b/sound/soc/codecs/wcd938x.c -@@ -1174,6 +1174,9 @@ static bool wcd938x_readonly_register(struct device *dev, unsigned int reg) - case WCD938X_DIGITAL_INTR_STATUS_0: - case WCD938X_DIGITAL_INTR_STATUS_1: - case WCD938X_DIGITAL_INTR_STATUS_2: -+ case WCD938X_DIGITAL_INTR_CLEAR_0: -+ case WCD938X_DIGITAL_INTR_CLEAR_1: -+ case WCD938X_DIGITAL_INTR_CLEAR_2: - case WCD938X_DIGITAL_SWR_HM_TEST_0: - case WCD938X_DIGITAL_SWR_HM_TEST_1: - case WCD938X_DIGITAL_EFUSE_T_DATA_0: -diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c -index 2da4a5fa7a18d..564b78f3cdd0a 100644 ---- a/sound/soc/codecs/wsa881x.c -+++ b/sound/soc/codecs/wsa881x.c -@@ -772,7 +772,8 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc, - - usleep_range(1000, 1010); - } -- return 0; -+ -+ return 1; - } - - static int wsa881x_get_port(struct snd_kcontrol *kcontrol, -@@ -816,15 +817,22 @@ static int wsa881x_set_port(struct snd_kcontrol *kcontrol, - (struct soc_mixer_control *)kcontrol->private_value; - int portidx = mixer->reg; - -- if (ucontrol->value.integer.value[0]) -+ if (ucontrol->value.integer.value[0]) { -+ if (data->port_enable[portidx]) -+ return 0; -+ - data->port_enable[portidx] = true; -- else -+ } else { -+ if (!data->port_enable[portidx]) -+ return 0; -+ - data->port_enable[portidx] = false; -+ } - - if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */ - wsa881x_boost_ctrl(comp, data->port_enable[portidx]); - -- return 0; -+ return 1; - } - - static const char * const smart_boost_lvl_text[] = { -diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c -index 6b06248a9327a..f10496206ceed 100644 ---- a/sound/soc/intel/boards/sof_sdw.c -+++ b/sound/soc/intel/boards/sof_sdw.c -@@ -213,6 +213,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { - SOF_RT715_DAI_ID_FIX | - SOF_SDW_FOUR_SPK), - }, -+ { -+ .callback = sof_sdw_quirk_cb, -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45") -+ }, -+ .driver_data = (void *)(SOF_SDW_TGL_HDMI | -+ RT711_JD2 | -+ SOF_RT715_DAI_ID_FIX), -+ }, - /* AlderLake devices */ - { - .callback = sof_sdw_quirk_cb, -diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c -index 785d5f5f8a9c9..11801b905ecc2 100644 ---- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c -+++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c -@@ -156,6 +156,15 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { - } - }; - -+static const struct snd_soc_acpi_adr_device rt1316_1_single_adr[] = { -+ { -+ .adr = 0x000131025D131601ull, -+ .num_endpoints = 1, -+ .endpoints = &single_endpoint, -+ .name_prefix = "rt1316-1" -+ } -+}; -+ - static const struct snd_soc_acpi_adr_device rt1316_1_group1_adr[] = { - { - .adr = 0x000131025D131601ull, /* unique ID is set for some reason */ -@@ -320,6 +329,25 @@ static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca[] = { - {} - }; - -+static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca_mono[] = { -+ { -+ .mask = BIT(0), -+ .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), -+ .adr_d = rt711_sdca_0_adr, -+ }, -+ { -+ .mask = BIT(1), -+ .num_adr = ARRAY_SIZE(rt1316_1_single_adr), -+ .adr_d = rt1316_1_single_adr, -+ }, -+ { -+ .mask = BIT(3), -+ .num_adr = ARRAY_SIZE(rt714_3_adr), -+ .adr_d = rt714_3_adr, -+ }, -+ {} -+}; -+ - static const struct snd_soc_acpi_codecs tgl_max98373_amp = { - .num_codecs = 1, - .codecs = {"MX98373"} -@@ -412,6 +440,19 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { - .drv_name = "sof_sdw", - .sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg", - }, -+ { -+ /* -+ * link_mask should be 0xB, but all links are enabled by BIOS. -+ * This entry will be selected if there is no rt1316 amplifier exposed -+ * on link2 since it will fail to match the above entry. -+ */ -+ -+ .link_mask = 0xF, /* 4 active links required */ -+ .links = tgl_3_in_1_sdca_mono, -+ .drv_name = "sof_sdw", -+ .sof_tplg_filename = "sof-tgl-rt711-l0-rt1316-l1-mono-rt714-l3.tplg", -+ }, -+ - { - .link_mask = 0x3, /* rt711 on link 0 and 1 rt1308 on link 1 */ - .links = tgl_hp, -diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c -index de09f67c04502..a3fa8efc8f81c 100644 ---- a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c -+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c -@@ -1040,8 +1040,10 @@ static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev) - } - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) -+ if (!priv) { -+ of_node_put(platform_node); - return -ENOMEM; -+ } - - snd_soc_card_set_drvdata(card, priv); - -@@ -1049,6 +1051,8 @@ static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev) - if (ret) - dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", - __func__, ret); -+ -+ of_node_put(platform_node); - return ret; - } - -diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c -index 46f365528d501..b74b67720ef43 100644 ---- a/sound/soc/qcom/qdsp6/q6asm-dai.c -+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c -@@ -269,9 +269,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, - - if (ret < 0) { - dev_err(dev, "%s: q6asm_open_write failed\n", __func__); -- q6asm_audio_client_free(prtd->audio_client); -- prtd->audio_client = NULL; -- return -ENOMEM; -+ goto open_err; - } - - prtd->session_id = q6asm_get_session_id(prtd->audio_client); -@@ -279,7 +277,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, - prtd->session_id, substream->stream); - if (ret) { - dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret); -- return ret; -+ goto routing_err; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -@@ -301,10 +299,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, - } - if (ret < 0) - dev_info(dev, "%s: CMD Format block failed\n", __func__); -+ else -+ prtd->state = Q6ASM_STREAM_RUNNING; - -- prtd->state = Q6ASM_STREAM_RUNNING; -+ return ret; - -- return 0; -+routing_err: -+ q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); -+open_err: -+ q6asm_unmap_memory_regions(substream->stream, prtd->audio_client); -+ q6asm_audio_client_free(prtd->audio_client); -+ prtd->audio_client = NULL; -+ -+ return ret; - } - - static int q6asm_dai_trigger(struct snd_soc_component *component, -diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c -index 3390ebef9549d..18c90bb4922be 100644 ---- a/sound/soc/qcom/qdsp6/q6routing.c -+++ b/sound/soc/qcom/qdsp6/q6routing.c -@@ -492,9 +492,15 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, - struct session_data *session = &data->sessions[session_id]; - - if (ucontrol->value.integer.value[0]) { -+ if (session->port_id == be_id) -+ return 0; -+ - session->port_id = be_id; - snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update); - } else { -+ if (session->port_id == -1 || session->port_id != be_id) -+ return 0; -+ - session->port_id = -1; - snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update); - } -diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c -index 978bd0406729a..6a8fe0da7670b 100644 ---- a/sound/soc/sh/rcar/core.c -+++ b/sound/soc/sh/rcar/core.c -@@ -1225,6 +1225,7 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name - if (i < 0) { - dev_err(dev, "strange node numbering (%s)", - of_node_full_name(node)); -+ of_node_put(np); - return 0; - } - i++; -diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c -index 16c6e0265749b..03e0d4eca7815 100644 ---- a/sound/soc/sh/rcar/dma.c -+++ b/sound/soc/sh/rcar/dma.c -@@ -102,7 +102,7 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, - struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); - - if (dmaen->chan) -- dmaengine_terminate_sync(dmaen->chan); -+ dmaengine_terminate_async(dmaen->chan); - - return 0; - } -diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c -index 59d07648a7e7f..0479bb0005abd 100644 ---- a/sound/soc/soc-dapm.c -+++ b/sound/soc/soc-dapm.c -@@ -2557,8 +2557,13 @@ static struct snd_soc_dapm_widget *dapm_find_widget( - return NULL; - } - --static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, -- const char *pin, int status) -+/* -+ * set the DAPM pin status: -+ * returns 1 when the value has been updated, 0 when unchanged, or a negative -+ * error code; called from kcontrol put callback -+ */ -+static int __snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, -+ const char *pin, int status) - { - struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); - int ret = 0; -@@ -2584,6 +2589,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, - return ret; - } - -+/* -+ * similar as __snd_soc_dapm_set_pin(), but returns 0 when successful; -+ * called from several API functions below -+ */ -+static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, -+ const char *pin, int status) -+{ -+ int ret = __snd_soc_dapm_set_pin(dapm, pin, status); -+ -+ return ret < 0 ? ret : 0; -+} -+ - /** - * snd_soc_dapm_sync_unlocked - scan and power dapm paths - * @dapm: DAPM context -@@ -3587,10 +3604,10 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, - const char *pin = (const char *)kcontrol->private_value; - int ret; - -- if (ucontrol->value.integer.value[0]) -- ret = snd_soc_dapm_enable_pin(&card->dapm, pin); -- else -- ret = snd_soc_dapm_disable_pin(&card->dapm, pin); -+ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); -+ ret = __snd_soc_dapm_set_pin(&card->dapm, pin, -+ !!ucontrol->value.integer.value[0]); -+ mutex_unlock(&card->dapm_mutex); - - snd_soc_dapm_sync(&card->dapm); - return ret; -diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c -index f6e5ac3e03140..7459956d62b99 100644 ---- a/sound/soc/soc-topology.c -+++ b/sound/soc/soc-topology.c -@@ -2674,6 +2674,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load); - /* remove dynamic controls from the component driver */ - int snd_soc_tplg_component_remove(struct snd_soc_component *comp) - { -+ struct snd_card *card = comp->card->snd_card; - struct snd_soc_dobj *dobj, *next_dobj; - int pass = SOC_TPLG_PASS_END; - -@@ -2681,6 +2682,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp) - while (pass >= SOC_TPLG_PASS_START) { - - /* remove mixer controls */ -+ down_write(&card->controls_rwsem); - list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, - list) { - -@@ -2719,6 +2721,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp) - break; - } - } -+ up_write(&card->controls_rwsem); - pass--; - } - -diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c -index 30025d3c16b6e..0862ff8b66273 100644 ---- a/sound/soc/sof/intel/hda-bus.c -+++ b/sound/soc/sof/intel/hda-bus.c -@@ -10,6 +10,8 @@ - #include <linux/io.h> - #include <sound/hdaudio.h> - #include <sound/hda_i915.h> -+#include <sound/hda_codec.h> -+#include <sound/hda_register.h> - #include "../sof-priv.h" - #include "hda.h" - -@@ -21,6 +23,18 @@ - #endif - - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -+static void update_codec_wake_enable(struct hdac_bus *bus, unsigned int addr, bool link_power) -+{ -+ unsigned int mask = snd_hdac_chip_readw(bus, WAKEEN); -+ -+ if (link_power) -+ mask &= ~BIT(addr); -+ else -+ mask |= BIT(addr); -+ -+ snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask); -+} -+ - static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable) - { - struct hdac_bus *bus = codec->bus; -@@ -41,6 +55,9 @@ static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable) - */ - if (codec->addr == HDA_IDISP_ADDR && !enable) - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); -+ -+ /* WAKEEN needs to be set for disabled links */ -+ update_codec_wake_enable(bus, codec->addr, enable); - } - - static const struct hdac_bus_ops bus_core_ops = { -diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c -index c1f9f0f584647..6704dbcd101cd 100644 ---- a/sound/soc/sof/intel/hda-dai.c -+++ b/sound/soc/sof/intel/hda-dai.c -@@ -68,6 +68,7 @@ static struct hdac_ext_stream * - return NULL; - } - -+ spin_lock_irq(&bus->reg_lock); - list_for_each_entry(stream, &bus->stream_list, list) { - struct hdac_ext_stream *hstream = - stream_to_hdac_ext_stream(stream); -@@ -107,12 +108,12 @@ static struct hdac_ext_stream * - * is updated in snd_hdac_ext_stream_decouple(). - */ - if (!res->decoupled) -- snd_hdac_ext_stream_decouple(bus, res, true); -- spin_lock_irq(&bus->reg_lock); -+ snd_hdac_ext_stream_decouple_locked(bus, res, true); -+ - res->link_locked = 1; - res->link_substream = substream; -- spin_unlock_irq(&bus->reg_lock); - } -+ spin_unlock_irq(&bus->reg_lock); - - return res; - } -diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c -index 623cf291e2074..262a70791a8f8 100644 ---- a/sound/soc/sof/intel/hda-dsp.c -+++ b/sound/soc/sof/intel/hda-dsp.c -@@ -623,8 +623,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) - hda_dsp_ipc_int_disable(sdev); - - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -- if (runtime_suspend) -- hda_codec_jack_wake_enable(sdev, true); -+ hda_codec_jack_wake_enable(sdev, runtime_suspend); - - /* power down all hda link */ - snd_hdac_ext_bus_link_power_down_all(bus); -diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c -index f60e2c57d3d0c..ef92cca7ae01e 100644 ---- a/sound/soc/sof/intel/hda.c -+++ b/sound/soc/sof/intel/hda.c -@@ -696,6 +696,20 @@ skip_soundwire: - return 0; - } - -+static void hda_check_for_state_change(struct snd_sof_dev *sdev) -+{ -+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) -+ struct hdac_bus *bus = sof_to_bus(sdev); -+ unsigned int codec_mask; -+ -+ codec_mask = snd_hdac_chip_readw(bus, STATESTS); -+ if (codec_mask) { -+ hda_codec_jack_check(sdev); -+ snd_hdac_chip_writew(bus, STATESTS, codec_mask); -+ } -+#endif -+} -+ - static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context) - { - struct snd_sof_dev *sdev = context; -@@ -737,6 +751,8 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) - if (hda_sdw_check_wakeen_irq(sdev)) - hda_sdw_process_wakeen(sdev); - -+ hda_check_for_state_change(sdev); -+ - /* enable GIE interrupt */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - SOF_HDA_INTCTL, -diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c -index cc9585bfa4e9f..1bb2dcf37ffe9 100644 ---- a/sound/soc/sof/topology.c -+++ b/sound/soc/sof/topology.c -@@ -2598,6 +2598,15 @@ static int sof_widget_unload(struct snd_soc_component *scomp, - - /* power down the pipeline schedule core */ - pipeline = swidget->private; -+ -+ /* -+ * Runtime PM should still function normally if topology loading fails and -+ * it's components are unloaded. Do not power down the primary core so that the -+ * CTX_SAVE IPC can succeed during runtime suspend. -+ */ -+ if (pipeline->core == SOF_DSP_PRIMARY_CORE) -+ break; -+ - ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core); - if (ret < 0) - dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n", -diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c -index 6254bacad6eb7..717f45a83445c 100644 ---- a/sound/soc/stm/stm32_i2s.c -+++ b/sound/soc/stm/stm32_i2s.c -@@ -700,7 +700,7 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, - if (ret < 0) - return ret; - -- nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1); -+ nb_bits = frame_len * (FIELD_GET(I2S_CGFR_CHLEN, cgfr) + 1); - ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, - (nb_bits * rate)); - if (ret) -diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c -index 8ee9a77bd83d3..a74c980ee7753 100644 ---- a/sound/soc/tegra/tegra186_dspk.c -+++ b/sound/soc/tegra/tegra186_dspk.c -@@ -26,51 +26,162 @@ static const struct reg_default tegra186_dspk_reg_defaults[] = { - { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, - }; - --static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol, -+static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); - struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); - -- if (strstr(kcontrol->id.name, "FIFO Threshold")) -- ucontrol->value.integer.value[0] = dspk->rx_fifo_th; -- else if (strstr(kcontrol->id.name, "OSR Value")) -- ucontrol->value.integer.value[0] = dspk->osr_val; -- else if (strstr(kcontrol->id.name, "LR Polarity Select")) -- ucontrol->value.integer.value[0] = dspk->lrsel; -- else if (strstr(kcontrol->id.name, "Channel Select")) -- ucontrol->value.integer.value[0] = dspk->ch_sel; -- else if (strstr(kcontrol->id.name, "Mono To Stereo")) -- ucontrol->value.integer.value[0] = dspk->mono_to_stereo; -- else if (strstr(kcontrol->id.name, "Stereo To Mono")) -- ucontrol->value.integer.value[0] = dspk->stereo_to_mono; -+ ucontrol->value.integer.value[0] = dspk->rx_fifo_th; - - return 0; - } - --static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, -+static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); - struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -- int val = ucontrol->value.integer.value[0]; -- -- if (strstr(kcontrol->id.name, "FIFO Threshold")) -- dspk->rx_fifo_th = val; -- else if (strstr(kcontrol->id.name, "OSR Value")) -- dspk->osr_val = val; -- else if (strstr(kcontrol->id.name, "LR Polarity Select")) -- dspk->lrsel = val; -- else if (strstr(kcontrol->id.name, "Channel Select")) -- dspk->ch_sel = val; -- else if (strstr(kcontrol->id.name, "Mono To Stereo")) -- dspk->mono_to_stereo = val; -- else if (strstr(kcontrol->id.name, "Stereo To Mono")) -- dspk->stereo_to_mono = val; -+ int value = ucontrol->value.integer.value[0]; -+ -+ if (value == dspk->rx_fifo_th) -+ return 0; -+ -+ dspk->rx_fifo_th = value; -+ -+ return 1; -+} -+ -+static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ -+ ucontrol->value.enumerated.item[0] = dspk->osr_val; - - return 0; - } - -+static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dspk->osr_val) -+ return 0; -+ -+ dspk->osr_val = value; -+ -+ return 1; -+} -+ -+static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ -+ ucontrol->value.enumerated.item[0] = dspk->lrsel; -+ -+ return 0; -+} -+ -+static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dspk->lrsel) -+ return 0; -+ -+ dspk->lrsel = value; -+ -+ return 1; -+} -+ -+static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ -+ ucontrol->value.enumerated.item[0] = dspk->ch_sel; -+ -+ return 0; -+} -+ -+static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dspk->ch_sel) -+ return 0; -+ -+ dspk->ch_sel = value; -+ -+ return 1; -+} -+ -+static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ -+ ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo; -+ -+ return 0; -+} -+ -+static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dspk->mono_to_stereo) -+ return 0; -+ -+ dspk->mono_to_stereo = value; -+ -+ return 1; -+} -+ -+static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ -+ ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono; -+ -+ return 0; -+} -+ -+static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); -+ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dspk->stereo_to_mono) -+ return 0; -+ -+ dspk->stereo_to_mono = value; -+ -+ return 1; -+} -+ - static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) - { - struct tegra186_dspk *dspk = dev_get_drvdata(dev); -@@ -279,17 +390,19 @@ static const struct soc_enum tegra186_dspk_lrsel_enum = - static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { - SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, - TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, -- tegra186_dspk_get_control, tegra186_dspk_put_control), -+ tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th), - SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, -- tegra186_dspk_get_control, tegra186_dspk_put_control), -+ tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val), - SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, -- tegra186_dspk_get_control, tegra186_dspk_put_control), -+ tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel), - SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, -- tegra186_dspk_get_control, tegra186_dspk_put_control), -+ tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel), - SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, -- tegra186_dspk_get_control, tegra186_dspk_put_control), -+ tegra186_dspk_get_mono_to_stereo, -+ tegra186_dspk_put_mono_to_stereo), - SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, -- tegra186_dspk_get_control, tegra186_dspk_put_control), -+ tegra186_dspk_get_stereo_to_mono, -+ tegra186_dspk_put_stereo_to_mono), - }; - - static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { -diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c -index bcccdf3ddc528..1a2e868a62209 100644 ---- a/sound/soc/tegra/tegra210_admaif.c -+++ b/sound/soc/tegra/tegra210_admaif.c -@@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { - .trigger = tegra_admaif_trigger, - }; - --static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); -+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; -+ -+ ucontrol->value.enumerated.item[0] = -+ admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; -+ -+ return 0; -+} -+ -+static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); -+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]) -+ return 0; -+ -+ admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; -+ -+ return 1; -+} -+ -+static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); -+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; -+ -+ ucontrol->value.enumerated.item[0] = -+ admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; -+ -+ return 0; -+} -+ -+static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); - struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]) -+ return 0; -+ -+ admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; -+ -+ return 1; -+} -+ -+static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); - struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); -- long *uctl_val = &ucontrol->value.integer.value[0]; -+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; - -- if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) -- *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; -- else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) -- *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; -- else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) -- *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; -- else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) -- *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; -+ ucontrol->value.enumerated.item[0] = -+ admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; - - return 0; - } - --static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); - struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]) -+ return 0; -+ -+ admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; -+ -+ return 1; -+} -+ -+static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); - struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); -- int value = ucontrol->value.integer.value[0]; -+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; - -- if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) -- admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; -- else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) -- admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; -- else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) -- admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; -- else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) -- admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; -+ ucontrol->value.enumerated.item[0] = -+ admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; - - return 0; - } - -+static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); -+ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]) -+ return 0; -+ -+ admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; -+ -+ return 1; -+} -+ - static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) - { - struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); -@@ -559,17 +635,21 @@ static const char * const tegra_admaif_mono_conv_text[] = { - } - - #define TEGRA_ADMAIF_CIF_CTRL(reg) \ -- NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ -- tegra_admaif_get_control, tegra_admaif_put_control, \ -+ NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \ -+ tegra210_admaif_pget_mono_to_stereo, \ -+ tegra210_admaif_pput_mono_to_stereo, \ - tegra_admaif_mono_conv_text), \ -- NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ -- tegra_admaif_get_control, tegra_admaif_put_control, \ -+ NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \ -+ tegra210_admaif_pget_stereo_to_mono, \ -+ tegra210_admaif_pput_stereo_to_mono, \ - tegra_admaif_stereo_conv_text), \ -- NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ -- tegra_admaif_get_control, tegra_admaif_put_control, \ -+ NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ -+ tegra210_admaif_cget_mono_to_stereo, \ -+ tegra210_admaif_cput_mono_to_stereo, \ - tegra_admaif_mono_conv_text), \ -- NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ -- tegra_admaif_get_control, tegra_admaif_put_control, \ -+ NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ -+ tegra210_admaif_cget_stereo_to_mono, \ -+ tegra210_admaif_cput_stereo_to_mono, \ - tegra_admaif_stereo_conv_text) - - static struct snd_kcontrol_new tegra210_admaif_controls[] = { -diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c -index 66287a7c9865d..1b2f7cb8c6adc 100644 ---- a/sound/soc/tegra/tegra210_ahub.c -+++ b/sound/soc/tegra/tegra210_ahub.c -@@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, - unsigned int *item = uctl->value.enumerated.item; - unsigned int value = e->values[item[0]]; - unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; -+ int change = 0; - - if (item[0] >= e->items) - return -EINVAL; -@@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, - - /* Update widget power if state has changed */ - if (snd_soc_component_test_bits(cmpnt, update[i].reg, -- update[i].mask, update[i].val)) -- snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, -- &update[i]); -+ update[i].mask, -+ update[i].val)) -+ change |= snd_soc_dapm_mux_update_power(dapm, kctl, -+ item[0], e, -+ &update[i]); - } - -- return 0; -+ return change; - } - - static struct snd_soc_dai_driver tegra210_ahub_dais[] = { -diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c -index b096478cd2ef0..db95794530f46 100644 ---- a/sound/soc/tegra/tegra210_dmic.c -+++ b/sound/soc/tegra/tegra210_dmic.c -@@ -156,51 +156,162 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, - return 0; - } - --static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, -+static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ -+ ucontrol->value.integer.value[0] = dmic->boost_gain; -+ -+ return 0; -+} -+ -+static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ int value = ucontrol->value.integer.value[0]; -+ -+ if (value == dmic->boost_gain) -+ return 0; -+ -+ dmic->boost_gain = value; -+ -+ return 1; -+} -+ -+static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ -+ ucontrol->value.enumerated.item[0] = dmic->ch_select; -+ -+ return 0; -+} -+ -+static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dmic->ch_select) -+ return 0; -+ -+ dmic->ch_select = value; -+ -+ return 1; -+} -+ -+static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ -+ ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo; -+ -+ return 0; -+} -+ -+static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dmic->mono_to_stereo) -+ return 0; -+ -+ dmic->mono_to_stereo = value; -+ -+ return 1; -+} -+ -+static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ -+ ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono; -+ -+ return 0; -+} -+ -+static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dmic->stereo_to_mono) -+ return 0; -+ -+ dmic->stereo_to_mono = value; -+ -+ return 1; -+} -+ -+static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); - struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); - -- if (strstr(kcontrol->id.name, "Boost Gain Volume")) -- ucontrol->value.integer.value[0] = dmic->boost_gain; -- else if (strstr(kcontrol->id.name, "Channel Select")) -- ucontrol->value.integer.value[0] = dmic->ch_select; -- else if (strstr(kcontrol->id.name, "Mono To Stereo")) -- ucontrol->value.integer.value[0] = dmic->mono_to_stereo; -- else if (strstr(kcontrol->id.name, "Stereo To Mono")) -- ucontrol->value.integer.value[0] = dmic->stereo_to_mono; -- else if (strstr(kcontrol->id.name, "OSR Value")) -- ucontrol->value.integer.value[0] = dmic->osr_val; -- else if (strstr(kcontrol->id.name, "LR Polarity Select")) -- ucontrol->value.integer.value[0] = dmic->lrsel; -+ ucontrol->value.enumerated.item[0] = dmic->osr_val; - - return 0; - } - --static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, -+static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); - struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -- int value = ucontrol->value.integer.value[0]; -+ unsigned int value = ucontrol->value.enumerated.item[0]; - -- if (strstr(kcontrol->id.name, "Boost Gain Volume")) -- dmic->boost_gain = value; -- else if (strstr(kcontrol->id.name, "Channel Select")) -- dmic->ch_select = ucontrol->value.integer.value[0]; -- else if (strstr(kcontrol->id.name, "Mono To Stereo")) -- dmic->mono_to_stereo = value; -- else if (strstr(kcontrol->id.name, "Stereo To Mono")) -- dmic->stereo_to_mono = value; -- else if (strstr(kcontrol->id.name, "OSR Value")) -- dmic->osr_val = value; -- else if (strstr(kcontrol->id.name, "LR Polarity Select")) -- dmic->lrsel = value; -+ if (value == dmic->osr_val) -+ return 0; -+ -+ dmic->osr_val = value; -+ -+ return 1; -+} -+ -+static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ -+ ucontrol->value.enumerated.item[0] = dmic->lrsel; - - return 0; - } - -+static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == dmic->lrsel) -+ return 0; -+ -+ dmic->lrsel = value; -+ -+ return 1; -+} -+ - static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { - .hw_params = tegra210_dmic_hw_params, - }; -@@ -287,19 +398,22 @@ static const struct soc_enum tegra210_dmic_lrsel_enum = - - static const struct snd_kcontrol_new tegra210_dmic_controls[] = { - SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, -- tegra210_dmic_get_control, tegra210_dmic_put_control), -+ tegra210_dmic_get_boost_gain, -+ tegra210_dmic_put_boost_gain), - SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, -- tegra210_dmic_get_control, tegra210_dmic_put_control), -+ tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select), - SOC_ENUM_EXT("Mono To Stereo", -- tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, -- tegra210_dmic_put_control), -+ tegra210_dmic_mono_conv_enum, -+ tegra210_dmic_get_mono_to_stereo, -+ tegra210_dmic_put_mono_to_stereo), - SOC_ENUM_EXT("Stereo To Mono", -- tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, -- tegra210_dmic_put_control), -+ tegra210_dmic_stereo_conv_enum, -+ tegra210_dmic_get_stereo_to_mono, -+ tegra210_dmic_put_stereo_to_mono), - SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, -- tegra210_dmic_get_control, tegra210_dmic_put_control), -+ tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val), - SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, -- tegra210_dmic_get_control, tegra210_dmic_put_control), -+ tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel), - }; - - static const struct snd_soc_component_driver tegra210_dmic_compnt = { -diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c -index 45f31ccb49d89..9552bbb939dd1 100644 ---- a/sound/soc/tegra/tegra210_i2s.c -+++ b/sound/soc/tegra/tegra210_i2s.c -@@ -302,85 +302,235 @@ static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai, - return 0; - } - --static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, -- unsigned int ratio) -+static int tegra210_i2s_get_loopback(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { -- struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); - -- i2s->bclk_ratio = ratio; -+ ucontrol->value.integer.value[0] = i2s->loopback; - - return 0; - } - --static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+static int tegra210_i2s_put_loopback(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ int value = ucontrol->value.integer.value[0]; -+ -+ if (value == i2s->loopback) -+ return 0; -+ -+ i2s->loopback = value; -+ -+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK, -+ i2s->loopback << I2S_CTRL_LPBK_SHIFT); -+ -+ return 1; -+} -+ -+static int tegra210_i2s_get_fsync_width(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); - struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -- long *uctl_val = &ucontrol->value.integer.value[0]; -- -- if (strstr(kcontrol->id.name, "Loopback")) -- *uctl_val = i2s->loopback; -- else if (strstr(kcontrol->id.name, "FSYNC Width")) -- *uctl_val = i2s->fsync_width; -- else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) -- *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH]; -- else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) -- *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH]; -- else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) -- *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH]; -- else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) -- *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH]; -- else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) -- *uctl_val = i2s->rx_fifo_th; -- else if (strstr(kcontrol->id.name, "BCLK Ratio")) -- *uctl_val = i2s->bclk_ratio; -+ -+ ucontrol->value.integer.value[0] = i2s->fsync_width; - - return 0; - } - --static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+static int tegra210_i2s_put_fsync_width(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) - { - struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); - struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); - int value = ucontrol->value.integer.value[0]; - -- if (strstr(kcontrol->id.name, "Loopback")) { -- i2s->loopback = value; -+ if (value == i2s->fsync_width) -+ return 0; - -- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, -- I2S_CTRL_LPBK_MASK, -- i2s->loopback << I2S_CTRL_LPBK_SHIFT); -+ i2s->fsync_width = value; - -- } else if (strstr(kcontrol->id.name, "FSYNC Width")) { -- /* -- * Frame sync width is used only for FSYNC modes and not -- * applicable for LRCK modes. Reset value for this field is "0", -- * which means the width is one bit clock wide. -- * The width requirement may depend on the codec and in such -- * cases mixer control is used to update custom values. A value -- * of "N" here means, width is "N + 1" bit clock wide. -- */ -- i2s->fsync_width = value; -- -- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, -- I2S_CTRL_FSYNC_WIDTH_MASK, -- i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); -- -- } else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) { -- i2s->stereo_to_mono[I2S_TX_PATH] = value; -- } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) { -- i2s->mono_to_stereo[I2S_TX_PATH] = value; -- } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) { -- i2s->stereo_to_mono[I2S_RX_PATH] = value; -- } else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) { -- i2s->mono_to_stereo[I2S_RX_PATH] = value; -- } else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) { -- i2s->rx_fifo_th = value; -- } else if (strstr(kcontrol->id.name, "BCLK Ratio")) { -- i2s->bclk_ratio = value; -- } -+ /* -+ * Frame sync width is used only for FSYNC modes and not -+ * applicable for LRCK modes. Reset value for this field is "0", -+ * which means the width is one bit clock wide. -+ * The width requirement may depend on the codec and in such -+ * cases mixer control is used to update custom values. A value -+ * of "N" here means, width is "N + 1" bit clock wide. -+ */ -+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, -+ I2S_CTRL_FSYNC_WIDTH_MASK, -+ i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); -+ -+ return 1; -+} -+ -+static int tegra210_i2s_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ -+ ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_TX_PATH]; -+ -+ return 0; -+} -+ -+static int tegra210_i2s_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == i2s->stereo_to_mono[I2S_TX_PATH]) -+ return 0; -+ -+ i2s->stereo_to_mono[I2S_TX_PATH] = value; -+ -+ return 1; -+} -+ -+static int tegra210_i2s_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ -+ ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_TX_PATH]; -+ -+ return 0; -+} -+ -+static int tegra210_i2s_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == i2s->mono_to_stereo[I2S_TX_PATH]) -+ return 0; -+ -+ i2s->mono_to_stereo[I2S_TX_PATH] = value; -+ -+ return 1; -+} -+ -+static int tegra210_i2s_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ -+ ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_RX_PATH]; -+ -+ return 0; -+} -+ -+static int tegra210_i2s_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == i2s->stereo_to_mono[I2S_RX_PATH]) -+ return 0; -+ -+ i2s->stereo_to_mono[I2S_RX_PATH] = value; -+ -+ return 1; -+} -+ -+static int tegra210_i2s_pget_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ -+ ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_RX_PATH]; -+ -+ return 0; -+} -+ -+static int tegra210_i2s_pput_mono_to_stereo(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ unsigned int value = ucontrol->value.enumerated.item[0]; -+ -+ if (value == i2s->mono_to_stereo[I2S_RX_PATH]) -+ return 0; -+ -+ i2s->mono_to_stereo[I2S_RX_PATH] = value; -+ -+ return 1; -+} -+ -+static int tegra210_i2s_pget_fifo_th(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ -+ ucontrol->value.integer.value[0] = i2s->rx_fifo_th; -+ -+ return 0; -+} -+ -+static int tegra210_i2s_pput_fifo_th(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ int value = ucontrol->value.integer.value[0]; -+ -+ if (value == i2s->rx_fifo_th) -+ return 0; -+ -+ i2s->rx_fifo_th = value; -+ -+ return 1; -+} -+ -+static int tegra210_i2s_get_bclk_ratio(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ -+ ucontrol->value.integer.value[0] = i2s->bclk_ratio; -+ -+ return 0; -+} -+ -+static int tegra210_i2s_put_bclk_ratio(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); -+ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); -+ int value = ucontrol->value.integer.value[0]; -+ -+ if (value == i2s->bclk_ratio) -+ return 0; -+ -+ i2s->bclk_ratio = value; -+ -+ return 1; -+} -+ -+static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, -+ unsigned int ratio) -+{ -+ struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); -+ -+ i2s->bclk_ratio = ratio; - - return 0; - } -@@ -598,22 +748,28 @@ static const struct soc_enum tegra210_i2s_stereo_conv_enum = - tegra210_i2s_stereo_conv_text); - - static const struct snd_kcontrol_new tegra210_i2s_controls[] = { -- SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control, -- tegra210_i2s_put_control), -- SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control, -- tegra210_i2s_put_control), -+ SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_loopback, -+ tegra210_i2s_put_loopback), -+ SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, -+ tegra210_i2s_get_fsync_width, -+ tegra210_i2s_put_fsync_width), - SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum, -- tegra210_i2s_get_control, tegra210_i2s_put_control), -+ tegra210_i2s_cget_stereo_to_mono, -+ tegra210_i2s_cput_stereo_to_mono), - SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum, -- tegra210_i2s_get_control, tegra210_i2s_put_control), -+ tegra210_i2s_cget_mono_to_stereo, -+ tegra210_i2s_cput_mono_to_stereo), - SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum, -- tegra210_i2s_get_control, tegra210_i2s_put_control), -+ tegra210_i2s_pget_mono_to_stereo, -+ tegra210_i2s_pput_mono_to_stereo), - SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum, -- tegra210_i2s_get_control, tegra210_i2s_put_control), -+ tegra210_i2s_pget_stereo_to_mono, -+ tegra210_i2s_pput_stereo_to_mono), - SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1, -- 0, tegra210_i2s_get_control, tegra210_i2s_put_control), -- SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control, -- tegra210_i2s_put_control), -+ 0, tegra210_i2s_pget_fifo_th, tegra210_i2s_pput_fifo_th), -+ SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, -+ tegra210_i2s_get_bclk_ratio, -+ tegra210_i2s_put_bclk_ratio), - }; - - static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = { -diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c -index 735909310a262..78fb423df550b 100644 ---- a/sound/soc/tegra/tegra_asoc_machine.c -+++ b/sound/soc/tegra/tegra_asoc_machine.c -@@ -341,9 +341,34 @@ tegra_machine_parse_phandle(struct device *dev, const char *name) - return np; - } - -+static void tegra_machine_unregister_codec(void *pdev) -+{ -+ platform_device_unregister(pdev); -+} -+ -+static int tegra_machine_register_codec(struct device *dev, const char *name) -+{ -+ struct platform_device *pdev; -+ int err; -+ -+ if (!name) -+ return 0; -+ -+ pdev = platform_device_register_simple(name, -1, NULL, 0); -+ if (IS_ERR(pdev)) -+ return PTR_ERR(pdev); -+ -+ err = devm_add_action_or_reset(dev, tegra_machine_unregister_codec, -+ pdev); -+ if (err) -+ return err; -+ -+ return 0; -+} -+ - int tegra_asoc_machine_probe(struct platform_device *pdev) - { -- struct device_node *np_codec, *np_i2s; -+ struct device_node *np_codec, *np_i2s, *np_ac97; - const struct tegra_asoc_data *asoc; - struct device *dev = &pdev->dev; - struct tegra_machine *machine; -@@ -404,17 +429,30 @@ int tegra_asoc_machine_probe(struct platform_device *pdev) - return err; - } - -- np_codec = tegra_machine_parse_phandle(dev, "nvidia,audio-codec"); -- if (IS_ERR(np_codec)) -- return PTR_ERR(np_codec); -+ if (asoc->set_ac97) { -+ err = tegra_machine_register_codec(dev, asoc->codec_dev_name); -+ if (err) -+ return err; -+ -+ np_ac97 = tegra_machine_parse_phandle(dev, "nvidia,ac97-controller"); -+ if (IS_ERR(np_ac97)) -+ return PTR_ERR(np_ac97); - -- np_i2s = tegra_machine_parse_phandle(dev, "nvidia,i2s-controller"); -- if (IS_ERR(np_i2s)) -- return PTR_ERR(np_i2s); -+ card->dai_link->cpus->of_node = np_ac97; -+ card->dai_link->platforms->of_node = np_ac97; -+ } else { -+ np_codec = tegra_machine_parse_phandle(dev, "nvidia,audio-codec"); -+ if (IS_ERR(np_codec)) -+ return PTR_ERR(np_codec); - -- card->dai_link->cpus->of_node = np_i2s; -- card->dai_link->codecs->of_node = np_codec; -- card->dai_link->platforms->of_node = np_i2s; -+ np_i2s = tegra_machine_parse_phandle(dev, "nvidia,i2s-controller"); -+ if (IS_ERR(np_i2s)) -+ return PTR_ERR(np_i2s); -+ -+ card->dai_link->cpus->of_node = np_i2s; -+ card->dai_link->codecs->of_node = np_codec; -+ card->dai_link->platforms->of_node = np_i2s; -+ } - - if (asoc->add_common_controls) { - card->controls = tegra_machine_controls; -@@ -589,6 +627,7 @@ static struct snd_soc_card snd_soc_tegra_wm9712 = { - static const struct tegra_asoc_data tegra_wm9712_data = { - .card = &snd_soc_tegra_wm9712, - .add_common_dapm_widgets = true, -+ .codec_dev_name = "wm9712-codec", - .set_ac97 = true, - }; - -@@ -686,6 +725,7 @@ static struct snd_soc_dai_link tegra_tlv320aic23_dai = { - }; - - static struct snd_soc_card snd_soc_tegra_trimslice = { -+ .name = "tegra-trimslice", - .components = "codec:tlv320aic23", - .dai_link = &tegra_tlv320aic23_dai, - .num_links = 1, -diff --git a/sound/soc/tegra/tegra_asoc_machine.h b/sound/soc/tegra/tegra_asoc_machine.h -index 8ee0ec814f67c..d6a8d13205516 100644 ---- a/sound/soc/tegra/tegra_asoc_machine.h -+++ b/sound/soc/tegra/tegra_asoc_machine.h -@@ -13,6 +13,7 @@ struct snd_soc_pcm_runtime; - - struct tegra_asoc_data { - unsigned int (*mclk_rate)(unsigned int srate); -+ const char *codec_dev_name; - struct snd_soc_card *card; - unsigned int mclk_id; - bool hp_jack_gpio_active_low; -diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c -index 49d1976a132c0..5ed8e36d2e043 100644 ---- a/sound/synth/emux/emux.c -+++ b/sound/synth/emux/emux.c -@@ -88,7 +88,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch - emu->name = kstrdup(name, GFP_KERNEL); - emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice), - GFP_KERNEL); -- if (emu->voices == NULL) -+ if (emu->name == NULL || emu->voices == NULL) - return -ENOMEM; - - /* create soundfont list */ -diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c -index 43a2a62d66f7e..49629d4bb327a 100644 ---- a/sound/usb/6fire/comm.c -+++ b/sound/usb/6fire/comm.c -@@ -95,7 +95,7 @@ static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev) - int actual_len; - - ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP), -- buffer, buffer[1] + 2, &actual_len, HZ); -+ buffer, buffer[1] + 2, &actual_len, 1000); - if (ret < 0) - return ret; - else if (actual_len != buffer[1] + 2) -diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c -index 8981e61f2da4a..c51abc54d2f84 100644 ---- a/sound/usb/6fire/firmware.c -+++ b/sound/usb/6fire/firmware.c -@@ -160,7 +160,7 @@ static int usb6fire_fw_ezusb_write(struct usb_device *device, - { - return usb_control_msg_send(device, 0, type, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, -- value, 0, data, len, HZ, GFP_KERNEL); -+ value, 0, data, len, 1000, GFP_KERNEL); - } - - static int usb6fire_fw_ezusb_read(struct usb_device *device, -@@ -168,7 +168,7 @@ static int usb6fire_fw_ezusb_read(struct usb_device *device, - { - return usb_control_msg_recv(device, 0, type, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, -- value, 0, data, len, HZ, GFP_KERNEL); -+ value, 0, data, len, 1000, GFP_KERNEL); - } - - static int usb6fire_fw_fpga_write(struct usb_device *device, -@@ -178,7 +178,7 @@ static int usb6fire_fw_fpga_write(struct usb_device *device, - int ret; - - ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len, -- &actual_len, HZ); -+ &actual_len, 1000); - if (ret < 0) - return ret; - else if (actual_len != len) -diff --git a/sound/usb/card.h b/sound/usb/card.h -index 5b19901f305a3..87f042d06ce08 100644 ---- a/sound/usb/card.h -+++ b/sound/usb/card.h -@@ -74,8 +74,9 @@ struct snd_usb_endpoint { - - atomic_t state; /* running state */ - -- void (*prepare_data_urb) (struct snd_usb_substream *subs, -- struct urb *urb); -+ int (*prepare_data_urb) (struct snd_usb_substream *subs, -+ struct urb *urb, -+ bool in_stream_lock); - void (*retire_data_urb) (struct snd_usb_substream *subs, - struct urb *urb); - -@@ -94,9 +95,9 @@ struct snd_usb_endpoint { - struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */ - - unsigned int nurbs; /* # urbs */ -- unsigned int nominal_queue_size; /* total buffer sizes in URBs */ - unsigned long active_mask; /* bitmask of active urbs */ - unsigned long unlink_mask; /* bitmask of unlinked urbs */ -+ atomic_t submitted_urbs; /* currently submitted urbs */ - char *syncbuf; /* sync buffer for all sync URBs */ - dma_addr_t sync_dma; /* DMA address of syncbuf */ - -@@ -125,6 +126,7 @@ struct snd_usb_endpoint { - int skip_packets; /* quirks for devices to ignore the first n packets - in a stream */ - bool implicit_fb_sync; /* syncs with implicit feedback */ -+ bool lowlatency_playback; /* low-latency playback mode */ - bool need_setup; /* (re-)need for configure? */ - - /* for hw constraints */ -@@ -136,6 +138,7 @@ struct snd_usb_endpoint { - unsigned int cur_period_frames; - unsigned int cur_period_bytes; - unsigned int cur_buffer_periods; -+ unsigned char cur_clock; - - spinlock_t lock; - struct list_head list; -@@ -188,7 +191,7 @@ struct snd_usb_substream { - } dsd_dop; - - bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */ -- bool early_playback_start; /* early start needed for playback? */ -+ bool lowlatency_playback; /* low-latency playback mode */ - struct media_ctl *media_ctl; - }; - -diff --git a/sound/usb/clock.c b/sound/usb/clock.c -index 81d5ce07d548b..98345a695dccb 100644 ---- a/sound/usb/clock.c -+++ b/sound/usb/clock.c -@@ -496,6 +496,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, - union uac23_clock_source_desc *cs_desc; - - cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol); -+ -+ if (!cs_desc) -+ return 0; -+ - if (fmt->protocol == UAC_VERSION_3) - bmControls = le32_to_cpu(cs_desc->v3.bmControls); - else -diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c -index 533919a28856f..743b8287cfcdd 100644 ---- a/sound/usb/endpoint.c -+++ b/sound/usb/endpoint.c -@@ -148,18 +148,23 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep) - * This won't be used for implicit feedback which takes the packet size - * returned from the sync source - */ --static int slave_next_packet_size(struct snd_usb_endpoint *ep) -+static int slave_next_packet_size(struct snd_usb_endpoint *ep, -+ unsigned int avail) - { - unsigned long flags; -+ unsigned int phase; - int ret; - - if (ep->fill_max) - return ep->maxframesize; - - spin_lock_irqsave(&ep->lock, flags); -- ep->phase = (ep->phase & 0xffff) -- + (ep->freqm << ep->datainterval); -- ret = min(ep->phase >> 16, ep->maxframesize); -+ phase = (ep->phase & 0xffff) + (ep->freqm << ep->datainterval); -+ ret = min(phase >> 16, ep->maxframesize); -+ if (avail && ret >= avail) -+ ret = -EAGAIN; -+ else -+ ep->phase = phase; - spin_unlock_irqrestore(&ep->lock, flags); - - return ret; -@@ -169,20 +174,25 @@ static int slave_next_packet_size(struct snd_usb_endpoint *ep) - * Return the number of samples to be sent in the next packet - * for adaptive and synchronous endpoints - */ --static int next_packet_size(struct snd_usb_endpoint *ep) -+static int next_packet_size(struct snd_usb_endpoint *ep, unsigned int avail) - { -+ unsigned int sample_accum; - int ret; - - if (ep->fill_max) - return ep->maxframesize; - -- ep->sample_accum += ep->sample_rem; -- if (ep->sample_accum >= ep->pps) { -- ep->sample_accum -= ep->pps; -+ sample_accum = ep->sample_accum + ep->sample_rem; -+ if (sample_accum >= ep->pps) { -+ sample_accum -= ep->pps; - ret = ep->packsize[1]; - } else { - ret = ep->packsize[0]; - } -+ if (avail && ret >= avail) -+ ret = -EAGAIN; -+ else -+ ep->sample_accum = sample_accum; - - return ret; - } -@@ -190,16 +200,27 @@ static int next_packet_size(struct snd_usb_endpoint *ep) - /* - * snd_usb_endpoint_next_packet_size: Return the number of samples to be sent - * in the next packet -+ * -+ * If the size is equal or exceeds @avail, don't proceed but return -EAGAIN -+ * Exception: @avail = 0 for skipping the check. - */ - int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, -- struct snd_urb_ctx *ctx, int idx) -+ struct snd_urb_ctx *ctx, int idx, -+ unsigned int avail) - { -- if (ctx->packet_size[idx]) -- return ctx->packet_size[idx]; -- else if (ep->sync_source) -- return slave_next_packet_size(ep); -+ unsigned int packet; -+ -+ packet = ctx->packet_size[idx]; -+ if (packet) { -+ if (avail && packet >= avail) -+ return -EAGAIN; -+ return packet; -+ } -+ -+ if (ep->sync_source) -+ return slave_next_packet_size(ep, avail); - else -- return next_packet_size(ep); -+ return next_packet_size(ep, avail); - } - - static void call_retire_callback(struct snd_usb_endpoint *ep, -@@ -263,7 +284,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, - unsigned int length; - int counts; - -- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); -+ counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); - length = counts * ep->stride; /* number of silent bytes */ - offset = offs * ep->stride + extra * i; - urb->iso_frame_desc[i].offset = offset; -@@ -286,8 +307,9 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, - /* - * Prepare a PLAYBACK urb for submission to the bus. - */ --static void prepare_outbound_urb(struct snd_usb_endpoint *ep, -- struct snd_urb_ctx *ctx) -+static int prepare_outbound_urb(struct snd_usb_endpoint *ep, -+ struct snd_urb_ctx *ctx, -+ bool in_stream_lock) - { - struct urb *urb = ctx->urb; - unsigned char *cp = urb->transfer_buffer; -@@ -299,9 +321,9 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, - case SND_USB_ENDPOINT_TYPE_DATA: - data_subs = READ_ONCE(ep->data_subs); - if (data_subs && ep->prepare_data_urb) -- ep->prepare_data_urb(data_subs, urb); -- else /* no data provider, so send silence */ -- prepare_silent_urb(ep, ctx); -+ return ep->prepare_data_urb(data_subs, urb, in_stream_lock); -+ /* no data provider, so send silence */ -+ prepare_silent_urb(ep, ctx); - break; - - case SND_USB_ENDPOINT_TYPE_SYNC: -@@ -330,13 +352,14 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, - - break; - } -+ return 0; - } - - /* - * Prepare a CAPTURE or SYNC urb for submission to the bus. - */ --static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep, -- struct snd_urb_ctx *urb_ctx) -+static int prepare_inbound_urb(struct snd_usb_endpoint *ep, -+ struct snd_urb_ctx *urb_ctx) - { - int i, offs; - struct urb *urb = urb_ctx->urb; -@@ -361,6 +384,7 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep, - urb->iso_frame_desc[0].offset = 0; - break; - } -+ return 0; - } - - /* notify an error as XRUN to the assigned PCM data substream */ -@@ -396,6 +420,16 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) - return p; - } - -+static void push_back_to_ready_list(struct snd_usb_endpoint *ep, -+ struct snd_urb_ctx *ctx) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ep->lock, flags); -+ list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); -+ spin_unlock_irqrestore(&ep->lock, flags); -+} -+ - /* - * Send output urbs that have been prepared previously. URBs are dequeued - * from ep->ready_playback_urbs and in case there aren't any available -@@ -406,12 +440,14 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) - * is that host controllers don't guarantee the order in which they return - * inbound and outbound packets to their submitters. - * -- * This function is only used for implicit feedback endpoints. For endpoints -- * driven by dedicated sync endpoints, URBs are immediately re-submitted -- * from their completion handler. -+ * This function is used both for implicit feedback endpoints and in low- -+ * latency playback mode. - */ --static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) -+void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, -+ bool in_stream_lock) - { -+ bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep); -+ - while (ep_state_running(ep)) { - - unsigned long flags; -@@ -420,14 +456,14 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) - int err, i; - - spin_lock_irqsave(&ep->lock, flags); -- if (ep->next_packet_queued > 0 && -+ if ((!implicit_fb || ep->next_packet_queued > 0) && - !list_empty(&ep->ready_playback_urbs)) { - /* take URB out of FIFO */ - ctx = list_first_entry(&ep->ready_playback_urbs, - struct snd_urb_ctx, ready_list); - list_del_init(&ctx->ready_list); -- -- packet = next_packet_fifo_dequeue(ep); -+ if (implicit_fb) -+ packet = next_packet_fifo_dequeue(ep); - } - spin_unlock_irqrestore(&ep->lock, flags); - -@@ -435,11 +471,24 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) - return; - - /* copy over the length information */ -- for (i = 0; i < packet->packets; i++) -- ctx->packet_size[i] = packet->packet_size[i]; -+ if (implicit_fb) { -+ for (i = 0; i < packet->packets; i++) -+ ctx->packet_size[i] = packet->packet_size[i]; -+ } - - /* call the data handler to fill in playback data */ -- prepare_outbound_urb(ep, ctx); -+ err = prepare_outbound_urb(ep, ctx, in_stream_lock); -+ /* can be stopped during prepare callback */ -+ if (unlikely(!ep_state_running(ep))) -+ break; -+ if (err < 0) { -+ /* push back to ready list again for -EAGAIN */ -+ if (err == -EAGAIN) -+ push_back_to_ready_list(ep, ctx); -+ else -+ notify_xrun(ep); -+ return; -+ } - - err = usb_submit_urb(ctx->urb, GFP_ATOMIC); - if (err < 0) { -@@ -451,6 +500,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) - } - - set_bit(ctx->index, &ep->active_mask); -+ atomic_inc(&ep->submitted_urbs); - } - } - -@@ -461,7 +511,6 @@ static void snd_complete_urb(struct urb *urb) - { - struct snd_urb_ctx *ctx = urb->context; - struct snd_usb_endpoint *ep = ctx->ep; -- unsigned long flags; - int err; - - if (unlikely(urb->status == -ENOENT || /* unlinked */ -@@ -482,16 +531,20 @@ static void snd_complete_urb(struct urb *urb) - if (unlikely(!ep_state_running(ep))) - goto exit_clear; - -- if (snd_usb_endpoint_implicit_feedback_sink(ep)) { -- spin_lock_irqsave(&ep->lock, flags); -- list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); -+ /* in low-latency and implicit-feedback modes, push back the -+ * URB to ready list at first, then process as much as possible -+ */ -+ if (ep->lowlatency_playback || -+ snd_usb_endpoint_implicit_feedback_sink(ep)) { -+ push_back_to_ready_list(ep, ctx); - clear_bit(ctx->index, &ep->active_mask); -- spin_unlock_irqrestore(&ep->lock, flags); -- queue_pending_output_urbs(ep); -+ snd_usb_queue_pending_output_urbs(ep, false); -+ atomic_dec(&ep->submitted_urbs); /* decrement at last */ - return; - } - -- prepare_outbound_urb(ep, ctx); -+ /* in non-lowlatency mode, no error handling for prepare */ -+ prepare_outbound_urb(ep, ctx, false); - /* can be stopped during prepare callback */ - if (unlikely(!ep_state_running(ep))) - goto exit_clear; -@@ -513,6 +566,7 @@ static void snd_complete_urb(struct urb *urb) - - exit_clear: - clear_bit(ctx->index, &ep->active_mask); -+ atomic_dec(&ep->submitted_urbs); - } - - /* -@@ -596,6 +650,7 @@ int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type) - ep->type = type; - ep->ep_num = ep_num; - INIT_LIST_HEAD(&ep->ready_playback_urbs); -+ atomic_set(&ep->submitted_urbs, 0); - - is_playback = ((ep_num & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); - ep_num &= USB_ENDPOINT_NUMBER_MASK; -@@ -722,6 +777,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, - ep->cur_period_frames = params_period_size(params); - ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes; - ep->cur_buffer_periods = params_periods(params); -+ ep->cur_clock = fp->clock; - - if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) - endpoint_set_syncinterval(chip, ep); -@@ -781,14 +837,19 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, - * Pass NULL to deactivate each callback. - */ - void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, -- void (*prepare)(struct snd_usb_substream *subs, -- struct urb *urb), -+ int (*prepare)(struct snd_usb_substream *subs, -+ struct urb *urb, -+ bool in_stream_lock), - void (*retire)(struct snd_usb_substream *subs, - struct urb *urb), - struct snd_usb_substream *data_subs) - { - ep->prepare_data_urb = prepare; - ep->retire_data_urb = retire; -+ if (data_subs) -+ ep->lowlatency_playback = data_subs->lowlatency_playback; -+ else -+ ep->lowlatency_playback = false; - WRITE_ONCE(ep->data_subs, data_subs); - } - -@@ -833,6 +894,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, - ep->altsetting = 0; - ep->cur_audiofmt = NULL; - ep->cur_rate = 0; -+ ep->cur_clock = 0; - ep->iface_ref = NULL; - usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num); - } -@@ -859,7 +921,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) - return 0; - - do { -- alive = bitmap_weight(&ep->active_mask, ep->nurbs); -+ alive = atomic_read(&ep->submitted_urbs); - if (!alive) - break; - -@@ -893,9 +955,10 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) - * - * This function moves the EP to STOPPING state if it's being RUNNING. - */ --static int stop_urbs(struct snd_usb_endpoint *ep, bool force) -+static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending) - { - unsigned int i; -+ unsigned long flags; - - if (!force && atomic_read(&ep->running)) - return -EBUSY; -@@ -903,9 +966,14 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force) - if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING)) - return 0; - -+ spin_lock_irqsave(&ep->lock, flags); - INIT_LIST_HEAD(&ep->ready_playback_urbs); - ep->next_packet_head = 0; - ep->next_packet_queued = 0; -+ spin_unlock_irqrestore(&ep->lock, flags); -+ -+ if (keep_pending) -+ return 0; - - for (i = 0; i < ep->nurbs; i++) { - if (test_bit(i, &ep->active_mask)) { -@@ -930,7 +998,7 @@ static int release_urbs(struct snd_usb_endpoint *ep, bool force) - snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); - - /* stop and unlink urbs */ -- err = stop_urbs(ep, force); -+ err = stop_urbs(ep, force, false); - if (err) - return err; - -@@ -1132,10 +1200,6 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep) - INIT_LIST_HEAD(&u->ready_list); - } - -- /* total buffer bytes of all URBs plus the next queue; -- * referred in pcm.c -- */ -- ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1); - return 0; - - out_of_memory: -@@ -1340,6 +1404,25 @@ unlock: - return err; - } - -+/* get the current rate set to the given clock by any endpoint */ -+int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock) -+{ -+ struct snd_usb_endpoint *ep; -+ int rate = 0; -+ -+ if (!clock) -+ return 0; -+ mutex_lock(&chip->mutex); -+ list_for_each_entry(ep, &chip->ep_list, list) { -+ if (ep->cur_clock == clock && ep->cur_rate) { -+ rate = ep->cur_rate; -+ break; -+ } -+ } -+ mutex_unlock(&chip->mutex); -+ return rate; -+} -+ - /** - * snd_usb_endpoint_start: start an snd_usb_endpoint - * -@@ -1355,6 +1438,7 @@ unlock: - */ - int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) - { -+ bool is_playback = usb_pipeout(ep->pipe); - int err; - unsigned int i; - -@@ -1391,13 +1475,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) - - if (snd_usb_endpoint_implicit_feedback_sink(ep) && - !(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) { -- for (i = 0; i < ep->nurbs; i++) { -- struct snd_urb_ctx *ctx = ep->urb + i; -- list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); -- } -- - usb_audio_dbg(ep->chip, "No URB submission due to implicit fb sync\n"); -- return 0; -+ i = 0; -+ goto fill_rest; - } - - for (i = 0; i < ep->nurbs; i++) { -@@ -1406,10 +1486,18 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) - if (snd_BUG_ON(!urb)) - goto __error; - -- if (usb_pipeout(ep->pipe)) { -- prepare_outbound_urb(ep, urb->context); -- } else { -- prepare_inbound_urb(ep, urb->context); -+ if (is_playback) -+ err = prepare_outbound_urb(ep, urb->context, true); -+ else -+ err = prepare_inbound_urb(ep, urb->context); -+ if (err < 0) { -+ /* stop filling at applptr */ -+ if (err == -EAGAIN) -+ break; -+ usb_audio_dbg(ep->chip, -+ "EP 0x%x: failed to prepare urb: %d\n", -+ ep->ep_num, err); -+ goto __error; - } - - err = usb_submit_urb(urb, GFP_ATOMIC); -@@ -1420,14 +1508,29 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) - goto __error; - } - set_bit(i, &ep->active_mask); -+ atomic_inc(&ep->submitted_urbs); -+ } -+ -+ if (!i) { -+ usb_audio_dbg(ep->chip, "XRUN at starting EP 0x%x\n", -+ ep->ep_num); -+ goto __error; - } - - usb_audio_dbg(ep->chip, "%d URBs submitted for EP 0x%x\n", -- ep->nurbs, ep->ep_num); -+ i, ep->ep_num); -+ -+ fill_rest: -+ /* put the remaining URBs to ready list */ -+ if (is_playback) { -+ for (; i < ep->nurbs; i++) -+ push_back_to_ready_list(ep, ep->urb + i); -+ } -+ - return 0; - - __error: -- snd_usb_endpoint_stop(ep); -+ snd_usb_endpoint_stop(ep, false); - return -EPIPE; - } - -@@ -1435,6 +1538,7 @@ __error: - * snd_usb_endpoint_stop: stop an snd_usb_endpoint - * - * @ep: the endpoint to stop (may be NULL) -+ * @keep_pending: keep in-flight URBs - * - * A call to this function will decrement the running count of the endpoint. - * In case the last user has requested the endpoint stop, the URBs will -@@ -1445,7 +1549,7 @@ __error: - * The caller needs to synchronize the pending stop operation via - * snd_usb_endpoint_sync_pending_stop(). - */ --void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) -+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending) - { - if (!ep) - return; -@@ -1460,7 +1564,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) - if (!atomic_dec_return(&ep->running)) { - if (ep->sync_source) - WRITE_ONCE(ep->sync_source->sync_sink, NULL); -- stop_urbs(ep, false); -+ stop_urbs(ep, false, keep_pending); - } - } - -@@ -1575,7 +1679,7 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, - } - - spin_unlock_irqrestore(&ep->lock, flags); -- queue_pending_output_urbs(ep); -+ snd_usb_queue_pending_output_urbs(ep, false); - - return; - } -diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h -index a668f675b52b0..6a9af04cf175a 100644 ---- a/sound/usb/endpoint.h -+++ b/sound/usb/endpoint.h -@@ -19,6 +19,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep); - int snd_usb_endpoint_configure(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep); -+int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock); - - bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep, -@@ -29,14 +30,15 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, - struct snd_usb_endpoint *data_ep, - struct snd_usb_endpoint *sync_ep); - void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, -- void (*prepare)(struct snd_usb_substream *subs, -- struct urb *urb), -+ int (*prepare)(struct snd_usb_substream *subs, -+ struct urb *urb, -+ bool in_stream_lock), - void (*retire)(struct snd_usb_substream *subs, - struct urb *urb), - struct snd_usb_substream *data_subs); - - int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); --void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); -+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending); - void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); - void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep); - int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); -@@ -45,6 +47,9 @@ void snd_usb_endpoint_free_all(struct snd_usb_audio *chip); - - int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); - int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, -- struct snd_urb_ctx *ctx, int idx); -+ struct snd_urb_ctx *ctx, int idx, -+ unsigned int avail); -+void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, -+ bool in_stream_lock); - - #endif /* __USBAUDIO_ENDPOINT_H */ -diff --git a/sound/usb/format.c b/sound/usb/format.c -index 50efccbffb8a7..f5e676a51b30d 100644 ---- a/sound/usb/format.c -+++ b/sound/usb/format.c -@@ -414,6 +414,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, - case USB_ID(0x0e41, 0x4242): /* Line6 Helix Rack */ - case USB_ID(0x0e41, 0x4244): /* Line6 Helix LT */ - case USB_ID(0x0e41, 0x4246): /* Line6 HX-Stomp */ -+ case USB_ID(0x0e41, 0x4253): /* Line6 HX-Stomp XL */ - case USB_ID(0x0e41, 0x4247): /* Line6 Pod Go */ - case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */ - case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */ -diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c -index 23767a14d1266..70319c822c10b 100644 ---- a/sound/usb/implicit.c -+++ b/sound/usb/implicit.c -@@ -54,8 +54,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { - - /* Fixed EP */ - /* FIXME: check the availability of generic matching */ -- IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */ -- IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */ - IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */ - IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */ - IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */ -diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c -index 9602929b7de90..59faa5a9a7141 100644 ---- a/sound/usb/line6/driver.c -+++ b/sound/usb/line6/driver.c -@@ -113,12 +113,12 @@ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, - retval = usb_interrupt_msg(line6->usbdev, - usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w), - (char *)frag_buf, frag_size, -- &partial, LINE6_TIMEOUT * HZ); -+ &partial, LINE6_TIMEOUT); - } else { - retval = usb_bulk_msg(line6->usbdev, - usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w), - (char *)frag_buf, frag_size, -- &partial, LINE6_TIMEOUT * HZ); -+ &partial, LINE6_TIMEOUT); - } - - if (retval) { -@@ -347,7 +347,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, - ret = usb_control_msg_send(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - (datalen << 8) | 0x21, address, NULL, 0, -- LINE6_TIMEOUT * HZ, GFP_KERNEL); -+ LINE6_TIMEOUT, GFP_KERNEL); - if (ret) { - dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); - goto exit; -@@ -360,7 +360,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, - ret = usb_control_msg_recv(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x0012, 0x0000, &len, 1, -- LINE6_TIMEOUT * HZ, GFP_KERNEL); -+ LINE6_TIMEOUT, GFP_KERNEL); - if (ret) { - dev_err(line6->ifcdev, - "receive length failed (error %d)\n", ret); -@@ -387,7 +387,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, - /* receive the result: */ - ret = usb_control_msg_recv(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, -- 0x0013, 0x0000, data, datalen, LINE6_TIMEOUT * HZ, -+ 0x0013, 0x0000, data, datalen, LINE6_TIMEOUT, - GFP_KERNEL); - if (ret) - dev_err(line6->ifcdev, "read failed (error %d)\n", ret); -@@ -417,7 +417,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, - - ret = usb_control_msg_send(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, -- 0x0022, address, data, datalen, LINE6_TIMEOUT * HZ, -+ 0x0022, address, data, datalen, LINE6_TIMEOUT, - GFP_KERNEL); - if (ret) { - dev_err(line6->ifcdev, -@@ -430,7 +430,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, - - ret = usb_control_msg_recv(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, -- 0x0012, 0x0000, status, 1, LINE6_TIMEOUT * HZ, -+ 0x0012, 0x0000, status, 1, LINE6_TIMEOUT, - GFP_KERNEL); - if (ret) { - dev_err(line6->ifcdev, -diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h -index 71d3da1db8c81..ecf3a2b39c7eb 100644 ---- a/sound/usb/line6/driver.h -+++ b/sound/usb/line6/driver.h -@@ -27,7 +27,7 @@ - #define LINE6_FALLBACK_INTERVAL 10 - #define LINE6_FALLBACK_MAXPACKETSIZE 16 - --#define LINE6_TIMEOUT 1 -+#define LINE6_TIMEOUT 1000 - #define LINE6_BUFSIZE_LISTEN 64 - #define LINE6_MIDI_MESSAGE_MAXLEN 256 - -diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c -index 28794a35949d4..b24bc82f89e37 100644 ---- a/sound/usb/line6/podhd.c -+++ b/sound/usb/line6/podhd.c -@@ -190,7 +190,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) - ret = usb_control_msg_send(usbdev, 0, - 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - 0x11, 0, -- NULL, 0, LINE6_TIMEOUT * HZ, GFP_KERNEL); -+ NULL, 0, LINE6_TIMEOUT, GFP_KERNEL); - if (ret) { - dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); - goto exit; -@@ -200,7 +200,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) - ret = usb_control_msg_recv(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x11, 0x0, -- init_bytes, 3, LINE6_TIMEOUT * HZ, GFP_KERNEL); -+ init_bytes, 3, LINE6_TIMEOUT, GFP_KERNEL); - if (ret) { - dev_err(pod->line6.ifcdev, - "receive length failed (error %d)\n", ret); -@@ -220,7 +220,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) - USB_REQ_SET_FEATURE, - USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, - 1, 0, -- NULL, 0, LINE6_TIMEOUT * HZ, GFP_KERNEL); -+ NULL, 0, LINE6_TIMEOUT, GFP_KERNEL); - exit: - return ret; - } -diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c -index 4e5693c97aa42..e33df58740a91 100644 ---- a/sound/usb/line6/toneport.c -+++ b/sound/usb/line6/toneport.c -@@ -128,7 +128,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) - - ret = usb_control_msg_send(usbdev, 0, 0x67, - USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, -- cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ, -+ cmd1, cmd2, NULL, 0, LINE6_TIMEOUT, - GFP_KERNEL); - - if (ret) { -diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c -index 5834d1dc317ef..4f6b20ed29dd7 100644 ---- a/sound/usb/misc/ua101.c -+++ b/sound/usb/misc/ua101.c -@@ -1000,7 +1000,7 @@ static int detect_usb_format(struct ua101 *ua) - fmt_playback->bSubframeSize * ua->playback.channels; - - epd = &ua->intf[INTF_CAPTURE]->altsetting[1].endpoint[0].desc; -- if (!usb_endpoint_is_isoc_in(epd)) { -+ if (!usb_endpoint_is_isoc_in(epd) || usb_endpoint_maxp(epd) == 0) { - dev_err(&ua->dev->dev, "invalid capture endpoint\n"); - return -ENXIO; - } -@@ -1008,7 +1008,7 @@ static int detect_usb_format(struct ua101 *ua) - ua->capture.max_packet_bytes = usb_endpoint_maxp(epd); - - epd = &ua->intf[INTF_PLAYBACK]->altsetting[1].endpoint[0].desc; -- if (!usb_endpoint_is_isoc_out(epd)) { -+ if (!usb_endpoint_is_isoc_out(epd) || usb_endpoint_maxp(epd) == 0) { - dev_err(&ua->dev->dev, "invalid playback endpoint\n"); - return -ENXIO; - } -diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c -index 46082dc57be09..823b6b8de942d 100644 ---- a/sound/usb/mixer_quirks.c -+++ b/sound/usb/mixer_quirks.c -@@ -2795,6 +2795,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) - #define SND_DJM_750_IDX 0x1 - #define SND_DJM_850_IDX 0x2 - #define SND_DJM_900NXS2_IDX 0x3 -+#define SND_DJM_750MK2_IDX 0x4 - - - #define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ -@@ -2984,12 +2985,42 @@ static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = { - SND_DJM_CTL("Ch5 Input", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP) - }; - -+// DJM-750MK2 -+static const u16 snd_djm_opts_750mk2_cap1[] = { -+ 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a }; -+static const u16 snd_djm_opts_750mk2_cap2[] = { -+ 0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a }; -+static const u16 snd_djm_opts_750mk2_cap3[] = { -+ 0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a }; -+static const u16 snd_djm_opts_750mk2_cap4[] = { -+ 0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a }; -+static const u16 snd_djm_opts_750mk2_cap5[] = { -+ 0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 }; -+ -+static const u16 snd_djm_opts_750mk2_pb1[] = { 0x0100, 0x0101, 0x0104 }; -+static const u16 snd_djm_opts_750mk2_pb2[] = { 0x0200, 0x0201, 0x0204 }; -+static const u16 snd_djm_opts_750mk2_pb3[] = { 0x0300, 0x0301, 0x0304 }; -+ -+ -+static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = { -+ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), -+ SND_DJM_CTL("Ch1 Input", 750mk2_cap1, 2, SND_DJM_WINDEX_CAP), -+ SND_DJM_CTL("Ch2 Input", 750mk2_cap2, 2, SND_DJM_WINDEX_CAP), -+ SND_DJM_CTL("Ch3 Input", 750mk2_cap3, 2, SND_DJM_WINDEX_CAP), -+ SND_DJM_CTL("Ch4 Input", 750mk2_cap4, 2, SND_DJM_WINDEX_CAP), -+ SND_DJM_CTL("Ch5 Input", 750mk2_cap5, 3, SND_DJM_WINDEX_CAP), -+ SND_DJM_CTL("Ch1 Output", 750mk2_pb1, 0, SND_DJM_WINDEX_PB), -+ SND_DJM_CTL("Ch2 Output", 750mk2_pb2, 1, SND_DJM_WINDEX_PB), -+ SND_DJM_CTL("Ch3 Output", 750mk2_pb3, 2, SND_DJM_WINDEX_PB) -+}; -+ - - static const struct snd_djm_device snd_djm_devices[] = { -- SND_DJM_DEVICE(250mk2), -- SND_DJM_DEVICE(750), -- SND_DJM_DEVICE(850), -- SND_DJM_DEVICE(900nxs2) -+ [SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2), -+ [SND_DJM_750_IDX] = SND_DJM_DEVICE(750), -+ [SND_DJM_850_IDX] = SND_DJM_DEVICE(850), -+ [SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2), -+ [SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2), - }; - - -@@ -3235,6 +3266,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) - case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ - err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); - break; -+ case USB_ID(0x2b73, 0x001b): /* Pioneer DJ DJM-750MK2 */ -+ err = snd_djm_controls_create(mixer, SND_DJM_750MK2_IDX); -+ break; - case USB_ID(0x08e4, 0x0163): /* Pioneer DJ DJM-850 */ - err = snd_djm_controls_create(mixer, SND_DJM_850_IDX); - break; -diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c -index 5dc9266180e37..2e51fb031ae01 100644 ---- a/sound/usb/pcm.c -+++ b/sound/usb/pcm.c -@@ -219,16 +219,16 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, - return 0; - } - --static bool stop_endpoints(struct snd_usb_substream *subs) -+static bool stop_endpoints(struct snd_usb_substream *subs, bool keep_pending) - { - bool stopped = 0; - - if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { -- snd_usb_endpoint_stop(subs->sync_endpoint); -+ snd_usb_endpoint_stop(subs->sync_endpoint, keep_pending); - stopped = true; - } - if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { -- snd_usb_endpoint_stop(subs->data_endpoint); -+ snd_usb_endpoint_stop(subs->data_endpoint, keep_pending); - stopped = true; - } - return stopped; -@@ -261,7 +261,7 @@ static int start_endpoints(struct snd_usb_substream *subs) - return 0; - - error: -- stop_endpoints(subs); -+ stop_endpoints(subs, false); - return err; - } - -@@ -437,7 +437,7 @@ static int configure_endpoints(struct snd_usb_audio *chip, - - if (subs->data_endpoint->need_setup) { - /* stop any running stream beforehand */ -- if (stop_endpoints(subs)) -+ if (stop_endpoints(subs, false)) - sync_pending_stops(subs); - err = snd_usb_endpoint_configure(chip, subs->data_endpoint); - if (err < 0) -@@ -572,7 +572,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) - subs->cur_audiofmt = NULL; - mutex_unlock(&chip->mutex); - if (!snd_usb_lock_shutdown(chip)) { -- if (stop_endpoints(subs)) -+ if (stop_endpoints(subs, false)) - sync_pending_stops(subs); - close_endpoints(chip, subs); - snd_usb_unlock_shutdown(chip); -@@ -581,6 +581,31 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) - return 0; - } - -+/* free-wheeling mode? (e.g. dmix) */ -+static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime) -+{ -+ return runtime->stop_threshold > runtime->buffer_size; -+} -+ -+/* check whether early start is needed for playback stream */ -+static int lowlatency_playback_available(struct snd_pcm_runtime *runtime, -+ struct snd_usb_substream *subs) -+{ -+ struct snd_usb_audio *chip = subs->stream->chip; -+ -+ if (subs->direction == SNDRV_PCM_STREAM_CAPTURE) -+ return false; -+ /* disabled via module option? */ -+ if (!chip->lowlatency) -+ return false; -+ if (in_free_wheeling_mode(runtime)) -+ return false; -+ /* implicit feedback mode has own operation mode */ -+ if (snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) -+ return false; -+ return true; -+} -+ - /* - * prepare callback - * -@@ -614,13 +639,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) - subs->period_elapsed_pending = 0; - runtime->delay = 0; - -- /* check whether early start is needed for playback stream */ -- subs->early_playback_start = -- subs->direction == SNDRV_PCM_STREAM_PLAYBACK && -- (!chip->lowlatency || -- (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes)); -- -- if (subs->early_playback_start) -+ subs->lowlatency_playback = lowlatency_playback_available(runtime, subs); -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && -+ !subs->lowlatency_playback) - ret = start_endpoints(subs); - - unlock: -@@ -734,6 +755,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) - { - struct snd_usb_substream *subs = rule->private; -+ struct snd_usb_audio *chip = subs->stream->chip; - const struct audioformat *fp; - struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - unsigned int rmin, rmax, r; -@@ -745,6 +767,14 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, - list_for_each_entry(fp, &subs->fmt_list, list) { - if (!hw_check_valid_format(subs, params, fp)) - continue; -+ r = snd_usb_endpoint_get_clock_rate(chip, fp->clock); -+ if (r > 0) { -+ if (!snd_interval_test(it, r)) -+ continue; -+ rmin = min(rmin, r); -+ rmax = max(rmax, r); -+ continue; -+ } - if (fp->rate_table && fp->nr_rates) { - for (i = 0; i < fp->nr_rates; i++) { - r = fp->rate_table[i]; -@@ -1068,6 +1098,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) - int ret; - - runtime->hw = snd_usb_hardware; -+ /* need an explicit sync to catch applptr update in low-latency mode */ -+ if (direction == SNDRV_PCM_STREAM_PLAYBACK && -+ as->chip->lowlatency) -+ runtime->hw.info |= SNDRV_PCM_INFO_SYNC_APPLPTR; - runtime->private_data = subs; - subs->pcm_substream = substream; - /* runtime PM is also done there */ -@@ -1320,44 +1354,66 @@ static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs, - return bytes; - } - --static void prepare_playback_urb(struct snd_usb_substream *subs, -- struct urb *urb) -+static int prepare_playback_urb(struct snd_usb_substream *subs, -+ struct urb *urb, -+ bool in_stream_lock) - { - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - struct snd_usb_endpoint *ep = subs->data_endpoint; - struct snd_urb_ctx *ctx = urb->context; -- unsigned int counts, frames, bytes; -+ unsigned int frames, bytes; -+ int counts; -+ unsigned int transfer_done, frame_limit, avail = 0; - int i, stride, period_elapsed = 0; - unsigned long flags; -+ int err = 0; - - stride = ep->stride; - - frames = 0; - ctx->queued = 0; - urb->number_of_packets = 0; -+ - spin_lock_irqsave(&subs->lock, flags); -- subs->frame_limit += ep->max_urb_frames; -+ frame_limit = subs->frame_limit + ep->max_urb_frames; -+ transfer_done = subs->transfer_done; -+ -+ if (subs->lowlatency_playback && -+ runtime->status->state != SNDRV_PCM_STATE_DRAINING) { -+ unsigned int hwptr = subs->hwptr_done / stride; -+ -+ /* calculate the byte offset-in-buffer of the appl_ptr */ -+ avail = (runtime->control->appl_ptr - runtime->hw_ptr_base) -+ % runtime->buffer_size; -+ if (avail <= hwptr) -+ avail += runtime->buffer_size; -+ avail -= hwptr; -+ } -+ - for (i = 0; i < ctx->packets; i++) { -- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); -+ counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail); -+ if (counts < 0) -+ break; - /* set up descriptor */ - urb->iso_frame_desc[i].offset = frames * stride; - urb->iso_frame_desc[i].length = counts * stride; - frames += counts; -+ avail -= counts; - urb->number_of_packets++; -- subs->transfer_done += counts; -- if (subs->transfer_done >= runtime->period_size) { -- subs->transfer_done -= runtime->period_size; -- subs->frame_limit = 0; -+ transfer_done += counts; -+ if (transfer_done >= runtime->period_size) { -+ transfer_done -= runtime->period_size; -+ frame_limit = 0; - period_elapsed = 1; - if (subs->fmt_type == UAC_FORMAT_TYPE_II) { -- if (subs->transfer_done > 0) { -+ if (transfer_done > 0) { - /* FIXME: fill-max mode is not - * supported yet */ -- frames -= subs->transfer_done; -- counts -= subs->transfer_done; -+ frames -= transfer_done; -+ counts -= transfer_done; - urb->iso_frame_desc[i].length = - counts * stride; -- subs->transfer_done = 0; -+ transfer_done = 0; - } - i++; - if (i < ctx->packets) { -@@ -1371,13 +1427,19 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, - } - } - /* finish at the period boundary or after enough frames */ -- if ((period_elapsed || -- subs->transfer_done >= subs->frame_limit) && -+ if ((period_elapsed || transfer_done >= frame_limit) && - !snd_usb_endpoint_implicit_feedback_sink(ep)) - break; - } -- bytes = frames * stride; - -+ if (!frames) { -+ err = -EAGAIN; -+ goto unlock; -+ } -+ -+ bytes = frames * stride; -+ subs->transfer_done = transfer_done; -+ subs->frame_limit = frame_limit; - if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && - subs->cur_audiofmt->dsd_dop)) { - fill_playback_urb_dsd_dop(subs, urb, bytes); -@@ -1403,14 +1465,23 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, - subs->trigger_tstamp_pending_update = false; - } - -- if (period_elapsed && !subs->running && !subs->early_playback_start) { -+ if (period_elapsed && !subs->running && subs->lowlatency_playback) { - subs->period_elapsed_pending = 1; - period_elapsed = 0; - } -+ -+ unlock: - spin_unlock_irqrestore(&subs->lock, flags); -+ if (err < 0) -+ return err; - urb->transfer_buffer_length = bytes; -- if (period_elapsed) -- snd_pcm_period_elapsed(subs->pcm_substream); -+ if (period_elapsed) { -+ if (in_stream_lock) -+ snd_pcm_period_elapsed_under_stream_lock(subs->pcm_substream); -+ else -+ snd_pcm_period_elapsed(subs->pcm_substream); -+ } -+ return 0; - } - - /* -@@ -1442,6 +1513,27 @@ static void retire_playback_urb(struct snd_usb_substream *subs, - snd_pcm_period_elapsed(subs->pcm_substream); - } - -+/* PCM ack callback for the playback stream; -+ * this plays a role only when the stream is running in low-latency mode. -+ */ -+static int snd_usb_pcm_playback_ack(struct snd_pcm_substream *substream) -+{ -+ struct snd_usb_substream *subs = substream->runtime->private_data; -+ struct snd_usb_endpoint *ep; -+ -+ if (!subs->lowlatency_playback || !subs->running) -+ return 0; -+ ep = subs->data_endpoint; -+ if (!ep) -+ return 0; -+ /* When no more in-flight URBs available, try to process the pending -+ * outputs here -+ */ -+ if (!ep->active_mask) -+ snd_usb_queue_pending_output_urbs(ep, true); -+ return 0; -+} -+ - static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, - int cmd) - { -@@ -1457,8 +1549,10 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea - prepare_playback_urb, - retire_playback_urb, - subs); -- if (!subs->early_playback_start && -+ if (subs->lowlatency_playback && - cmd == SNDRV_PCM_TRIGGER_START) { -+ if (in_free_wheeling_mode(substream->runtime)) -+ subs->lowlatency_playback = false; - err = start_endpoints(subs); - if (err < 0) { - snd_usb_endpoint_set_callback(subs->data_endpoint, -@@ -1473,7 +1567,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea - return 0; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: -- stop_endpoints(subs); -+ stop_endpoints(subs, substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING); - snd_usb_endpoint_set_callback(subs->data_endpoint, - NULL, NULL, NULL); - subs->running = 0; -@@ -1521,7 +1615,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream - return 0; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: -- stop_endpoints(subs); -+ stop_endpoints(subs, false); - fallthrough; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_usb_endpoint_set_callback(subs->data_endpoint, -@@ -1545,6 +1639,7 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { - .trigger = snd_usb_substream_playback_trigger, - .sync_stop = snd_usb_pcm_sync_stop, - .pointer = snd_usb_pcm_pointer, -+ .ack = snd_usb_pcm_playback_ack, - }; - - static const struct snd_pcm_ops snd_usb_capture_ops = { -diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h -index 2af8c68fac275..b1522e43173e1 100644 ---- a/sound/usb/quirks-table.h -+++ b/sound/usb/quirks-table.h -@@ -3892,6 +3892,64 @@ YAMAHA_DEVICE(0x7010, "UB99"), - } - } - }, -+{ -+ /* -+ * Pioneer DJ DJM-750MK2 -+ * 10 channels playback & 12 channels capture @ 48kHz S24LE -+ */ -+ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001b), -+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { -+ .ifnum = QUIRK_ANY_INTERFACE, -+ .type = QUIRK_COMPOSITE, -+ .data = (const struct snd_usb_audio_quirk[]) { -+ { -+ .ifnum = 0, -+ .type = QUIRK_AUDIO_FIXED_ENDPOINT, -+ .data = &(const struct audioformat) { -+ .formats = SNDRV_PCM_FMTBIT_S24_3LE, -+ .channels = 10, -+ .iface = 0, -+ .altsetting = 1, -+ .altset_idx = 1, -+ .endpoint = 0x01, -+ .ep_attr = USB_ENDPOINT_XFER_ISOC| -+ USB_ENDPOINT_SYNC_ASYNC, -+ .rates = SNDRV_PCM_RATE_48000, -+ .rate_min = 48000, -+ .rate_max = 48000, -+ .nr_rates = 1, -+ .rate_table = (unsigned int[]) { -+ 48000 -+ } -+ } -+ }, -+ { -+ .ifnum = 0, -+ .type = QUIRK_AUDIO_FIXED_ENDPOINT, -+ .data = &(const struct audioformat) { -+ .formats = SNDRV_PCM_FMTBIT_S24_3LE, -+ .channels = 12, -+ .iface = 0, -+ .altsetting = 1, -+ .altset_idx = 1, -+ .endpoint = 0x82, -+ .ep_idx = 1, -+ .ep_attr = USB_ENDPOINT_XFER_ISOC| -+ USB_ENDPOINT_SYNC_ASYNC| -+ USB_ENDPOINT_USAGE_IMPLICIT_FB, -+ .rates = SNDRV_PCM_RATE_48000, -+ .rate_min = 48000, -+ .rate_max = 48000, -+ .nr_rates = 1, -+ .rate_table = (unsigned int[]) { 48000 } -+ } -+ }, -+ { -+ .ifnum = -1 -+ } -+ } -+ } -+}, - { - /* - * Pioneer DJ DJM-850 -diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c -index 8929d9abe8aa8..64e1c20311ed4 100644 ---- a/sound/usb/quirks.c -+++ b/sound/usb/quirks.c -@@ -1749,6 +1749,7 @@ static const struct registration_quirk registration_quirks[] = { - REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */ -+ REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */ -@@ -1887,6 +1888,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { - QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), - DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */ - QUIRK_FLAG_GET_SAMPLE_RATE), -+ DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ -+ QUIRK_FLAG_IGNORE_CTL_ERROR), - DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ - QUIRK_FLAG_GET_SAMPLE_RATE), - DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ -diff --git a/tools/arch/x86/lib/insn.c b/tools/arch/x86/lib/insn.c -index 797699462cd8e..8fd63a067308a 100644 ---- a/tools/arch/x86/lib/insn.c -+++ b/tools/arch/x86/lib/insn.c -@@ -13,6 +13,7 @@ - #endif - #include "../include/asm/inat.h" /* __ignore_sync_check__ */ - #include "../include/asm/insn.h" /* __ignore_sync_check__ */ -+#include "../include/asm-generic/unaligned.h" /* __ignore_sync_check__ */ - - #include <linux/errno.h> - #include <linux/kconfig.h> -@@ -37,10 +38,10 @@ - ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr) - - #define __get_next(t, insn) \ -- ({ t r; memcpy(&r, insn->next_byte, sizeof(t)); insn->next_byte += sizeof(t); leXX_to_cpu(t, r); }) -+ ({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); }) - - #define __peek_nbyte_next(t, insn, n) \ -- ({ t r; memcpy(&r, (insn)->next_byte + n, sizeof(t)); leXX_to_cpu(t, r); }) -+ ({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); }) - - #define get_next(t, insn) \ - ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); }) -diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c -index 9c3e343b7d872..fe59404e87046 100644 ---- a/tools/bpf/bpftool/prog.c -+++ b/tools/bpf/bpftool/prog.c -@@ -308,18 +308,12 @@ static void show_prog_metadata(int fd, __u32 num_maps) - if (printed_header) - jsonw_end_object(json_wtr); - } else { -- json_writer_t *btf_wtr = jsonw_new(stdout); -+ json_writer_t *btf_wtr; - struct btf_dumper d = { - .btf = btf, -- .jw = btf_wtr, - .is_plain_text = true, - }; - -- if (!btf_wtr) { -- p_err("jsonw alloc failed"); -- goto out_free; -- } -- - for (i = 0; i < vlen; i++, vsi++) { - t_var = btf__type_by_id(btf, vsi->type); - name = btf__name_by_offset(btf, t_var->name_off); -@@ -329,6 +323,14 @@ static void show_prog_metadata(int fd, __u32 num_maps) - - if (!printed_header) { - printf("\tmetadata:"); -+ -+ btf_wtr = jsonw_new(stdout); -+ if (!btf_wtr) { -+ p_err("jsonw alloc failed"); -+ goto out_free; -+ } -+ d.jw = btf_wtr, -+ - printed_header = true; - } - -diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature -index 3dd2f68366f95..88dd7db55d385 100644 ---- a/tools/build/Makefile.feature -+++ b/tools/build/Makefile.feature -@@ -48,7 +48,6 @@ FEATURE_TESTS_BASIC := \ - numa_num_possible_cpus \ - libperl \ - libpython \ -- libpython-version \ - libslang \ - libslang-include-subdir \ - libtraceevent \ -diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile -index eff55d287db1f..e1e670014bd0c 100644 ---- a/tools/build/feature/Makefile -+++ b/tools/build/feature/Makefile -@@ -32,7 +32,6 @@ FILES= \ - test-numa_num_possible_cpus.bin \ - test-libperl.bin \ - test-libpython.bin \ -- test-libpython-version.bin \ - test-libslang.bin \ - test-libslang-include-subdir.bin \ - test-libtraceevent.bin \ -@@ -223,9 +222,6 @@ $(OUTPUT)test-libperl.bin: - $(OUTPUT)test-libpython.bin: - $(BUILD) $(FLAGS_PYTHON_EMBED) - --$(OUTPUT)test-libpython-version.bin: -- $(BUILD) -- - $(OUTPUT)test-libbfd.bin: - $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl - -diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c -index 9204395272912..5ffafb967b6e4 100644 ---- a/tools/build/feature/test-all.c -+++ b/tools/build/feature/test-all.c -@@ -14,10 +14,6 @@ - # include "test-libpython.c" - #undef main - --#define main main_test_libpython_version --# include "test-libpython-version.c" --#undef main -- - #define main main_test_libperl - # include "test-libperl.c" - #undef main -@@ -177,7 +173,6 @@ - int main(int argc, char *argv[]) - { - main_test_libpython(); -- main_test_libpython_version(); - main_test_libperl(); - main_test_hello(); - main_test_libelf(); -@@ -200,7 +195,6 @@ int main(int argc, char *argv[]) - main_test_timerfd(); - main_test_stackprotector_all(); - main_test_libdw_dwarf_unwind(); -- main_test_sync_compare_and_swap(argc, argv); - main_test_zlib(); - main_test_pthread_attr_setaffinity_np(); - main_test_pthread_barrier(); -diff --git a/tools/build/feature/test-libpython-version.c b/tools/build/feature/test-libpython-version.c -deleted file mode 100644 -index 47714b942d4d3..0000000000000 ---- a/tools/build/feature/test-libpython-version.c -+++ /dev/null -@@ -1,11 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --#include <Python.h> -- --#if PY_VERSION_HEX >= 0x03000000 -- #error --#endif -- --int main(void) --{ -- return 0; --} -diff --git a/tools/include/asm-generic/unaligned.h b/tools/include/asm-generic/unaligned.h -new file mode 100644 -index 0000000000000..47387c607035e ---- /dev/null -+++ b/tools/include/asm-generic/unaligned.h -@@ -0,0 +1,23 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+/* -+ * Copied from the kernel sources to tools/perf/: -+ */ -+ -+#ifndef __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H -+#define __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H -+ -+#define __get_unaligned_t(type, ptr) ({ \ -+ const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ -+ __pptr->x; \ -+}) -+ -+#define __put_unaligned_t(type, val, ptr) do { \ -+ struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ -+ __pptr->x = (val); \ -+} while (0) -+ -+#define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) -+#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr)) -+ -+#endif /* __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H */ -+ -diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c -index 2401fad090c52..bfd1ce9fe2110 100644 ---- a/tools/lib/bpf/bpf.c -+++ b/tools/lib/bpf/bpf.c -@@ -480,6 +480,7 @@ int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) - int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags) - { - union bpf_attr attr; -+ int ret; - - memset(&attr, 0, sizeof(attr)); - attr.map_fd = fd; -@@ -487,7 +488,8 @@ int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, _ - attr.value = ptr_to_u64(value); - attr.flags = flags; - -- return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); -+ ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); -+ return libbpf_err_errno(ret); - } - - int bpf_map_delete_elem(int fd, const void *key) -diff --git a/tools/lib/bpf/bpf_core_read.h b/tools/lib/bpf/bpf_core_read.h -index 09ebe3db5f2f8..e4aa9996a5501 100644 ---- a/tools/lib/bpf/bpf_core_read.h -+++ b/tools/lib/bpf/bpf_core_read.h -@@ -40,7 +40,7 @@ enum bpf_enum_value_kind { - #define __CORE_RELO(src, field, info) \ - __builtin_preserve_field_info((src)->field, BPF_FIELD_##info) - --#if __BYTE_ORDER == __LITTLE_ENDIAN -+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - #define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \ - bpf_probe_read_kernel( \ - (void *)dst, \ -diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c -index 77dc24d58302d..1b9341ef638b0 100644 ---- a/tools/lib/bpf/btf.c -+++ b/tools/lib/bpf/btf.c -@@ -231,17 +231,23 @@ static int btf_parse_hdr(struct btf *btf) - } - btf_bswap_hdr(hdr); - } else if (hdr->magic != BTF_MAGIC) { -- pr_debug("Invalid BTF magic:%x\n", hdr->magic); -+ pr_debug("Invalid BTF magic: %x\n", hdr->magic); - return -EINVAL; - } - -- meta_left = btf->raw_size - sizeof(*hdr); -- if (meta_left < hdr->str_off + hdr->str_len) { -- pr_debug("Invalid BTF total size:%u\n", btf->raw_size); -+ if (btf->raw_size < hdr->hdr_len) { -+ pr_debug("BTF header len %u larger than data size %u\n", -+ hdr->hdr_len, btf->raw_size); - return -EINVAL; - } - -- if (hdr->type_off + hdr->type_len > hdr->str_off) { -+ meta_left = btf->raw_size - hdr->hdr_len; -+ if (meta_left < (long long)hdr->str_off + hdr->str_len) { -+ pr_debug("Invalid BTF total size: %u\n", btf->raw_size); -+ return -EINVAL; -+ } -+ -+ if ((long long)hdr->type_off + hdr->type_len > hdr->str_off) { - pr_debug("Invalid BTF data sections layout: type data at %u + %u, strings data at %u + %u\n", - hdr->type_off, hdr->type_len, hdr->str_off, hdr->str_len); - return -EINVAL; -@@ -2914,8 +2920,10 @@ int btf__dedup(struct btf *btf, struct btf_ext *btf_ext, - return libbpf_err(-EINVAL); - } - -- if (btf_ensure_modifiable(btf)) -- return libbpf_err(-ENOMEM); -+ if (btf_ensure_modifiable(btf)) { -+ err = -ENOMEM; -+ goto done; -+ } - - err = btf_dedup_prep(d); - if (err) { -diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c -index e4f83c304ec92..7145463a4a562 100644 ---- a/tools/lib/bpf/libbpf.c -+++ b/tools/lib/bpf/libbpf.c -@@ -2993,6 +2993,12 @@ static int bpf_object__elf_collect(struct bpf_object *obj) - } - } - -+ if (!obj->efile.symbols) { -+ pr_warn("elf: couldn't find symbol table in %s, stripped object file?\n", -+ obj->path); -+ return -ENOENT; -+ } -+ - scn = NULL; - while ((scn = elf_nextscn(elf, scn)) != NULL) { - idx++; -@@ -5132,7 +5138,7 @@ static int bpf_core_apply_relo(struct bpf_program *prog, - * relocated, so it's enough to just subtract in-section offset - */ - insn_idx = insn_idx - prog->sec_insn_off; -- if (insn_idx > prog->insns_cnt) -+ if (insn_idx >= prog->insns_cnt) - return -EINVAL; - insn = &prog->insns[insn_idx]; - -diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h -index b22b50c1b173e..9cf66702fa8dd 100644 ---- a/tools/lib/bpf/skel_internal.h -+++ b/tools/lib/bpf/skel_internal.h -@@ -105,10 +105,12 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) - err = skel_sys_bpf(BPF_PROG_RUN, &attr, sizeof(attr)); - if (err < 0 || (int)attr.test.retval < 0) { - opts->errstr = "failed to execute loader prog"; -- if (err < 0) -+ if (err < 0) { - err = -errno; -- else -+ } else { - err = (int)attr.test.retval; -+ errno = -err; -+ } - goto out; - } - err = 0; -diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c -index 0893436cc09f8..77b51600e3e94 100644 ---- a/tools/objtool/arch/x86/decode.c -+++ b/tools/objtool/arch/x86/decode.c -@@ -659,6 +659,26 @@ const char *arch_nop_insn(int len) - return nops[len-1]; - } - -+#define BYTE_RET 0xC3 -+ -+const char *arch_ret_insn(int len) -+{ -+ static const char ret[5][5] = { -+ { BYTE_RET }, -+ { BYTE_RET, BYTES_NOP1 }, -+ { BYTE_RET, BYTES_NOP2 }, -+ { BYTE_RET, BYTES_NOP3 }, -+ { BYTE_RET, BYTES_NOP4 }, -+ }; -+ -+ if (len < 1 || len > 5) { -+ WARN("invalid RET size: %d\n", len); -+ return NULL; -+ } -+ -+ return ret[len-1]; -+} -+ - /* asm/alternative.h ? */ - - #define ALTINSTR_FLAG_INV (1 << 15) -diff --git a/tools/objtool/check.c b/tools/objtool/check.c -index 06b5c164ae931..81982948f981d 100644 ---- a/tools/objtool/check.c -+++ b/tools/objtool/check.c -@@ -173,6 +173,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, - "rewind_stack_do_exit", - "kunit_try_catch_throw", - "xen_start_kernel", -+ "cpu_bringup_and_idle", - }; - - if (!func) -@@ -828,6 +829,79 @@ static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *i - return insn->reloc; - } - -+static void remove_insn_ops(struct instruction *insn) -+{ -+ struct stack_op *op, *tmp; -+ -+ list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { -+ list_del(&op->list); -+ free(op); -+ } -+} -+ -+static void add_call_dest(struct objtool_file *file, struct instruction *insn, -+ struct symbol *dest, bool sibling) -+{ -+ struct reloc *reloc = insn_reloc(file, insn); -+ -+ insn->call_dest = dest; -+ if (!dest) -+ return; -+ -+ if (insn->call_dest->static_call_tramp) { -+ list_add_tail(&insn->call_node, -+ &file->static_call_list); -+ } -+ -+ /* -+ * Many compilers cannot disable KCOV with a function attribute -+ * so they need a little help, NOP out any KCOV calls from noinstr -+ * text. -+ */ -+ if (insn->sec->noinstr && -+ !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) { -+ if (reloc) { -+ reloc->type = R_NONE; -+ elf_write_reloc(file->elf, reloc); -+ } -+ -+ elf_write_insn(file->elf, insn->sec, -+ insn->offset, insn->len, -+ sibling ? arch_ret_insn(insn->len) -+ : arch_nop_insn(insn->len)); -+ -+ insn->type = sibling ? INSN_RETURN : INSN_NOP; -+ } -+ -+ if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) { -+ if (sibling) -+ WARN_FUNC("Tail call to __fentry__ !?!?", insn->sec, insn->offset); -+ -+ if (reloc) { -+ reloc->type = R_NONE; -+ elf_write_reloc(file->elf, reloc); -+ } -+ -+ elf_write_insn(file->elf, insn->sec, -+ insn->offset, insn->len, -+ arch_nop_insn(insn->len)); -+ -+ insn->type = INSN_NOP; -+ -+ list_add_tail(&insn->mcount_loc_node, -+ &file->mcount_loc_list); -+ } -+ -+ /* -+ * Whatever stack impact regular CALLs have, should be undone -+ * by the RETURN of the called function. -+ * -+ * Annotated intra-function calls retain the stack_ops but -+ * are converted to JUMP, see read_intra_function_calls(). -+ */ -+ remove_insn_ops(insn); -+} -+ - /* - * Find the destination instructions for all jumps. - */ -@@ -866,11 +940,7 @@ static int add_jump_destinations(struct objtool_file *file) - continue; - } else if (insn->func) { - /* internal or external sibling call (with reloc) */ -- insn->call_dest = reloc->sym; -- if (insn->call_dest->static_call_tramp) { -- list_add_tail(&insn->call_node, -- &file->static_call_list); -- } -+ add_call_dest(file, insn, reloc->sym, true); - continue; - } else if (reloc->sym->sec->idx) { - dest_sec = reloc->sym->sec; -@@ -926,13 +996,8 @@ static int add_jump_destinations(struct objtool_file *file) - - } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && - insn->jump_dest->offset == insn->jump_dest->func->offset) { -- - /* internal sibling call (without reloc) */ -- insn->call_dest = insn->jump_dest->func; -- if (insn->call_dest->static_call_tramp) { -- list_add_tail(&insn->call_node, -- &file->static_call_list); -- } -+ add_call_dest(file, insn, insn->jump_dest->func, true); - } - } - } -@@ -940,16 +1005,6 @@ static int add_jump_destinations(struct objtool_file *file) - return 0; - } - --static void remove_insn_ops(struct instruction *insn) --{ -- struct stack_op *op, *tmp; -- -- list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { -- list_del(&op->list); -- free(op); -- } --} -- - static struct symbol *find_call_destination(struct section *sec, unsigned long offset) - { - struct symbol *call_dest; -@@ -968,6 +1023,7 @@ static int add_call_destinations(struct objtool_file *file) - { - struct instruction *insn; - unsigned long dest_off; -+ struct symbol *dest; - struct reloc *reloc; - - for_each_insn(file, insn) { -@@ -977,7 +1033,9 @@ static int add_call_destinations(struct objtool_file *file) - reloc = insn_reloc(file, insn); - if (!reloc) { - dest_off = arch_jump_destination(insn); -- insn->call_dest = find_call_destination(insn->sec, dest_off); -+ dest = find_call_destination(insn->sec, dest_off); -+ -+ add_call_dest(file, insn, dest, false); - - if (insn->ignore) - continue; -@@ -995,9 +1053,8 @@ static int add_call_destinations(struct objtool_file *file) - - } else if (reloc->sym->type == STT_SECTION) { - dest_off = arch_dest_reloc_offset(reloc->addend); -- insn->call_dest = find_call_destination(reloc->sym->sec, -- dest_off); -- if (!insn->call_dest) { -+ dest = find_call_destination(reloc->sym->sec, dest_off); -+ if (!dest) { - WARN_FUNC("can't find call dest symbol at %s+0x%lx", - insn->sec, insn->offset, - reloc->sym->sec->name, -@@ -1005,6 +1062,8 @@ static int add_call_destinations(struct objtool_file *file) - return -1; - } - -+ add_call_dest(file, insn, dest, false); -+ - } else if (arch_is_retpoline(reloc->sym)) { - /* - * Retpoline calls are really dynamic calls in -@@ -1020,55 +1079,7 @@ static int add_call_destinations(struct objtool_file *file) - continue; - - } else -- insn->call_dest = reloc->sym; -- -- if (insn->call_dest && insn->call_dest->static_call_tramp) { -- list_add_tail(&insn->call_node, -- &file->static_call_list); -- } -- -- /* -- * Many compilers cannot disable KCOV with a function attribute -- * so they need a little help, NOP out any KCOV calls from noinstr -- * text. -- */ -- if (insn->sec->noinstr && -- !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) { -- if (reloc) { -- reloc->type = R_NONE; -- elf_write_reloc(file->elf, reloc); -- } -- -- elf_write_insn(file->elf, insn->sec, -- insn->offset, insn->len, -- arch_nop_insn(insn->len)); -- insn->type = INSN_NOP; -- } -- -- if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) { -- if (reloc) { -- reloc->type = R_NONE; -- elf_write_reloc(file->elf, reloc); -- } -- -- elf_write_insn(file->elf, insn->sec, -- insn->offset, insn->len, -- arch_nop_insn(insn->len)); -- -- insn->type = INSN_NOP; -- -- list_add_tail(&insn->mcount_loc_node, -- &file->mcount_loc_list); -- } -- -- /* -- * Whatever stack impact regular CALLs have, should be undone -- * by the RETURN of the called function. -- * -- * Annotated intra-function calls retain the stack_ops but -- * are converted to JUMP, see read_intra_function_calls(). -- */ -- remove_insn_ops(insn); -+ add_call_dest(file, insn, reloc->sym, false); - } - - return 0; -diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h -index 062bb6e9b8658..478e054fcdf71 100644 ---- a/tools/objtool/include/objtool/arch.h -+++ b/tools/objtool/include/objtool/arch.h -@@ -82,6 +82,7 @@ unsigned long arch_jump_destination(struct instruction *insn); - unsigned long arch_dest_reloc_offset(int addend); - - const char *arch_nop_insn(int len); -+const char *arch_ret_insn(int len); - - int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg); - -diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config -index 14e3e8d702a02..3c077f61d676d 100644 ---- a/tools/perf/Makefile.config -+++ b/tools/perf/Makefile.config -@@ -271,8 +271,6 @@ endif - - FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) - FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) --FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) --FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) - - FEATURE_CHECK_LDFLAGS-libaio = -lrt - -diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c -index 5d1fe9c35807a..137890f78e17a 100644 ---- a/tools/perf/bench/futex-lock-pi.c -+++ b/tools/perf/bench/futex-lock-pi.c -@@ -233,6 +233,7 @@ int bench_futex_lock_pi(int argc, const char **argv) - print_summary(); - - free(worker); -+ perf_cpu_map__put(cpu); - return ret; - err: - usage_with_options(bench_futex_lock_pi_usage, options); -diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c -index 97fe31fd3a236..f7a5ffebb9408 100644 ---- a/tools/perf/bench/futex-requeue.c -+++ b/tools/perf/bench/futex-requeue.c -@@ -294,6 +294,7 @@ int bench_futex_requeue(int argc, const char **argv) - print_summary(); - - free(worker); -+ perf_cpu_map__put(cpu); - return ret; - err: - usage_with_options(bench_futex_requeue_usage, options); -diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c -index e970e6b9ad535..0983f40b4b408 100644 ---- a/tools/perf/bench/futex-wake-parallel.c -+++ b/tools/perf/bench/futex-wake-parallel.c -@@ -329,6 +329,7 @@ int bench_futex_wake_parallel(int argc, const char **argv) - print_summary(); - - free(blocked_worker); -+ perf_cpu_map__put(cpu); - return ret; - } - #endif /* HAVE_PTHREAD_BARRIER */ -diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c -index 77f058a477903..2226a475e782b 100644 ---- a/tools/perf/bench/futex-wake.c -+++ b/tools/perf/bench/futex-wake.c -@@ -222,5 +222,6 @@ int bench_futex_wake(int argc, const char **argv) - print_summary(); - - free(worker); -+ perf_cpu_map__put(cpu); - return ret; - } -diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c -index 6ad191e731fc9..50c2e6892b3e9 100644 ---- a/tools/perf/builtin-inject.c -+++ b/tools/perf/builtin-inject.c -@@ -755,12 +755,16 @@ static int parse_vm_time_correlation(const struct option *opt, const char *str, - return inject->itrace_synth_opts.vm_tm_corr_args ? 0 : -ENOMEM; - } - -+static int output_fd(struct perf_inject *inject) -+{ -+ return inject->in_place_update ? -1 : perf_data__fd(&inject->output); -+} -+ - static int __cmd_inject(struct perf_inject *inject) - { - int ret = -EINVAL; - struct perf_session *session = inject->session; -- struct perf_data *data_out = &inject->output; -- int fd = inject->in_place_update ? -1 : perf_data__fd(data_out); -+ int fd = output_fd(inject); - u64 output_data_offset; - - signal(SIGINT, sig_handler); -@@ -819,7 +823,7 @@ static int __cmd_inject(struct perf_inject *inject) - inject->tool.ordered_events = true; - inject->tool.ordering_requires_timestamps = true; - /* Allow space in the header for new attributes */ -- output_data_offset = 4096; -+ output_data_offset = roundup(8192 + session->header.data_offset, 4096); - if (inject->strip) - strip_init(inject); - } -@@ -1006,7 +1010,7 @@ int cmd_inject(int argc, const char **argv) - } - - inject.session = __perf_session__new(&data, repipe, -- perf_data__fd(&inject.output), -+ output_fd(&inject), - &inject.tool); - if (IS_ERR(inject.session)) { - ret = PTR_ERR(inject.session); -@@ -1069,7 +1073,8 @@ out_delete: - zstd_fini(&(inject.session->zstd_data)); - perf_session__delete(inject.session); - out_close_output: -- perf_data__close(&inject.output); -+ if (!inject.in_place_update) -+ perf_data__close(&inject.output); - free(inject.itrace_synth_opts.vm_tm_corr_args); - return ret; - } -diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c -index a0316ce910db6..997e0a4b0902a 100644 ---- a/tools/perf/builtin-report.c -+++ b/tools/perf/builtin-report.c -@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep) - int ret; - struct perf_session *session = rep->session; - struct evlist *evlist = session->evlist; -- const char *help = perf_tip(system_path(TIPDIR)); -+ char *help = NULL, *path = NULL; - -- if (help == NULL) { -+ path = system_path(TIPDIR); -+ if (perf_tip(&help, path) || help == NULL) { - /* fallback for people who don't install perf ;-) */ -- help = perf_tip(DOCDIR); -- if (help == NULL) -- help = "Cannot load tips.txt file, please install perf!"; -+ free(path); -+ path = system_path(DOCDIR); -+ if (perf_tip(&help, path) || help == NULL) -+ help = strdup("Cannot load tips.txt file, please install perf!"); - } -+ free(path); - - switch (use_browser) { - case 1: -@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep) - ret = evlist__tty_browse_hists(evlist, rep, help); - break; - } -- -+ free(help); - return ret; - } - -diff --git a/tools/perf/tests/shell/record+zstd_comp_decomp.sh b/tools/perf/tests/shell/record+zstd_comp_decomp.sh -index 8a168cf8bacca..49bd875d51227 100755 ---- a/tools/perf/tests/shell/record+zstd_comp_decomp.sh -+++ b/tools/perf/tests/shell/record+zstd_comp_decomp.sh -@@ -12,7 +12,7 @@ skip_if_no_z_record() { - - collect_z_record() { - echo "Collecting compressed record file:" -- [[ "$(uname -m)" != s390x ]] && gflag='-g' -+ [ "$(uname -m)" != s390x ] && gflag='-g' - $perf_tool record -o $trace_file $gflag -z -F 5000 -- \ - dd count=500 if=/dev/urandom of=/dev/null - } -diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c -index c1f24d0048527..5075ecead5f3d 100644 ---- a/tools/perf/ui/hist.c -+++ b/tools/perf/ui/hist.c -@@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = { - #undef __HPP_SORT_ACC_FN - #undef __HPP_SORT_RAW_FN - -+static void fmt_free(struct perf_hpp_fmt *fmt) -+{ -+ /* -+ * At this point fmt should be completely -+ * unhooked, if not it's a bug. -+ */ -+ BUG_ON(!list_empty(&fmt->list)); -+ BUG_ON(!list_empty(&fmt->sort_list)); -+ -+ if (fmt->free) -+ fmt->free(fmt); -+} - - void perf_hpp__init(void) - { -@@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, - list_add(&format->sort_list, &list->sorts); - } - --void perf_hpp__column_unregister(struct perf_hpp_fmt *format) -+static void perf_hpp__column_unregister(struct perf_hpp_fmt *format) - { - list_del_init(&format->list); -+ fmt_free(format); - } - - void perf_hpp__cancel_cumulate(void) -@@ -672,19 +685,6 @@ next: - } - - --static void fmt_free(struct perf_hpp_fmt *fmt) --{ -- /* -- * At this point fmt should be completely -- * unhooked, if not it's a bug. -- */ -- BUG_ON(!list_empty(&fmt->list)); -- BUG_ON(!list_empty(&fmt->sort_list)); -- -- if (fmt->free) -- fmt->free(fmt); --} -- - void perf_hpp__reset_output_field(struct perf_hpp_list *list) - { - struct perf_hpp_fmt *fmt, *tmp; -diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c -index 58b7069c5a5f8..7054f23150e1b 100644 ---- a/tools/perf/util/arm-spe.c -+++ b/tools/perf/util/arm-spe.c -@@ -51,6 +51,7 @@ struct arm_spe { - u8 timeless_decoding; - u8 data_queued; - -+ u64 sample_type; - u8 sample_flc; - u8 sample_llc; - u8 sample_tlb; -@@ -248,6 +249,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe, - event->sample.header.size = sizeof(struct perf_event_header); - } - -+static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type) -+{ -+ event->header.size = perf_event__sample_event_size(sample, type, 0); -+ return perf_event__synthesize_sample(event, type, 0, sample); -+} -+ - static inline int - arm_spe_deliver_synth_event(struct arm_spe *spe, - struct arm_spe_queue *speq __maybe_unused, -@@ -256,6 +263,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe, - { - int ret; - -+ if (spe->synth_opts.inject) { -+ ret = arm_spe__inject_event(event, sample, spe->sample_type); -+ if (ret) -+ return ret; -+ } -+ - ret = perf_session__deliver_synth_event(spe->session, event, sample); - if (ret) - pr_err("ARM SPE: failed to deliver event, error %d\n", ret); -@@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session) - else - attr.sample_type |= PERF_SAMPLE_TIME; - -+ spe->sample_type = attr.sample_type; -+ - attr.exclude_user = evsel->core.attr.exclude_user; - attr.exclude_kernel = evsel->core.attr.exclude_kernel; - attr.exclude_hv = evsel->core.attr.exclude_hv; -diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c -index 1a7112a87736a..16ad0e6e9e9c5 100644 ---- a/tools/perf/util/bpf-event.c -+++ b/tools/perf/util/bpf-event.c -@@ -120,7 +120,11 @@ static int perf_env__fetch_btf(struct perf_env *env, - node->data_size = data_size; - memcpy(node->data, data, data_size); - -- perf_env__insert_btf(env, node); -+ if (!perf_env__insert_btf(env, node)) { -+ /* Insertion failed because of a duplicate. */ -+ free(node); -+ return -1; -+ } - return 0; - } - -@@ -576,7 +580,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, - synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, 0); - fprintf(fp, "# bpf_prog_info %u: %s addr 0x%llx size %u\n", - info->id, name, prog_addrs[0], prog_lens[0]); -- return; -+ goto out; - } - - fprintf(fp, "# bpf_prog_info %u:\n", info->id); -@@ -586,4 +590,6 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, - fprintf(fp, "# \tsub_prog %u: %s addr 0x%llx size %u\n", - i, name, prog_addrs[i], prog_lens[i]); - } -+out: -+ btf__free(btf); - } -diff --git a/tools/perf/util/bpf_skel/bperf.h b/tools/perf/util/bpf_skel/bperf.h -deleted file mode 100644 -index 186a5551ddb9d..0000000000000 ---- a/tools/perf/util/bpf_skel/bperf.h -+++ /dev/null -@@ -1,14 +0,0 @@ --// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) --// Copyright (c) 2021 Facebook -- --#ifndef __BPERF_STAT_H --#define __BPERF_STAT_H -- --typedef struct { -- __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); -- __uint(key_size, sizeof(__u32)); -- __uint(value_size, sizeof(struct bpf_perf_event_value)); -- __uint(max_entries, 1); --} reading_map; -- --#endif /* __BPERF_STAT_H */ -diff --git a/tools/perf/util/bpf_skel/bperf_follower.bpf.c b/tools/perf/util/bpf_skel/bperf_follower.bpf.c -index b8fa3cb2da230..6d2ea67b161ac 100644 ---- a/tools/perf/util/bpf_skel/bperf_follower.bpf.c -+++ b/tools/perf/util/bpf_skel/bperf_follower.bpf.c -@@ -4,11 +4,21 @@ - #include <linux/perf_event.h> - #include <bpf/bpf_helpers.h> - #include <bpf/bpf_tracing.h> --#include "bperf.h" - #include "bperf_u.h" - --reading_map diff_readings SEC(".maps"); --reading_map accum_readings SEC(".maps"); -+struct { -+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); -+ __uint(key_size, sizeof(__u32)); -+ __uint(value_size, sizeof(struct bpf_perf_event_value)); -+ __uint(max_entries, 1); -+} diff_readings SEC(".maps"); -+ -+struct { -+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); -+ __uint(key_size, sizeof(__u32)); -+ __uint(value_size, sizeof(struct bpf_perf_event_value)); -+ __uint(max_entries, 1); -+} accum_readings SEC(".maps"); - - struct { - __uint(type, BPF_MAP_TYPE_HASH); -diff --git a/tools/perf/util/bpf_skel/bperf_leader.bpf.c b/tools/perf/util/bpf_skel/bperf_leader.bpf.c -index 4f70d1459e86c..d82e1633a2e0a 100644 ---- a/tools/perf/util/bpf_skel/bperf_leader.bpf.c -+++ b/tools/perf/util/bpf_skel/bperf_leader.bpf.c -@@ -4,7 +4,6 @@ - #include <linux/perf_event.h> - #include <bpf/bpf_helpers.h> - #include <bpf/bpf_tracing.h> --#include "bperf.h" - - struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); -@@ -13,8 +12,19 @@ struct { - __uint(map_flags, BPF_F_PRESERVE_ELEMS); - } events SEC(".maps"); - --reading_map prev_readings SEC(".maps"); --reading_map diff_readings SEC(".maps"); -+struct { -+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); -+ __uint(key_size, sizeof(__u32)); -+ __uint(value_size, sizeof(struct bpf_perf_event_value)); -+ __uint(max_entries, 1); -+} prev_readings SEC(".maps"); -+ -+struct { -+ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); -+ __uint(key_size, sizeof(__u32)); -+ __uint(value_size, sizeof(struct bpf_perf_event_value)); -+ __uint(max_entries, 1); -+} diff_readings SEC(".maps"); - - SEC("raw_tp/sched_switch") - int BPF_PROG(on_switch) -diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c -index cf773f0dec384..5b24eb010336c 100644 ---- a/tools/perf/util/env.c -+++ b/tools/perf/util/env.c -@@ -74,12 +74,13 @@ out: - return node; - } - --void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) -+bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) - { - struct rb_node *parent = NULL; - __u32 btf_id = btf_node->id; - struct btf_node *node; - struct rb_node **p; -+ bool ret = true; - - down_write(&env->bpf_progs.lock); - p = &env->bpf_progs.btfs.rb_node; -@@ -93,6 +94,7 @@ void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) - p = &(*p)->rb_right; - } else { - pr_debug("duplicated btf %u\n", btf_id); -+ ret = false; - goto out; - } - } -@@ -102,6 +104,7 @@ void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) - env->bpf_progs.btfs_cnt++; - out: - up_write(&env->bpf_progs.lock); -+ return ret; - } - - struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id) -diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h -index 1383876f72b37..163e5ec503a26 100644 ---- a/tools/perf/util/env.h -+++ b/tools/perf/util/env.h -@@ -167,7 +167,7 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env, - struct bpf_prog_info_node *info_node); - struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, - __u32 prog_id); --void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); -+bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); - struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); - - int perf_env__numa_node(struct perf_env *env, int cpu); -diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c -index 65fe65ba03c25..b776465e04ef3 100644 ---- a/tools/perf/util/hist.c -+++ b/tools/perf/util/hist.c -@@ -289,15 +289,10 @@ static long hist_time(unsigned long htime) - return htime; - } - --static void he_stat__add_period(struct he_stat *he_stat, u64 period, -- u64 weight, u64 ins_lat, u64 p_stage_cyc) -+static void he_stat__add_period(struct he_stat *he_stat, u64 period) - { -- - he_stat->period += period; -- he_stat->weight += weight; - he_stat->nr_events += 1; -- he_stat->ins_lat += ins_lat; -- he_stat->p_stage_cyc += p_stage_cyc; - } - - static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) -@@ -308,9 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) - dest->period_guest_sys += src->period_guest_sys; - dest->period_guest_us += src->period_guest_us; - dest->nr_events += src->nr_events; -- dest->weight += src->weight; -- dest->ins_lat += src->ins_lat; -- dest->p_stage_cyc += src->p_stage_cyc; - } - - static void he_stat__decay(struct he_stat *he_stat) -@@ -598,9 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, - struct hist_entry *he; - int64_t cmp; - u64 period = entry->stat.period; -- u64 weight = entry->stat.weight; -- u64 ins_lat = entry->stat.ins_lat; -- u64 p_stage_cyc = entry->stat.p_stage_cyc; - bool leftmost = true; - - p = &hists->entries_in->rb_root.rb_node; -@@ -619,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, - - if (!cmp) { - if (sample_self) { -- he_stat__add_period(&he->stat, period, weight, ins_lat, p_stage_cyc); -+ he_stat__add_period(&he->stat, period); - hist_entry__add_callchain_period(he, period); - } - if (symbol_conf.cumulate_callchain) -- he_stat__add_period(he->stat_acc, period, weight, ins_lat, p_stage_cyc); -+ he_stat__add_period(he->stat_acc, period); - - /* - * This mem info was allocated from sample__resolve_mem -@@ -733,9 +722,6 @@ __hists__add_entry(struct hists *hists, - .stat = { - .nr_events = 1, - .period = sample->period, -- .weight = sample->weight, -- .ins_lat = sample->ins_lat, -- .p_stage_cyc = sample->p_stage_cyc, - }, - .parent = sym_parent, - .filtered = symbol__parent_filter(sym_parent) | al->filtered, -@@ -748,6 +734,9 @@ __hists__add_entry(struct hists *hists, - .raw_size = sample->raw_size, - .ops = ops, - .time = hist_time(sample->time), -+ .weight = sample->weight, -+ .ins_lat = sample->ins_lat, -+ .p_stage_cyc = sample->p_stage_cyc, - }, *he = hists__findnew_entry(hists, &entry, al, sample_self); - - if (!hists->has_callchains && he && he->callchain_size != 0) -diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h -index 5343b62476e60..621f35ae1efa5 100644 ---- a/tools/perf/util/hist.h -+++ b/tools/perf/util/hist.h -@@ -369,7 +369,6 @@ enum { - }; - - void perf_hpp__init(void); --void perf_hpp__column_unregister(struct perf_hpp_fmt *format); - void perf_hpp__cancel_cumulate(void); - void perf_hpp__setup_output_field(struct perf_hpp_list *list); - void perf_hpp__reset_output_field(struct perf_hpp_list *list); -diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build -index bc629359826fb..b41c2e9c6f887 100644 ---- a/tools/perf/util/intel-pt-decoder/Build -+++ b/tools/perf/util/intel-pt-decoder/Build -@@ -18,3 +18,5 @@ CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder - ifeq ($(CC_NO_CLANG), 1) - CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init - endif -+ -+CFLAGS_intel-pt-insn-decoder.o += -Wno-packed -diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -index 5ab631702769b..b0034ee4bba50 100644 ---- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -@@ -1204,61 +1204,69 @@ out_no_progress: - - static bool intel_pt_fup_event(struct intel_pt_decoder *decoder) - { -+ enum intel_pt_sample_type type = decoder->state.type; - bool ret = false; - -+ decoder->state.type &= ~INTEL_PT_BRANCH; -+ - if (decoder->set_fup_tx_flags) { - decoder->set_fup_tx_flags = false; - decoder->tx_flags = decoder->fup_tx_flags; -- decoder->state.type = INTEL_PT_TRANSACTION; -+ decoder->state.type |= INTEL_PT_TRANSACTION; - if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX) - decoder->state.type |= INTEL_PT_BRANCH; -- decoder->state.from_ip = decoder->ip; -- decoder->state.to_ip = 0; - decoder->state.flags = decoder->fup_tx_flags; -- return true; -+ ret = true; - } - if (decoder->set_fup_ptw) { - decoder->set_fup_ptw = false; -- decoder->state.type = INTEL_PT_PTW; -+ decoder->state.type |= INTEL_PT_PTW; - decoder->state.flags |= INTEL_PT_FUP_IP; -- decoder->state.from_ip = decoder->ip; -- decoder->state.to_ip = 0; - decoder->state.ptw_payload = decoder->fup_ptw_payload; -- return true; -+ ret = true; - } - if (decoder->set_fup_mwait) { - decoder->set_fup_mwait = false; -- decoder->state.type = INTEL_PT_MWAIT_OP; -- decoder->state.from_ip = decoder->ip; -- decoder->state.to_ip = 0; -+ decoder->state.type |= INTEL_PT_MWAIT_OP; - decoder->state.mwait_payload = decoder->fup_mwait_payload; - ret = true; - } - if (decoder->set_fup_pwre) { - decoder->set_fup_pwre = false; - decoder->state.type |= INTEL_PT_PWR_ENTRY; -- decoder->state.type &= ~INTEL_PT_BRANCH; -- decoder->state.from_ip = decoder->ip; -- decoder->state.to_ip = 0; - decoder->state.pwre_payload = decoder->fup_pwre_payload; - ret = true; - } - if (decoder->set_fup_exstop) { - decoder->set_fup_exstop = false; - decoder->state.type |= INTEL_PT_EX_STOP; -- decoder->state.type &= ~INTEL_PT_BRANCH; - decoder->state.flags |= INTEL_PT_FUP_IP; -- decoder->state.from_ip = decoder->ip; -- decoder->state.to_ip = 0; - ret = true; - } - if (decoder->set_fup_bep) { - decoder->set_fup_bep = false; - decoder->state.type |= INTEL_PT_BLK_ITEMS; -- decoder->state.type &= ~INTEL_PT_BRANCH; -+ ret = true; -+ } -+ if (decoder->overflow) { -+ decoder->overflow = false; -+ if (!ret && !decoder->pge) { -+ if (decoder->hop) { -+ decoder->state.type = 0; -+ decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; -+ } -+ decoder->pge = true; -+ decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN; -+ decoder->state.from_ip = 0; -+ decoder->state.to_ip = decoder->ip; -+ return true; -+ } -+ } -+ if (ret) { - decoder->state.from_ip = decoder->ip; - decoder->state.to_ip = 0; -- ret = true; -+ } else { -+ decoder->state.type = type; - } - return ret; - } -@@ -1607,7 +1615,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) - intel_pt_clear_tx_flags(decoder); - intel_pt_set_nr(decoder); - decoder->timestamp_insn_cnt = 0; -- decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; -+ decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; -+ decoder->state.from_ip = decoder->ip; -+ decoder->ip = 0; -+ decoder->pge = false; -+ decoder->set_fup_tx_flags = false; -+ decoder->set_fup_ptw = false; -+ decoder->set_fup_mwait = false; -+ decoder->set_fup_pwre = false; -+ decoder->set_fup_exstop = false; -+ decoder->set_fup_bep = false; - decoder->overflow = true; - return -EOVERFLOW; - } -@@ -2665,6 +2682,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder); - /* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */ - static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err) - { -+ *err = 0; -+ - /* Leap from PSB to PSB, getting ip from FUP within PSB+ */ - if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) { - *err = intel_pt_scan_for_psb(decoder); -@@ -2677,6 +2696,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in - return HOP_IGNORE; - - case INTEL_PT_TIP_PGD: -+ decoder->pge = false; - if (!decoder->packet.count) { - intel_pt_set_nr(decoder); - return HOP_IGNORE; -@@ -2704,18 +2724,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in - if (!decoder->packet.count) - return HOP_IGNORE; - intel_pt_set_ip(decoder); -- if (intel_pt_fup_event(decoder)) -- return HOP_RETURN; -- if (!decoder->branch_enable) -+ if (decoder->set_fup_mwait || decoder->set_fup_pwre) -+ *no_tip = true; -+ if (!decoder->branch_enable || !decoder->pge) - *no_tip = true; - if (*no_tip) { - decoder->state.type = INTEL_PT_INSTRUCTION; - decoder->state.from_ip = decoder->ip; - decoder->state.to_ip = 0; -+ intel_pt_fup_event(decoder); - return HOP_RETURN; - } -+ intel_pt_fup_event(decoder); -+ decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH; - *err = intel_pt_walk_fup_tip(decoder); -- if (!*err) -+ if (!*err && decoder->state.to_ip) - decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; - return HOP_RETURN; - -@@ -2896,7 +2919,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err) - { - struct intel_pt_psb_info data = { .fup = false }; - -- if (!decoder->branch_enable || !decoder->pge) -+ if (!decoder->branch_enable) - return false; - - intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data); -@@ -2923,6 +2946,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) - if (err) - return err; - next: -+ err = 0; - if (decoder->cyc_threshold) { - if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC) - decoder->sample_cyc = false; -@@ -2961,6 +2985,7 @@ next: - - case INTEL_PT_TIP_PGE: { - decoder->pge = true; -+ decoder->overflow = false; - intel_pt_mtc_cyc_cnt_pge(decoder); - intel_pt_set_nr(decoder); - if (decoder->packet.count == 0) { -@@ -2998,7 +3023,7 @@ next: - break; - } - intel_pt_set_last_ip(decoder); -- if (!decoder->branch_enable) { -+ if (!decoder->branch_enable || !decoder->pge) { - decoder->ip = decoder->last_ip; - if (intel_pt_fup_event(decoder)) - return 0; -@@ -3466,10 +3491,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) - decoder->set_fup_pwre = false; - decoder->set_fup_exstop = false; - decoder->set_fup_bep = false; -+ decoder->overflow = false; - - if (!decoder->branch_enable) { - decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; -- decoder->overflow = false; - decoder->state.type = 0; /* Do not have a sample */ - return 0; - } -@@ -3484,7 +3509,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) - decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; - else - decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; -- decoder->overflow = false; - - decoder->state.from_ip = 0; - decoder->state.to_ip = decoder->ip; -@@ -3606,7 +3630,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) - } - - decoder->have_last_ip = true; -- decoder->pkt_state = INTEL_PT_STATE_NO_IP; -+ decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; - - err = intel_pt_walk_psb(decoder); - if (err) -@@ -3703,7 +3727,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) - - if (err) { - decoder->state.err = intel_pt_ext_err(err); -- decoder->state.from_ip = decoder->ip; -+ if (err != -EOVERFLOW) -+ decoder->state.from_ip = decoder->ip; - intel_pt_update_sample_time(decoder); - decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; - intel_pt_set_nr(decoder); -diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c -index 6f852b305e92b..824bceb063bfe 100644 ---- a/tools/perf/util/intel-pt.c -+++ b/tools/perf/util/intel-pt.c -@@ -2510,6 +2510,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) - ptq->sync_switch = false; - intel_pt_next_tid(pt, ptq); - } -+ ptq->timestamp = state->est_timestamp; - if (pt->synth_opts.errors) { - err = intel_ptq_synth_error(ptq, state); - if (err) -diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c -index 20bacd5972ade..34f1b1b1176c7 100644 ---- a/tools/perf/util/smt.c -+++ b/tools/perf/util/smt.c -@@ -15,7 +15,7 @@ int smt_on(void) - if (cached) - return cached_result; - -- if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) > 0) -+ if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) - goto done; - - ncpu = sysconf(_SC_NPROCESSORS_CONF); -diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c -index 568a88c001c6c..a111065b484ef 100644 ---- a/tools/perf/util/sort.c -+++ b/tools/perf/util/sort.c -@@ -1325,88 +1325,68 @@ struct sort_entry sort_mispredict = { - .se_width_idx = HISTC_MISPREDICT, - }; - --static u64 he_weight(struct hist_entry *he) --{ -- return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0; --} -- - static int64_t --sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) -+sort__weight_cmp(struct hist_entry *left, struct hist_entry *right) - { -- return he_weight(left) - he_weight(right); -+ return left->weight - right->weight; - } - - static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) - { -- return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); -+ return repsep_snprintf(bf, size, "%-*llu", width, he->weight); - } - - struct sort_entry sort_local_weight = { - .se_header = "Local Weight", -- .se_cmp = sort__local_weight_cmp, -+ .se_cmp = sort__weight_cmp, - .se_snprintf = hist_entry__local_weight_snprintf, - .se_width_idx = HISTC_LOCAL_WEIGHT, - }; - --static int64_t --sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right) --{ -- return left->stat.weight - right->stat.weight; --} -- - static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) - { -- return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); -+ return repsep_snprintf(bf, size, "%-*llu", width, -+ he->weight * he->stat.nr_events); - } - - struct sort_entry sort_global_weight = { - .se_header = "Weight", -- .se_cmp = sort__global_weight_cmp, -+ .se_cmp = sort__weight_cmp, - .se_snprintf = hist_entry__global_weight_snprintf, - .se_width_idx = HISTC_GLOBAL_WEIGHT, - }; - --static u64 he_ins_lat(struct hist_entry *he) --{ -- return he->stat.nr_events ? he->stat.ins_lat / he->stat.nr_events : 0; --} -- - static int64_t --sort__local_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) -+sort__ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) - { -- return he_ins_lat(left) - he_ins_lat(right); -+ return left->ins_lat - right->ins_lat; - } - - static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) - { -- return repsep_snprintf(bf, size, "%-*u", width, he_ins_lat(he)); -+ return repsep_snprintf(bf, size, "%-*u", width, he->ins_lat); - } - - struct sort_entry sort_local_ins_lat = { - .se_header = "Local INSTR Latency", -- .se_cmp = sort__local_ins_lat_cmp, -+ .se_cmp = sort__ins_lat_cmp, - .se_snprintf = hist_entry__local_ins_lat_snprintf, - .se_width_idx = HISTC_LOCAL_INS_LAT, - }; - --static int64_t --sort__global_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) --{ -- return left->stat.ins_lat - right->stat.ins_lat; --} -- - static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) - { -- return repsep_snprintf(bf, size, "%-*u", width, he->stat.ins_lat); -+ return repsep_snprintf(bf, size, "%-*u", width, -+ he->ins_lat * he->stat.nr_events); - } - - struct sort_entry sort_global_ins_lat = { - .se_header = "INSTR Latency", -- .se_cmp = sort__global_ins_lat_cmp, -+ .se_cmp = sort__ins_lat_cmp, - .se_snprintf = hist_entry__global_ins_lat_snprintf, - .se_width_idx = HISTC_GLOBAL_INS_LAT, - }; -@@ -1414,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = { - static int64_t - sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right) - { -- return left->stat.p_stage_cyc - right->stat.p_stage_cyc; -+ return left->p_stage_cyc - right->p_stage_cyc; - } - - static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) - { -- return repsep_snprintf(bf, size, "%-*u", width, he->stat.p_stage_cyc); -+ return repsep_snprintf(bf, size, "%-*u", width, he->p_stage_cyc); - } - - struct sort_entry sort_p_stage_cyc = { -diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h -index b67c469aba795..7b7145501933f 100644 ---- a/tools/perf/util/sort.h -+++ b/tools/perf/util/sort.h -@@ -49,9 +49,6 @@ struct he_stat { - u64 period_us; - u64 period_guest_sys; - u64 period_guest_us; -- u64 weight; -- u64 ins_lat; -- u64 p_stage_cyc; - u32 nr_events; - }; - -@@ -109,6 +106,9 @@ struct hist_entry { - s32 socket; - s32 cpu; - u64 code_page_size; -+ u64 weight; -+ u64 ins_lat; -+ u64 p_stage_cyc; - u8 cpumode; - u8 depth; - -diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c -index 37a9492edb3eb..df3c4671be72a 100644 ---- a/tools/perf/util/util.c -+++ b/tools/perf/util/util.c -@@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str, - return 0; - } - --const char *perf_tip(const char *dirpath) -+int perf_tip(char **strp, const char *dirpath) - { - struct strlist *tips; - struct str_node *node; -- char *tip = NULL; - struct strlist_config conf = { - .dirname = dirpath, - .file_only = true, - }; -+ int ret = 0; - -+ *strp = NULL; - tips = strlist__new("tips.txt", &conf); - if (tips == NULL) -- return errno == ENOENT ? NULL : -- "Tip: check path of tips.txt or get more memory! ;-p"; -+ return -errno; - - if (strlist__nr_entries(tips) == 0) - goto out; - - node = strlist__entry(tips, random() % strlist__nr_entries(tips)); -- if (asprintf(&tip, "Tip: %s", node->s) < 0) -- tip = (char *)"Tip: get more memory! ;-)"; -+ if (asprintf(strp, "Tip: %s", node->s) < 0) -+ ret = -ENOMEM; - - out: - strlist__delete(tips); - -- return tip; -+ return ret; - } - - char *perf_exe(char *buf, int len) -diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h -index ad737052e5977..9f0d36ba77f2d 100644 ---- a/tools/perf/util/util.h -+++ b/tools/perf/util/util.h -@@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint, - #define KVER_FMT "%d.%d.%d" - #define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) - --const char *perf_tip(const char *dirpath); -+int perf_tip(char **strp, const char *dirpath); - - #ifndef HAVE_SCHED_GETCPU_SUPPORT - int sched_getcpu(void); -diff --git a/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c b/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c -index 762f6a9da8b5e..664ffc0364f4f 100644 ---- a/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c -+++ b/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c -@@ -90,7 +90,7 @@ static void print_err_line(void) - - static void test_conn(void) - { -- int listen_fd = -1, cli_fd = -1, err; -+ int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; - socklen_t addrlen = sizeof(srv_sa6); - int srv_port; - -@@ -112,6 +112,10 @@ static void test_conn(void) - if (CHECK_FAIL(cli_fd == -1)) - goto done; - -+ srv_fd = accept(listen_fd, NULL, NULL); -+ if (CHECK_FAIL(srv_fd == -1)) -+ goto done; -+ - if (CHECK(skel->bss->listen_tp_sport != srv_port || - skel->bss->req_sk_sport != srv_port, - "Unexpected sk src port", -@@ -134,11 +138,13 @@ done: - close(listen_fd); - if (cli_fd != -1) - close(cli_fd); -+ if (srv_fd != -1) -+ close(srv_fd); - } - - static void test_syncookie(void) - { -- int listen_fd = -1, cli_fd = -1, err; -+ int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; - socklen_t addrlen = sizeof(srv_sa6); - int srv_port; - -@@ -161,6 +167,10 @@ static void test_syncookie(void) - if (CHECK_FAIL(cli_fd == -1)) - goto done; - -+ srv_fd = accept(listen_fd, NULL, NULL); -+ if (CHECK_FAIL(srv_fd == -1)) -+ goto done; -+ - if (CHECK(skel->bss->listen_tp_sport != srv_port, - "Unexpected tp src port", - "listen_tp_sport:%u expected:%u\n", -@@ -188,6 +198,8 @@ done: - close(listen_fd); - if (cli_fd != -1) - close(cli_fd); -+ if (srv_fd != -1) -+ close(srv_fd); - } - - struct test { -diff --git a/tools/testing/selftests/bpf/prog_tests/perf_buffer.c b/tools/testing/selftests/bpf/prog_tests/perf_buffer.c -index 6490e9673002f..7daaaab13681b 100644 ---- a/tools/testing/selftests/bpf/prog_tests/perf_buffer.c -+++ b/tools/testing/selftests/bpf/prog_tests/perf_buffer.c -@@ -107,8 +107,8 @@ void test_perf_buffer(void) - "expect %d, seen %d\n", nr_on_cpus, CPU_COUNT(&cpu_seen))) - goto out_free_pb; - -- if (CHECK(perf_buffer__buffer_cnt(pb) != nr_cpus, "buf_cnt", -- "got %zu, expected %d\n", perf_buffer__buffer_cnt(pb), nr_cpus)) -+ if (CHECK(perf_buffer__buffer_cnt(pb) != nr_on_cpus, "buf_cnt", -+ "got %zu, expected %d\n", perf_buffer__buffer_cnt(pb), nr_on_cpus)) - goto out_close; - - for (i = 0; i < nr_cpus; i++) { -diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c -index aee41547e7f45..6db07401bc493 100644 ---- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c -+++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c -@@ -598,7 +598,7 @@ close: - - static void run_lookup_prog(const struct test *t) - { -- int server_fds[MAX_SERVERS] = { -1 }; -+ int server_fds[] = { [0 ... MAX_SERVERS - 1] = -1 }; - int client_fd, reuse_conn_fd = -1; - struct bpf_link *lookup_link; - int i, err; -@@ -1053,7 +1053,7 @@ static void run_sk_assign(struct test_sk_lookup *skel, - struct bpf_program *lookup_prog, - const char *remote_ip, const char *local_ip) - { -- int server_fds[MAX_SERVERS] = { -1 }; -+ int server_fds[] = { [0 ... MAX_SERVERS - 1] = -1 }; - struct bpf_sk_lookup ctx; - __u64 server_cookie; - int i, err; -diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c -index 0252f61d611a9..97d8a6f84f4ab 100644 ---- a/tools/testing/selftests/bpf/prog_tests/test_ima.c -+++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c -@@ -43,7 +43,7 @@ static int process_sample(void *ctx, void *data, size_t len) - void test_test_ima(void) - { - char measured_dir_template[] = "/tmp/ima_measuredXXXXXX"; -- struct ring_buffer *ringbuf; -+ struct ring_buffer *ringbuf = NULL; - const char *measured_dir; - char cmd[256]; - -@@ -85,5 +85,6 @@ close_clean: - err = system(cmd); - CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno); - close_prog: -+ ring_buffer__free(ringbuf); - ima__destroy(skel); - } -diff --git a/tools/testing/selftests/bpf/progs/strobemeta.h b/tools/testing/selftests/bpf/progs/strobemeta.h -index 7de534f38c3f1..60c93aee2f4ad 100644 ---- a/tools/testing/selftests/bpf/progs/strobemeta.h -+++ b/tools/testing/selftests/bpf/progs/strobemeta.h -@@ -358,7 +358,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg, - void *payload) - { - void *location; -- uint32_t len; -+ uint64_t len; - - data->str_lens[idx] = 0; - location = calc_location(&cfg->str_locs[idx], tls_base); -@@ -390,7 +390,7 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, - struct strobe_map_descr* descr = &data->map_descrs[idx]; - struct strobe_map_raw map; - void *location; -- uint32_t len; -+ uint64_t len; - int i; - - descr->tag_len = 0; /* presume no tag is set */ -diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c -index cc1cd240445d2..e3fea6f281e4b 100644 ---- a/tools/testing/selftests/bpf/test_progs.c -+++ b/tools/testing/selftests/bpf/test_progs.c -@@ -370,7 +370,7 @@ int extract_build_id(char *build_id, size_t size) - - if (getline(&line, &len, fp) == -1) - goto err; -- fclose(fp); -+ pclose(fp); - - if (len > size) - len = size; -@@ -379,7 +379,7 @@ int extract_build_id(char *build_id, size_t size) - free(line); - return 0; - err: -- fclose(fp); -+ pclose(fp); - return -1; - } - -diff --git a/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh b/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh -index 1538373157e3c..bedff7aa7023f 100755 ---- a/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh -+++ b/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh -@@ -2,11 +2,11 @@ - # SPDX-License-Identifier: GPL-2.0 - # - # Test topology: --# - - - - - - - - - - - - - - - - - - - - - - - - - --# | veth1 veth2 veth3 | ... init net -+# - - - - - - - - - - - - - - - - - - - -+# | veth1 veth2 veth3 | ns0 - # - -| - - - - - - | - - - - - - | - - - # --------- --------- --------- --# | veth0 | | veth0 | | veth0 | ... -+# | veth0 | | veth0 | | veth0 | - # --------- --------- --------- - # ns1 ns2 ns3 - # -@@ -31,6 +31,7 @@ IFACES="" - DRV_MODE="xdpgeneric xdpdrv xdpegress" - PASS=0 - FAIL=0 -+LOG_DIR=$(mktemp -d) - - test_pass() - { -@@ -50,6 +51,7 @@ clean_up() - ip link del veth$i 2> /dev/null - ip netns del ns$i 2> /dev/null - done -+ ip netns del ns0 2> /dev/null - } - - # Kselftest framework requirement - SKIP code is 4. -@@ -77,10 +79,12 @@ setup_ns() - mode="xdpdrv" - fi - -+ ip netns add ns0 - for i in $(seq $NUM); do - ip netns add ns$i -- ip link add veth$i type veth peer name veth0 netns ns$i -- ip link set veth$i up -+ ip -n ns$i link add veth0 index 2 type veth \ -+ peer name veth$i netns ns0 index $((1 + $i)) -+ ip -n ns0 link set veth$i up - ip -n ns$i link set veth0 up - - ip -n ns$i addr add 192.0.2.$i/24 dev veth0 -@@ -91,7 +95,7 @@ setup_ns() - xdp_dummy.o sec xdp_dummy &> /dev/null || \ - { test_fail "Unable to load dummy xdp" && exit 1; } - IFACES="$IFACES veth$i" -- veth_mac[$i]=$(ip link show veth$i | awk '/link\/ether/ {print $2}') -+ veth_mac[$i]=$(ip -n ns0 link show veth$i | awk '/link\/ether/ {print $2}') - done - } - -@@ -100,17 +104,17 @@ do_egress_tests() - local mode=$1 - - # mac test -- ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-2_${mode}.log & -- ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-3_${mode}.log & -+ ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-2_${mode}.log & -+ ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-3_${mode}.log & - sleep 0.5 - ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null - sleep 0.5 -- pkill -9 tcpdump -+ pkill tcpdump - - # mac check -- grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" mac_ns1-2_${mode}.log && \ -+ grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-2_${mode}.log && \ - test_pass "$mode mac ns1-2" || test_fail "$mode mac ns1-2" -- grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" mac_ns1-3_${mode}.log && \ -+ grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-3_${mode}.log && \ - test_pass "$mode mac ns1-3" || test_fail "$mode mac ns1-3" - } - -@@ -121,46 +125,46 @@ do_ping_tests() - # ping6 test: echo request should be redirect back to itself, not others - ip netns exec ns1 ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02 - -- ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ns1-1_${mode}.log & -- ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ns1-2_${mode}.log & -- ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ns1-3_${mode}.log & -+ ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-1_${mode}.log & -+ ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-2_${mode}.log & -+ ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-3_${mode}.log & - sleep 0.5 - # ARP test -- ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null -+ ip netns exec ns1 arping -q -c 2 -I veth0 192.0.2.254 - # IPv4 test - ip netns exec ns1 ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null - # IPv6 test - ip netns exec ns1 ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null - sleep 0.5 -- pkill -9 tcpdump -+ pkill tcpdump - - # All netns should receive the redirect arp requests -- [ $(grep -c "who-has 192.0.2.254" ns1-1_${mode}.log) -gt 4 ] && \ -+ [ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \ - test_pass "$mode arp(F_BROADCAST) ns1-1" || \ - test_fail "$mode arp(F_BROADCAST) ns1-1" -- [ $(grep -c "who-has 192.0.2.254" ns1-2_${mode}.log) -le 4 ] && \ -+ [ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-2_${mode}.log) -eq 2 ] && \ - test_pass "$mode arp(F_BROADCAST) ns1-2" || \ - test_fail "$mode arp(F_BROADCAST) ns1-2" -- [ $(grep -c "who-has 192.0.2.254" ns1-3_${mode}.log) -le 4 ] && \ -+ [ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-3_${mode}.log) -eq 2 ] && \ - test_pass "$mode arp(F_BROADCAST) ns1-3" || \ - test_fail "$mode arp(F_BROADCAST) ns1-3" - - # ns1 should not receive the redirect echo request, others should -- [ $(grep -c "ICMP echo request" ns1-1_${mode}.log) -eq 4 ] && \ -+ [ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \ - test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1" || \ - test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1" -- [ $(grep -c "ICMP echo request" ns1-2_${mode}.log) -eq 4 ] && \ -+ [ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 4 ] && \ - test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2" || \ - test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2" -- [ $(grep -c "ICMP echo request" ns1-3_${mode}.log) -eq 4 ] && \ -+ [ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-3_${mode}.log) -eq 4 ] && \ - test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3" || \ - test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3" - - # ns1 should receive the echo request, ns2 should not -- [ $(grep -c "ICMP6, echo request" ns1-1_${mode}.log) -eq 4 ] && \ -+ [ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \ - test_pass "$mode IPv6 (no flags) ns1-1" || \ - test_fail "$mode IPv6 (no flags) ns1-1" -- [ $(grep -c "ICMP6, echo request" ns1-2_${mode}.log) -eq 0 ] && \ -+ [ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 0 ] && \ - test_pass "$mode IPv6 (no flags) ns1-2" || \ - test_fail "$mode IPv6 (no flags) ns1-2" - } -@@ -176,9 +180,13 @@ do_tests() - xdpgeneric) drv_p="-S";; - esac - -- ./xdp_redirect_multi $drv_p $IFACES &> xdp_redirect_${mode}.log & -+ ip netns exec ns0 ./xdp_redirect_multi $drv_p $IFACES &> ${LOG_DIR}/xdp_redirect_${mode}.log & - xdp_pid=$! - sleep 1 -+ if ! ps -p $xdp_pid > /dev/null; then -+ test_fail "$mode xdp_redirect_multi start failed" -+ return 1 -+ fi - - if [ "$mode" = "xdpegress" ]; then - do_egress_tests $mode -@@ -189,16 +197,16 @@ do_tests() - kill $xdp_pid - } - --trap clean_up 0 2 3 6 9 -+trap clean_up EXIT - - check_env --rm -f xdp_redirect_*.log ns*.log mac_ns*.log - - for mode in ${DRV_MODE}; do - setup_ns $mode - do_tests $mode - clean_up - done -+rm -rf ${LOG_DIR} - - echo "Summary: PASS $PASS, FAIL $FAIL" - [ $FAIL -eq 0 ] && exit 0 || exit 1 -diff --git a/tools/testing/selftests/bpf/verifier/array_access.c b/tools/testing/selftests/bpf/verifier/array_access.c -index 1b1c798e92489..1b138cd2b187d 100644 ---- a/tools/testing/selftests/bpf/verifier/array_access.c -+++ b/tools/testing/selftests/bpf/verifier/array_access.c -@@ -186,7 +186,7 @@ - }, - .fixup_map_hash_48b = { 3 }, - .errstr_unpriv = "R0 leaks addr", -- .errstr = "R0 unbounded memory access", -+ .errstr = "invalid access to map value, value_size=48 off=44 size=8", - .result_unpriv = REJECT, - .result = REJECT, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -diff --git a/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c b/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c -index 6e52dfc644153..6fb52d8cfd889 100644 ---- a/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c -+++ b/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c -@@ -71,6 +71,8 @@ - BPF_EXIT_INSN(), - }, - .result = ACCEPT, -+ .result_unpriv = REJECT, -+ .errstr_unpriv = "R0 leaks addr into mem", - }, - { - "Can't use cmpxchg on uninit src reg", -@@ -118,4 +120,88 @@ - BPF_EXIT_INSN(), - }, - .result = ACCEPT, -+ .result_unpriv = REJECT, -+ .errstr_unpriv = "R0 leaks addr into mem", -+}, -+{ -+ "Dest pointer in r0 - succeed, check 2", -+ .insns = { -+ /* r0 = &val */ -+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_10), -+ /* val = r0; */ -+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), -+ /* r5 = &val */ -+ BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), -+ /* r0 = atomic_cmpxchg(&val, r0, r5); */ -+ BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), -+ /* r1 = *r0 */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8), -+ /* exit(0); */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .result_unpriv = REJECT, -+ .errstr_unpriv = "R0 leaks addr into mem", -+}, -+{ -+ "Dest pointer in r0 - succeed, check 3", -+ .insns = { -+ /* r0 = &val */ -+ BPF_MOV64_REG(BPF_REG_0, BPF_REG_10), -+ /* val = r0; */ -+ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), -+ /* r5 = &val */ -+ BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), -+ /* r0 = atomic_cmpxchg(&val, r0, r5); */ -+ BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), -+ /* exit(0); */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = REJECT, -+ .errstr = "invalid size of register fill", -+ .errstr_unpriv = "R0 leaks addr into mem", -+}, -+{ -+ "Dest pointer in r0 - succeed, check 4", -+ .insns = { -+ /* r0 = &val */ -+ BPF_MOV32_REG(BPF_REG_0, BPF_REG_10), -+ /* val = r0; */ -+ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8), -+ /* r5 = &val */ -+ BPF_MOV32_REG(BPF_REG_5, BPF_REG_10), -+ /* r0 = atomic_cmpxchg(&val, r0, r5); */ -+ BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), -+ /* r1 = *r10 */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -8), -+ /* exit(0); */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .result_unpriv = REJECT, -+ .errstr_unpriv = "R10 partial copy of pointer", -+}, -+{ -+ "Dest pointer in r0 - succeed, check 5", -+ .insns = { -+ /* r0 = &val */ -+ BPF_MOV32_REG(BPF_REG_0, BPF_REG_10), -+ /* val = r0; */ -+ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8), -+ /* r5 = &val */ -+ BPF_MOV32_REG(BPF_REG_5, BPF_REG_10), -+ /* r0 = atomic_cmpxchg(&val, r0, r5); */ -+ BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), -+ /* r1 = *r0 */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -8), -+ /* exit(0); */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = REJECT, -+ .errstr = "R0 invalid mem access", -+ .errstr_unpriv = "R10 partial copy of pointer", - }, -diff --git a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c -index 2debba4e8a3a8..4d347bc53aa28 100644 ---- a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c -+++ b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c -@@ -1077,6 +1077,29 @@ - .errstr = "R0 invalid mem access 'inv'", - .errstr_unpriv = "R0 pointer -= pointer prohibited", - }, -+{ -+ "map access: trying to leak tained dst reg", -+ .insns = { -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), -+ BPF_LD_MAP_FD(BPF_REG_1, 0), -+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), -+ BPF_EXIT_INSN(), -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), -+ BPF_MOV32_IMM(BPF_REG_1, 0xFFFFFFFF), -+ BPF_MOV32_REG(BPF_REG_1, BPF_REG_1), -+ BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1), -+ BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 0), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .fixup_map_array_48b = { 4 }, -+ .result = REJECT, -+ .errstr = "math between map_value pointer and 4294967295 is not allowed", -+}, - { - "32bit pkt_ptr -= scalar", - .insns = { -diff --git a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c -index bfb97383e6b5a..b4ec228eb95d0 100644 ---- a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c -+++ b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c -@@ -35,7 +35,7 @@ - .prog_type = BPF_PROG_TYPE_XDP, - }, - { -- "XDP pkt read, pkt_data' > pkt_end, good access", -+ "XDP pkt read, pkt_data' > pkt_end, corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -@@ -87,6 +87,41 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_data' > pkt_end, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data' > pkt_end, corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_end > pkt_data', good access", - .insns = { -@@ -106,16 +141,16 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_end > pkt_data', bad access 1", -+ "XDP pkt read, pkt_end > pkt_data', corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, - offsetof(struct xdp_md, data_end)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), - BPF_JMP_IMM(BPF_JA, 0, 0, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -142,6 +177,42 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_end > pkt_data', corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_end > pkt_data', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_data' < pkt_end, good access", - .insns = { -@@ -161,16 +232,16 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data' < pkt_end, bad access 1", -+ "XDP pkt read, pkt_data' < pkt_end, corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, - offsetof(struct xdp_md, data_end)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), - BPF_JMP_IMM(BPF_JA, 0, 0, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -198,7 +269,43 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_end < pkt_data', good access", -+ "XDP pkt read, pkt_data' < pkt_end, corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data' < pkt_end, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_end < pkt_data', corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -@@ -250,6 +357,41 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_end < pkt_data', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_end < pkt_data', corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_data' >= pkt_end, good access", - .insns = { -@@ -268,15 +410,15 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data' >= pkt_end, bad access 1", -+ "XDP pkt read, pkt_data' >= pkt_end, corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, - offsetof(struct xdp_md, data_end)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -304,7 +446,41 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_end >= pkt_data', good access", -+ "XDP pkt read, pkt_data' >= pkt_end, corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data' >= pkt_end, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_end >= pkt_data', corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -@@ -359,7 +535,44 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data' <= pkt_end, good access", -+ "XDP pkt read, pkt_end >= pkt_data', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_end >= pkt_data', corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data' <= pkt_end, corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -@@ -413,6 +626,43 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_data' <= pkt_end, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data' <= pkt_end, corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_end <= pkt_data', good access", - .insns = { -@@ -431,15 +681,15 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_end <= pkt_data', bad access 1", -+ "XDP pkt read, pkt_end <= pkt_data', corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, - offsetof(struct xdp_md, data_end)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -467,7 +717,41 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_meta' > pkt_data, good access", -+ "XDP pkt read, pkt_end <= pkt_data', corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_end <= pkt_data', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, -+ offsetof(struct xdp_md, data_end)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_meta' > pkt_data, corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), -@@ -519,6 +803,41 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_meta' > pkt_data, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_meta' > pkt_data, corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_data > pkt_meta', good access", - .insns = { -@@ -538,16 +857,16 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data > pkt_meta', bad access 1", -+ "XDP pkt read, pkt_data > pkt_meta', corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), - BPF_JMP_IMM(BPF_JA, 0, 0, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -574,6 +893,42 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_data > pkt_meta', corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data > pkt_meta', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_meta' < pkt_data, good access", - .insns = { -@@ -593,16 +948,16 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_meta' < pkt_data, bad access 1", -+ "XDP pkt read, pkt_meta' < pkt_data, corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), - BPF_JMP_IMM(BPF_JA, 0, 0, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -630,7 +985,43 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data < pkt_meta', good access", -+ "XDP pkt read, pkt_meta' < pkt_data, corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_meta' < pkt_data, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data < pkt_meta', corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), -@@ -682,6 +1073,41 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_data < pkt_meta', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data < pkt_meta', corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_meta' >= pkt_data, good access", - .insns = { -@@ -700,15 +1126,15 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_meta' >= pkt_data, bad access 1", -+ "XDP pkt read, pkt_meta' >= pkt_data, corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -736,7 +1162,41 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data >= pkt_meta', good access", -+ "XDP pkt read, pkt_meta' >= pkt_data, corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_meta' >= pkt_data, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data >= pkt_meta', corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), -@@ -791,7 +1251,44 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_meta' <= pkt_data, good access", -+ "XDP pkt read, pkt_data >= pkt_meta', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data >= pkt_meta', corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_meta' <= pkt_data, corner case, good access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), -@@ -845,6 +1342,43 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_meta' <= pkt_data, corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_meta' <= pkt_data, corner case -1, bad access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), -+ BPF_JMP_IMM(BPF_JA, 0, 0, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .errstr = "R1 offset is outside of the packet", -+ .result = REJECT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, - { - "XDP pkt read, pkt_data <= pkt_meta', good access", - .insns = { -@@ -863,15 +1397,15 @@ - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, - { -- "XDP pkt read, pkt_data <= pkt_meta', bad access 1", -+ "XDP pkt read, pkt_data <= pkt_meta', corner case -1, bad access", - .insns = { - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, - offsetof(struct xdp_md, data_meta)), - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), - BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), - BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), -- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), - BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_EXIT_INSN(), - }, -@@ -898,3 +1432,37 @@ - .prog_type = BPF_PROG_TYPE_XDP, - .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, - }, -+{ -+ "XDP pkt read, pkt_data <= pkt_meta', corner case, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -+{ -+ "XDP pkt read, pkt_data <= pkt_meta', corner case +1, good access", -+ .insns = { -+ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, -+ offsetof(struct xdp_md, data_meta)), -+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), -+ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .result = ACCEPT, -+ .prog_type = BPF_PROG_TYPE_XDP, -+ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, -+}, -diff --git a/tools/testing/selftests/bpf/xdp_redirect_multi.c b/tools/testing/selftests/bpf/xdp_redirect_multi.c -index 3696a8f32c235..f5ffba341c174 100644 ---- a/tools/testing/selftests/bpf/xdp_redirect_multi.c -+++ b/tools/testing/selftests/bpf/xdp_redirect_multi.c -@@ -129,7 +129,7 @@ int main(int argc, char **argv) - goto err_out; - } - -- printf("Get interfaces"); -+ printf("Get interfaces:"); - for (i = 0; i < MAX_IFACE_NUM && argv[optind + i]; i++) { - ifaces[i] = if_nametoindex(argv[optind + i]); - if (!ifaces[i]) -@@ -139,7 +139,7 @@ int main(int argc, char **argv) - goto err_out; - } - if (ifaces[i] > MAX_INDEX_NUM) { -- printf("Interface index to large\n"); -+ printf(" interface index too large\n"); - goto err_out; - } - printf(" %d", ifaces[i]); -diff --git a/tools/testing/selftests/core/close_range_test.c b/tools/testing/selftests/core/close_range_test.c -index 73eb29c916d1b..aa7d13d91963f 100644 ---- a/tools/testing/selftests/core/close_range_test.c -+++ b/tools/testing/selftests/core/close_range_test.c -@@ -54,7 +54,7 @@ static inline int sys_close_range(unsigned int fd, unsigned int max_fd, - #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - #endif - --TEST(close_range) -+TEST(core_close_range) - { - int i, ret; - int open_fds[101]; -diff --git a/tools/testing/selftests/damon/.gitignore b/tools/testing/selftests/damon/.gitignore -new file mode 100644 -index 0000000000000..c6c2965a66075 ---- /dev/null -+++ b/tools/testing/selftests/damon/.gitignore -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+huge_count_read_write -diff --git a/tools/testing/selftests/damon/Makefile b/tools/testing/selftests/damon/Makefile -index 8a3f2cd9fec0c..f0aa954b5d135 100644 ---- a/tools/testing/selftests/damon/Makefile -+++ b/tools/testing/selftests/damon/Makefile -@@ -1,6 +1,8 @@ - # SPDX-License-Identifier: GPL-2.0 - # Makefile for damon selftests - -+TEST_GEN_FILES += huge_count_read_write -+ - TEST_FILES = _chk_dependency.sh - TEST_PROGS = debugfs_attrs.sh - -diff --git a/tools/testing/selftests/damon/debugfs_attrs.sh b/tools/testing/selftests/damon/debugfs_attrs.sh -index bfabb19dc0d3d..ecda972e87775 100644 ---- a/tools/testing/selftests/damon/debugfs_attrs.sh -+++ b/tools/testing/selftests/damon/debugfs_attrs.sh -@@ -72,4 +72,22 @@ test_write_succ "$file" "" "$orig_content" "empty input" - test_content "$file" "$orig_content" "" "empty input written" - echo "$orig_content" > "$file" - -+# Test huge count read write -+# ========================== -+ -+dmesg -C -+ -+for file in "$DBGFS/"* -+do -+ ./huge_count_read_write "$file" -+done -+ -+if dmesg | grep -q WARNING -+then -+ dmesg -+ exit 1 -+else -+ exit 0 -+fi -+ - echo "PASS" -diff --git a/tools/testing/selftests/damon/huge_count_read_write.c b/tools/testing/selftests/damon/huge_count_read_write.c -new file mode 100644 -index 0000000000000..ad7a6b4cf3387 ---- /dev/null -+++ b/tools/testing/selftests/damon/huge_count_read_write.c -@@ -0,0 +1,39 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Author: SeongJae Park <sj@kernel.org> -+ */ -+ -+#include <fcntl.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <stdio.h> -+ -+void write_read_with_huge_count(char *file) -+{ -+ int filedesc = open(file, O_RDWR); -+ char buf[25]; -+ int ret; -+ -+ printf("%s %s\n", __func__, file); -+ if (filedesc < 0) { -+ fprintf(stderr, "failed opening %s\n", file); -+ exit(1); -+ } -+ -+ write(filedesc, "", 0xfffffffful); -+ perror("after write: "); -+ ret = read(filedesc, buf, 0xfffffffful); -+ perror("after read: "); -+ close(filedesc); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ if (argc != 2) { -+ fprintf(stderr, "Usage: %s <file>\n", argv[0]); -+ exit(1); -+ } -+ write_read_with_huge_count(argv[1]); -+ -+ return 0; -+} -diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile -index 39f2bbe8dd3df..42ea7d2aa8440 100644 ---- a/tools/testing/selftests/gpio/Makefile -+++ b/tools/testing/selftests/gpio/Makefile -@@ -3,5 +3,6 @@ - TEST_PROGS := gpio-mockup.sh - TEST_FILES := gpio-mockup-sysfs.sh - TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev -+CFLAGS += -I../../../../usr/include - - include ../lib.mk -diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h -index 010b59b139176..35314277fb586 100644 ---- a/tools/testing/selftests/kvm/include/kvm_util.h -+++ b/tools/testing/selftests/kvm/include/kvm_util.h -@@ -69,6 +69,15 @@ enum vm_guest_mode { - - #endif - -+#if defined(__x86_64__) -+unsigned long vm_compute_max_gfn(struct kvm_vm *vm); -+#else -+static inline unsigned long vm_compute_max_gfn(struct kvm_vm *vm) -+{ -+ return ((1ULL << vm->pa_bits) >> vm->page_shift) - 1; -+} -+#endif -+ - #define MIN_PAGE_SIZE (1U << MIN_PAGE_SHIFT) - #define PTES_PER_MIN_PAGE ptes_per_page(MIN_PAGE_SIZE) - -diff --git a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c b/tools/testing/selftests/kvm/kvm_create_max_vcpus.c -index 0299cd81b8ba2..aa3795cd7bd3d 100644 ---- a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c -+++ b/tools/testing/selftests/kvm/kvm_create_max_vcpus.c -@@ -12,6 +12,7 @@ - #include <stdio.h> - #include <stdlib.h> - #include <string.h> -+#include <sys/resource.h> - - #include "test_util.h" - -@@ -40,10 +41,39 @@ int main(int argc, char *argv[]) - { - int kvm_max_vcpu_id = kvm_check_cap(KVM_CAP_MAX_VCPU_ID); - int kvm_max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); -+ /* -+ * Number of file descriptors reqired, KVM_CAP_MAX_VCPUS for vCPU fds + -+ * an arbitrary number for everything else. -+ */ -+ int nr_fds_wanted = kvm_max_vcpus + 100; -+ struct rlimit rl; - - pr_info("KVM_CAP_MAX_VCPU_ID: %d\n", kvm_max_vcpu_id); - pr_info("KVM_CAP_MAX_VCPUS: %d\n", kvm_max_vcpus); - -+ /* -+ * Check that we're allowed to open nr_fds_wanted file descriptors and -+ * try raising the limits if needed. -+ */ -+ TEST_ASSERT(!getrlimit(RLIMIT_NOFILE, &rl), "getrlimit() failed!"); -+ -+ if (rl.rlim_cur < nr_fds_wanted) { -+ rl.rlim_cur = nr_fds_wanted; -+ if (rl.rlim_max < nr_fds_wanted) { -+ int old_rlim_max = rl.rlim_max; -+ rl.rlim_max = nr_fds_wanted; -+ -+ int r = setrlimit(RLIMIT_NOFILE, &rl); -+ if (r < 0) { -+ printf("RLIMIT_NOFILE hard limit is too low (%d, wanted %d)\n", -+ old_rlim_max, nr_fds_wanted); -+ exit(KSFT_SKIP); -+ } -+ } else { -+ TEST_ASSERT(!setrlimit(RLIMIT_NOFILE, &rl), "setrlimit() failed!"); -+ } -+ } -+ - /* - * Upstream KVM prior to 4.8 does not support KVM_CAP_MAX_VCPU_ID. - * Userspace is supposed to use KVM_CAP_MAX_VCPUS as the maximum ID -diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c -index 10a8ed691c669..c439fb653fde2 100644 ---- a/tools/testing/selftests/kvm/lib/kvm_util.c -+++ b/tools/testing/selftests/kvm/lib/kvm_util.c -@@ -307,7 +307,7 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) - (1ULL << (vm->va_bits - 1)) >> vm->page_shift); - - /* Limit physical addresses to PA-bits. */ -- vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1; -+ vm->max_gfn = vm_compute_max_gfn(vm); - - /* Allocate and setup memory for guest. */ - vm->vpages_mapped = sparsebit_alloc(); -diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c -index 28cb881f440d0..da73b97e1e6dc 100644 ---- a/tools/testing/selftests/kvm/lib/x86_64/processor.c -+++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c -@@ -1433,3 +1433,71 @@ struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vm *vm, uint32_t vcpui - - return cpuid; - } -+ -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 -+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 -+ -+static inline unsigned x86_family(unsigned int eax) -+{ -+ unsigned int x86; -+ -+ x86 = (eax >> 8) & 0xf; -+ -+ if (x86 == 0xf) -+ x86 += (eax >> 20) & 0xff; -+ -+ return x86; -+} -+ -+unsigned long vm_compute_max_gfn(struct kvm_vm *vm) -+{ -+ const unsigned long num_ht_pages = 12 << (30 - vm->page_shift); /* 12 GiB */ -+ unsigned long ht_gfn, max_gfn, max_pfn; -+ uint32_t eax, ebx, ecx, edx, max_ext_leaf; -+ -+ max_gfn = (1ULL << (vm->pa_bits - vm->page_shift)) - 1; -+ -+ /* Avoid reserved HyperTransport region on AMD processors. */ -+ eax = ecx = 0; -+ cpuid(&eax, &ebx, &ecx, &edx); -+ if (ebx != X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx || -+ ecx != X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx || -+ edx != X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) -+ return max_gfn; -+ -+ /* On parts with <40 physical address bits, the area is fully hidden */ -+ if (vm->pa_bits < 40) -+ return max_gfn; -+ -+ /* Before family 17h, the HyperTransport area is just below 1T. */ -+ ht_gfn = (1 << 28) - num_ht_pages; -+ eax = 1; -+ cpuid(&eax, &ebx, &ecx, &edx); -+ if (x86_family(eax) < 0x17) -+ goto done; -+ -+ /* -+ * Otherwise it's at the top of the physical address space, possibly -+ * reduced due to SME by bits 11:6 of CPUID[0x8000001f].EBX. Use -+ * the old conservative value if MAXPHYADDR is not enumerated. -+ */ -+ eax = 0x80000000; -+ cpuid(&eax, &ebx, &ecx, &edx); -+ max_ext_leaf = eax; -+ if (max_ext_leaf < 0x80000008) -+ goto done; -+ -+ eax = 0x80000008; -+ cpuid(&eax, &ebx, &ecx, &edx); -+ max_pfn = (1ULL << ((eax & 0xff) - vm->page_shift)) - 1; -+ if (max_ext_leaf >= 0x8000001f) { -+ eax = 0x8000001f; -+ cpuid(&eax, &ebx, &ecx, &edx); -+ max_pfn >>= (ebx >> 6) & 0x3f; -+ } -+ -+ ht_gfn = max_pfn - num_ht_pages; -+done: -+ return min(max_gfn, ht_gfn - 1); -+} -diff --git a/tools/testing/selftests/kvm/lib/x86_64/svm.c b/tools/testing/selftests/kvm/lib/x86_64/svm.c -index 2ac98d70d02bd..161eba7cd1289 100644 ---- a/tools/testing/selftests/kvm/lib/x86_64/svm.c -+++ b/tools/testing/selftests/kvm/lib/x86_64/svm.c -@@ -54,6 +54,18 @@ static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector, - seg->base = base; - } - -+/* -+ * Avoid using memset to clear the vmcb, since libc may not be -+ * available in L1 (and, even if it is, features that libc memset may -+ * want to use, like AVX, may not be enabled). -+ */ -+static void clear_vmcb(struct vmcb *vmcb) -+{ -+ int n = sizeof(*vmcb) / sizeof(u32); -+ -+ asm volatile ("rep stosl" : "+c"(n), "+D"(vmcb) : "a"(0) : "memory"); -+} -+ - void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp) - { - struct vmcb *vmcb = svm->vmcb; -@@ -70,7 +82,7 @@ void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_r - wrmsr(MSR_EFER, efer | EFER_SVME); - wrmsr(MSR_VM_HSAVE_PA, svm->save_area_gpa); - -- memset(vmcb, 0, sizeof(*vmcb)); -+ clear_vmcb(vmcb); - asm volatile ("vmsave %0\n\t" : : "a" (vmcb_gpa) : "memory"); - vmcb_set_seg(&save->es, get_es(), 0, -1U, data_seg_attr); - vmcb_set_seg(&save->cs, get_cs(), 0, -1U, code_seg_attr); -diff --git a/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c b/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c -index 8039e1eff9388..9f55ccd169a13 100644 ---- a/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c -+++ b/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c -@@ -84,7 +84,7 @@ int get_warnings_count(void) - f = popen("dmesg | grep \"WARNING:\" | wc -l", "r"); - if (fscanf(f, "%d", &warnings) < 1) - warnings = 0; -- fclose(f); -+ pclose(f); - - return warnings; - } -diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile -index 492b273743b4e..6a953ec793ced 100644 ---- a/tools/testing/selftests/net/Makefile -+++ b/tools/testing/selftests/net/Makefile -@@ -12,7 +12,7 @@ TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_a - TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh - TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh l2tp.sh traceroute.sh - TEST_PROGS += fin_ack_lat.sh fib_nexthop_multiprefix.sh fib_nexthops.sh --TEST_PROGS += altnames.sh icmp_redirect.sh ip6_gre_headroom.sh -+TEST_PROGS += altnames.sh icmp.sh icmp_redirect.sh ip6_gre_headroom.sh - TEST_PROGS += route_localnet.sh - TEST_PROGS += reuseaddr_ports_exhausted.sh - TEST_PROGS += txtimestamp.sh -@@ -28,7 +28,12 @@ TEST_PROGS += veth.sh - TEST_PROGS += ioam6.sh - TEST_PROGS += gro.sh - TEST_PROGS += gre_gso.sh --TEST_PROGS_EXTENDED := in_netns.sh -+TEST_PROGS += srv6_end_dt46_l3vpn_test.sh -+TEST_PROGS += srv6_end_dt4_l3vpn_test.sh -+TEST_PROGS += srv6_end_dt6_l3vpn_test.sh -+TEST_PROGS += vrf_strict_mode_test.sh -+TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh -+TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh - TEST_GEN_FILES = socket nettest - TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any - TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd txring_overwrite -diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh -index 3313566ce9062..aec9e784d0b46 100755 ---- a/tools/testing/selftests/net/fcnal-test.sh -+++ b/tools/testing/selftests/net/fcnal-test.sh -@@ -455,6 +455,22 @@ cleanup() - ip netns del ${NSC} >/dev/null 2>&1 - } - -+cleanup_vrf_dup() -+{ -+ ip link del ${NSA_DEV2} >/dev/null 2>&1 -+ ip netns pids ${NSC} | xargs kill 2>/dev/null -+ ip netns del ${NSC} >/dev/null 2>&1 -+} -+ -+setup_vrf_dup() -+{ -+ # some VRF tests use ns-C which has the same config as -+ # ns-B but for a device NOT in the VRF -+ create_ns ${NSC} "-" "-" -+ connect_ns ${NSA} ${NSA_DEV2} ${NSA_IP}/24 ${NSA_IP6}/64 \ -+ ${NSC} ${NSC_DEV} ${NSB_IP}/24 ${NSB_IP6}/64 -+} -+ - setup() - { - local with_vrf=${1} -@@ -484,12 +500,6 @@ setup() - - ip -netns ${NSB} ro add ${VRF_IP}/32 via ${NSA_IP} dev ${NSB_DEV} - ip -netns ${NSB} -6 ro add ${VRF_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV} -- -- # some VRF tests use ns-C which has the same config as -- # ns-B but for a device NOT in the VRF -- create_ns ${NSC} "-" "-" -- connect_ns ${NSA} ${NSA_DEV2} ${NSA_IP}/24 ${NSA_IP6}/64 \ -- ${NSC} ${NSC_DEV} ${NSB_IP}/24 ${NSB_IP6}/64 - else - ip -netns ${NSA} ro add ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV} - ip -netns ${NSA} ro add ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV} -@@ -1240,7 +1250,9 @@ ipv4_tcp_vrf() - log_test_addr ${a} $? 1 "Global server, local connection" - - # run MD5 tests -+ setup_vrf_dup - ipv4_tcp_md5 -+ cleanup_vrf_dup - - # - # enable VRF global server -@@ -1798,8 +1810,9 @@ ipv4_addr_bind_vrf() - for a in ${NSA_IP} ${VRF_IP} - do - log_start -+ show_hint "Socket not bound to VRF, but address is in VRF" - run_cmd nettest -s -R -P icmp -l ${a} -b -- log_test_addr ${a} $? 0 "Raw socket bind to local address" -+ log_test_addr ${a} $? 1 "Raw socket bind to local address" - - log_start - run_cmd nettest -s -R -P icmp -l ${a} -I ${NSA_DEV} -b -@@ -2191,7 +2204,7 @@ ipv6_ping_vrf() - log_start - show_hint "Fails since VRF device does not support linklocal or multicast" - run_cmd ${ping6} -c1 -w1 ${a} -- log_test_addr ${a} $? 2 "ping out, VRF bind" -+ log_test_addr ${a} $? 1 "ping out, VRF bind" - done - - for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} -@@ -2719,7 +2732,9 @@ ipv6_tcp_vrf() - log_test_addr ${a} $? 1 "Global server, local connection" - - # run MD5 tests -+ setup_vrf_dup - ipv6_tcp_md5 -+ cleanup_vrf_dup - - # - # enable VRF global server -@@ -3414,11 +3429,14 @@ ipv6_addr_bind_novrf() - run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b - log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" - -+ # Sadly, the kernel allows binding a socket to a device and then -+ # binding to an address not on the device. So this test passes -+ # when it really should not - a=${NSA_LO_IP6} - log_start -- show_hint "Should fail with 'Cannot assign requested address'" -+ show_hint "Tecnically should fail since address is not on device but kernel allows" - run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b -- log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" -+ log_test_addr ${a} $? 0 "TCP socket bind to out of scope local address" - } - - ipv6_addr_bind_vrf() -@@ -3459,10 +3477,15 @@ ipv6_addr_bind_vrf() - run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b - log_test_addr ${a} $? 0 "TCP socket bind to local address with device bind" - -+ # Sadly, the kernel allows binding a socket to a device and then -+ # binding to an address not on the device. The only restriction -+ # is that the address is valid in the L3 domain. So this test -+ # passes when it really should not - a=${VRF_IP6} - log_start -+ show_hint "Tecnically should fail since address is not on device but kernel allows" - run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b -- log_test_addr ${a} $? 1 "TCP socket bind to VRF address with device bind" -+ log_test_addr ${a} $? 0 "TCP socket bind to VRF address with device bind" - - a=${NSA_LO_IP6} - log_start -@@ -4002,8 +4025,8 @@ EOF - ################################################################################ - # main - --TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" --TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime ipv6_netfilter" -+TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_bind ipv4_runtime ipv4_netfilter" -+TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_bind ipv6_runtime ipv6_netfilter" - TESTS_OTHER="use_cases" - - PAUSE_ON_FAIL=no -diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh -index 0d293391e9a44..b5a69ad191b07 100755 ---- a/tools/testing/selftests/net/fib_nexthops.sh -+++ b/tools/testing/selftests/net/fib_nexthops.sh -@@ -2078,6 +2078,7 @@ basic_res() - "id 101 index 0 nhid 2 id 101 index 1 nhid 2 id 101 index 2 nhid 1 id 101 index 3 nhid 1" - log_test $? 0 "Dump all nexthop buckets in a group" - -+ sleep 0.1 - (( $($IP -j nexthop bucket list id 101 | - jq '[.[] | select(.bucket.idle_time > 0 and - .bucket.idle_time < 2)] | length') == 4 )) -diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh -index 5abe92d55b696..996af1ae3d3dd 100755 ---- a/tools/testing/selftests/net/fib_tests.sh -+++ b/tools/testing/selftests/net/fib_tests.sh -@@ -444,24 +444,63 @@ fib_rp_filter_test() - setup - - set -e -+ ip netns add ns2 -+ ip netns set ns2 auto -+ -+ ip -netns ns2 link set dev lo up -+ -+ $IP link add name veth1 type veth peer name veth2 -+ $IP link set dev veth2 netns ns2 -+ $IP address add 192.0.2.1/24 dev veth1 -+ ip -netns ns2 address add 192.0.2.1/24 dev veth2 -+ $IP link set dev veth1 up -+ ip -netns ns2 link set dev veth2 up -+ - $IP link set dev lo address 52:54:00:6a:c7:5e -- $IP link set dummy0 address 52:54:00:6a:c7:5e -- $IP link add dummy1 type dummy -- $IP link set dummy1 address 52:54:00:6a:c7:5e -- $IP link set dev dummy1 up -+ $IP link set dev veth1 address 52:54:00:6a:c7:5e -+ ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e -+ ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e -+ -+ # 1. (ns2) redirect lo's egress to veth2's egress -+ ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel -+ ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \ -+ action mirred egress redirect dev veth2 -+ ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \ -+ action mirred egress redirect dev veth2 -+ -+ # 2. (ns1) redirect veth1's ingress to lo's ingress -+ $NS_EXEC tc qdisc add dev veth1 ingress -+ $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \ -+ action mirred ingress redirect dev lo -+ $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \ -+ action mirred ingress redirect dev lo -+ -+ # 3. (ns1) redirect lo's egress to veth1's egress -+ $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel -+ $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \ -+ action mirred egress redirect dev veth1 -+ $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \ -+ action mirred egress redirect dev veth1 -+ -+ # 4. (ns2) redirect veth2's ingress to lo's ingress -+ ip netns exec ns2 tc qdisc add dev veth2 ingress -+ ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \ -+ action mirred ingress redirect dev lo -+ ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \ -+ action mirred ingress redirect dev lo -+ - $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1 - $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1 - $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1 -- -- $NS_EXEC tc qd add dev dummy1 parent root handle 1: fq_codel -- $NS_EXEC tc filter add dev dummy1 parent 1: protocol arp basic action mirred egress redirect dev lo -- $NS_EXEC tc filter add dev dummy1 parent 1: protocol ip basic action mirred egress redirect dev lo -+ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1 -+ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1 -+ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1 - set +e - -- run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 198.51.100.1" -+ run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1" - log_test $? 0 "rp_filter passes local packets" - -- run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 127.0.0.1" -+ run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1" - log_test $? 0 "rp_filter passes loopback packets" - - cleanup -diff --git a/tools/testing/selftests/net/forwarding/bridge_igmp.sh b/tools/testing/selftests/net/forwarding/bridge_igmp.sh -index 675eff45b0371..1162836f8f329 100755 ---- a/tools/testing/selftests/net/forwarding/bridge_igmp.sh -+++ b/tools/testing/selftests/net/forwarding/bridge_igmp.sh -@@ -482,10 +482,15 @@ v3exc_timeout_test() - local X=("192.0.2.20" "192.0.2.30") - - # GMI should be 3 seconds -- ip link set dev br0 type bridge mcast_query_interval 100 mcast_query_response_interval 100 -+ ip link set dev br0 type bridge mcast_query_interval 100 \ -+ mcast_query_response_interval 100 \ -+ mcast_membership_interval 300 - - v3exclude_prepare $h1 $ALL_MAC $ALL_GROUP -- ip link set dev br0 type bridge mcast_query_interval 500 mcast_query_response_interval 500 -+ ip link set dev br0 type bridge mcast_query_interval 500 \ -+ mcast_query_response_interval 500 \ -+ mcast_membership_interval 1500 -+ - $MZ $h1 -c 1 -b $ALL_MAC -B $ALL_GROUP -t ip "proto=2,p=$MZPKT_ALLOW2" -q - sleep 3 - bridge -j -d -s mdb show dev br0 \ -@@ -517,7 +522,8 @@ v3exc_timeout_test() - log_test "IGMPv3 group $TEST_GROUP exclude timeout" - - ip link set dev br0 type bridge mcast_query_interval 12500 \ -- mcast_query_response_interval 1000 -+ mcast_query_response_interval 1000 \ -+ mcast_membership_interval 26000 - - v3cleanup $swp1 $TEST_GROUP - } -diff --git a/tools/testing/selftests/net/forwarding/bridge_mld.sh b/tools/testing/selftests/net/forwarding/bridge_mld.sh -index ffdcfa87ca2ba..e2b9ff773c6b6 100755 ---- a/tools/testing/selftests/net/forwarding/bridge_mld.sh -+++ b/tools/testing/selftests/net/forwarding/bridge_mld.sh -@@ -479,10 +479,15 @@ mldv2exc_timeout_test() - local X=("2001:db8:1::20" "2001:db8:1::30") - - # GMI should be 3 seconds -- ip link set dev br0 type bridge mcast_query_interval 100 mcast_query_response_interval 100 -+ ip link set dev br0 type bridge mcast_query_interval 100 \ -+ mcast_query_response_interval 100 \ -+ mcast_membership_interval 300 - - mldv2exclude_prepare $h1 -- ip link set dev br0 type bridge mcast_query_interval 500 mcast_query_response_interval 500 -+ ip link set dev br0 type bridge mcast_query_interval 500 \ -+ mcast_query_response_interval 500 \ -+ mcast_membership_interval 1500 -+ - $MZ $h1 -c 1 $MZPKT_ALLOW2 -q - sleep 3 - bridge -j -d -s mdb show dev br0 \ -@@ -514,7 +519,8 @@ mldv2exc_timeout_test() - log_test "MLDv2 group $TEST_GROUP exclude timeout" - - ip link set dev br0 type bridge mcast_query_interval 12500 \ -- mcast_query_response_interval 1000 -+ mcast_query_response_interval 1000 \ -+ mcast_membership_interval 26000 - - mldv2cleanup $swp1 - } -diff --git a/tools/testing/selftests/net/forwarding/forwarding.config.sample b/tools/testing/selftests/net/forwarding/forwarding.config.sample -index e5e2fbeca22ec..e51def39fd801 100644 ---- a/tools/testing/selftests/net/forwarding/forwarding.config.sample -+++ b/tools/testing/selftests/net/forwarding/forwarding.config.sample -@@ -13,6 +13,8 @@ NETIFS[p5]=veth4 - NETIFS[p6]=veth5 - NETIFS[p7]=veth6 - NETIFS[p8]=veth7 -+NETIFS[p9]=veth8 -+NETIFS[p10]=veth9 - - # Port that does not have a cable connected. - NETIF_NO_CABLE=eth8 -diff --git a/tools/testing/selftests/net/gre_gso.sh b/tools/testing/selftests/net/gre_gso.sh -index facbb0c804439..3224651db97b8 100755 ---- a/tools/testing/selftests/net/gre_gso.sh -+++ b/tools/testing/selftests/net/gre_gso.sh -@@ -116,17 +116,20 @@ gre_gst_test_checks() - { - local name=$1 - local addr=$2 -+ local proto=$3 - -- $NS_EXEC nc -kl $port >/dev/null & -+ [ "$proto" == 6 ] && addr="[$addr]" -+ -+ $NS_EXEC socat - tcp${proto}-listen:$port,reuseaddr,fork >/dev/null & - PID=$! - while ! $NS_EXEC ss -ltn | grep -q $port; do ((i++)); sleep 0.01; done - -- cat $TMPFILE | timeout 1 nc $addr $port -+ cat $TMPFILE | timeout 1 socat -u STDIN TCP:$addr:$port - log_test $? 0 "$name - copy file w/ TSO" - - ethtool -K veth0 tso off - -- cat $TMPFILE | timeout 1 nc $addr $port -+ cat $TMPFILE | timeout 1 socat -u STDIN TCP:$addr:$port - log_test $? 0 "$name - copy file w/ GSO" - - ethtool -K veth0 tso on -@@ -154,8 +157,8 @@ gre6_gso_test() - - sleep 2 - -- gre_gst_test_checks GREv6/v4 172.16.2.2 -- gre_gst_test_checks GREv6/v6 2001:db8:1::2 -+ gre_gst_test_checks GREv6/v4 172.16.2.2 4 -+ gre_gst_test_checks GREv6/v6 2001:db8:1::2 6 - - cleanup - } -@@ -211,8 +214,8 @@ if [ ! -x "$(command -v ip)" ]; then - exit $ksft_skip - fi - --if [ ! -x "$(command -v nc)" ]; then -- echo "SKIP: Could not run test without nc tool" -+if [ ! -x "$(command -v socat)" ]; then -+ echo "SKIP: Could not run test without socat tool" - exit $ksft_skip - fi - -diff --git a/tools/testing/selftests/net/icmp_redirect.sh b/tools/testing/selftests/net/icmp_redirect.sh -index ecbf57f264ed9..7b9d6e31b8e7d 100755 ---- a/tools/testing/selftests/net/icmp_redirect.sh -+++ b/tools/testing/selftests/net/icmp_redirect.sh -@@ -311,7 +311,7 @@ check_exception() - ip -netns h1 ro get ${H1_VRF_ARG} ${H2_N2_IP} | \ - grep -E -v 'mtu|redirected' | grep -q "cache" - fi -- log_test $? 0 "IPv4: ${desc}" -+ log_test $? 0 "IPv4: ${desc}" 0 - - # No PMTU info for test "redirect" and "mtu exception plus redirect" - if [ "$with_redirect" = "yes" ] && [ "$desc" != "redirect exception plus mtu" ]; then -diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh -index 255793c5ac4ff..586af88194e56 100755 ---- a/tools/testing/selftests/net/mptcp/mptcp_join.sh -+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh -@@ -297,7 +297,7 @@ do_transfer() - if [ "$test_link_fail" -eq 2 ];then - timeout ${timeout_test} \ - ip netns exec ${listener_ns} \ -- $mptcp_connect -t ${timeout_poll} -l -p $port -s ${cl_proto} \ -+ $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - ${local_addr} < "$sinfail" > "$sout" & - else - timeout ${timeout_test} \ -diff --git a/tools/testing/selftests/net/toeplitz.c b/tools/testing/selftests/net/toeplitz.c -index 710ac956bdb33..c5489341cfb80 100644 ---- a/tools/testing/selftests/net/toeplitz.c -+++ b/tools/testing/selftests/net/toeplitz.c -@@ -498,7 +498,7 @@ static void parse_opts(int argc, char **argv) - bool have_toeplitz = false; - int index, c; - -- while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:u:v", long_options, &index)) != -1) { -+ while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:uv", long_options, &index)) != -1) { - switch (c) { - case '4': - cfg_family = AF_INET; -diff --git a/tools/testing/selftests/net/udpgso_bench_rx.c b/tools/testing/selftests/net/udpgso_bench_rx.c -index 76a24052f4b47..6a193425c367f 100644 ---- a/tools/testing/selftests/net/udpgso_bench_rx.c -+++ b/tools/testing/selftests/net/udpgso_bench_rx.c -@@ -293,19 +293,17 @@ static void usage(const char *filepath) - - static void parse_opts(int argc, char **argv) - { -+ const char *bind_addr = NULL; - int c; - -- /* bind to any by default */ -- setup_sockaddr(PF_INET6, "::", &cfg_bind_addr); - while ((c = getopt(argc, argv, "4b:C:Gl:n:p:rR:S:tv")) != -1) { - switch (c) { - case '4': - cfg_family = PF_INET; - cfg_alen = sizeof(struct sockaddr_in); -- setup_sockaddr(PF_INET, "0.0.0.0", &cfg_bind_addr); - break; - case 'b': -- setup_sockaddr(cfg_family, optarg, &cfg_bind_addr); -+ bind_addr = optarg; - break; - case 'C': - cfg_connect_timeout_ms = strtoul(optarg, NULL, 0); -@@ -341,6 +339,11 @@ static void parse_opts(int argc, char **argv) - } - } - -+ if (!bind_addr) -+ bind_addr = cfg_family == PF_INET6 ? "::" : "0.0.0.0"; -+ -+ setup_sockaddr(cfg_family, bind_addr, &cfg_bind_addr); -+ - if (optind != argc) - usage(argv[0]); - -diff --git a/tools/testing/selftests/netfilter/Makefile b/tools/testing/selftests/netfilter/Makefile -index 8748199ac1098..ffca314897c4c 100644 ---- a/tools/testing/selftests/netfilter/Makefile -+++ b/tools/testing/selftests/netfilter/Makefile -@@ -5,7 +5,8 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \ - conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \ - nft_concat_range.sh nft_conntrack_helper.sh \ - nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ -- ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh -+ ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ -+ conntrack_vrf.sh - - LDLIBS = -lmnl - TEST_GEN_FILES = nf-queue -diff --git a/tools/testing/selftests/netfilter/conntrack_vrf.sh b/tools/testing/selftests/netfilter/conntrack_vrf.sh -new file mode 100755 -index 0000000000000..8b5ea92345882 ---- /dev/null -+++ b/tools/testing/selftests/netfilter/conntrack_vrf.sh -@@ -0,0 +1,241 @@ -+#!/bin/sh -+ -+# This script demonstrates interaction of conntrack and vrf. -+# The vrf driver calls the netfilter hooks again, with oif/iif -+# pointing at the VRF device. -+# -+# For ingress, this means first iteration has iifname of lower/real -+# device. In this script, thats veth0. -+# Second iteration is iifname set to vrf device, tvrf in this script. -+# -+# For egress, this is reversed: first iteration has the vrf device, -+# second iteration is done with the lower/real/veth0 device. -+# -+# test_ct_zone_in demonstrates unexpected change of nftables -+# behavior # caused by commit 09e856d54bda5f28 "vrf: Reset skb conntrack -+# connection on VRF rcv" -+# -+# It was possible to assign conntrack zone to a packet (or mark it for -+# `notracking`) in the prerouting chain before conntrack, based on real iif. -+# -+# After the change, the zone assignment is lost and the zone is assigned based -+# on the VRF master interface (in case such a rule exists). -+# assignment is lost. Instead, assignment based on the `iif` matching -+# Thus it is impossible to distinguish packets based on the original -+# interface. -+# -+# test_masquerade_vrf and test_masquerade_veth0 demonstrate the problem -+# that was supposed to be fixed by the commit mentioned above to make sure -+# that any fix to test case 1 won't break masquerade again. -+ -+ksft_skip=4 -+ -+IP0=172.30.30.1 -+IP1=172.30.30.2 -+PFXL=30 -+ret=0 -+ -+sfx=$(mktemp -u "XXXXXXXX") -+ns0="ns0-$sfx" -+ns1="ns1-$sfx" -+ -+cleanup() -+{ -+ ip netns pids $ns0 | xargs kill 2>/dev/null -+ ip netns pids $ns1 | xargs kill 2>/dev/null -+ -+ ip netns del $ns0 $ns1 -+} -+ -+nft --version > /dev/null 2>&1 -+if [ $? -ne 0 ];then -+ echo "SKIP: Could not run test without nft tool" -+ exit $ksft_skip -+fi -+ -+ip -Version > /dev/null 2>&1 -+if [ $? -ne 0 ];then -+ echo "SKIP: Could not run test without ip tool" -+ exit $ksft_skip -+fi -+ -+ip netns add "$ns0" -+if [ $? -ne 0 ];then -+ echo "SKIP: Could not create net namespace $ns0" -+ exit $ksft_skip -+fi -+ip netns add "$ns1" -+ -+trap cleanup EXIT -+ -+ip netns exec $ns0 sysctl -q -w net.ipv4.conf.default.rp_filter=0 -+ip netns exec $ns0 sysctl -q -w net.ipv4.conf.all.rp_filter=0 -+ip netns exec $ns0 sysctl -q -w net.ipv4.conf.all.rp_filter=0 -+ -+ip link add veth0 netns "$ns0" type veth peer name veth0 netns "$ns1" > /dev/null 2>&1 -+if [ $? -ne 0 ];then -+ echo "SKIP: Could not add veth device" -+ exit $ksft_skip -+fi -+ -+ip -net $ns0 li add tvrf type vrf table 9876 -+if [ $? -ne 0 ];then -+ echo "SKIP: Could not add vrf device" -+ exit $ksft_skip -+fi -+ -+ip -net $ns0 li set lo up -+ -+ip -net $ns0 li set veth0 master tvrf -+ip -net $ns0 li set tvrf up -+ip -net $ns0 li set veth0 up -+ip -net $ns1 li set veth0 up -+ -+ip -net $ns0 addr add $IP0/$PFXL dev veth0 -+ip -net $ns1 addr add $IP1/$PFXL dev veth0 -+ -+ip netns exec $ns1 iperf3 -s > /dev/null 2>&1& -+if [ $? -ne 0 ];then -+ echo "SKIP: Could not start iperf3" -+ exit $ksft_skip -+fi -+ -+# test vrf ingress handling. -+# The incoming connection should be placed in conntrack zone 1, -+# as decided by the first iteration of the ruleset. -+test_ct_zone_in() -+{ -+ip netns exec $ns0 nft -f - <<EOF -+table testct { -+ chain rawpre { -+ type filter hook prerouting priority raw; -+ -+ iif { veth0, tvrf } counter meta nftrace set 1 -+ iif veth0 counter ct zone set 1 counter return -+ iif tvrf counter ct zone set 2 counter return -+ ip protocol icmp counter -+ notrack counter -+ } -+ -+ chain rawout { -+ type filter hook output priority raw; -+ -+ oif veth0 counter ct zone set 1 counter return -+ oif tvrf counter ct zone set 2 counter return -+ notrack counter -+ } -+} -+EOF -+ ip netns exec $ns1 ping -W 1 -c 1 -I veth0 $IP0 > /dev/null -+ -+ # should be in zone 1, not zone 2 -+ count=$(ip netns exec $ns0 conntrack -L -s $IP1 -d $IP0 -p icmp --zone 1 2>/dev/null | wc -l) -+ if [ $count -eq 1 ]; then -+ echo "PASS: entry found in conntrack zone 1" -+ else -+ echo "FAIL: entry not found in conntrack zone 1" -+ count=$(ip netns exec $ns0 conntrack -L -s $IP1 -d $IP0 -p icmp --zone 2 2> /dev/null | wc -l) -+ if [ $count -eq 1 ]; then -+ echo "FAIL: entry found in zone 2 instead" -+ else -+ echo "FAIL: entry not in zone 1 or 2, dumping table" -+ ip netns exec $ns0 conntrack -L -+ ip netns exec $ns0 nft list ruleset -+ fi -+ fi -+} -+ -+# add masq rule that gets evaluated w. outif set to vrf device. -+# This tests the first iteration of the packet through conntrack, -+# oifname is the vrf device. -+test_masquerade_vrf() -+{ -+ local qdisc=$1 -+ -+ if [ "$qdisc" != "default" ]; then -+ tc -net $ns0 qdisc add dev tvrf root $qdisc -+ fi -+ -+ ip netns exec $ns0 conntrack -F 2>/dev/null -+ -+ip netns exec $ns0 nft -f - <<EOF -+flush ruleset -+table ip nat { -+ chain rawout { -+ type filter hook output priority raw; -+ -+ oif tvrf ct state untracked counter -+ } -+ chain postrouting2 { -+ type filter hook postrouting priority mangle; -+ -+ oif tvrf ct state untracked counter -+ } -+ chain postrouting { -+ type nat hook postrouting priority 0; -+ # NB: masquerade should always be combined with 'oif(name) bla', -+ # lack of this is intentional here, we want to exercise double-snat. -+ ip saddr 172.30.30.0/30 counter masquerade random -+ } -+} -+EOF -+ ip netns exec $ns0 ip vrf exec tvrf iperf3 -t 1 -c $IP1 >/dev/null -+ if [ $? -ne 0 ]; then -+ echo "FAIL: iperf3 connect failure with masquerade + sport rewrite on vrf device" -+ ret=1 -+ return -+ fi -+ -+ # must also check that nat table was evaluated on second (lower device) iteration. -+ ip netns exec $ns0 nft list table ip nat |grep -q 'counter packets 2' && -+ ip netns exec $ns0 nft list table ip nat |grep -q 'untracked counter packets [1-9]' -+ if [ $? -eq 0 ]; then -+ echo "PASS: iperf3 connect with masquerade + sport rewrite on vrf device ($qdisc qdisc)" -+ else -+ echo "FAIL: vrf rules have unexpected counter value" -+ ret=1 -+ fi -+ -+ if [ "$qdisc" != "default" ]; then -+ tc -net $ns0 qdisc del dev tvrf root -+ fi -+} -+ -+# add masq rule that gets evaluated w. outif set to veth device. -+# This tests the 2nd iteration of the packet through conntrack, -+# oifname is the lower device (veth0 in this case). -+test_masquerade_veth() -+{ -+ ip netns exec $ns0 conntrack -F 2>/dev/null -+ip netns exec $ns0 nft -f - <<EOF -+flush ruleset -+table ip nat { -+ chain postrouting { -+ type nat hook postrouting priority 0; -+ meta oif veth0 ip saddr 172.30.30.0/30 counter masquerade random -+ } -+} -+EOF -+ ip netns exec $ns0 ip vrf exec tvrf iperf3 -t 1 -c $IP1 > /dev/null -+ if [ $? -ne 0 ]; then -+ echo "FAIL: iperf3 connect failure with masquerade + sport rewrite on veth device" -+ ret=1 -+ return -+ fi -+ -+ # must also check that nat table was evaluated on second (lower device) iteration. -+ ip netns exec $ns0 nft list table ip nat |grep -q 'counter packets 2' -+ if [ $? -eq 0 ]; then -+ echo "PASS: iperf3 connect with masquerade + sport rewrite on veth device" -+ else -+ echo "FAIL: vrf masq rule has unexpected counter value" -+ ret=1 -+ fi -+} -+ -+test_ct_zone_in -+test_masquerade_vrf "default" -+test_masquerade_vrf "pfifo" -+test_masquerade_veth -+ -+exit $ret -diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c -index 7db9cf822dc75..8109b17dc764c 100644 ---- a/tools/testing/selftests/sched/cs_prctl_test.c -+++ b/tools/testing/selftests/sched/cs_prctl_test.c -@@ -62,6 +62,17 @@ enum pid_type {PIDTYPE_PID = 0, PIDTYPE_TGID, PIDTYPE_PGID}; - - const int THREAD_CLONE_FLAGS = CLONE_THREAD | CLONE_SIGHAND | CLONE_FS | CLONE_VM | CLONE_FILES; - -+struct child_args { -+ int num_threads; -+ int pfd[2]; -+ int cpid; -+ int thr_tids[MAX_THREADS]; -+}; -+ -+static struct child_args procs[MAX_PROCESSES]; -+static int num_processes = 2; -+static int need_cleanup = 0; -+ - static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, - unsigned long arg5) - { -@@ -78,8 +89,14 @@ static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned l - #define handle_error(msg) __handle_error(__FILE__, __LINE__, msg) - static void __handle_error(char *fn, int ln, char *msg) - { -+ int pidx; - printf("(%s:%d) - ", fn, ln); - perror(msg); -+ if (need_cleanup) { -+ for (pidx = 0; pidx < num_processes; ++pidx) -+ kill(procs[pidx].cpid, 15); -+ need_cleanup = 0; -+ } - exit(EXIT_FAILURE); - } - -@@ -106,13 +123,6 @@ static unsigned long get_cs_cookie(int pid) - return cookie; - } - --struct child_args { -- int num_threads; -- int pfd[2]; -- int cpid; -- int thr_tids[MAX_THREADS]; --}; -- - static int child_func_thread(void __attribute__((unused))*arg) - { - while (1) -@@ -212,10 +222,7 @@ void _validate(int line, int val, char *msg) - - int main(int argc, char *argv[]) - { -- struct child_args procs[MAX_PROCESSES]; -- - int keypress = 0; -- int num_processes = 2; - int num_threads = 3; - int delay = 0; - int res = 0; -@@ -262,6 +269,7 @@ int main(int argc, char *argv[]) - - printf("\n## Create a thread/process/process group hiearchy\n"); - create_processes(num_processes, num_threads, procs); -+ need_cleanup = 1; - disp_processes(num_processes, procs); - validate(get_cs_cookie(0) == 0); - -diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh -index ebc4ee0fe179f..8a9461aa0878a 100755 ---- a/tools/testing/selftests/wireguard/netns.sh -+++ b/tools/testing/selftests/wireguard/netns.sh -@@ -276,7 +276,11 @@ n0 ping -W 1 -c 1 192.168.241.2 - n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7 - ip2 link del wg0 - ip2 link del wg1 --! n0 ping -W 1 -c 10 -f 192.168.241.2 || false # Should not crash kernel -+read _ _ tx_bytes_before < <(n0 wg show wg1 transfer) -+! n0 ping -W 1 -c 10 -f 192.168.241.2 || false -+sleep 1 -+read _ _ tx_bytes_after < <(n0 wg show wg1 transfer) -+(( tx_bytes_after - tx_bytes_before < 70000 )) - - ip0 link del wg1 - ip1 link del wg0 -@@ -609,6 +613,28 @@ ip0 link set wg0 up - kill $ncat_pid - ip0 link del wg0 - -+# Ensure that dst_cache references don't outlive netns lifetime -+ip1 link add dev wg0 type wireguard -+ip2 link add dev wg0 type wireguard -+configure_peers -+ip1 link add veth1 type veth peer name veth2 -+ip1 link set veth2 netns $netns2 -+ip1 addr add fd00:aa::1/64 dev veth1 -+ip2 addr add fd00:aa::2/64 dev veth2 -+ip1 link set veth1 up -+ip2 link set veth2 up -+waitiface $netns1 veth1 -+waitiface $netns2 veth2 -+ip1 -6 route add default dev veth1 via fd00:aa::2 -+ip2 -6 route add default dev veth2 via fd00:aa::1 -+n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2 -+n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1 -+n1 ping6 -c 1 fd00::2 -+pp ip netns delete $netns1 -+pp ip netns delete $netns2 -+pp ip netns add $netns1 -+pp ip netns add $netns2 -+ - # Ensure there aren't circular reference loops - ip1 link add wg1 type wireguard - ip2 link add wg2 type wireguard -@@ -627,7 +653,7 @@ while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do - done < /dev/kmsg - alldeleted=1 - for object in "${!objects[@]}"; do -- if [[ ${objects["$object"]} != *createddestroyed ]]; then -+ if [[ ${objects["$object"]} != *createddestroyed && ${objects["$object"]} != *createdcreateddestroyeddestroyed ]]; then - echo "Error: $object: merely ${objects["$object"]}" >&3 - alldeleted=0 - fi -diff --git a/tools/testing/selftests/wireguard/qemu/debug.config b/tools/testing/selftests/wireguard/qemu/debug.config -index fe07d97df9fa8..2b321b8a96cf3 100644 ---- a/tools/testing/selftests/wireguard/qemu/debug.config -+++ b/tools/testing/selftests/wireguard/qemu/debug.config -@@ -47,7 +47,7 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y - CONFIG_TRACE_IRQFLAGS=y - CONFIG_DEBUG_BUGVERBOSE=y - CONFIG_DEBUG_LIST=y --CONFIG_DEBUG_PI_LIST=y -+CONFIG_DEBUG_PLIST=y - CONFIG_PROVE_RCU=y - CONFIG_SPARSE_RCU_POINTER=y - CONFIG_RCU_CPU_STALL_TIMEOUT=21 -diff --git a/tools/testing/selftests/wireguard/qemu/kernel.config b/tools/testing/selftests/wireguard/qemu/kernel.config -index 74db83a0aedd8..a9b5a520a1d22 100644 ---- a/tools/testing/selftests/wireguard/qemu/kernel.config -+++ b/tools/testing/selftests/wireguard/qemu/kernel.config -@@ -66,6 +66,7 @@ CONFIG_PROC_SYSCTL=y - CONFIG_SYSFS=y - CONFIG_TMPFS=y - CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 -+CONFIG_LOG_BUF_SHIFT=18 - CONFIG_PRINTK_TIME=y - CONFIG_BLK_DEV_INITRD=y - CONFIG_LEGACY_VSYSCALL_NONE=y -diff --git a/tools/testing/selftests/x86/iopl.c b/tools/testing/selftests/x86/iopl.c -index bab2f6e06b63d..7e3e09c1abac6 100644 ---- a/tools/testing/selftests/x86/iopl.c -+++ b/tools/testing/selftests/x86/iopl.c -@@ -85,48 +85,88 @@ static void expect_gp_outb(unsigned short port) - printf("[OK]\toutb to 0x%02hx failed\n", port); - } - --static bool try_cli(void) -+#define RET_FAULTED 0 -+#define RET_FAIL 1 -+#define RET_EMUL 2 -+ -+static int try_cli(void) - { -+ unsigned long flags; -+ - sethandler(SIGSEGV, sigsegv, SA_RESETHAND); - if (sigsetjmp(jmpbuf, 1) != 0) { -- return false; -+ return RET_FAULTED; - } else { -- asm volatile ("cli"); -- return true; -+ asm volatile("cli; pushf; pop %[flags]" -+ : [flags] "=rm" (flags)); -+ -+ /* X86_FLAGS_IF */ -+ if (!(flags & (1 << 9))) -+ return RET_FAIL; -+ else -+ return RET_EMUL; - } - clearhandler(SIGSEGV); - } - --static bool try_sti(void) -+static int try_sti(bool irqs_off) - { -+ unsigned long flags; -+ - sethandler(SIGSEGV, sigsegv, SA_RESETHAND); - if (sigsetjmp(jmpbuf, 1) != 0) { -- return false; -+ return RET_FAULTED; - } else { -- asm volatile ("sti"); -- return true; -+ asm volatile("sti; pushf; pop %[flags]" -+ : [flags] "=rm" (flags)); -+ -+ /* X86_FLAGS_IF */ -+ if (irqs_off && (flags & (1 << 9))) -+ return RET_FAIL; -+ else -+ return RET_EMUL; - } - clearhandler(SIGSEGV); - } - --static void expect_gp_sti(void) -+static void expect_gp_sti(bool irqs_off) - { -- if (try_sti()) { -+ int ret = try_sti(irqs_off); -+ -+ switch (ret) { -+ case RET_FAULTED: -+ printf("[OK]\tSTI faulted\n"); -+ break; -+ case RET_EMUL: -+ printf("[OK]\tSTI NOPped\n"); -+ break; -+ default: - printf("[FAIL]\tSTI worked\n"); - nerrs++; -- } else { -- printf("[OK]\tSTI faulted\n"); - } - } - --static void expect_gp_cli(void) -+/* -+ * Returns whether it managed to disable interrupts. -+ */ -+static bool test_cli(void) - { -- if (try_cli()) { -+ int ret = try_cli(); -+ -+ switch (ret) { -+ case RET_FAULTED: -+ printf("[OK]\tCLI faulted\n"); -+ break; -+ case RET_EMUL: -+ printf("[OK]\tCLI NOPped\n"); -+ break; -+ default: - printf("[FAIL]\tCLI worked\n"); - nerrs++; -- } else { -- printf("[OK]\tCLI faulted\n"); -+ return true; - } -+ -+ return false; - } - - int main(void) -@@ -152,8 +192,7 @@ int main(void) - } - - /* Make sure that CLI/STI are blocked even with IOPL level 3 */ -- expect_gp_cli(); -- expect_gp_sti(); -+ expect_gp_sti(test_cli()); - expect_ok_outb(0x80); - - /* Establish an I/O bitmap to test the restore */ -@@ -204,8 +243,7 @@ int main(void) - printf("[RUN]\tparent: write to 0x80 (should fail)\n"); - - expect_gp_outb(0x80); -- expect_gp_cli(); -- expect_gp_sti(); -+ expect_gp_sti(test_cli()); - - /* Test the capability checks. */ - printf("\tiopl(3)\n"); -diff --git a/tools/tracing/latency/latency-collector.c b/tools/tracing/latency/latency-collector.c -index 3a2e6bb781a8c..59a7f2346eab4 100644 ---- a/tools/tracing/latency/latency-collector.c -+++ b/tools/tracing/latency/latency-collector.c -@@ -1538,7 +1538,7 @@ static void tracing_loop(void) - mutex_lock(&print_mtx); - check_signals(); - write_or_die(fd_stdout, queue_full_warning, -- sizeof(queue_full_warning)); -+ strlen(queue_full_warning)); - mutex_unlock(&print_mtx); - } - modified--; -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 7851f3a1b5f7c..c6bfd4e15d28a 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -1523,11 +1523,10 @@ static struct kvm_memslots *kvm_dup_memslots(struct kvm_memslots *old, - - static int kvm_set_memslot(struct kvm *kvm, - const struct kvm_userspace_memory_region *mem, -- struct kvm_memory_slot *old, - struct kvm_memory_slot *new, int as_id, - enum kvm_mr_change change) - { -- struct kvm_memory_slot *slot; -+ struct kvm_memory_slot *slot, old; - struct kvm_memslots *slots; - int r; - -@@ -1558,7 +1557,7 @@ static int kvm_set_memslot(struct kvm *kvm, - * Note, the INVALID flag needs to be in the appropriate entry - * in the freshly allocated memslots, not in @old or @new. - */ -- slot = id_to_memslot(slots, old->id); -+ slot = id_to_memslot(slots, new->id); - slot->flags |= KVM_MEMSLOT_INVALID; - - /* -@@ -1589,6 +1588,26 @@ static int kvm_set_memslot(struct kvm *kvm, - kvm_copy_memslots(slots, __kvm_memslots(kvm, as_id)); - } - -+ /* -+ * Make a full copy of the old memslot, the pointer will become stale -+ * when the memslots are re-sorted by update_memslots(), and the old -+ * memslot needs to be referenced after calling update_memslots(), e.g. -+ * to free its resources and for arch specific behavior. This needs to -+ * happen *after* (re)acquiring slots_arch_lock. -+ */ -+ slot = id_to_memslot(slots, new->id); -+ if (slot) { -+ old = *slot; -+ } else { -+ WARN_ON_ONCE(change != KVM_MR_CREATE); -+ memset(&old, 0, sizeof(old)); -+ old.id = new->id; -+ old.as_id = as_id; -+ } -+ -+ /* Copy the arch-specific data, again after (re)acquiring slots_arch_lock. */ -+ memcpy(&new->arch, &old.arch, sizeof(old.arch)); -+ - r = kvm_arch_prepare_memory_region(kvm, new, mem, change); - if (r) - goto out_slots; -@@ -1596,14 +1615,18 @@ static int kvm_set_memslot(struct kvm *kvm, - update_memslots(slots, new, change); - slots = install_new_memslots(kvm, as_id, slots); - -- kvm_arch_commit_memory_region(kvm, mem, old, new, change); -+ kvm_arch_commit_memory_region(kvm, mem, &old, new, change); -+ -+ /* Free the old memslot's metadata. Note, this is the full copy!!! */ -+ if (change == KVM_MR_DELETE) -+ kvm_free_memslot(kvm, &old); - - kvfree(slots); - return 0; - - out_slots: - if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) { -- slot = id_to_memslot(slots, old->id); -+ slot = id_to_memslot(slots, new->id); - slot->flags &= ~KVM_MEMSLOT_INVALID; - slots = install_new_memslots(kvm, as_id, slots); - } else { -@@ -1618,7 +1641,6 @@ static int kvm_delete_memslot(struct kvm *kvm, - struct kvm_memory_slot *old, int as_id) - { - struct kvm_memory_slot new; -- int r; - - if (!old->npages) - return -EINVAL; -@@ -1631,12 +1653,7 @@ static int kvm_delete_memslot(struct kvm *kvm, - */ - new.as_id = as_id; - -- r = kvm_set_memslot(kvm, mem, old, &new, as_id, KVM_MR_DELETE); -- if (r) -- return r; -- -- kvm_free_memslot(kvm, old); -- return 0; -+ return kvm_set_memslot(kvm, mem, &new, as_id, KVM_MR_DELETE); - } - - /* -@@ -1664,7 +1681,8 @@ int __kvm_set_memory_region(struct kvm *kvm, - id = (u16)mem->slot; - - /* General sanity checks */ -- if (mem->memory_size & (PAGE_SIZE - 1)) -+ if ((mem->memory_size & (PAGE_SIZE - 1)) || -+ (mem->memory_size != (unsigned long)mem->memory_size)) - return -EINVAL; - if (mem->guest_phys_addr & (PAGE_SIZE - 1)) - return -EINVAL; -@@ -1710,7 +1728,6 @@ int __kvm_set_memory_region(struct kvm *kvm, - if (!old.npages) { - change = KVM_MR_CREATE; - new.dirty_bitmap = NULL; -- memset(&new.arch, 0, sizeof(new.arch)); - } else { /* Modify an existing slot. */ - if ((new.userspace_addr != old.userspace_addr) || - (new.npages != old.npages) || -@@ -1724,9 +1741,8 @@ int __kvm_set_memory_region(struct kvm *kvm, - else /* Nothing to change. */ - return 0; - -- /* Copy dirty_bitmap and arch from the current memslot. */ -+ /* Copy dirty_bitmap from the current memslot. */ - new.dirty_bitmap = old.dirty_bitmap; -- memcpy(&new.arch, &old.arch, sizeof(new.arch)); - } - - if ((change == KVM_MR_CREATE) || (change == KVM_MR_MOVE)) { -@@ -1752,7 +1768,7 @@ int __kvm_set_memory_region(struct kvm *kvm, - bitmap_set(new.dirty_bitmap, 0, new.npages); - } - -- r = kvm_set_memslot(kvm, mem, &old, &new, as_id, change); -+ r = kvm_set_memslot(kvm, mem, &new, as_id, change); - if (r) - goto out_bitmap; - -@@ -2985,7 +3001,8 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, - int r; - gpa_t gpa = ghc->gpa + offset; - -- BUG_ON(len + offset > ghc->len); -+ if (WARN_ON_ONCE(len + offset > ghc->len)) -+ return -EINVAL; - - if (slots->generation != ghc->generation) { - if (__kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len)) -@@ -3022,7 +3039,8 @@ int kvm_read_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, - int r; - gpa_t gpa = ghc->gpa + offset; - -- BUG_ON(len + offset > ghc->len); -+ if (WARN_ON_ONCE(len + offset > ghc->len)) -+ return -EINVAL; - - if (slots->generation != ghc->generation) { - if (__kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len)) diff --git a/system/easy-kernel/0100-linux-5.15.28.patch b/system/easy-kernel/0100-linux-5.15.28.patch new file mode 100644 index 000000000..5e307cfc9 --- /dev/null +++ b/system/easy-kernel/0100-linux-5.15.28.patch @@ -0,0 +1,174425 @@ +diff --git a/Documentation/accounting/psi.rst b/Documentation/accounting/psi.rst +index f2b3439edcc2c..860fe651d6453 100644 +--- a/Documentation/accounting/psi.rst ++++ b/Documentation/accounting/psi.rst +@@ -92,7 +92,8 @@ Triggers can be set on more than one psi metric and more than one trigger + for the same psi metric can be specified. However for each trigger a separate + file descriptor is required to be able to poll it separately from others, + therefore for each trigger a separate open() syscall should be made even +-when opening the same psi interface file. ++when opening the same psi interface file. Write operations to a file descriptor ++with an already existing psi trigger will fail with EBUSY. + + Monitors activate only when system enters stall state for the monitored + psi metric and deactivates upon exit from the stall state. While system is +diff --git a/Documentation/admin-guide/cifs/usage.rst b/Documentation/admin-guide/cifs/usage.rst +index f170d88202588..3766bf8a1c20e 100644 +--- a/Documentation/admin-guide/cifs/usage.rst ++++ b/Documentation/admin-guide/cifs/usage.rst +@@ -734,10 +734,9 @@ SecurityFlags Flags which control security negotiation and + using weaker password hashes is 0x37037 (lanman, + plaintext, ntlm, ntlmv2, signing allowed). Some + SecurityFlags require the corresponding menuconfig +- options to be enabled (lanman and plaintext require +- CONFIG_CIFS_WEAK_PW_HASH for example). Enabling +- plaintext authentication currently requires also +- enabling lanman authentication in the security flags ++ options to be enabled. Enabling plaintext ++ authentication currently requires also enabling ++ lanman authentication in the security flags + because the cifs module only supports sending + laintext passwords using the older lanman dialect + form of the session setup SMB. (e.g. for authentication +diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt +index 922c23bb4372a..c07dc0ee860e7 100644 +--- a/Documentation/admin-guide/devices.txt ++++ b/Documentation/admin-guide/devices.txt +@@ -2339,13 +2339,7 @@ + disks (see major number 3) except that the limit on + partitions is 31. + +- 162 char Raw block device interface +- 0 = /dev/rawctl Raw I/O control device +- 1 = /dev/raw/raw1 First raw I/O device +- 2 = /dev/raw/raw2 Second raw I/O device +- ... +- max minor number of raw device is set by kernel config +- MAX_RAW_DEVS or raw module parameter 'max_raw_devs' ++ 162 char Used for (now removed) raw block device interface + + 163 char + +diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst +index e05e581af5cfe..6bd97cd50d625 100644 +--- a/Documentation/admin-guide/hw-vuln/spectre.rst ++++ b/Documentation/admin-guide/hw-vuln/spectre.rst +@@ -60,8 +60,8 @@ privileged data touched during the speculative execution. + Spectre variant 1 attacks take advantage of speculative execution of + conditional branches, while Spectre variant 2 attacks use speculative + execution of indirect branches to leak privileged memory. +-See :ref:`[1] <spec_ref1>` :ref:`[5] <spec_ref5>` :ref:`[7] <spec_ref7>` +-:ref:`[10] <spec_ref10>` :ref:`[11] <spec_ref11>`. ++See :ref:`[1] <spec_ref1>` :ref:`[5] <spec_ref5>` :ref:`[6] <spec_ref6>` ++:ref:`[7] <spec_ref7>` :ref:`[10] <spec_ref10>` :ref:`[11] <spec_ref11>`. + + Spectre variant 1 (Bounds Check Bypass) + --------------------------------------- +@@ -131,6 +131,19 @@ steer its indirect branch speculations to gadget code, and measure the + speculative execution's side effects left in level 1 cache to infer the + victim's data. + ++Yet another variant 2 attack vector is for the attacker to poison the ++Branch History Buffer (BHB) to speculatively steer an indirect branch ++to a specific Branch Target Buffer (BTB) entry, even if the entry isn't ++associated with the source address of the indirect branch. Specifically, ++the BHB might be shared across privilege levels even in the presence of ++Enhanced IBRS. ++ ++Currently the only known real-world BHB attack vector is via ++unprivileged eBPF. Therefore, it's highly recommended to not enable ++unprivileged eBPF, especially when eIBRS is used (without retpolines). ++For a full mitigation against BHB attacks, it's recommended to use ++retpolines (or eIBRS combined with retpolines). ++ + Attack scenarios + ---------------- + +@@ -364,13 +377,15 @@ The possible values in this file are: + + - Kernel status: + +- ==================================== ================================= +- 'Not affected' The processor is not vulnerable +- 'Vulnerable' Vulnerable, no mitigation +- 'Mitigation: Full generic retpoline' Software-focused mitigation +- 'Mitigation: Full AMD retpoline' AMD-specific software mitigation +- 'Mitigation: Enhanced IBRS' Hardware-focused mitigation +- ==================================== ================================= ++ ======================================== ================================= ++ 'Not affected' The processor is not vulnerable ++ 'Mitigation: None' Vulnerable, no mitigation ++ 'Mitigation: Retpolines' Use Retpoline thunks ++ 'Mitigation: LFENCE' Use LFENCE instructions ++ 'Mitigation: Enhanced IBRS' Hardware-focused mitigation ++ 'Mitigation: Enhanced IBRS + Retpolines' Hardware-focused + Retpolines ++ 'Mitigation: Enhanced IBRS + LFENCE' Hardware-focused + LFENCE ++ ======================================== ================================= + + - Firmware status: Show if Indirect Branch Restricted Speculation (IBRS) is + used to protect against Spectre variant 2 attacks when calling firmware (x86 only). +@@ -468,7 +483,7 @@ Spectre variant 2 + before invoking any firmware code to prevent Spectre variant 2 exploits + using the firmware. + +- Using kernel address space randomization (CONFIG_RANDOMIZE_SLAB=y ++ Using kernel address space randomization (CONFIG_RANDOMIZE_BASE=y + and CONFIG_SLAB_FREELIST_RANDOM=y in the kernel configuration) makes + attacks on the kernel generally more difficult. + +@@ -584,12 +599,13 @@ kernel command line. + + Specific mitigations can also be selected manually: + +- retpoline +- replace indirect branches +- retpoline,generic +- google's original retpoline +- retpoline,amd +- AMD-specific minimal thunk ++ retpoline auto pick between generic,lfence ++ retpoline,generic Retpolines ++ retpoline,lfence LFENCE; indirect branch ++ retpoline,amd alias for retpoline,lfence ++ eibrs enhanced IBRS ++ eibrs,retpoline enhanced IBRS + Retpolines ++ eibrs,lfence enhanced IBRS + LFENCE + + Not specifying this option is equivalent to + spectre_v2=auto. +@@ -730,7 +746,7 @@ AMD white papers: + + .. _spec_ref6: + +-[6] `Software techniques for managing speculation on AMD processors <https://developer.amd.com/wp-content/resources/90343-B_SoftwareTechniquesforManagingSpeculation_WP_7-18Update_FNL.pdf>`_. ++[6] `Software techniques for managing speculation on AMD processors <https://developer.amd.com/wp-content/resources/Managing-Speculation-on-AMD-Processors.pdf>`_. + + ARM white papers: + +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 43dc35fe5bc03..ed55ea20352bc 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -1690,6 +1690,8 @@ + architectures force reset to be always executed + i8042.unlock [HW] Unlock (ignore) the keylock + i8042.kbdreset [HW] Reset device connected to KBD port ++ i8042.probe_defer ++ [HW] Allow deferred probing upon i8042 probe errors + + i810= [HW,DRM] + +@@ -2403,8 +2405,12 @@ + Default is 1 (enabled) + + kvm-intel.emulate_invalid_guest_state= +- [KVM,Intel] Enable emulation of invalid guest states +- Default is 0 (disabled) ++ [KVM,Intel] Disable emulation of invalid guest state. ++ Ignored if kvm-intel.enable_unrestricted_guest=1, as ++ guest state is never invalid for unrestricted guests. ++ This param doesn't apply to nested guests (L2), as KVM ++ never emulates invalid L2 guest state. ++ Default is 1 (enabled) + + kvm-intel.flexpriority= + [KVM,Intel] Disable FlexPriority feature (TPR shadow). +@@ -5261,8 +5267,12 @@ + Specific mitigations can also be selected manually: + + retpoline - replace indirect branches +- retpoline,generic - google's original retpoline +- retpoline,amd - AMD-specific minimal thunk ++ retpoline,generic - Retpolines ++ retpoline,lfence - LFENCE; indirect branch ++ retpoline,amd - alias for retpoline,lfence ++ eibrs - enhanced IBRS ++ eibrs,retpoline - enhanced IBRS + Retpolines ++ eibrs,lfence - enhanced IBRS + LFENCE + + Not specifying this option is equivalent to + spectre_v2=auto. +@@ -6349,6 +6359,13 @@ + improve timer resolution at the expense of processing + more timer interrupts. + ++ xen.balloon_boot_timeout= [XEN] ++ The time (in seconds) to wait before giving up to boot ++ in case initial ballooning fails to free enough memory. ++ Applies only when running as HVM or PVH guest and ++ started with less memory configured than allowed at ++ max. Default is 180. ++ + xen.event_eoi_delay= [XEN] + How long to delay EOI handling in case of event + storms (jiffies). Default is 10. +diff --git a/Documentation/admin-guide/mm/pagemap.rst b/Documentation/admin-guide/mm/pagemap.rst +index fb578fbbb76ca..49857ce1cd03e 100644 +--- a/Documentation/admin-guide/mm/pagemap.rst ++++ b/Documentation/admin-guide/mm/pagemap.rst +@@ -23,7 +23,7 @@ There are four components to pagemap: + * Bit 56 page exclusively mapped (since 4.2) + * Bit 57 pte is uffd-wp write-protected (since 5.13) (see + :ref:`Documentation/admin-guide/mm/userfaultfd.rst <userfaultfd>`) +- * Bits 57-60 zero ++ * Bits 58-60 zero + * Bit 61 page is file-page or shared-anon (since 3.5) + * Bit 62 page swapped + * Bit 63 page present +diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst +index 426162009ce99..0e486f41185ef 100644 +--- a/Documentation/admin-guide/sysctl/kernel.rst ++++ b/Documentation/admin-guide/sysctl/kernel.rst +@@ -1099,7 +1099,7 @@ task_delayacct + =============== + + Enables/disables task delay accounting (see +-:doc:`accounting/delay-accounting.rst`). Enabling this feature incurs ++Documentation/accounting/delay-accounting.rst. Enabling this feature incurs + a small amount of overhead in the scheduler but is useful for debugging + and performance tuning. It is required by some tools such as iotop. + +diff --git a/Documentation/arm64/cpu-feature-registers.rst b/Documentation/arm64/cpu-feature-registers.rst +index 328e0c454fbd4..749ae970c3195 100644 +--- a/Documentation/arm64/cpu-feature-registers.rst ++++ b/Documentation/arm64/cpu-feature-registers.rst +@@ -235,7 +235,15 @@ infrastructure: + | DPB | [3-0] | y | + +------------------------------+---------+---------+ + +- 6) ID_AA64MMFR2_EL1 - Memory model feature register 2 ++ 6) ID_AA64MMFR0_EL1 - Memory model feature register 0 ++ ++ +------------------------------+---------+---------+ ++ | Name | bits | visible | ++ +------------------------------+---------+---------+ ++ | ECV | [63-60] | y | ++ +------------------------------+---------+---------+ ++ ++ 7) ID_AA64MMFR2_EL1 - Memory model feature register 2 + + +------------------------------+---------+---------+ + | Name | bits | visible | +@@ -243,7 +251,7 @@ infrastructure: + | AT | [35-32] | y | + +------------------------------+---------+---------+ + +- 7) ID_AA64ZFR0_EL1 - SVE feature ID register 0 ++ 8) ID_AA64ZFR0_EL1 - SVE feature ID register 0 + + +------------------------------+---------+---------+ + | Name | bits | visible | +@@ -267,6 +275,23 @@ infrastructure: + | SVEVer | [3-0] | y | + +------------------------------+---------+---------+ + ++ 8) ID_AA64MMFR1_EL1 - Memory model feature register 1 ++ ++ +------------------------------+---------+---------+ ++ | Name | bits | visible | ++ +------------------------------+---------+---------+ ++ | AFP | [47-44] | y | ++ +------------------------------+---------+---------+ ++ ++ 9) ID_AA64ISAR2_EL1 - Instruction set attribute register 2 ++ ++ +------------------------------+---------+---------+ ++ | Name | bits | visible | ++ +------------------------------+---------+---------+ ++ | RPRES | [7-4] | y | ++ +------------------------------+---------+---------+ ++ ++ + Appendix I: Example + ------------------- + +diff --git a/Documentation/arm64/elf_hwcaps.rst b/Documentation/arm64/elf_hwcaps.rst +index ec1a5a63c1d09..b72ff17d600ae 100644 +--- a/Documentation/arm64/elf_hwcaps.rst ++++ b/Documentation/arm64/elf_hwcaps.rst +@@ -247,6 +247,18 @@ HWCAP2_MTE + Functionality implied by ID_AA64PFR1_EL1.MTE == 0b0010, as described + by Documentation/arm64/memory-tagging-extension.rst. + ++HWCAP2_ECV ++ ++ Functionality implied by ID_AA64MMFR0_EL1.ECV == 0b0001. ++ ++HWCAP2_AFP ++ ++ Functionality implied by ID_AA64MFR1_EL1.AFP == 0b0001. ++ ++HWCAP2_RPRES ++ ++ Functionality implied by ID_AA64ISAR2_EL1.RPRES == 0b0001. ++ + 4. Unused AT_HWCAP bits + ----------------------- + +diff --git a/Documentation/dev-tools/kfence.rst b/Documentation/dev-tools/kfence.rst +index 0fbe3308bf37f..48244d32780f6 100644 +--- a/Documentation/dev-tools/kfence.rst ++++ b/Documentation/dev-tools/kfence.rst +@@ -231,10 +231,14 @@ Guarded allocations are set up based on the sample interval. After expiration + of the sample interval, the next allocation through the main allocator (SLAB or + SLUB) returns a guarded allocation from the KFENCE object pool (allocation + sizes up to PAGE_SIZE are supported). At this point, the timer is reset, and +-the next allocation is set up after the expiration of the interval. To "gate" a +-KFENCE allocation through the main allocator's fast-path without overhead, +-KFENCE relies on static branches via the static keys infrastructure. The static +-branch is toggled to redirect the allocation to KFENCE. ++the next allocation is set up after the expiration of the interval. ++ ++When using ``CONFIG_KFENCE_STATIC_KEYS=y``, KFENCE allocations are "gated" ++through the main allocator's fast-path by relying on static branches via the ++static keys infrastructure. The static branch is toggled to redirect the ++allocation to KFENCE. Depending on sample interval, target workloads, and ++system architecture, this may perform better than the simple dynamic branch. ++Careful benchmarking is recommended. + + KFENCE objects each reside on a dedicated page, at either the left or right + page boundaries selected at random. The pages to the left and right of the +diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt +index e77635c5422c6..fa8b31660cadd 100644 +--- a/Documentation/devicetree/bindings/arm/omap/omap.txt ++++ b/Documentation/devicetree/bindings/arm/omap/omap.txt +@@ -119,6 +119,9 @@ Boards (incomplete list of examples): + - OMAP3 BeagleBoard : Low cost community board + compatible = "ti,omap3-beagle", "ti,omap3430", "ti,omap3" + ++- OMAP3 BeagleBoard A to B4 : Early BeagleBoard revisions A to B4 with a timer quirk ++ compatible = "ti,omap3-beagle-ab4", "ti,omap3-beagle", "ti,omap3430", "ti,omap3" ++ + - OMAP3 Tobi with Overo : Commercial expansion board with daughter board + compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3" + +diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml +index cf5a208f2f105..343598c9f473b 100644 +--- a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml +@@ -10,6 +10,9 @@ title: Amlogic specific extensions to the Synopsys Designware HDMI Controller + maintainers: + - Neil Armstrong <narmstrong@baylibre.com> + ++allOf: ++ - $ref: /schemas/sound/name-prefix.yaml# ++ + description: | + The Amlogic Meson Synopsys Designware Integration is composed of + - A Synopsys DesignWare HDMI Controller IP +@@ -99,6 +102,8 @@ properties: + "#sound-dai-cells": + const: 0 + ++ sound-name-prefix: true ++ + required: + - compatible + - reg +diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml +index 851cb07812173..047fd69e03770 100644 +--- a/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml ++++ b/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml +@@ -78,6 +78,10 @@ properties: + interrupts: + maxItems: 1 + ++ amlogic,canvas: ++ description: should point to a canvas provider node ++ $ref: /schemas/types.yaml#/definitions/phandle ++ + power-domains: + maxItems: 1 + description: phandle to the associated power domain +@@ -106,6 +110,7 @@ required: + - port@1 + - "#address-cells" + - "#size-cells" ++ - amlogic,canvas + + additionalProperties: false + +@@ -118,6 +123,7 @@ examples: + interrupts = <3>; + #address-cells = <1>; + #size-cells = <0>; ++ amlogic,canvas = <&canvas>; + + /* CVBS VDAC output port */ + port@0 { +diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml +index d5c54813ce872..a8f7720d1e3e2 100644 +--- a/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml ++++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml +@@ -54,7 +54,7 @@ examples: + + ad5766@0 { + compatible = "adi,ad5766"; +- output-range-microvolts = <(-5000) 5000>; ++ output-range-microvolts = <(-5000000) 5000000>; + reg = <0>; + spi-cpol; + spi-max-frequency = <1000000>; +diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt +index c76bafaf98d2f..34c43d3bddfd1 100644 +--- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt ++++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt +@@ -32,6 +32,8 @@ device-specific compatible properties, which should be used in addition to the + - vdd-supply: phandle of the regulator that provides the supply voltage. + - post-power-on-delay-ms: time required by the device after enabling its regulators + or powering it on, before it is ready for communication. ++- touchscreen-inverted-x: See touchscreen.txt ++- touchscreen-inverted-y: See touchscreen.txt + + Example: + +diff --git a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml +index 877183cf42787..1ef849dc74d7e 100644 +--- a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml ++++ b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml +@@ -79,6 +79,8 @@ properties: + + properties: + data-lanes: ++ description: ++ Note that 'fsl,imx7-mipi-csi2' only supports up to 2 data lines. + items: + minItems: 1 + maxItems: 4 +@@ -91,18 +93,6 @@ properties: + required: + - data-lanes + +- allOf: +- - if: +- properties: +- compatible: +- contains: +- const: fsl,imx7-mipi-csi2 +- then: +- properties: +- data-lanes: +- items: +- maxItems: 2 +- + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: +diff --git a/Documentation/devicetree/bindings/net/can/tcan4x5x.txt b/Documentation/devicetree/bindings/net/can/tcan4x5x.txt +index 0968b40aef1e8..e3501bfa22e90 100644 +--- a/Documentation/devicetree/bindings/net/can/tcan4x5x.txt ++++ b/Documentation/devicetree/bindings/net/can/tcan4x5x.txt +@@ -31,7 +31,7 @@ tcan4x5x: tcan4x5x@0 { + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <10000000>; +- bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>; ++ bosch,mram-cfg = <0x0 0 0 16 0 0 1 1>; + interrupt-parent = <&gpio1>; + interrupts = <14 IRQ_TYPE_LEVEL_LOW>; + device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; +diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml +index 2766fe45bb98b..ee42328a109dc 100644 +--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml ++++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml +@@ -91,6 +91,14 @@ properties: + compensate for the board being designed with the lanes + swapped. + ++ enet-phy-lane-no-swap: ++ $ref: /schemas/types.yaml#/definitions/flag ++ description: ++ If set, indicates that PHY will disable swap of the ++ TX/RX lanes. This property allows the PHY to work correcly after ++ e.g. wrong bootstrap configuration caused by issues in PCB ++ layout design. ++ + eee-broken-100tx: + $ref: /schemas/types.yaml#/definitions/flag + description: +diff --git a/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt b/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt +index 093edda0c8dfc..6cd83d920155f 100644 +--- a/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt ++++ b/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt +@@ -13,6 +13,14 @@ common regulator binding documented in: + + + Required properties of the main device node (the parent!): ++ - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used ++ for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines. ++ ++ [1] If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional ++ property is specified, then all the eight voltage values for the ++ 's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified. ++ ++Optional properties of the main device node (the parent!): + - s5m8767,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV) + units for buck2 when changing voltage using gpio dvs. Refer to [1] below + for additional information. +@@ -25,26 +33,13 @@ Required properties of the main device node (the parent!): + units for buck4 when changing voltage using gpio dvs. Refer to [1] below + for additional information. + +- - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used +- for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines. +- +- [1] If none of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional +- property is specified, the 's5m8767,pmic-buck[2/3/4]-dvs-voltage' +- property should specify atleast one voltage level (which would be a +- safe operating voltage). +- +- If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional +- property is specified, then all the eight voltage values for the +- 's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified. +- +-Optional properties of the main device node (the parent!): + - s5m8767,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs. + - s5m8767,pmic-buck3-uses-gpio-dvs: 'buck3' can be controlled by gpio dvs. + - s5m8767,pmic-buck4-uses-gpio-dvs: 'buck4' can be controlled by gpio dvs. + + Additional properties required if either of the optional properties are used: + +- - s5m8767,pmic-buck234-default-dvs-idx: Default voltage setting selected from ++ - s5m8767,pmic-buck-default-dvs-idx: Default voltage setting selected from + the possible 8 options selectable by the dvs gpios. The value of this + property should be between 0 and 7. If not specified or if out of range, the + default value of this property is set to 0. +diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml +index a07de5ed0ca6a..2d34f3ccb2572 100644 +--- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml ++++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml +@@ -199,12 +199,11 @@ patternProperties: + + contribution: + $ref: /schemas/types.yaml#/definitions/uint32 +- minimum: 0 +- maximum: 100 + description: +- The percentage contribution of the cooling devices at the +- specific trip temperature referenced in this map +- to this thermal zone ++ The cooling contribution to the thermal zone of the referred ++ cooling device at the referred trip point. The contribution is ++ a ratio of the sum of all cooling contributions within a ++ thermal zone. + + required: + - trip +diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml b/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml +index 76cb9586ee00c..93cd77a6e92c0 100644 +--- a/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml ++++ b/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml +@@ -39,8 +39,8 @@ properties: + samsung,syscon-phandle: + $ref: /schemas/types.yaml#/definitions/phandle + description: +- Phandle to the PMU system controller node (in case of Exynos5250 +- and Exynos5420). ++ Phandle to the PMU system controller node (in case of Exynos5250, ++ Exynos5420 and Exynos7). + + required: + - compatible +@@ -58,6 +58,7 @@ allOf: + enum: + - samsung,exynos5250-wdt + - samsung,exynos5420-wdt ++ - samsung,exynos7-wdt + then: + required: + - samsung,syscon-phandle +diff --git a/Documentation/driver-api/dmaengine/dmatest.rst b/Documentation/driver-api/dmaengine/dmatest.rst +index ee268d445d38b..d2e1d8b58e7dc 100644 +--- a/Documentation/driver-api/dmaengine/dmatest.rst ++++ b/Documentation/driver-api/dmaengine/dmatest.rst +@@ -143,13 +143,14 @@ Part 5 - Handling channel allocation + Allocating Channels + ------------------- + +-Channels are required to be configured prior to starting the test run. +-Attempting to run the test without configuring the channels will fail. ++Channels do not need to be configured prior to starting a test run. Attempting ++to run the test without configuring the channels will result in testing any ++channels that are available. + + Example:: + + % echo 1 > /sys/module/dmatest/parameters/run +- dmatest: Could not start test, no channels configured ++ dmatest: No channels configured, continue with any + + Channels are registered using the "channel" parameter. Channels can be requested by their + name, once requested, the channel is registered and a pending thread is added to the test list. +diff --git a/Documentation/driver-api/firewire.rst b/Documentation/driver-api/firewire.rst +index 94a2d7f01d999..d3cfa73cbb2b4 100644 +--- a/Documentation/driver-api/firewire.rst ++++ b/Documentation/driver-api/firewire.rst +@@ -19,7 +19,7 @@ of kernel interfaces is available via exported symbols in `firewire-core` module + Firewire char device data structures + ==================================== + +-.. include:: /ABI/stable/firewire-cdev ++.. include:: ../ABI/stable/firewire-cdev + :literal: + + .. kernel-doc:: include/uapi/linux/firewire-cdev.h +@@ -28,7 +28,7 @@ Firewire char device data structures + Firewire device probing and sysfs interfaces + ============================================ + +-.. include:: /ABI/stable/sysfs-bus-firewire ++.. include:: ../ABI/stable/sysfs-bus-firewire + :literal: + + .. kernel-doc:: drivers/firewire/core-device.c +diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst +index 0eb799d9d05a2..7940a45d39522 100644 +--- a/Documentation/filesystems/fscrypt.rst ++++ b/Documentation/filesystems/fscrypt.rst +@@ -176,11 +176,11 @@ Master Keys + + Each encrypted directory tree is protected by a *master key*. Master + keys can be up to 64 bytes long, and must be at least as long as the +-greater of the key length needed by the contents and filenames +-encryption modes being used. For example, if AES-256-XTS is used for +-contents encryption, the master key must be 64 bytes (512 bits). Note +-that the XTS mode is defined to require a key twice as long as that +-required by the underlying block cipher. ++greater of the security strength of the contents and filenames ++encryption modes being used. For example, if any AES-256 mode is ++used, the master key must be at least 256 bits, i.e. 32 bytes. A ++stricter requirement applies if the key is used by a v1 encryption ++policy and AES-256-XTS is used; such keys must be 64 bytes. + + To "unlock" an encrypted directory tree, userspace must provide the + appropriate master key. There can be any number of master keys, each +diff --git a/Documentation/firmware-guide/acpi/dsd/data-node-references.rst b/Documentation/firmware-guide/acpi/dsd/data-node-references.rst +index b7ad47df49de0..8b65b32e6e40e 100644 +--- a/Documentation/firmware-guide/acpi/dsd/data-node-references.rst ++++ b/Documentation/firmware-guide/acpi/dsd/data-node-references.rst +@@ -5,7 +5,7 @@ + Referencing hierarchical data nodes + =================================== + +-:Copyright: |copy| 2018 Intel Corporation ++:Copyright: |copy| 2018, 2021 Intel Corporation + :Author: Sakari Ailus <sakari.ailus@linux.intel.com> + + ACPI in general allows referring to device objects in the tree only. +@@ -52,12 +52,14 @@ the ANOD object which is also the final target node of the reference. + Name (NOD0, Package() { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () { ++ Package () { "reg", 0 }, + Package () { "random-property", 3 }, + } + }) + Name (NOD1, Package() { + ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"), + Package () { ++ Package () { "reg", 1 }, + Package () { "anothernode", "ANOD" }, + } + }) +@@ -74,7 +76,11 @@ the ANOD object which is also the final target node of the reference. + Name (_DSD, Package () { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () { +- Package () { "reference", ^DEV0, "node@1", "anothernode" }, ++ Package () { ++ "reference", Package () { ++ ^DEV0, "node@1", "anothernode" ++ } ++ }, + } + }) + } +diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst +index 204ebdaadb45a..03021dfa0dd81 100644 +--- a/Documentation/gpu/i915.rst ++++ b/Documentation/gpu/i915.rst +@@ -183,25 +183,25 @@ Frame Buffer Compression (FBC) + Display Refresh Rate Switching (DRRS) + ------------------------------------- + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :doc: Display Refresh Rate Switching (DRRS) + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :functions: intel_dp_set_drrs_state + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :functions: intel_edp_drrs_enable + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :functions: intel_edp_drrs_disable + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :functions: intel_edp_drrs_invalidate + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :functions: intel_edp_drrs_flush + +-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c ++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c + :functions: intel_dp_drrs_init + + DPIO +diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst +index 12e61869939e8..67de1e94fdf76 100644 +--- a/Documentation/gpu/todo.rst ++++ b/Documentation/gpu/todo.rst +@@ -311,27 +311,6 @@ Contact: Daniel Vetter, Noralf Tronnes + + Level: Advanced + +-Garbage collect fbdev scrolling acceleration +--------------------------------------------- +- +-Scroll acceleration is disabled in fbcon by hard-wiring p->scrollmode = +-SCROLL_REDRAW. There's a ton of code this will allow us to remove: +- +-- lots of code in fbcon.c +- +-- a bunch of the hooks in fbcon_ops, maybe the remaining hooks could be called +- directly instead of the function table (with a switch on p->rotate) +- +-- fb_copyarea is unused after this, and can be deleted from all drivers +- +-Note that not all acceleration code can be deleted, since clearing and cursor +-support is still accelerated, which might be good candidates for further +-deletion projects. +- +-Contact: Daniel Vetter +- +-Level: Intermediate +- + idr_init_base() + --------------- + +diff --git a/Documentation/hwmon/lm90.rst b/Documentation/hwmon/lm90.rst +index 3da8c6e06a365..05391fb4042d9 100644 +--- a/Documentation/hwmon/lm90.rst ++++ b/Documentation/hwmon/lm90.rst +@@ -265,6 +265,16 @@ Supported chips: + + https://www.ti.com/litv/pdf/sbos686 + ++ * Texas Instruments TMP461 ++ ++ Prefix: 'tmp461' ++ ++ Addresses scanned: I2C 0x48 through 0x4F ++ ++ Datasheet: Publicly available at TI website ++ ++ https://www.ti.com/lit/gpn/tmp461 ++ + Author: Jean Delvare <jdelvare@suse.de> + + +diff --git a/Documentation/locking/locktypes.rst b/Documentation/locking/locktypes.rst +index ddada4a537493..4fd7b70fcde19 100644 +--- a/Documentation/locking/locktypes.rst ++++ b/Documentation/locking/locktypes.rst +@@ -439,11 +439,9 @@ preemption. The following substitution works on both kernels:: + spin_lock(&p->lock); + p->count += this_cpu_read(var2); + +-On a non-PREEMPT_RT kernel migrate_disable() maps to preempt_disable() +-which makes the above code fully equivalent. On a PREEMPT_RT kernel + migrate_disable() ensures that the task is pinned on the current CPU which + in turn guarantees that the per-CPU access to var1 and var2 are staying on +-the same CPU. ++the same CPU while the task remains preemptible. + + The migrate_disable() substitution is not valid for the following + scenario:: +@@ -456,9 +454,8 @@ scenario:: + p = this_cpu_ptr(&var1); + p->val = func2(); + +-While correct on a non-PREEMPT_RT kernel, this breaks on PREEMPT_RT because +-here migrate_disable() does not protect against reentrancy from a +-preempting task. A correct substitution for this case is:: ++This breaks because migrate_disable() does not protect against reentrancy from ++a preempting task. A correct substitution for this case is:: + + func() + { +diff --git a/Documentation/networking/bonding.rst b/Documentation/networking/bonding.rst +index 31cfd7d674a6c..c0a789b008063 100644 +--- a/Documentation/networking/bonding.rst ++++ b/Documentation/networking/bonding.rst +@@ -196,11 +196,12 @@ ad_actor_sys_prio + ad_actor_system + + In an AD system, this specifies the mac-address for the actor in +- protocol packet exchanges (LACPDUs). The value cannot be NULL or +- multicast. It is preferred to have the local-admin bit set for this +- mac but driver does not enforce it. If the value is not given then +- system defaults to using the masters' mac address as actors' system +- address. ++ protocol packet exchanges (LACPDUs). The value cannot be a multicast ++ address. If the all-zeroes MAC is specified, bonding will internally ++ use the MAC of the bond itself. It is preferred to have the ++ local-admin bit set for this mac but driver does not enforce it. If ++ the value is not given then system defaults to using the masters' ++ mac address as actors' system address. + + This parameter has effect only in 802.3ad mode and is available through + SysFs interface. +diff --git a/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst b/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst +index f1d5233e5e510..0a233b17c664e 100644 +--- a/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst ++++ b/Documentation/networking/device_drivers/ethernet/intel/ixgbe.rst +@@ -440,6 +440,22 @@ NOTE: For 82599-based network connections, if you are enabling jumbo frames in + a virtual function (VF), jumbo frames must first be enabled in the physical + function (PF). The VF MTU setting cannot be larger than the PF MTU. + ++NBASE-T Support ++--------------- ++The ixgbe driver supports NBASE-T on some devices. However, the advertisement ++of NBASE-T speeds is suppressed by default, to accommodate broken network ++switches which cannot cope with advertised NBASE-T speeds. Use the ethtool ++command to enable advertising NBASE-T speeds on devices which support it:: ++ ++ ethtool -s eth? advertise 0x1800000001028 ++ ++On Linux systems with INTERFACES(5), this can be specified as a pre-up command ++in /etc/network/interfaces so that the interface is always brought up with ++NBASE-T support, e.g.:: ++ ++ iface eth? inet dhcp ++ pre-up ethtool -s eth? advertise 0x1800000001028 || true ++ + Generic Receive Offload, aka GRO + -------------------------------- + The driver supports the in-kernel software implementation of GRO. GRO has +diff --git a/Documentation/networking/ipvs-sysctl.rst b/Documentation/networking/ipvs-sysctl.rst +index 2afccc63856ee..1cfbf1add2fc9 100644 +--- a/Documentation/networking/ipvs-sysctl.rst ++++ b/Documentation/networking/ipvs-sysctl.rst +@@ -37,8 +37,7 @@ conn_reuse_mode - INTEGER + + 0: disable any special handling on port reuse. The new + connection will be delivered to the same real server that was +- servicing the previous connection. This will effectively +- disable expire_nodest_conn. ++ servicing the previous connection. + + bit 1: enable rescheduling of new connections when it is safe. + That is, whenever expire_nodest_conn and for TCP sockets, when +diff --git a/Documentation/sound/hd-audio/models.rst b/Documentation/sound/hd-audio/models.rst +index 0ea967d345838..d25335993e553 100644 +--- a/Documentation/sound/hd-audio/models.rst ++++ b/Documentation/sound/hd-audio/models.rst +@@ -326,6 +326,8 @@ usi-headset + Headset support on USI machines + dual-codecs + Lenovo laptops with dual codecs ++alc285-hp-amp-init ++ HP laptops which require speaker amplifier initialization (ALC285) + + ALC680 + ====== +diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst +index a4e3ef2952401..6ed13398ca2ce 100644 +--- a/Documentation/trace/coresight/coresight-config.rst ++++ b/Documentation/trace/coresight/coresight-config.rst +@@ -211,19 +211,13 @@ also declared in the perf 'cs_etm' event infrastructure so that they can + be selected when running trace under perf:: + + $ ls /sys/devices/cs_etm +- configurations format perf_event_mux_interval_ms sinks type +- events nr_addr_filters power ++ cpu0 cpu2 events nr_addr_filters power subsystem uevent ++ cpu1 cpu3 format perf_event_mux_interval_ms sinks type + +-Key directories here are 'configurations' - which lists the loaded +-configurations, and 'events' - a generic perf directory which allows +-selection on the perf command line.:: ++The key directory here is 'events' - a generic perf directory which allows ++selection on the perf command line. As with the sinks entries, this provides ++a hash of the configuration name. + +- $ ls configurations/ +- autofdo +- $ cat configurations/autofdo +- 0xa7c3dddd +- +-As with the sinks entries, this provides a hash of the configuration name. + The entry in the 'events' directory uses perfs built in syntax generator + to substitute the syntax for the name when evaluating the command:: + +diff --git a/Documentation/trace/events.rst b/Documentation/trace/events.rst +index 8ddb9b09451c8..c47f381d0c002 100644 +--- a/Documentation/trace/events.rst ++++ b/Documentation/trace/events.rst +@@ -198,6 +198,15 @@ The glob (~) accepts a wild card character (\*,?) and character classes + prev_comm ~ "*sh*" + prev_comm ~ "ba*sh" + ++If the field is a pointer that points into user space (for example ++"filename" from sys_enter_openat), then you have to append ".ustring" to the ++field name:: ++ ++ filename.ustring ~ "password" ++ ++As the kernel will have to know how to retrieve the memory that the pointer ++is at from user space. ++ + 5.2 Setting filters + ------------------- + +@@ -230,6 +239,16 @@ Currently the caret ('^') for an error always appears at the beginning of + the filter string; the error message should still be useful though + even without more accurate position info. + ++5.2.1 Filter limitations ++------------------------ ++ ++If a filter is placed on a string pointer ``(char *)`` that does not point ++to a string on the ring buffer, but instead points to kernel or user space ++memory, then, for safety reasons, at most 1024 bytes of the content is ++copied onto a temporary buffer to do the compare. If the copy of the memory ++faults (the pointer points to memory that should not be accessed), then the ++string compare will be treated as not matching. ++ + 5.3 Clearing filters + -------------------- + +diff --git a/MAINTAINERS b/MAINTAINERS +index 3b79fd441dde8..c8103e57a70be 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -7024,7 +7024,6 @@ F: drivers/net/mdio/fwnode_mdio.c + F: drivers/net/mdio/of_mdio.c + F: drivers/net/pcs/ + F: drivers/net/phy/ +-F: drivers/of/of_net.c + F: include/dt-bindings/net/qca-ar803x.h + F: include/linux/*mdio*.h + F: include/linux/mdio/*.h +@@ -7036,6 +7035,7 @@ F: include/linux/platform_data/mdio-gpio.h + F: include/trace/events/mdio.h + F: include/uapi/linux/mdio.h + F: include/uapi/linux/mii.h ++F: net/core/of_net.c + + EXFAT FILE SYSTEM + M: Namjae Jeon <linkinjeon@kernel.org> +diff --git a/Makefile b/Makefile +index ed6e7ec60eff6..ad64687080cff 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 15 +-SUBLEVEL = 0 ++SUBLEVEL = 28 + EXTRAVERSION = + NAME = Trick or Treat + +diff --git a/arch/Kconfig b/arch/Kconfig +index 8df1c71026435..d1e69d6e8498b 100644 +--- a/arch/Kconfig ++++ b/arch/Kconfig +@@ -1234,6 +1234,9 @@ config RELR + config ARCH_HAS_MEM_ENCRYPT + bool + ++config ARCH_HAS_CC_PLATFORM ++ bool ++ + config HAVE_SPARSE_SYSCALL_NR + bool + help +diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c +index 3793876f42d9b..8e90052f6f056 100644 +--- a/arch/arc/kernel/process.c ++++ b/arch/arc/kernel/process.c +@@ -294,7 +294,7 @@ int elf_check_arch(const struct elf32_hdr *x) + eflags = x->e_flags; + if ((eflags & EF_ARC_OSABI_MSK) != EF_ARC_OSABI_CURRENT) { + pr_err("ABI mismatch - you need newer toolchain\n"); +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + return 0; + } + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index dcf2df6da98f0..4ebd512043be5 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1455,6 +1455,7 @@ config HIGHMEM + bool "High Memory Support" + depends on MMU + select KMAP_LOCAL ++ select KMAP_LOCAL_NON_LINEAR_PTE_ARRAY + help + The address space of ARM processors is only 4 Gigabytes large + and it has to accommodate user address space, kernel address +diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug +index 98436702e0c7e..644875d73ba15 100644 +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -410,12 +410,12 @@ choice + Say Y here if you want kernel low-level debugging support + on i.MX25. + +- config DEBUG_IMX21_IMX27_UART +- bool "i.MX21 and i.MX27 Debug UART" +- depends on SOC_IMX21 || SOC_IMX27 ++ config DEBUG_IMX27_UART ++ bool "i.MX27 Debug UART" ++ depends on SOC_IMX27 + help + Say Y here if you want kernel low-level debugging support +- on i.MX21 or i.MX27. ++ on i.MX27. + + config DEBUG_IMX28_UART + bool "i.MX28 Debug UART" +@@ -1481,7 +1481,7 @@ config DEBUG_IMX_UART_PORT + int "i.MX Debug UART Port Selection" + depends on DEBUG_IMX1_UART || \ + DEBUG_IMX25_UART || \ +- DEBUG_IMX21_IMX27_UART || \ ++ DEBUG_IMX27_UART || \ + DEBUG_IMX31_UART || \ + DEBUG_IMX35_UART || \ + DEBUG_IMX50_UART || \ +@@ -1540,12 +1540,12 @@ config DEBUG_LL_INCLUDE + default "debug/icedcc.S" if DEBUG_ICEDCC + default "debug/imx.S" if DEBUG_IMX1_UART || \ + DEBUG_IMX25_UART || \ +- DEBUG_IMX21_IMX27_UART || \ ++ DEBUG_IMX27_UART || \ + DEBUG_IMX31_UART || \ + DEBUG_IMX35_UART || \ + DEBUG_IMX50_UART || \ + DEBUG_IMX51_UART || \ +- DEBUG_IMX53_UART ||\ ++ DEBUG_IMX53_UART || \ + DEBUG_IMX6Q_UART || \ + DEBUG_IMX6SL_UART || \ + DEBUG_IMX6SX_UART || \ +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 847c31e7c3687..fa45837b8065c 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -60,15 +60,15 @@ KBUILD_CFLAGS += $(call cc-option,-fno-ipa-sra) + # Note that GCC does not numerically define an architecture version + # macro, but instead defines a whole series of macros which makes + # testing for a specific architecture or later rather impossible. +-arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m +-arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) +-arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) ++arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m ++arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -march=armv7-a ++arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 -march=armv6 + # Only override the compiler option if ARMv6. The ARMv6K extensions are + # always available in ARMv7 + ifeq ($(CONFIG_CPU_32v6),y) +-arch-$(CONFIG_CPU_32v6K) =-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) ++arch-$(CONFIG_CPU_32v6K) =-D__LINUX_ARM_ARCH__=6 -march=armv6k + endif +-arch-$(CONFIG_CPU_32v5) =-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) ++arch-$(CONFIG_CPU_32v5) =-D__LINUX_ARM_ARCH__=5 -march=armv5te + arch-$(CONFIG_CPU_32v4T) =-D__LINUX_ARM_ARCH__=4 -march=armv4t + arch-$(CONFIG_CPU_32v4) =-D__LINUX_ARM_ARCH__=4 -march=armv4 + arch-$(CONFIG_CPU_32v3) =-D__LINUX_ARM_ARCH__=3 -march=armv3m +@@ -82,7 +82,7 @@ tune-$(CONFIG_CPU_ARM720T) =-mtune=arm7tdmi + tune-$(CONFIG_CPU_ARM740T) =-mtune=arm7tdmi + tune-$(CONFIG_CPU_ARM9TDMI) =-mtune=arm9tdmi + tune-$(CONFIG_CPU_ARM940T) =-mtune=arm9tdmi +-tune-$(CONFIG_CPU_ARM946E) =$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi) ++tune-$(CONFIG_CPU_ARM946E) =-mtune=arm9e + tune-$(CONFIG_CPU_ARM920T) =-mtune=arm9tdmi + tune-$(CONFIG_CPU_ARM922T) =-mtune=arm9tdmi + tune-$(CONFIG_CPU_ARM925T) =-mtune=arm9tdmi +@@ -90,11 +90,11 @@ tune-$(CONFIG_CPU_ARM926T) =-mtune=arm9tdmi + tune-$(CONFIG_CPU_FA526) =-mtune=arm9tdmi + tune-$(CONFIG_CPU_SA110) =-mtune=strongarm110 + tune-$(CONFIG_CPU_SA1100) =-mtune=strongarm1100 +-tune-$(CONFIG_CPU_XSCALE) =$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +-tune-$(CONFIG_CPU_XSC3) =$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +-tune-$(CONFIG_CPU_FEROCEON) =$(call cc-option,-mtune=marvell-f,-mtune=xscale) +-tune-$(CONFIG_CPU_V6) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) +-tune-$(CONFIG_CPU_V6K) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) ++tune-$(CONFIG_CPU_XSCALE) =-mtune=xscale ++tune-$(CONFIG_CPU_XSC3) =-mtune=xscale ++tune-$(CONFIG_CPU_FEROCEON) =-mtune=xscale ++tune-$(CONFIG_CPU_V6) =-mtune=arm1136j-s ++tune-$(CONFIG_CPU_V6K) =-mtune=arm1136j-s + + # Evaluate tune cc-option calls now + tune-y := $(tune-y) +diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S +index c0e7a745103e2..230030c130853 100644 +--- a/arch/arm/boot/compressed/efi-header.S ++++ b/arch/arm/boot/compressed/efi-header.S +@@ -9,16 +9,22 @@ + #include <linux/sizes.h> + + .macro __nop +-#ifdef CONFIG_EFI_STUB +- @ This is almost but not quite a NOP, since it does clobber the +- @ condition flags. But it is the best we can do for EFI, since +- @ PE/COFF expects the magic string "MZ" at offset 0, while the +- @ ARM/Linux boot protocol expects an executable instruction +- @ there. +- .inst MZ_MAGIC | (0x1310 << 16) @ tstne r0, #0x4d000 +-#else + AR_CLASS( mov r0, r0 ) + M_CLASS( nop.w ) ++ .endm ++ ++ .macro __initial_nops ++#ifdef CONFIG_EFI_STUB ++ @ This is a two-instruction NOP, which happens to bear the ++ @ PE/COFF signature "MZ" in the first two bytes, so the kernel ++ @ is accepted as an EFI binary. Booting via the UEFI stub ++ @ will not execute those instructions, but the ARM/Linux ++ @ boot protocol does, so we need some NOPs here. ++ .inst MZ_MAGIC | (0xe225 << 16) @ eor r5, r5, 0x4d000 ++ eor r5, r5, 0x4d000 @ undo previous insn ++#else ++ __nop ++ __nop + #endif + .endm + +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index b1cb1972361b8..bf79f2f78d232 100644 +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -203,7 +203,8 @@ start: + * were patching the initial instructions of the kernel, i.e + * had started to exploit this "patch area". + */ +- .rept 7 ++ __initial_nops ++ .rept 5 + __nop + .endr + #ifndef CONFIG_THUMB2_KERNEL +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 7e0934180724d..27ca1ca6e827c 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -779,6 +779,7 @@ dtb-$(CONFIG_ARCH_OMAP3) += \ + logicpd-som-lv-37xx-devkit.dtb \ + omap3430-sdp.dtb \ + omap3-beagle.dtb \ ++ omap3-beagle-ab4.dtb \ + omap3-beagle-xm.dtb \ + omap3-beagle-xm-ab.dtb \ + omap3-cm-t3517.dtb \ +diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi +index 9b1a24cc5e91f..df3c8d1d8f641 100644 +--- a/arch/arm/boot/dts/armada-38x.dtsi ++++ b/arch/arm/boot/dts/armada-38x.dtsi +@@ -168,7 +168,7 @@ + }; + + uart0: serial@12000 { +- compatible = "marvell,armada-38x-uart"; ++ compatible = "marvell,armada-38x-uart", "ns16550a"; + reg = <0x12000 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; +@@ -178,7 +178,7 @@ + }; + + uart1: serial@12100 { +- compatible = "marvell,armada-38x-uart"; ++ compatible = "marvell,armada-38x-uart", "ns16550a"; + reg = <0x12100 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; +diff --git a/arch/arm/boot/dts/at91-tse850-3.dts b/arch/arm/boot/dts/at91-tse850-3.dts +index 3ca97b47c69ce..7e5c598e7e68f 100644 +--- a/arch/arm/boot/dts/at91-tse850-3.dts ++++ b/arch/arm/boot/dts/at91-tse850-3.dts +@@ -262,7 +262,7 @@ + &macb1 { + status = "okay"; + +- phy-mode = "rgmii"; ++ phy-mode = "rmii"; + + #address-cells = <1>; + #size-cells = <0>; +diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi +index 748df7955ae67..e96ddb2e26e2c 100644 +--- a/arch/arm/boot/dts/bcm-nsp.dtsi ++++ b/arch/arm/boot/dts/bcm-nsp.dtsi +@@ -77,7 +77,7 @@ + interrupt-affinity = <&cpu0>, <&cpu1>; + }; + +- mpcore@19000000 { ++ mpcore-bus@19000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x19000000 0x00023000>; + #address-cells = <1>; +@@ -219,7 +219,7 @@ + status = "disabled"; + }; + +- sdio: sdhci@21000 { ++ sdio: mmc@21000 { + compatible = "brcm,sdhci-iproc-cygnus"; + reg = <0x21000 0x100>; + interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>; +diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi +index 3b60297af7f60..dff18fc9a9065 100644 +--- a/arch/arm/boot/dts/bcm2711.dtsi ++++ b/arch/arm/boot/dts/bcm2711.dtsi +@@ -506,11 +506,17 @@ + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; +- interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, ++ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "pcie", "msi"; + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 144 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 145 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 146 + IRQ_TYPE_LEVEL_HIGH>; + msi-controller; + msi-parent = <&pcie0>; +@@ -576,6 +582,8 @@ + <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + ++ gpio-ranges = <&gpio 0 0 58>; ++ + gpclk0_gpio49: gpclk0_gpio49 { + pin-gpclk { + pins = "gpio49"; +diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi +index a3e06b6809476..c113661a6668f 100644 +--- a/arch/arm/boot/dts/bcm283x.dtsi ++++ b/arch/arm/boot/dts/bcm283x.dtsi +@@ -126,6 +126,8 @@ + interrupt-controller; + #interrupt-cells = <2>; + ++ gpio-ranges = <&gpio 0 0 54>; ++ + /* Defines common pin muxing groups + * + * While each pin can have its mux selected +diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +index 61c7b137607e5..7900aac4f35a9 100644 +--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +@@ -20,7 +20,7 @@ + bootargs = "console=ttyS0,115200 earlycon"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x08000000>; +diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +index 6c6bb7b17d27a..7546c8d07bcd7 100644 +--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +@@ -19,7 +19,7 @@ + bootargs = "console=ttyS0,115200"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x08000000>; +diff --git a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +index d29e7f80ea6aa..beae9eab9cb8c 100644 +--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -19,7 +19,7 @@ + bootargs = "console=ttyS0,115200"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x18000000>; +diff --git a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts +index 9b6887d477d86..7879f7d7d9c33 100644 +--- a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts ++++ b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts +@@ -16,7 +16,7 @@ + bootargs = "console=ttyS0,115200"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x08000000>; +diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts +index 7989a53597d4f..56d309dbc6b0d 100644 +--- a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts ++++ b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts +@@ -19,7 +19,7 @@ + bootargs = "console=ttyS0,115200"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x08000000>; +diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +index 87b655be674c5..184e3039aa864 100644 +--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +@@ -30,7 +30,7 @@ + bootargs = "console=ttyS0,115200"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x08000000>; +diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts +index f806be5da7237..c2a266a439d05 100644 +--- a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts ++++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts +@@ -15,7 +15,7 @@ + bootargs = "console=ttyS0,115200 earlycon"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>; + }; +diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts +index 05d4f2931772b..9bef6b9bfa8d9 100644 +--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts ++++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts +@@ -129,7 +129,7 @@ + }; + }; + +- mdio-bus-mux@18003000 { ++ mdio-mux@18003000 { + + /* BIT(9) = 1 => external mdio */ + mdio@200 { +diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts b/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts +index 452b8d0ab180e..b0d8a688141d3 100644 +--- a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts ++++ b/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts +@@ -16,7 +16,7 @@ + bootargs = "earlycon"; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>, + <0x88000000 0x18000000>; +diff --git a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +index 3b978dc8997a4..577a4dc604d93 100644 +--- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts ++++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts +@@ -20,7 +20,7 @@ + bootargs = " console=ttyS0,115200n8 earlycon"; + }; + +- memory { ++ memory@0 { + reg = <0x00000000 0x08000000>; + device_type = "memory"; + }; +@@ -195,3 +195,25 @@ + }; + }; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ reg = <0>; ++ label = "poe"; ++ }; ++ ++ port@5 { ++ reg = <5>; ++ label = "cpu"; ++ ethernet = <&gmac0>; ++ ++ fixed-link { ++ speed = <1000>; ++ duplex-full; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi +index f92089290ccd5..f69d2af3c1fa4 100644 +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -19,7 +19,7 @@ + #size-cells = <1>; + interrupt-parent = <&gic>; + +- chipcommonA@18000000 { ++ chipcommon-a-bus@18000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x18000000 0x00001000>; + #address-cells = <1>; +@@ -44,7 +44,7 @@ + }; + }; + +- mpcore@19000000 { ++ mpcore-bus@19000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x19000000 0x00023000>; + #address-cells = <1>; +@@ -242,6 +242,8 @@ + + gpio-controller; + #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; + }; + + pcie0: pcie@12000 { +@@ -369,8 +371,8 @@ + #address-cells = <1>; + }; + +- mdio-bus-mux@18003000 { +- compatible = "mdio-mux-mmioreg"; ++ mdio-mux@18003000 { ++ compatible = "mdio-mux-mmioreg", "mdio-mux"; + mdio-parent-bus = <&mdio>; + #address-cells = <1>; + #size-cells = <0>; +@@ -408,14 +410,14 @@ + i2c0: i2c@18009000 { + compatible = "brcm,iproc-i2c"; + reg = <0x18009000 0x50>; +- interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>; ++ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + status = "disabled"; + }; + +- dmu@1800c000 { ++ dmu-bus@1800c000 { + compatible = "simple-bus"; + ranges = <0 0x1800c000 0x1000>; + #address-cells = <1>; +diff --git a/arch/arm/boot/dts/bcm94708.dts b/arch/arm/boot/dts/bcm94708.dts +index 3d13e46c69494..d9eb2040b9631 100644 +--- a/arch/arm/boot/dts/bcm94708.dts ++++ b/arch/arm/boot/dts/bcm94708.dts +@@ -38,7 +38,7 @@ + model = "NorthStar SVK (BCM94708)"; + compatible = "brcm,bcm94708", "brcm,bcm4708"; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>; + }; +diff --git a/arch/arm/boot/dts/bcm94709.dts b/arch/arm/boot/dts/bcm94709.dts +index 5017b7b259cbe..618c812eef73e 100644 +--- a/arch/arm/boot/dts/bcm94709.dts ++++ b/arch/arm/boot/dts/bcm94709.dts +@@ -38,7 +38,7 @@ + model = "NorthStar SVK (BCM94709)"; + compatible = "brcm,bcm94709", "brcm,bcm4709", "brcm,bcm4708"; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>; + }; +diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/exynos4210-i9100.dts +index 55922176807e6..5f5d9b1357365 100644 +--- a/arch/arm/boot/dts/exynos4210-i9100.dts ++++ b/arch/arm/boot/dts/exynos4210-i9100.dts +@@ -827,7 +827,7 @@ + compatible = "brcm,bcm4330-bt"; + + shutdown-gpios = <&gpl0 4 GPIO_ACTIVE_HIGH>; +- reset-gpios = <&gpl1 0 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&gpl1 0 GPIO_ACTIVE_LOW>; + device-wakeup-gpios = <&gpx3 1 GPIO_ACTIVE_HIGH>; + host-wakeup-gpios = <&gpx2 6 GPIO_ACTIVE_HIGH>; + }; +diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts +index 13112a8a5dd88..6544c730340fa 100644 +--- a/arch/arm/boot/dts/gemini-nas4220b.dts ++++ b/arch/arm/boot/dts/gemini-nas4220b.dts +@@ -84,7 +84,7 @@ + partitions { + compatible = "redboot-fis"; + /* Eraseblock at 0xfe0000 */ +- fis-index-block = <0x1fc>; ++ fis-index-block = <0x7f>; + }; + }; + +diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts +index 8cbaf1c811745..3b609d987d883 100644 +--- a/arch/arm/boot/dts/imx23-evk.dts ++++ b/arch/arm/boot/dts/imx23-evk.dts +@@ -79,7 +79,6 @@ + MX23_PAD_LCD_RESET__GPIO_1_18 + MX23_PAD_PWM3__GPIO_1_29 + MX23_PAD_PWM4__GPIO_1_30 +- MX23_PAD_SSP1_DETECT__SSP1_DETECT + >; + fsl,drive-strength = <MXS_DRIVE_4mA>; + fsl,voltage = <MXS_VOLTAGE_HIGH>; +diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi +index d07d8f83456d2..ccfa8e320be62 100644 +--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi +@@ -5,6 +5,8 @@ + * Author: Fabio Estevam <fabio.estevam@freescale.com> + */ + ++#include <dt-bindings/gpio/gpio.h> ++ + / { + aliases { + backlight = &backlight; +@@ -226,6 +228,7 @@ + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 ++ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 + >; + }; + +@@ -304,7 +307,7 @@ + &usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; +- non-removable; ++ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + +diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +index b62a0dbb033ff..ec6fba5ee8fde 100644 +--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi +@@ -309,6 +309,7 @@ + + ethphy: ethernet-phy@1 { + reg = <1>; ++ qca,clk-out-frequency = <125000000>; + }; + }; + }; +diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h +index eb025a9d47592..7328d4ef8559f 100644 +--- a/arch/arm/boot/dts/imx6ull-pinfunc.h ++++ b/arch/arm/boot/dts/imx6ull-pinfunc.h +@@ -82,6 +82,6 @@ + #define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS 0x01F4 0x0480 0x0000 0x9 0x0 + #define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK 0x01F8 0x0484 0x0000 0x9 0x0 + #define MX6ULL_PAD_CSI_DATA06__ESAI_TX5_RX0 0x01FC 0x0488 0x0000 0x9 0x0 +-#define MX6ULL_PAD_CSI_DATA07__ESAI_T0 0x0200 0x048C 0x0000 0x9 0x0 ++#define MX6ULL_PAD_CSI_DATA07__ESAI_TX0 0x0200 0x048C 0x0000 0x9 0x0 + + #endif /* __DTS_IMX6ULL_PINFUNC_H */ +diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi +index b7ea37ad4e55c..bcec98b964114 100644 +--- a/arch/arm/boot/dts/imx7ulp.dtsi ++++ b/arch/arm/boot/dts/imx7ulp.dtsi +@@ -259,7 +259,7 @@ + interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&pcc2 IMX7ULP_CLK_WDG1>; + assigned-clocks = <&pcc2 IMX7ULP_CLK_WDG1>; +- assigned-clocks-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>; ++ assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC_BUS_CLK>; + timeout-sec = <40>; + }; + +diff --git a/arch/arm/boot/dts/ls1021a-tsn.dts b/arch/arm/boot/dts/ls1021a-tsn.dts +index 9d8f0c2a8aba3..aca78b5eddf20 100644 +--- a/arch/arm/boot/dts/ls1021a-tsn.dts ++++ b/arch/arm/boot/dts/ls1021a-tsn.dts +@@ -251,7 +251,7 @@ + + flash@0 { + /* Rev. A uses 64MB flash, Rev. B & C use 32MB flash */ +- compatible = "jedec,spi-nor", "s25fl256s1", "s25fl512s"; ++ compatible = "jedec,spi-nor"; + spi-max-frequency = <20000000>; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi +index 4fce81422943b..f3b8540750b61 100644 +--- a/arch/arm/boot/dts/ls1021a.dtsi ++++ b/arch/arm/boot/dts/ls1021a.dtsi +@@ -329,39 +329,6 @@ + #thermal-sensor-cells = <1>; + }; + +- thermal-zones { +- cpu_thermal: cpu-thermal { +- polling-delay-passive = <1000>; +- polling-delay = <5000>; +- +- thermal-sensors = <&tmu 0>; +- +- trips { +- cpu_alert: cpu-alert { +- temperature = <85000>; +- hysteresis = <2000>; +- type = "passive"; +- }; +- cpu_crit: cpu-crit { +- temperature = <95000>; +- hysteresis = <2000>; +- type = "critical"; +- }; +- }; +- +- cooling-maps { +- map0 { +- trip = <&cpu_alert>; +- cooling-device = +- <&cpu0 THERMAL_NO_LIMIT +- THERMAL_NO_LIMIT>, +- <&cpu1 THERMAL_NO_LIMIT +- THERMAL_NO_LIMIT>; +- }; +- }; +- }; +- }; +- + dspi0: spi@2100000 { + compatible = "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; +@@ -1016,4 +983,37 @@ + big-endian; + }; + }; ++ ++ thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ ++ thermal-sensors = <&tmu 0>; ++ ++ trips { ++ cpu_alert: cpu-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ cpu_crit: cpu-crit { ++ temperature = <95000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert>; ++ cooling-device = ++ <&cpu0 THERMAL_NO_LIMIT ++ THERMAL_NO_LIMIT>, ++ <&cpu1 THERMAL_NO_LIMIT ++ THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/meson.dtsi +index 3be7cba603d5a..26eaba3fa96f3 100644 +--- a/arch/arm/boot/dts/meson.dtsi ++++ b/arch/arm/boot/dts/meson.dtsi +@@ -59,7 +59,7 @@ + }; + + uart_A: serial@84c0 { +- compatible = "amlogic,meson6-uart", "amlogic,meson-uart"; ++ compatible = "amlogic,meson6-uart"; + reg = <0x84c0 0x18>; + interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>; + fifo-size = <128>; +@@ -67,7 +67,7 @@ + }; + + uart_B: serial@84dc { +- compatible = "amlogic,meson6-uart", "amlogic,meson-uart"; ++ compatible = "amlogic,meson6-uart"; + reg = <0x84dc 0x18>; + interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; +@@ -105,7 +105,7 @@ + }; + + uart_C: serial@8700 { +- compatible = "amlogic,meson6-uart", "amlogic,meson-uart"; ++ compatible = "amlogic,meson6-uart"; + reg = <0x8700 0x18>; + interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; +@@ -228,7 +228,7 @@ + }; + + uart_AO: serial@4c0 { +- compatible = "amlogic,meson6-uart", "amlogic,meson-ao-uart", "amlogic,meson-uart"; ++ compatible = "amlogic,meson6-uart", "amlogic,meson-ao-uart"; + reg = <0x4c0 0x18>; + interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>; + status = "disabled"; +diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi +index f80ddc98d3a2b..9997a5d0333a3 100644 +--- a/arch/arm/boot/dts/meson8.dtsi ++++ b/arch/arm/boot/dts/meson8.dtsi +@@ -736,27 +736,27 @@ + }; + + &uart_AO { +- compatible = "amlogic,meson8-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_CLK81>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8-uart", "amlogic,meson-ao-uart"; ++ clocks = <&xtal>, <&clkc CLKID_CLK81>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &uart_A { +- compatible = "amlogic,meson8-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_UART0>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8-uart"; ++ clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &uart_B { +- compatible = "amlogic,meson8-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_UART1>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8-uart"; ++ clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &uart_C { +- compatible = "amlogic,meson8-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_UART2>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8-uart"; ++ clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &usb0 { +diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi +index b49b7cbaed4ee..94f1c03deccef 100644 +--- a/arch/arm/boot/dts/meson8b.dtsi ++++ b/arch/arm/boot/dts/meson8b.dtsi +@@ -724,27 +724,27 @@ + }; + + &uart_AO { +- compatible = "amlogic,meson8b-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_CLK81>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8b-uart", "amlogic,meson-ao-uart"; ++ clocks = <&xtal>, <&clkc CLKID_CLK81>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &uart_A { +- compatible = "amlogic,meson8b-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_UART0>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8b-uart"; ++ clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &uart_B { +- compatible = "amlogic,meson8b-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_UART1>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8b-uart"; ++ clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &uart_C { +- compatible = "amlogic,meson8b-uart", "amlogic,meson-uart"; +- clocks = <&clkc CLKID_CLK81>, <&xtal>, <&clkc CLKID_UART2>; +- clock-names = "baud", "xtal", "pclk"; ++ compatible = "amlogic,meson8b-uart"; ++ clocks = <&xtal>, <&clkc CLKID_UART0>, <&clkc CLKID_CLK81>; ++ clock-names = "xtal", "pclk", "baud"; + }; + + &usb0 { +diff --git a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi +index 7f6aefd134514..e7534fe9c53cf 100644 +--- a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi ++++ b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi +@@ -29,7 +29,7 @@ + compatible = "smsc,lan9221","smsc,lan9115"; + bank-width = <2>; + +- gpmc,mux-add-data; ++ gpmc,mux-add-data = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <42>; + gpmc,cs-wr-off-ns = <36>; +diff --git a/arch/arm/boot/dts/omap3-beagle-ab4.dts b/arch/arm/boot/dts/omap3-beagle-ab4.dts +new file mode 100644 +index 0000000000000..990ff2d846868 +--- /dev/null ++++ b/arch/arm/boot/dts/omap3-beagle-ab4.dts +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/dts-v1/; ++ ++#include "omap3-beagle.dts" ++ ++/ { ++ model = "TI OMAP3 BeagleBoard A to B4"; ++ compatible = "ti,omap3-beagle-ab4", "ti,omap3-beagle", "ti,omap3430", "ti,omap3"; ++}; ++ ++/* ++ * Workaround for capacitor C70 issue, see "Boards revision A and < B5" ++ * section at https://elinux.org/BeagleBoard_Community ++ */ ++ ++/* Unusable as clocksource because of unreliable oscillator */ ++&counter32k { ++ status = "disabled"; ++}; ++ ++/* Unusable as clockevent because of unreliable oscillator, allow to idle */ ++&timer1_target { ++ /delete-property/ti,no-reset-on-init; ++ /delete-property/ti,no-idle; ++ timer@0 { ++ /delete-property/ti,timer-alwon; ++ }; ++}; ++ ++/* Preferred always-on timer for clocksource */ ++&timer12_target { ++ ti,no-reset-on-init; ++ ti,no-idle; ++ timer@0 { ++ /* Always clocked by secure_32k_fck */ ++ }; ++}; ++ ++/* Preferred timer for clockevent */ ++&timer2_target { ++ ti,no-reset-on-init; ++ ti,no-idle; ++ timer@0 { ++ assigned-clocks = <&gpt2_fck>; ++ assigned-clock-parents = <&sys_ck>; ++ }; ++}; +diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts +index f9f34b8458e91..0548b391334fd 100644 +--- a/arch/arm/boot/dts/omap3-beagle.dts ++++ b/arch/arm/boot/dts/omap3-beagle.dts +@@ -304,39 +304,6 @@ + phys = <0 &hsusb2_phy>; + }; + +-/* Unusable as clocksource because of unreliable oscillator */ +-&counter32k { +- status = "disabled"; +-}; +- +-/* Unusable as clockevent because if unreliable oscillator, allow to idle */ +-&timer1_target { +- /delete-property/ti,no-reset-on-init; +- /delete-property/ti,no-idle; +- timer@0 { +- /delete-property/ti,timer-alwon; +- }; +-}; +- +-/* Preferred always-on timer for clocksource */ +-&timer12_target { +- ti,no-reset-on-init; +- ti,no-idle; +- timer@0 { +- /* Always clocked by secure_32k_fck */ +- }; +-}; +- +-/* Preferred timer for clockevent */ +-&timer2_target { +- ti,no-reset-on-init; +- ti,no-idle; +- timer@0 { +- assigned-clocks = <&gpt2_fck>; +- assigned-clock-parents = <&sys_ck>; +- }; +-}; +- + &twl_gpio { + ti,use-leds; + /* pullups: BIT(1) */ +diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi +index 2c19d6e255bdc..6883ccb45600b 100644 +--- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi ++++ b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi +@@ -158,6 +158,24 @@ + status = "disabled"; + }; + ++/* Unusable as clockevent because if unreliable oscillator, allow to idle */ ++&timer1_target { ++ /delete-property/ti,no-reset-on-init; ++ /delete-property/ti,no-idle; ++ timer@0 { ++ /delete-property/ti,timer-alwon; ++ }; ++}; ++ ++/* Preferred timer for clockevent */ ++&timer12_target { ++ ti,no-reset-on-init; ++ ti,no-idle; ++ timer@0 { ++ /* Always clocked by secure_32k_fck */ ++ }; ++}; ++ + &twl_gpio { + ti,use-leds; + /* +diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/omap3-devkit8000.dts +index c2995a280729d..162d0726b0080 100644 +--- a/arch/arm/boot/dts/omap3-devkit8000.dts ++++ b/arch/arm/boot/dts/omap3-devkit8000.dts +@@ -14,36 +14,3 @@ + display2 = &tv0; + }; + }; +- +-/* Unusable as clocksource because of unreliable oscillator */ +-&counter32k { +- status = "disabled"; +-}; +- +-/* Unusable as clockevent because if unreliable oscillator, allow to idle */ +-&timer1_target { +- /delete-property/ti,no-reset-on-init; +- /delete-property/ti,no-idle; +- timer@0 { +- /delete-property/ti,timer-alwon; +- }; +-}; +- +-/* Preferred always-on timer for clocksource */ +-&timer12_target { +- ti,no-reset-on-init; +- ti,no-idle; +- timer@0 { +- /* Always clocked by secure_32k_fck */ +- }; +-}; +- +-/* Preferred timer for clockevent */ +-&timer2_target { +- ti,no-reset-on-init; +- ti,no-idle; +- timer@0 { +- assigned-clocks = <&gpt2_fck>; +- assigned-clock-parents = <&sys_ck>; +- }; +-}; +diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi +index 938cc691bb2fe..23ab27fe4ee5d 100644 +--- a/arch/arm/boot/dts/omap3-gta04.dtsi ++++ b/arch/arm/boot/dts/omap3-gta04.dtsi +@@ -515,7 +515,7 @@ + compatible = "bosch,bma180"; + reg = <0x41>; + pinctrl-names = "default"; +- pintcrl-0 = <&bma180_pins>; ++ pinctrl-0 = <&bma180_pins>; + interrupt-parent = <&gpio4>; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; /* GPIO_115 */ + }; +diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts +index 32335d4ce478b..d40c3d2c4914e 100644 +--- a/arch/arm/boot/dts/omap3-n900.dts ++++ b/arch/arm/boot/dts/omap3-n900.dts +@@ -8,6 +8,7 @@ + + #include "omap34xx.dtsi" + #include <dt-bindings/input/input.h> ++#include <dt-bindings/leds/common.h> + + /* + * Default secure signed bootloader (Nokia X-Loader) does not enable L3 firewall +@@ -630,63 +631,92 @@ + }; + + lp5523: lp5523@32 { ++ #address-cells = <1>; ++ #size-cells = <0>; + compatible = "national,lp5523"; + reg = <0x32>; + clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */ +- enable-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */ ++ enable-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */ + +- chan0 { ++ led@0 { ++ reg = <0>; + chan-name = "lp5523:kb1"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_WHITE>; ++ function = LED_FUNCTION_KBD_BACKLIGHT; + }; + +- chan1 { ++ led@1 { ++ reg = <1>; + chan-name = "lp5523:kb2"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_WHITE>; ++ function = LED_FUNCTION_KBD_BACKLIGHT; + }; + +- chan2 { ++ led@2 { ++ reg = <2>; + chan-name = "lp5523:kb3"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_WHITE>; ++ function = LED_FUNCTION_KBD_BACKLIGHT; + }; + +- chan3 { ++ led@3 { ++ reg = <3>; + chan-name = "lp5523:kb4"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_WHITE>; ++ function = LED_FUNCTION_KBD_BACKLIGHT; + }; + +- chan4 { ++ led@4 { ++ reg = <4>; + chan-name = "lp5523:b"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_BLUE>; ++ function = LED_FUNCTION_STATUS; + }; + +- chan5 { ++ led@5 { ++ reg = <5>; + chan-name = "lp5523:g"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_GREEN>; ++ function = LED_FUNCTION_STATUS; + }; + +- chan6 { ++ led@6 { ++ reg = <6>; + chan-name = "lp5523:r"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_RED>; ++ function = LED_FUNCTION_STATUS; + }; + +- chan7 { ++ led@7 { ++ reg = <7>; + chan-name = "lp5523:kb5"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_WHITE>; ++ function = LED_FUNCTION_KBD_BACKLIGHT; + }; + +- chan8 { ++ led@8 { ++ reg = <8>; + chan-name = "lp5523:kb6"; + led-cur = /bits/ 8 <50>; + max-cur = /bits/ 8 <100>; ++ color = <LED_COLOR_ID_WHITE>; ++ function = LED_FUNCTION_KBD_BACKLIGHT; + }; + }; + +diff --git a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi +index e5da3bc6f1050..218a10c0d8159 100644 +--- a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi ++++ b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi +@@ -22,7 +22,7 @@ + compatible = "smsc,lan9221","smsc,lan9115"; + bank-width = <2>; + +- gpmc,mux-add-data; ++ gpmc,mux-add-data = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <42>; + gpmc,cs-wr-off-ns = <36>; +diff --git a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts +index f7ea2e5dd1914..971d2e2292600 100644 +--- a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts ++++ b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts +@@ -19,12 +19,12 @@ + stdout-path = "serial0:115200n8"; + }; + +- memory@0 { ++ memory@42000000 { + reg = <0x42000000 0x3e000000>; + device_type = "memory"; + }; + +- mdio0: mdio@0 { ++ mdio0: mdio-0 { + status = "okay"; + compatible = "virtual,mdio-gpio"; + gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>, +@@ -91,7 +91,7 @@ + }; + }; + +- mdio1: mdio@1 { ++ mdio1: mdio-1 { + status = "okay"; + compatible = "virtual,mdio-gpio"; + gpios = <&qcom_pinmux 11 GPIO_ACTIVE_HIGH>, +diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi +index 78ec496d5bc30..2b01bc29ddf23 100644 +--- a/arch/arm/boot/dts/qcom-msm8974.dtsi ++++ b/arch/arm/boot/dts/qcom-msm8974.dtsi +@@ -1589,8 +1589,8 @@ + #phy-cells = <0>; + qcom,dsi-phy-index = <0>; + +- clocks = <&mmcc MDSS_AHB_CLK>; +- clock-names = "iface"; ++ clocks = <&mmcc MDSS_AHB_CLK>, <&xo_board>; ++ clock-names = "iface", "ref"; + }; + }; + +diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi +index 1e6ce035f76a9..b5b784c5c65e4 100644 +--- a/arch/arm/boot/dts/qcom-sdx55.dtsi ++++ b/arch/arm/boot/dts/qcom-sdx55.dtsi +@@ -334,12 +334,10 @@ + clocks = <&rpmhcc RPMH_IPA_CLK>; + clock-names = "core"; + +- interconnects = <&system_noc MASTER_IPA &system_noc SLAVE_SNOC_MEM_NOC_GC>, +- <&mem_noc MASTER_SNOC_GC_MEM_NOC &mc_virt SLAVE_EBI_CH0>, ++ interconnects = <&system_noc MASTER_IPA &mc_virt SLAVE_EBI_CH0>, + <&system_noc MASTER_IPA &system_noc SLAVE_OCIMEM>, + <&mem_noc MASTER_AMPSS_M0 &system_noc SLAVE_IPA_CFG>; +- interconnect-names = "memory-a", +- "memory-b", ++ interconnect-names = "memory", + "imem", + "config"; + +diff --git a/arch/arm/boot/dts/sama7g5-pinfunc.h b/arch/arm/boot/dts/sama7g5-pinfunc.h +index 22fe9e522a97b..4eb30445d2057 100644 +--- a/arch/arm/boot/dts/sama7g5-pinfunc.h ++++ b/arch/arm/boot/dts/sama7g5-pinfunc.h +@@ -765,7 +765,7 @@ + #define PIN_PD20__PCK0 PINMUX_PIN(PIN_PD20, 1, 3) + #define PIN_PD20__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD20, 2, 2) + #define PIN_PD20__PWMH3 PINMUX_PIN(PIN_PD20, 3, 4) +-#define PIN_PD20__CANTX4 PINMUX_PIN(PIN_PD20, 5, 2) ++#define PIN_PD20__CANTX4 PINMUX_PIN(PIN_PD20, 4, 2) + #define PIN_PD20__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD20, 6, 5) + #define PIN_PD21 117 + #define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0) +diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts +index 2b645642b9352..2a745522404d6 100644 +--- a/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts ++++ b/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts +@@ -12,7 +12,7 @@ + flash0: n25q00@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q00aa"; ++ compatible = "micron,mt25qu02g", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + +diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/socfpga_arria5_socdk.dts +index 90e676e7019f2..1b02d46496a85 100644 +--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts ++++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts +@@ -119,7 +119,7 @@ + flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q256a"; ++ compatible = "micron,n25q256a", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + +diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts +index 6f138b2b26163..51bb436784e24 100644 +--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts ++++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts +@@ -124,7 +124,7 @@ + flash0: n25q00@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q00"; ++ compatible = "micron,mt25qu02g", "jedec,spi-nor"; + reg = <0>; /* chip select */ + spi-max-frequency = <100000000>; + +diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts +index c155ff02eb6e0..cae9ddd5ed38b 100644 +--- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts ++++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts +@@ -169,7 +169,7 @@ + flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q00"; ++ compatible = "micron,mt25qu02g", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + +diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts +index 8d5d3996f6f27..ca18b959e6559 100644 +--- a/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts ++++ b/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts +@@ -80,7 +80,7 @@ + flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q256a"; ++ compatible = "micron,n25q256a", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + m25p,fast-read; +diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts +index 99a71757cdf46..3f7aa7bf0863a 100644 +--- a/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts ++++ b/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts +@@ -116,7 +116,7 @@ + flash0: n25q512a@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q512a"; ++ compatible = "micron,n25q512a", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + +diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts +index a060718758b67..25874e1b9c829 100644 +--- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts ++++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts +@@ -224,7 +224,7 @@ + n25q128@0 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q128"; ++ compatible = "micron,n25q128", "jedec,spi-nor"; + reg = <0>; /* chip select */ + spi-max-frequency = <100000000>; + m25p,fast-read; +@@ -241,7 +241,7 @@ + n25q00@1 { + #address-cells = <1>; + #size-cells = <1>; +- compatible = "n25q00"; ++ compatible = "micron,mt25qu02g", "jedec,spi-nor"; + reg = <1>; /* chip select */ + spi-max-frequency = <100000000>; + m25p,fast-read; +diff --git a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts +index 264f3e9b5fce5..7fab746e0570e 100644 +--- a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts ++++ b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts +@@ -181,10 +181,6 @@ + cap-sd-highspeed; + cap-mmc-highspeed; + /* All direction control is used */ +- st,sig-dir-cmd; +- st,sig-dir-dat0; +- st,sig-dir-dat2; +- st,sig-dir-dat31; + st,sig-pin-fbclk; + full-pwr-cycle; + vmmc-supply = <&ab8500_ldo_aux3_reg>; +@@ -292,10 +288,10 @@ + }; + + ab8500_ldo_aux2 { +- /* Supplies the Cypress TMA140 touchscreen only with 3.3V */ ++ /* Supplies the Cypress TMA140 touchscreen only with 3.0V */ + regulator-name = "AUX2"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; + }; + + ab8500_ldo_aux3 { +@@ -314,9 +310,9 @@ + + ab8500_ldo_aux5 { + regulator-name = "AUX5"; ++ /* Intended for 1V8 for touchscreen but actually left unused */ + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <2790000>; +- regulator-always-on; + }; + + ab8500_ldo_aux6 { +diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/stm32f429-disco.dts +index 075ac57d0bf4a..6435e099c6326 100644 +--- a/arch/arm/boot/dts/stm32f429-disco.dts ++++ b/arch/arm/boot/dts/stm32f429-disco.dts +@@ -192,7 +192,7 @@ + + display: display@1{ + /* Connect panel-ilitek-9341 to ltdc */ +- compatible = "st,sf-tc240t-9370-t"; ++ compatible = "st,sf-tc240t-9370-t", "ilitek,ili9341"; + reg = <1>; + spi-3wire; + spi-max-frequency = <10000000>; +diff --git a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +index 5b60ecbd718f0..2ebafe27a865b 100644 +--- a/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi ++++ b/arch/arm/boot/dts/stm32mp15-pinctrl.dtsi +@@ -1179,7 +1179,7 @@ + }; + }; + +- sai2a_pins_c: sai2a-4 { ++ sai2a_pins_c: sai2a-2 { + pins { + pinmux = <STM32_PINMUX('D', 13, AF10)>, /* SAI2_SCK_A */ + <STM32_PINMUX('D', 11, AF10)>, /* SAI2_SD_A */ +@@ -1190,7 +1190,7 @@ + }; + }; + +- sai2a_sleep_pins_c: sai2a-5 { ++ sai2a_sleep_pins_c: sai2a-2 { + pins { + pinmux = <STM32_PINMUX('D', 13, ANALOG)>, /* SAI2_SCK_A */ + <STM32_PINMUX('D', 11, ANALOG)>, /* SAI2_SD_A */ +@@ -1235,14 +1235,14 @@ + }; + }; + +- sai2b_pins_c: sai2a-4 { ++ sai2b_pins_c: sai2b-2 { + pins1 { + pinmux = <STM32_PINMUX('F', 11, AF10)>; /* SAI2_SD_B */ + bias-disable; + }; + }; + +- sai2b_sleep_pins_c: sai2a-sleep-5 { ++ sai2b_sleep_pins_c: sai2b-sleep-2 { + pins { + pinmux = <STM32_PINMUX('F', 11, ANALOG)>; /* SAI2_SD_B */ + }; +diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi +index bd289bf5d2690..6992a4b0ba79b 100644 +--- a/arch/arm/boot/dts/stm32mp151.dtsi ++++ b/arch/arm/boot/dts/stm32mp151.dtsi +@@ -824,7 +824,7 @@ + #sound-dai-cells = <0>; + + compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1c>; ++ reg = <0x4 0x20>; + clocks = <&rcc SAI1_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 87 0x400 0x01>; +@@ -834,7 +834,7 @@ + sai1b: audio-controller@4400a024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI1_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 88 0x400 0x01>; +@@ -855,7 +855,7 @@ + sai2a: audio-controller@4400b004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; +- reg = <0x4 0x1c>; ++ reg = <0x4 0x20>; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 89 0x400 0x01>; +@@ -865,7 +865,7 @@ + sai2b: audio-controller@4400b024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 90 0x400 0x01>; +@@ -886,7 +886,7 @@ + sai3a: audio-controller@4400c004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; +- reg = <0x04 0x1c>; ++ reg = <0x04 0x20>; + clocks = <&rcc SAI3_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 113 0x400 0x01>; +@@ -896,7 +896,7 @@ + sai3b: audio-controller@4400c024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI3_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 114 0x400 0x01>; +@@ -1271,7 +1271,7 @@ + sai4a: audio-controller@50027004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; +- reg = <0x04 0x1c>; ++ reg = <0x04 0x20>; + clocks = <&rcc SAI4_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 99 0x400 0x01>; +@@ -1281,7 +1281,7 @@ + sai4b: audio-controller@50027024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; +- reg = <0x24 0x1c>; ++ reg = <0x24 0x20>; + clocks = <&rcc SAI4_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 100 0x400 0x01>; +diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi +index 2b0ac605549d7..44ecc47085871 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-som.dtsi +@@ -202,7 +202,7 @@ + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; +- spi-max-frequency = <108000000>; ++ spi-max-frequency = <50000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +index 899bfe04aeb91..48beed0f1f30a 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi +@@ -249,7 +249,7 @@ + stusb1600@28 { + compatible = "st,stusb1600"; + reg = <0x28>; +- interrupts = <11 IRQ_TYPE_EDGE_FALLING>; ++ interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&gpioi>; + pinctrl-names = "default"; + pinctrl-0 = <&stusb1600_pins_a>; +diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi +index 2beddbb3c5183..b3d1bdfb5118e 100644 +--- a/arch/arm/boot/dts/sun8i-a33.dtsi ++++ b/arch/arm/boot/dts/sun8i-a33.dtsi +@@ -46,7 +46,7 @@ + #include <dt-bindings/thermal/thermal.h> + + / { +- cpu0_opp_table: opp_table0 { ++ cpu0_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + +@@ -164,7 +164,7 @@ + io-channels = <&ths>; + }; + +- mali_opp_table: gpu-opp-table { ++ mali_opp_table: opp-table-gpu { + compatible = "operating-points-v2"; + + opp-144000000 { +diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi +index ac97eac91349b..82fdb04122caa 100644 +--- a/arch/arm/boot/dts/sun8i-a83t.dtsi ++++ b/arch/arm/boot/dts/sun8i-a83t.dtsi +@@ -200,7 +200,7 @@ + status = "disabled"; + }; + +- cpu0_opp_table: opp_table0 { ++ cpu0_opp_table: opp-table-cluster0 { + compatible = "operating-points-v2"; + opp-shared; + +@@ -253,7 +253,7 @@ + }; + }; + +- cpu1_opp_table: opp_table1 { ++ cpu1_opp_table: opp-table-cluster1 { + compatible = "operating-points-v2"; + opp-shared; + +diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi +index 4e89701df91f8..ae4f933abb895 100644 +--- a/arch/arm/boot/dts/sun8i-h3.dtsi ++++ b/arch/arm/boot/dts/sun8i-h3.dtsi +@@ -44,7 +44,7 @@ + #include <dt-bindings/thermal/thermal.h> + + / { +- cpu0_opp_table: opp_table0 { ++ cpu0_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + +@@ -112,7 +112,7 @@ + }; + }; + +- gpu_opp_table: gpu-opp-table { ++ gpu_opp_table: opp-table-gpu { + compatible = "operating-points-v2"; + + opp-120000000 { +diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts +index 1d2aac2cb6d03..fdc1d64dfff9d 100644 +--- a/arch/arm/boot/dts/tegra124-nyan-big.dts ++++ b/arch/arm/boot/dts/tegra124-nyan-big.dts +@@ -13,12 +13,15 @@ + "google,nyan-big-rev1", "google,nyan-big-rev0", + "google,nyan-big", "google,nyan", "nvidia,tegra124"; + +- panel: panel { +- compatible = "auo,b133xtn01"; +- +- power-supply = <&vdd_3v3_panel>; +- backlight = <&backlight>; +- ddc-i2c-bus = <&dpaux>; ++ host1x@50000000 { ++ dpaux@545c0000 { ++ aux-bus { ++ panel: panel { ++ compatible = "auo,b133xtn01"; ++ backlight = <&backlight>; ++ }; ++ }; ++ }; + }; + + mmc@700b0400 { /* SD Card on this bus */ +diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/tegra124-nyan-blaze.dts +index 677babde6460e..abdf4456826f8 100644 +--- a/arch/arm/boot/dts/tegra124-nyan-blaze.dts ++++ b/arch/arm/boot/dts/tegra124-nyan-blaze.dts +@@ -15,12 +15,15 @@ + "google,nyan-blaze-rev0", "google,nyan-blaze", + "google,nyan", "nvidia,tegra124"; + +- panel: panel { +- compatible = "samsung,ltn140at29-301"; +- +- power-supply = <&vdd_3v3_panel>; +- backlight = <&backlight>; +- ddc-i2c-bus = <&dpaux>; ++ host1x@50000000 { ++ dpaux@545c0000 { ++ aux-bus { ++ panel: panel { ++ compatible = "samsung,ltn140at29-301"; ++ backlight = <&backlight>; ++ }; ++ }; ++ }; + }; + + sound { +diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts +index e6b54ac1ebd1a..84e2d24065e9a 100644 +--- a/arch/arm/boot/dts/tegra124-venice2.dts ++++ b/arch/arm/boot/dts/tegra124-venice2.dts +@@ -48,6 +48,13 @@ + dpaux@545c0000 { + vdd-supply = <&vdd_3v3_panel>; + status = "okay"; ++ ++ aux-bus { ++ panel: panel { ++ compatible = "lg,lp129qe"; ++ backlight = <&backlight>; ++ }; ++ }; + }; + }; + +@@ -1079,13 +1086,6 @@ + }; + }; + +- panel: panel { +- compatible = "lg,lp129qe"; +- power-supply = <&vdd_3v3_panel>; +- backlight = <&backlight>; +- ddc-i2c-bus = <&dpaux>; +- }; +- + vdd_mux: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "+VDD_MUX"; +diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig +index 502a9d870ca44..45769d0ddd4ef 100644 +--- a/arch/arm/configs/cm_x300_defconfig ++++ b/arch/arm/configs/cm_x300_defconfig +@@ -146,7 +146,6 @@ CONFIG_NFS_V3_ACL=y + CONFIG_NFS_V4=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_PARTITION_ADVANCED=y + CONFIG_NLS_CODEPAGE_437=m + CONFIG_NLS_ISO8859_1=m +diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig +index a49e699e52de3..ec84d80096b1c 100644 +--- a/arch/arm/configs/ezx_defconfig ++++ b/arch/arm/configs/ezx_defconfig +@@ -314,7 +314,6 @@ CONFIG_NFSD_V3_ACL=y + CONFIG_SMB_FS=m + CONFIG_CIFS=m + CONFIG_CIFS_STATS=y +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig +index 118c4c927f264..6db871d4e0775 100644 +--- a/arch/arm/configs/imote2_defconfig ++++ b/arch/arm/configs/imote2_defconfig +@@ -288,7 +288,6 @@ CONFIG_NFSD_V3_ACL=y + CONFIG_SMB_FS=m + CONFIG_CIFS=m + CONFIG_CIFS_STATS=y +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig +index 23595fc5a29a9..907d6512821ad 100644 +--- a/arch/arm/configs/nhk8815_defconfig ++++ b/arch/arm/configs/nhk8815_defconfig +@@ -127,7 +127,6 @@ CONFIG_NFS_FS=y + CONFIG_NFS_V3_ACL=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_NLS_CODEPAGE_437=y + CONFIG_NLS_ASCII=y + CONFIG_NLS_ISO8859_1=y +diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig +index 58f4834289e63..dedaaae3d0d8a 100644 +--- a/arch/arm/configs/pxa_defconfig ++++ b/arch/arm/configs/pxa_defconfig +@@ -699,7 +699,6 @@ CONFIG_NFSD_V3_ACL=y + CONFIG_NFSD_V4=y + CONFIG_CIFS=m + CONFIG_CIFS_STATS=y +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_DEFAULT="utf8" +diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig +index 3b206a31902ff..065553326b391 100644 +--- a/arch/arm/configs/spear13xx_defconfig ++++ b/arch/arm/configs/spear13xx_defconfig +@@ -61,7 +61,6 @@ CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + # CONFIG_HW_RANDOM is not set + CONFIG_RAW_DRIVER=y +-CONFIG_MAX_RAW_DEVS=8192 + CONFIG_I2C=y + CONFIG_I2C_DESIGNWARE_PLATFORM=y + CONFIG_SPI=y +diff --git a/arch/arm/configs/spear3xx_defconfig b/arch/arm/configs/spear3xx_defconfig +index fc5f71c765edc..afca722d6605c 100644 +--- a/arch/arm/configs/spear3xx_defconfig ++++ b/arch/arm/configs/spear3xx_defconfig +@@ -41,7 +41,6 @@ CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + # CONFIG_HW_RANDOM is not set + CONFIG_RAW_DRIVER=y +-CONFIG_MAX_RAW_DEVS=8192 + CONFIG_I2C=y + CONFIG_I2C_DESIGNWARE_PLATFORM=y + CONFIG_SPI=y +diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig +index 52a56b8ce6a71..bc32c02cb86b1 100644 +--- a/arch/arm/configs/spear6xx_defconfig ++++ b/arch/arm/configs/spear6xx_defconfig +@@ -36,7 +36,6 @@ CONFIG_INPUT_FF_MEMLESS=y + CONFIG_SERIAL_AMBA_PL011=y + CONFIG_SERIAL_AMBA_PL011_CONSOLE=y + CONFIG_RAW_DRIVER=y +-CONFIG_MAX_RAW_DEVS=8192 + CONFIG_I2C=y + CONFIG_I2C_DESIGNWARE_PLATFORM=y + CONFIG_SPI=y +diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h +index e2b1fd558bf3c..09c241280ed9c 100644 +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -107,6 +107,16 @@ + .endm + #endif + ++#if __LINUX_ARM_ARCH__ < 7 ++ .macro dsb, args ++ mcr p15, 0, r0, c7, c10, 4 ++ .endm ++ ++ .macro isb, args ++ mcr p15, 0, r0, c7, c5, 4 ++ .endm ++#endif ++ + .macro asm_trace_hardirqs_off, save=1 + #if defined(CONFIG_TRACE_IRQFLAGS) + .if \save +@@ -259,6 +269,7 @@ + */ + #define ALT_UP(instr...) \ + .pushsection ".alt.smp.init", "a" ;\ ++ .align 2 ;\ + .long 9998b - . ;\ + 9997: instr ;\ + .if . - 9997b == 2 ;\ +@@ -270,6 +281,7 @@ + .popsection + #define ALT_UP_B(label) \ + .pushsection ".alt.smp.init", "a" ;\ ++ .align 2 ;\ + .long 9998b - . ;\ + W(b) . + (label - 9998b) ;\ + .popsection +diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h +index a6f3b179e8a94..27218eabbf9a0 100644 +--- a/arch/arm/include/asm/efi.h ++++ b/arch/arm/include/asm/efi.h +@@ -17,7 +17,6 @@ + + #ifdef CONFIG_EFI + void efi_init(void); +-extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); + + int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); + int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); +diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h +index 9e6b972863077..8aeff55aebfaf 100644 +--- a/arch/arm/include/asm/processor.h ++++ b/arch/arm/include/asm/processor.h +@@ -96,6 +96,7 @@ unsigned long get_wchan(struct task_struct *p); + #define __ALT_SMP_ASM(smp, up) \ + "9998: " smp "\n" \ + " .pushsection \".alt.smp.init\", \"a\"\n" \ ++ " .align 2\n" \ + " .long 9998b - .\n" \ + " " up "\n" \ + " .popsection\n" +diff --git a/arch/arm/include/asm/spectre.h b/arch/arm/include/asm/spectre.h +new file mode 100644 +index 0000000000000..d1fa5607d3aa3 +--- /dev/null ++++ b/arch/arm/include/asm/spectre.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef __ASM_SPECTRE_H ++#define __ASM_SPECTRE_H ++ ++enum { ++ SPECTRE_UNAFFECTED, ++ SPECTRE_MITIGATED, ++ SPECTRE_VULNERABLE, ++}; ++ ++enum { ++ __SPECTRE_V2_METHOD_BPIALL, ++ __SPECTRE_V2_METHOD_ICIALLU, ++ __SPECTRE_V2_METHOD_SMC, ++ __SPECTRE_V2_METHOD_HVC, ++ __SPECTRE_V2_METHOD_LOOP8, ++}; ++ ++enum { ++ SPECTRE_V2_METHOD_BPIALL = BIT(__SPECTRE_V2_METHOD_BPIALL), ++ SPECTRE_V2_METHOD_ICIALLU = BIT(__SPECTRE_V2_METHOD_ICIALLU), ++ SPECTRE_V2_METHOD_SMC = BIT(__SPECTRE_V2_METHOD_SMC), ++ SPECTRE_V2_METHOD_HVC = BIT(__SPECTRE_V2_METHOD_HVC), ++ SPECTRE_V2_METHOD_LOOP8 = BIT(__SPECTRE_V2_METHOD_LOOP8), ++}; ++ ++void spectre_v2_update_state(unsigned int state, unsigned int methods); ++ ++int spectre_bhb_update_vectors(unsigned int method); ++ ++#endif +diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h +index 36fbc33292526..32dbfd81f42a4 100644 +--- a/arch/arm/include/asm/uaccess.h ++++ b/arch/arm/include/asm/uaccess.h +@@ -11,6 +11,7 @@ + #include <linux/string.h> + #include <asm/memory.h> + #include <asm/domain.h> ++#include <asm/unaligned.h> + #include <asm/unified.h> + #include <asm/compiler.h> + +@@ -497,7 +498,10 @@ do { \ + } \ + default: __err = __get_user_bad(); break; \ + } \ +- *(type *)(dst) = __val; \ ++ if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) \ ++ put_unaligned(__val, (type *)(dst)); \ ++ else \ ++ *(type *)(dst) = __val; /* aligned by caller */ \ + if (__err) \ + goto err_label; \ + } while (0) +@@ -507,7 +511,9 @@ do { \ + const type *__pk_ptr = (dst); \ + unsigned long __dst = (unsigned long)__pk_ptr; \ + int __err = 0; \ +- type __val = *(type *)src; \ ++ type __val = IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) \ ++ ? get_unaligned((type *)(src)) \ ++ : *(type *)(src); /* aligned by caller */ \ + switch (sizeof(type)) { \ + case 1: __put_user_asm_byte(__val, __dst, __err, ""); break; \ + case 2: __put_user_asm_half(__val, __dst, __err, ""); break; \ +diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h +index 4a91428c324db..fad45c884e988 100644 +--- a/arch/arm/include/asm/vmlinux.lds.h ++++ b/arch/arm/include/asm/vmlinux.lds.h +@@ -26,6 +26,19 @@ + #define ARM_MMU_DISCARD(x) x + #endif + ++/* ++ * ld.lld does not support NOCROSSREFS: ++ * https://github.com/ClangBuiltLinux/linux/issues/1609 ++ */ ++#ifdef CONFIG_LD_IS_LLD ++#define NOCROSSREFS ++#endif ++ ++/* Set start/end symbol names to the LMA for the section */ ++#define ARM_LMA(sym, section) \ ++ sym##_start = LOADADDR(section); \ ++ sym##_end = LOADADDR(section) + SIZEOF(section) ++ + #define PROC_INFO \ + . = ALIGN(4); \ + __proc_info_begin = .; \ +@@ -110,19 +123,31 @@ + * only thing that matters is their relative offsets + */ + #define ARM_VECTORS \ +- __vectors_start = .; \ +- .vectors 0xffff0000 : AT(__vectors_start) { \ +- *(.vectors) \ ++ __vectors_lma = .; \ ++ OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) { \ ++ .vectors { \ ++ *(.vectors) \ ++ } \ ++ .vectors.bhb.loop8 { \ ++ *(.vectors.bhb.loop8) \ ++ } \ ++ .vectors.bhb.bpiall { \ ++ *(.vectors.bhb.bpiall) \ ++ } \ + } \ +- . = __vectors_start + SIZEOF(.vectors); \ +- __vectors_end = .; \ ++ ARM_LMA(__vectors, .vectors); \ ++ ARM_LMA(__vectors_bhb_loop8, .vectors.bhb.loop8); \ ++ ARM_LMA(__vectors_bhb_bpiall, .vectors.bhb.bpiall); \ ++ . = __vectors_lma + SIZEOF(.vectors) + \ ++ SIZEOF(.vectors.bhb.loop8) + \ ++ SIZEOF(.vectors.bhb.bpiall); \ + \ +- __stubs_start = .; \ +- .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { \ ++ __stubs_lma = .; \ ++ .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) { \ + *(.stubs) \ + } \ +- . = __stubs_start + SIZEOF(.stubs); \ +- __stubs_end = .; \ ++ ARM_LMA(__stubs, .stubs); \ ++ . = __stubs_lma + SIZEOF(.stubs); \ + \ + PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors)); + +diff --git a/arch/arm/include/debug/imx-uart.h b/arch/arm/include/debug/imx-uart.h +index c8eb83d4b8964..3edbb3c5b42bf 100644 +--- a/arch/arm/include/debug/imx-uart.h ++++ b/arch/arm/include/debug/imx-uart.h +@@ -11,13 +11,6 @@ + #define IMX1_UART_BASE_ADDR(n) IMX1_UART##n##_BASE_ADDR + #define IMX1_UART_BASE(n) IMX1_UART_BASE_ADDR(n) + +-#define IMX21_UART1_BASE_ADDR 0x1000a000 +-#define IMX21_UART2_BASE_ADDR 0x1000b000 +-#define IMX21_UART3_BASE_ADDR 0x1000c000 +-#define IMX21_UART4_BASE_ADDR 0x1000d000 +-#define IMX21_UART_BASE_ADDR(n) IMX21_UART##n##_BASE_ADDR +-#define IMX21_UART_BASE(n) IMX21_UART_BASE_ADDR(n) +- + #define IMX25_UART1_BASE_ADDR 0x43f90000 + #define IMX25_UART2_BASE_ADDR 0x43f94000 + #define IMX25_UART3_BASE_ADDR 0x5000c000 +@@ -26,6 +19,13 @@ + #define IMX25_UART_BASE_ADDR(n) IMX25_UART##n##_BASE_ADDR + #define IMX25_UART_BASE(n) IMX25_UART_BASE_ADDR(n) + ++#define IMX27_UART1_BASE_ADDR 0x1000a000 ++#define IMX27_UART2_BASE_ADDR 0x1000b000 ++#define IMX27_UART3_BASE_ADDR 0x1000c000 ++#define IMX27_UART4_BASE_ADDR 0x1000d000 ++#define IMX27_UART_BASE_ADDR(n) IMX27_UART##n##_BASE_ADDR ++#define IMX27_UART_BASE(n) IMX27_UART_BASE_ADDR(n) ++ + #define IMX31_UART1_BASE_ADDR 0x43f90000 + #define IMX31_UART2_BASE_ADDR 0x43f94000 + #define IMX31_UART3_BASE_ADDR 0x5000c000 +@@ -112,10 +112,10 @@ + + #ifdef CONFIG_DEBUG_IMX1_UART + #define UART_PADDR IMX_DEBUG_UART_BASE(IMX1) +-#elif defined(CONFIG_DEBUG_IMX21_IMX27_UART) +-#define UART_PADDR IMX_DEBUG_UART_BASE(IMX21) + #elif defined(CONFIG_DEBUG_IMX25_UART) + #define UART_PADDR IMX_DEBUG_UART_BASE(IMX25) ++#elif defined(CONFIG_DEBUG_IMX27_UART) ++#define UART_PADDR IMX_DEBUG_UART_BASE(IMX27) + #elif defined(CONFIG_DEBUG_IMX31_UART) + #define UART_PADDR IMX_DEBUG_UART_BASE(IMX31) + #elif defined(CONFIG_DEBUG_IMX35_UART) +diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile +index ae295a3bcfefd..6ef3b535b7bf7 100644 +--- a/arch/arm/kernel/Makefile ++++ b/arch/arm/kernel/Makefile +@@ -106,4 +106,6 @@ endif + + obj-$(CONFIG_HAVE_ARM_SMCCC) += smccc-call.o + ++obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += spectre.o ++ + extra-y := $(head-y) vmlinux.lds +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index 241b73d64df73..a0654ab1074f9 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -597,11 +597,9 @@ call_fpe: + tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2 + reteq lr + and r8, r0, #0x00000f00 @ mask out CP number +- THUMB( lsr r8, r8, #8 ) + mov r7, #1 +- add r6, r10, #TI_USED_CP +- ARM( strb r7, [r6, r8, lsr #8] ) @ set appropriate used_cp[] +- THUMB( strb r7, [r6, r8] ) @ set appropriate used_cp[] ++ add r6, r10, r8, lsr #8 @ add used_cp[] array offset first ++ strb r7, [r6, #TI_USED_CP] @ set appropriate used_cp[] + #ifdef CONFIG_IWMMXT + @ Test if we need to give access to iWMMXt coprocessors + ldr r5, [r10, #TI_FLAGS] +@@ -610,7 +608,7 @@ call_fpe: + bcs iwmmxt_task_enable + #endif + ARM( add pc, pc, r8, lsr #6 ) +- THUMB( lsl r8, r8, #2 ) ++ THUMB( lsr r8, r8, #6 ) + THUMB( add pc, r8 ) + nop + +@@ -1002,12 +1000,11 @@ vector_\name: + sub lr, lr, #\correction + .endif + +- @ +- @ Save r0, lr_<exception> (parent PC) and spsr_<exception> +- @ (parent CPSR) +- @ ++ @ Save r0, lr_<exception> (parent PC) + stmia sp, {r0, lr} @ save r0, lr +- mrs lr, spsr ++ ++ @ Save spsr_<exception> (parent CPSR) ++2: mrs lr, spsr + str lr, [sp, #8] @ save spsr + + @ +@@ -1028,6 +1025,44 @@ vector_\name: + movs pc, lr @ branch to handler in SVC mode + ENDPROC(vector_\name) + ++#ifdef CONFIG_HARDEN_BRANCH_HISTORY ++ .subsection 1 ++ .align 5 ++vector_bhb_loop8_\name: ++ .if \correction ++ sub lr, lr, #\correction ++ .endif ++ ++ @ Save r0, lr_<exception> (parent PC) ++ stmia sp, {r0, lr} ++ ++ @ bhb workaround ++ mov r0, #8 ++1: b . + 4 ++ subs r0, r0, #1 ++ bne 1b ++ dsb ++ isb ++ b 2b ++ENDPROC(vector_bhb_loop8_\name) ++ ++vector_bhb_bpiall_\name: ++ .if \correction ++ sub lr, lr, #\correction ++ .endif ++ ++ @ Save r0, lr_<exception> (parent PC) ++ stmia sp, {r0, lr} ++ ++ @ bhb workaround ++ mcr p15, 0, r0, c7, c5, 6 @ BPIALL ++ @ isb not needed due to "movs pc, lr" in the vector stub ++ @ which gives a "context synchronisation". ++ b 2b ++ENDPROC(vector_bhb_bpiall_\name) ++ .previous ++#endif ++ + .align 2 + @ handler addresses follow this label + 1: +@@ -1036,6 +1071,10 @@ ENDPROC(vector_\name) + .section .stubs, "ax", %progbits + @ This must be the first word + .word vector_swi ++#ifdef CONFIG_HARDEN_BRANCH_HISTORY ++ .word vector_bhb_loop8_swi ++ .word vector_bhb_bpiall_swi ++#endif + + vector_rst: + ARM( swi SYS_ERROR0 ) +@@ -1150,8 +1189,10 @@ vector_addrexcptn: + * FIQ "NMI" handler + *----------------------------------------------------------------------------- + * Handle a FIQ using the SVC stack allowing FIQ act like NMI on x86 +- * systems. ++ * systems. This must be the last vector stub, so lets place it in its own ++ * subsection. + */ ++ .subsection 2 + vector_stub fiq, FIQ_MODE, 4 + + .long __fiq_usr @ 0 (USR_26 / USR_32) +@@ -1184,6 +1225,30 @@ vector_addrexcptn: + W(b) vector_irq + W(b) vector_fiq + ++#ifdef CONFIG_HARDEN_BRANCH_HISTORY ++ .section .vectors.bhb.loop8, "ax", %progbits ++.L__vectors_bhb_loop8_start: ++ W(b) vector_rst ++ W(b) vector_bhb_loop8_und ++ W(ldr) pc, .L__vectors_bhb_loop8_start + 0x1004 ++ W(b) vector_bhb_loop8_pabt ++ W(b) vector_bhb_loop8_dabt ++ W(b) vector_addrexcptn ++ W(b) vector_bhb_loop8_irq ++ W(b) vector_bhb_loop8_fiq ++ ++ .section .vectors.bhb.bpiall, "ax", %progbits ++.L__vectors_bhb_bpiall_start: ++ W(b) vector_rst ++ W(b) vector_bhb_bpiall_und ++ W(ldr) pc, .L__vectors_bhb_bpiall_start + 0x1008 ++ W(b) vector_bhb_bpiall_pabt ++ W(b) vector_bhb_bpiall_dabt ++ W(b) vector_addrexcptn ++ W(b) vector_bhb_bpiall_irq ++ W(b) vector_bhb_bpiall_fiq ++#endif ++ + .data + .align 2 + +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index d9c99db50243f..fde7ac271b147 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -153,6 +153,29 @@ ENDPROC(ret_from_fork) + *----------------------------------------------------------------------------- + */ + ++ .align 5 ++#ifdef CONFIG_HARDEN_BRANCH_HISTORY ++ENTRY(vector_bhb_loop8_swi) ++ sub sp, sp, #PT_REGS_SIZE ++ stmia sp, {r0 - r12} ++ mov r8, #8 ++1: b 2f ++2: subs r8, r8, #1 ++ bne 1b ++ dsb ++ isb ++ b 3f ++ENDPROC(vector_bhb_loop8_swi) ++ ++ .align 5 ++ENTRY(vector_bhb_bpiall_swi) ++ sub sp, sp, #PT_REGS_SIZE ++ stmia sp, {r0 - r12} ++ mcr p15, 0, r8, c7, c5, 6 @ BPIALL ++ isb ++ b 3f ++ENDPROC(vector_bhb_bpiall_swi) ++#endif + .align 5 + ENTRY(vector_swi) + #ifdef CONFIG_CPU_V7M +@@ -160,6 +183,7 @@ ENTRY(vector_swi) + #else + sub sp, sp, #PT_REGS_SIZE + stmia sp, {r0 - r12} @ Calling r0 - r12 ++3: + ARM( add r8, sp, #S_PC ) + ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr + THUMB( mov r8, sp ) +diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S +index 0fc814bbc34b1..8796a69c78e00 100644 +--- a/arch/arm/kernel/head-nommu.S ++++ b/arch/arm/kernel/head-nommu.S +@@ -114,6 +114,7 @@ ENTRY(secondary_startup) + add r12, r12, r10 + ret r12 + 1: bl __after_proc_init ++ ldr r7, __secondary_data @ reload r7 + ldr sp, [r7, #12] @ set up the stack pointer + mov fp, #0 + b secondary_start_kernel +diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c +index 7bd30c0a4280d..22f937e6f3ffb 100644 +--- a/arch/arm/kernel/kgdb.c ++++ b/arch/arm/kernel/kgdb.c +@@ -154,22 +154,38 @@ static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr) + return 0; + } + +-static struct undef_hook kgdb_brkpt_hook = { ++static struct undef_hook kgdb_brkpt_arm_hook = { + .instr_mask = 0xffffffff, + .instr_val = KGDB_BREAKINST, +- .cpsr_mask = MODE_MASK, ++ .cpsr_mask = PSR_T_BIT | MODE_MASK, + .cpsr_val = SVC_MODE, + .fn = kgdb_brk_fn + }; + +-static struct undef_hook kgdb_compiled_brkpt_hook = { ++static struct undef_hook kgdb_brkpt_thumb_hook = { ++ .instr_mask = 0xffff, ++ .instr_val = KGDB_BREAKINST & 0xffff, ++ .cpsr_mask = PSR_T_BIT | MODE_MASK, ++ .cpsr_val = PSR_T_BIT | SVC_MODE, ++ .fn = kgdb_brk_fn ++}; ++ ++static struct undef_hook kgdb_compiled_brkpt_arm_hook = { + .instr_mask = 0xffffffff, + .instr_val = KGDB_COMPILED_BREAK, +- .cpsr_mask = MODE_MASK, ++ .cpsr_mask = PSR_T_BIT | MODE_MASK, + .cpsr_val = SVC_MODE, + .fn = kgdb_compiled_brk_fn + }; + ++static struct undef_hook kgdb_compiled_brkpt_thumb_hook = { ++ .instr_mask = 0xffff, ++ .instr_val = KGDB_COMPILED_BREAK & 0xffff, ++ .cpsr_mask = PSR_T_BIT | MODE_MASK, ++ .cpsr_val = PSR_T_BIT | SVC_MODE, ++ .fn = kgdb_compiled_brk_fn ++}; ++ + static int __kgdb_notify(struct die_args *args, unsigned long cmd) + { + struct pt_regs *regs = args->regs; +@@ -210,8 +226,10 @@ int kgdb_arch_init(void) + if (ret != 0) + return ret; + +- register_undef_hook(&kgdb_brkpt_hook); +- register_undef_hook(&kgdb_compiled_brkpt_hook); ++ register_undef_hook(&kgdb_brkpt_arm_hook); ++ register_undef_hook(&kgdb_brkpt_thumb_hook); ++ register_undef_hook(&kgdb_compiled_brkpt_arm_hook); ++ register_undef_hook(&kgdb_compiled_brkpt_thumb_hook); + + return 0; + } +@@ -224,8 +242,10 @@ int kgdb_arch_init(void) + */ + void kgdb_arch_exit(void) + { +- unregister_undef_hook(&kgdb_brkpt_hook); +- unregister_undef_hook(&kgdb_compiled_brkpt_hook); ++ unregister_undef_hook(&kgdb_brkpt_arm_hook); ++ unregister_undef_hook(&kgdb_brkpt_thumb_hook); ++ unregister_undef_hook(&kgdb_compiled_brkpt_arm_hook); ++ unregister_undef_hook(&kgdb_compiled_brkpt_thumb_hook); + unregister_die_notifier(&kgdb_notifier); + } + +diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c +index 3b69a76d341e7..1626dfc6f6ce6 100644 +--- a/arch/arm/kernel/perf_callchain.c ++++ b/arch/arm/kernel/perf_callchain.c +@@ -62,9 +62,10 @@ user_backtrace(struct frame_tail __user *tail, + void + perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct frame_tail __user *tail; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* We don't support guest os callchain now */ + return; + } +@@ -98,9 +99,10 @@ callchain_trace(struct stackframe *fr, + void + perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct stackframe fr; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* We don't support guest os callchain now */ + return; + } +@@ -111,18 +113,21 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re + + unsigned long perf_instruction_pointer(struct pt_regs *regs) + { +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) +- return perf_guest_cbs->get_guest_ip(); ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); ++ ++ if (guest_cbs && guest_cbs->is_in_guest()) ++ return guest_cbs->get_guest_ip(); + + return instruction_pointer(regs); + } + + unsigned long perf_misc_flags(struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + int misc = 0; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { +- if (perf_guest_cbs->is_user_mode()) ++ if (guest_cbs && guest_cbs->is_in_guest()) { ++ if (guest_cbs->is_user_mode()) + misc |= PERF_RECORD_MISC_GUEST_USER; + else + misc |= PERF_RECORD_MISC_GUEST_KERNEL; +diff --git a/arch/arm/kernel/spectre.c b/arch/arm/kernel/spectre.c +new file mode 100644 +index 0000000000000..0dcefc36fb7a0 +--- /dev/null ++++ b/arch/arm/kernel/spectre.c +@@ -0,0 +1,71 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++#include <linux/bpf.h> ++#include <linux/cpu.h> ++#include <linux/device.h> ++ ++#include <asm/spectre.h> ++ ++static bool _unprivileged_ebpf_enabled(void) ++{ ++#ifdef CONFIG_BPF_SYSCALL ++ return !sysctl_unprivileged_bpf_disabled; ++#else ++ return false; ++#endif ++} ++ ++ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "Mitigation: __user pointer sanitization\n"); ++} ++ ++static unsigned int spectre_v2_state; ++static unsigned int spectre_v2_methods; ++ ++void spectre_v2_update_state(unsigned int state, unsigned int method) ++{ ++ if (state > spectre_v2_state) ++ spectre_v2_state = state; ++ spectre_v2_methods |= method; ++} ++ ++ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ const char *method; ++ ++ if (spectre_v2_state == SPECTRE_UNAFFECTED) ++ return sprintf(buf, "%s\n", "Not affected"); ++ ++ if (spectre_v2_state != SPECTRE_MITIGATED) ++ return sprintf(buf, "%s\n", "Vulnerable"); ++ ++ if (_unprivileged_ebpf_enabled()) ++ return sprintf(buf, "Vulnerable: Unprivileged eBPF enabled\n"); ++ ++ switch (spectre_v2_methods) { ++ case SPECTRE_V2_METHOD_BPIALL: ++ method = "Branch predictor hardening"; ++ break; ++ ++ case SPECTRE_V2_METHOD_ICIALLU: ++ method = "I-cache invalidation"; ++ break; ++ ++ case SPECTRE_V2_METHOD_SMC: ++ case SPECTRE_V2_METHOD_HVC: ++ method = "Firmware call"; ++ break; ++ ++ case SPECTRE_V2_METHOD_LOOP8: ++ method = "History overwrite"; ++ break; ++ ++ default: ++ method = "Multiple mitigations"; ++ break; ++ } ++ ++ return sprintf(buf, "Mitigation: %s\n", method); ++} +diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c +index 76ea4178a55cb..db798eac74315 100644 +--- a/arch/arm/kernel/stacktrace.c ++++ b/arch/arm/kernel/stacktrace.c +@@ -54,8 +54,7 @@ int notrace unwind_frame(struct stackframe *frame) + + frame->sp = frame->fp; + frame->fp = *(unsigned long *)(fp); +- frame->pc = frame->lr; +- frame->lr = *(unsigned long *)(fp + 4); ++ frame->pc = *(unsigned long *)(fp + 4); + #else + /* check current frame pointer is within bounds */ + if (fp < low + 12 || fp > high - 4) +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index 195dff58bafc7..655c4fe0b4d08 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -30,6 +30,7 @@ + #include <linux/atomic.h> + #include <asm/cacheflush.h> + #include <asm/exception.h> ++#include <asm/spectre.h> + #include <asm/unistd.h> + #include <asm/traps.h> + #include <asm/ptrace.h> +@@ -787,10 +788,59 @@ static inline void __init kuser_init(void *vectors) + } + #endif + ++#ifndef CONFIG_CPU_V7M ++static void copy_from_lma(void *vma, void *lma_start, void *lma_end) ++{ ++ memcpy(vma, lma_start, lma_end - lma_start); ++} ++ ++static void flush_vectors(void *vma, size_t offset, size_t size) ++{ ++ unsigned long start = (unsigned long)vma + offset; ++ unsigned long end = start + size; ++ ++ flush_icache_range(start, end); ++} ++ ++#ifdef CONFIG_HARDEN_BRANCH_HISTORY ++int spectre_bhb_update_vectors(unsigned int method) ++{ ++ extern char __vectors_bhb_bpiall_start[], __vectors_bhb_bpiall_end[]; ++ extern char __vectors_bhb_loop8_start[], __vectors_bhb_loop8_end[]; ++ void *vec_start, *vec_end; ++ ++ if (system_state > SYSTEM_SCHEDULING) { ++ pr_err("CPU%u: Spectre BHB workaround too late - system vulnerable\n", ++ smp_processor_id()); ++ return SPECTRE_VULNERABLE; ++ } ++ ++ switch (method) { ++ case SPECTRE_V2_METHOD_LOOP8: ++ vec_start = __vectors_bhb_loop8_start; ++ vec_end = __vectors_bhb_loop8_end; ++ break; ++ ++ case SPECTRE_V2_METHOD_BPIALL: ++ vec_start = __vectors_bhb_bpiall_start; ++ vec_end = __vectors_bhb_bpiall_end; ++ break; ++ ++ default: ++ pr_err("CPU%u: unknown Spectre BHB state %d\n", ++ smp_processor_id(), method); ++ return SPECTRE_VULNERABLE; ++ } ++ ++ copy_from_lma(vectors_page, vec_start, vec_end); ++ flush_vectors(vectors_page, 0, vec_end - vec_start); ++ ++ return SPECTRE_MITIGATED; ++} ++#endif ++ + void __init early_trap_init(void *vectors_base) + { +-#ifndef CONFIG_CPU_V7M +- unsigned long vectors = (unsigned long)vectors_base; + extern char __stubs_start[], __stubs_end[]; + extern char __vectors_start[], __vectors_end[]; + unsigned i; +@@ -811,17 +861,20 @@ void __init early_trap_init(void *vectors_base) + * into the vector page, mapped at 0xffff0000, and ensure these + * are visible to the instruction stream. + */ +- memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); +- memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start); ++ copy_from_lma(vectors_base, __vectors_start, __vectors_end); ++ copy_from_lma(vectors_base + 0x1000, __stubs_start, __stubs_end); + + kuser_init(vectors_base); + +- flush_icache_range(vectors, vectors + PAGE_SIZE * 2); ++ flush_vectors(vectors_base, 0, PAGE_SIZE * 2); ++} + #else /* ifndef CONFIG_CPU_V7M */ ++void __init early_trap_init(void *vectors_base) ++{ + /* + * on V7-M there is no need to copy the vector table to a dedicated + * memory area. The address is configurable and so a table in the kernel + * image can be used. + */ +-#endif + } ++#endif +diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c +index 6daaa645ae5d9..21413a9b7b6c6 100644 +--- a/arch/arm/mach-omap2/display.c ++++ b/arch/arm/mach-omap2/display.c +@@ -263,9 +263,9 @@ static int __init omapdss_init_of(void) + } + + r = of_platform_populate(node, NULL, NULL, &pdev->dev); ++ put_device(&pdev->dev); + if (r) { + pr_err("Unable to populate DSS submodule devices\n"); +- put_device(&pdev->dev); + return r; + } + +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 0c2936c7a3799..a5e9cffcac10c 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -752,8 +752,10 @@ static int __init _init_clkctrl_providers(void) + + for_each_matching_node(np, ti_clkctrl_match_table) { + ret = _setup_clkctrl_provider(np); +- if (ret) ++ if (ret) { ++ of_node_put(np); + break; ++ } + } + + return ret; +diff --git a/arch/arm/mach-s3c/irq-s3c24xx.c b/arch/arm/mach-s3c/irq-s3c24xx.c +index 3edc5f614eefc..c1c2f041ad3b1 100644 +--- a/arch/arm/mach-s3c/irq-s3c24xx.c ++++ b/arch/arm/mach-s3c/irq-s3c24xx.c +@@ -361,11 +361,25 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, + static asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs) + { + do { +- if (likely(s3c_intc[0])) +- if (s3c24xx_handle_intc(s3c_intc[0], regs, 0)) +- continue; ++ /* ++ * For platform based machines, neither ERR nor NULL can happen here. ++ * The s3c24xx_handle_irq() will be set as IRQ handler iff this succeeds: ++ * ++ * s3c_intc[0] = s3c24xx_init_intc() ++ * ++ * If this fails, the next calls to s3c24xx_init_intc() won't be executed. ++ * ++ * For DT machine, s3c_init_intc_of() could set the IRQ handler without ++ * setting s3c_intc[0] only if it was called with num_ctrl=0. There is no ++ * such code path, so again the s3c_intc[0] will have a valid pointer if ++ * set_handle_irq() is called. ++ * ++ * Therefore in s3c24xx_handle_irq(), the s3c_intc[0] is always something. ++ */ ++ if (s3c24xx_handle_intc(s3c_intc[0], regs, 0)) ++ continue; + +- if (s3c_intc[2]) ++ if (!IS_ERR_OR_NULL(s3c_intc[2])) + if (s3c24xx_handle_intc(s3c_intc[2], regs, 64)) + continue; + +diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +index ee949255ced3f..09ef73b99dd86 100644 +--- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c ++++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c +@@ -154,8 +154,10 @@ static int __init rcar_gen2_regulator_quirk(void) + return -ENODEV; + + for_each_matching_node_and_match(np, rcar_gen2_quirk_match, &id) { +- if (!of_device_is_available(np)) ++ if (!of_device_is_available(np)) { ++ of_node_put(np); + break; ++ } + + ret = of_property_read_u32(np, "reg", &addr); + if (ret) /* Skip invalid entry and continue */ +@@ -164,6 +166,7 @@ static int __init rcar_gen2_regulator_quirk(void) + quirk = kzalloc(sizeof(*quirk), GFP_KERNEL); + if (!quirk) { + ret = -ENOMEM; ++ of_node_put(np); + goto err_mem; + } + +diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig +index 43ddec677c0b3..594edf9bbea44 100644 +--- a/arch/arm/mach-socfpga/Kconfig ++++ b/arch/arm/mach-socfpga/Kconfig +@@ -2,6 +2,7 @@ + menuconfig ARCH_INTEL_SOCFPGA + bool "Altera SOCFPGA family" + depends on ARCH_MULTI_V7 ++ select ARCH_HAS_RESET_CONTROLLER + select ARCH_SUPPORTS_BIG_ENDIAN + select ARM_AMBA + select ARM_GIC +@@ -18,6 +19,7 @@ menuconfig ARCH_INTEL_SOCFPGA + select PL310_ERRATA_727915 + select PL310_ERRATA_753970 if PL310 + select PL310_ERRATA_769419 ++ select RESET_CONTROLLER + + if ARCH_INTEL_SOCFPGA + config SOCFPGA_SUSPEND +diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h +index fc2608b18a0d0..18f01190dcfd4 100644 +--- a/arch/arm/mach-socfpga/core.h ++++ b/arch/arm/mach-socfpga/core.h +@@ -33,7 +33,7 @@ extern void __iomem *sdr_ctl_base_addr; + u32 socfpga_sdram_self_refresh(u32 sdr_base); + extern unsigned int socfpga_sdram_self_refresh_sz; + +-extern char secondary_trampoline, secondary_trampoline_end; ++extern char secondary_trampoline[], secondary_trampoline_end[]; + + extern unsigned long socfpga_cpu1start_addr; + +diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c +index fbb80b883e5dd..201191cf68f32 100644 +--- a/arch/arm/mach-socfpga/platsmp.c ++++ b/arch/arm/mach-socfpga/platsmp.c +@@ -20,14 +20,14 @@ + + static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) + { +- int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; ++ int trampoline_size = secondary_trampoline_end - secondary_trampoline; + + if (socfpga_cpu1start_addr) { + /* This will put CPU #1 into reset. */ + writel(RSTMGR_MPUMODRST_CPU1, + rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST); + +- memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); ++ memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size); + + writel(__pa_symbol(secondary_startup), + sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff)); +@@ -45,12 +45,12 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) + + static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle) + { +- int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; ++ int trampoline_size = secondary_trampoline_end - secondary_trampoline; + + if (socfpga_cpu1start_addr) { + writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr + + SOCFPGA_A10_RSTMGR_MODMPURST); +- memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); ++ memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size); + + writel(__pa_symbol(secondary_startup), + sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff)); +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 8355c38958942..f43cdc1cfbaed 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -750,7 +750,7 @@ config CPU_BIG_ENDIAN + config CPU_ENDIAN_BE8 + bool + depends on CPU_BIG_ENDIAN +- default CPU_V6 || CPU_V6K || CPU_V7 ++ default CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M + help + Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors. + +@@ -830,6 +830,7 @@ config CPU_BPREDICT_DISABLE + + config CPU_SPECTRE + bool ++ select GENERIC_CPU_VULNERABILITIES + + config HARDEN_BRANCH_PREDICTOR + bool "Harden the branch predictor against aliasing attacks" if EXPERT +@@ -850,6 +851,16 @@ config HARDEN_BRANCH_PREDICTOR + + If unsure, say Y. + ++config HARDEN_BRANCH_HISTORY ++ bool "Harden Spectre style attacks against branch history" if EXPERT ++ depends on CPU_SPECTRE ++ default y ++ help ++ Speculation attacks against some high-performance processors can ++ make use of branch history to influence future speculation. When ++ taking an exception, a sequence of branches overwrites the branch ++ history, or branch history is invalidated. ++ + config TLS_REG_EMUL + bool + select NEED_KUSER_HELPERS +diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c +index 9c348042a7244..4b1619584b23c 100644 +--- a/arch/arm/mm/kasan_init.c ++++ b/arch/arm/mm/kasan_init.c +@@ -226,7 +226,7 @@ void __init kasan_init(void) + BUILD_BUG_ON(pgd_index(KASAN_SHADOW_START) != + pgd_index(KASAN_SHADOW_END)); + memcpy(tmp_pmd_table, +- pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_START)), ++ (void*)pgd_page_vaddr(*pgd_offset_k(KASAN_SHADOW_START)), + sizeof(tmp_pmd_table)); + set_pgd(&tmp_pgd_table[pgd_index(KASAN_SHADOW_START)], + __pgd(__pa(tmp_pmd_table) | PMD_TYPE_TABLE | L_PGD_SWAPPER)); +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index a4e0060051070..5e2be37a198e2 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -212,12 +212,14 @@ early_param("ecc", early_ecc); + static int __init early_cachepolicy(char *p) + { + pr_warn("cachepolicy kernel parameter not supported without cp15\n"); ++ return 0; + } + early_param("cachepolicy", early_cachepolicy); + + static int __init noalign_setup(char *__unused) + { + pr_warn("noalign kernel parameter not supported without cp15\n"); ++ return 1; + } + __setup("noalign", noalign_setup); + +@@ -390,9 +392,9 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) + BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) < FIXADDR_START); + BUG_ON(idx >= __end_of_fixed_addresses); + +- /* we only support device mappings until pgprot_kernel has been set */ ++ /* We support only device mappings before pgprot_kernel is set. */ + if (WARN_ON(pgprot_val(prot) != pgprot_val(FIXMAP_PAGE_IO) && +- pgprot_val(pgprot_kernel) == 0)) ++ pgprot_val(prot) && pgprot_val(pgprot_kernel) == 0)) + return; + + if (pgprot_val(prot)) +diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c +index 114c05ab4dd91..06dbfb968182d 100644 +--- a/arch/arm/mm/proc-v7-bugs.c ++++ b/arch/arm/mm/proc-v7-bugs.c +@@ -6,8 +6,35 @@ + #include <asm/cp15.h> + #include <asm/cputype.h> + #include <asm/proc-fns.h> ++#include <asm/spectre.h> + #include <asm/system_misc.h> + ++#ifdef CONFIG_ARM_PSCI ++static int __maybe_unused spectre_v2_get_cpu_fw_mitigation_state(void) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_1, &res); ++ ++ switch ((int)res.a0) { ++ case SMCCC_RET_SUCCESS: ++ return SPECTRE_MITIGATED; ++ ++ case SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED: ++ return SPECTRE_UNAFFECTED; ++ ++ default: ++ return SPECTRE_VULNERABLE; ++ } ++} ++#else ++static int __maybe_unused spectre_v2_get_cpu_fw_mitigation_state(void) ++{ ++ return SPECTRE_VULNERABLE; ++} ++#endif ++ + #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR + DEFINE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn); + +@@ -36,13 +63,61 @@ static void __maybe_unused call_hvc_arch_workaround_1(void) + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); + } + +-static void cpu_v7_spectre_init(void) ++static unsigned int spectre_v2_install_workaround(unsigned int method) + { + const char *spectre_v2_method = NULL; + int cpu = smp_processor_id(); + + if (per_cpu(harden_branch_predictor_fn, cpu)) +- return; ++ return SPECTRE_MITIGATED; ++ ++ switch (method) { ++ case SPECTRE_V2_METHOD_BPIALL: ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ harden_branch_predictor_bpiall; ++ spectre_v2_method = "BPIALL"; ++ break; ++ ++ case SPECTRE_V2_METHOD_ICIALLU: ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ harden_branch_predictor_iciallu; ++ spectre_v2_method = "ICIALLU"; ++ break; ++ ++ case SPECTRE_V2_METHOD_HVC: ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ call_hvc_arch_workaround_1; ++ cpu_do_switch_mm = cpu_v7_hvc_switch_mm; ++ spectre_v2_method = "hypervisor"; ++ break; ++ ++ case SPECTRE_V2_METHOD_SMC: ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ call_smc_arch_workaround_1; ++ cpu_do_switch_mm = cpu_v7_smc_switch_mm; ++ spectre_v2_method = "firmware"; ++ break; ++ } ++ ++ if (spectre_v2_method) ++ pr_info("CPU%u: Spectre v2: using %s workaround\n", ++ smp_processor_id(), spectre_v2_method); ++ ++ return SPECTRE_MITIGATED; ++} ++#else ++static unsigned int spectre_v2_install_workaround(unsigned int method) ++{ ++ pr_info("CPU%u: Spectre V2: workarounds disabled by configuration\n", ++ smp_processor_id()); ++ ++ return SPECTRE_VULNERABLE; ++} ++#endif ++ ++static void cpu_v7_spectre_v2_init(void) ++{ ++ unsigned int state, method = 0; + + switch (read_cpuid_part()) { + case ARM_CPU_PART_CORTEX_A8: +@@ -51,69 +126,133 @@ static void cpu_v7_spectre_init(void) + case ARM_CPU_PART_CORTEX_A17: + case ARM_CPU_PART_CORTEX_A73: + case ARM_CPU_PART_CORTEX_A75: +- per_cpu(harden_branch_predictor_fn, cpu) = +- harden_branch_predictor_bpiall; +- spectre_v2_method = "BPIALL"; ++ state = SPECTRE_MITIGATED; ++ method = SPECTRE_V2_METHOD_BPIALL; + break; + + case ARM_CPU_PART_CORTEX_A15: + case ARM_CPU_PART_BRAHMA_B15: +- per_cpu(harden_branch_predictor_fn, cpu) = +- harden_branch_predictor_iciallu; +- spectre_v2_method = "ICIALLU"; ++ state = SPECTRE_MITIGATED; ++ method = SPECTRE_V2_METHOD_ICIALLU; + break; + +-#ifdef CONFIG_ARM_PSCI + case ARM_CPU_PART_BRAHMA_B53: + /* Requires no workaround */ ++ state = SPECTRE_UNAFFECTED; + break; ++ + default: + /* Other ARM CPUs require no workaround */ +- if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) ++ if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) { ++ state = SPECTRE_UNAFFECTED; + break; ++ } ++ + fallthrough; +- /* Cortex A57/A72 require firmware workaround */ +- case ARM_CPU_PART_CORTEX_A57: +- case ARM_CPU_PART_CORTEX_A72: { +- struct arm_smccc_res res; + +- arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, +- ARM_SMCCC_ARCH_WORKAROUND_1, &res); +- if ((int)res.a0 != 0) +- return; ++ /* Cortex A57/A72 require firmware workaround */ ++ case ARM_CPU_PART_CORTEX_A57: ++ case ARM_CPU_PART_CORTEX_A72: ++ state = spectre_v2_get_cpu_fw_mitigation_state(); ++ if (state != SPECTRE_MITIGATED) ++ break; + + switch (arm_smccc_1_1_get_conduit()) { + case SMCCC_CONDUIT_HVC: +- per_cpu(harden_branch_predictor_fn, cpu) = +- call_hvc_arch_workaround_1; +- cpu_do_switch_mm = cpu_v7_hvc_switch_mm; +- spectre_v2_method = "hypervisor"; ++ method = SPECTRE_V2_METHOD_HVC; + break; + + case SMCCC_CONDUIT_SMC: +- per_cpu(harden_branch_predictor_fn, cpu) = +- call_smc_arch_workaround_1; +- cpu_do_switch_mm = cpu_v7_smc_switch_mm; +- spectre_v2_method = "firmware"; ++ method = SPECTRE_V2_METHOD_SMC; + break; + + default: ++ state = SPECTRE_VULNERABLE; + break; + } + } +-#endif ++ ++ if (state == SPECTRE_MITIGATED) ++ state = spectre_v2_install_workaround(method); ++ ++ spectre_v2_update_state(state, method); ++} ++ ++#ifdef CONFIG_HARDEN_BRANCH_HISTORY ++static int spectre_bhb_method; ++ ++static const char *spectre_bhb_method_name(int method) ++{ ++ switch (method) { ++ case SPECTRE_V2_METHOD_LOOP8: ++ return "loop"; ++ ++ case SPECTRE_V2_METHOD_BPIALL: ++ return "BPIALL"; ++ ++ default: ++ return "unknown"; + } ++} + +- if (spectre_v2_method) +- pr_info("CPU%u: Spectre v2: using %s workaround\n", +- smp_processor_id(), spectre_v2_method); ++static int spectre_bhb_install_workaround(int method) ++{ ++ if (spectre_bhb_method != method) { ++ if (spectre_bhb_method) { ++ pr_err("CPU%u: Spectre BHB: method disagreement, system vulnerable\n", ++ smp_processor_id()); ++ ++ return SPECTRE_VULNERABLE; ++ } ++ ++ if (spectre_bhb_update_vectors(method) == SPECTRE_VULNERABLE) ++ return SPECTRE_VULNERABLE; ++ ++ spectre_bhb_method = method; ++ } ++ ++ pr_info("CPU%u: Spectre BHB: using %s workaround\n", ++ smp_processor_id(), spectre_bhb_method_name(method)); ++ ++ return SPECTRE_MITIGATED; + } + #else +-static void cpu_v7_spectre_init(void) ++static int spectre_bhb_install_workaround(int method) + { ++ return SPECTRE_VULNERABLE; + } + #endif + ++static void cpu_v7_spectre_bhb_init(void) ++{ ++ unsigned int state, method = 0; ++ ++ switch (read_cpuid_part()) { ++ case ARM_CPU_PART_CORTEX_A15: ++ case ARM_CPU_PART_BRAHMA_B15: ++ case ARM_CPU_PART_CORTEX_A57: ++ case ARM_CPU_PART_CORTEX_A72: ++ state = SPECTRE_MITIGATED; ++ method = SPECTRE_V2_METHOD_LOOP8; ++ break; ++ ++ case ARM_CPU_PART_CORTEX_A73: ++ case ARM_CPU_PART_CORTEX_A75: ++ state = SPECTRE_MITIGATED; ++ method = SPECTRE_V2_METHOD_BPIALL; ++ break; ++ ++ default: ++ state = SPECTRE_UNAFFECTED; ++ break; ++ } ++ ++ if (state == SPECTRE_MITIGATED) ++ state = spectre_bhb_install_workaround(method); ++ ++ spectre_v2_update_state(state, method); ++} ++ + static __maybe_unused bool cpu_v7_check_auxcr_set(bool *warned, + u32 mask, const char *msg) + { +@@ -142,16 +281,17 @@ static bool check_spectre_auxcr(bool *warned, u32 bit) + void cpu_v7_ca8_ibe(void) + { + if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6))) +- cpu_v7_spectre_init(); ++ cpu_v7_spectre_v2_init(); + } + + void cpu_v7_ca15_ibe(void) + { + if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0))) +- cpu_v7_spectre_init(); ++ cpu_v7_spectre_v2_init(); + } + + void cpu_v7_bugs_init(void) + { +- cpu_v7_spectre_init(); ++ cpu_v7_spectre_v2_init(); ++ cpu_v7_spectre_bhb_init(); + } +diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile +index 14db56f49f0a3..6159010dac4a6 100644 +--- a/arch/arm/probes/kprobes/Makefile ++++ b/arch/arm/probes/kprobes/Makefile +@@ -1,4 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 ++KASAN_SANITIZE_actions-common.o := n ++KASAN_SANITIZE_actions-arm.o := n ++KASAN_SANITIZE_actions-thumb.o := n + obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o + obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o + test-kprobes-objs := test-core.o +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index fee914c716aa2..b68d5cbbeca6a 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -1184,6 +1184,15 @@ config UNMAP_KERNEL_AT_EL0 + + If unsure, say Y. + ++config MITIGATE_SPECTRE_BRANCH_HISTORY ++ bool "Mitigate Spectre style attacks against branch history" if EXPERT ++ default y ++ help ++ Speculation attacks against some high-performance processors can ++ make use of branch history to influence future speculation. ++ When taking an exception from user-space, a sequence of branches ++ or a firmware call overwrites the branch history. ++ + config RODATA_FULL_DEFAULT_ENABLED + bool "Apply r/o permissions of VM areas also to their linear aliases" + default y +@@ -1264,7 +1273,8 @@ config KUSER_HELPERS + + config COMPAT_VDSO + bool "Enable vDSO for 32-bit applications" +- depends on !CPU_BIG_ENDIAN && "$(CROSS_COMPILE_COMPAT)" != "" ++ depends on !CPU_BIG_ENDIAN ++ depends on (CC_IS_CLANG && LD_IS_LLD) || "$(CROSS_COMPILE_COMPAT)" != "" + select GENERIC_COMPAT_VDSO + default y + help +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi +index cc321c04f1219..f6d7d7f7fdabe 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi +@@ -343,19 +343,19 @@ + }; + + thermal-zones { +- cpu-thermal-zone { ++ cpu-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 0>; + }; + +- ddr-thermal-zone { ++ ddr-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 2>; + }; + +- gpu-thermal-zone { ++ gpu-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 1>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi +index 578c37490d901..e39db51eb4489 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-cpu-opp.dtsi +@@ -4,7 +4,7 @@ + */ + + / { +- cpu0_opp_table: opp_table0 { ++ cpu0_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi +index b2657201957eb..1afad8b437d72 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi +@@ -2,7 +2,7 @@ + // Copyright (C) 2020 Chen-Yu Tsai <wens@csie.org> + + / { +- cpu_opp_table: cpu-opp-table { ++ cpu_opp_table: opp-table-cpu { + compatible = "operating-points-v2"; + opp-shared; + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts +index d13980ed7a79a..7ec5ac850a0dc 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts +@@ -69,7 +69,7 @@ + pinctrl-0 = <&emac_rgmii_pins>; + phy-supply = <®_gmac_3v3>; + phy-handle = <&ext_rgmii_phy>; +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + status = "okay"; + }; + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +index 578a63dedf466..9988e87ea7b3d 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +@@ -217,7 +217,7 @@ + }; + }; + +- gpu_thermal { ++ gpu-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 1>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi +index 8c6e8536b69fa..0baf0f8e4d272 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi +@@ -3,7 +3,7 @@ + // Copyright (C) 2020 Clément Péron <peron.clem@gmail.com> + + / { +- cpu_opp_table: cpu-opp-table { ++ cpu_opp_table: opp-table-cpu { + compatible = "allwinner,sun50i-h6-operating-points"; + nvmem-cells = <&cpu_speed_grade>; + opp-shared; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +index 00c6f53290d43..a3a1ea0f21340 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +@@ -58,7 +58,7 @@ + secure-monitor = <&sm>; + }; + +- gpu_opp_table: gpu-opp-table { ++ gpu_opp_table: opp-table-gpu { + compatible = "operating-points-v2"; + + opp-124999998 { +@@ -107,6 +107,12 @@ + no-map; + }; + ++ /* 32 MiB reserved for ARM Trusted Firmware (BL32) */ ++ secmon_reserved_bl32: secmon@5300000 { ++ reg = <0x0 0x05300000 0x0 0x2000000>; ++ no-map; ++ }; ++ + linux,cma { + compatible = "shared-dma-pool"; + reusable; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts +index 81269ccc24968..4fb31c2ba31c4 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts +@@ -139,7 +139,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&dc_in>; ++ pwm-supply = <&dc_in>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +@@ -157,14 +157,6 @@ + regulator-always-on; + }; + +- reserved-memory { +- /* TEE Reserved Memory */ +- bl32_reserved: bl32@5000000 { +- reg = <0x0 0x05300000 0x0 0x2000000>; +- no-map; +- }; +- }; +- + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts +index a26bfe72550fe..4b5d11e56364d 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts +@@ -139,7 +139,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&main_12v>; ++ pwm-supply = <&main_12v>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts +index 579f3d02d613e..b4e86196e3468 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts +@@ -139,7 +139,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&dc_in>; ++ pwm-supply = <&dc_in>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi +index f42cf4b8af2d4..16dd409051b40 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi +@@ -18,7 +18,7 @@ + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + +- vin-supply = <&dc_in>; ++ pwm-supply = <&dc_in>; + + pwms = <&pwm_ab 0 1250 0>; + pwm-dutycycle-range = <100 0>; +@@ -37,7 +37,7 @@ + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + +- vin-supply = <&vsys_3v3>; ++ pwm-supply = <&vsys_3v3>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi +index 344573e157a7b..d33e54b5e1969 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi +@@ -17,7 +17,7 @@ + rtc1 = &vrtc; + }; + +- dioo2133: audio-amplifier-0 { ++ dio2133: audio-amplifier-0 { + compatible = "simple-audio-amplifier"; + enable-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; + VCC-supply = <&vcc_5v>; +@@ -130,7 +130,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&main_12v>; ++ pwm-supply = <&main_12v>; + + pwms = <&pwm_ab 0 1250 0>; + pwm-dutycycle-range = <100 0>; +@@ -149,7 +149,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&main_12v>; ++ pwm-supply = <&main_12v>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +@@ -217,7 +217,7 @@ + audio-widgets = "Line", "Lineout"; + audio-aux-devs = <&tdmout_b>, <&tdmout_c>, <&tdmin_a>, + <&tdmin_b>, <&tdmin_c>, <&tdmin_lb>, +- <&dioo2133>; ++ <&dio2133>; + audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", + "TDMOUT_B IN 1", "FRDDR_B OUT 1", + "TDMOUT_B IN 2", "FRDDR_C OUT 1", +@@ -607,7 +607,7 @@ + pinctrl-0 = <&nor_pins>; + pinctrl-names = "default"; + +- mx25u64: spi-flash@0 { ++ mx25u64: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mxicy,mx25u6435f", "jedec,spi-nor"; +diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi +index feb0885047400..b40d2c1002c92 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-g12b-w400.dtsi +@@ -96,7 +96,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&main_12v>; ++ pwm-supply = <&main_12v>; + + pwms = <&pwm_ab 0 1250 0>; + pwm-dutycycle-range = <100 0>; +@@ -115,7 +115,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&main_12v>; ++ pwm-supply = <&main_12v>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +index 6b457b2c30a4b..aa14ea017a613 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +@@ -49,6 +49,12 @@ + no-map; + }; + ++ /* 32 MiB reserved for ARM Trusted Firmware (BL32) */ ++ secmon_reserved_bl32: secmon@5300000 { ++ reg = <0x0 0x05300000 0x0 0x2000000>; ++ no-map; ++ }; ++ + linux,cma { + compatible = "shared-dma-pool"; + reusable; +diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi +index a350fee1264d7..a4d34398da358 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi +@@ -6,6 +6,7 @@ + */ + + #include "meson-gxbb.dtsi" ++#include <dt-bindings/gpio/gpio.h> + + / { + aliases { +@@ -64,6 +65,7 @@ + regulator-name = "VDDIO_AO18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; ++ regulator-always-on; + }; + + vcc_3v3: regulator-vcc_3v3 { +@@ -161,6 +163,7 @@ + status = "okay"; + pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>; + pinctrl-names = "default"; ++ hdmi-supply = <&vddio_ao18>; + }; + + &hdmi_tx_tmds_port { +diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts +index effaa138b5f98..5751c48620edf 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-bananapi-m5.dts +@@ -123,7 +123,7 @@ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + +- enable-gpio = <&gpio GPIOE_2 GPIO_ACTIVE_HIGH>; ++ enable-gpio = <&gpio_ao GPIOE_2 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + +@@ -173,7 +173,7 @@ + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + +- vin-supply = <&dc_in>; ++ pwm-supply = <&dc_in>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts +index f2c0981435944..9c0b544e22098 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dts +@@ -24,7 +24,7 @@ + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + +- vin-supply = <&vsys_3v3>; ++ pwm-supply = <&vsys_3v3>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi +index fd0ad85c165ba..76ad052fbf0c9 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi ++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-odroid.dtsi +@@ -48,7 +48,7 @@ + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_5v>; + +- enable-gpio = <&gpio GPIOE_2 GPIO_ACTIVE_HIGH>; ++ enable-gpio = <&gpio_ao GPIOE_2 GPIO_OPEN_DRAIN>; + enable-active-high; + regulator-always-on; + +@@ -116,7 +116,7 @@ + regulator-min-microvolt = <721000>; + regulator-max-microvolt = <1022000>; + +- vin-supply = <&main_12v>; ++ pwm-supply = <&main_12v>; + + pwms = <&pwm_AO_cd 1 1250 0>; + pwm-dutycycle-range = <100 0>; +@@ -263,6 +263,10 @@ + reg = <0>; + max-speed = <1000>; + ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ + interrupt-parent = <&gpio_intc>; + /* MAC_INTR on GPIOZ_14 */ + interrupts = <26 IRQ_TYPE_LEVEL_LOW>; +diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts +index 2194a778973f1..a5d79f2f7c196 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts +@@ -185,7 +185,7 @@ + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <1050000>; + +- vin-supply = <&dc_in>; ++ pwm-supply = <&dc_in>; + + pwms = <&pwm_AO_cd 1 1500 0>; + pwm-dutycycle-range = <100 0>; +@@ -203,14 +203,6 @@ + regulator-always-on; + }; + +- reserved-memory { +- /* TEE Reserved Memory */ +- bl32_reserved: bl32@5000000 { +- reg = <0x0 0x05300000 0x0 0x2000000>; +- no-map; +- }; +- }; +- + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; +diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi +index 6288e104a0893..a2635b14da309 100644 +--- a/arch/arm64/boot/dts/arm/juno-base.dtsi ++++ b/arch/arm64/boot/dts/arm/juno-base.dtsi +@@ -543,8 +543,7 @@ + <0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>, + <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>; + /* Standard AXI Translation entries as programmed by EDK2 */ +- dma-ranges = <0x02000000 0x0 0x2c1c0000 0x0 0x2c1c0000 0x0 0x00040000>, +- <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>, ++ dma-ranges = <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>, + <0x43000000 0x8 0x00000000 0x8 0x00000000 0x2 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; +diff --git a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi +index a5a64d17d9ea6..5118816b1ed76 100644 +--- a/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm4908/bcm4908.dtsi +@@ -292,7 +292,7 @@ + reg = <0x640 0x18>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&periph_clk>; +- clock-names = "periph"; ++ clock-names = "refclk"; + status = "okay"; + }; + +@@ -326,12 +326,12 @@ + #reset-cells = <1>; + }; + }; ++ }; + +- reboot { +- compatible = "syscon-reboot"; +- regmap = <&timer>; +- offset = <0x34>; +- mask = <1>; +- }; ++ reboot { ++ compatible = "syscon-reboot"; ++ regmap = <&timer>; ++ offset = <0x34>; ++ mask = <1>; + }; + }; +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts +index 79f155dedb2d0..e662677a6e28f 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts +@@ -15,6 +15,7 @@ + compatible = "fsl,ls1012a-rdb", "fsl,ls1012a"; + + aliases { ++ serial0 = &duart0; + mmc0 = &esdhc0; + mmc1 = &esdhc1; + }; +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts +index bfd14b64567e4..2f92e62ecafe9 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts +@@ -272,11 +272,6 @@ + vcc-supply = <&sb_3v3>; + }; + +- rtc@51 { +- compatible = "nxp,pcf2129"; +- reg = <0x51>; +- }; +- + eeprom@56 { + compatible = "atmel,24c512"; + reg = <0x56>; +@@ -318,6 +313,15 @@ + + }; + ++&i2c1 { ++ status = "okay"; ++ ++ rtc@51 { ++ compatible = "nxp,pcf2129"; ++ reg = <0x51>; ++ }; ++}; ++ + &enetc_port1 { + phy-handle = <&qds_phy1>; + phy-connection-type = "rgmii-id"; +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts +index 3063851c2fb91..d3f03dcbb8c38 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a-ten64.dts +@@ -38,7 +38,6 @@ + powerdn { + label = "External Power Down"; + gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; +- interrupts = <&gpio1 17 IRQ_TYPE_EDGE_FALLING>; + linux,code = <KEY_POWER>; + }; + +@@ -46,7 +45,6 @@ + admin { + label = "ADMIN button"; + gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>; +- interrupts = <&gpio3 8 IRQ_TYPE_EDGE_RISING>; + linux,code = <KEY_WPS_BUTTON>; + }; + }; +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +index f85e437f80b73..6050723172436 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi +@@ -847,7 +847,7 @@ + }; + + cluster1_core0_watchdog: wdt@c000000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc000000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -857,7 +857,7 @@ + }; + + cluster1_core1_watchdog: wdt@c010000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc010000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -867,7 +867,7 @@ + }; + + cluster1_core2_watchdog: wdt@c020000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc020000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -877,7 +877,7 @@ + }; + + cluster1_core3_watchdog: wdt@c030000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc030000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -887,7 +887,7 @@ + }; + + cluster2_core0_watchdog: wdt@c100000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc100000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -897,7 +897,7 @@ + }; + + cluster2_core1_watchdog: wdt@c110000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc110000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -907,7 +907,7 @@ + }; + + cluster2_core2_watchdog: wdt@c120000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc120000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +@@ -917,7 +917,7 @@ + }; + + cluster2_core3_watchdog: wdt@c130000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc130000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>, +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi +index 801ba9612d361..1282b61da8a55 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi +@@ -387,7 +387,7 @@ + }; + + cluster1_core0_watchdog: wdt@c000000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc000000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -397,7 +397,7 @@ + }; + + cluster1_core1_watchdog: wdt@c010000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc010000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -407,7 +407,7 @@ + }; + + cluster2_core0_watchdog: wdt@c100000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc100000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -417,7 +417,7 @@ + }; + + cluster2_core1_watchdog: wdt@c110000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc110000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -427,7 +427,7 @@ + }; + + cluster3_core0_watchdog: wdt@c200000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc200000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -437,7 +437,7 @@ + }; + + cluster3_core1_watchdog: wdt@c210000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc210000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -447,7 +447,7 @@ + }; + + cluster4_core0_watchdog: wdt@c300000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc300000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +@@ -457,7 +457,7 @@ + }; + + cluster4_core1_watchdog: wdt@c310000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xc310000 0x0 0x1000>; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(4)>, +diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +index c4b1a59ba424b..51c4f61007cdb 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +@@ -719,7 +719,7 @@ + clock-names = "i2c"; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>; +- scl-gpio = <&gpio2 15 GPIO_ACTIVE_HIGH>; ++ scl-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + +@@ -768,7 +768,7 @@ + clock-names = "i2c"; + clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL + QORIQ_CLK_PLL_DIV(16)>; +- scl-gpio = <&gpio2 16 GPIO_ACTIVE_HIGH>; ++ scl-gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + +diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts +index e99e7644ff392..49d7470812eef 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts +@@ -123,8 +123,8 @@ + + ethphy: ethernet-phy@0 { + reg = <0>; +- reset-assert-us = <100>; +- reset-deassert-us = <100>; ++ reset-assert-us = <1>; ++ reset-deassert-us = <15000>; + reset-gpios = <&gpio4 27 GPIO_ACTIVE_LOW>; + }; + }; +diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi +index 4066b16126552..fd38092bb247e 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi +@@ -524,11 +524,9 @@ + <&clk IMX8MQ_VIDEO_PLL1>, + <&clk IMX8MQ_VIDEO_PLL1_OUT>; + assigned-clock-rates = <0>, <0>, <0>, <594000000>; +- interconnects = <&noc IMX8MQ_ICM_LCDIF &noc IMX8MQ_ICS_DRAM>; +- interconnect-names = "dram"; + status = "disabled"; + +- port@0 { ++ port { + lcdif_mipi_dsi: endpoint { + remote-endpoint = <&mipi_dsi_lcdif_in>; + }; +@@ -1125,8 +1123,8 @@ + #address-cells = <1>; + #size-cells = <0>; + +- port@0 { +- reg = <0>; ++ port@1 { ++ reg = <1>; + + csi1_mipi_ep: endpoint { + remote-endpoint = <&csi1_ep>; +@@ -1177,8 +1175,8 @@ + #address-cells = <1>; + #size-cells = <0>; + +- port@0 { +- reg = <0>; ++ port@1 { ++ reg = <1>; + + csi2_mipi_ep: endpoint { + remote-endpoint = <&csi2_ep>; +diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +index 2d5c1a348716a..6eabec2602e23 100644 +--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi ++++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +@@ -1087,7 +1087,7 @@ + }; + + watchdog0: watchdog@e8a06000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xe8a06000 0x0 0x1000>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&crg_ctrl HI3660_OSC32K>, +@@ -1096,7 +1096,7 @@ + }; + + watchdog1: watchdog@e8a07000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xe8a07000 0x0 0x1000>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&crg_ctrl HI3660_OSC32K>, +diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +index dde9371dc5451..e4860b8a638ec 100644 +--- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi ++++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi +@@ -840,7 +840,7 @@ + }; + + watchdog0: watchdog@f8005000 { +- compatible = "arm,sp805-wdt", "arm,primecell"; ++ compatible = "arm,sp805", "arm,primecell"; + reg = <0x0 0xf8005000 0x0 0x1000>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&ao_ctrl HI6220_WDT0_PCLK>, +diff --git a/arch/arm64/boot/dts/marvell/cn9130.dtsi b/arch/arm64/boot/dts/marvell/cn9130.dtsi +index a2b7e5ec979d3..327b04134134f 100644 +--- a/arch/arm64/boot/dts/marvell/cn9130.dtsi ++++ b/arch/arm64/boot/dts/marvell/cn9130.dtsi +@@ -11,6 +11,13 @@ + model = "Marvell Armada CN9130 SoC"; + compatible = "marvell,cn9130", "marvell,armada-ap807-quad", + "marvell,armada-ap807"; ++ ++ aliases { ++ gpio1 = &cp0_gpio1; ++ gpio2 = &cp0_gpio2; ++ spi1 = &cp0_spi0; ++ spi2 = &cp0_spi1; ++ }; + }; + + /* +@@ -35,3 +42,11 @@ + #undef CP11X_PCIE0_BASE + #undef CP11X_PCIE1_BASE + #undef CP11X_PCIE2_BASE ++ ++&cp0_gpio1 { ++ status = "okay"; ++}; ++ ++&cp0_gpio2 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi +index e94f8add1a400..062e87e893316 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi +@@ -1079,7 +1079,7 @@ + + ccplex@e000000 { + compatible = "nvidia,tegra186-ccplex-cluster"; +- reg = <0x0 0x0e000000 0x0 0x3fffff>; ++ reg = <0x0 0x0e000000 0x0 0x400000>; + + nvidia,bpmp = <&bpmp>; + }; +diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi +index c8250a3f7891f..510d2974470cd 100644 +--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi ++++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi +@@ -818,9 +818,8 @@ + <&bpmp TEGRA194_CLK_HDA2CODEC_2X>; + clock-names = "hda", "hda2hdmi", "hda2codec_2x"; + resets = <&bpmp TEGRA194_RESET_HDA>, +- <&bpmp TEGRA194_RESET_HDA2HDMICODEC>, +- <&bpmp TEGRA194_RESET_HDA2CODEC_2X>; +- reset-names = "hda", "hda2hdmi", "hda2codec_2x"; ++ <&bpmp TEGRA194_RESET_HDA2HDMICODEC>; ++ reset-names = "hda", "hda2hdmi"; + power-domains = <&bpmp TEGRA194_POWER_DOMAIN_DISP>; + interconnects = <&mc TEGRA194_MEMORY_CLIENT_HDAR &emc>, + <&mc TEGRA194_MEMORY_CLIENT_HDAW &emc>; +diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +index d2fe58e0eb7aa..ce4c2b4a5fc07 100644 +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -200,7 +200,7 @@ + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <1>; +- qcom,controlled-remotely = <1>; ++ qcom,controlled-remotely; + qcom,config-pipe-trust-reg = <0>; + }; + +@@ -221,7 +221,7 @@ + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; +- gpio-ranges = <&tlmm 0 80>; ++ gpio-ranges = <&tlmm 0 0 80>; + interrupt-controller; + #interrupt-cells = <2>; + +diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +index db333001df4d6..97f99663c132e 100644 +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -220,7 +220,7 @@ + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <1>; +- qcom,controlled-remotely = <1>; ++ qcom,controlled-remotely; + status = "disabled"; + }; + +diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi +index 3f85e34a8ce6f..8b27242724641 100644 +--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi +@@ -19,8 +19,8 @@ + #size-cells = <2>; + + aliases { +- sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ +- sdhc2 = &sdhc_2; /* SDC2 SD card slot */ ++ mmc0 = &sdhc_1; /* SDC1 eMMC slot */ ++ mmc1 = &sdhc_2; /* SDC2 SD card slot */ + }; + + chosen { }; +@@ -445,7 +445,7 @@ + }; + }; + +- rpm_msg_ram: memory@60000 { ++ rpm_msg_ram: sram@60000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00060000 0x8000>; + }; +@@ -1384,11 +1384,17 @@ + lpass: audio-controller@7708000 { + status = "disabled"; + compatible = "qcom,lpass-cpu-apq8016"; ++ ++ /* ++ * Note: Unlike the name would suggest, the SEC_I2S_CLK ++ * is actually only used by Tertiary MI2S while ++ * Primary/Secondary MI2S both use the PRI_I2S_CLK. ++ */ + clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>, + <&gcc GCC_ULTAUDIO_PCNOC_MPORT_CLK>, + <&gcc GCC_ULTAUDIO_PCNOC_SWAY_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, +- <&gcc GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK>, ++ <&gcc GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK>, + <&gcc GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK>; + +diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi +index 986fe60dec5fb..5a9a5ed0565f6 100644 +--- a/arch/arm64/boot/dts/qcom/msm8994.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi +@@ -715,7 +715,7 @@ + reg = <0xfc400000 0x2000>; + }; + +- rpm_msg_ram: memory@fc428000 { ++ rpm_msg_ram: sram@fc428000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0xfc428000 0x4000>; + }; +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index 52df22ab3f6ae..6077c36019514 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -638,7 +638,7 @@ + }; + }; + +- rpm_msg_ram: memory@68000 { ++ rpm_msg_ram: sram@68000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00068000 0x6000>; + }; +@@ -965,9 +965,6 @@ + nvmem-cells = <&speedbin_efuse>; + nvmem-cell-names = "speed_bin"; + +- qcom,gpu-quirk-two-pass-use-wfi; +- qcom,gpu-quirk-fault-detect-mask; +- + operating-points-v2 = <&gpu_opp_table>; + + status = "disabled"; +diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi +index 34039b5c80175..228339f81c327 100644 +--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi +@@ -308,38 +308,42 @@ + LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + idle-state-name = "little-retention"; ++ /* CPU Retention (C2D), L2 Active */ + arm,psci-suspend-param = <0x00000002>; + entry-latency-us = <81>; + exit-latency-us = <86>; +- min-residency-us = <200>; ++ min-residency-us = <504>; + }; + + LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 { + compatible = "arm,idle-state"; + idle-state-name = "little-power-collapse"; ++ /* CPU + L2 Power Collapse (C3, D4) */ + arm,psci-suspend-param = <0x40000003>; +- entry-latency-us = <273>; +- exit-latency-us = <612>; +- min-residency-us = <1000>; ++ entry-latency-us = <814>; ++ exit-latency-us = <4562>; ++ min-residency-us = <9183>; + local-timer-stop; + }; + + BIG_CPU_SLEEP_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + idle-state-name = "big-retention"; ++ /* CPU Retention (C2D), L2 Active */ + arm,psci-suspend-param = <0x00000002>; + entry-latency-us = <79>; + exit-latency-us = <82>; +- min-residency-us = <200>; ++ min-residency-us = <1302>; + }; + + BIG_CPU_SLEEP_1: cpu-sleep-1-1 { + compatible = "arm,idle-state"; + idle-state-name = "big-power-collapse"; ++ /* CPU + L2 Power Collapse (C3, D4) */ + arm,psci-suspend-param = <0x40000003>; +- entry-latency-us = <336>; +- exit-latency-us = <525>; +- min-residency-us = <1000>; ++ entry-latency-us = <724>; ++ exit-latency-us = <2027>; ++ min-residency-us = <9419>; + local-timer-stop; + }; + }; +@@ -857,7 +861,7 @@ + reg = <0x00100000 0xb0000>; + }; + +- rpm_msg_ram: memory@778000 { ++ rpm_msg_ram: sram@778000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00778000 0x7000>; + }; +diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi +index f931cb0de231f..42180f1b5dbbb 100644 +--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi ++++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi +@@ -86,7 +86,6 @@ + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000>; +- reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + }; + +diff --git a/arch/arm64/boot/dts/qcom/pmi8994.dtsi b/arch/arm64/boot/dts/qcom/pmi8994.dtsi +index b4ac900ab115f..a06ea9adae810 100644 +--- a/arch/arm64/boot/dts/qcom/pmi8994.dtsi ++++ b/arch/arm64/boot/dts/qcom/pmi8994.dtsi +@@ -42,7 +42,7 @@ + /* Yes, all four strings *have to* be defined or things won't work. */ + qcom,enabled-strings = <0 1 2 3>; + qcom,cabc; +- qcom,eternal-pfet; ++ qcom,external-pfet; + status = "disabled"; + }; + }; +diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi +index 339790ba585de..ca5be16479809 100644 +--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi ++++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi +@@ -318,7 +318,7 @@ + status = "disabled"; + }; + +- rpm_msg_ram: memory@60000 { ++ rpm_msg_ram: sram@60000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00060000 0x6000>; + }; +diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi +index a758e4d226122..81098aa9687ba 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi +@@ -33,7 +33,7 @@ ap_h1_spi: &spi0 {}; + polling-delay = <0>; + + thermal-sensors = <&pm6150_adc_tm 1>; +- sustainable-power = <814>; ++ sustainable-power = <965>; + + trips { + skin_temp_alert0: trip-point0 { +diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi +index a246dbd74cc11..b7b5264888b7c 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi +@@ -44,7 +44,7 @@ ap_h1_spi: &spi0 {}; + }; + + &cpu6_thermal { +- sustainable-power = <948>; ++ sustainable-power = <1124>; + }; + + &cpu7_alert0 { +@@ -56,7 +56,7 @@ ap_h1_spi: &spi0 {}; + }; + + &cpu7_thermal { +- sustainable-power = <948>; ++ sustainable-power = <1124>; + }; + + &cpu8_alert0 { +@@ -68,7 +68,7 @@ ap_h1_spi: &spi0 {}; + }; + + &cpu8_thermal { +- sustainable-power = <948>; ++ sustainable-power = <1124>; + }; + + &cpu9_alert0 { +@@ -80,7 +80,7 @@ ap_h1_spi: &spi0 {}; + }; + + &cpu9_thermal { +- sustainable-power = <948>; ++ sustainable-power = <1124>; + }; + + &gpio_keys { +diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi +index c8921e2d6480f..495c15deacb7d 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi +@@ -137,8 +137,8 @@ + cpu-idle-states = <&LITTLE_CPU_SLEEP_0 + &LITTLE_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1024>; +- dynamic-power-coefficient = <100>; ++ capacity-dmips-mhz = <415>; ++ dynamic-power-coefficient = <137>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, + <&osm_l3 MASTER_OSM_L3_APPS &osm_l3 SLAVE_OSM_L3>; +@@ -162,8 +162,8 @@ + cpu-idle-states = <&LITTLE_CPU_SLEEP_0 + &LITTLE_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1024>; +- dynamic-power-coefficient = <100>; ++ capacity-dmips-mhz = <415>; ++ dynamic-power-coefficient = <137>; + next-level-cache = <&L2_100>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -184,8 +184,8 @@ + cpu-idle-states = <&LITTLE_CPU_SLEEP_0 + &LITTLE_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1024>; +- dynamic-power-coefficient = <100>; ++ capacity-dmips-mhz = <415>; ++ dynamic-power-coefficient = <137>; + next-level-cache = <&L2_200>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -206,8 +206,8 @@ + cpu-idle-states = <&LITTLE_CPU_SLEEP_0 + &LITTLE_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1024>; +- dynamic-power-coefficient = <100>; ++ capacity-dmips-mhz = <415>; ++ dynamic-power-coefficient = <137>; + next-level-cache = <&L2_300>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -228,8 +228,8 @@ + cpu-idle-states = <&LITTLE_CPU_SLEEP_0 + &LITTLE_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1024>; +- dynamic-power-coefficient = <100>; ++ capacity-dmips-mhz = <415>; ++ dynamic-power-coefficient = <137>; + next-level-cache = <&L2_400>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -250,8 +250,8 @@ + cpu-idle-states = <&LITTLE_CPU_SLEEP_0 + &LITTLE_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1024>; +- dynamic-power-coefficient = <100>; ++ capacity-dmips-mhz = <415>; ++ dynamic-power-coefficient = <137>; + next-level-cache = <&L2_500>; + operating-points-v2 = <&cpu0_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -272,8 +272,8 @@ + cpu-idle-states = <&BIG_CPU_SLEEP_0 + &BIG_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1740>; +- dynamic-power-coefficient = <405>; ++ capacity-dmips-mhz = <1024>; ++ dynamic-power-coefficient = <480>; + next-level-cache = <&L2_600>; + operating-points-v2 = <&cpu6_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -294,8 +294,8 @@ + cpu-idle-states = <&BIG_CPU_SLEEP_0 + &BIG_CPU_SLEEP_1 + &CLUSTER_SLEEP_0>; +- capacity-dmips-mhz = <1740>; +- dynamic-power-coefficient = <405>; ++ capacity-dmips-mhz = <1024>; ++ dynamic-power-coefficient = <480>; + next-level-cache = <&L2_700>; + operating-points-v2 = <&cpu6_opp_table>; + interconnects = <&gem_noc MASTER_APPSS_PROC 3 &mc_virt SLAVE_EBI1 3>, +@@ -3616,7 +3616,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 1>; +- sustainable-power = <768>; ++ sustainable-power = <1052>; + + trips { + cpu0_alert0: trip-point0 { +@@ -3665,7 +3665,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 2>; +- sustainable-power = <768>; ++ sustainable-power = <1052>; + + trips { + cpu1_alert0: trip-point0 { +@@ -3714,7 +3714,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 3>; +- sustainable-power = <768>; ++ sustainable-power = <1052>; + + trips { + cpu2_alert0: trip-point0 { +@@ -3763,7 +3763,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 4>; +- sustainable-power = <768>; ++ sustainable-power = <1052>; + + trips { + cpu3_alert0: trip-point0 { +@@ -3812,7 +3812,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 5>; +- sustainable-power = <768>; ++ sustainable-power = <1052>; + + trips { + cpu4_alert0: trip-point0 { +@@ -3861,7 +3861,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 6>; +- sustainable-power = <768>; ++ sustainable-power = <1052>; + + trips { + cpu5_alert0: trip-point0 { +@@ -3910,7 +3910,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 9>; +- sustainable-power = <1202>; ++ sustainable-power = <1425>; + + trips { + cpu6_alert0: trip-point0 { +@@ -3951,7 +3951,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 10>; +- sustainable-power = <1202>; ++ sustainable-power = <1425>; + + trips { + cpu7_alert0: trip-point0 { +@@ -3992,7 +3992,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 11>; +- sustainable-power = <1202>; ++ sustainable-power = <1425>; + + trips { + cpu8_alert0: trip-point0 { +@@ -4033,7 +4033,7 @@ + polling-delay = <0>; + + thermal-sensors = <&tsens0 12>; +- sustainable-power = <1202>; ++ sustainable-power = <1425>; + + trips { + cpu9_alert0: trip-point0 { +diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi +index fd78f16181ddd..692973c4f4344 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi +@@ -429,7 +429,7 @@ + <&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>, + <0>, <0>, <0>, <0>, <0>, <0>; + clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk", +- "pcie_0_pipe_clk", "pcie_1_pipe-clk", ++ "pcie_0_pipe_clk", "pcie_1_pipe_clk", + "ufs_phy_rx_symbol_0_clk", "ufs_phy_rx_symbol_1_clk", + "ufs_phy_tx_symbol_0_clk", + "usb3_phy_wrapper_gcc_usb30_pipe_clk"; +@@ -1258,15 +1258,11 @@ + dp_phy: dp-phy@88ea200 { + reg = <0 0x088ea200 0 0x200>, + <0 0x088ea400 0 0x200>, +- <0 0x088eac00 0 0x400>, ++ <0 0x088eaa00 0 0x200>, + <0 0x088ea600 0 0x200>, +- <0 0x088ea800 0 0x200>, +- <0 0x088eaa00 0 0x100>; ++ <0 0x088ea800 0 0x200>; + #phy-cells = <0>; + #clock-cells = <1>; +- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_phy_pipe_clk_src"; + }; + }; + +diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi +index 9c7f87e42fccd..a8724fd60645f 100644 +--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi +@@ -541,7 +541,7 @@ + <&sleep_clk>; + }; + +- rpm_msg_ram: memory@778000 { ++ rpm_msg_ram: sram@778000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x00778000 0x7000>; + }; +diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi +index b3b9119261844..519ca9a705b4f 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi +@@ -2316,11 +2316,11 @@ + compatible = "qcom,bam-v1.7.0"; + reg = <0 0x01dc4000 0 0x24000>; + interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>; +- clocks = <&rpmhcc 15>; ++ clocks = <&rpmhcc RPMH_CE_CLK>; + clock-names = "bam_clk"; + #dma-cells = <1>; + qcom,ee = <0>; +- qcom,controlled-remotely = <1>; ++ qcom,controlled-remotely; + iommus = <&apps_smmu 0x704 0x1>, + <&apps_smmu 0x706 0x1>, + <&apps_smmu 0x714 0x1>, +@@ -2331,8 +2331,8 @@ + compatible = "qcom,crypto-v5.4"; + reg = <0 0x01dfa000 0 0x6000>; + clocks = <&gcc GCC_CE1_AHB_CLK>, +- <&gcc GCC_CE1_AHB_CLK>, +- <&rpmhcc 15>; ++ <&gcc GCC_CE1_AXI_CLK>, ++ <&rpmhcc RPMH_CE_CLK>; + clock-names = "iface", "bus", "core"; + dmas = <&cryptobam 6>, <&cryptobam 7>; + dma-names = "rx", "tx"; +diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts +index 2ba23aa582a18..617a634ac9051 100644 +--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts ++++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts +@@ -518,6 +518,10 @@ + dai@1 { + reg = <1>; + }; ++ ++ dai@2 { ++ reg = <2>; ++ }; + }; + + &sound { +@@ -530,6 +534,7 @@ + "SpkrLeft IN", "SPK1 OUT", + "SpkrRight IN", "SPK2 OUT", + "MM_DL1", "MultiMedia1 Playback", ++ "MM_DL3", "MultiMedia3 Playback", + "MultiMedia2 Capture", "MM_UL2"; + + mm1-dai-link { +@@ -546,6 +551,13 @@ + }; + }; + ++ mm3-dai-link { ++ link-name = "MultiMedia3"; ++ cpu { ++ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>; ++ }; ++ }; ++ + slim-dai-link { + link-name = "SLIM Playback"; + cpu { +@@ -575,6 +587,21 @@ + sound-dai = <&wcd9340 1>; + }; + }; ++ ++ slim-wcd-dai-link { ++ link-name = "SLIM WCD Playback"; ++ cpu { ++ sound-dai = <&q6afedai SLIMBUS_1_RX>; ++ }; ++ ++ platform { ++ sound-dai = <&q6routing>; ++ }; ++ ++ codec { ++ sound-dai = <&wcd9340 2>; ++ }; ++ }; + }; + + &tlmm { +diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi +index 2b37ce6a9f9c5..9f476e3d0720b 100644 +--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi +@@ -380,7 +380,7 @@ + status = "disabled"; + }; + +- rpm_msg_ram: memory@45f0000 { ++ rpm_msg_ram: sram@45f0000 { + compatible = "qcom,rpm-msg-ram"; + reg = <0x045f0000 0x7000>; + }; +diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi +index e91cd8a5e5356..296ffb0e9888c 100644 +--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi +@@ -2185,7 +2185,7 @@ + }; + }; + +- camera-thermal-bottom { ++ cam-thermal-bottom { + polling-delay-passive = <250>; + polling-delay = <1000>; + +diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi +index 090dc9c4f57b5..937d17a426b66 100644 +--- a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi ++++ b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi +@@ -50,6 +50,7 @@ + &avb { + pinctrl-0 = <&avb_pins>; + pinctrl-names = "default"; ++ phy-mode = "rgmii-rxid"; + phy-handle = <&phy0>; + rx-internal-delay-ps = <1800>; + tx-internal-delay-ps = <2000>; +diff --git a/arch/arm64/boot/dts/renesas/cat875.dtsi b/arch/arm64/boot/dts/renesas/cat875.dtsi +index 801ea54b027c4..20f8adc635e72 100644 +--- a/arch/arm64/boot/dts/renesas/cat875.dtsi ++++ b/arch/arm64/boot/dts/renesas/cat875.dtsi +@@ -18,6 +18,7 @@ + pinctrl-names = "default"; + renesas,no-ether-link; + phy-handle = <&phy0>; ++ phy-mode = "rgmii-id"; + status = "okay"; + + phy0: ethernet-phy@0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +index 6f4fffacfca21..e70aa5a087402 100644 +--- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +@@ -2784,7 +2784,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -2799,7 +2799,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -2814,7 +2814,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi +index 0f7bdfc90a0dc..6c5694fa66900 100644 +--- a/arch/arm64/boot/dts/renesas/r8a774b1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a774b1.dtsi +@@ -2629,7 +2629,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -2644,7 +2644,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -2659,7 +2659,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi +index 379a1300272ba..62209ab6deb9a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a774e1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a774e1.dtsi +@@ -2904,7 +2904,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -2919,7 +2919,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -2934,7 +2934,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77951.dtsi b/arch/arm64/boot/dts/renesas/r8a77951.dtsi +index 1768a3e6bb8da..193d81be40fc4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77951.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77951.dtsi +@@ -3375,7 +3375,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -3390,7 +3390,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -3405,7 +3405,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi +index 2bd8169735d35..b526e4f0ee6a8 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi +@@ -2972,7 +2972,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -2987,7 +2987,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -3002,7 +3002,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi +index 041473aa5cd09..21fc95397c3c2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi +@@ -2719,7 +2719,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -2734,7 +2734,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -2749,7 +2749,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi +index 08df75606430b..f9679a4dd85fa 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi +@@ -2784,7 +2784,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -2799,7 +2799,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -2814,7 +2814,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +index 6347d15e66b64..21fe602bd25af 100644 +--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi +@@ -1580,7 +1580,7 @@ + }; + + thermal-zones { +- thermal-sensor-1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -1599,7 +1599,7 @@ + }; + }; + +- thermal-sensor-2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi +index 631d520cebee5..26899fb768a73 100644 +--- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi +@@ -1149,7 +1149,7 @@ + }; + + thermal-zones { +- sensor_thermal1: sensor-thermal1 { ++ sensor1_thermal: sensor1-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 0>; +@@ -1163,7 +1163,7 @@ + }; + }; + +- sensor_thermal2: sensor-thermal2 { ++ sensor2_thermal: sensor2-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 1>; +@@ -1177,7 +1177,7 @@ + }; + }; + +- sensor_thermal3: sensor-thermal3 { ++ sensor3_thermal: sensor3-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 2>; +@@ -1191,7 +1191,7 @@ + }; + }; + +- sensor_thermal4: sensor-thermal4 { ++ sensor4_thermal: sensor4-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 3>; +@@ -1205,7 +1205,7 @@ + }; + }; + +- sensor_thermal5: sensor-thermal5 { ++ sensor5_thermal: sensor5-thermal { + polling-delay-passive = <250>; + polling-delay = <1000>; + thermal-sensors = <&tsc 4>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts +index 665b2e69455dd..ea6820902ede0 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3308-roc-cc.dts +@@ -97,7 +97,7 @@ + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; +- vim-supply = <&vcc_io>; ++ vin-supply = <&vcc_io>; + }; + + vdd_core: vdd-core { +diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +index 8c821acb21ffb..da84be6f4715e 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -599,7 +599,7 @@ + + gpu: gpu@ff300000 { + compatible = "rockchip,rk3328-mali", "arm,mali-450"; +- reg = <0x0 0xff300000 0x0 0x40000>; ++ reg = <0x0 0xff300000 0x0 0x30000>; + interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>, +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +index c1bcc8ca3769d..2f8e117109699 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi +@@ -286,7 +286,7 @@ + + sound: sound { + compatible = "rockchip,rk3399-gru-sound"; +- rockchip,cpu = <&i2s0 &i2s2>; ++ rockchip,cpu = <&i2s0 &spdif>; + }; + }; + +@@ -437,10 +437,6 @@ ap_i2c_audio: &i2c8 { + status = "okay"; + }; + +-&i2s2 { +- status = "okay"; +-}; +- + &io_domains { + status = "okay"; + +@@ -537,6 +533,17 @@ ap_i2c_audio: &i2c8 { + vqmmc-supply = <&ppvar_sd_card_io>; + }; + ++&spdif { ++ status = "okay"; ++ ++ /* ++ * SPDIF is routed internally to DP; we either don't use these pins, or ++ * mux them to something else. ++ */ ++ /delete-property/ pinctrl-0; ++ /delete-property/ pinctrl-names; ++}; ++ + &spi1 { + status = "okay"; + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +index d5c7648c841dc..f1fcc6b5b402c 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi +@@ -705,7 +705,6 @@ + &sdhci { + bus-width = <8>; + mmc-hs400-1_8v; +- mmc-hs400-enhanced-strobe; + non-removable; + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +index 738cfd21df3ef..354f54767bad8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +@@ -269,6 +269,7 @@ + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; ++ rockchip,system-power-controller; + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +index 7c93f840bc64f..e890166e7fd43 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts +@@ -55,7 +55,7 @@ + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +- vim-supply = <&vcc3v3_sys>; ++ vin-supply = <&vcc3v3_sys>; + }; + + vcc3v3_sys: vcc3v3-sys { +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +index 2b5f001ff4a61..9e5d07f5712e6 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +@@ -385,10 +385,6 @@ + }; + }; + +-&cdn_dp { +- status = "okay"; +-}; +- + &cpu_b0 { + cpu-supply = <&vdd_cpu_b>; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +index b28888ea9262e..100a769165ef9 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +@@ -457,7 +457,7 @@ + status = "okay"; + + bt656-supply = <&vcc_3v0>; +- audio-supply = <&vcc_3v0>; ++ audio-supply = <&vcc1v8_codec>; + sdmmc-supply = <&vcc_sdio>; + gpio1830-supply = <&vcc_3v0>; + }; +diff --git a/arch/arm64/boot/dts/ti/k3-am642.dtsi b/arch/arm64/boot/dts/ti/k3-am642.dtsi +index e2b397c884018..8a76f4821b11b 100644 +--- a/arch/arm64/boot/dts/ti/k3-am642.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am642.dtsi +@@ -60,6 +60,6 @@ + cache-level = <2>; + cache-size = <0x40000>; + cache-line-size = <64>; +- cache-sets = <512>; ++ cache-sets = <256>; + }; + }; +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +index e8a41d09b45f2..7daa280220442 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +@@ -32,7 +32,7 @@ + #size-cells = <1>; + ranges = <0x00 0x00 0x00100000 0x1c000>; + +- serdes_ln_ctrl: serdes-ln-ctrl@4080 { ++ serdes_ln_ctrl: mux-controller@4080 { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */ +@@ -606,10 +606,10 @@ + clock-names = "fck"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x0 0xff>; + cdns,no-bar-match-nbits = <64>; +- vendor-id = /bits/ 16 <0x104c>; +- device-id = /bits/ 16 <0xb00f>; ++ vendor-id = <0x104c>; ++ device-id = <0xb00f>; + msi-map = <0x0 &gic_its 0x0 0x10000>; + dma-coherent; + ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>, +diff --git a/arch/arm64/boot/dts/ti/k3-j7200.dtsi b/arch/arm64/boot/dts/ti/k3-j7200.dtsi +index b7005b8031495..7586b5aea446f 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200.dtsi +@@ -60,7 +60,7 @@ + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; +- d-cache-sets = <128>; ++ d-cache-sets = <256>; + next-level-cache = <&L2_0>; + }; + +@@ -74,7 +74,7 @@ + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; +- d-cache-sets = <128>; ++ d-cache-sets = <256>; + next-level-cache = <&L2_0>; + }; + }; +@@ -84,7 +84,7 @@ + cache-level = <2>; + cache-size = <0x100000>; + cache-line-size = <64>; +- cache-sets = <2048>; ++ cache-sets = <1024>; + next-level-cache = <&msmc_l3>; + }; + +diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +index cf3482376c1e6..e85c89eebfa31 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +@@ -42,7 +42,7 @@ + #size-cells = <1>; + ranges = <0x0 0x0 0x00100000 0x1c000>; + +- serdes_ln_ctrl: mux@4080 { ++ serdes_ln_ctrl: mux-controller@4080 { + compatible = "mmio-mux"; + reg = <0x00004080 0x50>; + #mux-control-cells = <1>; +@@ -610,7 +610,7 @@ + clock-names = "fck"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x0 0xff>; + vendor-id = <0x104c>; + device-id = <0xb00d>; + msi-map = <0x0 &gic_its 0x0 0x10000>; +@@ -636,7 +636,7 @@ + clocks = <&k3_clks 239 1>; + clock-names = "fck"; + max-functions = /bits/ 8 <6>; +- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; ++ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; + dma-coherent; + }; + +@@ -658,7 +658,7 @@ + clock-names = "fck"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x0 0xff>; + vendor-id = <0x104c>; + device-id = <0xb00d>; + msi-map = <0x0 &gic_its 0x10000 0x10000>; +@@ -684,7 +684,7 @@ + clocks = <&k3_clks 240 1>; + clock-names = "fck"; + max-functions = /bits/ 8 <6>; +- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; ++ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; + dma-coherent; + }; + +@@ -706,7 +706,7 @@ + clock-names = "fck"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x0 0xff>; + vendor-id = <0x104c>; + device-id = <0xb00d>; + msi-map = <0x0 &gic_its 0x20000 0x10000>; +@@ -732,7 +732,7 @@ + clocks = <&k3_clks 241 1>; + clock-names = "fck"; + max-functions = /bits/ 8 <6>; +- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; ++ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; + dma-coherent; + }; + +@@ -754,7 +754,7 @@ + clock-names = "fck"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x0 0xff>; + vendor-id = <0x104c>; + device-id = <0xb00d>; + msi-map = <0x0 &gic_its 0x30000 0x10000>; +@@ -780,7 +780,7 @@ + clocks = <&k3_clks 242 1>; + clock-names = "fck"; + max-functions = /bits/ 8 <6>; +- max-virtual-functions = /bits/ 16 <4 4 4 4 0 0>; ++ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; + dma-coherent; + #address-cells = <2>; + #size-cells = <2>; +diff --git a/arch/arm64/boot/dts/ti/k3-j721e.dtsi b/arch/arm64/boot/dts/ti/k3-j721e.dtsi +index f0587fde147e6..69ce048a2136e 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721e.dtsi +@@ -61,7 +61,7 @@ + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; +- d-cache-sets = <128>; ++ d-cache-sets = <256>; + next-level-cache = <&L2_0>; + }; + +@@ -75,7 +75,7 @@ + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; +- d-cache-sets = <128>; ++ d-cache-sets = <256>; + next-level-cache = <&L2_0>; + }; + }; +@@ -85,7 +85,7 @@ + cache-level = <2>; + cache-size = <0x100000>; + cache-line-size = <64>; +- cache-sets = <2048>; ++ cache-sets = <1024>; + next-level-cache = <&msmc_l3>; + }; + +diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts +index 4a86efa32d687..f7124e15f0ff6 100644 +--- a/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts ++++ b/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts +@@ -131,7 +131,7 @@ + reg = <0>; + + partition@0 { +- label = "data"; ++ label = "spi0-data"; + reg = <0x0 0x100000>; + }; + }; +@@ -149,7 +149,7 @@ + reg = <0>; + + partition@0 { +- label = "data"; ++ label = "spi1-data"; + reg = <0x0 0x84000>; + }; + }; +diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi +index 28dccb891a535..8278876ad33fa 100644 +--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi ++++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi +@@ -792,7 +792,7 @@ + }; + + uart0: serial@ff000000 { +- compatible = "cdns,uart-r1p12", "xlnx,xuartps"; ++ compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12"; + status = "disabled"; + interrupt-parent = <&gic>; + interrupts = <0 21 4>; +@@ -802,7 +802,7 @@ + }; + + uart1: serial@ff010000 { +- compatible = "cdns,uart-r1p12", "xlnx,xuartps"; ++ compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12"; + status = "disabled"; + interrupt-parent = <&gic>; + interrupts = <0 22 4>; +diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h +index bfa58409a4d4d..448a575db8e8e 100644 +--- a/arch/arm64/include/asm/assembler.h ++++ b/arch/arm64/include/asm/assembler.h +@@ -107,6 +107,13 @@ + hint #20 + .endm + ++/* ++ * Clear Branch History instruction ++ */ ++ .macro clearbhb ++ hint #22 ++ .endm ++ + /* + * Speculation barrier + */ +@@ -830,4 +837,50 @@ alternative_endif + + #endif /* GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT */ + ++ .macro __mitigate_spectre_bhb_loop tmp ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++alternative_cb spectre_bhb_patch_loop_iter ++ mov \tmp, #32 // Patched to correct the immediate ++alternative_cb_end ++.Lspectre_bhb_loop\@: ++ b . + 4 ++ subs \tmp, \tmp, #1 ++ b.ne .Lspectre_bhb_loop\@ ++ sb ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ .endm ++ ++ .macro mitigate_spectre_bhb_loop tmp ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++alternative_cb spectre_bhb_patch_loop_mitigation_enable ++ b .L_spectre_bhb_loop_done\@ // Patched to NOP ++alternative_cb_end ++ __mitigate_spectre_bhb_loop \tmp ++.L_spectre_bhb_loop_done\@: ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ .endm ++ ++ /* Save/restores x0-x3 to the stack */ ++ .macro __mitigate_spectre_bhb_fw ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++ stp x0, x1, [sp, #-16]! ++ stp x2, x3, [sp, #-16]! ++ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_3 ++alternative_cb smccc_patch_fw_mitigation_conduit ++ nop // Patched to SMC/HVC #0 ++alternative_cb_end ++ ldp x2, x3, [sp], #16 ++ ldp x0, x1, [sp], #16 ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ .endm ++ ++ .macro mitigate_spectre_bhb_clear_insn ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++alternative_cb spectre_bhb_patch_clearbhb ++ /* Patched to NOP when not supported */ ++ clearbhb ++ isb ++alternative_cb_end ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ .endm + #endif /* __ASM_ASSEMBLER_H */ +diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h +index 0f6d16faa5402..a58e366f0b074 100644 +--- a/arch/arm64/include/asm/cpu.h ++++ b/arch/arm64/include/asm/cpu.h +@@ -51,6 +51,7 @@ struct cpuinfo_arm64 { + u64 reg_id_aa64dfr1; + u64 reg_id_aa64isar0; + u64 reg_id_aa64isar1; ++ u64 reg_id_aa64isar2; + u64 reg_id_aa64mmfr0; + u64 reg_id_aa64mmfr1; + u64 reg_id_aa64mmfr2; +diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h +index ef6be92b1921a..a77b5f49b3a6c 100644 +--- a/arch/arm64/include/asm/cpufeature.h ++++ b/arch/arm64/include/asm/cpufeature.h +@@ -637,6 +637,35 @@ static inline bool cpu_supports_mixed_endian_el0(void) + return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1)); + } + ++ ++static inline bool supports_csv2p3(int scope) ++{ ++ u64 pfr0; ++ u8 csv2_val; ++ ++ if (scope == SCOPE_LOCAL_CPU) ++ pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1); ++ else ++ pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); ++ ++ csv2_val = cpuid_feature_extract_unsigned_field(pfr0, ++ ID_AA64PFR0_CSV2_SHIFT); ++ return csv2_val == 3; ++} ++ ++static inline bool supports_clearbhb(int scope) ++{ ++ u64 isar2; ++ ++ if (scope == SCOPE_LOCAL_CPU) ++ isar2 = read_sysreg_s(SYS_ID_AA64ISAR2_EL1); ++ else ++ isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1); ++ ++ return cpuid_feature_extract_unsigned_field(isar2, ++ ID_AA64ISAR2_CLEARBHB_SHIFT); ++} ++ + const struct cpumask *system_32bit_el0_cpumask(void); + DECLARE_STATIC_KEY_FALSE(arm64_mismatched_32bit_el0); + +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index 6231e1f0abe7e..bfbf0c4c7c5e5 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -73,6 +73,14 @@ + #define ARM_CPU_PART_CORTEX_A76 0xD0B + #define ARM_CPU_PART_NEOVERSE_N1 0xD0C + #define ARM_CPU_PART_CORTEX_A77 0xD0D ++#define ARM_CPU_PART_NEOVERSE_V1 0xD40 ++#define ARM_CPU_PART_CORTEX_A78 0xD41 ++#define ARM_CPU_PART_CORTEX_X1 0xD44 ++#define ARM_CPU_PART_CORTEX_A510 0xD46 ++#define ARM_CPU_PART_CORTEX_A710 0xD47 ++#define ARM_CPU_PART_CORTEX_X2 0xD48 ++#define ARM_CPU_PART_NEOVERSE_N2 0xD49 ++#define ARM_CPU_PART_CORTEX_A78C 0xD4B + + #define APM_CPU_PART_POTENZA 0x000 + +@@ -113,6 +121,14 @@ + #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) + #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) + #define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) ++#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1) ++#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) ++#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) ++#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) ++#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) ++#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) ++#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) ++#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) + #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) + #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) + #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) +diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h +index d3e1825337be3..ad55079abe476 100644 +--- a/arch/arm64/include/asm/efi.h ++++ b/arch/arm64/include/asm/efi.h +@@ -14,7 +14,6 @@ + + #ifdef CONFIG_EFI + extern void efi_init(void); +-extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); + #else + #define efi_init() + #endif +diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h +index 3198acb2aad8c..7f3c87f7a0cec 100644 +--- a/arch/arm64/include/asm/el2_setup.h ++++ b/arch/arm64/include/asm/el2_setup.h +@@ -106,7 +106,7 @@ + msr_s SYS_ICC_SRE_EL2, x0 + isb // Make sure SRE is now set + mrs_s x0, SYS_ICC_SRE_EL2 // Read SRE back, +- tbz x0, #0, 1f // and check that it sticks ++ tbz x0, #0, .Lskip_gicv3_\@ // and check that it sticks + msr_s SYS_ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults + .Lskip_gicv3_\@: + .endm +diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h +index 29f97eb3dad41..8f59bbeba7a7e 100644 +--- a/arch/arm64/include/asm/esr.h ++++ b/arch/arm64/include/asm/esr.h +@@ -68,6 +68,7 @@ + #define ESR_ELx_EC_MAX (0x3F) + + #define ESR_ELx_EC_SHIFT (26) ++#define ESR_ELx_EC_WIDTH (6) + #define ESR_ELx_EC_MASK (UL(0x3F) << ESR_ELx_EC_SHIFT) + #define ESR_ELx_EC(esr) (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT) + +diff --git a/arch/arm64/include/asm/extable.h b/arch/arm64/include/asm/extable.h +index b15eb4a3e6b20..840a35ed92ec8 100644 +--- a/arch/arm64/include/asm/extable.h ++++ b/arch/arm64/include/asm/extable.h +@@ -22,15 +22,6 @@ struct exception_table_entry + + #define ARCH_HAS_RELATIVE_EXTABLE + +-static inline bool in_bpf_jit(struct pt_regs *regs) +-{ +- if (!IS_ENABLED(CONFIG_BPF_JIT)) +- return false; +- +- return regs->pc >= BPF_JIT_REGION_START && +- regs->pc < BPF_JIT_REGION_END; +-} +- + #ifdef CONFIG_BPF_JIT + int arm64_bpf_fixup_exception(const struct exception_table_entry *ex, + struct pt_regs *regs); +diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h +index 4335800201c97..daff882883f92 100644 +--- a/arch/arm64/include/asm/fixmap.h ++++ b/arch/arm64/include/asm/fixmap.h +@@ -62,9 +62,11 @@ enum fixed_addresses { + #endif /* CONFIG_ACPI_APEI_GHES */ + + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++ FIX_ENTRY_TRAMP_TEXT3, ++ FIX_ENTRY_TRAMP_TEXT2, ++ FIX_ENTRY_TRAMP_TEXT1, + FIX_ENTRY_TRAMP_DATA, +- FIX_ENTRY_TRAMP_TEXT, +-#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT)) ++#define TRAMP_VALIAS (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT1)) + #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + __end_of_permanent_fixed_addresses, + +diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h +index 8c129db8232a6..f68fbb2074730 100644 +--- a/arch/arm64/include/asm/hwcap.h ++++ b/arch/arm64/include/asm/hwcap.h +@@ -105,6 +105,9 @@ + #define KERNEL_HWCAP_RNG __khwcap2_feature(RNG) + #define KERNEL_HWCAP_BTI __khwcap2_feature(BTI) + #define KERNEL_HWCAP_MTE __khwcap2_feature(MTE) ++#define KERNEL_HWCAP_ECV __khwcap2_feature(ECV) ++#define KERNEL_HWCAP_AFP __khwcap2_feature(AFP) ++#define KERNEL_HWCAP_RPRES __khwcap2_feature(RPRES) + + /* + * This yields a mask that user programs can use to figure out what +diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h +index 6b776c8667b20..b02f0c328c8e4 100644 +--- a/arch/arm64/include/asm/insn.h ++++ b/arch/arm64/include/asm/insn.h +@@ -65,6 +65,7 @@ enum aarch64_insn_hint_cr_op { + AARCH64_INSN_HINT_PSB = 0x11 << 5, + AARCH64_INSN_HINT_TSB = 0x12 << 5, + AARCH64_INSN_HINT_CSDB = 0x14 << 5, ++ AARCH64_INSN_HINT_CLEARBHB = 0x16 << 5, + + AARCH64_INSN_HINT_BTI = 0x20 << 5, + AARCH64_INSN_HINT_BTIC = 0x22 << 5, +diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h +index 327120c0089fe..f67a561e0935e 100644 +--- a/arch/arm64/include/asm/kvm_arm.h ++++ b/arch/arm64/include/asm/kvm_arm.h +@@ -91,7 +91,7 @@ + #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) + + /* TCR_EL2 Registers bits */ +-#define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) ++#define TCR_EL2_RES1 ((1U << 31) | (1 << 23)) + #define TCR_EL2_TBI (1 << 20) + #define TCR_EL2_PS_SHIFT 16 + #define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT) +@@ -276,7 +276,7 @@ + #define CPTR_EL2_TFP_SHIFT 10 + + /* Hyp Coprocessor Trap Register */ +-#define CPTR_EL2_TCPAC (1 << 31) ++#define CPTR_EL2_TCPAC (1U << 31) + #define CPTR_EL2_TAM (1 << 30) + #define CPTR_EL2_TTA (1 << 20) + #define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT) +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index f8be56d5342ba..fc6ee6c5972d0 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -711,6 +711,11 @@ static inline void kvm_init_host_cpu_context(struct kvm_cpu_context *cpu_ctxt) + ctxt_sys_reg(cpu_ctxt, MPIDR_EL1) = read_cpuid_mpidr(); + } + ++static inline bool kvm_system_needs_idmapped_vectors(void) ++{ ++ return cpus_have_const_cap(ARM64_SPECTRE_V3A); ++} ++ + void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu); + + static inline void kvm_arch_hardware_unsetup(void) {} +diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h +index f1745a8434144..05886322c300c 100644 +--- a/arch/arm64/include/asm/memory.h ++++ b/arch/arm64/include/asm/memory.h +@@ -44,11 +44,8 @@ + #define _PAGE_OFFSET(va) (-(UL(1) << (va))) + #define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS)) + #define KIMAGE_VADDR (MODULES_END) +-#define BPF_JIT_REGION_START (_PAGE_END(VA_BITS_MIN)) +-#define BPF_JIT_REGION_SIZE (SZ_128M) +-#define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE) + #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) +-#define MODULES_VADDR (BPF_JIT_REGION_END) ++#define MODULES_VADDR (_PAGE_END(VA_BITS_MIN)) + #define MODULES_VSIZE (SZ_128M) + #define VMEMMAP_START (-(UL(1) << (VA_BITS - VMEMMAP_SHIFT))) + #define VMEMMAP_END (VMEMMAP_START + VMEMMAP_SIZE) +diff --git a/arch/arm64/include/asm/mte-kasan.h b/arch/arm64/include/asm/mte-kasan.h +index 22420e1f8c037..26e013e540ae2 100644 +--- a/arch/arm64/include/asm/mte-kasan.h ++++ b/arch/arm64/include/asm/mte-kasan.h +@@ -84,10 +84,12 @@ static inline void __dc_gzva(u64 p) + static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag, + bool init) + { +- u64 curr, mask, dczid_bs, end1, end2, end3; ++ u64 curr, mask, dczid, dczid_bs, dczid_dzp, end1, end2, end3; + + /* Read DC G(Z)VA block size from the system register. */ +- dczid_bs = 4ul << (read_cpuid(DCZID_EL0) & 0xf); ++ dczid = read_cpuid(DCZID_EL0); ++ dczid_bs = 4ul << (dczid & 0xf); ++ dczid_dzp = (dczid >> 4) & 1; + + curr = (u64)__tag_set(addr, tag); + mask = dczid_bs - 1; +@@ -106,7 +108,7 @@ static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag, + */ + #define SET_MEMTAG_RANGE(stg_post, dc_gva) \ + do { \ +- if (size >= 2 * dczid_bs) { \ ++ if (!dczid_dzp && size >= 2 * dczid_bs) {\ + do { \ + curr = stg_post(curr); \ + } while (curr < end1); \ +diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h +index 8433a2058eb15..237224484d0f6 100644 +--- a/arch/arm64/include/asm/pgalloc.h ++++ b/arch/arm64/include/asm/pgalloc.h +@@ -76,7 +76,7 @@ static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t ptep, + static inline void + pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) + { +- VM_BUG_ON(mm != &init_mm); ++ VM_BUG_ON(mm && mm != &init_mm); + __pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE | PMD_TABLE_UXN); + } + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index dfa76afa0ccff..72f95c6a70519 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -67,9 +67,15 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; + * page table entry, taking care of 52-bit addresses. + */ + #ifdef CONFIG_ARM64_PA_BITS_52 +-#define __pte_to_phys(pte) \ +- ((pte_val(pte) & PTE_ADDR_LOW) | ((pte_val(pte) & PTE_ADDR_HIGH) << 36)) +-#define __phys_to_pte_val(phys) (((phys) | ((phys) >> 36)) & PTE_ADDR_MASK) ++static inline phys_addr_t __pte_to_phys(pte_t pte) ++{ ++ return (pte_val(pte) & PTE_ADDR_LOW) | ++ ((pte_val(pte) & PTE_ADDR_HIGH) << 36); ++} ++static inline pteval_t __phys_to_pte_val(phys_addr_t phys) ++{ ++ return (phys | (phys >> 36)) & PTE_ADDR_MASK; ++} + #else + #define __pte_to_phys(pte) (pte_val(pte) & PTE_ADDR_MASK) + #define __phys_to_pte_val(phys) (phys) +diff --git a/arch/arm64/include/asm/rwonce.h b/arch/arm64/include/asm/rwonce.h +index 1bce62fa908a3..56f7b1d4d54b9 100644 +--- a/arch/arm64/include/asm/rwonce.h ++++ b/arch/arm64/include/asm/rwonce.h +@@ -5,7 +5,7 @@ + #ifndef __ASM_RWONCE_H + #define __ASM_RWONCE_H + +-#ifdef CONFIG_LTO ++#if defined(CONFIG_LTO) && !defined(__ASSEMBLY__) + + #include <linux/compiler_types.h> + #include <asm/alternative-macros.h> +@@ -66,7 +66,7 @@ + }) + + #endif /* !BUILD_VDSO */ +-#endif /* CONFIG_LTO */ ++#endif /* CONFIG_LTO && !__ASSEMBLY__ */ + + #include <asm-generic/rwonce.h> + +diff --git a/arch/arm64/include/asm/sections.h b/arch/arm64/include/asm/sections.h +index e4ad9db53af1d..552891e626e53 100644 +--- a/arch/arm64/include/asm/sections.h ++++ b/arch/arm64/include/asm/sections.h +@@ -22,4 +22,9 @@ extern char __irqentry_text_start[], __irqentry_text_end[]; + extern char __mmuoff_data_start[], __mmuoff_data_end[]; + extern char __entry_tramp_text_start[], __entry_tramp_text_end[]; + ++static inline size_t entry_tramp_text_size(void) ++{ ++ return __entry_tramp_text_end - __entry_tramp_text_start; ++} ++ + #endif /* __ASM_SECTIONS_H */ +diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h +index f62ca39da6c5a..86e0cc9b9c685 100644 +--- a/arch/arm64/include/asm/spectre.h ++++ b/arch/arm64/include/asm/spectre.h +@@ -93,5 +93,9 @@ void spectre_v4_enable_task_mitigation(struct task_struct *tsk); + + enum mitigation_state arm64_get_meltdown_state(void); + ++enum mitigation_state arm64_get_spectre_bhb_state(void); ++bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope); ++u8 spectre_bhb_loop_affected(int scope); ++void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); + #endif /* __ASSEMBLY__ */ + #endif /* __ASM_SPECTRE_H */ +diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h +index b268082d67edd..394fc5998a4b2 100644 +--- a/arch/arm64/include/asm/sysreg.h ++++ b/arch/arm64/include/asm/sysreg.h +@@ -180,6 +180,7 @@ + + #define SYS_ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0) + #define SYS_ID_AA64ISAR1_EL1 sys_reg(3, 0, 0, 6, 1) ++#define SYS_ID_AA64ISAR2_EL1 sys_reg(3, 0, 0, 6, 2) + + #define SYS_ID_AA64MMFR0_EL1 sys_reg(3, 0, 0, 7, 0) + #define SYS_ID_AA64MMFR1_EL1 sys_reg(3, 0, 0, 7, 1) +@@ -764,6 +765,21 @@ + #define ID_AA64ISAR1_GPI_NI 0x0 + #define ID_AA64ISAR1_GPI_IMP_DEF 0x1 + ++/* id_aa64isar2 */ ++#define ID_AA64ISAR2_CLEARBHB_SHIFT 28 ++#define ID_AA64ISAR2_RPRES_SHIFT 4 ++#define ID_AA64ISAR2_WFXT_SHIFT 0 ++ ++#define ID_AA64ISAR2_RPRES_8BIT 0x0 ++#define ID_AA64ISAR2_RPRES_12BIT 0x1 ++/* ++ * Value 0x1 has been removed from the architecture, and is ++ * reserved, but has not yet been removed from the ARM ARM ++ * as of ARM DDI 0487G.b. ++ */ ++#define ID_AA64ISAR2_WFXT_NI 0x0 ++#define ID_AA64ISAR2_WFXT_SUPPORTED 0x2 ++ + /* id_aa64pfr0 */ + #define ID_AA64PFR0_CSV3_SHIFT 60 + #define ID_AA64PFR0_CSV2_SHIFT 56 +@@ -881,6 +897,8 @@ + #endif + + /* id_aa64mmfr1 */ ++#define ID_AA64MMFR1_ECBHB_SHIFT 60 ++#define ID_AA64MMFR1_AFP_SHIFT 44 + #define ID_AA64MMFR1_ETS_SHIFT 36 + #define ID_AA64MMFR1_TWED_SHIFT 32 + #define ID_AA64MMFR1_XNX_SHIFT 28 +diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h +index 190b494e22ab9..0fd6056ba412b 100644 +--- a/arch/arm64/include/asm/uaccess.h ++++ b/arch/arm64/include/asm/uaccess.h +@@ -292,12 +292,22 @@ do { \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ + } while (0) + ++/* ++ * We must not call into the scheduler between uaccess_ttbr0_enable() and ++ * uaccess_ttbr0_disable(). As `x` and `ptr` could contain blocking functions, ++ * we must evaluate these outside of the critical section. ++ */ + #define __raw_get_user(x, ptr, err) \ + do { \ ++ __typeof__(*(ptr)) __user *__rgu_ptr = (ptr); \ ++ __typeof__(x) __rgu_val; \ + __chk_user_ptr(ptr); \ ++ \ + uaccess_ttbr0_enable(); \ +- __raw_get_mem("ldtr", x, ptr, err); \ ++ __raw_get_mem("ldtr", __rgu_val, __rgu_ptr, err); \ + uaccess_ttbr0_disable(); \ ++ \ ++ (x) = __rgu_val; \ + } while (0) + + #define __get_user_error(x, ptr, err) \ +@@ -321,14 +331,22 @@ do { \ + + #define get_user __get_user + ++/* ++ * We must not call into the scheduler between __uaccess_enable_tco_async() and ++ * __uaccess_disable_tco_async(). As `dst` and `src` may contain blocking ++ * functions, we must evaluate these outside of the critical section. ++ */ + #define __get_kernel_nofault(dst, src, type, err_label) \ + do { \ ++ __typeof__(dst) __gkn_dst = (dst); \ ++ __typeof__(src) __gkn_src = (src); \ + int __gkn_err = 0; \ + \ + __uaccess_enable_tco_async(); \ +- __raw_get_mem("ldr", *((type *)(dst)), \ +- (__force type *)(src), __gkn_err); \ ++ __raw_get_mem("ldr", *((type *)(__gkn_dst)), \ ++ (__force type *)(__gkn_src), __gkn_err); \ + __uaccess_disable_tco_async(); \ ++ \ + if (unlikely(__gkn_err)) \ + goto err_label; \ + } while (0) +@@ -367,11 +385,19 @@ do { \ + } \ + } while (0) + ++/* ++ * We must not call into the scheduler between uaccess_ttbr0_enable() and ++ * uaccess_ttbr0_disable(). As `x` and `ptr` could contain blocking functions, ++ * we must evaluate these outside of the critical section. ++ */ + #define __raw_put_user(x, ptr, err) \ + do { \ +- __chk_user_ptr(ptr); \ ++ __typeof__(*(ptr)) __user *__rpu_ptr = (ptr); \ ++ __typeof__(*(ptr)) __rpu_val = (x); \ ++ __chk_user_ptr(__rpu_ptr); \ ++ \ + uaccess_ttbr0_enable(); \ +- __raw_put_mem("sttr", x, ptr, err); \ ++ __raw_put_mem("sttr", __rpu_val, __rpu_ptr, err); \ + uaccess_ttbr0_disable(); \ + } while (0) + +@@ -396,14 +422,22 @@ do { \ + + #define put_user __put_user + ++/* ++ * We must not call into the scheduler between __uaccess_enable_tco_async() and ++ * __uaccess_disable_tco_async(). As `dst` and `src` may contain blocking ++ * functions, we must evaluate these outside of the critical section. ++ */ + #define __put_kernel_nofault(dst, src, type, err_label) \ + do { \ ++ __typeof__(dst) __pkn_dst = (dst); \ ++ __typeof__(src) __pkn_src = (src); \ + int __pkn_err = 0; \ + \ + __uaccess_enable_tco_async(); \ +- __raw_put_mem("str", *((type *)(src)), \ +- (__force type *)(dst), __pkn_err); \ ++ __raw_put_mem("str", *((type *)(__pkn_src)), \ ++ (__force type *)(__pkn_dst), __pkn_err); \ + __uaccess_disable_tco_async(); \ ++ \ + if (unlikely(__pkn_err)) \ + goto err_label; \ + } while(0) +diff --git a/arch/arm64/include/asm/vectors.h b/arch/arm64/include/asm/vectors.h +new file mode 100644 +index 0000000000000..f64613a96d530 +--- /dev/null ++++ b/arch/arm64/include/asm/vectors.h +@@ -0,0 +1,73 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2022 ARM Ltd. ++ */ ++#ifndef __ASM_VECTORS_H ++#define __ASM_VECTORS_H ++ ++#include <linux/bug.h> ++#include <linux/percpu.h> ++ ++#include <asm/fixmap.h> ++ ++extern char vectors[]; ++extern char tramp_vectors[]; ++extern char __bp_harden_el1_vectors[]; ++ ++/* ++ * Note: the order of this enum corresponds to two arrays in entry.S: ++ * tramp_vecs and __bp_harden_el1_vectors. By default the canonical ++ * 'full fat' vectors are used directly. ++ */ ++enum arm64_bp_harden_el1_vectors { ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++ /* ++ * Perform the BHB loop mitigation, before branching to the canonical ++ * vectors. ++ */ ++ EL1_VECTOR_BHB_LOOP, ++ ++ /* ++ * Make the SMC call for firmware mitigation, before branching to the ++ * canonical vectors. ++ */ ++ EL1_VECTOR_BHB_FW, ++ ++ /* ++ * Use the ClearBHB instruction, before branching to the canonical ++ * vectors. ++ */ ++ EL1_VECTOR_BHB_CLEAR_INSN, ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ ++ /* ++ * Remap the kernel before branching to the canonical vectors. ++ */ ++ EL1_VECTOR_KPTI, ++}; ++ ++#ifndef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++#define EL1_VECTOR_BHB_LOOP -1 ++#define EL1_VECTOR_BHB_FW -1 ++#define EL1_VECTOR_BHB_CLEAR_INSN -1 ++#endif /* !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ ++/* The vectors to use on return from EL0. e.g. to remap the kernel */ ++DECLARE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector); ++ ++#ifndef CONFIG_UNMAP_KERNEL_AT_EL0 ++#define TRAMP_VALIAS 0 ++#endif ++ ++static inline const char * ++arm64_get_bp_hardening_vector(enum arm64_bp_harden_el1_vectors slot) ++{ ++ if (arm64_kernel_unmapped_at_el0()) ++ return (char *)TRAMP_VALIAS + SZ_2K * slot; ++ ++ WARN_ON_ONCE(slot == EL1_VECTOR_KPTI); ++ ++ return __bp_harden_el1_vectors + SZ_2K * slot; ++} ++ ++#endif /* __ASM_VECTORS_H */ +diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h +index b8f41aa234ee1..f03731847d9df 100644 +--- a/arch/arm64/include/uapi/asm/hwcap.h ++++ b/arch/arm64/include/uapi/asm/hwcap.h +@@ -75,5 +75,8 @@ + #define HWCAP2_RNG (1 << 16) + #define HWCAP2_BTI (1 << 17) + #define HWCAP2_MTE (1 << 18) ++#define HWCAP2_ECV (1 << 19) ++#define HWCAP2_AFP (1 << 20) ++#define HWCAP2_RPRES (1 << 21) + + #endif /* _UAPI__ASM_HWCAP_H */ +diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h +index b3edde68bc3e0..323e251ed37bc 100644 +--- a/arch/arm64/include/uapi/asm/kvm.h ++++ b/arch/arm64/include/uapi/asm/kvm.h +@@ -281,6 +281,11 @@ struct kvm_arm_copy_mte_tags { + #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3 + #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4) + ++#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 KVM_REG_ARM_FW_REG(3) ++#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL 0 ++#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL 1 ++#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED 2 ++ + /* SVE registers */ + #define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT) + +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index e2c20c036442f..a33d7b8f3b935 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -464,6 +464,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + .matches = has_spectre_v4, + .cpu_enable = spectre_v4_enable_mitigation, + }, ++ { ++ .desc = "Spectre-BHB", ++ .capability = ARM64_SPECTRE_BHB, ++ .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, ++ .matches = is_spectre_bhb_affected, ++ .cpu_enable = spectre_bhb_enable_mitigation, ++ }, + #ifdef CONFIG_ARM64_ERRATUM_1418040 + { + .desc = "ARM erratum 1418040", +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 6ec7036ef7e18..e71c9cfb46e8c 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -73,6 +73,8 @@ + #include <linux/mm.h> + #include <linux/cpu.h> + #include <linux/kasan.h> ++#include <linux/percpu.h> ++ + #include <asm/cpu.h> + #include <asm/cpufeature.h> + #include <asm/cpu_ops.h> +@@ -85,6 +87,7 @@ + #include <asm/smp.h> + #include <asm/sysreg.h> + #include <asm/traps.h> ++#include <asm/vectors.h> + #include <asm/virt.h> + + /* Kernel representation of AT_HWCAP and AT_HWCAP2 */ +@@ -110,6 +113,8 @@ DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE); + bool arm64_use_ng_mappings = false; + EXPORT_SYMBOL(arm64_use_ng_mappings); + ++DEFINE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector) = vectors; ++ + /* + * Permit PER_LINUX32 and execve() of 32-bit binaries even if not all CPUs + * support it? +@@ -225,6 +230,12 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { + ARM64_FTR_END, + }; + ++static const struct arm64_ftr_bits ftr_id_aa64isar2[] = { ++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_CLEARBHB_SHIFT, 4, 0), ++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_RPRES_SHIFT, 4, 0), ++ ARM64_FTR_END, ++}; ++ + static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0), +@@ -279,7 +290,7 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = { + }; + + static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { +- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_ECV_SHIFT, 4, 0), ++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_ECV_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_FGT_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_EXS_SHIFT, 4, 0), + /* +@@ -325,6 +336,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { + }; + + static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { ++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_AFP_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_ETS_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_TWED_SHIFT, 4, 0), + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_XNX_SHIFT, 4, 0), +@@ -573,15 +585,19 @@ static const struct arm64_ftr_bits ftr_raz[] = { + ARM64_FTR_END, + }; + +-#define ARM64_FTR_REG_OVERRIDE(id, table, ovr) { \ ++#define __ARM64_FTR_REG_OVERRIDE(id_str, id, table, ovr) { \ + .sys_id = id, \ + .reg = &(struct arm64_ftr_reg){ \ +- .name = #id, \ ++ .name = id_str, \ + .override = (ovr), \ + .ftr_bits = &((table)[0]), \ + }} + +-#define ARM64_FTR_REG(id, table) ARM64_FTR_REG_OVERRIDE(id, table, &no_override) ++#define ARM64_FTR_REG_OVERRIDE(id, table, ovr) \ ++ __ARM64_FTR_REG_OVERRIDE(#id, id, table, ovr) ++ ++#define ARM64_FTR_REG(id, table) \ ++ __ARM64_FTR_REG_OVERRIDE(#id, id, table, &no_override) + + struct arm64_ftr_override __ro_after_init id_aa64mmfr1_override; + struct arm64_ftr_override __ro_after_init id_aa64pfr1_override; +@@ -633,6 +649,7 @@ static const struct __ftr_reg_entry { + ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0), + ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1, + &id_aa64isar1_override), ++ ARM64_FTR_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2), + + /* Op1 = 0, CRn = 0, CRm = 7 */ + ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0), +@@ -929,6 +946,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info) + init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1); + init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0); + init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1); ++ init_cpu_ftr_reg(SYS_ID_AA64ISAR2_EL1, info->reg_id_aa64isar2); + init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0); + init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1); + init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2); +@@ -1147,6 +1165,8 @@ void update_cpu_features(int cpu, + info->reg_id_aa64isar0, boot->reg_id_aa64isar0); + taint |= check_update_ftr_reg(SYS_ID_AA64ISAR1_EL1, cpu, + info->reg_id_aa64isar1, boot->reg_id_aa64isar1); ++ taint |= check_update_ftr_reg(SYS_ID_AA64ISAR2_EL1, cpu, ++ info->reg_id_aa64isar2, boot->reg_id_aa64isar2); + + /* + * Differing PARange support is fine as long as all peripherals and +@@ -1268,6 +1288,7 @@ u64 __read_sysreg_by_encoding(u32 sys_id) + read_sysreg_case(SYS_ID_AA64MMFR2_EL1); + read_sysreg_case(SYS_ID_AA64ISAR0_EL1); + read_sysreg_case(SYS_ID_AA64ISAR1_EL1); ++ read_sysreg_case(SYS_ID_AA64ISAR2_EL1); + + read_sysreg_case(SYS_CNTFRQ_EL0); + read_sysreg_case(SYS_CTR_EL0); +@@ -1575,6 +1596,12 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused) + + int cpu = smp_processor_id(); + ++ if (__this_cpu_read(this_cpu_vector) == vectors) { ++ const char *v = arm64_get_bp_hardening_vector(EL1_VECTOR_KPTI); ++ ++ __this_cpu_write(this_cpu_vector, v); ++ } ++ + /* + * We don't need to rewrite the page-tables if either we've done + * it already or we have KASLR enabled and therefore have not +@@ -2451,6 +2478,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { + #ifdef CONFIG_ARM64_MTE + HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_MTE_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_MTE, CAP_HWCAP, KERNEL_HWCAP_MTE), + #endif /* CONFIG_ARM64_MTE */ ++ HWCAP_CAP(SYS_ID_AA64MMFR0_EL1, ID_AA64MMFR0_ECV_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ECV), ++ HWCAP_CAP(SYS_ID_AA64MMFR1_EL1, ID_AA64MMFR1_AFP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AFP), ++ HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_RPRES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_RPRES), + {}, + }; + +diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c +index 87731fea5e418..591c18a889a56 100644 +--- a/arch/arm64/kernel/cpuinfo.c ++++ b/arch/arm64/kernel/cpuinfo.c +@@ -94,6 +94,9 @@ static const char *const hwcap_str[] = { + [KERNEL_HWCAP_RNG] = "rng", + [KERNEL_HWCAP_BTI] = "bti", + [KERNEL_HWCAP_MTE] = "mte", ++ [KERNEL_HWCAP_ECV] = "ecv", ++ [KERNEL_HWCAP_AFP] = "afp", ++ [KERNEL_HWCAP_RPRES] = "rpres", + }; + + #ifdef CONFIG_COMPAT +@@ -390,6 +393,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) + info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1); + info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1); + info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1); ++ info->reg_id_aa64isar2 = read_cpuid(ID_AA64ISAR2_EL1); + info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); + info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); + info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1); +diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S +index b3e4f9a088b1a..8cf970d219f5d 100644 +--- a/arch/arm64/kernel/entry-ftrace.S ++++ b/arch/arm64/kernel/entry-ftrace.S +@@ -77,11 +77,17 @@ + .endm + + SYM_CODE_START(ftrace_regs_caller) ++#ifdef BTI_C ++ BTI_C ++#endif + ftrace_regs_entry 1 + b ftrace_common + SYM_CODE_END(ftrace_regs_caller) + + SYM_CODE_START(ftrace_caller) ++#ifdef BTI_C ++ BTI_C ++#endif + ftrace_regs_entry 0 + b ftrace_common + SYM_CODE_END(ftrace_caller) +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index bc6d5a970a131..34e38eb00f056 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -37,18 +37,21 @@ + + .macro kernel_ventry, el:req, ht:req, regsize:req, label:req + .align 7 +-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++.Lventry_start\@: + .if \el == 0 +-alternative_if ARM64_UNMAP_KERNEL_AT_EL0 ++ /* ++ * This must be the first instruction of the EL0 vector entries. It is ++ * skipped by the trampoline vectors, to trigger the cleanup. ++ */ ++ b .Lskip_tramp_vectors_cleanup\@ + .if \regsize == 64 + mrs x30, tpidrro_el0 + msr tpidrro_el0, xzr + .else + mov x30, xzr + .endif +-alternative_else_nop_endif ++.Lskip_tramp_vectors_cleanup\@: + .endif +-#endif + + sub sp, sp, #PT_REGS_SIZE + #ifdef CONFIG_VMAP_STACK +@@ -95,11 +98,15 @@ alternative_else_nop_endif + mrs x0, tpidrro_el0 + #endif + b el\el\ht\()_\regsize\()_\label ++.org .Lventry_start\@ + 128 // Did we overflow the ventry slot? + .endm + +- .macro tramp_alias, dst, sym ++ .macro tramp_alias, dst, sym, tmp + mov_q \dst, TRAMP_VALIAS +- add \dst, \dst, #(\sym - .entry.tramp.text) ++ adr_l \tmp, \sym ++ add \dst, \dst, \tmp ++ adr_l \tmp, .entry.tramp.text ++ sub \dst, \dst, \tmp + .endm + + /* +@@ -116,7 +123,7 @@ alternative_cb_end + tbnz \tmp2, #TIF_SSBD, .L__asm_ssbd_skip\@ + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 + mov w1, #\state +-alternative_cb spectre_v4_patch_fw_mitigation_conduit ++alternative_cb smccc_patch_fw_mitigation_conduit + nop // Patched to SMC/HVC #0 + alternative_cb_end + .L__asm_ssbd_skip\@: +@@ -413,21 +420,26 @@ alternative_else_nop_endif + ldp x24, x25, [sp, #16 * 12] + ldp x26, x27, [sp, #16 * 13] + ldp x28, x29, [sp, #16 * 14] +- ldr lr, [sp, #S_LR] +- add sp, sp, #PT_REGS_SIZE // restore sp + + .if \el == 0 +-alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 ++alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 ++ ldr lr, [sp, #S_LR] ++ add sp, sp, #PT_REGS_SIZE // restore sp ++ eret ++alternative_else_nop_endif + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + bne 4f +- msr far_el1, x30 +- tramp_alias x30, tramp_exit_native ++ msr far_el1, x29 ++ tramp_alias x30, tramp_exit_native, x29 + br x30 + 4: +- tramp_alias x30, tramp_exit_compat ++ tramp_alias x30, tramp_exit_compat, x29 + br x30 + #endif + .else ++ ldr lr, [sp, #S_LR] ++ add sp, sp, #PT_REGS_SIZE // restore sp ++ + /* Ensure any device/NC reads complete */ + alternative_insn nop, "dmb sy", ARM64_WORKAROUND_1508412 + +@@ -594,12 +606,6 @@ SYM_CODE_END(ret_to_user) + + .popsection // .entry.text + +-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +-/* +- * Exception vectors trampoline. +- */ +- .pushsection ".entry.tramp.text", "ax" +- + // Move from tramp_pg_dir to swapper_pg_dir + .macro tramp_map_kernel, tmp + mrs \tmp, ttbr1_el1 +@@ -633,12 +639,47 @@ alternative_else_nop_endif + */ + .endm + +- .macro tramp_ventry, regsize = 64 ++ .macro tramp_data_page dst ++ adr_l \dst, .entry.tramp.text ++ sub \dst, \dst, PAGE_SIZE ++ .endm ++ ++ .macro tramp_data_read_var dst, var ++#ifdef CONFIG_RANDOMIZE_BASE ++ tramp_data_page \dst ++ add \dst, \dst, #:lo12:__entry_tramp_data_\var ++ ldr \dst, [\dst] ++#else ++ ldr \dst, =\var ++#endif ++ .endm ++ ++#define BHB_MITIGATION_NONE 0 ++#define BHB_MITIGATION_LOOP 1 ++#define BHB_MITIGATION_FW 2 ++#define BHB_MITIGATION_INSN 3 ++ ++ .macro tramp_ventry, vector_start, regsize, kpti, bhb + .align 7 + 1: + .if \regsize == 64 + msr tpidrro_el0, x30 // Restored in kernel_ventry + .endif ++ ++ .if \bhb == BHB_MITIGATION_LOOP ++ /* ++ * This sequence must appear before the first indirect branch. i.e. the ++ * ret out of tramp_ventry. It appears here because x30 is free. ++ */ ++ __mitigate_spectre_bhb_loop x30 ++ .endif // \bhb == BHB_MITIGATION_LOOP ++ ++ .if \bhb == BHB_MITIGATION_INSN ++ clearbhb ++ isb ++ .endif // \bhb == BHB_MITIGATION_INSN ++ ++ .if \kpti == 1 + /* + * Defend against branch aliasing attacks by pushing a dummy + * entry onto the return stack and using a RET instruction to +@@ -648,46 +689,75 @@ alternative_else_nop_endif + b . + 2: + tramp_map_kernel x30 +-#ifdef CONFIG_RANDOMIZE_BASE +- adr x30, tramp_vectors + PAGE_SIZE + alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003 +- ldr x30, [x30] +-#else +- ldr x30, =vectors +-#endif ++ tramp_data_read_var x30, vectors + alternative_if_not ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM +- prfm plil1strm, [x30, #(1b - tramp_vectors)] ++ prfm plil1strm, [x30, #(1b - \vector_start)] + alternative_else_nop_endif ++ + msr vbar_el1, x30 +- add x30, x30, #(1b - tramp_vectors) + isb ++ .else ++ ldr x30, =vectors ++ .endif // \kpti == 1 ++ ++ .if \bhb == BHB_MITIGATION_FW ++ /* ++ * The firmware sequence must appear before the first indirect branch. ++ * i.e. the ret out of tramp_ventry. But it also needs the stack to be ++ * mapped to save/restore the registers the SMC clobbers. ++ */ ++ __mitigate_spectre_bhb_fw ++ .endif // \bhb == BHB_MITIGATION_FW ++ ++ add x30, x30, #(1b - \vector_start + 4) + ret ++.org 1b + 128 // Did we overflow the ventry slot? + .endm + + .macro tramp_exit, regsize = 64 +- adr x30, tramp_vectors ++ tramp_data_read_var x30, this_cpu_vector ++ get_this_cpu_offset x29 ++ ldr x30, [x30, x29] ++ + msr vbar_el1, x30 +- tramp_unmap_kernel x30 ++ ldr lr, [sp, #S_LR] ++ tramp_unmap_kernel x29 + .if \regsize == 64 +- mrs x30, far_el1 ++ mrs x29, far_el1 + .endif ++ add sp, sp, #PT_REGS_SIZE // restore sp + eret + sb + .endm + +- .align 11 +-SYM_CODE_START_NOALIGN(tramp_vectors) ++ .macro generate_tramp_vector, kpti, bhb ++.Lvector_start\@: + .space 0x400 + +- tramp_ventry +- tramp_ventry +- tramp_ventry +- tramp_ventry ++ .rept 4 ++ tramp_ventry .Lvector_start\@, 64, \kpti, \bhb ++ .endr ++ .rept 4 ++ tramp_ventry .Lvector_start\@, 32, \kpti, \bhb ++ .endr ++ .endm + +- tramp_ventry 32 +- tramp_ventry 32 +- tramp_ventry 32 +- tramp_ventry 32 ++#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 ++/* ++ * Exception vectors trampoline. ++ * The order must match __bp_harden_el1_vectors and the ++ * arm64_bp_harden_el1_vectors enum. ++ */ ++ .pushsection ".entry.tramp.text", "ax" ++ .align 11 ++SYM_CODE_START_NOALIGN(tramp_vectors) ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++ generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_LOOP ++ generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_FW ++ generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_INSN ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++ generate_tramp_vector kpti=1, bhb=BHB_MITIGATION_NONE + SYM_CODE_END(tramp_vectors) + + SYM_CODE_START(tramp_exit_native) +@@ -704,12 +774,56 @@ SYM_CODE_END(tramp_exit_compat) + .pushsection ".rodata", "a" + .align PAGE_SHIFT + SYM_DATA_START(__entry_tramp_data_start) ++__entry_tramp_data_vectors: + .quad vectors ++#ifdef CONFIG_ARM_SDE_INTERFACE ++__entry_tramp_data___sdei_asm_handler: ++ .quad __sdei_asm_handler ++#endif /* CONFIG_ARM_SDE_INTERFACE */ ++__entry_tramp_data_this_cpu_vector: ++ .quad this_cpu_vector + SYM_DATA_END(__entry_tramp_data_start) + .popsection // .rodata + #endif /* CONFIG_RANDOMIZE_BASE */ + #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + ++/* ++ * Exception vectors for spectre mitigations on entry from EL1 when ++ * kpti is not in use. ++ */ ++ .macro generate_el1_vector, bhb ++.Lvector_start\@: ++ kernel_ventry 1, t, 64, sync // Synchronous EL1t ++ kernel_ventry 1, t, 64, irq // IRQ EL1t ++ kernel_ventry 1, t, 64, fiq // FIQ EL1h ++ kernel_ventry 1, t, 64, error // Error EL1t ++ ++ kernel_ventry 1, h, 64, sync // Synchronous EL1h ++ kernel_ventry 1, h, 64, irq // IRQ EL1h ++ kernel_ventry 1, h, 64, fiq // FIQ EL1h ++ kernel_ventry 1, h, 64, error // Error EL1h ++ ++ .rept 4 ++ tramp_ventry .Lvector_start\@, 64, 0, \bhb ++ .endr ++ .rept 4 ++ tramp_ventry .Lvector_start\@, 32, 0, \bhb ++ .endr ++ .endm ++ ++/* The order must match tramp_vecs and the arm64_bp_harden_el1_vectors enum. */ ++ .pushsection ".entry.text", "ax" ++ .align 11 ++SYM_CODE_START(__bp_harden_el1_vectors) ++#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY ++ generate_el1_vector bhb=BHB_MITIGATION_LOOP ++ generate_el1_vector bhb=BHB_MITIGATION_FW ++ generate_el1_vector bhb=BHB_MITIGATION_INSN ++#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */ ++SYM_CODE_END(__bp_harden_el1_vectors) ++ .popsection ++ ++ + /* + * Register switch for AArch64. The callee-saved registers need to be saved + * and restored. On entry: +@@ -835,14 +949,7 @@ SYM_CODE_START(__sdei_asm_entry_trampoline) + * Remember whether to unmap the kernel on exit. + */ + 1: str x4, [x1, #(SDEI_EVENT_INTREGS + S_SDEI_TTBR1)] +- +-#ifdef CONFIG_RANDOMIZE_BASE +- adr x4, tramp_vectors + PAGE_SIZE +- add x4, x4, #:lo12:__sdei_asm_trampoline_next_handler +- ldr x4, [x4] +-#else +- ldr x4, =__sdei_asm_handler +-#endif ++ tramp_data_read_var x4, __sdei_asm_handler + br x4 + SYM_CODE_END(__sdei_asm_entry_trampoline) + NOKPROBE(__sdei_asm_entry_trampoline) +@@ -865,13 +972,6 @@ SYM_CODE_END(__sdei_asm_exit_trampoline) + NOKPROBE(__sdei_asm_exit_trampoline) + .ltorg + .popsection // .entry.tramp.text +-#ifdef CONFIG_RANDOMIZE_BASE +-.pushsection ".rodata", "a" +-SYM_DATA_START(__sdei_asm_trampoline_next_handler) +- .quad __sdei_asm_handler +-SYM_DATA_END(__sdei_asm_trampoline_next_handler) +-.popsection // .rodata +-#endif /* CONFIG_RANDOMIZE_BASE */ + #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + + /* +@@ -979,7 +1079,7 @@ alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 + alternative_else_nop_endif + + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +- tramp_alias dst=x5, sym=__sdei_asm_exit_trampoline ++ tramp_alias dst=x5, sym=__sdei_asm_exit_trampoline, tmp=x3 + br x5 + #endif + SYM_CODE_END(__sdei_asm_handler) +diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h +index c96a9a0043bf4..e03e60f9482b4 100644 +--- a/arch/arm64/kernel/image-vars.h ++++ b/arch/arm64/kernel/image-vars.h +@@ -66,6 +66,10 @@ KVM_NVHE_ALIAS(kvm_patch_vector_branch); + KVM_NVHE_ALIAS(kvm_update_va_mask); + KVM_NVHE_ALIAS(kvm_get_kimage_voffset); + KVM_NVHE_ALIAS(kvm_compute_final_ctr_el0); ++KVM_NVHE_ALIAS(spectre_bhb_patch_loop_iter); ++KVM_NVHE_ALIAS(spectre_bhb_patch_loop_mitigation_enable); ++KVM_NVHE_ALIAS(spectre_bhb_patch_wa3); ++KVM_NVHE_ALIAS(spectre_bhb_patch_clearbhb); + + /* Global kernel state accessed by nVHE hyp code. */ + KVM_NVHE_ALIAS(kvm_vgic_global_state); +diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c +index 63634b4d72c15..59c648d518488 100644 +--- a/arch/arm64/kernel/machine_kexec_file.c ++++ b/arch/arm64/kernel/machine_kexec_file.c +@@ -149,6 +149,7 @@ int load_other_segments(struct kimage *image, + initrd_len, cmdline, 0); + if (!dtb) { + pr_err("Preparing for new dtb failed\n"); ++ ret = -EINVAL; + goto out_err; + } + +diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c +index b5ec010c481f3..309a27553c875 100644 +--- a/arch/arm64/kernel/module.c ++++ b/arch/arm64/kernel/module.c +@@ -36,7 +36,7 @@ void *module_alloc(unsigned long size) + module_alloc_end = MODULES_END; + + p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, +- module_alloc_end, gfp_mask, PAGE_KERNEL, 0, ++ module_alloc_end, gfp_mask, PAGE_KERNEL, VM_DEFER_KMEMLEAK, + NUMA_NO_NODE, __builtin_return_address(0)); + + if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && +@@ -58,7 +58,7 @@ void *module_alloc(unsigned long size) + PAGE_KERNEL, 0, NUMA_NO_NODE, + __builtin_return_address(0)); + +- if (p && (kasan_module_alloc(p, size) < 0)) { ++ if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { + vfree(p); + return NULL; + } +diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c +index 4a72c27273097..86d9f20131723 100644 +--- a/arch/arm64/kernel/perf_callchain.c ++++ b/arch/arm64/kernel/perf_callchain.c +@@ -102,7 +102,9 @@ compat_user_backtrace(struct compat_frame_tail __user *tail, + void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); ++ ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* We don't support guest os callchain now */ + return; + } +@@ -147,9 +149,10 @@ static bool callchain_trace(void *data, unsigned long pc) + void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct stackframe frame; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* We don't support guest os callchain now */ + return; + } +@@ -160,18 +163,21 @@ void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + + unsigned long perf_instruction_pointer(struct pt_regs *regs) + { +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) +- return perf_guest_cbs->get_guest_ip(); ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); ++ ++ if (guest_cbs && guest_cbs->is_in_guest()) ++ return guest_cbs->get_guest_ip(); + + return instruction_pointer(regs); + } + + unsigned long perf_misc_flags(struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + int misc = 0; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { +- if (perf_guest_cbs->is_user_mode()) ++ if (guest_cbs && guest_cbs->is_in_guest()) { ++ if (guest_cbs->is_user_mode()) + misc |= PERF_RECORD_MISC_GUEST_USER; + else + misc |= PERF_RECORD_MISC_GUEST_KERNEL; +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 40adb8cdbf5af..23efabcb00b85 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -439,34 +439,26 @@ static void entry_task_switch(struct task_struct *next) + + /* + * ARM erratum 1418040 handling, affecting the 32bit view of CNTVCT. +- * Assuming the virtual counter is enabled at the beginning of times: +- * +- * - disable access when switching from a 64bit task to a 32bit task +- * - enable access when switching from a 32bit task to a 64bit task ++ * Ensure access is disabled when switching to a 32bit task, ensure ++ * access is enabled when switching to a 64bit task. + */ +-static void erratum_1418040_thread_switch(struct task_struct *prev, +- struct task_struct *next) ++static void erratum_1418040_thread_switch(struct task_struct *next) + { +- bool prev32, next32; +- u64 val; +- +- if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040)) +- return; +- +- prev32 = is_compat_thread(task_thread_info(prev)); +- next32 = is_compat_thread(task_thread_info(next)); +- +- if (prev32 == next32 || !this_cpu_has_cap(ARM64_WORKAROUND_1418040)) ++ if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040) || ++ !this_cpu_has_cap(ARM64_WORKAROUND_1418040)) + return; + +- val = read_sysreg(cntkctl_el1); +- +- if (!next32) +- val |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ if (is_compat_thread(task_thread_info(next))) ++ sysreg_clear_set(cntkctl_el1, ARCH_TIMER_USR_VCT_ACCESS_EN, 0); + else +- val &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; ++ sysreg_clear_set(cntkctl_el1, 0, ARCH_TIMER_USR_VCT_ACCESS_EN); ++} + +- write_sysreg(val, cntkctl_el1); ++static void erratum_1418040_new_exec(void) ++{ ++ preempt_disable(); ++ erratum_1418040_thread_switch(current); ++ preempt_enable(); + } + + /* +@@ -501,7 +493,7 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev, + contextidr_thread_switch(next); + entry_task_switch(next); + ssbs_thread_switch(next); +- erratum_1418040_thread_switch(prev, next); ++ erratum_1418040_thread_switch(next); + ptrauth_thread_switch_user(next); + + /* +@@ -613,6 +605,7 @@ void arch_setup_new_exec(void) + current->mm->context.flags = mmflags; + ptrauth_thread_init_user(); + mte_thread_init_user(); ++ erratum_1418040_new_exec(); + + if (task_spec_ssb_noexec(current)) { + arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS, +diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c +index 902e4084c4775..6d45c63c64548 100644 +--- a/arch/arm64/kernel/proton-pack.c ++++ b/arch/arm64/kernel/proton-pack.c +@@ -18,15 +18,18 @@ + */ + + #include <linux/arm-smccc.h> ++#include <linux/bpf.h> + #include <linux/cpu.h> + #include <linux/device.h> + #include <linux/nospec.h> + #include <linux/prctl.h> + #include <linux/sched/task_stack.h> + ++#include <asm/debug-monitors.h> + #include <asm/insn.h> + #include <asm/spectre.h> + #include <asm/traps.h> ++#include <asm/vectors.h> + #include <asm/virt.h> + + /* +@@ -96,14 +99,51 @@ static bool spectre_v2_mitigations_off(void) + return ret; + } + ++static const char *get_bhb_affected_string(enum mitigation_state bhb_state) ++{ ++ switch (bhb_state) { ++ case SPECTRE_UNAFFECTED: ++ return ""; ++ default: ++ case SPECTRE_VULNERABLE: ++ return ", but not BHB"; ++ case SPECTRE_MITIGATED: ++ return ", BHB"; ++ } ++} ++ ++static bool _unprivileged_ebpf_enabled(void) ++{ ++#ifdef CONFIG_BPF_SYSCALL ++ return !sysctl_unprivileged_bpf_disabled; ++#else ++ return false; ++#endif ++} ++ + ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, + char *buf) + { ++ enum mitigation_state bhb_state = arm64_get_spectre_bhb_state(); ++ const char *bhb_str = get_bhb_affected_string(bhb_state); ++ const char *v2_str = "Branch predictor hardening"; ++ + switch (spectre_v2_state) { + case SPECTRE_UNAFFECTED: +- return sprintf(buf, "Not affected\n"); ++ if (bhb_state == SPECTRE_UNAFFECTED) ++ return sprintf(buf, "Not affected\n"); ++ ++ /* ++ * Platforms affected by Spectre-BHB can't report ++ * "Not affected" for Spectre-v2. ++ */ ++ v2_str = "CSV2"; ++ fallthrough; + case SPECTRE_MITIGATED: +- return sprintf(buf, "Mitigation: Branch predictor hardening\n"); ++ if (bhb_state == SPECTRE_MITIGATED && _unprivileged_ebpf_enabled()) ++ return sprintf(buf, "Vulnerable: Unprivileged eBPF enabled\n"); ++ ++ return sprintf(buf, "Mitigation: %s%s\n", v2_str, bhb_str); + case SPECTRE_VULNERABLE: + fallthrough; + default: +@@ -554,9 +594,9 @@ void __init spectre_v4_patch_fw_mitigation_enable(struct alt_instr *alt, + * Patch a NOP in the Spectre-v4 mitigation code with an SMC/HVC instruction + * to call into firmware to adjust the mitigation state. + */ +-void __init spectre_v4_patch_fw_mitigation_conduit(struct alt_instr *alt, +- __le32 *origptr, +- __le32 *updptr, int nr_inst) ++void __init smccc_patch_fw_mitigation_conduit(struct alt_instr *alt, ++ __le32 *origptr, ++ __le32 *updptr, int nr_inst) + { + u32 insn; + +@@ -770,3 +810,344 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) + return -ENODEV; + } + } ++ ++/* ++ * Spectre BHB. ++ * ++ * A CPU is either: ++ * - Mitigated by a branchy loop a CPU specific number of times, and listed ++ * in our "loop mitigated list". ++ * - Mitigated in software by the firmware Spectre v2 call. ++ * - Has the ClearBHB instruction to perform the mitigation. ++ * - Has the 'Exception Clears Branch History Buffer' (ECBHB) feature, so no ++ * software mitigation in the vectors is needed. ++ * - Has CSV2.3, so is unaffected. ++ */ ++static enum mitigation_state spectre_bhb_state; ++ ++enum mitigation_state arm64_get_spectre_bhb_state(void) ++{ ++ return spectre_bhb_state; ++} ++ ++enum bhb_mitigation_bits { ++ BHB_LOOP, ++ BHB_FW, ++ BHB_HW, ++ BHB_INSN, ++}; ++static unsigned long system_bhb_mitigations; ++ ++/* ++ * This must be called with SCOPE_LOCAL_CPU for each type of CPU, before any ++ * SCOPE_SYSTEM call will give the right answer. ++ */ ++u8 spectre_bhb_loop_affected(int scope) ++{ ++ u8 k = 0; ++ static u8 max_bhb_k; ++ ++ if (scope == SCOPE_LOCAL_CPU) { ++ static const struct midr_range spectre_bhb_k32_list[] = { ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), ++ {}, ++ }; ++ static const struct midr_range spectre_bhb_k24_list[] = { ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), ++ MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), ++ {}, ++ }; ++ static const struct midr_range spectre_bhb_k8_list[] = { ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), ++ {}, ++ }; ++ ++ if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) ++ k = 32; ++ else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) ++ k = 24; ++ else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list)) ++ k = 8; ++ ++ max_bhb_k = max(max_bhb_k, k); ++ } else { ++ k = max_bhb_k; ++ } ++ ++ return k; ++} ++ ++static enum mitigation_state spectre_bhb_get_cpu_fw_mitigation_state(void) ++{ ++ int ret; ++ struct arm_smccc_res res; ++ ++ arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_3, &res); ++ ++ ret = res.a0; ++ switch (ret) { ++ case SMCCC_RET_SUCCESS: ++ return SPECTRE_MITIGATED; ++ case SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED: ++ return SPECTRE_UNAFFECTED; ++ default: ++ fallthrough; ++ case SMCCC_RET_NOT_SUPPORTED: ++ return SPECTRE_VULNERABLE; ++ } ++} ++ ++static bool is_spectre_bhb_fw_affected(int scope) ++{ ++ static bool system_affected; ++ enum mitigation_state fw_state; ++ bool has_smccc = arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_NONE; ++ static const struct midr_range spectre_bhb_firmware_mitigated_list[] = { ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), ++ MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), ++ {}, ++ }; ++ bool cpu_in_list = is_midr_in_range_list(read_cpuid_id(), ++ spectre_bhb_firmware_mitigated_list); ++ ++ if (scope != SCOPE_LOCAL_CPU) ++ return system_affected; ++ ++ fw_state = spectre_bhb_get_cpu_fw_mitigation_state(); ++ if (cpu_in_list || (has_smccc && fw_state == SPECTRE_MITIGATED)) { ++ system_affected = true; ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool supports_ecbhb(int scope) ++{ ++ u64 mmfr1; ++ ++ if (scope == SCOPE_LOCAL_CPU) ++ mmfr1 = read_sysreg_s(SYS_ID_AA64MMFR1_EL1); ++ else ++ mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1); ++ ++ return cpuid_feature_extract_unsigned_field(mmfr1, ++ ID_AA64MMFR1_ECBHB_SHIFT); ++} ++ ++bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, ++ int scope) ++{ ++ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); ++ ++ if (supports_csv2p3(scope)) ++ return false; ++ ++ if (supports_clearbhb(scope)) ++ return true; ++ ++ if (spectre_bhb_loop_affected(scope)) ++ return true; ++ ++ if (is_spectre_bhb_fw_affected(scope)) ++ return true; ++ ++ return false; ++} ++ ++static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) ++{ ++ const char *v = arm64_get_bp_hardening_vector(slot); ++ ++ if (slot < 0) ++ return; ++ ++ __this_cpu_write(this_cpu_vector, v); ++ ++ /* ++ * When KPTI is in use, the vectors are switched when exiting to ++ * user-space. ++ */ ++ if (arm64_kernel_unmapped_at_el0()) ++ return; ++ ++ write_sysreg(v, vbar_el1); ++ isb(); ++} ++ ++void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) ++{ ++ bp_hardening_cb_t cpu_cb; ++ enum mitigation_state fw_state, state = SPECTRE_VULNERABLE; ++ struct bp_hardening_data *data = this_cpu_ptr(&bp_hardening_data); ++ ++ if (!is_spectre_bhb_affected(entry, SCOPE_LOCAL_CPU)) ++ return; ++ ++ if (arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE) { ++ /* No point mitigating Spectre-BHB alone. */ ++ } else if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY)) { ++ pr_info_once("spectre-bhb mitigation disabled by compile time option\n"); ++ } else if (cpu_mitigations_off()) { ++ pr_info_once("spectre-bhb mitigation disabled by command line option\n"); ++ } else if (supports_ecbhb(SCOPE_LOCAL_CPU)) { ++ state = SPECTRE_MITIGATED; ++ set_bit(BHB_HW, &system_bhb_mitigations); ++ } else if (supports_clearbhb(SCOPE_LOCAL_CPU)) { ++ /* ++ * Ensure KVM uses the indirect vector which will have ClearBHB ++ * added. ++ */ ++ if (!data->slot) ++ data->slot = HYP_VECTOR_INDIRECT; ++ ++ this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN); ++ state = SPECTRE_MITIGATED; ++ set_bit(BHB_INSN, &system_bhb_mitigations); ++ } else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) { ++ /* ++ * Ensure KVM uses the indirect vector which will have the ++ * branchy-loop added. A57/A72-r0 will already have selected ++ * the spectre-indirect vector, which is sufficient for BHB ++ * too. ++ */ ++ if (!data->slot) ++ data->slot = HYP_VECTOR_INDIRECT; ++ ++ this_cpu_set_vectors(EL1_VECTOR_BHB_LOOP); ++ state = SPECTRE_MITIGATED; ++ set_bit(BHB_LOOP, &system_bhb_mitigations); ++ } else if (is_spectre_bhb_fw_affected(SCOPE_LOCAL_CPU)) { ++ fw_state = spectre_bhb_get_cpu_fw_mitigation_state(); ++ if (fw_state == SPECTRE_MITIGATED) { ++ /* ++ * Ensure KVM uses one of the spectre bp_hardening ++ * vectors. The indirect vector doesn't include the EL3 ++ * call, so needs upgrading to ++ * HYP_VECTOR_SPECTRE_INDIRECT. ++ */ ++ if (!data->slot || data->slot == HYP_VECTOR_INDIRECT) ++ data->slot += 1; ++ ++ this_cpu_set_vectors(EL1_VECTOR_BHB_FW); ++ ++ /* ++ * The WA3 call in the vectors supersedes the WA1 call ++ * made during context-switch. Uninstall any firmware ++ * bp_hardening callback. ++ */ ++ cpu_cb = spectre_v2_get_sw_mitigation_cb(); ++ if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb) ++ __this_cpu_write(bp_hardening_data.fn, NULL); ++ ++ state = SPECTRE_MITIGATED; ++ set_bit(BHB_FW, &system_bhb_mitigations); ++ } ++ } ++ ++ update_mitigation_state(&spectre_bhb_state, state); ++} ++ ++/* Patched to NOP when enabled */ ++void noinstr spectre_bhb_patch_loop_mitigation_enable(struct alt_instr *alt, ++ __le32 *origptr, ++ __le32 *updptr, int nr_inst) ++{ ++ BUG_ON(nr_inst != 1); ++ ++ if (test_bit(BHB_LOOP, &system_bhb_mitigations)) ++ *updptr++ = cpu_to_le32(aarch64_insn_gen_nop()); ++} ++ ++/* Patched to NOP when enabled */ ++void noinstr spectre_bhb_patch_fw_mitigation_enabled(struct alt_instr *alt, ++ __le32 *origptr, ++ __le32 *updptr, int nr_inst) ++{ ++ BUG_ON(nr_inst != 1); ++ ++ if (test_bit(BHB_FW, &system_bhb_mitigations)) ++ *updptr++ = cpu_to_le32(aarch64_insn_gen_nop()); ++} ++ ++/* Patched to correct the immediate */ ++void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst) ++{ ++ u8 rd; ++ u32 insn; ++ u16 loop_count = spectre_bhb_loop_affected(SCOPE_SYSTEM); ++ ++ BUG_ON(nr_inst != 1); /* MOV -> MOV */ ++ ++ if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY)) ++ return; ++ ++ insn = le32_to_cpu(*origptr); ++ rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn); ++ insn = aarch64_insn_gen_movewide(rd, loop_count, 0, ++ AARCH64_INSN_VARIANT_64BIT, ++ AARCH64_INSN_MOVEWIDE_ZERO); ++ *updptr++ = cpu_to_le32(insn); ++} ++ ++/* Patched to mov WA3 when supported */ ++void noinstr spectre_bhb_patch_wa3(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst) ++{ ++ u8 rd; ++ u32 insn; ++ ++ BUG_ON(nr_inst != 1); /* MOV -> MOV */ ++ ++ if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY) || ++ !test_bit(BHB_FW, &system_bhb_mitigations)) ++ return; ++ ++ insn = le32_to_cpu(*origptr); ++ rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn); ++ ++ insn = aarch64_insn_gen_logical_immediate(AARCH64_INSN_LOGIC_ORR, ++ AARCH64_INSN_VARIANT_32BIT, ++ AARCH64_INSN_REG_ZR, rd, ++ ARM_SMCCC_ARCH_WORKAROUND_3); ++ if (WARN_ON_ONCE(insn == AARCH64_BREAK_FAULT)) ++ return; ++ ++ *updptr++ = cpu_to_le32(insn); ++} ++ ++/* Patched to NOP when not supported */ ++void __init spectre_bhb_patch_clearbhb(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst) ++{ ++ BUG_ON(nr_inst != 2); ++ ++ if (test_bit(BHB_INSN, &system_bhb_mitigations)) ++ return; ++ ++ *updptr++ = cpu_to_le32(aarch64_insn_gen_nop()); ++ *updptr++ = cpu_to_le32(aarch64_insn_gen_nop()); ++} ++ ++#ifdef CONFIG_BPF_SYSCALL ++#define EBPF_WARN "Unprivileged eBPF is enabled, data leaks possible via Spectre v2 BHB attacks!\n" ++void unpriv_ebpf_notify(int new_state) ++{ ++ if (spectre_v2_state == SPECTRE_VULNERABLE || ++ spectre_bhb_state != SPECTRE_MITIGATED) ++ return; ++ ++ if (!new_state) ++ pr_err("WARNING: %s", EBPF_WARN); ++} ++#endif +diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c +index 8982a2b78acfc..3b8dc538a4c42 100644 +--- a/arch/arm64/kernel/stacktrace.c ++++ b/arch/arm64/kernel/stacktrace.c +@@ -33,7 +33,7 @@ + */ + + +-void start_backtrace(struct stackframe *frame, unsigned long fp, ++notrace void start_backtrace(struct stackframe *frame, unsigned long fp, + unsigned long pc) + { + frame->fp = fp; +@@ -55,6 +55,7 @@ void start_backtrace(struct stackframe *frame, unsigned long fp, + frame->prev_fp = 0; + frame->prev_type = STACK_TYPE_UNKNOWN; + } ++NOKPROBE_SYMBOL(start_backtrace); + + /* + * Unwind from one frame record (A) to the next frame record (B). +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index b03e383d944ab..fe0cd0568813e 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -988,7 +988,7 @@ static struct break_hook bug_break_hook = { + static int reserved_fault_handler(struct pt_regs *regs, unsigned int esr) + { + pr_err("%s generated an invalid instruction at %pS!\n", +- in_bpf_jit(regs) ? "BPF JIT" : "Kernel text patching", ++ "Kernel text patching", + (void *)instruction_pointer(regs)); + + /* We cannot handle this */ +diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile +index 3dba0c4f8f42b..3514269ac75fb 100644 +--- a/arch/arm64/kernel/vdso32/Makefile ++++ b/arch/arm64/kernel/vdso32/Makefile +@@ -10,18 +10,15 @@ include $(srctree)/lib/vdso/Makefile + + # Same as cc-*option, but using CC_COMPAT instead of CC + ifeq ($(CONFIG_CC_IS_CLANG), y) +-CC_COMPAT_CLANG_FLAGS := --target=$(notdir $(CROSS_COMPILE_COMPAT:%-=%)) +- + CC_COMPAT ?= $(CC) +-CC_COMPAT += $(CC_COMPAT_CLANG_FLAGS) +- +-ifneq ($(LLVM),) +-LD_COMPAT ?= $(LD) ++CC_COMPAT += --target=arm-linux-gnueabi + else +-LD_COMPAT ?= $(CROSS_COMPILE_COMPAT)ld ++CC_COMPAT ?= $(CROSS_COMPILE_COMPAT)gcc + endif ++ ++ifeq ($(CONFIG_LD_IS_LLD), y) ++LD_COMPAT ?= $(LD) + else +-CC_COMPAT ?= $(CROSS_COMPILE_COMPAT)gcc + LD_COMPAT ?= $(CROSS_COMPILE_COMPAT)ld + endif + +@@ -40,16 +37,13 @@ cc32-as-instr = $(call try-run,\ + # As a result we set our own flags here. + + # KBUILD_CPPFLAGS and NOSTDINC_FLAGS from top-level Makefile +-VDSO_CPPFLAGS := -DBUILD_VDSO -D__KERNEL__ -nostdinc -isystem $(shell $(CC_COMPAT) -print-file-name=include) ++VDSO_CPPFLAGS := -DBUILD_VDSO -D__KERNEL__ -nostdinc ++VDSO_CPPFLAGS += -isystem $(shell $(CC_COMPAT) -print-file-name=include 2>/dev/null) + VDSO_CPPFLAGS += $(LINUXINCLUDE) + + # Common C and assembly flags + # From top-level Makefile + VDSO_CAFLAGS := $(VDSO_CPPFLAGS) +-ifneq ($(shell $(CC_COMPAT) --version 2>&1 | head -n 1 | grep clang),) +-VDSO_CAFLAGS += --target=$(notdir $(CROSS_COMPILE_COMPAT:%-=%)) +-endif +- + VDSO_CAFLAGS += $(call cc32-option,-fno-PIE) + ifdef CONFIG_DEBUG_INFO + VDSO_CAFLAGS += -g +diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S +index f6b1a88245db2..184abd7c4206e 100644 +--- a/arch/arm64/kernel/vmlinux.lds.S ++++ b/arch/arm64/kernel/vmlinux.lds.S +@@ -330,7 +330,7 @@ ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1)) + <= SZ_4K, "Hibernate exit text too big or misaligned") + #endif + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +-ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE, ++ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE, + "Entry trampoline text too big") + #endif + #ifdef CONFIG_KVM +diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c +index fe102cd2e5183..0b2f684cd8ca5 100644 +--- a/arch/arm64/kvm/arm.c ++++ b/arch/arm64/kvm/arm.c +@@ -755,6 +755,24 @@ static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret) + xfer_to_guest_mode_work_pending(); + } + ++/* ++ * Actually run the vCPU, entering an RCU extended quiescent state (EQS) while ++ * the vCPU is running. ++ * ++ * This must be noinstr as instrumentation may make use of RCU, and this is not ++ * safe during the EQS. ++ */ ++static int noinstr kvm_arm_vcpu_enter_exit(struct kvm_vcpu *vcpu) ++{ ++ int ret; ++ ++ guest_state_enter_irqoff(); ++ ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu); ++ guest_state_exit_irqoff(); ++ ++ return ret; ++} ++ + /** + * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code + * @vcpu: The VCPU pointer +@@ -845,9 +863,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) + * Enter the guest + */ + trace_kvm_entry(*vcpu_pc(vcpu)); +- guest_enter_irqoff(); ++ guest_timing_enter_irqoff(); + +- ret = kvm_call_hyp_ret(__kvm_vcpu_run, vcpu); ++ ret = kvm_arm_vcpu_enter_exit(vcpu); + + vcpu->mode = OUTSIDE_GUEST_MODE; + vcpu->stat.exits++; +@@ -882,26 +900,23 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) + kvm_arch_vcpu_ctxsync_fp(vcpu); + + /* +- * We may have taken a host interrupt in HYP mode (ie +- * while executing the guest). This interrupt is still +- * pending, as we haven't serviced it yet! ++ * We must ensure that any pending interrupts are taken before ++ * we exit guest timing so that timer ticks are accounted as ++ * guest time. Transiently unmask interrupts so that any ++ * pending interrupts are taken. + * +- * We're now back in SVC mode, with interrupts +- * disabled. Enabling the interrupts now will have +- * the effect of taking the interrupt again, in SVC +- * mode this time. ++ * Per ARM DDI 0487G.b section D1.13.4, an ISB (or other ++ * context synchronization event) is necessary to ensure that ++ * pending interrupts are taken. + */ + local_irq_enable(); ++ isb(); ++ local_irq_disable(); ++ ++ guest_timing_exit_irqoff(); ++ ++ local_irq_enable(); + +- /* +- * We do local_irq_enable() before calling guest_exit() so +- * that if a timer interrupt hits while running the guest we +- * account that tick as being spent in the guest. We enable +- * preemption after calling guest_exit() so that if we get +- * preempted we make sure ticks after that is not counted as +- * guest time. +- */ +- guest_exit(); + trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); + + /* Exit types that need handling before we can be preempted */ +@@ -1443,10 +1458,7 @@ static int kvm_init_vector_slots(void) + base = kern_hyp_va(kvm_ksym_ref(__bp_harden_hyp_vecs)); + kvm_init_vector_slot(base, HYP_VECTOR_SPECTRE_DIRECT); + +- if (!cpus_have_const_cap(ARM64_SPECTRE_V3A)) +- return 0; +- +- if (!has_vhe()) { ++ if (kvm_system_needs_idmapped_vectors() && !has_vhe()) { + err = create_hyp_exec_mappings(__pa_symbol(__bp_harden_hyp_vecs), + __BP_HARDEN_HYP_VECS_SZ, &base); + if (err) +@@ -1971,9 +1983,25 @@ out_err: + return err; + } + +-static void _kvm_host_prot_finalize(void *discard) ++static void _kvm_host_prot_finalize(void *arg) ++{ ++ int *err = arg; ++ ++ if (WARN_ON(kvm_call_hyp_nvhe(__pkvm_prot_finalize))) ++ WRITE_ONCE(*err, -EINVAL); ++} ++ ++static int pkvm_drop_host_privileges(void) + { +- WARN_ON(kvm_call_hyp_nvhe(__pkvm_prot_finalize)); ++ int ret = 0; ++ ++ /* ++ * Flip the static key upfront as that may no longer be possible ++ * once the host stage 2 is installed. ++ */ ++ static_branch_enable(&kvm_protected_mode_initialized); ++ on_each_cpu(_kvm_host_prot_finalize, &ret, 1); ++ return ret; + } + + static int finalize_hyp_mode(void) +@@ -1987,15 +2015,7 @@ static int finalize_hyp_mode(void) + * None of other sections should ever be introspected. + */ + kmemleak_free_part(__hyp_bss_start, __hyp_bss_end - __hyp_bss_start); +- +- /* +- * Flip the static key upfront as that may no longer be possible +- * once the host stage 2 is installed. +- */ +- static_branch_enable(&kvm_protected_mode_initialized); +- on_each_cpu(_kvm_host_prot_finalize, NULL, 1); +- +- return 0; ++ return pkvm_drop_host_privileges(); + } + + struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr) +diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c +index 275a27368a04c..a5ab5215094ee 100644 +--- a/arch/arm64/kvm/handle_exit.c ++++ b/arch/arm64/kvm/handle_exit.c +@@ -226,6 +226,14 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index) + { + struct kvm_run *run = vcpu->run; + ++ if (ARM_SERROR_PENDING(exception_index)) { ++ /* ++ * The SError is handled by handle_exit_early(). If the guest ++ * survives it will re-execute the original instruction. ++ */ ++ return 1; ++ } ++ + exception_index = ARM_EXCEPTION_CODE(exception_index); + + switch (exception_index) { +diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c +index 0418399e0a201..c5d0097154020 100644 +--- a/arch/arm64/kvm/hyp/exception.c ++++ b/arch/arm64/kvm/hyp/exception.c +@@ -38,7 +38,10 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) + + static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, u64 val) + { +- write_sysreg_el1(val, SYS_SPSR); ++ if (has_vhe()) ++ write_sysreg_el1(val, SYS_SPSR); ++ else ++ __vcpu_sys_reg(vcpu, SPSR_EL1) = val; + } + + static void __vcpu_write_spsr_abt(struct kvm_vcpu *vcpu, u64 val) +diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S +index 9aa9b73475c95..7839d075729b1 100644 +--- a/arch/arm64/kvm/hyp/hyp-entry.S ++++ b/arch/arm64/kvm/hyp/hyp-entry.S +@@ -44,7 +44,7 @@ + el1_sync: // Guest trapped into EL2 + + mrs x0, esr_el2 +- lsr x0, x0, #ESR_ELx_EC_SHIFT ++ ubfx x0, x0, #ESR_ELx_EC_SHIFT, #ESR_ELx_EC_WIDTH + cmp x0, #ESR_ELx_EC_HVC64 + ccmp x0, #ESR_ELx_EC_HVC32, #4, ne + b.ne el1_trap +@@ -62,6 +62,10 @@ el1_sync: // Guest trapped into EL2 + /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ + eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \ + ARM_SMCCC_ARCH_WORKAROUND_2) ++ cbz w1, wa_epilogue ++ ++ eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_2 ^ \ ++ ARM_SMCCC_ARCH_WORKAROUND_3) + cbnz w1, el1_trap + + wa_epilogue: +@@ -192,7 +196,10 @@ SYM_CODE_END(__kvm_hyp_vector) + sub sp, sp, #(8 * 4) + stp x2, x3, [sp, #(8 * 0)] + stp x0, x1, [sp, #(8 * 2)] ++ alternative_cb spectre_bhb_patch_wa3 ++ /* Patched to mov WA3 when supported */ + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 ++ alternative_cb_end + smc #0 + ldp x2, x3, [sp, #(8 * 0)] + add sp, sp, #(8 * 2) +@@ -205,6 +212,8 @@ SYM_CODE_END(__kvm_hyp_vector) + spectrev2_smccc_wa1_smc + .else + stp x0, x1, [sp, #-16]! ++ mitigate_spectre_bhb_loop x0 ++ mitigate_spectre_bhb_clear_insn + .endif + .if \indirect != 0 + alternative_cb kvm_patch_vector_branch +diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h +index a0e78a6027be0..ecd41844eda09 100644 +--- a/arch/arm64/kvm/hyp/include/hyp/switch.h ++++ b/arch/arm64/kvm/hyp/include/hyp/switch.h +@@ -416,10 +416,17 @@ static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) + */ + static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) + { ++ /* ++ * Save PSTATE early so that we can evaluate the vcpu mode ++ * early on. ++ */ ++ vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR); ++ + if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) + vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); + +- if (ARM_SERROR_PENDING(*exit_code)) { ++ if (ARM_SERROR_PENDING(*exit_code) && ++ ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) { + u8 esr_ec = kvm_vcpu_trap_get_class(vcpu); + + /* +diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +index de7e14c862e6c..7ecca8b078519 100644 +--- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h ++++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +@@ -70,7 +70,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) + static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) + { + ctxt->regs.pc = read_sysreg_el2(SYS_ELR); +- ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); ++ /* ++ * Guest PSTATE gets saved at guest fixup time in all ++ * cases. We still need to handle the nVHE host side here. ++ */ ++ if (!has_vhe() && ctxt->__hyp_running_vcpu) ++ ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); + + if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) + ctxt_sys_reg(ctxt, DISR_EL1) = read_sysreg_s(SYS_VDISR_EL2); +diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S +index 4b652ffb591d4..d310d2b2c8b40 100644 +--- a/arch/arm64/kvm/hyp/nvhe/host.S ++++ b/arch/arm64/kvm/hyp/nvhe/host.S +@@ -115,7 +115,7 @@ SYM_FUNC_END(__hyp_do_panic) + .L__vect_start\@: + stp x0, x1, [sp, #-16]! + mrs x0, esr_el2 +- lsr x0, x0, #ESR_ELx_EC_SHIFT ++ ubfx x0, x0, #ESR_ELx_EC_SHIFT, #ESR_ELx_EC_WIDTH + cmp x0, #ESR_ELx_EC_HVC64 + b.ne __host_exit + +diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c +index 2fabeceb889a9..5146fb1705054 100644 +--- a/arch/arm64/kvm/hyp/nvhe/mm.c ++++ b/arch/arm64/kvm/hyp/nvhe/mm.c +@@ -146,8 +146,10 @@ int hyp_map_vectors(void) + phys_addr_t phys; + void *bp_base; + +- if (!cpus_have_const_cap(ARM64_SPECTRE_V3A)) ++ if (!kvm_system_needs_idmapped_vectors()) { ++ __hyp_bp_vect_base = __bp_harden_hyp_vecs; + return 0; ++ } + + phys = __hyp_pa(__bp_harden_hyp_vecs); + bp_base = (void *)__pkvm_create_private_mapping(phys, +diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c +index 57c27846320f4..58ad9c5ba3112 100644 +--- a/arch/arm64/kvm/hyp/nvhe/setup.c ++++ b/arch/arm64/kvm/hyp/nvhe/setup.c +@@ -177,7 +177,7 @@ static int finalize_host_mappings_walker(u64 addr, u64 end, u32 level, + + phys = kvm_pte_to_phys(pte); + if (!addr_is_memory(phys)) +- return 0; ++ return -EINVAL; + + /* + * Adjust the host stage-2 mappings to match the ownership attributes +@@ -206,8 +206,18 @@ static int finalize_host_mappings(void) + .cb = finalize_host_mappings_walker, + .flags = KVM_PGTABLE_WALK_LEAF, + }; ++ int i, ret; ++ ++ for (i = 0; i < hyp_memblock_nr; i++) { ++ struct memblock_region *reg = &hyp_memory[i]; ++ u64 start = (u64)hyp_phys_to_virt(reg->base); ++ ++ ret = kvm_pgtable_walk(&pkvm_pgtable, start, reg->size, &walker); ++ if (ret) ++ return ret; ++ } + +- return kvm_pgtable_walk(&pkvm_pgtable, 0, BIT(pkvm_pgtable.ia_bits), &walker); ++ return 0; + } + + void __noreturn __pkvm_init_finalise(void) +diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c +index f8ceebe4982eb..4c77ff556f0ae 100644 +--- a/arch/arm64/kvm/hyp/pgtable.c ++++ b/arch/arm64/kvm/hyp/pgtable.c +@@ -921,13 +921,9 @@ static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep, + */ + stage2_put_pte(ptep, mmu, addr, level, mm_ops); + +- if (need_flush) { +- kvm_pte_t *pte_follow = kvm_pte_follow(pte, mm_ops); +- +- dcache_clean_inval_poc((unsigned long)pte_follow, +- (unsigned long)pte_follow + +- kvm_granule_size(level)); +- } ++ if (need_flush && mm_ops->dcache_clean_inval_poc) ++ mm_ops->dcache_clean_inval_poc(kvm_pte_follow(pte, mm_ops), ++ kvm_granule_size(level)); + + if (childp) + mm_ops->put_page(childp); +@@ -1089,15 +1085,13 @@ static int stage2_flush_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep, + struct kvm_pgtable *pgt = arg; + struct kvm_pgtable_mm_ops *mm_ops = pgt->mm_ops; + kvm_pte_t pte = *ptep; +- kvm_pte_t *pte_follow; + + if (!kvm_pte_valid(pte) || !stage2_pte_cacheable(pgt, pte)) + return 0; + +- pte_follow = kvm_pte_follow(pte, mm_ops); +- dcache_clean_inval_poc((unsigned long)pte_follow, +- (unsigned long)pte_follow + +- kvm_granule_size(level)); ++ if (mm_ops->dcache_clean_inval_poc) ++ mm_ops->dcache_clean_inval_poc(kvm_pte_follow(pte, mm_ops), ++ kvm_granule_size(level)); + return 0; + } + +diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c +index ded2c66675f06..d88d3c143a735 100644 +--- a/arch/arm64/kvm/hyp/vhe/switch.c ++++ b/arch/arm64/kvm/hyp/vhe/switch.c +@@ -10,6 +10,7 @@ + #include <linux/kvm_host.h> + #include <linux/types.h> + #include <linux/jump_label.h> ++#include <linux/percpu.h> + #include <uapi/linux/psci.h> + + #include <kvm/arm_psci.h> +@@ -25,6 +26,7 @@ + #include <asm/debug-monitors.h> + #include <asm/processor.h> + #include <asm/thread_info.h> ++#include <asm/vectors.h> + + /* VHE specific context */ + DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); +@@ -68,7 +70,7 @@ NOKPROBE_SYMBOL(__activate_traps); + + static void __deactivate_traps(struct kvm_vcpu *vcpu) + { +- extern char vectors[]; /* kernel exception vectors */ ++ const char *host_vectors = vectors; + + ___deactivate_traps(vcpu); + +@@ -82,7 +84,10 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) + asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); + + write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1); +- write_sysreg(vectors, vbar_el1); ++ ++ if (!arm64_kernel_unmapped_at_el0()) ++ host_vectors = __this_cpu_read(this_cpu_vector); ++ write_sysreg(host_vectors, vbar_el1); + } + NOKPROBE_SYMBOL(__deactivate_traps); + +diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c +index 30da78f72b3b3..202b8c455724b 100644 +--- a/arch/arm64/kvm/hypercalls.c ++++ b/arch/arm64/kvm/hypercalls.c +@@ -107,6 +107,18 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + break; + } + break; ++ case ARM_SMCCC_ARCH_WORKAROUND_3: ++ switch (arm64_get_spectre_bhb_state()) { ++ case SPECTRE_VULNERABLE: ++ break; ++ case SPECTRE_MITIGATED: ++ val[0] = SMCCC_RET_SUCCESS; ++ break; ++ case SPECTRE_UNAFFECTED: ++ val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; ++ break; ++ } ++ break; + case ARM_SMCCC_HV_PV_TIME_FEATURES: + val[0] = SMCCC_RET_SUCCESS; + break; +diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c +index 74c47d4202534..44efe12dfc066 100644 +--- a/arch/arm64/kvm/psci.c ++++ b/arch/arm64/kvm/psci.c +@@ -406,7 +406,7 @@ int kvm_psci_call(struct kvm_vcpu *vcpu) + + int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu) + { +- return 3; /* PSCI version and two workaround registers */ ++ return 4; /* PSCI version and three workaround registers */ + } + + int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) +@@ -420,6 +420,9 @@ int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) + if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, uindices++)) + return -EFAULT; + ++ if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, uindices++)) ++ return -EFAULT; ++ + return 0; + } + +@@ -459,6 +462,17 @@ static int get_kernel_wa_level(u64 regid) + case SPECTRE_VULNERABLE: + return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; + } ++ break; ++ case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: ++ switch (arm64_get_spectre_bhb_state()) { ++ case SPECTRE_VULNERABLE: ++ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; ++ case SPECTRE_MITIGATED: ++ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL; ++ case SPECTRE_UNAFFECTED: ++ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED; ++ } ++ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; + } + + return -EINVAL; +@@ -475,6 +489,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) + break; + case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: + case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: ++ case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: + val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK; + break; + default: +@@ -520,6 +535,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) + } + + case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: ++ case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: + if (val & ~KVM_REG_FEATURE_LEVEL_MASK) + return -EINVAL; + +diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c +index 1d46e185f31e1..7c18e429b4493 100644 +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -1518,7 +1518,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { + /* CRm=6 */ + ID_SANITISED(ID_AA64ISAR0_EL1), + ID_SANITISED(ID_AA64ISAR1_EL1), +- ID_UNALLOCATED(6,2), ++ ID_SANITISED(ID_AA64ISAR2_EL1), + ID_UNALLOCATED(6,3), + ID_UNALLOCATED(6,4), + ID_UNALLOCATED(6,5), +diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c +index 48c6067fc5ecb..f972992682746 100644 +--- a/arch/arm64/kvm/vgic/vgic-mmio.c ++++ b/arch/arm64/kvm/vgic/vgic-mmio.c +@@ -248,6 +248,8 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, + IRQCHIP_STATE_PENDING, + &val); + WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); ++ } else if (vgic_irq_is_mapped_level(irq)) { ++ val = vgic_get_phys_line_level(irq); + } else { + val = irq_is_pending(irq); + } +diff --git a/arch/arm64/lib/clear_page.S b/arch/arm64/lib/clear_page.S +index b84b179edba3a..1fd5d790ab800 100644 +--- a/arch/arm64/lib/clear_page.S ++++ b/arch/arm64/lib/clear_page.S +@@ -16,6 +16,7 @@ + */ + SYM_FUNC_START_PI(clear_page) + mrs x1, dczid_el0 ++ tbnz x1, #4, 2f /* Branch if DC ZVA is prohibited */ + and w1, w1, #0xf + mov x2, #4 + lsl x1, x2, x1 +@@ -25,5 +26,14 @@ SYM_FUNC_START_PI(clear_page) + tst x0, #(PAGE_SIZE - 1) + b.ne 1b + ret ++ ++2: stnp xzr, xzr, [x0] ++ stnp xzr, xzr, [x0, #16] ++ stnp xzr, xzr, [x0, #32] ++ stnp xzr, xzr, [x0, #48] ++ add x0, x0, #64 ++ tst x0, #(PAGE_SIZE - 1) ++ b.ne 2b ++ ret + SYM_FUNC_END_PI(clear_page) + EXPORT_SYMBOL(clear_page) +diff --git a/arch/arm64/lib/mte.S b/arch/arm64/lib/mte.S +index e83643b3995f4..f531dcb95174a 100644 +--- a/arch/arm64/lib/mte.S ++++ b/arch/arm64/lib/mte.S +@@ -43,17 +43,23 @@ SYM_FUNC_END(mte_clear_page_tags) + * x0 - address to the beginning of the page + */ + SYM_FUNC_START(mte_zero_clear_page_tags) ++ and x0, x0, #(1 << MTE_TAG_SHIFT) - 1 // clear the tag + mrs x1, dczid_el0 ++ tbnz x1, #4, 2f // Branch if DC GZVA is prohibited + and w1, w1, #0xf + mov x2, #4 + lsl x1, x2, x1 +- and x0, x0, #(1 << MTE_TAG_SHIFT) - 1 // clear the tag + + 1: dc gzva, x0 + add x0, x0, x1 + tst x0, #(PAGE_SIZE - 1) + b.ne 1b + ret ++ ++2: stz2g x0, [x0], #(MTE_GRANULE_SIZE * 2) ++ tst x0, #(PAGE_SIZE - 1) ++ b.ne 2b ++ ret + SYM_FUNC_END(mte_zero_clear_page_tags) + + /* +diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c +index aa0060178343a..60a8b6a8a42b5 100644 +--- a/arch/arm64/mm/extable.c ++++ b/arch/arm64/mm/extable.c +@@ -9,14 +9,19 @@ + int fixup_exception(struct pt_regs *regs) + { + const struct exception_table_entry *fixup; ++ unsigned long addr; + +- fixup = search_exception_tables(instruction_pointer(regs)); +- if (!fixup) +- return 0; ++ addr = instruction_pointer(regs); + +- if (in_bpf_jit(regs)) ++ /* Search the BPF tables first, these are formatted differently */ ++ fixup = search_bpf_extables(addr); ++ if (fixup) + return arm64_bpf_fixup_exception(fixup, regs); + ++ fixup = search_exception_tables(addr); ++ if (!fixup) ++ return 0; ++ + regs->pc = (unsigned long)&fixup->fixup + fixup->fixup; + return 1; + } +diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c +index cfd9deb347c38..9d03806316905 100644 +--- a/arch/arm64/mm/mmu.c ++++ b/arch/arm64/mm/mmu.c +@@ -616,6 +616,8 @@ early_param("rodata", parse_rodata); + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + static int __init map_entry_trampoline(void) + { ++ int i; ++ + pgprot_t prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC; + phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start); + +@@ -624,11 +626,15 @@ static int __init map_entry_trampoline(void) + + /* Map only the text into the trampoline page table */ + memset(tramp_pg_dir, 0, PGD_SIZE); +- __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE, +- prot, __pgd_pgtable_alloc, 0); ++ __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, ++ entry_tramp_text_size(), prot, ++ __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS); + + /* Map both the text and data into the kernel page table */ +- __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot); ++ for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++) ++ __set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i, ++ pa_start + i * PAGE_SIZE, prot); ++ + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { + extern char __entry_tramp_data_start[]; + +@@ -1499,6 +1505,11 @@ int arch_add_memory(int nid, u64 start, u64 size, + if (ret) + __remove_pgd_mapping(swapper_pg_dir, + __phys_to_virt(start), size); ++ else { ++ max_pfn = PFN_UP(start + size); ++ max_low_pfn = max_pfn; ++ } ++ + return ret; + } + +diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c +index 1c403536c9bb0..9bc4066c5bf33 100644 +--- a/arch/arm64/mm/ptdump.c ++++ b/arch/arm64/mm/ptdump.c +@@ -41,8 +41,6 @@ static struct addr_marker address_markers[] = { + { 0 /* KASAN_SHADOW_START */, "Kasan shadow start" }, + { KASAN_SHADOW_END, "Kasan shadow end" }, + #endif +- { BPF_JIT_REGION_START, "BPF start" }, +- { BPF_JIT_REGION_END, "BPF end" }, + { MODULES_VADDR, "Modules start" }, + { MODULES_END, "Modules end" }, + { VMALLOC_START, "vmalloc() area" }, +diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c +index 803e7773fa869..465c44d0c72fc 100644 +--- a/arch/arm64/net/bpf_jit_comp.c ++++ b/arch/arm64/net/bpf_jit_comp.c +@@ -1138,15 +1138,12 @@ out: + + u64 bpf_jit_alloc_exec_limit(void) + { +- return BPF_JIT_REGION_SIZE; ++ return VMALLOC_END - VMALLOC_START; + } + + void *bpf_jit_alloc_exec(unsigned long size) + { +- return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START, +- BPF_JIT_REGION_END, GFP_KERNEL, +- PAGE_KERNEL, 0, NUMA_NO_NODE, +- __builtin_return_address(0)); ++ return vmalloc(size); + } + + void bpf_jit_free_exec(void *addr) +diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps +index 49305c2e6dfd3..b71c6cbb23095 100644 +--- a/arch/arm64/tools/cpucaps ++++ b/arch/arm64/tools/cpucaps +@@ -42,6 +42,7 @@ MTE + SPECTRE_V2 + SPECTRE_V3A + SPECTRE_V4 ++SPECTRE_BHB + SSBS + SVE + UNMAP_KERNEL_AT_EL0 +diff --git a/arch/csky/kernel/perf_callchain.c b/arch/csky/kernel/perf_callchain.c +index ab55e98ee8f62..35318a635a5fa 100644 +--- a/arch/csky/kernel/perf_callchain.c ++++ b/arch/csky/kernel/perf_callchain.c +@@ -86,10 +86,11 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry, + void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + unsigned long fp = 0; + + /* C-SKY does not support virtualization. */ +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) ++ if (guest_cbs && guest_cbs->is_in_guest()) + return; + + fp = regs->regs[4]; +@@ -110,10 +111,11 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct stackframe fr; + + /* C-SKY does not support virtualization. */ +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + pr_warn("C-SKY does not support perf in guest mode!"); + return; + } +diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c +index e5fbf8653a215..2020af88b6361 100644 +--- a/arch/csky/kernel/traps.c ++++ b/arch/csky/kernel/traps.c +@@ -209,7 +209,7 @@ asmlinkage void do_trap_illinsn(struct pt_regs *regs) + + asmlinkage void do_trap_fpe(struct pt_regs *regs) + { +-#ifdef CONFIG_CPU_HAS_FP ++#ifdef CONFIG_CPU_HAS_FPU + return fpu_fpe(regs); + #else + do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, +@@ -219,7 +219,7 @@ asmlinkage void do_trap_fpe(struct pt_regs *regs) + + asmlinkage void do_trap_priv(struct pt_regs *regs) + { +-#ifdef CONFIG_CPU_HAS_FP ++#ifdef CONFIG_CPU_HAS_FPU + if (user_mode(regs) && fpu_libc_helper(regs)) + return; + #endif +diff --git a/arch/hexagon/include/asm/timer-regs.h b/arch/hexagon/include/asm/timer-regs.h +deleted file mode 100644 +index ee6c61423a058..0000000000000 +--- a/arch/hexagon/include/asm/timer-regs.h ++++ /dev/null +@@ -1,26 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * Timer support for Hexagon +- * +- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. +- */ +- +-#ifndef _ASM_TIMER_REGS_H +-#define _ASM_TIMER_REGS_H +- +-/* This stuff should go into a platform specific file */ +-#define TCX0_CLK_RATE 19200 +-#define TIMER_ENABLE 0 +-#define TIMER_CLR_ON_MATCH 1 +- +-/* +- * 8x50 HDD Specs 5-8. Simulator co-sim not fixed until +- * release 1.1, and then it's "adjustable" and probably not defaulted. +- */ +-#define RTOS_TIMER_INT 3 +-#ifdef CONFIG_HEXAGON_COMET +-#define RTOS_TIMER_REGS_ADDR 0xAB000000UL +-#endif +-#define SLEEP_CLK_RATE 32000 +- +-#endif +diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h +index 8d4ec76fceb45..dfe69e118b2be 100644 +--- a/arch/hexagon/include/asm/timex.h ++++ b/arch/hexagon/include/asm/timex.h +@@ -7,11 +7,10 @@ + #define _ASM_TIMEX_H + + #include <asm-generic/timex.h> +-#include <asm/timer-regs.h> + #include <asm/hexagon_vm.h> + + /* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */ +-#define CLOCK_TICK_RATE TCX0_CLK_RATE ++#define CLOCK_TICK_RATE 19200 + + #define ARCH_HAS_READ_CURRENT_TIMER + +diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c +index feffe527ac929..febc95714d756 100644 +--- a/arch/hexagon/kernel/time.c ++++ b/arch/hexagon/kernel/time.c +@@ -17,9 +17,10 @@ + #include <linux/of_irq.h> + #include <linux/module.h> + +-#include <asm/timer-regs.h> + #include <asm/hexagon_vm.h> + ++#define TIMER_ENABLE BIT(0) ++ + /* + * For the clocksource we need: + * pcycle frequency (600MHz) +@@ -33,6 +34,13 @@ cycles_t pcycle_freq_mhz; + cycles_t thread_freq_mhz; + cycles_t sleep_clk_freq; + ++/* ++ * 8x50 HDD Specs 5-8. Simulator co-sim not fixed until ++ * release 1.1, and then it's "adjustable" and probably not defaulted. ++ */ ++#define RTOS_TIMER_INT 3 ++#define RTOS_TIMER_REGS_ADDR 0xAB000000UL ++ + static struct resource rtos_timer_resources[] = { + { + .start = RTOS_TIMER_REGS_ADDR, +@@ -80,7 +88,7 @@ static int set_next_event(unsigned long delta, struct clock_event_device *evt) + iowrite32(0, &rtos_timer->clear); + + iowrite32(delta, &rtos_timer->match); +- iowrite32(1 << TIMER_ENABLE, &rtos_timer->enable); ++ iowrite32(TIMER_ENABLE, &rtos_timer->enable); + return 0; + } + +diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c +index d35d69d6588c4..55f75392857b0 100644 +--- a/arch/hexagon/lib/io.c ++++ b/arch/hexagon/lib/io.c +@@ -27,6 +27,7 @@ void __raw_readsw(const void __iomem *addr, void *data, int len) + *dst++ = *src; + + } ++EXPORT_SYMBOL(__raw_readsw); + + /* + * __raw_writesw - read words a short at a time +@@ -47,6 +48,7 @@ void __raw_writesw(void __iomem *addr, const void *data, int len) + + + } ++EXPORT_SYMBOL(__raw_writesw); + + /* Pretty sure len is pre-adjusted for the length of the access already */ + void __raw_readsl(const void __iomem *addr, void *data, int len) +@@ -62,6 +64,7 @@ void __raw_readsl(const void __iomem *addr, void *data, int len) + + + } ++EXPORT_SYMBOL(__raw_readsl); + + void __raw_writesl(void __iomem *addr, const void *data, int len) + { +@@ -76,3 +79,4 @@ void __raw_writesl(void __iomem *addr, const void *data, int len) + + + } ++EXPORT_SYMBOL(__raw_writesl); +diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug +index 40ca23bd228d6..2ce008e2d1644 100644 +--- a/arch/ia64/Kconfig.debug ++++ b/arch/ia64/Kconfig.debug +@@ -39,7 +39,7 @@ config DISABLE_VHPT + + config IA64_DEBUG_CMPXCHG + bool "Turn on compare-and-exchange bug checking (slow!)" +- depends on DEBUG_KERNEL ++ depends on DEBUG_KERNEL && PRINTK + help + Selecting this option turns on bug checking for the IA-64 + compare-and-exchange instructions. This is slow! Itaniums +diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c +index 441ed04b10378..d4048518a1d7d 100644 +--- a/arch/ia64/kernel/kprobes.c ++++ b/arch/ia64/kernel/kprobes.c +@@ -398,7 +398,8 @@ static void kretprobe_trampoline(void) + + int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) + { +- regs->cr_iip = __kretprobe_trampoline_handler(regs, kretprobe_trampoline, NULL); ++ regs->cr_iip = __kretprobe_trampoline_handler(regs, ++ dereference_function_descriptor(kretprobe_trampoline), NULL); + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we don't want the post_handler +@@ -414,7 +415,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, + ri->fp = NULL; + + /* Replace the return addr with trampoline addr */ +- regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip; ++ regs->b0 = (unsigned long)dereference_function_descriptor(kretprobe_trampoline); + } + + /* Check the instruction in the slot is break */ +@@ -902,14 +903,14 @@ static struct kprobe trampoline_p = { + int __init arch_init_kprobes(void) + { + trampoline_p.addr = +- (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip; ++ dereference_function_descriptor(kretprobe_trampoline); + return register_kprobe(&trampoline_p); + } + + int __kprobes arch_trampoline_kprobe(struct kprobe *p) + { + if (p->addr == +- (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip) ++ dereference_function_descriptor(kretprobe_trampoline)) + return 1; + + return 0; +diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c +index acb55a41260dd..2bcdd7d3a1ada 100644 +--- a/arch/ia64/pci/fixup.c ++++ b/arch/ia64/pci/fixup.c +@@ -76,5 +76,5 @@ static void pci_fixup_video(struct pci_dev *pdev) + } + } + } +-DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, +- PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); ++DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); +diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine +index 36fa0c3ef1296..eeab4f3e6c197 100644 +--- a/arch/m68k/Kconfig.machine ++++ b/arch/m68k/Kconfig.machine +@@ -203,6 +203,7 @@ config INIT_LCD + config MEMORY_RESERVE + int "Memory reservation (MiB)" + depends on (UCSIMM || UCDIMM) ++ default 0 + help + Reserve certain memory regions on 68x328 based boards. + +diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c +index 9718ce94cc845..34d6458340b0f 100644 +--- a/arch/m68k/kernel/traps.c ++++ b/arch/m68k/kernel/traps.c +@@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long ssp) + */ + asmlinkage void fpsp040_die(void) + { +- force_sigsegv(SIGSEGV); ++ force_exit_sig(SIGSEGV); + } + + #ifdef CONFIG_M68KFPU_EMU +diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms +index 584081df89c28..6e3f36c841e5d 100644 +--- a/arch/mips/Kbuild.platforms ++++ b/arch/mips/Kbuild.platforms +@@ -38,4 +38,4 @@ platform-$(CONFIG_MACH_TX49XX) += txx9/ + platform-$(CONFIG_MACH_VR41XX) += vr41xx/ + + # include the platform specific files +-include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platform-y)) ++include $(patsubst %/, $(srctree)/arch/mips/%/Platform, $(platform-y)) +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 6b8f591c5054c..393eb2133243f 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -332,6 +332,9 @@ config BCM63XX + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_HAS_EARLY_PRINTK ++ select SYS_HAS_CPU_BMIPS32_3300 ++ select SYS_HAS_CPU_BMIPS4350 ++ select SYS_HAS_CPU_BMIPS4380 + select SWAP_IO_SPACE + select GPIOLIB + select MIPS_L1_CACHE_SHIFT_4 +@@ -1379,6 +1382,7 @@ config CPU_LOONGSON64 + select MIPS_ASID_BITS_VARIABLE + select MIPS_PGD_C0_CONTEXT + select MIPS_L1_CACHE_SHIFT_6 ++ select MIPS_FP_SUPPORT + select GPIOLIB + select SWIOTLB + select HAVE_KVM +@@ -1989,6 +1993,10 @@ config SYS_HAS_CPU_MIPS64_R1 + config SYS_HAS_CPU_MIPS64_R2 + bool + ++config SYS_HAS_CPU_MIPS64_R5 ++ bool ++ select ARCH_HAS_SYNC_DMA_FOR_CPU if DMA_NONCOHERENT ++ + config SYS_HAS_CPU_MIPS64_R6 + bool + select ARCH_HAS_SYNC_DMA_FOR_CPU if DMA_NONCOHERENT +@@ -2153,7 +2161,7 @@ config CPU_SUPPORTS_ADDRWINCFG + bool + config CPU_SUPPORTS_HUGEPAGES + bool +- depends on !(32BIT && (ARCH_PHYS_ADDR_T_64BIT || EVA)) ++ depends on !(32BIT && (PHYS_ADDR_T_64BIT || EVA)) + config MIPS_PGD_C0_CONTEXT + bool + depends on 64BIT +@@ -3185,7 +3193,7 @@ config STACKTRACE_SUPPORT + config PGTABLE_LEVELS + int + default 4 if PAGE_SIZE_4KB && MIPS_VA_BITS_48 +- default 3 if 64BIT && !PAGE_SIZE_64KB ++ default 3 if 64BIT && (!PAGE_SIZE_64KB || MIPS_VA_BITS_48) + default 2 + + config MIPS_AUTO_PFN_OFFSET +diff --git a/arch/mips/Makefile b/arch/mips/Makefile +index ea3cd080a1c7d..f7b58da2f3889 100644 +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -254,7 +254,9 @@ endif + # + # Board-dependent options and extra files + # ++ifdef need-compiler + include $(srctree)/arch/mips/Kbuild.platforms ++endif + + ifdef CONFIG_PHYSICAL_START + load-y = $(CONFIG_PHYSICAL_START) +diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c +index 5a3e325275d0d..6e6756e8fa0a9 100644 +--- a/arch/mips/bcm63xx/clk.c ++++ b/arch/mips/bcm63xx/clk.c +@@ -381,6 +381,18 @@ void clk_disable(struct clk *clk) + + EXPORT_SYMBOL(clk_disable); + ++struct clk *clk_get_parent(struct clk *clk) ++{ ++ return NULL; ++} ++EXPORT_SYMBOL(clk_get_parent); ++ ++int clk_set_parent(struct clk *clk, struct clk *parent) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(clk_set_parent); ++ + unsigned long clk_get_rate(struct clk *clk) + { + if (!clk) +diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile +index 3548b3b452699..705b9e7f8035a 100644 +--- a/arch/mips/boot/compressed/Makefile ++++ b/arch/mips/boot/compressed/Makefile +@@ -56,6 +56,8 @@ $(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c + + vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o + ++vmlinuzobjs-$(CONFIG_KERNEL_ZSTD) += $(obj)/bswapdi.o $(obj)/ashldi3.o $(obj)/clz_ctz.o ++ + extra-y += ashldi3.c + $(obj)/ashldi3.c: $(obj)/%.c: $(srctree)/lib/%.c FORCE + $(call if_changed,shipped) +@@ -64,6 +66,10 @@ extra-y += bswapsi.c + $(obj)/bswapsi.c: $(obj)/%.c: $(srctree)/arch/mips/lib/%.c FORCE + $(call if_changed,shipped) + ++extra-y += bswapdi.c ++$(obj)/bswapdi.c: $(obj)/%.c: $(srctree)/arch/mips/lib/%.c FORCE ++ $(call if_changed,shipped) ++ + targets := $(notdir $(vmlinuzobjs-y)) + + targets += vmlinux.bin +diff --git a/arch/mips/boot/compressed/clz_ctz.c b/arch/mips/boot/compressed/clz_ctz.c +new file mode 100644 +index 0000000000000..b4a1b6eb2f8ad +--- /dev/null ++++ b/arch/mips/boot/compressed/clz_ctz.c +@@ -0,0 +1,2 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++#include "../../../../lib/clz_ctz.c" +diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S +index 0a515cde1c183..25860fba6218d 100644 +--- a/arch/mips/cavium-octeon/octeon-memcpy.S ++++ b/arch/mips/cavium-octeon/octeon-memcpy.S +@@ -74,7 +74,7 @@ + #define EXC(inst_reg,addr,handler) \ + 9: inst_reg, addr; \ + .section __ex_table,"a"; \ +- PTR 9b, handler; \ ++ PTR_WD 9b, handler; \ + .previous + + /* +diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c +index d56e9b9d2e434..a994022e32c9f 100644 +--- a/arch/mips/cavium-octeon/octeon-platform.c ++++ b/arch/mips/cavium-octeon/octeon-platform.c +@@ -328,6 +328,7 @@ static int __init octeon_ehci_device_init(void) + + pd->dev.platform_data = &octeon_ehci_pdata; + octeon_ehci_hw_start(&pd->dev); ++ put_device(&pd->dev); + + return ret; + } +@@ -391,6 +392,7 @@ static int __init octeon_ohci_device_init(void) + + pd->dev.platform_data = &octeon_ohci_pdata; + octeon_ohci_hw_start(&pd->dev); ++ put_device(&pd->dev); + + return ret; + } +diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c +index 6e4d3619137af..4df919d26b082 100644 +--- a/arch/mips/cavium-octeon/octeon-usb.c ++++ b/arch/mips/cavium-octeon/octeon-usb.c +@@ -537,6 +537,7 @@ static int __init dwc3_octeon_device_init(void) + devm_iounmap(&pdev->dev, base); + devm_release_mem_region(&pdev->dev, res->start, + resource_size(res)); ++ put_device(&pdev->dev); + } + } while (node != NULL); + +diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig +index 5c24ac7fdf56d..ba47c5e929b7f 100644 +--- a/arch/mips/configs/fuloong2e_defconfig ++++ b/arch/mips/configs/fuloong2e_defconfig +@@ -206,7 +206,6 @@ CONFIG_NFSD_V3_ACL=y + CONFIG_NFSD_V4=y + CONFIG_CIFS=m + CONFIG_CIFS_STATS2=y +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_CIFS_DEBUG2=y +diff --git a/arch/mips/configs/malta_qemu_32r6_defconfig b/arch/mips/configs/malta_qemu_32r6_defconfig +index 614af02d83e6e..6fb9bc29f4a03 100644 +--- a/arch/mips/configs/malta_qemu_32r6_defconfig ++++ b/arch/mips/configs/malta_qemu_32r6_defconfig +@@ -165,7 +165,6 @@ CONFIG_TMPFS=y + CONFIG_NFS_FS=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig +index 9c051f8fd3300..eb72df528243a 100644 +--- a/arch/mips/configs/maltaaprp_defconfig ++++ b/arch/mips/configs/maltaaprp_defconfig +@@ -166,7 +166,6 @@ CONFIG_TMPFS=y + CONFIG_NFS_FS=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig +index 2e90d97551d6f..1fb40d310f49c 100644 +--- a/arch/mips/configs/maltasmvp_defconfig ++++ b/arch/mips/configs/maltasmvp_defconfig +@@ -167,7 +167,6 @@ CONFIG_TMPFS=y + CONFIG_NFS_FS=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/mips/configs/maltasmvp_eva_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig +index d1f7fdb27284b..75cb778c61496 100644 +--- a/arch/mips/configs/maltasmvp_eva_defconfig ++++ b/arch/mips/configs/maltasmvp_eva_defconfig +@@ -169,7 +169,6 @@ CONFIG_TMPFS=y + CONFIG_NFS_FS=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig +index 48e5bd4924522..7b4f247dc60cc 100644 +--- a/arch/mips/configs/maltaup_defconfig ++++ b/arch/mips/configs/maltaup_defconfig +@@ -165,7 +165,6 @@ CONFIG_TMPFS=y + CONFIG_NFS_FS=y + CONFIG_ROOT_NFS=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y + CONFIG_NLS_CODEPAGE_437=m +diff --git a/arch/mips/generic/yamon-dt.c b/arch/mips/generic/yamon-dt.c +index a3aa22c77cadc..a07a5edbcda78 100644 +--- a/arch/mips/generic/yamon-dt.c ++++ b/arch/mips/generic/yamon-dt.c +@@ -75,7 +75,7 @@ static unsigned int __init gen_fdt_mem_array( + __init int yamon_dt_append_memory(void *fdt, + const struct yamon_mem_region *regions) + { +- unsigned long phys_memsize, memsize; ++ unsigned long phys_memsize = 0, memsize; + __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES]; + unsigned int mem_entries; + int i, err, mem_off; +diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h +index 2f8ce94ebaafe..cc69f1deb1ca8 100644 +--- a/arch/mips/include/asm/asm.h ++++ b/arch/mips/include/asm/asm.h +@@ -276,7 +276,7 @@ symbol = value + + #define PTR_SCALESHIFT 2 + +-#define PTR .word ++#define PTR_WD .word + #define PTRSIZE 4 + #define PTRLOG 2 + #endif +@@ -301,7 +301,7 @@ symbol = value + + #define PTR_SCALESHIFT 3 + +-#define PTR .dword ++#define PTR_WD .dword + #define PTRSIZE 8 + #define PTRLOG 3 + #endif +diff --git a/arch/mips/include/asm/cmpxchg.h b/arch/mips/include/asm/cmpxchg.h +index 0b983800f48b7..66a8b293fd80b 100644 +--- a/arch/mips/include/asm/cmpxchg.h ++++ b/arch/mips/include/asm/cmpxchg.h +@@ -249,6 +249,7 @@ static inline unsigned long __cmpxchg64(volatile void *ptr, + /* Load 64 bits from ptr */ + " " __SYNC(full, loongson3_war) " \n" + "1: lld %L0, %3 # __cmpxchg64 \n" ++ " .set pop \n" + /* + * Split the 64 bit value we loaded into the 2 registers that hold the + * ret variable. +@@ -276,12 +277,14 @@ static inline unsigned long __cmpxchg64(volatile void *ptr, + " or %L1, %L1, $at \n" + " .set at \n" + # endif ++ " .set push \n" ++ " .set " MIPS_ISA_ARCH_LEVEL " \n" + /* Attempt to store new at ptr */ + " scd %L1, %2 \n" + /* If we failed, loop! */ + "\t" __SC_BEQZ "%L1, 1b \n" +- " .set pop \n" + "2: " __SYNC(full, loongson3_war) " \n" ++ " .set pop \n" + : "=&r"(ret), + "=&r"(tmp), + "=" GCC_OFF_SMALL_ASM() (*(unsigned long long *)ptr) +diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h +index b463f2aa5a613..db497a8167da2 100644 +--- a/arch/mips/include/asm/ftrace.h ++++ b/arch/mips/include/asm/ftrace.h +@@ -32,7 +32,7 @@ do { \ + ".previous\n" \ + \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR) "\t1b, 3b\n\t" \ ++ STR(PTR_WD) "\t1b, 3b\n\t" \ + ".previous\n" \ + \ + : [tmp_dst] "=&r" (dst), [tmp_err] "=r" (error)\ +@@ -54,7 +54,7 @@ do { \ + ".previous\n" \ + \ + ".section\t__ex_table,\"a\"\n\t"\ +- STR(PTR) "\t1b, 3b\n\t" \ ++ STR(PTR_WD) "\t1b, 3b\n\t" \ + ".previous\n" \ + \ + : [tmp_err] "=r" (error) \ +diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h +index ecda7295ddcd1..3fa6340903882 100644 +--- a/arch/mips/include/asm/local.h ++++ b/arch/mips/include/asm/local.h +@@ -5,6 +5,7 @@ + #include <linux/percpu.h> + #include <linux/bitops.h> + #include <linux/atomic.h> ++#include <asm/asm.h> + #include <asm/cmpxchg.h> + #include <asm/compiler.h> + #include <asm/war.h> +@@ -39,7 +40,7 @@ static __inline__ long local_add_return(long i, local_t * l) + " .set arch=r4000 \n" + __SYNC(full, loongson3_war) " \n" + "1:" __LL "%1, %2 # local_add_return \n" +- " addu %0, %1, %3 \n" ++ __stringify(LONG_ADDU) " %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqzl %0, 1b \n" + " addu %0, %1, %3 \n" +@@ -55,7 +56,7 @@ static __inline__ long local_add_return(long i, local_t * l) + " .set "MIPS_ISA_ARCH_LEVEL" \n" + __SYNC(full, loongson3_war) " \n" + "1:" __LL "%1, %2 # local_add_return \n" +- " addu %0, %1, %3 \n" ++ __stringify(LONG_ADDU) " %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqz %0, 1b \n" + " addu %0, %1, %3 \n" +@@ -88,7 +89,7 @@ static __inline__ long local_sub_return(long i, local_t * l) + " .set arch=r4000 \n" + __SYNC(full, loongson3_war) " \n" + "1:" __LL "%1, %2 # local_sub_return \n" +- " subu %0, %1, %3 \n" ++ __stringify(LONG_SUBU) " %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqzl %0, 1b \n" + " subu %0, %1, %3 \n" +@@ -104,7 +105,7 @@ static __inline__ long local_sub_return(long i, local_t * l) + " .set "MIPS_ISA_ARCH_LEVEL" \n" + __SYNC(full, loongson3_war) " \n" + "1:" __LL "%1, %2 # local_sub_return \n" +- " subu %0, %1, %3 \n" ++ __stringify(LONG_SUBU) " %0, %1, %3 \n" + __SC "%0, %2 \n" + " beqz %0, 1b \n" + " subu %0, %1, %3 \n" +diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +index 13373c5144f89..efb41b3519747 100644 +--- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h ++++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h +@@ -32,7 +32,7 @@ + nop + /* Loongson-3A R2/R3 */ + andi t0, (PRID_IMP_MASK | PRID_REV_MASK) +- slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) ++ slti t0, t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) + bnez t0, 2f + nop + 1: +@@ -63,7 +63,7 @@ + nop + /* Loongson-3A R2/R3 */ + andi t0, (PRID_IMP_MASK | PRID_REV_MASK) +- slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) ++ slti t0, t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) + bnez t0, 2f + nop + 1: +diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h +index aeae2effa123d..23c67c0871b17 100644 +--- a/arch/mips/include/asm/mips-cm.h ++++ b/arch/mips/include/asm/mips-cm.h +@@ -11,6 +11,7 @@ + #ifndef __MIPS_ASM_MIPS_CM_H__ + #define __MIPS_ASM_MIPS_CM_H__ + ++#include <linux/bitfield.h> + #include <linux/bitops.h> + #include <linux/errno.h> + +@@ -153,8 +154,8 @@ GCR_ACCESSOR_RO(32, 0x030, rev) + #define CM_GCR_REV_MINOR GENMASK(7, 0) + + #define CM_ENCODE_REV(major, minor) \ +- (((major) << __ffs(CM_GCR_REV_MAJOR)) | \ +- ((minor) << __ffs(CM_GCR_REV_MINOR))) ++ (FIELD_PREP(CM_GCR_REV_MAJOR, major) | \ ++ FIELD_PREP(CM_GCR_REV_MINOR, minor)) + + #define CM_REV_CM2 CM_ENCODE_REV(6, 0) + #define CM_REV_CM2_5 CM_ENCODE_REV(7, 0) +@@ -362,10 +363,10 @@ static inline int mips_cm_revision(void) + static inline unsigned int mips_cm_max_vp_width(void) + { + extern int smp_num_siblings; +- uint32_t cfg; + + if (mips_cm_revision() >= CM_REV_CM3) +- return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW; ++ return FIELD_GET(CM_GCR_SYS_CONFIG2_MAXVPW, ++ read_gcr_sys_config2()); + + if (mips_cm_present()) { + /* +@@ -373,8 +374,7 @@ static inline unsigned int mips_cm_max_vp_width(void) + * number of VP(E)s, and if that ever changes then this will + * need revisiting. + */ +- cfg = read_gcr_cl_config() & CM_GCR_Cx_CONFIG_PVPE; +- return (cfg >> __ffs(CM_GCR_Cx_CONFIG_PVPE)) + 1; ++ return FIELD_GET(CM_GCR_Cx_CONFIG_PVPE, read_gcr_cl_config()) + 1; + } + + if (IS_ENABLED(CONFIG_SMP)) +diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h +index 0e6bf220db618..6c61e0a639249 100644 +--- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h ++++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h +@@ -318,7 +318,7 @@ enum cvmx_chip_types_enum { + + /* Functions to return string based on type */ + #define ENUM_BRD_TYPE_CASE(x) \ +- case x: return(#x + 16); /* Skip CVMX_BOARD_TYPE_ */ ++ case x: return (&#x[16]); /* Skip CVMX_BOARD_TYPE_ */ + static inline const char *cvmx_board_type_to_string(enum + cvmx_board_types_enum type) + { +@@ -410,7 +410,7 @@ static inline const char *cvmx_board_type_to_string(enum + } + + #define ENUM_CHIP_TYPE_CASE(x) \ +- case x: return(#x + 15); /* Skip CVMX_CHIP_TYPE */ ++ case x: return (&#x[15]); /* Skip CVMX_CHIP_TYPE */ + static inline const char *cvmx_chip_type_to_string(enum + cvmx_chip_types_enum type) + { +diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h +index af3788589ee6d..431a1c9d53fc7 100644 +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -119,7 +119,7 @@ static inline void flush_scache_line(unsigned long addr) + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ +- " "STR(PTR)" 1b, 3b \n" \ ++ " "STR(PTR_WD)" 1b, 3b \n" \ + " .previous" \ + : "+r" (__err) \ + : "i" (op), "r" (addr), "i" (-EFAULT)); \ +@@ -142,7 +142,7 @@ static inline void flush_scache_line(unsigned long addr) + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ +- " "STR(PTR)" 1b, 3b \n" \ ++ " "STR(PTR_WD)" 1b, 3b \n" \ + " .previous" \ + : "+r" (__err) \ + : "i" (op), "r" (addr), "i" (-EFAULT)); \ +diff --git a/arch/mips/include/asm/unaligned-emul.h b/arch/mips/include/asm/unaligned-emul.h +index 2022b18944b97..9af0f4d3d288c 100644 +--- a/arch/mips/include/asm/unaligned-emul.h ++++ b/arch/mips/include/asm/unaligned-emul.h +@@ -20,8 +20,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -41,8 +41,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -74,10 +74,10 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -102,8 +102,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -125,8 +125,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -145,8 +145,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -178,10 +178,10 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -223,14 +223,14 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ +- STR(PTR)"\t5b, 11b\n\t" \ +- STR(PTR)"\t6b, 11b\n\t" \ +- STR(PTR)"\t7b, 11b\n\t" \ +- STR(PTR)"\t8b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t5b, 11b\n\t" \ ++ STR(PTR_WD)"\t6b, 11b\n\t" \ ++ STR(PTR_WD)"\t7b, 11b\n\t" \ ++ STR(PTR_WD)"\t8b, 11b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -255,8 +255,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT));\ +@@ -276,8 +276,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +@@ -296,8 +296,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +@@ -325,10 +325,10 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ + ".previous" \ + : "=&r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT) \ +@@ -365,14 +365,14 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ +- STR(PTR)"\t5b, 11b\n\t" \ +- STR(PTR)"\t6b, 11b\n\t" \ +- STR(PTR)"\t7b, 11b\n\t" \ +- STR(PTR)"\t8b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t5b, 11b\n\t" \ ++ STR(PTR_WD)"\t6b, 11b\n\t" \ ++ STR(PTR_WD)"\t7b, 11b\n\t" \ ++ STR(PTR_WD)"\t8b, 11b\n\t" \ + ".previous" \ + : "=&r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT) \ +@@ -398,8 +398,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -419,8 +419,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -452,10 +452,10 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -481,8 +481,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -504,8 +504,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -524,8 +524,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -557,10 +557,10 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -602,14 +602,14 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ +- STR(PTR)"\t5b, 11b\n\t" \ +- STR(PTR)"\t6b, 11b\n\t" \ +- STR(PTR)"\t7b, 11b\n\t" \ +- STR(PTR)"\t8b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t5b, 11b\n\t" \ ++ STR(PTR_WD)"\t6b, 11b\n\t" \ ++ STR(PTR_WD)"\t7b, 11b\n\t" \ ++ STR(PTR_WD)"\t8b, 11b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); \ +@@ -632,8 +632,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT));\ +@@ -653,8 +653,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +@@ -673,8 +673,8 @@ do { \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 4b\n\t" \ +- STR(PTR)"\t2b, 4b\n\t" \ ++ STR(PTR_WD)"\t1b, 4b\n\t" \ ++ STR(PTR_WD)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); \ +@@ -703,10 +703,10 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ + ".previous" \ + : "=&r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT) \ +@@ -743,14 +743,14 @@ do { \ + "j\t10b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ +- STR(PTR)"\t1b, 11b\n\t" \ +- STR(PTR)"\t2b, 11b\n\t" \ +- STR(PTR)"\t3b, 11b\n\t" \ +- STR(PTR)"\t4b, 11b\n\t" \ +- STR(PTR)"\t5b, 11b\n\t" \ +- STR(PTR)"\t6b, 11b\n\t" \ +- STR(PTR)"\t7b, 11b\n\t" \ +- STR(PTR)"\t8b, 11b\n\t" \ ++ STR(PTR_WD)"\t1b, 11b\n\t" \ ++ STR(PTR_WD)"\t2b, 11b\n\t" \ ++ STR(PTR_WD)"\t3b, 11b\n\t" \ ++ STR(PTR_WD)"\t4b, 11b\n\t" \ ++ STR(PTR_WD)"\t5b, 11b\n\t" \ ++ STR(PTR_WD)"\t6b, 11b\n\t" \ ++ STR(PTR_WD)"\t7b, 11b\n\t" \ ++ STR(PTR_WD)"\t8b, 11b\n\t" \ + ".previous" \ + : "=&r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT) \ +diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c +index 630fcb4cb30e7..7c861e6a89529 100644 +--- a/arch/mips/kernel/cpu-probe.c ++++ b/arch/mips/kernel/cpu-probe.c +@@ -1734,8 +1734,6 @@ static inline void decode_cpucfg(struct cpuinfo_mips *c) + + static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) + { +- decode_configs(c); +- + /* All Loongson processors covered here define ExcCode 16 as GSExc. */ + c->options |= MIPS_CPU_GSEXCEX; + +@@ -1796,6 +1794,8 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) + panic("Unknown Loongson Processor ID!"); + break; + } ++ ++ decode_configs(c); + } + #else + static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { } +diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c +index 90f1c3df1f0e4..b4f7d950c8468 100644 +--- a/arch/mips/kernel/mips-cm.c ++++ b/arch/mips/kernel/mips-cm.c +@@ -221,8 +221,7 @@ static void mips_cm_probe_l2sync(void) + phys_addr_t addr; + + /* L2-only sync was introduced with CM major revision 6 */ +- major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR) >> +- __ffs(CM_GCR_REV_MAJOR); ++ major_rev = FIELD_GET(CM_GCR_REV_MAJOR, read_gcr_rev()); + if (major_rev < 6) + return; + +@@ -306,13 +305,13 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core, + preempt_disable(); + + if (cm_rev >= CM_REV_CM3) { +- val = core << __ffs(CM3_GCR_Cx_OTHER_CORE); +- val |= vp << __ffs(CM3_GCR_Cx_OTHER_VP); ++ val = FIELD_PREP(CM3_GCR_Cx_OTHER_CORE, core) | ++ FIELD_PREP(CM3_GCR_Cx_OTHER_VP, vp); + + if (cm_rev >= CM_REV_CM3_5) { + val |= CM_GCR_Cx_OTHER_CLUSTER_EN; +- val |= cluster << __ffs(CM_GCR_Cx_OTHER_CLUSTER); +- val |= block << __ffs(CM_GCR_Cx_OTHER_BLOCK); ++ val |= FIELD_PREP(CM_GCR_Cx_OTHER_CLUSTER, cluster); ++ val |= FIELD_PREP(CM_GCR_Cx_OTHER_BLOCK, block); + } else { + WARN_ON(cluster != 0); + WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL); +@@ -342,7 +341,7 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core, + spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core), + per_cpu(cm_core_lock_flags, curr_core)); + +- val = core << __ffs(CM_GCR_Cx_OTHER_CORENUM); ++ val = FIELD_PREP(CM_GCR_Cx_OTHER_CORENUM, core); + } + + write_gcr_cl_other(val); +@@ -386,8 +385,8 @@ void mips_cm_error_report(void) + cm_other = read_gcr_error_mult(); + + if (revision < CM_REV_CM3) { /* CM2 */ +- cause = cm_error >> __ffs(CM_GCR_ERROR_CAUSE_ERRTYPE); +- ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND); ++ cause = FIELD_GET(CM_GCR_ERROR_CAUSE_ERRTYPE, cm_error); ++ ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other); + + if (!cause) + return; +@@ -445,8 +444,8 @@ void mips_cm_error_report(void) + ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits; + ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit; + +- cause = cm_error >> __ffs64(CM3_GCR_ERROR_CAUSE_ERRTYPE); +- ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND); ++ cause = FIELD_GET(CM3_GCR_ERROR_CAUSE_ERRTYPE, cm_error); ++ ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other); + + if (!cause) + return; +diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c +index a39ec755e4c24..750fe569862b6 100644 +--- a/arch/mips/kernel/mips-r2-to-r6-emul.c ++++ b/arch/mips/kernel/mips-r2-to-r6-emul.c +@@ -1258,10 +1258,10 @@ fpu_emul: + " j 10b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1333,10 +1333,10 @@ fpu_emul: + " j 10b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1404,10 +1404,10 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1474,10 +1474,10 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1589,14 +1589,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" +- STR(PTR) " 5b,8b\n" +- STR(PTR) " 6b,8b\n" +- STR(PTR) " 7b,8b\n" +- STR(PTR) " 0b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" ++ STR(PTR_WD) " 5b,8b\n" ++ STR(PTR_WD) " 6b,8b\n" ++ STR(PTR_WD) " 7b,8b\n" ++ STR(PTR_WD) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1708,14 +1708,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" +- STR(PTR) " 5b,8b\n" +- STR(PTR) " 6b,8b\n" +- STR(PTR) " 7b,8b\n" +- STR(PTR) " 0b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" ++ STR(PTR_WD) " 5b,8b\n" ++ STR(PTR_WD) " 6b,8b\n" ++ STR(PTR_WD) " 7b,8b\n" ++ STR(PTR_WD) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1827,14 +1827,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" +- STR(PTR) " 5b,8b\n" +- STR(PTR) " 6b,8b\n" +- STR(PTR) " 7b,8b\n" +- STR(PTR) " 0b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" ++ STR(PTR_WD) " 5b,8b\n" ++ STR(PTR_WD) " 6b,8b\n" ++ STR(PTR_WD) " 7b,8b\n" ++ STR(PTR_WD) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -1945,14 +1945,14 @@ fpu_emul: + " j 9b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" +- STR(PTR) " 1b,8b\n" +- STR(PTR) " 2b,8b\n" +- STR(PTR) " 3b,8b\n" +- STR(PTR) " 4b,8b\n" +- STR(PTR) " 5b,8b\n" +- STR(PTR) " 6b,8b\n" +- STR(PTR) " 7b,8b\n" +- STR(PTR) " 0b,8b\n" ++ STR(PTR_WD) " 1b,8b\n" ++ STR(PTR_WD) " 2b,8b\n" ++ STR(PTR_WD) " 3b,8b\n" ++ STR(PTR_WD) " 4b,8b\n" ++ STR(PTR_WD) " 5b,8b\n" ++ STR(PTR_WD) " 6b,8b\n" ++ STR(PTR_WD) " 7b,8b\n" ++ STR(PTR_WD) " 0b,8b\n" + " .previous\n" + " .set pop\n" + : "+&r"(rt), "=&r"(rs), +@@ -2007,7 +2007,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- STR(PTR) " 1b,3b\n" ++ STR(PTR_WD) " 1b,3b\n" + ".previous\n" + : "=&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV) +@@ -2065,7 +2065,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- STR(PTR) " 1b,3b\n" ++ STR(PTR_WD) " 1b,3b\n" + ".previous\n" + : "+&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV)); +@@ -2126,7 +2126,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- STR(PTR) " 1b,3b\n" ++ STR(PTR_WD) " 1b,3b\n" + ".previous\n" + : "=&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV) +@@ -2189,7 +2189,7 @@ fpu_emul: + "j 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" +- STR(PTR) " 1b,3b\n" ++ STR(PTR_WD) " 1b,3b\n" + ".previous\n" + : "+&r"(res), "+&r"(err) + : "r"(vaddr), "i"(SIGSEGV)); +diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S +index 12e58053544fc..2748c55820c24 100644 +--- a/arch/mips/kernel/r2300_fpu.S ++++ b/arch/mips/kernel/r2300_fpu.S +@@ -23,14 +23,14 @@ + #define EX(a,b) \ + 9: a,##b; \ + .section __ex_table,"a"; \ +- PTR 9b,fault; \ ++ PTR_WD 9b,fault; \ + .previous + + #define EX2(a,b) \ + 9: a,##b; \ + .section __ex_table,"a"; \ +- PTR 9b,bad_stack; \ +- PTR 9b+4,bad_stack; \ ++ PTR_WD 9b,fault; \ ++ PTR_WD 9b+4,fault; \ + .previous + + .set mips1 +diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S +index b91e911064756..2e687c60bc4f1 100644 +--- a/arch/mips/kernel/r4k_fpu.S ++++ b/arch/mips/kernel/r4k_fpu.S +@@ -31,7 +31,7 @@ + .ex\@: \insn \reg, \src + .set pop + .section __ex_table,"a" +- PTR .ex\@, fault ++ PTR_WD .ex\@, fault + .previous + .endm + +diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S +index f3c908abdbb80..cfde14b48fd8d 100644 +--- a/arch/mips/kernel/relocate_kernel.S ++++ b/arch/mips/kernel/relocate_kernel.S +@@ -147,10 +147,10 @@ LEAF(kexec_smp_wait) + + kexec_args: + EXPORT(kexec_args) +-arg0: PTR 0x0 +-arg1: PTR 0x0 +-arg2: PTR 0x0 +-arg3: PTR 0x0 ++arg0: PTR_WD 0x0 ++arg1: PTR_WD 0x0 ++arg2: PTR_WD 0x0 ++arg3: PTR_WD 0x0 + .size kexec_args,PTRSIZE*4 + + #ifdef CONFIG_SMP +@@ -161,10 +161,10 @@ arg3: PTR 0x0 + */ + secondary_kexec_args: + EXPORT(secondary_kexec_args) +-s_arg0: PTR 0x0 +-s_arg1: PTR 0x0 +-s_arg2: PTR 0x0 +-s_arg3: PTR 0x0 ++s_arg0: PTR_WD 0x0 ++s_arg1: PTR_WD 0x0 ++s_arg2: PTR_WD 0x0 ++s_arg3: PTR_WD 0x0 + .size secondary_kexec_args,PTRSIZE*4 + kexec_flag: + LONG 0x1 +@@ -173,17 +173,17 @@ kexec_flag: + + kexec_start_address: + EXPORT(kexec_start_address) +- PTR 0x0 ++ PTR_WD 0x0 + .size kexec_start_address, PTRSIZE + + kexec_indirection_page: + EXPORT(kexec_indirection_page) +- PTR 0 ++ PTR_WD 0 + .size kexec_indirection_page, PTRSIZE + + relocate_new_kernel_end: + + relocate_new_kernel_size: + EXPORT(relocate_new_kernel_size) +- PTR relocate_new_kernel_end - relocate_new_kernel ++ PTR_WD relocate_new_kernel_end - relocate_new_kernel + .size relocate_new_kernel_size, PTRSIZE +diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S +index b1b2e106f7118..9bfce5f75f601 100644 +--- a/arch/mips/kernel/scall32-o32.S ++++ b/arch/mips/kernel/scall32-o32.S +@@ -72,10 +72,10 @@ loads_done: + .set pop + + .section __ex_table,"a" +- PTR load_a4, bad_stack_a4 +- PTR load_a5, bad_stack_a5 +- PTR load_a6, bad_stack_a6 +- PTR load_a7, bad_stack_a7 ++ PTR_WD load_a4, bad_stack_a4 ++ PTR_WD load_a5, bad_stack_a5 ++ PTR_WD load_a6, bad_stack_a6 ++ PTR_WD load_a7, bad_stack_a7 + .previous + + lw t0, TI_FLAGS($28) # syscall tracing enabled? +@@ -216,7 +216,7 @@ einval: li v0, -ENOSYS + #endif /* CONFIG_MIPS_MT_FPAFF */ + + #define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native) +-#define __SYSCALL(nr, entry) PTR entry ++#define __SYSCALL(nr, entry) PTR_WD entry + .align 2 + .type sys_call_table, @object + EXPORT(sys_call_table) +diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S +index f650c55a17dc5..97456b2ca7dc3 100644 +--- a/arch/mips/kernel/scall64-n32.S ++++ b/arch/mips/kernel/scall64-n32.S +@@ -101,7 +101,7 @@ not_n32_scall: + + END(handle_sysn32) + +-#define __SYSCALL(nr, entry) PTR entry ++#define __SYSCALL(nr, entry) PTR_WD entry + .type sysn32_call_table, @object + EXPORT(sysn32_call_table) + #include <asm/syscall_table_n32.h> +diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S +index 5d7bfc65e4d0b..5f6ed4b4c3993 100644 +--- a/arch/mips/kernel/scall64-n64.S ++++ b/arch/mips/kernel/scall64-n64.S +@@ -109,7 +109,7 @@ illegal_syscall: + j n64_syscall_exit + END(handle_sys64) + +-#define __SYSCALL(nr, entry) PTR entry ++#define __SYSCALL(nr, entry) PTR_WD entry + .align 3 + .type sys_call_table, @object + EXPORT(sys_call_table) +diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S +index cedc8bd888046..d3c2616cba226 100644 +--- a/arch/mips/kernel/scall64-o32.S ++++ b/arch/mips/kernel/scall64-o32.S +@@ -73,10 +73,10 @@ load_a7: lw a7, 28(t0) # argument #8 from usp + loads_done: + + .section __ex_table,"a" +- PTR load_a4, bad_stack_a4 +- PTR load_a5, bad_stack_a5 +- PTR load_a6, bad_stack_a6 +- PTR load_a7, bad_stack_a7 ++ PTR_WD load_a4, bad_stack_a4 ++ PTR_WD load_a5, bad_stack_a5 ++ PTR_WD load_a6, bad_stack_a6 ++ PTR_WD load_a7, bad_stack_a7 + .previous + + li t1, _TIF_WORK_SYSCALL_ENTRY +@@ -214,7 +214,7 @@ einval: li v0, -ENOSYS + END(sys32_syscall) + + #define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, compat) +-#define __SYSCALL(nr, entry) PTR entry ++#define __SYSCALL(nr, entry) PTR_WD entry + .align 3 + .type sys32_call_table,@object + EXPORT(sys32_call_table) +diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c +index f979adfd4fc20..ef73ba1e0ec10 100644 +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -803,7 +803,7 @@ early_param("coherentio", setcoherentio); + + static int __init setnocoherentio(char *str) + { +- dma_default_coherent = true; ++ dma_default_coherent = false; + pr_info("Software DMA cache coherency (command line)\n"); + return 0; + } +diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c +index 2afa3eef486a9..ae93a607ddf7e 100644 +--- a/arch/mips/kernel/syscall.c ++++ b/arch/mips/kernel/syscall.c +@@ -122,8 +122,8 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) + " j 3b \n" + " .previous \n" + " .section __ex_table,\"a\" \n" +- " "STR(PTR)" 1b, 4b \n" +- " "STR(PTR)" 2b, 4b \n" ++ " "STR(PTR_WD)" 1b, 4b \n" ++ " "STR(PTR_WD)" 2b, 4b \n" + " .previous \n" + " .set pop \n" + : [old] "=&r" (old), +@@ -152,8 +152,8 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) + " j 3b \n" + " .previous \n" + " .section __ex_table,\"a\" \n" +- " "STR(PTR)" 1b, 5b \n" +- " "STR(PTR)" 2b, 5b \n" ++ " "STR(PTR_WD)" 1b, 5b \n" ++ " "STR(PTR_WD)" 2b, 5b \n" + " .previous \n" + " .set pop \n" + : [old] "=&r" (old), +@@ -240,12 +240,3 @@ SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op) + { + return -ENOSYS; + } +- +-/* +- * If we ever come here the user sp is bad. Zap the process right away. +- * Due to the bad stack signaling wouldn't work. +- */ +-asmlinkage void bad_stack(void) +-{ +- do_exit(SIGSEGV); +-} +diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c +index dd819e31fcbbf..7a623684d9b5e 100644 +--- a/arch/mips/lantiq/clk.c ++++ b/arch/mips/lantiq/clk.c +@@ -158,6 +158,18 @@ void clk_deactivate(struct clk *clk) + } + EXPORT_SYMBOL(clk_deactivate); + ++struct clk *clk_get_parent(struct clk *clk) ++{ ++ return NULL; ++} ++EXPORT_SYMBOL(clk_get_parent); ++ ++int clk_set_parent(struct clk *clk, struct clk *parent) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(clk_set_parent); ++ + static inline u32 get_counter_resolution(void) + { + u32 res; +diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c +index 63dccb2ed08b2..53fcc672a2944 100644 +--- a/arch/mips/lantiq/xway/dma.c ++++ b/arch/mips/lantiq/xway/dma.c +@@ -11,6 +11,7 @@ + #include <linux/export.h> + #include <linux/spinlock.h> + #include <linux/clk.h> ++#include <linux/delay.h> + #include <linux/err.h> + #include <linux/of.h> + +@@ -30,6 +31,7 @@ + #define LTQ_DMA_PCTRL 0x44 + #define LTQ_DMA_IRNEN 0xf4 + ++#define DMA_ID_CHNR GENMASK(26, 20) /* channel number */ + #define DMA_DESCPT BIT(3) /* descriptor complete irq */ + #define DMA_TX BIT(8) /* TX channel direction */ + #define DMA_CHAN_ON BIT(0) /* channel on / off bit */ +@@ -39,8 +41,11 @@ + #define DMA_IRQ_ACK 0x7e /* IRQ status register */ + #define DMA_POLL BIT(31) /* turn on channel polling */ + #define DMA_CLK_DIV4 BIT(6) /* polling clock divider */ +-#define DMA_2W_BURST BIT(1) /* 2 word burst length */ +-#define DMA_MAX_CHANNEL 20 /* the soc has 20 channels */ ++#define DMA_PCTRL_2W_BURST 0x1 /* 2 word burst length */ ++#define DMA_PCTRL_4W_BURST 0x2 /* 4 word burst length */ ++#define DMA_PCTRL_8W_BURST 0x3 /* 8 word burst length */ ++#define DMA_TX_BURST_SHIFT 4 /* tx burst shift */ ++#define DMA_RX_BURST_SHIFT 2 /* rx burst shift */ + #define DMA_ETOP_ENDIANNESS (0xf << 8) /* endianness swap etop channels */ + #define DMA_WEIGHT (BIT(17) | BIT(16)) /* default channel wheight */ + +@@ -191,7 +196,8 @@ ltq_dma_init_port(int p) + break; + + case DMA_PORT_DEU: +- ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2), ++ ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) | ++ (DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT), + LTQ_DMA_PCTRL); + break; + +@@ -206,7 +212,7 @@ ltq_dma_init(struct platform_device *pdev) + { + struct clk *clk; + struct resource *res; +- unsigned id; ++ unsigned int id, nchannels; + int i; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -222,21 +228,24 @@ ltq_dma_init(struct platform_device *pdev) + clk_enable(clk); + ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL); + ++ usleep_range(1, 10); ++ + /* disable all interrupts */ + ltq_dma_w32(0, LTQ_DMA_IRNEN); + + /* reset/configure each channel */ +- for (i = 0; i < DMA_MAX_CHANNEL; i++) { ++ id = ltq_dma_r32(LTQ_DMA_ID); ++ nchannels = ((id & DMA_ID_CHNR) >> 20); ++ for (i = 0; i < nchannels; i++) { + ltq_dma_w32(i, LTQ_DMA_CS); + ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL); + ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL); + ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL); + } + +- id = ltq_dma_r32(LTQ_DMA_ID); + dev_info(&pdev->dev, + "Init done - hw rev: %X, ports: %d, channels: %d\n", +- id & 0x1f, (id >> 16) & 0xf, id >> 20); ++ id & 0x1f, (id >> 16) & 0xf, nchannels); + + return 0; + } +diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S +index a46db08071953..7767137c3e49a 100644 +--- a/arch/mips/lib/csum_partial.S ++++ b/arch/mips/lib/csum_partial.S +@@ -347,7 +347,7 @@ EXPORT_SYMBOL(csum_partial) + .if \mode == LEGACY_MODE; \ + 9: insn reg, addr; \ + .section __ex_table,"a"; \ +- PTR 9b, .L_exc; \ ++ PTR_WD 9b, .L_exc; \ + .previous; \ + /* This is enabled in EVA mode */ \ + .else; \ +@@ -356,7 +356,7 @@ EXPORT_SYMBOL(csum_partial) + ((\to == USEROP) && (type == ST_INSN)); \ + 9: __BUILD_EVA_INSN(insn##e, reg, addr); \ + .section __ex_table,"a"; \ +- PTR 9b, .L_exc; \ ++ PTR_WD 9b, .L_exc; \ + .previous; \ + .else; \ + /* EVA without exception */ \ +diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S +index 277c32296636d..18a43f2e29c81 100644 +--- a/arch/mips/lib/memcpy.S ++++ b/arch/mips/lib/memcpy.S +@@ -116,7 +116,7 @@ + .if \mode == LEGACY_MODE; \ + 9: insn reg, addr; \ + .section __ex_table,"a"; \ +- PTR 9b, handler; \ ++ PTR_WD 9b, handler; \ + .previous; \ + /* This is assembled in EVA mode */ \ + .else; \ +@@ -125,7 +125,7 @@ + ((\to == USEROP) && (type == ST_INSN)); \ + 9: __BUILD_EVA_INSN(insn##e, reg, addr); \ + .section __ex_table,"a"; \ +- PTR 9b, handler; \ ++ PTR_WD 9b, handler; \ + .previous; \ + .else; \ + /* \ +diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S +index b0baa3c79fad0..0b342bae9a98c 100644 +--- a/arch/mips/lib/memset.S ++++ b/arch/mips/lib/memset.S +@@ -52,7 +52,7 @@ + 9: ___BUILD_EVA_INSN(insn, reg, addr); \ + .endif; \ + .section __ex_table,"a"; \ +- PTR 9b, handler; \ ++ PTR_WD 9b, handler; \ + .previous + + .macro f_fill64 dst, offset, val, fixup, mode +diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S +index 556acf684d7be..13aaa9927ad12 100644 +--- a/arch/mips/lib/strncpy_user.S ++++ b/arch/mips/lib/strncpy_user.S +@@ -15,7 +15,7 @@ + #define EX(insn,reg,addr,handler) \ + 9: insn reg, addr; \ + .section __ex_table,"a"; \ +- PTR 9b, handler; \ ++ PTR_WD 9b, handler; \ + .previous + + /* +@@ -59,7 +59,7 @@ LEAF(__strncpy_from_user_asm) + jr ra + + .section __ex_table,"a" +- PTR 1b, .Lfault ++ PTR_WD 1b, .Lfault + .previous + + EXPORT_SYMBOL(__strncpy_from_user_asm) +diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S +index 92b63f20ec05f..6de31b616f9c1 100644 +--- a/arch/mips/lib/strnlen_user.S ++++ b/arch/mips/lib/strnlen_user.S +@@ -14,7 +14,7 @@ + #define EX(insn,reg,addr,handler) \ + 9: insn reg, addr; \ + .section __ex_table,"a"; \ +- PTR 9b, handler; \ ++ PTR_WD 9b, handler; \ + .previous + + /* +diff --git a/arch/mips/loongson64/vbios_quirk.c b/arch/mips/loongson64/vbios_quirk.c +index 9a29e94d3db1d..3115d4de982c5 100644 +--- a/arch/mips/loongson64/vbios_quirk.c ++++ b/arch/mips/loongson64/vbios_quirk.c +@@ -3,7 +3,7 @@ + #include <linux/pci.h> + #include <loongson.h> + +-static void pci_fixup_radeon(struct pci_dev *pdev) ++static void pci_fixup_video(struct pci_dev *pdev) + { + struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; + +@@ -22,8 +22,7 @@ static void pci_fixup_radeon(struct pci_dev *pdev) + res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW | + IORESOURCE_PCI_FIXED; + +- dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n", +- PCI_ROM_RESOURCE, res); ++ dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n", res); + } +-DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, 0x9615, +- PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon); ++DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, 0x9615, ++ PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); +diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c +index bd71f5b142383..4c83786612193 100644 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -20,31 +20,41 @@ + + #include "common.h" + +-static void *detect_magic __initdata = detect_memory_region; ++#define MT7621_MEM_TEST_PATTERN 0xaa5555aa ++ ++static u32 detect_magic __initdata; + + phys_addr_t mips_cpc_default_phys_base(void) + { + panic("Cannot detect cpc address"); + } + ++static bool __init mt7621_addr_wraparound_test(phys_addr_t size) ++{ ++ void *dm = (void *)KSEG1ADDR(&detect_magic); ++ ++ if (CPHYSADDR(dm + size) >= MT7621_LOWMEM_MAX_SIZE) ++ return true; ++ __raw_writel(MT7621_MEM_TEST_PATTERN, dm); ++ if (__raw_readl(dm) != __raw_readl(dm + size)) ++ return false; ++ __raw_writel(~MT7621_MEM_TEST_PATTERN, dm); ++ return __raw_readl(dm) == __raw_readl(dm + size); ++} ++ + static void __init mt7621_memory_detect(void) + { +- void *dm = &detect_magic; + phys_addr_t size; + +- for (size = 32 * SZ_1M; size < 256 * SZ_1M; size <<= 1) { +- if (!__builtin_memcmp(dm, dm + size, sizeof(detect_magic))) +- break; ++ for (size = 32 * SZ_1M; size <= 256 * SZ_1M; size <<= 1) { ++ if (mt7621_addr_wraparound_test(size)) { ++ memblock_add(MT7621_LOWMEM_BASE, size); ++ return; ++ } + } + +- if ((size == 256 * SZ_1M) && +- (CPHYSADDR(dm + size) < MT7621_LOWMEM_MAX_SIZE) && +- __builtin_memcmp(dm, dm + size, sizeof(detect_magic))) { +- memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE); +- memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE); +- } else { +- memblock_add(MT7621_LOWMEM_BASE, size); +- } ++ memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE); ++ memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE); + } + + void __init ralink_of_remap(void) +diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c +index 240bb68ec2478..ff3ba7e778901 100644 +--- a/arch/mips/sni/time.c ++++ b/arch/mips/sni/time.c +@@ -18,14 +18,14 @@ static int a20r_set_periodic(struct clock_event_device *evt) + { + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34; + wmb(); +- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV; ++ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV & 0xff; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8; + wmb(); + + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4; + wmb(); +- *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV; ++ *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV & 0xff; + wmb(); + *(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8; + wmb(); +diff --git a/arch/nds32/kernel/perf_event_cpu.c b/arch/nds32/kernel/perf_event_cpu.c +index 0ce6f9f307e6a..f387919607813 100644 +--- a/arch/nds32/kernel/perf_event_cpu.c ++++ b/arch/nds32/kernel/perf_event_cpu.c +@@ -1363,6 +1363,7 @@ void + perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + unsigned long fp = 0; + unsigned long gp = 0; + unsigned long lp = 0; +@@ -1371,7 +1372,7 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, + + leaf_fp = 0; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* We don't support guest os callchain now */ + return; + } +@@ -1479,9 +1480,10 @@ void + perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct stackframe fr; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* We don't support guest os callchain now */ + return; + } +@@ -1493,20 +1495,23 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + + unsigned long perf_instruction_pointer(struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); ++ + /* However, NDS32 does not support virtualization */ +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) +- return perf_guest_cbs->get_guest_ip(); ++ if (guest_cbs && guest_cbs->is_in_guest()) ++ return guest_cbs->get_guest_ip(); + + return instruction_pointer(regs); + } + + unsigned long perf_misc_flags(struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + int misc = 0; + + /* However, NDS32 does not support virtualization */ +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { +- if (perf_guest_cbs->is_user_mode()) ++ if (guest_cbs && guest_cbs->is_in_guest()) { ++ if (guest_cbs->is_user_mode()) + misc |= PERF_RECORD_MISC_GUEST_USER; + else + misc |= PERF_RECORD_MISC_GUEST_KERNEL; +diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h +index 3a7eeae6f56a8..aa1c7e98722e3 100644 +--- a/arch/openrisc/include/asm/syscalls.h ++++ b/arch/openrisc/include/asm/syscalls.h +@@ -22,9 +22,11 @@ asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1, + + asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp, + void __user *parent_tid, void __user *child_tid, int tls); ++asmlinkage long __sys_clone3(struct clone_args __user *uargs, size_t size); + asmlinkage long __sys_fork(void); + + #define sys_clone __sys_clone ++#define sys_clone3 __sys_clone3 + #define sys_fork __sys_fork + + #endif /* __ASM_OPENRISC_SYSCALLS_H */ +diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c +index 1b16d97e7da7f..a82b2caaa560d 100644 +--- a/arch/openrisc/kernel/dma.c ++++ b/arch/openrisc/kernel/dma.c +@@ -33,7 +33,7 @@ page_set_nocache(pte_t *pte, unsigned long addr, + * Flush the page out of the TLB so that the new page flags get + * picked up next time there's an access + */ +- flush_tlb_page(NULL, addr); ++ flush_tlb_kernel_range(addr, addr + PAGE_SIZE); + + /* Flush page out of dcache */ + for (cl = __pa(addr); cl < __pa(next); cl += cpuinfo->dcache_block_size) +@@ -56,7 +56,7 @@ page_clear_nocache(pte_t *pte, unsigned long addr, + * Flush the page out of the TLB so that the new page flags get + * picked up next time there's an access + */ +- flush_tlb_page(NULL, addr); ++ flush_tlb_kernel_range(addr, addr + PAGE_SIZE); + + return 0; + } +diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S +index edaa775a648e6..c68f3349c1741 100644 +--- a/arch/openrisc/kernel/entry.S ++++ b/arch/openrisc/kernel/entry.S +@@ -1170,6 +1170,11 @@ ENTRY(__sys_clone) + l.j _fork_save_extra_regs_and_call + l.nop + ++ENTRY(__sys_clone3) ++ l.movhi r29,hi(sys_clone3) ++ l.j _fork_save_extra_regs_and_call ++ l.ori r29,r29,lo(sys_clone3) ++ + ENTRY(__sys_fork) + l.movhi r29,hi(sys_fork) + l.ori r29,r29,lo(sys_fork) +diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c +index 415e209732a3d..ba78766cf00b5 100644 +--- a/arch/openrisc/kernel/smp.c ++++ b/arch/openrisc/kernel/smp.c +@@ -272,7 +272,7 @@ static inline void ipi_flush_tlb_range(void *info) + local_flush_tlb_range(NULL, fd->addr1, fd->addr2); + } + +-static void smp_flush_tlb_range(struct cpumask *cmask, unsigned long start, ++static void smp_flush_tlb_range(const struct cpumask *cmask, unsigned long start, + unsigned long end) + { + unsigned int cpuid; +@@ -320,7 +320,9 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) + void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) + { +- smp_flush_tlb_range(mm_cpumask(vma->vm_mm), start, end); ++ const struct cpumask *cmask = vma ? mm_cpumask(vma->vm_mm) ++ : cpu_online_mask; ++ smp_flush_tlb_range(cmask, start, end); + } + + /* Instruction cache invalidate - performed on each cpu */ +diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile +index fcde3ffa02213..fadb098de1545 100644 +--- a/arch/parisc/Makefile ++++ b/arch/parisc/Makefile +@@ -17,7 +17,12 @@ + # Mike Shaver, Helge Deller and Martin K. Petersen + # + ++ifdef CONFIG_PARISC_SELF_EXTRACT ++boot := arch/parisc/boot ++KBUILD_IMAGE := $(boot)/bzImage ++else + KBUILD_IMAGE := vmlinuz ++endif + + NM = sh $(srctree)/arch/parisc/nm + CHECKFLAGS += -D__hppa__=1 +diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h +index aa4e883431c1a..5779d463b341f 100644 +--- a/arch/parisc/include/asm/bitops.h ++++ b/arch/parisc/include/asm/bitops.h +@@ -12,6 +12,14 @@ + #include <asm/barrier.h> + #include <linux/atomic.h> + ++/* compiler build environment sanity checks: */ ++#if !defined(CONFIG_64BIT) && defined(__LP64__) ++#error "Please use 'ARCH=parisc' to build the 32-bit kernel." ++#endif ++#if defined(CONFIG_64BIT) && !defined(__LP64__) ++#error "Please use 'ARCH=parisc64' to build the 64-bit kernel." ++#endif ++ + /* See http://marc.theaimsgroup.com/?t=108826637900003 for discussion + * on use of volatile and __*_bit() (set/clear/change): + * *_bit() want use of volatile. +diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h +index fceb9cf02fb3a..71aa0921d6c72 100644 +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -16,7 +16,7 @@ static inline void + _futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags) + { + extern u32 lws_lock_start[]; +- long index = ((long)uaddr & 0x3f8) >> 1; ++ long index = ((long)uaddr & 0x7f8) >> 1; + arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index]; + local_irq_save(*flags); + arch_spin_lock(s); +@@ -26,7 +26,7 @@ static inline void + _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags) + { + extern u32 lws_lock_start[]; +- long index = ((long)uaddr & 0x3f8) >> 1; ++ long index = ((long)uaddr & 0x7f8) >> 1; + arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index]; + arch_spin_unlock(s); + local_irq_restore(*flags); +diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h +index 7badd872f05ac..3e7cf882639fb 100644 +--- a/arch/parisc/include/asm/pgtable.h ++++ b/arch/parisc/include/asm/pgtable.h +@@ -76,6 +76,8 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) + purge_tlb_end(flags); + } + ++extern void __update_cache(pte_t pte); ++ + /* Certain architectures need to do special things when PTEs + * within a page table are directly modified. Thus, the following + * hook is made available. +@@ -83,11 +85,14 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) + #define set_pte(pteptr, pteval) \ + do { \ + *(pteptr) = (pteval); \ +- barrier(); \ ++ mb(); \ + } while(0) + + #define set_pte_at(mm, addr, pteptr, pteval) \ + do { \ ++ if (pte_present(pteval) && \ ++ pte_user(pteval)) \ ++ __update_cache(pteval); \ + *(pteptr) = (pteval); \ + purge_tlb_entries(mm, addr); \ + } while (0) +@@ -303,6 +308,7 @@ extern unsigned long *empty_zero_page; + + #define pte_none(x) (pte_val(x) == 0) + #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) ++#define pte_user(x) (pte_val(x) & _PAGE_USER) + #define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0)) + + #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) +@@ -410,7 +416,7 @@ extern void paging_init (void); + + #define PG_dcache_dirty PG_arch_1 + +-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); ++#define update_mmu_cache(vms,addr,ptep) __update_cache(*ptep) + + /* Encode and de-code a swap entry */ + +diff --git a/arch/parisc/include/asm/rt_sigframe.h b/arch/parisc/include/asm/rt_sigframe.h +index 4b9e3d707571b..2b3010ade00e7 100644 +--- a/arch/parisc/include/asm/rt_sigframe.h ++++ b/arch/parisc/include/asm/rt_sigframe.h +@@ -2,7 +2,7 @@ + #ifndef _ASM_PARISC_RT_SIGFRAME_H + #define _ASM_PARISC_RT_SIGFRAME_H + +-#define SIGRETURN_TRAMP 3 ++#define SIGRETURN_TRAMP 4 + #define SIGRESTARTBLOCK_TRAMP 5 + #define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP) + +diff --git a/arch/parisc/include/asm/special_insns.h b/arch/parisc/include/asm/special_insns.h +index a303ae9a77f41..16ee41e77174f 100644 +--- a/arch/parisc/include/asm/special_insns.h ++++ b/arch/parisc/include/asm/special_insns.h +@@ -2,28 +2,32 @@ + #ifndef __PARISC_SPECIAL_INSNS_H + #define __PARISC_SPECIAL_INSNS_H + +-#define lpa(va) ({ \ +- unsigned long pa; \ +- __asm__ __volatile__( \ +- "copy %%r0,%0\n\t" \ +- "lpa %%r0(%1),%0" \ +- : "=r" (pa) \ +- : "r" (va) \ +- : "memory" \ +- ); \ +- pa; \ ++#define lpa(va) ({ \ ++ unsigned long pa; \ ++ __asm__ __volatile__( \ ++ "copy %%r0,%0\n" \ ++ "8:\tlpa %%r0(%1),%0\n" \ ++ "9:\n" \ ++ ASM_EXCEPTIONTABLE_ENTRY(8b, 9b) \ ++ : "=&r" (pa) \ ++ : "r" (va) \ ++ : "memory" \ ++ ); \ ++ pa; \ + }) + +-#define lpa_user(va) ({ \ +- unsigned long pa; \ +- __asm__ __volatile__( \ +- "copy %%r0,%0\n\t" \ +- "lpa %%r0(%%sr3,%1),%0" \ +- : "=r" (pa) \ +- : "r" (va) \ +- : "memory" \ +- ); \ +- pa; \ ++#define lpa_user(va) ({ \ ++ unsigned long pa; \ ++ __asm__ __volatile__( \ ++ "copy %%r0,%0\n" \ ++ "8:\tlpa %%r0(%%sr3,%1),%0\n" \ ++ "9:\n" \ ++ ASM_EXCEPTIONTABLE_ENTRY(8b, 9b) \ ++ : "=&r" (pa) \ ++ : "r" (va) \ ++ : "memory" \ ++ ); \ ++ pa; \ + }) + + #define mfctl(reg) ({ \ +diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh +index 056d588befdd6..70d3cffb02515 100644 +--- a/arch/parisc/install.sh ++++ b/arch/parisc/install.sh +@@ -39,6 +39,7 @@ verify "$3" + if [ -n "${INSTALLKERNEL}" ]; then + if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi + if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi ++ if [ -x /usr/sbin/${INSTALLKERNEL} ]; then exec /usr/sbin/${INSTALLKERNEL} "$@"; fi + fi + + # Default install +diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c +index 39e02227e2310..4ed4942d8312b 100644 +--- a/arch/parisc/kernel/cache.c ++++ b/arch/parisc/kernel/cache.c +@@ -83,9 +83,9 @@ EXPORT_SYMBOL(flush_cache_all_local); + #define pfn_va(pfn) __va(PFN_PHYS(pfn)) + + void +-update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) ++__update_cache(pte_t pte) + { +- unsigned long pfn = pte_pfn(*ptep); ++ unsigned long pfn = pte_pfn(pte); + struct page *page; + + /* We don't have pte special. As a result, we can be called with +diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S +index 9f939afe6b88c..437c8d31f3907 100644 +--- a/arch/parisc/kernel/entry.S ++++ b/arch/parisc/kernel/entry.S +@@ -1834,8 +1834,8 @@ syscall_restore: + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + + /* Are we being ptraced? */ +- ldw TASK_FLAGS(%r1),%r19 +- ldi _TIF_SYSCALL_TRACE_MASK,%r2 ++ LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 ++ ldi _TIF_SINGLESTEP|_TIF_BLOCKSTEP,%r2 + and,COND(=) %r19,%r2,%r0 + b,n syscall_restore_rfi + +diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c +index bbfe23c40c016..0fb06d87b3a5c 100644 +--- a/arch/parisc/kernel/signal.c ++++ b/arch/parisc/kernel/signal.c +@@ -288,21 +288,22 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, + already in userspace. The first words of tramp are used to + save the previous sigrestartblock trampoline that might be + on the stack. We start the sigreturn trampoline at +- SIGRESTARTBLOCK_TRAMP. */ ++ SIGRESTARTBLOCK_TRAMP+X. */ + err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0, + &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]); +- err |= __put_user(INSN_BLE_SR2_R0, +- &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]); + err |= __put_user(INSN_LDI_R20, ++ &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]); ++ err |= __put_user(INSN_BLE_SR2_R0, + &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]); ++ err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]); + +- start = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]; +- end = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]; ++ start = (unsigned long) &frame->tramp[0]; ++ end = (unsigned long) &frame->tramp[TRAMP_SIZE]; + flush_user_dcache_range_asm(start, end); + flush_user_icache_range_asm(start, end); + + /* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP +- * TRAMP Words 5-7, Length 3 = SIGRETURN_TRAMP ++ * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP + * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP + */ + rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP]; +diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h +index a5bdbb5678b72..f166250f2d064 100644 +--- a/arch/parisc/kernel/signal32.h ++++ b/arch/parisc/kernel/signal32.h +@@ -36,7 +36,7 @@ struct compat_regfile { + compat_int_t rf_sar; + }; + +-#define COMPAT_SIGRETURN_TRAMP 3 ++#define COMPAT_SIGRETURN_TRAMP 4 + #define COMPAT_SIGRESTARTBLOCK_TRAMP 5 + #define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + \ + COMPAT_SIGRESTARTBLOCK_TRAMP) +diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c +index 1405b603b91b6..cf92ece20b757 100644 +--- a/arch/parisc/kernel/smp.c ++++ b/arch/parisc/kernel/smp.c +@@ -29,6 +29,7 @@ + #include <linux/bitops.h> + #include <linux/ftrace.h> + #include <linux/cpu.h> ++#include <linux/kgdb.h> + + #include <linux/atomic.h> + #include <asm/current.h> +@@ -69,7 +70,10 @@ enum ipi_message_type { + IPI_CALL_FUNC, + IPI_CPU_START, + IPI_CPU_STOP, +- IPI_CPU_TEST ++ IPI_CPU_TEST, ++#ifdef CONFIG_KGDB ++ IPI_ENTER_KGDB, ++#endif + }; + + +@@ -167,7 +171,12 @@ ipi_interrupt(int irq, void *dev_id) + case IPI_CPU_TEST: + smp_debug(100, KERN_DEBUG "CPU%d is alive!\n", this_cpu); + break; +- ++#ifdef CONFIG_KGDB ++ case IPI_ENTER_KGDB: ++ smp_debug(100, KERN_DEBUG "CPU%d ENTER_KGDB\n", this_cpu); ++ kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); ++ break; ++#endif + default: + printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", + this_cpu, which); +@@ -226,6 +235,12 @@ send_IPI_allbutself(enum ipi_message_type op) + } + } + ++#ifdef CONFIG_KGDB ++void kgdb_roundup_cpus(void) ++{ ++ send_IPI_allbutself(IPI_ENTER_KGDB); ++} ++#endif + + inline void + smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } +diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S +index 3f24a0af1e047..9842dcb2041e5 100644 +--- a/arch/parisc/kernel/syscall.S ++++ b/arch/parisc/kernel/syscall.S +@@ -478,7 +478,7 @@ lws_start: + extrd,u %r1,PSW_W_BIT,1,%r1 + /* sp must be aligned on 4, so deposit the W bit setting into + * the bottom of sp temporarily */ +- or,ev %r1,%r30,%r30 ++ or,od %r1,%r30,%r30 + + /* Clip LWS number to a 32-bit value for 32-bit processes */ + depdi 0, 31, 32, %r20 +diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c +index 9fb1e794831b0..061119a56fbe8 100644 +--- a/arch/parisc/kernel/time.c ++++ b/arch/parisc/kernel/time.c +@@ -249,30 +249,16 @@ void __init time_init(void) + static int __init init_cr16_clocksource(void) + { + /* +- * The cr16 interval timers are not syncronized across CPUs on +- * different sockets, so mark them unstable and lower rating on +- * multi-socket SMP systems. ++ * The cr16 interval timers are not syncronized across CPUs, even if ++ * they share the same socket. + */ + if (num_online_cpus() > 1 && !running_on_qemu) { +- int cpu; +- unsigned long cpu0_loc; +- cpu0_loc = per_cpu(cpu_data, 0).cpu_loc; +- +- for_each_online_cpu(cpu) { +- if (cpu == 0) +- continue; +- if ((cpu0_loc != 0) && +- (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc)) +- continue; +- +- /* mark sched_clock unstable */ +- clear_sched_clock_stable(); +- +- clocksource_cr16.name = "cr16_unstable"; +- clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; +- clocksource_cr16.rating = 0; +- break; +- } ++ /* mark sched_clock unstable */ ++ clear_sched_clock_stable(); ++ ++ clocksource_cr16.name = "cr16_unstable"; ++ clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; ++ clocksource_cr16.rating = 0; + } + + /* register at clocksource framework */ +diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c +index 747c328fb8862..afe8b902a8fc4 100644 +--- a/arch/parisc/kernel/traps.c ++++ b/arch/parisc/kernel/traps.c +@@ -729,6 +729,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs) + } + mmap_read_unlock(current->mm); + } ++ /* CPU could not fetch instruction, so clear stale IIR value. */ ++ regs->iir = 0xbaadf00d; + fallthrough; + case 27: + /* Data memory protection ID trap */ +@@ -782,7 +784,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) + * unless pagefault_disable() was called before. + */ + +- if (fault_space == 0 && !faulthandler_disabled()) ++ if (faulthandler_disabled() || fault_space == 0) + { + /* Clean up and return if in exception table. */ + if (fixup_exception(regs)) +diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c +index 237d20dd5622d..286cec4d86d7b 100644 +--- a/arch/parisc/kernel/unaligned.c ++++ b/arch/parisc/kernel/unaligned.c +@@ -340,7 +340,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop) + : "r" (val), "r" (regs->ior), "r" (regs->isr) + : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER ); + +- return 0; ++ return ret; + } + static int emulate_std(struct pt_regs *regs, int frreg, int flop) + { +@@ -397,7 +397,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) + __asm__ __volatile__ ( + " mtsp %4, %%sr1\n" + " zdep %2, 29, 2, %%r19\n" +-" dep %%r0, 31, 2, %2\n" ++" dep %%r0, 31, 2, %3\n" + " mtsar %%r19\n" + " zvdepi -2, 32, %%r19\n" + "1: ldw 0(%%sr1,%3),%%r20\n" +@@ -409,7 +409,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) + " andcm %%r21, %%r19, %%r21\n" + " or %1, %%r20, %1\n" + " or %2, %%r21, %2\n" +-"3: stw %1,0(%%sr1,%1)\n" ++"3: stw %1,0(%%sr1,%3)\n" + "4: stw %%r1,4(%%sr1,%3)\n" + "5: stw %2,8(%%sr1,%3)\n" + " copy %%r0, %0\n" +@@ -596,7 +596,6 @@ void handle_unaligned(struct pt_regs *regs) + ret = ERR_NOTHANDLED; /* "undefined", but lets kill them. */ + break; + } +-#ifdef CONFIG_PA20 + switch (regs->iir & OPCODE2_MASK) + { + case OPCODE_FLDD_L: +@@ -607,22 +606,23 @@ void handle_unaligned(struct pt_regs *regs) + flop=1; + ret = emulate_std(regs, R2(regs->iir),1); + break; ++#ifdef CONFIG_PA20 + case OPCODE_LDD_L: + ret = emulate_ldd(regs, R2(regs->iir),0); + break; + case OPCODE_STD_L: + ret = emulate_std(regs, R2(regs->iir),0); + break; +- } + #endif ++ } + switch (regs->iir & OPCODE3_MASK) + { + case OPCODE_FLDW_L: + flop=1; +- ret = emulate_ldw(regs, R2(regs->iir),0); ++ ret = emulate_ldw(regs, R2(regs->iir), 1); + break; + case OPCODE_LDW_M: +- ret = emulate_ldw(regs, R2(regs->iir),1); ++ ret = emulate_ldw(regs, R2(regs->iir), 0); + break; + + case OPCODE_FSTW_L: +diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c +index 87ae476d1c4f5..86a57fb0e6fae 100644 +--- a/arch/parisc/kernel/unwind.c ++++ b/arch/parisc/kernel/unwind.c +@@ -21,6 +21,8 @@ + #include <asm/ptrace.h> + + #include <asm/unwind.h> ++#include <asm/switch_to.h> ++#include <asm/sections.h> + + /* #define DEBUG 1 */ + #ifdef DEBUG +@@ -203,6 +205,11 @@ int __init unwind_init(void) + return 0; + } + ++static bool pc_is_kernel_fn(unsigned long pc, void *fn) ++{ ++ return (unsigned long)dereference_kernel_function_descriptor(fn) == pc; ++} ++ + static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) + { + /* +@@ -221,7 +228,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int + extern void * const _call_on_stack; + #endif /* CONFIG_IRQSTACKS */ + +- if (pc == (unsigned long) &handle_interruption) { ++ if (pc_is_kernel_fn(pc, handle_interruption)) { + struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); + dbg("Unwinding through handle_interruption()\n"); + info->prev_sp = regs->gr[30]; +@@ -229,13 +236,13 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int + return 1; + } + +- if (pc == (unsigned long) &ret_from_kernel_thread || +- pc == (unsigned long) &syscall_exit) { ++ if (pc_is_kernel_fn(pc, ret_from_kernel_thread) || ++ pc_is_kernel_fn(pc, syscall_exit)) { + info->prev_sp = info->prev_ip = 0; + return 1; + } + +- if (pc == (unsigned long) &intr_return) { ++ if (pc_is_kernel_fn(pc, intr_return)) { + struct pt_regs *regs; + + dbg("Found intr_return()\n"); +@@ -246,20 +253,20 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int + return 1; + } + +- if (pc == (unsigned long) &_switch_to_ret) { ++ if (pc_is_kernel_fn(pc, _switch_to) || ++ pc_is_kernel_fn(pc, _switch_to_ret)) { + info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; + info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); + return 1; + } + + #ifdef CONFIG_IRQSTACKS +- if (pc == (unsigned long) &_call_on_stack) { ++ if (pc_is_kernel_fn(pc, _call_on_stack)) { + info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ); + info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET); + return 1; + } + #endif +- + return 0; + } + +diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c +index 367f6397bda7a..8603850580857 100644 +--- a/arch/parisc/lib/iomap.c ++++ b/arch/parisc/lib/iomap.c +@@ -346,6 +346,16 @@ u64 ioread64be(const void __iomem *addr) + return *((u64 *)addr); + } + ++u64 ioread64_lo_hi(const void __iomem *addr) ++{ ++ u32 low, high; ++ ++ low = ioread32(addr); ++ high = ioread32(addr + sizeof(u32)); ++ ++ return low + ((u64)high << 32); ++} ++ + u64 ioread64_hi_lo(const void __iomem *addr) + { + u32 low, high; +@@ -419,6 +429,12 @@ void iowrite64be(u64 datum, void __iomem *addr) + } + } + ++void iowrite64_lo_hi(u64 val, void __iomem *addr) ++{ ++ iowrite32(val, addr); ++ iowrite32(val >> 32, addr + sizeof(u32)); ++} ++ + void iowrite64_hi_lo(u64 val, void __iomem *addr) + { + iowrite32(val >> 32, addr + sizeof(u32)); +@@ -530,6 +546,7 @@ EXPORT_SYMBOL(ioread32); + EXPORT_SYMBOL(ioread32be); + EXPORT_SYMBOL(ioread64); + EXPORT_SYMBOL(ioread64be); ++EXPORT_SYMBOL(ioread64_lo_hi); + EXPORT_SYMBOL(ioread64_hi_lo); + EXPORT_SYMBOL(iowrite8); + EXPORT_SYMBOL(iowrite16); +@@ -538,6 +555,7 @@ EXPORT_SYMBOL(iowrite32); + EXPORT_SYMBOL(iowrite32be); + EXPORT_SYMBOL(iowrite64); + EXPORT_SYMBOL(iowrite64be); ++EXPORT_SYMBOL(iowrite64_lo_hi); + EXPORT_SYMBOL(iowrite64_hi_lo); + EXPORT_SYMBOL(ioread8_rep); + EXPORT_SYMBOL(ioread16_rep); +diff --git a/arch/parisc/mm/fixmap.c b/arch/parisc/mm/fixmap.c +index 24426a7e1a5e5..cc15d737fda64 100644 +--- a/arch/parisc/mm/fixmap.c ++++ b/arch/parisc/mm/fixmap.c +@@ -20,12 +20,9 @@ void notrace set_fixmap(enum fixed_addresses idx, phys_addr_t phys) + pte_t *pte; + + if (pmd_none(*pmd)) +- pmd = pmd_alloc(NULL, pud, vaddr); +- +- pte = pte_offset_kernel(pmd, vaddr); +- if (pte_none(*pte)) + pte = pte_alloc_kernel(pmd, vaddr); + ++ pte = pte_offset_kernel(pmd, vaddr); + set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); + flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); + } +diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c +index 3f7d6d5b56ac8..e5c18313b5d4f 100644 +--- a/arch/parisc/mm/init.c ++++ b/arch/parisc/mm/init.c +@@ -341,9 +341,9 @@ static void __init setup_bootmem(void) + + static bool kernel_set_to_readonly; + +-static void __init map_pages(unsigned long start_vaddr, +- unsigned long start_paddr, unsigned long size, +- pgprot_t pgprot, int force) ++static void __ref map_pages(unsigned long start_vaddr, ++ unsigned long start_paddr, unsigned long size, ++ pgprot_t pgprot, int force) + { + pmd_t *pmd; + pte_t *pg_table; +@@ -453,7 +453,7 @@ void __init set_kernel_text_rw(int enable_read_write) + flush_tlb_all(); + } + +-void __ref free_initmem(void) ++void free_initmem(void) + { + unsigned long init_begin = (unsigned long)__init_begin; + unsigned long init_end = (unsigned long)__init_end; +@@ -467,7 +467,6 @@ void __ref free_initmem(void) + /* The init text pages are marked R-X. We have to + * flush the icache and mark them RW- + * +- * This is tricky, because map_pages is in the init section. + * Do a dummy remap of the data section first (the data + * section is already PAGE_KERNEL) to pull in the TLB entries + * for map_kernel */ +@@ -842,9 +841,9 @@ void flush_tlb_all(void) + { + int do_recycle; + +- __inc_irq_stat(irq_tlb_count); + do_recycle = 0; + spin_lock(&sid_lock); ++ __inc_irq_stat(irq_tlb_count); + if (dirty_space_ids > RECYCLE_THRESHOLD) { + BUG_ON(recycle_inuse); /* FIXME: Use a semaphore/wait queue here */ + get_dirty_sids(&recycle_ndirty,recycle_dirty_array); +@@ -863,8 +862,8 @@ void flush_tlb_all(void) + #else + void flush_tlb_all(void) + { +- __inc_irq_stat(irq_tlb_count); + spin_lock(&sid_lock); ++ __inc_irq_stat(irq_tlb_count); + flush_tlb_all_local(NULL); + recycle_sids(); + spin_unlock(&sid_lock); +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index ba5b661893588..6b9f523882c58 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -138,7 +138,7 @@ config PPC + select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64 + select ARCH_HAS_SET_MEMORY +- select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION) ++ select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION + select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32 + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST + select ARCH_HAS_UACCESS_FLUSHCACHE +@@ -150,7 +150,7 @@ config PPC + select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX + select ARCH_STACKWALK + select ARCH_SUPPORTS_ATOMIC_RMW +- select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC32 || PPC_BOOK3S_64 ++ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x + select ARCH_USE_BUILTIN_BSWAP + select ARCH_USE_CMPXCHG_LOCKREF if PPC64 + select ARCH_USE_MEMTEST +@@ -190,7 +190,7 @@ config PPC + select HAVE_ARCH_JUMP_LABEL_RELATIVE + select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14 + select HAVE_ARCH_KASAN_VMALLOC if PPC32 && PPC_PAGE_SHIFT <= 14 +- select HAVE_ARCH_KFENCE if PPC32 ++ select HAVE_ARCH_KFENCE if PPC_BOOK3S_32 || PPC_8xx || 40x + select HAVE_ARCH_KGDB + select HAVE_ARCH_MMAP_RND_BITS + select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT +diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts +index 408b486b13dff..cd589539f313f 100644 +--- a/arch/powerpc/boot/dts/charon.dts ++++ b/arch/powerpc/boot/dts/charon.dts +@@ -35,7 +35,7 @@ + }; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x08000000>; // 128MB + }; +diff --git a/arch/powerpc/boot/dts/digsy_mtc.dts b/arch/powerpc/boot/dts/digsy_mtc.dts +index 0e5e9d3acf79f..19a14e62e65f4 100644 +--- a/arch/powerpc/boot/dts/digsy_mtc.dts ++++ b/arch/powerpc/boot/dts/digsy_mtc.dts +@@ -16,7 +16,7 @@ + model = "intercontrol,digsy-mtc"; + compatible = "intercontrol,digsy-mtc"; + +- memory { ++ memory@0 { + reg = <0x00000000 0x02000000>; // 32MB + }; + +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi +index c90702b04a530..48e5cd61599c6 100644 +--- a/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi +@@ -79,6 +79,7 @@ fman0: fman@400000 { + #size-cells = <0>; + compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; + reg = <0xfc000 0x1000>; ++ fsl,erratum-a009885; + }; + + xmdio0: mdio@fd000 { +@@ -86,6 +87,7 @@ fman0: fman@400000 { + #size-cells = <0>; + compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; + reg = <0xfd000 0x1000>; ++ fsl,erratum-a009885; + }; + }; + +diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts +index cb2782dd6132c..e7b194775d783 100644 +--- a/arch/powerpc/boot/dts/lite5200.dts ++++ b/arch/powerpc/boot/dts/lite5200.dts +@@ -32,7 +32,7 @@ + }; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x04000000>; // 64MB + }; +diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts +index 2b86c81f90485..547cbe726ff23 100644 +--- a/arch/powerpc/boot/dts/lite5200b.dts ++++ b/arch/powerpc/boot/dts/lite5200b.dts +@@ -31,7 +31,7 @@ + led4 { gpios = <&gpio_simple 2 1>; }; + }; + +- memory { ++ memory@0 { + reg = <0x00000000 0x10000000>; // 256MB + }; + +diff --git a/arch/powerpc/boot/dts/media5200.dts b/arch/powerpc/boot/dts/media5200.dts +index 61cae9dcddef4..f3188018faceb 100644 +--- a/arch/powerpc/boot/dts/media5200.dts ++++ b/arch/powerpc/boot/dts/media5200.dts +@@ -32,7 +32,7 @@ + }; + }; + +- memory { ++ memory@0 { + reg = <0x00000000 0x08000000>; // 128MB RAM + }; + +diff --git a/arch/powerpc/boot/dts/mpc5200b.dtsi b/arch/powerpc/boot/dts/mpc5200b.dtsi +index 648fe31795f49..8b796f3b11da7 100644 +--- a/arch/powerpc/boot/dts/mpc5200b.dtsi ++++ b/arch/powerpc/boot/dts/mpc5200b.dtsi +@@ -33,7 +33,7 @@ + }; + }; + +- memory: memory { ++ memory: memory@0 { + device_type = "memory"; + reg = <0x00000000 0x04000000>; // 64MB + }; +diff --git a/arch/powerpc/boot/dts/o2d.dts b/arch/powerpc/boot/dts/o2d.dts +index 24a46f65e5299..e0a8d3034417f 100644 +--- a/arch/powerpc/boot/dts/o2d.dts ++++ b/arch/powerpc/boot/dts/o2d.dts +@@ -12,7 +12,7 @@ + model = "ifm,o2d"; + compatible = "ifm,o2d"; + +- memory { ++ memory@0 { + reg = <0x00000000 0x08000000>; // 128MB + }; + +diff --git a/arch/powerpc/boot/dts/o2d.dtsi b/arch/powerpc/boot/dts/o2d.dtsi +index 6661955a2be47..b55a9e5bd828c 100644 +--- a/arch/powerpc/boot/dts/o2d.dtsi ++++ b/arch/powerpc/boot/dts/o2d.dtsi +@@ -19,7 +19,7 @@ + model = "ifm,o2d"; + compatible = "ifm,o2d"; + +- memory { ++ memory@0 { + reg = <0x00000000 0x04000000>; // 64MB + }; + +diff --git a/arch/powerpc/boot/dts/o2dnt2.dts b/arch/powerpc/boot/dts/o2dnt2.dts +index eeba7f5507d5d..c2eedbd1f5fcb 100644 +--- a/arch/powerpc/boot/dts/o2dnt2.dts ++++ b/arch/powerpc/boot/dts/o2dnt2.dts +@@ -12,7 +12,7 @@ + model = "ifm,o2dnt2"; + compatible = "ifm,o2d"; + +- memory { ++ memory@0 { + reg = <0x00000000 0x08000000>; // 128MB + }; + +diff --git a/arch/powerpc/boot/dts/o3dnt.dts b/arch/powerpc/boot/dts/o3dnt.dts +index fd00396b0593e..e4c1bdd412716 100644 +--- a/arch/powerpc/boot/dts/o3dnt.dts ++++ b/arch/powerpc/boot/dts/o3dnt.dts +@@ -12,7 +12,7 @@ + model = "ifm,o3dnt"; + compatible = "ifm,o2d"; + +- memory { ++ memory@0 { + reg = <0x00000000 0x04000000>; // 64MB + }; + +diff --git a/arch/powerpc/boot/dts/pcm032.dts b/arch/powerpc/boot/dts/pcm032.dts +index 780e13d99e7b8..1895bc95900cc 100644 +--- a/arch/powerpc/boot/dts/pcm032.dts ++++ b/arch/powerpc/boot/dts/pcm032.dts +@@ -20,7 +20,7 @@ + model = "phytec,pcm032"; + compatible = "phytec,pcm032"; + +- memory { ++ memory@0 { + reg = <0x00000000 0x08000000>; // 128MB + }; + +diff --git a/arch/powerpc/boot/dts/tqm5200.dts b/arch/powerpc/boot/dts/tqm5200.dts +index 9ed0bc78967e1..5bb25a9e40a01 100644 +--- a/arch/powerpc/boot/dts/tqm5200.dts ++++ b/arch/powerpc/boot/dts/tqm5200.dts +@@ -32,7 +32,7 @@ + }; + }; + +- memory { ++ memory@0 { + device_type = "memory"; + reg = <0x00000000 0x04000000>; // 64MB + }; +diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig +index 6697c5e6682f1..bb549cb1c3e33 100644 +--- a/arch/powerpc/configs/ppc6xx_defconfig ++++ b/arch/powerpc/configs/ppc6xx_defconfig +@@ -1022,7 +1022,6 @@ CONFIG_NFSD=m + CONFIG_NFSD_V3_ACL=y + CONFIG_NFSD_V4=y + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_CIFS_UPCALL=y + CONFIG_CIFS_XATTR=y + CONFIG_CIFS_POSIX=y +diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig +index b183629f1bcfb..d0494fbb49617 100644 +--- a/arch/powerpc/configs/pseries_defconfig ++++ b/arch/powerpc/configs/pseries_defconfig +@@ -190,7 +190,6 @@ CONFIG_HVCS=m + CONFIG_VIRTIO_CONSOLE=m + CONFIG_IBM_BSR=m + CONFIG_RAW_DRIVER=y +-CONFIG_MAX_RAW_DEVS=1024 + CONFIG_I2C_CHARDEV=y + CONFIG_FB=y + CONFIG_FIRMWARE_EDID=y +diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h +index f5be185cbdf8d..94ad7acfd0565 100644 +--- a/arch/powerpc/include/asm/book3s/32/mmu-hash.h ++++ b/arch/powerpc/include/asm/book3s/32/mmu-hash.h +@@ -143,6 +143,8 @@ static __always_inline void update_user_segments(u32 val) + update_user_segment(15, val); + } + ++int __init find_free_bat(void); ++unsigned int bat_block_size(unsigned long base, unsigned long top); + #endif /* !__ASSEMBLY__ */ + + /* We happily ignore the smaller BATs on 601, we don't actually use +diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h +index 609c80f671943..f8b94f78403f1 100644 +--- a/arch/powerpc/include/asm/book3s/32/pgtable.h ++++ b/arch/powerpc/include/asm/book3s/32/pgtable.h +@@ -178,6 +178,7 @@ static inline bool pte_user(pte_t pte) + #ifndef __ASSEMBLY__ + + int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); ++void unmap_kernel_page(unsigned long va); + + #endif /* !__ASSEMBLY__ */ + +diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h +index 5d34a8646f081..6866d860d4f30 100644 +--- a/arch/powerpc/include/asm/book3s/64/pgtable.h ++++ b/arch/powerpc/include/asm/book3s/64/pgtable.h +@@ -1082,6 +1082,8 @@ static inline int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t p + return hash__map_kernel_page(ea, pa, prot); + } + ++void unmap_kernel_page(unsigned long va); ++ + static inline int __meminit vmemmap_create_mapping(unsigned long start, + unsigned long page_size, + unsigned long phys) +diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h +index 947b5b9c44241..a832aeafe5601 100644 +--- a/arch/powerpc/include/asm/fixmap.h ++++ b/arch/powerpc/include/asm/fixmap.h +@@ -111,8 +111,10 @@ static inline void __set_fixmap(enum fixed_addresses idx, + BUILD_BUG_ON(idx >= __end_of_fixed_addresses); + else if (WARN_ON(idx >= __end_of_fixed_addresses)) + return; +- +- map_kernel_page(__fix_to_virt(idx), phys, flags); ++ if (pgprot_val(flags)) ++ map_kernel_page(__fix_to_virt(idx), phys, flags); ++ else ++ unmap_kernel_page(__fix_to_virt(idx)); + } + + #define __early_set_fixmap __set_fixmap +diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h +index 21cc571ea9c2d..5c98a950eca0d 100644 +--- a/arch/powerpc/include/asm/hw_irq.h ++++ b/arch/powerpc/include/asm/hw_irq.h +@@ -224,6 +224,42 @@ static inline bool arch_irqs_disabled(void) + return arch_irqs_disabled_flags(arch_local_save_flags()); + } + ++static inline void set_pmi_irq_pending(void) ++{ ++ /* ++ * Invoked from PMU callback functions to set PMI bit in the paca. ++ * This has to be called with irq's disabled (via hard_irq_disable()). ++ */ ++ if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) ++ WARN_ON_ONCE(mfmsr() & MSR_EE); ++ ++ get_paca()->irq_happened |= PACA_IRQ_PMI; ++} ++ ++static inline void clear_pmi_irq_pending(void) ++{ ++ /* ++ * Invoked from PMU callback functions to clear the pending PMI bit ++ * in the paca. ++ */ ++ if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) ++ WARN_ON_ONCE(mfmsr() & MSR_EE); ++ ++ get_paca()->irq_happened &= ~PACA_IRQ_PMI; ++} ++ ++static inline bool pmi_irq_pending(void) ++{ ++ /* ++ * Invoked from PMU callback functions to check if there is a pending ++ * PMI bit in the paca. ++ */ ++ if (get_paca()->irq_happened & PACA_IRQ_PMI) ++ return true; ++ ++ return false; ++} ++ + #ifdef CONFIG_PPC_BOOK3S + /* + * To support disabling and enabling of irq with PMI, set of +@@ -408,6 +444,10 @@ static inline void do_hard_irq_enable(void) + BUILD_BUG(); + } + ++static inline void clear_pmi_irq_pending(void) { } ++static inline void set_pmi_irq_pending(void) { } ++static inline bool pmi_irq_pending(void) { return false; } ++ + static inline void irq_soft_mask_regs_set_state(struct pt_regs *regs, unsigned long val) + { + } +diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h +index 19b6942c6969a..eaf3a562bf1ed 100644 +--- a/arch/powerpc/include/asm/kvm_book3s_64.h ++++ b/arch/powerpc/include/asm/kvm_book3s_64.h +@@ -39,7 +39,6 @@ struct kvm_nested_guest { + pgd_t *shadow_pgtable; /* our page table for this guest */ + u64 l1_gr_to_hr; /* L1's addr of part'n-scoped table */ + u64 process_table; /* process table entry for this guest */ +- u64 hfscr; /* HFSCR that the L1 requested for this nested guest */ + long refcnt; /* number of pointers to this struct */ + struct mutex tlb_lock; /* serialize page faults and tlbies */ + struct kvm_nested_guest *next; +diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h +index 080a7feb77318..0d81a9bf37650 100644 +--- a/arch/powerpc/include/asm/kvm_host.h ++++ b/arch/powerpc/include/asm/kvm_host.h +@@ -814,6 +814,7 @@ struct kvm_vcpu_arch { + + /* For support of nested guests */ + struct kvm_nested_guest *nested; ++ u64 nested_hfscr; /* HFSCR that the L1 requested for the nested guest */ + u32 nested_vcpu_id; + gpa_t nested_io_gpr; + #endif +diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h +index f06ae00f2a65e..63ea4693ccea6 100644 +--- a/arch/powerpc/include/asm/nohash/32/pgtable.h ++++ b/arch/powerpc/include/asm/nohash/32/pgtable.h +@@ -64,6 +64,7 @@ extern int icache_44x_need_flush; + #ifndef __ASSEMBLY__ + + int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); ++void unmap_kernel_page(unsigned long va); + + #endif /* !__ASSEMBLY__ */ + +@@ -193,10 +194,12 @@ static inline pte_t pte_wrprotect(pte_t pte) + } + #endif + ++#ifndef pte_mkexec + static inline pte_t pte_mkexec(pte_t pte) + { + return __pte(pte_val(pte) | _PAGE_EXEC); + } ++#endif + + #define pmd_none(pmd) (!pmd_val(pmd)) + #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) +@@ -306,30 +309,29 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, + } + + #define __HAVE_ARCH_PTEP_SET_WRPROTECT ++#ifndef ptep_set_wrprotect + static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) + { +- unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0))); +- unsigned long set = pte_val(pte_wrprotect(__pte(0))); +- +- pte_update(mm, addr, ptep, clr, set, 0); ++ pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); + } ++#endif + ++#ifndef __ptep_set_access_flags + static inline void __ptep_set_access_flags(struct vm_area_struct *vma, + pte_t *ptep, pte_t entry, + unsigned long address, + int psize) + { +- pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0))))); +- pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0))))); +- unsigned long set = pte_val(entry) & pte_val(pte_set); +- unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr); ++ unsigned long set = pte_val(entry) & ++ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); + int huge = psize > mmu_virtual_psize ? 1 : 0; + +- pte_update(vma->vm_mm, address, ptep, clr, set, huge); ++ pte_update(vma->vm_mm, address, ptep, 0, set, huge); + + flush_tlb_page(vma, address); + } ++#endif + + static inline int pte_young(pte_t pte) + { +diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h +index fcc48d590d888..1a89ebdc3acc9 100644 +--- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h ++++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h +@@ -136,6 +136,28 @@ static inline pte_t pte_mkhuge(pte_t pte) + + #define pte_mkhuge pte_mkhuge + ++static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, ++ unsigned long clr, unsigned long set, int huge); ++ ++static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) ++{ ++ pte_update(mm, addr, ptep, 0, _PAGE_RO, 0); ++} ++#define ptep_set_wrprotect ptep_set_wrprotect ++ ++static inline void __ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, ++ pte_t entry, unsigned long address, int psize) ++{ ++ unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_EXEC); ++ unsigned long clr = ~pte_val(entry) & _PAGE_RO; ++ int huge = psize > mmu_virtual_psize ? 1 : 0; ++ ++ pte_update(vma->vm_mm, address, ptep, clr, set, huge); ++ ++ flush_tlb_page(vma, address); ++} ++#define __ptep_set_access_flags __ptep_set_access_flags ++ + static inline unsigned long pgd_leaf_size(pgd_t pgd) + { + if (pgd_val(pgd) & _PMD_PAGE_8M) +diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h +index d081704b13fb9..2225991c69b55 100644 +--- a/arch/powerpc/include/asm/nohash/64/pgtable.h ++++ b/arch/powerpc/include/asm/nohash/64/pgtable.h +@@ -118,11 +118,6 @@ static inline pte_t pte_wrprotect(pte_t pte) + return __pte(pte_val(pte) & ~_PAGE_RW); + } + +-static inline pte_t pte_mkexec(pte_t pte) +-{ +- return __pte(pte_val(pte) | _PAGE_EXEC); +-} +- + #define PMD_BAD_BITS (PTE_TABLE_SIZE-1) + #define PUD_BAD_BITS (PMD_TABLE_SIZE-1) + +@@ -313,6 +308,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, + #define __swp_entry_to_pte(x) __pte((x).val) + + int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot); ++void unmap_kernel_page(unsigned long va); + extern int __meminit vmemmap_create_mapping(unsigned long start, + unsigned long page_size, + unsigned long phys); +diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h +index 813918f407653..f798640422c2d 100644 +--- a/arch/powerpc/include/asm/nohash/pte-book3e.h ++++ b/arch/powerpc/include/asm/nohash/pte-book3e.h +@@ -48,7 +48,7 @@ + #define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */ + + /* "Higher level" linux bit combinations */ +-#define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */ ++#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */ + #define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ + #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY) + #define _PAGE_KERNEL_RO (_PAGE_BAP_SR) +@@ -93,11 +93,11 @@ + /* Permission masks used to generate the __P and __S table */ + #define PAGE_NONE __pgprot(_PAGE_BASE) + #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) +-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) ++#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX) + #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) ++#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX) + #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) ++#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX) + + #ifndef __ASSEMBLY__ + static inline pte_t pte_mkprivileged(pte_t pte) +@@ -113,6 +113,16 @@ static inline pte_t pte_mkuser(pte_t pte) + } + + #define pte_mkuser pte_mkuser ++ ++static inline pte_t pte_mkexec(pte_t pte) ++{ ++ if (pte_val(pte) & _PAGE_BAP_UR) ++ return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX); ++ else ++ return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX); ++} ++#define pte_mkexec pte_mkexec ++ + #endif /* __ASSEMBLY__ */ + + #endif /* __KERNEL__ */ +diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h +index bcb7b5f917be6..b325022ffa2b0 100644 +--- a/arch/powerpc/include/asm/paravirt.h ++++ b/arch/powerpc/include/asm/paravirt.h +@@ -97,7 +97,23 @@ static inline bool vcpu_is_preempted(int cpu) + + #ifdef CONFIG_PPC_SPLPAR + if (!is_kvm_guest()) { +- int first_cpu = cpu_first_thread_sibling(smp_processor_id()); ++ int first_cpu; ++ ++ /* ++ * The result of vcpu_is_preempted() is used in a ++ * speculative way, and is always subject to invalidation ++ * by events internal and external to Linux. While we can ++ * be called in preemptable context (in the Linux sense), ++ * we're not accessing per-cpu resources in a way that can ++ * race destructively with Linux scheduler preemption and ++ * migration, and callers can tolerate the potential for ++ * error introduced by sampling the CPU index without ++ * pinning the task to it. So it is permissible to use ++ * raw_smp_processor_id() here to defeat the preempt debug ++ * warnings that can arise from using smp_processor_id() ++ * in arbitrary contexts. ++ */ ++ first_cpu = cpu_first_thread_sibling(raw_smp_processor_id()); + + /* + * Preemption can only happen at core granularity. This CPU +diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h +index baea657bc8687..bca31a61e57f8 100644 +--- a/arch/powerpc/include/asm/ppc-opcode.h ++++ b/arch/powerpc/include/asm/ppc-opcode.h +@@ -498,6 +498,7 @@ + #define PPC_RAW_LDX(r, base, b) (0x7c00002a | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) + #define PPC_RAW_LHZ(r, base, i) (0xa0000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) + #define PPC_RAW_LHBRX(r, base, b) (0x7c00062c | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) ++#define PPC_RAW_LWBRX(r, base, b) (0x7c00042c | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) + #define PPC_RAW_LDBRX(r, base, b) (0x7c000428 | ___PPC_RT(r) | ___PPC_RA(base) | ___PPC_RB(b)) + #define PPC_RAW_STWCX(s, a, b) (0x7c00012d | ___PPC_RS(s) | ___PPC_RA(a) | ___PPC_RB(b)) + #define PPC_RAW_CMPWI(a, i) (0x2c000000 | ___PPC_RA(a) | IMM_L(i)) +diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h +index c60ebd04b2ed9..61b968d9fba7c 100644 +--- a/arch/powerpc/include/asm/syscall.h ++++ b/arch/powerpc/include/asm/syscall.h +@@ -90,7 +90,7 @@ static inline void syscall_get_arguments(struct task_struct *task, + unsigned long val, mask = -1UL; + unsigned int n = 6; + +- if (is_32bit_task()) ++ if (is_tsk_32bit_task(task)) + mask = 0xffffffff; + + while (n--) { +@@ -115,7 +115,7 @@ static inline void syscall_set_arguments(struct task_struct *task, + + static inline int syscall_get_arch(struct task_struct *task) + { +- if (is_32bit_task()) ++ if (is_tsk_32bit_task(task)) + return AUDIT_ARCH_PPC; + else if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN)) + return AUDIT_ARCH_PPC64LE; +diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h +index b4ec6c7dd72ee..2a4ea0e213a92 100644 +--- a/arch/powerpc/include/asm/thread_info.h ++++ b/arch/powerpc/include/asm/thread_info.h +@@ -165,8 +165,10 @@ static inline bool test_thread_local_flags(unsigned int flags) + + #ifdef CONFIG_COMPAT + #define is_32bit_task() (test_thread_flag(TIF_32BIT)) ++#define is_tsk_32bit_task(tsk) (test_tsk_thread_flag(tsk, TIF_32BIT)) + #else + #define is_32bit_task() (IS_ENABLED(CONFIG_PPC32)) ++#define is_tsk_32bit_task(tsk) (IS_ENABLED(CONFIG_PPC32)) + #endif + + #if defined(CONFIG_PPC64) +diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile +index 7be36c1e1db6d..b1b23b4d56ba2 100644 +--- a/arch/powerpc/kernel/Makefile ++++ b/arch/powerpc/kernel/Makefile +@@ -11,6 +11,7 @@ CFLAGS_prom_init.o += -fPIC + CFLAGS_btext.o += -fPIC + endif + ++CFLAGS_early_32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) + CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) + CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) + CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) +@@ -196,3 +197,6 @@ clean-files := vmlinux.lds + # Force dependency (incbin is bad) + $(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg + $(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg ++ ++# for cleaning ++subdir- += vdso32 vdso64 +diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c +index 803c2a45b22ac..1cffb5e7c38d6 100644 +--- a/arch/powerpc/kernel/btext.c ++++ b/arch/powerpc/kernel/btext.c +@@ -241,8 +241,10 @@ int __init btext_find_display(int allow_nonstdout) + rc = btext_initialize(np); + printk("result: %d\n", rc); + } +- if (rc == 0) ++ if (rc == 0) { ++ of_node_put(np); + break; ++ } + } + return rc; + } +diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c +index b7ceb041743c9..60f5fc14aa235 100644 +--- a/arch/powerpc/kernel/fadump.c ++++ b/arch/powerpc/kernel/fadump.c +@@ -1641,6 +1641,14 @@ int __init setup_fadump(void) + else if (fw_dump.reserve_dump_area_size) + fw_dump.ops->fadump_init_mem_struct(&fw_dump); + ++ /* ++ * In case of panic, fadump is triggered via ppc_panic_event() ++ * panic notifier. Setting crash_kexec_post_notifiers to 'true' ++ * lets panic() function take crash friendly path before panic ++ * notifiers are invoked. ++ */ ++ crash_kexec_post_notifiers = true; ++ + return 1; + } + subsys_initcall(setup_fadump); +diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c +index c7022c41cc314..20328f72f9f2b 100644 +--- a/arch/powerpc/kernel/firmware.c ++++ b/arch/powerpc/kernel/firmware.c +@@ -31,11 +31,10 @@ int __init check_kvm_guest(void) + if (!hyper_node) + return 0; + +- if (!of_device_is_compatible(hyper_node, "linux,kvm")) +- return 0; +- +- static_branch_enable(&kvm_guest); ++ if (of_device_is_compatible(hyper_node, "linux,kvm")) ++ static_branch_enable(&kvm_guest); + ++ of_node_put(hyper_node); + return 0; + } + core_initcall(check_kvm_guest); // before kvm_guest_init() +diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h +index 6b1ec9e3541b9..349c4a820231b 100644 +--- a/arch/powerpc/kernel/head_32.h ++++ b/arch/powerpc/kernel/head_32.h +@@ -202,11 +202,11 @@ vmap_stack_overflow: + mfspr r1, SPRN_SPRG_THREAD + lwz r1, TASK_CPU - THREAD(r1) + slwi r1, r1, 3 +- addis r1, r1, emergency_ctx@ha ++ addis r1, r1, emergency_ctx-PAGE_OFFSET@ha + #else +- lis r1, emergency_ctx@ha ++ lis r1, emergency_ctx-PAGE_OFFSET@ha + #endif +- lwz r1, emergency_ctx@l(r1) ++ lwz r1, emergency_ctx-PAGE_OFFSET@l(r1) + addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE + EXCEPTION_PROLOG_2 0 vmap_stack_overflow + prepare_transfer_to_handler +diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S +index 7d72ee5ab387c..e783860bea838 100644 +--- a/arch/powerpc/kernel/head_40x.S ++++ b/arch/powerpc/kernel/head_40x.S +@@ -27,6 +27,7 @@ + + #include <linux/init.h> + #include <linux/pgtable.h> ++#include <linux/sizes.h> + #include <asm/processor.h> + #include <asm/page.h> + #include <asm/mmu.h> +@@ -650,7 +651,7 @@ start_here: + b . /* prevent prefetch past rfi */ + + /* Set up the initial MMU state so we can do the first level of +- * kernel initialization. This maps the first 16 MBytes of memory 1:1 ++ * kernel initialization. This maps the first 32 MBytes of memory 1:1 + * virtual to physical and more importantly sets the cache mode. + */ + initial_mmu: +@@ -687,6 +688,12 @@ initial_mmu: + tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */ + tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */ + ++ li r0,62 /* TLB slot 62 */ ++ addis r4,r4,SZ_16M@h ++ addis r3,r3,SZ_16M@h ++ tlbwe r4,r0,TLB_DATA /* Load the data portion of the entry */ ++ tlbwe r3,r0,TLB_TAG /* Load the tag portion of the entry */ ++ + isync + + /* Establish the exception vector base +diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S +index 9bdb95f5694f7..0d073b9fd52c5 100644 +--- a/arch/powerpc/kernel/head_8xx.S ++++ b/arch/powerpc/kernel/head_8xx.S +@@ -733,6 +733,7 @@ _GLOBAL(mmu_pin_tlb) + #ifdef CONFIG_PIN_TLB_DATA + LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET) + LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED) ++ li r8, 0 + #ifdef CONFIG_PIN_TLB_IMMR + li r0, 3 + #else +@@ -741,26 +742,26 @@ _GLOBAL(mmu_pin_tlb) + mtctr r0 + cmpwi r4, 0 + beq 4f +- LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT) + LOAD_REG_ADDR(r9, _sinittext) + + 2: ori r0, r6, MD_EVALID ++ ori r12, r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT + mtspr SPRN_MD_CTR, r5 + mtspr SPRN_MD_EPN, r0 + mtspr SPRN_MD_TWC, r7 +- mtspr SPRN_MD_RPN, r8 ++ mtspr SPRN_MD_RPN, r12 + addi r5, r5, 0x100 + addis r6, r6, SZ_8M@h + addis r8, r8, SZ_8M@h + cmplw r6, r9 + bdnzt lt, 2b +- +-4: LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT) ++4: + 2: ori r0, r6, MD_EVALID ++ ori r12, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT + mtspr SPRN_MD_CTR, r5 + mtspr SPRN_MD_EPN, r0 + mtspr SPRN_MD_TWC, r7 +- mtspr SPRN_MD_RPN, r8 ++ mtspr SPRN_MD_RPN, r12 + addi r5, r5, 0x100 + addis r6, r6, SZ_8M@h + addis r8, r8, SZ_8M@h +@@ -781,7 +782,7 @@ _GLOBAL(mmu_pin_tlb) + #endif + #if defined(CONFIG_PIN_TLB_IMMR) || defined(CONFIG_PIN_TLB_DATA) + lis r0, (MD_RSV4I | MD_TWAM)@h +- mtspr SPRN_MI_CTR, r0 ++ mtspr SPRN_MD_CTR, r0 + #endif + mtspr SPRN_SRR1, r10 + mtspr SPRN_SRR0, r11 +diff --git a/arch/powerpc/kernel/head_book3s_32.S b/arch/powerpc/kernel/head_book3s_32.S +index 68e5c0a7e99d1..2e2a8211b17be 100644 +--- a/arch/powerpc/kernel/head_book3s_32.S ++++ b/arch/powerpc/kernel/head_book3s_32.S +@@ -421,14 +421,14 @@ InstructionTLBMiss: + */ + /* Get PTE (linux-style) and check access */ + mfspr r3,SPRN_IMISS +-#ifdef CONFIG_MODULES ++#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE) + lis r1, TASK_SIZE@h /* check if kernel address */ + cmplw 0,r1,r3 + #endif + mfspr r2, SPRN_SDR1 + li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER + rlwinm r2, r2, 28, 0xfffff000 +-#ifdef CONFIG_MODULES ++#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE) + bgt- 112f + lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ + li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC +diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h +index e5503420b6c6d..ef8d1b1c234e7 100644 +--- a/arch/powerpc/kernel/head_booke.h ++++ b/arch/powerpc/kernel/head_booke.h +@@ -465,12 +465,21 @@ label: + bl do_page_fault; \ + b interrupt_return + ++/* ++ * Instruction TLB Error interrupt handlers may call InstructionStorage ++ * directly without clearing ESR, so the ESR at this point may be left over ++ * from a prior interrupt. ++ * ++ * In any case, do_page_fault for BOOK3E does not use ESR and always expects ++ * dsisr to be 0. ESR_DST from a prior store in particular would confuse fault ++ * handling. ++ */ + #define INSTRUCTION_STORAGE_EXCEPTION \ + START_EXCEPTION(InstructionStorage) \ +- NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \ +- mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ ++ NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \ ++ li r5,0; /* Store 0 in regs->esr (dsisr) */ \ + stw r5,_ESR(r11); \ +- stw r12, _DEAR(r11); /* Pass SRR0 as arg2 */ \ ++ stw r12, _DEAR(r11); /* Set regs->dear (dar) to SRR0 */ \ + prepare_transfer_to_handler; \ + bl do_page_fault; \ + b interrupt_return +diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c +index de10a26972581..df048e331cbfe 100644 +--- a/arch/powerpc/kernel/interrupt.c ++++ b/arch/powerpc/kernel/interrupt.c +@@ -148,7 +148,7 @@ notrace long system_call_exception(long r3, long r4, long r5, + */ + if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) && + unlikely(MSR_TM_TRANSACTIONAL(regs->msr))) +- current_thread_info()->flags |= _TIF_RESTOREALL; ++ set_bits(_TIF_RESTOREALL, ¤t_thread_info()->flags); + + /* + * If the system call was made with a transaction active, doom it and +@@ -266,7 +266,7 @@ static void check_return_regs_valid(struct pt_regs *regs) + if (trap_is_scv(regs)) + return; + +- trap = regs->trap; ++ trap = TRAP(regs); + // EE in HV mode sets HSRRs like 0xea0 + if (cpu_has_feature(CPU_FTR_HVMODE) && trap == INTERRUPT_EXTERNAL) + trap = 0xea0; +diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S +index ec950b08a8dcc..4c6d1a8dcefed 100644 +--- a/arch/powerpc/kernel/interrupt_64.S ++++ b/arch/powerpc/kernel/interrupt_64.S +@@ -30,21 +30,25 @@ COMPAT_SYS_CALL_TABLE: + .ifc \srr,srr + mfspr r11,SPRN_SRR0 + ld r12,_NIP(r1) ++ clrrdi r11,r11,2 ++ clrrdi r12,r12,2 + 100: tdne r11,r12 +- EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) ++ EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) + mfspr r11,SPRN_SRR1 + ld r12,_MSR(r1) + 100: tdne r11,r12 +- EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) ++ EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) + .else + mfspr r11,SPRN_HSRR0 + ld r12,_NIP(r1) ++ clrrdi r11,r11,2 ++ clrrdi r12,r12,2 + 100: tdne r11,r12 +- EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) ++ EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) + mfspr r11,SPRN_HSRR1 + ld r12,_MSR(r1) + 100: tdne r11,r12 +- EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) ++ EMIT_WARN_ENTRY 100b,__FILE__,__LINE__,(BUGFLAG_WARNING | BUGFLAG_ONCE) + .endif + #endif + .endm +diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c +index ed04a3ba66fe8..40a583e9d3c70 100644 +--- a/arch/powerpc/kernel/module.c ++++ b/arch/powerpc/kernel/module.c +@@ -90,16 +90,17 @@ int module_finalize(const Elf_Ehdr *hdr, + } + + static __always_inline void * +-__module_alloc(unsigned long size, unsigned long start, unsigned long end) ++__module_alloc(unsigned long size, unsigned long start, unsigned long end, bool nowarn) + { + pgprot_t prot = strict_module_rwx_enabled() ? PAGE_KERNEL : PAGE_KERNEL_EXEC; ++ gfp_t gfp = GFP_KERNEL | (nowarn ? __GFP_NOWARN : 0); + + /* + * Don't do huge page allocations for modules yet until more testing + * is done. STRICT_MODULE_RWX may require extra work to support this + * too. + */ +- return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL, prot, ++ return __vmalloc_node_range(size, 1, start, end, gfp, prot, + VM_FLUSH_RESET_PERMS | VM_NO_HUGE_VMAP, + NUMA_NO_NODE, __builtin_return_address(0)); + } +@@ -114,13 +115,13 @@ void *module_alloc(unsigned long size) + + /* First try within 32M limit from _etext to avoid branch trampolines */ + if (MODULES_VADDR < PAGE_OFFSET && MODULES_END > limit) +- ptr = __module_alloc(size, limit, MODULES_END); ++ ptr = __module_alloc(size, limit, MODULES_END, true); + + if (!ptr) +- ptr = __module_alloc(size, MODULES_VADDR, MODULES_END); ++ ptr = __module_alloc(size, MODULES_VADDR, MODULES_END, false); + + return ptr; + #else +- return __module_alloc(size, VMALLOC_START, VMALLOC_END); ++ return __module_alloc(size, VMALLOC_START, VMALLOC_END, false); + #endif + } +diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c +index 6baa676e7cb60..5d77d3f5fbb56 100644 +--- a/arch/powerpc/kernel/module_64.c ++++ b/arch/powerpc/kernel/module_64.c +@@ -422,11 +422,17 @@ static inline int create_stub(const Elf64_Shdr *sechdrs, + const char *name) + { + long reladdr; ++ func_desc_t desc; ++ int i; + + if (is_mprofile_ftrace_call(name)) + return create_ftrace_stub(entry, addr, me); + +- memcpy(entry->jump, ppc64_stub_insns, sizeof(ppc64_stub_insns)); ++ for (i = 0; i < sizeof(ppc64_stub_insns) / sizeof(u32); i++) { ++ if (patch_instruction(&entry->jump[i], ++ ppc_inst(ppc64_stub_insns[i]))) ++ return 0; ++ } + + /* Stub uses address relative to r2. */ + reladdr = (unsigned long)entry - my_r2(sechdrs, me); +@@ -437,10 +443,24 @@ static inline int create_stub(const Elf64_Shdr *sechdrs, + } + pr_debug("Stub %p get data from reladdr %li\n", entry, reladdr); + +- entry->jump[0] |= PPC_HA(reladdr); +- entry->jump[1] |= PPC_LO(reladdr); +- entry->funcdata = func_desc(addr); +- entry->magic = STUB_MAGIC; ++ if (patch_instruction(&entry->jump[0], ++ ppc_inst(entry->jump[0] | PPC_HA(reladdr)))) ++ return 0; ++ ++ if (patch_instruction(&entry->jump[1], ++ ppc_inst(entry->jump[1] | PPC_LO(reladdr)))) ++ return 0; ++ ++ // func_desc_t is 8 bytes if ABIv2, else 16 bytes ++ desc = func_desc(addr); ++ for (i = 0; i < sizeof(func_desc_t) / sizeof(u32); i++) { ++ if (patch_instruction(((u32 *)&entry->funcdata) + i, ++ ppc_inst(((u32 *)(&desc))[i]))) ++ return 0; ++ } ++ ++ if (patch_instruction(&entry->magic, ppc_inst(STUB_MAGIC))) ++ return 0; + + return 1; + } +@@ -495,8 +515,11 @@ static int restore_r2(const char *name, u32 *instruction, struct module *me) + me->name, *instruction, instruction); + return 0; + } ++ + /* ld r2,R2_STACK_OFFSET(r1) */ +- *instruction = PPC_INST_LD_TOC; ++ if (patch_instruction(instruction, ppc_inst(PPC_INST_LD_TOC))) ++ return 0; ++ + return 1; + } + +@@ -636,9 +659,12 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, + } + + /* Only replace bits 2 through 26 */ +- *(uint32_t *)location +- = (*(uint32_t *)location & ~0x03fffffc) ++ value = (*(uint32_t *)location & ~0x03fffffc) + | (value & 0x03fffffc); ++ ++ if (patch_instruction((u32 *)location, ppc_inst(value))) ++ return -EFAULT; ++ + break; + + case R_PPC64_REL64: +diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c +index 18b04b08b9833..f845065c860e3 100644 +--- a/arch/powerpc/kernel/prom_init.c ++++ b/arch/powerpc/kernel/prom_init.c +@@ -2991,7 +2991,7 @@ static void __init fixup_device_tree_efika_add_phy(void) + + /* Check if the phy-handle property exists - bail if it does */ + rv = prom_getprop(node, "phy-handle", prop, sizeof(prop)); +- if (!rv) ++ if (rv <= 0) + return; + + /* +diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h +index 1f07317964e49..618aeccdf6918 100644 +--- a/arch/powerpc/kernel/signal.h ++++ b/arch/powerpc/kernel/signal.h +@@ -25,8 +25,14 @@ static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src) + + return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]); + } +-#define unsafe_get_user_sigset(dst, src, label) \ +- unsafe_get_user((dst)->sig[0], (u64 __user *)&(src)->sig[0], label) ++#define unsafe_get_user_sigset(dst, src, label) do { \ ++ sigset_t *__dst = dst; \ ++ const sigset_t __user *__src = src; \ ++ int i; \ ++ \ ++ for (i = 0; i < _NSIG_WORDS; i++) \ ++ unsafe_get_user(__dst->sig[i], &__src->sig[i], label); \ ++} while (0) + + #ifdef CONFIG_VSX + extern unsigned long copy_vsx_to_user(void __user *to, +diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c +index 0608581967f09..f2da879264bcd 100644 +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -1062,8 +1062,10 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, + * or if another thread unmaps the region containing the context. + * We kill the task with a SIGSEGV in this situation. + */ +- if (do_setcontext(new_ctx, regs, 0)) +- do_exit(SIGSEGV); ++ if (do_setcontext(new_ctx, regs, 0)) { ++ force_exit_sig(SIGSEGV); ++ return -EFAULT; ++ } + + set_thread_flag(TIF_RESTOREALL); + return 0; +diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c +index 1831bba0582e1..bb9c077ac1322 100644 +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -703,15 +703,18 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, + * We kill the task with a SIGSEGV in this situation. + */ + +- if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) +- do_exit(SIGSEGV); ++ if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) { ++ force_exit_sig(SIGSEGV); ++ return -EFAULT; ++ } + set_current_blocked(&set); + + if (!user_read_access_begin(new_ctx, ctx_size)) + return -EFAULT; + if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) { + user_read_access_end(); +- do_exit(SIGSEGV); ++ force_exit_sig(SIGSEGV); ++ return -EFAULT; + } + user_read_access_end(); + +diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c +index 605bab448f847..fb95f92dcfac6 100644 +--- a/arch/powerpc/kernel/smp.c ++++ b/arch/powerpc/kernel/smp.c +@@ -61,6 +61,7 @@ + #include <asm/cpu_has_feature.h> + #include <asm/ftrace.h> + #include <asm/kup.h> ++#include <asm/fadump.h> + + #ifdef DEBUG + #include <asm/udbg.h> +@@ -620,6 +621,45 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) + } + #endif + ++#ifdef CONFIG_NMI_IPI ++static void crash_stop_this_cpu(struct pt_regs *regs) ++#else ++static void crash_stop_this_cpu(void *dummy) ++#endif ++{ ++ /* ++ * Just busy wait here and avoid marking CPU as offline to ensure ++ * register data is captured appropriately. ++ */ ++ while (1) ++ cpu_relax(); ++} ++ ++void crash_smp_send_stop(void) ++{ ++ static bool stopped = false; ++ ++ /* ++ * In case of fadump, register data for all CPUs is captured by f/w ++ * on ibm,os-term rtas call. Skip IPI callbacks to other CPUs before ++ * this rtas call to avoid tricky post processing of those CPUs' ++ * backtraces. ++ */ ++ if (should_fadump_crash()) ++ return; ++ ++ if (stopped) ++ return; ++ ++ stopped = true; ++ ++#ifdef CONFIG_NMI_IPI ++ smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, crash_stop_this_cpu, 1000000); ++#else ++ smp_call_function(crash_stop_this_cpu, NULL, 0); ++#endif /* CONFIG_NMI_IPI */ ++} ++ + #ifdef CONFIG_NMI_IPI + static void nmi_stop_this_cpu(struct pt_regs *regs) + { +@@ -1640,10 +1680,12 @@ void start_secondary(void *unused) + BUG(); + } + ++#ifdef CONFIG_PROFILING + int setup_profiling_timer(unsigned int multiplier) + { + return 0; + } ++#endif + + static void fixup_topology(void) + { +diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c +index f9ea0e5357f92..ad94a2c6b7337 100644 +--- a/arch/powerpc/kernel/watchdog.c ++++ b/arch/powerpc/kernel/watchdog.c +@@ -135,6 +135,10 @@ static void set_cpumask_stuck(const struct cpumask *cpumask, u64 tb) + { + cpumask_or(&wd_smp_cpus_stuck, &wd_smp_cpus_stuck, cpumask); + cpumask_andnot(&wd_smp_cpus_pending, &wd_smp_cpus_pending, cpumask); ++ /* ++ * See wd_smp_clear_cpu_pending() ++ */ ++ smp_mb(); + if (cpumask_empty(&wd_smp_cpus_pending)) { + wd_smp_last_reset_tb = tb; + cpumask_andnot(&wd_smp_cpus_pending, +@@ -187,6 +191,12 @@ static void watchdog_smp_panic(int cpu, u64 tb) + if (sysctl_hardlockup_all_cpu_backtrace) + trigger_allbutself_cpu_backtrace(); + ++ /* ++ * Force flush any remote buffers that might be stuck in IRQ context ++ * and therefore could not run their irq_work. ++ */ ++ printk_trigger_flush(); ++ + if (hardlockup_panic) + nmi_panic(NULL, "Hard LOCKUP"); + +@@ -215,13 +225,44 @@ static void wd_smp_clear_cpu_pending(int cpu, u64 tb) + + cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck); + wd_smp_unlock(&flags); ++ } else { ++ /* ++ * The last CPU to clear pending should have reset the ++ * watchdog so we generally should not find it empty ++ * here if our CPU was clear. However it could happen ++ * due to a rare race with another CPU taking the ++ * last CPU out of the mask concurrently. ++ * ++ * We can't add a warning for it. But just in case ++ * there is a problem with the watchdog that is causing ++ * the mask to not be reset, try to kick it along here. ++ */ ++ if (unlikely(cpumask_empty(&wd_smp_cpus_pending))) ++ goto none_pending; + } + return; + } ++ + cpumask_clear_cpu(cpu, &wd_smp_cpus_pending); ++ ++ /* ++ * Order the store to clear pending with the load(s) to check all ++ * words in the pending mask to check they are all empty. This orders ++ * with the same barrier on another CPU. This prevents two CPUs ++ * clearing the last 2 pending bits, but neither seeing the other's ++ * store when checking if the mask is empty, and missing an empty ++ * mask, which ends with a false positive. ++ */ ++ smp_mb(); + if (cpumask_empty(&wd_smp_cpus_pending)) { + unsigned long flags; + ++none_pending: ++ /* ++ * Double check under lock because more than one CPU could see ++ * a clear mask with the lockless check after clearing their ++ * pending bits. ++ */ + wd_smp_lock(&flags); + if (cpumask_empty(&wd_smp_cpus_pending)) { + wd_smp_last_reset_tb = tb; +@@ -312,8 +353,12 @@ void arch_touch_nmi_watchdog(void) + { + unsigned long ticks = tb_ticks_per_usec * wd_timer_period_ms * 1000; + int cpu = smp_processor_id(); +- u64 tb = get_tb(); ++ u64 tb; + ++ if (!cpumask_test_cpu(cpu, &watchdog_cpumask)) ++ return; ++ ++ tb = get_tb(); + if (tb - per_cpu(wd_timer_tb, cpu) >= ticks) { + per_cpu(wd_timer_tb, cpu) = tb; + wd_smp_clear_cpu_pending(cpu, tb); +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 2acb1c96cfafd..a2fd1db29f7e8 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -1731,7 +1731,6 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, + + static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) + { +- struct kvm_nested_guest *nested = vcpu->arch.nested; + int r; + int srcu_idx; + +@@ -1831,7 +1830,7 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) + * it into a HEAI. + */ + if (!(vcpu->arch.hfscr_permitted & (1UL << cause)) || +- (nested->hfscr & (1UL << cause))) { ++ (vcpu->arch.nested_hfscr & (1UL << cause))) { + vcpu->arch.trap = BOOK3S_INTERRUPT_H_EMUL_ASSIST; + + /* +@@ -3726,7 +3725,20 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) + + kvmppc_set_host_core(pcpu); + +- guest_exit_irqoff(); ++ context_tracking_guest_exit(); ++ if (!vtime_accounting_enabled_this_cpu()) { ++ local_irq_enable(); ++ /* ++ * Service IRQs here before vtime_account_guest_exit() so any ++ * ticks that occurred while running the guest are accounted to ++ * the guest. If vtime accounting is enabled, accounting uses ++ * TB rather than ticks, so it can be done without enabling ++ * interrupts here, which has the problem that it accounts ++ * interrupt processing overhead to the host. ++ */ ++ local_irq_disable(); ++ } ++ vtime_account_guest_exit(); + + local_irq_enable(); + +@@ -4510,7 +4522,20 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + + kvmppc_set_host_core(pcpu); + +- guest_exit_irqoff(); ++ context_tracking_guest_exit(); ++ if (!vtime_accounting_enabled_this_cpu()) { ++ local_irq_enable(); ++ /* ++ * Service IRQs here before vtime_account_guest_exit() so any ++ * ticks that occurred while running the guest are accounted to ++ * the guest. If vtime accounting is enabled, accounting uses ++ * TB rather than ticks, so it can be done without enabling ++ * interrupts here, which has the problem that it accounts ++ * interrupt processing overhead to the host. ++ */ ++ local_irq_disable(); ++ } ++ vtime_account_guest_exit(); + + local_irq_enable(); + +@@ -4835,8 +4860,12 @@ static int kvmppc_core_prepare_memory_region_hv(struct kvm *kvm, + unsigned long npages = mem->memory_size >> PAGE_SHIFT; + + if (change == KVM_MR_CREATE) { +- slot->arch.rmap = vzalloc(array_size(npages, +- sizeof(*slot->arch.rmap))); ++ unsigned long size = array_size(npages, sizeof(*slot->arch.rmap)); ++ ++ if ((size >> PAGE_SHIFT) > totalram_pages()) ++ return -ENOMEM; ++ ++ slot->arch.rmap = vzalloc(size); + if (!slot->arch.rmap) + return -ENOMEM; + } +diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c +index fcf4760a3a0ea..70b7a8f971538 100644 +--- a/arch/powerpc/kvm/book3s_hv_builtin.c ++++ b/arch/powerpc/kvm/book3s_hv_builtin.c +@@ -695,6 +695,7 @@ static void flush_guest_tlb(struct kvm *kvm) + "r" (0) : "memory"); + } + asm volatile("ptesync": : :"memory"); ++ // POWER9 congruence-class TLBIEL leaves ERAT. Flush it now. + asm volatile(PPC_RADIX_INVALIDATE_ERAT_GUEST : : :"memory"); + } else { + for (set = 0; set < kvm->arch.tlb_sets; ++set) { +@@ -705,7 +706,9 @@ static void flush_guest_tlb(struct kvm *kvm) + rb += PPC_BIT(51); /* increment set number */ + } + asm volatile("ptesync": : :"memory"); +- asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); ++ // POWER9 congruence-class TLBIEL leaves ERAT. Flush it now. ++ if (cpu_has_feature(CPU_FTR_ARCH_300)) ++ asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory"); + } + } + +diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c +index ed8a2c9f56299..6c4e0e93105ff 100644 +--- a/arch/powerpc/kvm/book3s_hv_nested.c ++++ b/arch/powerpc/kvm/book3s_hv_nested.c +@@ -362,7 +362,7 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu) + /* set L1 state to L2 state */ + vcpu->arch.nested = l2; + vcpu->arch.nested_vcpu_id = l2_hv.vcpu_token; +- l2->hfscr = l2_hv.hfscr; ++ vcpu->arch.nested_hfscr = l2_hv.hfscr; + vcpu->arch.regs = l2_regs; + + /* Guest must always run with ME enabled, HV disabled. */ +@@ -582,7 +582,7 @@ long kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu) + if (eaddr & (0xFFFUL << 52)) + return H_PARAMETER; + +- buf = kzalloc(n, GFP_KERNEL); ++ buf = kzalloc(n, GFP_KERNEL | __GFP_NOWARN); + if (!buf) + return H_NO_MEM; + +diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +index eb776d0c5d8e9..32a4b4d412b92 100644 +--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +@@ -2005,7 +2005,7 @@ hcall_real_table: + .globl hcall_real_table_end + hcall_real_table_end: + +-_GLOBAL(kvmppc_h_set_xdabr) ++_GLOBAL_TOC(kvmppc_h_set_xdabr) + EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr) + andi. r0, r5, DABRX_USER | DABRX_KERNEL + beq 6f +@@ -2015,7 +2015,7 @@ EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr) + 6: li r3, H_PARAMETER + blr + +-_GLOBAL(kvmppc_h_set_dabr) ++_GLOBAL_TOC(kvmppc_h_set_dabr) + EXPORT_SYMBOL_GPL(kvmppc_h_set_dabr) + li r5, DABRX_USER | DABRX_KERNEL + 3: +diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c +index 977801c83aff8..8c15c90dd3a97 100644 +--- a/arch/powerpc/kvm/booke.c ++++ b/arch/powerpc/kvm/booke.c +@@ -1042,7 +1042,21 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr) + } + + trace_kvm_exit(exit_nr, vcpu); +- guest_exit_irqoff(); ++ ++ context_tracking_guest_exit(); ++ if (!vtime_accounting_enabled_this_cpu()) { ++ local_irq_enable(); ++ /* ++ * Service IRQs here before vtime_account_guest_exit() so any ++ * ticks that occurred while running the guest are accounted to ++ * the guest. If vtime accounting is enabled, accounting uses ++ * TB rather than ticks, so it can be done without enabling ++ * interrupts here, which has the problem that it accounts ++ * interrupt processing overhead to the host. ++ */ ++ local_irq_disable(); ++ } ++ vtime_account_guest_exit(); + + local_irq_enable(); + +diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile +index 99a7c9132422c..54be64203b2ab 100644 +--- a/arch/powerpc/lib/Makefile ++++ b/arch/powerpc/lib/Makefile +@@ -19,6 +19,9 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING + CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING + endif + ++CFLAGS_code-patching.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) ++CFLAGS_feature-fixups.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) ++ + obj-y += alloc.o code-patching.o feature-fixups.o pmem.o test_code-patching.o + + ifndef CONFIG_KASAN +diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c +index cda17bee5afea..c3e06922468b3 100644 +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -228,6 +228,7 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types) + + static bool stf_exit_reentrant = false; + static bool rfi_exit_reentrant = false; ++static DEFINE_MUTEX(exit_flush_lock); + + static int __do_stf_barrier_fixups(void *data) + { +@@ -253,6 +254,9 @@ void do_stf_barrier_fixups(enum stf_barrier_type types) + * low level interrupt exit code before patching. After the patching, + * if allowed, then flip the branch to allow fast exits. + */ ++ ++ // Prevent static key update races with do_rfi_flush_fixups() ++ mutex_lock(&exit_flush_lock); + static_branch_enable(&interrupt_exit_not_reentrant); + + stop_machine(__do_stf_barrier_fixups, &types, NULL); +@@ -264,6 +268,8 @@ void do_stf_barrier_fixups(enum stf_barrier_type types) + + if (stf_exit_reentrant && rfi_exit_reentrant) + static_branch_disable(&interrupt_exit_not_reentrant); ++ ++ mutex_unlock(&exit_flush_lock); + } + + void do_uaccess_flush_fixups(enum l1d_flush_type types) +@@ -486,6 +492,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) + * without stop_machine, so this could be achieved with a broadcast + * IPI instead, but this matches the stf sequence. + */ ++ ++ // Prevent static key update races with do_stf_barrier_fixups() ++ mutex_lock(&exit_flush_lock); + static_branch_enable(&interrupt_exit_not_reentrant); + + stop_machine(__do_rfi_flush_fixups, &types, NULL); +@@ -497,6 +506,8 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) + + if (stf_exit_reentrant && rfi_exit_reentrant) + static_branch_disable(&interrupt_exit_not_reentrant); ++ ++ mutex_unlock(&exit_flush_lock); + } + + void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) +diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c +index d8d5f901cee1c..d8cc49f39fe47 100644 +--- a/arch/powerpc/lib/sstep.c ++++ b/arch/powerpc/lib/sstep.c +@@ -3181,12 +3181,14 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op) + case BARRIER_EIEIO: + eieio(); + break; ++#ifdef CONFIG_PPC64 + case BARRIER_LWSYNC: + asm volatile("lwsync" : : : "memory"); + break; + case BARRIER_PTESYNC: + asm volatile("ptesync" : : : "memory"); + break; ++#endif + } + break; + +diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c +index 27061583a0107..203735caf6915 100644 +--- a/arch/powerpc/mm/book3s32/mmu.c ++++ b/arch/powerpc/mm/book3s32/mmu.c +@@ -76,7 +76,7 @@ unsigned long p_block_mapped(phys_addr_t pa) + return 0; + } + +-static int find_free_bat(void) ++int __init find_free_bat(void) + { + int b; + int n = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4; +@@ -100,7 +100,7 @@ static int find_free_bat(void) + * - block size has to be a power of two. This is calculated by finding the + * highest bit set to 1. + */ +-static unsigned int block_size(unsigned long base, unsigned long top) ++unsigned int bat_block_size(unsigned long base, unsigned long top) + { + unsigned int max_size = SZ_256M; + unsigned int base_shift = (ffs(base) - 1) & 31; +@@ -145,7 +145,7 @@ static unsigned long __init __mmu_mapin_ram(unsigned long base, unsigned long to + int idx; + + while ((idx = find_free_bat()) != -1 && base != top) { +- unsigned int size = block_size(base, top); ++ unsigned int size = bat_block_size(base, top); + + if (size < 128 << 10) + break; +@@ -196,18 +196,17 @@ void mmu_mark_initmem_nx(void) + int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4; + int i; + unsigned long base = (unsigned long)_stext - PAGE_OFFSET; +- unsigned long top = (unsigned long)_etext - PAGE_OFFSET; ++ unsigned long top = ALIGN((unsigned long)_etext - PAGE_OFFSET, SZ_128K); + unsigned long border = (unsigned long)__init_begin - PAGE_OFFSET; + unsigned long size; + +- for (i = 0; i < nb - 1 && base < top && top - base > (128 << 10);) { +- size = block_size(base, top); ++ for (i = 0; i < nb - 1 && base < top;) { ++ size = bat_block_size(base, top); + setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT); + base += size; + } + if (base < top) { +- size = block_size(base, top); +- size = max(size, 128UL << 10); ++ size = bat_block_size(base, top); + if ((top - base) > size) { + size <<= 1; + if (strict_kernel_rwx_enabled() && base + size > border) +diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c +index ae20add7954a0..795d18a84f556 100644 +--- a/arch/powerpc/mm/book3s64/radix_pgtable.c ++++ b/arch/powerpc/mm/book3s64/radix_pgtable.c +@@ -1093,7 +1093,7 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) + + int pud_clear_huge(pud_t *pud) + { +- if (pud_huge(*pud)) { ++ if (pud_is_leaf(*pud)) { + pud_clear(pud); + return 1; + } +@@ -1140,7 +1140,7 @@ int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot) + + int pmd_clear_huge(pmd_t *pmd) + { +- if (pmd_huge(*pmd)) { ++ if (pmd_is_leaf(*pmd)) { + pmd_clear(pmd); + return 1; + } +diff --git a/arch/powerpc/mm/kasan/book3s_32.c b/arch/powerpc/mm/kasan/book3s_32.c +index 202bd260a0095..450a67ef0bbe1 100644 +--- a/arch/powerpc/mm/kasan/book3s_32.c ++++ b/arch/powerpc/mm/kasan/book3s_32.c +@@ -10,47 +10,51 @@ int __init kasan_init_region(void *start, size_t size) + { + unsigned long k_start = (unsigned long)kasan_mem_to_shadow(start); + unsigned long k_end = (unsigned long)kasan_mem_to_shadow(start + size); +- unsigned long k_cur = k_start; +- int k_size = k_end - k_start; +- int k_size_base = 1 << (ffs(k_size) - 1); ++ unsigned long k_nobat = k_start; ++ unsigned long k_cur; ++ phys_addr_t phys; + int ret; +- void *block; + +- block = memblock_alloc(k_size, k_size_base); +- +- if (block && k_size_base >= SZ_128K && k_start == ALIGN(k_start, k_size_base)) { +- int k_size_more = 1 << (ffs(k_size - k_size_base) - 1); +- +- setbat(-1, k_start, __pa(block), k_size_base, PAGE_KERNEL); +- if (k_size_more >= SZ_128K) +- setbat(-1, k_start + k_size_base, __pa(block) + k_size_base, +- k_size_more, PAGE_KERNEL); +- if (v_block_mapped(k_start)) +- k_cur = k_start + k_size_base; +- if (v_block_mapped(k_start + k_size_base)) +- k_cur = k_start + k_size_base + k_size_more; +- +- update_bats(); ++ while (k_nobat < k_end) { ++ unsigned int k_size = bat_block_size(k_nobat, k_end); ++ int idx = find_free_bat(); ++ ++ if (idx == -1) ++ break; ++ if (k_size < SZ_128K) ++ break; ++ phys = memblock_phys_alloc_range(k_size, k_size, 0, ++ MEMBLOCK_ALLOC_ANYWHERE); ++ if (!phys) ++ break; ++ ++ setbat(idx, k_nobat, phys, k_size, PAGE_KERNEL); ++ k_nobat += k_size; + } ++ if (k_nobat != k_start) ++ update_bats(); + +- if (!block) +- block = memblock_alloc(k_size, PAGE_SIZE); +- if (!block) +- return -ENOMEM; ++ if (k_nobat < k_end) { ++ phys = memblock_phys_alloc_range(k_end - k_nobat, PAGE_SIZE, 0, ++ MEMBLOCK_ALLOC_ANYWHERE); ++ if (!phys) ++ return -ENOMEM; ++ } + + ret = kasan_init_shadow_page_tables(k_start, k_end); + if (ret) + return ret; + +- kasan_update_early_region(k_start, k_cur, __pte(0)); ++ kasan_update_early_region(k_start, k_nobat, __pte(0)); + +- for (; k_cur < k_end; k_cur += PAGE_SIZE) { ++ for (k_cur = k_nobat; k_cur < k_end; k_cur += PAGE_SIZE) { + pmd_t *pmd = pmd_off_k(k_cur); +- void *va = block + k_cur - k_start; +- pte_t pte = pfn_pte(PHYS_PFN(__pa(va)), PAGE_KERNEL); ++ pte_t pte = pfn_pte(PHYS_PFN(phys + k_cur - k_nobat), PAGE_KERNEL); + + __set_pte_at(&init_mm, k_cur, pte_offset_kernel(pmd, k_cur), pte, 0); + } + flush_tlb_kernel_range(k_start, k_end); ++ memset(kasan_mem_to_shadow(start), 0, k_end - k_start); ++ + return 0; + } +diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c +index c3c4e31462eca..05b9c3f31456c 100644 +--- a/arch/powerpc/mm/mem.c ++++ b/arch/powerpc/mm/mem.c +@@ -20,8 +20,8 @@ + #include <asm/machdep.h> + #include <asm/rtas.h> + #include <asm/kasan.h> +-#include <asm/sparsemem.h> + #include <asm/svm.h> ++#include <asm/mmzone.h> + + #include <mm/mmu_decl.h> + +diff --git a/arch/powerpc/mm/nohash/tlb_low_64e.S b/arch/powerpc/mm/nohash/tlb_low_64e.S +index bf24451f3e71f..9235e720e3572 100644 +--- a/arch/powerpc/mm/nohash/tlb_low_64e.S ++++ b/arch/powerpc/mm/nohash/tlb_low_64e.S +@@ -222,7 +222,7 @@ tlb_miss_kernel_bolted: + + tlb_miss_fault_bolted: + /* We need to check if it was an instruction miss */ +- andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX ++ andi. r10,r11,_PAGE_BAP_UX|_PAGE_BAP_SX + bne itlb_miss_fault_bolted + dtlb_miss_fault_bolted: + tlb_epilog_bolted +@@ -239,7 +239,7 @@ itlb_miss_fault_bolted: + srdi r15,r16,60 /* get region */ + bne- itlb_miss_fault_bolted + +- li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */ ++ li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */ + + /* We do the user/kernel test for the PID here along with the RW test + */ +@@ -614,7 +614,7 @@ itlb_miss_fault_e6500: + + /* We do the user/kernel test for the PID here along with the RW test + */ +- li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */ ++ li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */ + oris r11,r11,_PAGE_ACCESSED@h + + cmpldi cr0,r15,0 /* Check for user region */ +@@ -734,7 +734,7 @@ normal_tlb_miss_done: + + normal_tlb_miss_access_fault: + /* We need to check if it was an instruction miss */ +- andi. r10,r11,_PAGE_EXEC ++ andi. r10,r11,_PAGE_BAP_UX + bne 1f + ld r14,EX_TLB_DEAR(r12) + ld r15,EX_TLB_ESR(r12) +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index 6f14c8fb6359d..59d3cfcd78879 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -376,9 +376,9 @@ static void initialize_form2_numa_distance_lookup_table(void) + { + int i, j; + struct device_node *root; +- const __u8 *numa_dist_table; ++ const __u8 *form2_distances; + const __be32 *numa_lookup_index; +- int numa_dist_table_length; ++ int form2_distances_length; + int max_numa_index, distance_index; + + if (firmware_has_feature(FW_FEATURE_OPAL)) +@@ -392,45 +392,41 @@ static void initialize_form2_numa_distance_lookup_table(void) + max_numa_index = of_read_number(&numa_lookup_index[0], 1); + + /* first element of the array is the size and is encode-int */ +- numa_dist_table = of_get_property(root, "ibm,numa-distance-table", NULL); +- numa_dist_table_length = of_read_number((const __be32 *)&numa_dist_table[0], 1); ++ form2_distances = of_get_property(root, "ibm,numa-distance-table", NULL); ++ form2_distances_length = of_read_number((const __be32 *)&form2_distances[0], 1); + /* Skip the size which is encoded int */ +- numa_dist_table += sizeof(__be32); ++ form2_distances += sizeof(__be32); + +- pr_debug("numa_dist_table_len = %d, numa_dist_indexes_len = %d\n", +- numa_dist_table_length, max_numa_index); ++ pr_debug("form2_distances_len = %d, numa_dist_indexes_len = %d\n", ++ form2_distances_length, max_numa_index); + + for (i = 0; i < max_numa_index; i++) + /* +1 skip the max_numa_index in the property */ + numa_id_index_table[i] = of_read_number(&numa_lookup_index[i + 1], 1); + + +- if (numa_dist_table_length != max_numa_index * max_numa_index) { ++ if (form2_distances_length != max_numa_index * max_numa_index) { + WARN(1, "Wrong NUMA distance information\n"); +- /* consider everybody else just remote. */ +- for (i = 0; i < max_numa_index; i++) { +- for (j = 0; j < max_numa_index; j++) { +- int nodeA = numa_id_index_table[i]; +- int nodeB = numa_id_index_table[j]; +- +- if (nodeA == nodeB) +- numa_distance_table[nodeA][nodeB] = LOCAL_DISTANCE; +- else +- numa_distance_table[nodeA][nodeB] = REMOTE_DISTANCE; +- } +- } ++ form2_distances = NULL; // don't use it + } +- + distance_index = 0; + for (i = 0; i < max_numa_index; i++) { + for (j = 0; j < max_numa_index; j++) { + int nodeA = numa_id_index_table[i]; + int nodeB = numa_id_index_table[j]; +- +- numa_distance_table[nodeA][nodeB] = numa_dist_table[distance_index++]; +- pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, numa_distance_table[nodeA][nodeB]); ++ int dist; ++ ++ if (form2_distances) ++ dist = form2_distances[distance_index++]; ++ else if (nodeA == nodeB) ++ dist = LOCAL_DISTANCE; ++ else ++ dist = REMOTE_DISTANCE; ++ numa_distance_table[nodeA][nodeB] = dist; ++ pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, dist); + } + } ++ + of_node_put(root); + } + +diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c +index cd16b407f47e1..9a93c1a5aa1d1 100644 +--- a/arch/powerpc/mm/pgtable.c ++++ b/arch/powerpc/mm/pgtable.c +@@ -203,6 +203,15 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, + __set_pte_at(mm, addr, ptep, pte, 0); + } + ++void unmap_kernel_page(unsigned long va) ++{ ++ pmd_t *pmdp = pmd_off_k(va); ++ pte_t *ptep = pte_offset_kernel(pmdp, va); ++ ++ pte_clear(&init_mm, va, ptep); ++ flush_tlb_kernel_range(va, va + PAGE_SIZE); ++} ++ + /* + * This is called when relaxing access to a PTE. It's also called in the page + * fault path when we don't hit any of the major fault cases, ie, a minor +diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c +index dcf5ecca19d99..fde1ed445ca46 100644 +--- a/arch/powerpc/mm/pgtable_32.c ++++ b/arch/powerpc/mm/pgtable_32.c +@@ -173,7 +173,7 @@ void mark_rodata_ro(void) + } + #endif + +-#ifdef CONFIG_DEBUG_PAGEALLOC ++#if defined(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) && defined(CONFIG_DEBUG_PAGEALLOC) + void __kernel_map_pages(struct page *page, int numpages, int enable) + { + unsigned long addr = (unsigned long)page_address(page); +diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c +index 78c8cf01db5f9..175aabf101e87 100644 +--- a/arch/powerpc/mm/pgtable_64.c ++++ b/arch/powerpc/mm/pgtable_64.c +@@ -102,7 +102,8 @@ EXPORT_SYMBOL(__pte_frag_size_shift); + struct page *p4d_page(p4d_t p4d) + { + if (p4d_is_leaf(p4d)) { +- VM_WARN_ON(!p4d_huge(p4d)); ++ if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP)) ++ VM_WARN_ON(!p4d_huge(p4d)); + return pte_page(p4d_pte(p4d)); + } + return virt_to_page(p4d_pgtable(p4d)); +@@ -112,7 +113,8 @@ struct page *p4d_page(p4d_t p4d) + struct page *pud_page(pud_t pud) + { + if (pud_is_leaf(pud)) { +- VM_WARN_ON(!pud_huge(pud)); ++ if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP)) ++ VM_WARN_ON(!pud_huge(pud)); + return pte_page(pud_pte(pud)); + } + return virt_to_page(pud_pgtable(pud)); +@@ -125,7 +127,13 @@ struct page *pud_page(pud_t pud) + struct page *pmd_page(pmd_t pmd) + { + if (pmd_is_leaf(pmd)) { +- VM_WARN_ON(!(pmd_large(pmd) || pmd_huge(pmd))); ++ /* ++ * vmalloc_to_page may be called on any vmap address (not only ++ * vmalloc), and it uses pmd_page() etc., when huge vmap is ++ * enabled so these checks can't be used. ++ */ ++ if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP)) ++ VM_WARN_ON(!(pmd_large(pmd) || pmd_huge(pmd))); + return pte_page(pmd_pte(pmd)); + } + return virt_to_page(pmd_page_vaddr(pmd)); +diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c +index bf251191e78d9..32bfb215c4858 100644 +--- a/arch/powerpc/mm/ptdump/ptdump.c ++++ b/arch/powerpc/mm/ptdump/ptdump.c +@@ -183,7 +183,7 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr) + { + pte_t pte = __pte(st->current_flags); + +- if (!IS_ENABLED(CONFIG_PPC_DEBUG_WX) || !st->check_wx) ++ if (!IS_ENABLED(CONFIG_DEBUG_WX) || !st->check_wx) + return; + + if (!pte_write(pte) || !pte_exec(pte)) +diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c +index fcbf7a917c566..8acf8a611a265 100644 +--- a/arch/powerpc/net/bpf_jit_comp.c ++++ b/arch/powerpc/net/bpf_jit_comp.c +@@ -23,15 +23,15 @@ static void bpf_jit_fill_ill_insns(void *area, unsigned int size) + memset32(area, BREAKPOINT_INSTRUCTION, size / 4); + } + +-/* Fix the branch target addresses for subprog calls */ +-static int bpf_jit_fixup_subprog_calls(struct bpf_prog *fp, u32 *image, +- struct codegen_context *ctx, u32 *addrs) ++/* Fix updated addresses (for subprog calls, ldimm64, et al) during extra pass */ ++static int bpf_jit_fixup_addresses(struct bpf_prog *fp, u32 *image, ++ struct codegen_context *ctx, u32 *addrs) + { + const struct bpf_insn *insn = fp->insnsi; + bool func_addr_fixed; + u64 func_addr; + u32 tmp_idx; +- int i, ret; ++ int i, j, ret; + + for (i = 0; i < fp->len; i++) { + /* +@@ -66,6 +66,23 @@ static int bpf_jit_fixup_subprog_calls(struct bpf_prog *fp, u32 *image, + * of the JITed sequence remains unchanged. + */ + ctx->idx = tmp_idx; ++ } else if (insn[i].code == (BPF_LD | BPF_IMM | BPF_DW)) { ++ tmp_idx = ctx->idx; ++ ctx->idx = addrs[i] / 4; ++#ifdef CONFIG_PPC32 ++ PPC_LI32(ctx->b2p[insn[i].dst_reg] - 1, (u32)insn[i + 1].imm); ++ PPC_LI32(ctx->b2p[insn[i].dst_reg], (u32)insn[i].imm); ++ for (j = ctx->idx - addrs[i] / 4; j < 4; j++) ++ EMIT(PPC_RAW_NOP()); ++#else ++ func_addr = ((u64)(u32)insn[i].imm) | (((u64)(u32)insn[i + 1].imm) << 32); ++ PPC_LI64(b2p[insn[i].dst_reg], func_addr); ++ /* overwrite rest with nops */ ++ for (j = ctx->idx - addrs[i] / 4; j < 5; j++) ++ EMIT(PPC_RAW_NOP()); ++#endif ++ ctx->idx = tmp_idx; ++ i++; + } + } + +@@ -193,13 +210,13 @@ skip_init_ctx: + /* + * Do not touch the prologue and epilogue as they will remain + * unchanged. Only fix the branch target address for subprog +- * calls in the body. ++ * calls in the body, and ldimm64 instructions. + * + * This does not change the offsets and lengths of the subprog + * call instruction sequences and hence, the size of the JITed + * image as well. + */ +- bpf_jit_fixup_subprog_calls(fp, code_base, &cgctx, addrs); ++ bpf_jit_fixup_addresses(fp, code_base, &cgctx, addrs); + + /* There is no need to perform the usual passes. */ + goto skip_codegen_passes; +@@ -241,8 +258,8 @@ skip_codegen_passes: + fp->jited_len = alloclen; + + bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + (bpf_hdr->pages * PAGE_SIZE)); +- bpf_jit_binary_lock_ro(bpf_hdr); + if (!fp->is_func || extra_pass) { ++ bpf_jit_binary_lock_ro(bpf_hdr); + bpf_prog_fill_jited_linfo(fp, addrs); + out_addrs: + kfree(addrs); +diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c +index 0da31d41d4131..bce5eda85170f 100644 +--- a/arch/powerpc/net/bpf_jit_comp32.c ++++ b/arch/powerpc/net/bpf_jit_comp32.c +@@ -191,6 +191,9 @@ void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 fun + + if (image && rel < 0x2000000 && rel >= -0x2000000) { + PPC_BL_ABS(func); ++ EMIT(PPC_RAW_NOP()); ++ EMIT(PPC_RAW_NOP()); ++ EMIT(PPC_RAW_NOP()); + } else { + /* Load function address into r0 */ + EMIT(PPC_RAW_LIS(_R0, IMM_H(func))); +@@ -289,6 +292,8 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * + bool func_addr_fixed; + u64 func_addr; + u32 true_cond; ++ u32 tmp_idx; ++ int j; + + /* + * addrs[] maps a BPF bytecode address into a real offset from +@@ -836,8 +841,12 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * + * 16 byte instruction that uses two 'struct bpf_insn' + */ + case BPF_LD | BPF_IMM | BPF_DW: /* dst = (u64) imm */ ++ tmp_idx = ctx->idx; + PPC_LI32(dst_reg_h, (u32)insn[i + 1].imm); + PPC_LI32(dst_reg, (u32)insn[i].imm); ++ /* padding to allow full 4 instructions for later patching */ ++ for (j = ctx->idx - tmp_idx; j < 4; j++) ++ EMIT(PPC_RAW_NOP()); + /* Adjust for two bpf instructions */ + addrs[++i] = ctx->idx * 4; + break; +diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c +index 8b5157ccfebae..57e1b6680365c 100644 +--- a/arch/powerpc/net/bpf_jit_comp64.c ++++ b/arch/powerpc/net/bpf_jit_comp64.c +@@ -318,6 +318,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * + u64 imm64; + u32 true_cond; + u32 tmp_idx; ++ int j; + + /* + * addrs[] maps a BPF bytecode address into a real offset from +@@ -632,17 +633,21 @@ bpf_alu32_trunc: + EMIT(PPC_RAW_MR(dst_reg, b2p[TMP_REG_1])); + break; + case 64: +- /* +- * Way easier and faster(?) to store the value +- * into stack and then use ldbrx +- * +- * ctx->seen will be reliable in pass2, but +- * the instructions generated will remain the +- * same across all passes +- */ ++ /* Store the value to stack and then use byte-reverse loads */ + PPC_BPF_STL(dst_reg, 1, bpf_jit_stack_local(ctx)); + EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], 1, bpf_jit_stack_local(ctx))); +- EMIT(PPC_RAW_LDBRX(dst_reg, 0, b2p[TMP_REG_1])); ++ if (cpu_has_feature(CPU_FTR_ARCH_206)) { ++ EMIT(PPC_RAW_LDBRX(dst_reg, 0, b2p[TMP_REG_1])); ++ } else { ++ EMIT(PPC_RAW_LWBRX(dst_reg, 0, b2p[TMP_REG_1])); ++ if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN)) ++ EMIT(PPC_RAW_SLDI(dst_reg, dst_reg, 32)); ++ EMIT(PPC_RAW_LI(b2p[TMP_REG_2], 4)); ++ EMIT(PPC_RAW_LWBRX(b2p[TMP_REG_2], b2p[TMP_REG_2], b2p[TMP_REG_1])); ++ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) ++ EMIT(PPC_RAW_SLDI(b2p[TMP_REG_2], b2p[TMP_REG_2], 32)); ++ EMIT(PPC_RAW_OR(dst_reg, dst_reg, b2p[TMP_REG_2])); ++ } + break; + } + break; +@@ -806,9 +811,13 @@ emit_clear: + case BPF_LD | BPF_IMM | BPF_DW: /* dst = (u64) imm */ + imm64 = ((u64)(u32) insn[i].imm) | + (((u64)(u32) insn[i+1].imm) << 32); ++ tmp_idx = ctx->idx; ++ PPC_LI64(dst_reg, imm64); ++ /* padding to allow full 5 instructions for later patching */ ++ for (j = ctx->idx - tmp_idx; j < 5; j++) ++ EMIT(PPC_RAW_NOP()); + /* Adjust for two bpf instructions */ + addrs[++i] = ctx->idx * 4; +- PPC_LI64(dst_reg, imm64); + break; + + /* +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index 73e62e9b179bc..e78de70509472 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -857,6 +857,19 @@ static void write_pmc(int idx, unsigned long val) + } + } + ++static int any_pmc_overflown(struct cpu_hw_events *cpuhw) ++{ ++ int i, idx; ++ ++ for (i = 0; i < cpuhw->n_events; i++) { ++ idx = cpuhw->event[i]->hw.idx; ++ if ((idx) && ((int)read_pmc(idx) < 0)) ++ return idx; ++ } ++ ++ return 0; ++} ++ + /* Called from sysrq_handle_showregs() */ + void perf_event_print_debug(void) + { +@@ -1281,11 +1294,13 @@ static void power_pmu_disable(struct pmu *pmu) + + /* + * Set the 'freeze counters' bit, clear EBE/BHRBA/PMCC/PMAO/FC56 ++ * Also clear PMXE to disable PMI's getting triggered in some ++ * corner cases during PMU disable. + */ + val = mmcr0 = mfspr(SPRN_MMCR0); + val |= MMCR0_FC; + val &= ~(MMCR0_EBE | MMCR0_BHRBA | MMCR0_PMCC | MMCR0_PMAO | +- MMCR0_FC56); ++ MMCR0_PMXE | MMCR0_FC56); + /* Set mmcr0 PMCCEXT for p10 */ + if (ppmu->flags & PPMU_ARCH_31) + val |= MMCR0_PMCCEXT; +@@ -1299,6 +1314,34 @@ static void power_pmu_disable(struct pmu *pmu) + mb(); + isync(); + ++ /* ++ * Some corner cases could clear the PMU counter overflow ++ * while a masked PMI is pending. One such case is when ++ * a PMI happens during interrupt replay and perf counter ++ * values are cleared by PMU callbacks before replay. ++ * ++ * If any PMC corresponding to the active PMU events are ++ * overflown, disable the interrupt by clearing the paca ++ * bit for PMI since we are disabling the PMU now. ++ * Otherwise provide a warning if there is PMI pending, but ++ * no counter is found overflown. ++ */ ++ if (any_pmc_overflown(cpuhw)) { ++ /* ++ * Since power_pmu_disable runs under local_irq_save, it ++ * could happen that code hits a PMC overflow without PMI ++ * pending in paca. Hence only clear PMI pending if it was ++ * set. ++ * ++ * If a PMI is pending, then MSR[EE] must be disabled (because ++ * the masked PMI handler disabling EE). So it is safe to ++ * call clear_pmi_irq_pending(). ++ */ ++ if (pmi_irq_pending()) ++ clear_pmi_irq_pending(); ++ } else ++ WARN_ON(pmi_irq_pending()); ++ + val = mmcra = cpuhw->mmcr.mmcra; + + /* +@@ -1390,6 +1433,15 @@ static void power_pmu_enable(struct pmu *pmu) + * (possibly updated for removal of events). + */ + if (!cpuhw->n_added) { ++ /* ++ * If there is any active event with an overflown PMC ++ * value, set back PACA_IRQ_PMI which would have been ++ * cleared in power_pmu_disable(). ++ */ ++ hard_irq_disable(); ++ if (any_pmc_overflown(cpuhw)) ++ set_pmi_irq_pending(); ++ + mtspr(SPRN_MMCRA, cpuhw->mmcr.mmcra & ~MMCRA_SAMPLE_ENABLE); + mtspr(SPRN_MMCR1, cpuhw->mmcr.mmcr1); + if (ppmu->flags & PPMU_ARCH_31) +@@ -2337,6 +2389,14 @@ static void __perf_event_interrupt(struct pt_regs *regs) + break; + } + } ++ ++ /* ++ * Clear PACA_IRQ_PMI in case it was set by ++ * set_pmi_irq_pending() when PMU was enabled ++ * after accounting for interrupts. ++ */ ++ clear_pmi_irq_pending(); ++ + if (!active) + /* reset non active counters that have overflowed */ + write_pmc(i + 1, 0); +@@ -2356,6 +2416,13 @@ static void __perf_event_interrupt(struct pt_regs *regs) + } + } + } ++ ++ /* ++ * During system wide profling or while specific CPU is monitored for an ++ * event, some corner cases could cause PMC to overflow in idle path. This ++ * will trigger a PMI after waking up from idle. Since counter values are _not_ ++ * saved/restored in idle path, can lead to below "Can't find PMC" message. ++ */ + if (unlikely(!found) && !arch_irq_disabled_regs(regs)) + printk_ratelimited(KERN_WARNING "Can't find PMC that caused IRQ\n"); + +diff --git a/arch/powerpc/perf/power10-events-list.h b/arch/powerpc/perf/power10-events-list.h +index 93be7197d2502..564f14097f07b 100644 +--- a/arch/powerpc/perf/power10-events-list.h ++++ b/arch/powerpc/perf/power10-events-list.h +@@ -9,10 +9,10 @@ + /* + * Power10 event codes. + */ +-EVENT(PM_RUN_CYC, 0x600f4); ++EVENT(PM_CYC, 0x600f4); + EVENT(PM_DISP_STALL_CYC, 0x100f8); + EVENT(PM_EXEC_STALL, 0x30008); +-EVENT(PM_RUN_INST_CMPL, 0x500fa); ++EVENT(PM_INST_CMPL, 0x500fa); + EVENT(PM_BR_CMPL, 0x4d05e); + EVENT(PM_BR_MPRED_CMPL, 0x400f6); + EVENT(PM_BR_FIN, 0x2f04a); +@@ -50,8 +50,8 @@ EVENT(PM_DTLB_MISS, 0x300fc); + /* ITLB Reloaded */ + EVENT(PM_ITLB_MISS, 0x400fc); + +-EVENT(PM_RUN_CYC_ALT, 0x0001e); +-EVENT(PM_RUN_INST_CMPL_ALT, 0x00002); ++EVENT(PM_CYC_ALT, 0x0001e); ++EVENT(PM_INST_CMPL_ALT, 0x00002); + + /* + * Memory Access Events +diff --git a/arch/powerpc/perf/power10-pmu.c b/arch/powerpc/perf/power10-pmu.c +index f9d64c63bb4a7..9dd75f3858372 100644 +--- a/arch/powerpc/perf/power10-pmu.c ++++ b/arch/powerpc/perf/power10-pmu.c +@@ -91,8 +91,8 @@ extern u64 PERF_REG_EXTENDED_MASK; + + /* Table of alternatives, sorted by column 0 */ + static const unsigned int power10_event_alternatives[][MAX_ALT] = { +- { PM_RUN_CYC_ALT, PM_RUN_CYC }, +- { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL }, ++ { PM_CYC_ALT, PM_CYC }, ++ { PM_INST_CMPL_ALT, PM_INST_CMPL }, + }; + + static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[]) +@@ -118,8 +118,8 @@ static int power10_check_attr_config(struct perf_event *ev) + return 0; + } + +-GENERIC_EVENT_ATTR(cpu-cycles, PM_RUN_CYC); +-GENERIC_EVENT_ATTR(instructions, PM_RUN_INST_CMPL); ++GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); ++GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL); + GENERIC_EVENT_ATTR(branch-instructions, PM_BR_CMPL); + GENERIC_EVENT_ATTR(branch-misses, PM_BR_MPRED_CMPL); + GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1); +@@ -148,8 +148,8 @@ CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS); + CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS); + + static struct attribute *power10_events_attr_dd1[] = { +- GENERIC_EVENT_PTR(PM_RUN_CYC), +- GENERIC_EVENT_PTR(PM_RUN_INST_CMPL), ++ GENERIC_EVENT_PTR(PM_CYC), ++ GENERIC_EVENT_PTR(PM_INST_CMPL), + GENERIC_EVENT_PTR(PM_BR_CMPL), + GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL), + GENERIC_EVENT_PTR(PM_LD_REF_L1), +@@ -173,8 +173,8 @@ static struct attribute *power10_events_attr_dd1[] = { + }; + + static struct attribute *power10_events_attr[] = { +- GENERIC_EVENT_PTR(PM_RUN_CYC), +- GENERIC_EVENT_PTR(PM_RUN_INST_CMPL), ++ GENERIC_EVENT_PTR(PM_CYC), ++ GENERIC_EVENT_PTR(PM_INST_CMPL), + GENERIC_EVENT_PTR(PM_BR_FIN), + GENERIC_EVENT_PTR(PM_MPRED_BR_FIN), + GENERIC_EVENT_PTR(PM_LD_REF_L1), +@@ -271,8 +271,8 @@ static const struct attribute_group *power10_pmu_attr_groups[] = { + }; + + static int power10_generic_events_dd1[] = { +- [PERF_COUNT_HW_CPU_CYCLES] = PM_RUN_CYC, +- [PERF_COUNT_HW_INSTRUCTIONS] = PM_RUN_INST_CMPL, ++ [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC, ++ [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_CMPL, + [PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL, + [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1, +@@ -280,8 +280,8 @@ static int power10_generic_events_dd1[] = { + }; + + static int power10_generic_events[] = { +- [PERF_COUNT_HW_CPU_CYCLES] = PM_RUN_CYC, +- [PERF_COUNT_HW_INSTRUCTIONS] = PM_RUN_INST_CMPL, ++ [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC, ++ [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_FIN, + [PERF_COUNT_HW_BRANCH_MISSES] = PM_MPRED_BR_FIN, + [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1, +@@ -548,6 +548,24 @@ static u64 power10_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { + + #undef C + ++/* ++ * Set the MMCR0[CC56RUN] bit to enable counting for ++ * PMC5 and PMC6 regardless of the state of CTRL[RUN], ++ * so that we can use counters 5 and 6 as PM_INST_CMPL and ++ * PM_CYC. ++ */ ++static int power10_compute_mmcr(u64 event[], int n_ev, ++ unsigned int hwc[], struct mmcr_regs *mmcr, ++ struct perf_event *pevents[], u32 flags) ++{ ++ int ret; ++ ++ ret = isa207_compute_mmcr(event, n_ev, hwc, mmcr, pevents, flags); ++ if (!ret) ++ mmcr->mmcr0 |= MMCR0_C56RUN; ++ return ret; ++} ++ + static struct power_pmu power10_pmu = { + .name = "POWER10", + .n_counter = MAX_PMU_COUNTERS, +@@ -555,7 +573,7 @@ static struct power_pmu power10_pmu = { + .test_adder = ISA207_TEST_ADDER, + .group_constraint_mask = CNST_CACHE_PMC4_MASK, + .group_constraint_val = CNST_CACHE_PMC4_VAL, +- .compute_mmcr = isa207_compute_mmcr, ++ .compute_mmcr = power10_compute_mmcr, + .config_bhrb = power10_config_bhrb, + .bhrb_filter_map = power10_bhrb_filter_map, + .get_constraint = isa207_get_constraint, +diff --git a/arch/powerpc/platforms/44x/fsp2.c b/arch/powerpc/platforms/44x/fsp2.c +index b299e43f5ef94..823397c802def 100644 +--- a/arch/powerpc/platforms/44x/fsp2.c ++++ b/arch/powerpc/platforms/44x/fsp2.c +@@ -208,6 +208,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler) + if (irq == NO_IRQ) { + pr_err("device tree node %pOFn is missing a interrupt", + np); ++ of_node_put(np); + return; + } + +@@ -215,6 +216,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler) + if (rc) { + pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d", + np, rc); ++ of_node_put(np); + return; + } + } +diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile +index 60e4e97a929db..260fbad7967b2 100644 +--- a/arch/powerpc/platforms/85xx/Makefile ++++ b/arch/powerpc/platforms/85xx/Makefile +@@ -3,7 +3,9 @@ + # Makefile for the PowerPC 85xx linux kernel. + # + obj-$(CONFIG_SMP) += smp.o +-obj-$(CONFIG_FSL_PMC) += mpc85xx_pm_ops.o ++ifneq ($(CONFIG_FSL_CORENET_RCPM),y) ++obj-$(CONFIG_SMP) += mpc85xx_pm_ops.o ++endif + + obj-y += common.o + +diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c +index 7c0133f558d02..4a8af80011a6f 100644 +--- a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c ++++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c +@@ -17,6 +17,7 @@ + + static struct ccsr_guts __iomem *guts; + ++#ifdef CONFIG_FSL_PMC + static void mpc85xx_irq_mask(int cpu) + { + +@@ -49,6 +50,7 @@ static void mpc85xx_cpu_up_prepare(int cpu) + { + + } ++#endif + + static void mpc85xx_freeze_time_base(bool freeze) + { +@@ -76,10 +78,12 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = { + + static const struct fsl_pm_ops mpc85xx_pm_ops = { + .freeze_time_base = mpc85xx_freeze_time_base, ++#ifdef CONFIG_FSL_PMC + .irq_mask = mpc85xx_irq_mask, + .irq_unmask = mpc85xx_irq_unmask, + .cpu_die = mpc85xx_cpu_die, + .cpu_up_prepare = mpc85xx_cpu_up_prepare, ++#endif + }; + + int __init mpc85xx_setup_pmc(void) +@@ -94,9 +98,8 @@ int __init mpc85xx_setup_pmc(void) + pr_err("Could not map guts node address\n"); + return -ENOMEM; + } ++ qoriq_pm_ops = &mpc85xx_pm_ops; + } + +- qoriq_pm_ops = &mpc85xx_pm_ops; +- + return 0; + } +diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c +index c6df294054fe9..d7081e9af65c7 100644 +--- a/arch/powerpc/platforms/85xx/smp.c ++++ b/arch/powerpc/platforms/85xx/smp.c +@@ -40,7 +40,6 @@ struct epapr_spin_table { + u32 pir; + }; + +-#ifdef CONFIG_HOTPLUG_CPU + static u64 timebase; + static int tb_req; + static int tb_valid; +@@ -112,6 +111,7 @@ static void mpc85xx_take_timebase(void) + local_irq_restore(flags); + } + ++#ifdef CONFIG_HOTPLUG_CPU + static void smp_85xx_cpu_offline_self(void) + { + unsigned int cpu = smp_processor_id(); +@@ -220,7 +220,7 @@ static int smp_85xx_start_cpu(int cpu) + local_irq_save(flags); + hard_irq_disable(); + +- if (qoriq_pm_ops) ++ if (qoriq_pm_ops && qoriq_pm_ops->cpu_up_prepare) + qoriq_pm_ops->cpu_up_prepare(cpu); + + /* if cpu is not spinning, reset it */ +@@ -292,7 +292,7 @@ static int smp_85xx_kick_cpu(int nr) + booting_thread_hwid = cpu_thread_in_core(nr); + primary = cpu_first_thread_sibling(nr); + +- if (qoriq_pm_ops) ++ if (qoriq_pm_ops && qoriq_pm_ops->cpu_up_prepare) + qoriq_pm_ops->cpu_up_prepare(nr); + + /* +@@ -495,21 +495,21 @@ void __init mpc85xx_smp_init(void) + smp_85xx_ops.probe = NULL; + } + +-#ifdef CONFIG_HOTPLUG_CPU + #ifdef CONFIG_FSL_CORENET_RCPM ++ /* Assign a value to qoriq_pm_ops on PPC_E500MC */ + fsl_rcpm_init(); +-#endif +- +-#ifdef CONFIG_FSL_PMC ++#else ++ /* Assign a value to qoriq_pm_ops on !PPC_E500MC */ + mpc85xx_setup_pmc(); + #endif + if (qoriq_pm_ops) { + smp_85xx_ops.give_timebase = mpc85xx_give_timebase; + smp_85xx_ops.take_timebase = mpc85xx_take_timebase; ++#ifdef CONFIG_HOTPLUG_CPU + smp_85xx_ops.cpu_offline_self = smp_85xx_cpu_offline_self; + smp_85xx_ops.cpu_die = qoriq_cpu_kill; +- } + #endif ++ } + smp_ops = &smp_85xx_ops; + + #ifdef CONFIG_KEXEC_CORE +diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c +index 30172e52e16b7..4d82c92ddd523 100644 +--- a/arch/powerpc/platforms/book3s/vas-api.c ++++ b/arch/powerpc/platforms/book3s/vas-api.c +@@ -303,7 +303,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) + return -EINVAL; + } + +- if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) { ++ if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->open_win) { + pr_err("VAS API is not registered\n"); + return -EACCES; + } +@@ -373,7 +373,7 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) + return -EINVAL; + } + +- if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->paste_addr) { ++ if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->paste_addr) { + pr_err("%s(): VAS API is not registered\n", __func__); + return -EACCES; + } +diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c +index fa08699aedeb8..d32f24de84798 100644 +--- a/arch/powerpc/platforms/cell/iommu.c ++++ b/arch/powerpc/platforms/cell/iommu.c +@@ -977,6 +977,7 @@ static int __init cell_iommu_fixed_mapping_init(void) + if (hbase < dbase || (hend > (dbase + dsize))) { + pr_debug("iommu: hash window doesn't fit in" + "real DMA window\n"); ++ of_node_put(np); + return -1; + } + } +diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c +index 5b9a7e9f144b3..dff8d5e7ab82b 100644 +--- a/arch/powerpc/platforms/cell/pervasive.c ++++ b/arch/powerpc/platforms/cell/pervasive.c +@@ -78,6 +78,7 @@ static int cbe_system_reset_exception(struct pt_regs *regs) + switch (regs->msr & SRR1_WAKEMASK) { + case SRR1_WAKEDEC: + set_dec(1); ++ break; + case SRR1_WAKEEE: + /* + * Handle these when interrupts get re-enabled and we take +diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +index 15396333a90bd..a4b020e4b6af0 100644 +--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c ++++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +@@ -214,6 +214,7 @@ void hlwd_pic_probe(void) + irq_set_chained_handler(cascade_virq, + hlwd_pic_irq_cascade); + hlwd_irq_host = host; ++ of_node_put(np); + break; + } + } +diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c +index f77a59b5c2e1a..df89d916236d9 100644 +--- a/arch/powerpc/platforms/powermac/low_i2c.c ++++ b/arch/powerpc/platforms/powermac/low_i2c.c +@@ -582,6 +582,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host, + bus->close = kw_i2c_close; + bus->xfer = kw_i2c_xfer; + mutex_init(&bus->mutex); ++ lockdep_register_key(&bus->lock_key); + lockdep_set_class(&bus->mutex, &bus->lock_key); + if (controller == busnode) + bus->flags = pmac_i2c_multibus; +@@ -810,6 +811,7 @@ static void __init pmu_i2c_probe(void) + bus->hostdata = bus + 1; + bus->xfer = pmu_i2c_xfer; + mutex_init(&bus->mutex); ++ lockdep_register_key(&bus->lock_key); + lockdep_set_class(&bus->mutex, &bus->lock_key); + bus->flags = pmac_i2c_multibus; + list_add(&bus->link, &pmac_i2c_busses); +@@ -933,6 +935,7 @@ static void __init smu_i2c_probe(void) + bus->hostdata = bus + 1; + bus->xfer = smu_i2c_xfer; + mutex_init(&bus->mutex); ++ lockdep_register_key(&bus->lock_key); + lockdep_set_class(&bus->mutex, &bus->lock_key); + bus->flags = 0; + list_add(&bus->link, &pmac_i2c_busses); +diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c +index 1e5d51db40f84..5390c888db162 100644 +--- a/arch/powerpc/platforms/powernv/opal-lpc.c ++++ b/arch/powerpc/platforms/powernv/opal-lpc.c +@@ -396,6 +396,7 @@ void __init opal_lpc_init(void) + if (!of_get_property(np, "primary", NULL)) + continue; + opal_lpc_chip_id = of_get_ibm_chip_id(np); ++ of_node_put(np); + break; + } + if (opal_lpc_chip_id < 0) +diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c +index a191f4c60ce71..113bdb151f687 100644 +--- a/arch/powerpc/platforms/powernv/opal-prd.c ++++ b/arch/powerpc/platforms/powernv/opal-prd.c +@@ -369,6 +369,12 @@ static struct notifier_block opal_prd_event_nb = { + .priority = 0, + }; + ++static struct notifier_block opal_prd_event_nb2 = { ++ .notifier_call = opal_prd_msg_notifier, ++ .next = NULL, ++ .priority = 0, ++}; ++ + static int opal_prd_probe(struct platform_device *pdev) + { + int rc; +@@ -390,9 +396,10 @@ static int opal_prd_probe(struct platform_device *pdev) + return rc; + } + +- rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb); ++ rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb2); + if (rc) { + pr_err("Couldn't register PRD2 event notifier\n"); ++ opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb); + return rc; + } + +@@ -401,6 +408,8 @@ static int opal_prd_probe(struct platform_device *pdev) + pr_err("failed to register miscdev\n"); + opal_message_notifier_unregister(OPAL_MSG_PRD, + &opal_prd_event_nb); ++ opal_message_notifier_unregister(OPAL_MSG_PRD2, ++ &opal_prd_event_nb2); + return rc; + } + +@@ -411,6 +420,7 @@ static int opal_prd_remove(struct platform_device *pdev) + { + misc_deregister(&opal_prd_dev); + opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb); ++ opal_message_notifier_unregister(OPAL_MSG_PRD2, &opal_prd_event_nb2); + return 0; + } + +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index a52af8fbf5711..8322ca86d5acf 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -1092,15 +1092,6 @@ static phys_addr_t ddw_memory_hotplug_max(void) + phys_addr_t max_addr = memory_hotplug_max(); + struct device_node *memory; + +- /* +- * The "ibm,pmemory" can appear anywhere in the address space. +- * Assuming it is still backed by page structs, set the upper limit +- * for the huge DMA window as MAX_PHYSMEM_BITS. +- */ +- if (of_find_node_by_type(NULL, "ibm,pmemory")) +- return (sizeof(phys_addr_t) * 8 <= MAX_PHYSMEM_BITS) ? +- (phys_addr_t) -1 : (1ULL << MAX_PHYSMEM_BITS); +- + for_each_node_by_type(memory, "memory") { + unsigned long start, size; + int n_mem_addr_cells, n_mem_size_cells, len; +@@ -1365,8 +1356,10 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) + len = order_base_2(query.largest_available_block << page_shift); + win_name = DMA64_PROPNAME; + } else { +- direct_mapping = true; +- win_name = DIRECT64_PROPNAME; ++ direct_mapping = !default_win_removed || ++ (len == MAX_PHYSMEM_BITS) || ++ (!pmem_present && (len == max_ram_len)); ++ win_name = direct_mapping ? DIRECT64_PROPNAME : DMA64_PROPNAME; + } + + ret = create_ddw(dev, ddw_avail, &create, page_shift, len); +diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c +index e83e0891272d3..210a37a065fb7 100644 +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -63,6 +63,27 @@ static int mobility_rtas_call(int token, char *buf, s32 scope) + + static int delete_dt_node(struct device_node *dn) + { ++ struct device_node *pdn; ++ bool is_platfac; ++ ++ pdn = of_get_parent(dn); ++ is_platfac = of_node_is_type(dn, "ibm,platform-facilities") || ++ of_node_is_type(pdn, "ibm,platform-facilities"); ++ of_node_put(pdn); ++ ++ /* ++ * The drivers that bind to nodes in the platform-facilities ++ * hierarchy don't support node removal, and the removal directive ++ * from firmware is always followed by an add of an equivalent ++ * node. The capability (e.g. RNG, encryption, compression) ++ * represented by the node is never interrupted by the migration. ++ * So ignore changes to this part of the tree. ++ */ ++ if (is_platfac) { ++ pr_notice("ignoring remove operation for %pOFfp\n", dn); ++ return 0; ++ } ++ + pr_debug("removing node %pOFfp\n", dn); + dlpar_detach_node(dn); + return 0; +@@ -222,6 +243,19 @@ static int add_dt_node(struct device_node *parent_dn, __be32 drc_index) + if (!dn) + return -ENOENT; + ++ /* ++ * Since delete_dt_node() ignores this node type, this is the ++ * necessary counterpart. We also know that a platform-facilities ++ * node returned from dlpar_configure_connector() has children ++ * attached, and dlpar_attach_node() only adds the parent, leaking ++ * the children. So ignore these on the add side for now. ++ */ ++ if (of_node_is_type(dn, "ibm,platform-facilities")) { ++ pr_notice("ignoring add operation for %pOF\n", dn); ++ dlpar_free_cc_nodes(dn); ++ return 0; ++ } ++ + rc = dlpar_attach_node(dn, parent_dn); + if (rc) + dlpar_free_cc_nodes(dn); +diff --git a/arch/powerpc/sysdev/dcr-low.S b/arch/powerpc/sysdev/dcr-low.S +index efeeb1b885a17..329b9c4ae5429 100644 +--- a/arch/powerpc/sysdev/dcr-low.S ++++ b/arch/powerpc/sysdev/dcr-low.S +@@ -11,7 +11,7 @@ + #include <asm/export.h> + + #define DCR_ACCESS_PROLOG(table) \ +- cmpli cr0,r3,1024; \ ++ cmplwi cr0,r3,1024; \ + rlwinm r3,r3,4,18,27; \ + lis r5,table@h; \ + ori r5,r5,table@l; \ +diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig +index 97796c6b63f04..785c292d104b7 100644 +--- a/arch/powerpc/sysdev/xive/Kconfig ++++ b/arch/powerpc/sysdev/xive/Kconfig +@@ -3,7 +3,6 @@ config PPC_XIVE + bool + select PPC_SMP_MUXED_IPI + select HARDIRQS_SW_RESEND +- select IRQ_DOMAIN_NOMAP + + config PPC_XIVE_NATIVE + bool +diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c +index c5d75c02ad8b5..7b69299c29123 100644 +--- a/arch/powerpc/sysdev/xive/common.c ++++ b/arch/powerpc/sysdev/xive/common.c +@@ -1443,8 +1443,7 @@ static const struct irq_domain_ops xive_irq_domain_ops = { + + static void __init xive_init_host(struct device_node *np) + { +- xive_irq_domain = irq_domain_add_nomap(np, XIVE_MAX_IRQ, +- &xive_irq_domain_ops, NULL); ++ xive_irq_domain = irq_domain_add_tree(np, &xive_irq_domain_ops, NULL); + if (WARN_ON(xive_irq_domain == NULL)) + return; + irq_set_default_host(xive_irq_domain); +diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c +index f143b6f111ac0..1179632560b8d 100644 +--- a/arch/powerpc/sysdev/xive/spapr.c ++++ b/arch/powerpc/sysdev/xive/spapr.c +@@ -653,6 +653,9 @@ static int xive_spapr_debug_show(struct seq_file *m, void *private) + struct xive_irq_bitmap *xibm; + char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + ++ if (!buf) ++ return -ENOMEM; ++ + list_for_each_entry(xibm, &xive_irq_bitmaps, list) { + memset(buf, 0, PAGE_SIZE); + bitmap_print_to_pagebuf(true, buf, xibm->bitmap, xibm->count); +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index dd8241c009e53..8b28ff9d98d16 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -3264,8 +3264,7 @@ static void show_task(struct task_struct *volatile tsk) + * appropriate for calling from xmon. This could be moved + * to a common, generic, routine used by both. + */ +- state = (p_state == 0) ? 'R' : +- (p_state < 0) ? 'U' : ++ state = (p_state == TASK_RUNNING) ? 'R' : + (p_state & TASK_UNINTERRUPTIBLE) ? 'D' : + (p_state & TASK_STOPPED) ? 'T' : + (p_state & TASK_TRACED) ? 'C' : +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index f076cee11af69..20bc4b8c13b92 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -158,10 +158,9 @@ config PA_BITS + + config PAGE_OFFSET + hex +- default 0xC0000000 if 32BIT && MAXPHYSMEM_1GB ++ default 0xC0000000 if 32BIT + default 0x80000000 if 64BIT && !MMU +- default 0xffffffff80000000 if 64BIT && MAXPHYSMEM_2GB +- default 0xffffffe000000000 if 64BIT && MAXPHYSMEM_128GB ++ default 0xffffffe000000000 if 64BIT + + config KASAN_SHADOW_OFFSET + hex +@@ -270,24 +269,6 @@ config MODULE_SECTIONS + bool + select HAVE_MOD_ARCH_SPECIFIC + +-choice +- prompt "Maximum Physical Memory" +- default MAXPHYSMEM_1GB if 32BIT +- default MAXPHYSMEM_2GB if 64BIT && CMODEL_MEDLOW +- default MAXPHYSMEM_128GB if 64BIT && CMODEL_MEDANY +- +- config MAXPHYSMEM_1GB +- depends on 32BIT +- bool "1GiB" +- config MAXPHYSMEM_2GB +- depends on 64BIT && CMODEL_MEDLOW +- bool "2GiB" +- config MAXPHYSMEM_128GB +- depends on 64BIT && CMODEL_MEDANY +- bool "128GiB" +-endchoice +- +- + config SMP + bool "Symmetric Multi-Processing" + help +diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile +index 0eb4568fbd290..e03f45f7711aa 100644 +--- a/arch/riscv/Makefile ++++ b/arch/riscv/Makefile +@@ -52,6 +52,12 @@ riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima + riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima + riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd + riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c ++ ++# Newer binutils versions default to ISA spec version 20191213 which moves some ++# instructions from the I extension to the Zicsr and Zifencei extensions. ++toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei) ++riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei ++ + KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y)) + KBUILD_AFLAGS += -march=$(riscv-march-y) + +@@ -108,11 +114,13 @@ PHONY += vdso_install + vdso_install: + $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@ + ++ifeq ($(KBUILD_EXTMOD),) + ifeq ($(CONFIG_MMU),y) + prepare: vdso_prepare + vdso_prepare: prepare0 + $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h + endif ++endif + + ifneq ($(CONFIG_XIP_KERNEL),y) + ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy) +diff --git a/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts +index b254c60589a1c..cce5eca31f257 100644 +--- a/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts ++++ b/arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts +@@ -12,7 +12,7 @@ + #address-cells = <2>; + #size-cells = <2>; + model = "Microchip PolarFire-SoC Icicle Kit"; +- compatible = "microchip,mpfs-icicle-kit"; ++ compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs"; + + aliases { + ethernet0 = &emac1; +@@ -56,8 +56,17 @@ + status = "okay"; + }; + +-&sdcard { ++&mmc { + status = "okay"; ++ ++ bus-width = <4>; ++ disable-wp; ++ cap-sd-highspeed; ++ card-detect-delay = <200>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; + }; + + &emac0 { +diff --git a/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi b/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi +index 9d2fbbc1f7778..4ef4bcb748729 100644 +--- a/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi ++++ b/arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi +@@ -6,11 +6,8 @@ + / { + #address-cells = <2>; + #size-cells = <2>; +- model = "Microchip MPFS Icicle Kit"; +- compatible = "microchip,mpfs-icicle-kit"; +- +- chosen { +- }; ++ model = "Microchip PolarFire SoC"; ++ compatible = "microchip,mpfs"; + + cpus { + #address-cells = <1>; +@@ -262,39 +259,14 @@ + status = "disabled"; + }; + +- emmc: mmc@20008000 { ++ /* Common node entry for emmc/sd */ ++ mmc: mmc@20008000 { + compatible = "cdns,sd4hc"; + reg = <0x0 0x20008000 0x0 0x1000>; + interrupt-parent = <&plic>; + interrupts = <88 89>; + pinctrl-names = "default"; + clocks = <&clkcfg 6>; +- bus-width = <4>; +- cap-mmc-highspeed; +- mmc-ddr-3_3v; +- max-frequency = <200000000>; +- non-removable; +- no-sd; +- no-sdio; +- voltage-ranges = <3300 3300>; +- status = "disabled"; +- }; +- +- sdcard: sdhc@20008000 { +- compatible = "cdns,sd4hc"; +- reg = <0x0 0x20008000 0x0 0x1000>; +- interrupt-parent = <&plic>; +- interrupts = <88>; +- pinctrl-names = "default"; +- clocks = <&clkcfg 6>; +- bus-width = <4>; +- disable-wp; +- cap-sd-highspeed; +- card-detect-delay = <200>; +- sd-uhs-sdr12; +- sd-uhs-sdr25; +- sd-uhs-sdr50; +- sd-uhs-sdr104; + max-frequency = <200000000>; + status = "disabled"; + }; +diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts +index 60846e88ae4b1..22f971e971614 100644 +--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts ++++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts +@@ -80,6 +80,7 @@ + spi-max-frequency = <20000000>; + voltage-ranges = <3300 3300>; + disable-wp; ++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + }; + }; + +diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +index 2e4ea84f27e77..b40990210fb50 100644 +--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts ++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +@@ -2,6 +2,7 @@ + /* Copyright (c) 2020 SiFive, Inc */ + + #include "fu740-c000.dtsi" ++#include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + /* Clock frequency (in Hz) of the PCB crystal for rtcclk */ +@@ -228,6 +229,7 @@ + spi-max-frequency = <20000000>; + voltage-ranges = <3300 3300>; + disable-wp; ++ gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + }; + +diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig +index b16a2a12c82a8..3b9f83221f9c2 100644 +--- a/arch/riscv/configs/nommu_k210_defconfig ++++ b/arch/riscv/configs/nommu_k210_defconfig +@@ -29,8 +29,6 @@ CONFIG_EMBEDDED=y + CONFIG_SLOB=y + # CONFIG_MMU is not set + CONFIG_SOC_CANAAN=y +-CONFIG_SOC_CANAAN_K210_DTB_SOURCE="k210_generic" +-CONFIG_MAXPHYSMEM_2GB=y + CONFIG_SMP=y + CONFIG_NR_CPUS=2 + CONFIG_CMDLINE="earlycon console=ttySIF0" +diff --git a/arch/riscv/configs/nommu_k210_sdcard_defconfig b/arch/riscv/configs/nommu_k210_sdcard_defconfig +index 61f887f654199..15d1fd0a70184 100644 +--- a/arch/riscv/configs/nommu_k210_sdcard_defconfig ++++ b/arch/riscv/configs/nommu_k210_sdcard_defconfig +@@ -21,11 +21,9 @@ CONFIG_EMBEDDED=y + CONFIG_SLOB=y + # CONFIG_MMU is not set + CONFIG_SOC_CANAAN=y +-CONFIG_SOC_CANAAN_K210_DTB_SOURCE="k210_generic" +-CONFIG_MAXPHYSMEM_2GB=y + CONFIG_SMP=y + CONFIG_NR_CPUS=2 +-CONFIG_CMDLINE="earlycon console=ttySIF0 rootdelay=2 root=/dev/mmcblk0p1 ro" ++CONFIG_CMDLINE="earlycon console=ttySIF0 root=/dev/mmcblk0p1 rootwait ro" + CONFIG_CMDLINE_FORCE=y + # CONFIG_SECCOMP is not set + # CONFIG_STACKPROTECTOR is not set +diff --git a/arch/riscv/configs/nommu_virt_defconfig b/arch/riscv/configs/nommu_virt_defconfig +index e046a0babde43..f224be697785f 100644 +--- a/arch/riscv/configs/nommu_virt_defconfig ++++ b/arch/riscv/configs/nommu_virt_defconfig +@@ -27,7 +27,6 @@ CONFIG_SLOB=y + # CONFIG_SLAB_MERGE_DEFAULT is not set + # CONFIG_MMU is not set + CONFIG_SOC_VIRT=y +-CONFIG_MAXPHYSMEM_2GB=y + CONFIG_SMP=y + CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0" + CONFIG_CMDLINE_FORCE=y +diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h +index 49b398fe99f1b..cc4f6787f9371 100644 +--- a/arch/riscv/include/asm/efi.h ++++ b/arch/riscv/include/asm/efi.h +@@ -13,7 +13,6 @@ + + #ifdef CONFIG_EFI + extern void efi_init(void); +-extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); + #else + #define efi_init() + #endif +diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h +index a7d2811f35365..62d0e6e61da83 100644 +--- a/arch/riscv/include/asm/smp.h ++++ b/arch/riscv/include/asm/smp.h +@@ -43,7 +43,6 @@ void arch_send_call_function_ipi_mask(struct cpumask *mask); + void arch_send_call_function_single_ipi(int cpu); + + int riscv_hartid_to_cpuid(int hartid); +-void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out); + + /* Set custom IPI operations */ + void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops); +@@ -85,13 +84,6 @@ static inline unsigned long cpuid_to_hartid_map(int cpu) + return boot_cpu_hartid; + } + +-static inline void riscv_cpuid_to_hartid_mask(const struct cpumask *in, +- struct cpumask *out) +-{ +- cpumask_clear(out); +- cpumask_set_cpu(boot_cpu_hartid, out); +-} +- + static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops) + { + } +@@ -102,6 +94,8 @@ static inline void riscv_clear_ipi(void) + + #endif /* CONFIG_SMP */ + ++void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out); ++ + #if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP) + bool cpu_has_hotplug(unsigned int cpu); + #else +diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile +index 3397ddac1a30c..16308ef1e5787 100644 +--- a/arch/riscv/kernel/Makefile ++++ b/arch/riscv/kernel/Makefile +@@ -50,6 +50,8 @@ obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o + obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o + obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o + ++obj-$(CONFIG_TRACE_IRQFLAGS) += trace_irq.o ++ + obj-$(CONFIG_RISCV_BASE_PMU) += perf_event.o + obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o + obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o +diff --git a/arch/riscv/kernel/cpu-hotplug.c b/arch/riscv/kernel/cpu-hotplug.c +index df84e0c13db18..66ddfba1cfbef 100644 +--- a/arch/riscv/kernel/cpu-hotplug.c ++++ b/arch/riscv/kernel/cpu-hotplug.c +@@ -12,6 +12,7 @@ + #include <linux/sched/hotplug.h> + #include <asm/irq.h> + #include <asm/cpu_ops.h> ++#include <asm/numa.h> + #include <asm/sbi.h> + + void cpu_stop(void); +@@ -46,6 +47,7 @@ int __cpu_disable(void) + return ret; + + remove_cpu_topology(cpu); ++ numa_remove_cpu(cpu); + set_cpu_online(cpu, false); + irq_migrate_all_off_this_cpu(); + +diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S +index 98f502654edd3..7e52ad5d61adb 100644 +--- a/arch/riscv/kernel/entry.S ++++ b/arch/riscv/kernel/entry.S +@@ -108,7 +108,7 @@ _save_context: + .option pop + + #ifdef CONFIG_TRACE_IRQFLAGS +- call trace_hardirqs_off ++ call __trace_hardirqs_off + #endif + + #ifdef CONFIG_CONTEXT_TRACKING +@@ -144,7 +144,7 @@ skip_context_tracking: + li t0, EXC_BREAKPOINT + beq s4, t0, 1f + #ifdef CONFIG_TRACE_IRQFLAGS +- call trace_hardirqs_on ++ call __trace_hardirqs_on + #endif + csrs CSR_STATUS, SR_IE + +@@ -235,7 +235,7 @@ ret_from_exception: + REG_L s0, PT_STATUS(sp) + csrc CSR_STATUS, SR_IE + #ifdef CONFIG_TRACE_IRQFLAGS +- call trace_hardirqs_off ++ call __trace_hardirqs_off + #endif + #ifdef CONFIG_RISCV_M_MODE + /* the MPP value is too large to be used as an immediate arg for addi */ +@@ -271,10 +271,10 @@ restore_all: + REG_L s1, PT_STATUS(sp) + andi t0, s1, SR_PIE + beqz t0, 1f +- call trace_hardirqs_on ++ call __trace_hardirqs_on + j 2f + 1: +- call trace_hardirqs_off ++ call __trace_hardirqs_off + 2: + #endif + REG_L a0, PT_STATUS(sp) +diff --git a/arch/riscv/kernel/kexec_relocate.S b/arch/riscv/kernel/kexec_relocate.S +index a80b52a74f58c..059c5e216ae75 100644 +--- a/arch/riscv/kernel/kexec_relocate.S ++++ b/arch/riscv/kernel/kexec_relocate.S +@@ -159,25 +159,15 @@ SYM_CODE_START(riscv_kexec_norelocate) + * s0: (const) Phys address to jump to + * s1: (const) Phys address of the FDT image + * s2: (const) The hartid of the current hart +- * s3: (const) kernel_map.va_pa_offset, used when switching MMU off + */ + mv s0, a1 + mv s1, a2 + mv s2, a3 +- mv s3, a4 + + /* Disable / cleanup interrupts */ + csrw CSR_SIE, zero + csrw CSR_SIP, zero + +- /* Switch to physical addressing */ +- la s4, 1f +- sub s4, s4, s3 +- csrw CSR_STVEC, s4 +- csrw CSR_SATP, zero +- +-.align 2 +-1: + /* Pass the arguments to the next kernel / Cleanup*/ + mv a0, s2 + mv a1, s1 +@@ -214,7 +204,15 @@ SYM_CODE_START(riscv_kexec_norelocate) + csrw CSR_SCAUSE, zero + csrw CSR_SSCRATCH, zero + +- jalr zero, a2, 0 ++ /* ++ * Switch to physical addressing ++ * This will also trigger a jump to CSR_STVEC ++ * which in this case is the address of the new ++ * kernel. ++ */ ++ csrw CSR_STVEC, a2 ++ csrw CSR_SATP, zero ++ + SYM_CODE_END(riscv_kexec_norelocate) + + .section ".rodata" +diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c +index e6eca271a4d60..cbef0fc73afa8 100644 +--- a/arch/riscv/kernel/machine_kexec.c ++++ b/arch/riscv/kernel/machine_kexec.c +@@ -169,7 +169,8 @@ machine_kexec(struct kimage *image) + struct kimage_arch *internal = &image->arch; + unsigned long jump_addr = (unsigned long) image->start; + unsigned long first_ind_entry = (unsigned long) &image->head; +- unsigned long this_hart_id = raw_smp_processor_id(); ++ unsigned long this_cpu_id = smp_processor_id(); ++ unsigned long this_hart_id = cpuid_to_hartid_map(this_cpu_id); + unsigned long fdt_addr = internal->fdt_addr; + void *control_code_buffer = page_address(image->control_code_page); + riscv_kexec_method kexec_method = NULL; +diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c +index 0bb1854dce833..8ecfc4c128bc5 100644 +--- a/arch/riscv/kernel/perf_callchain.c ++++ b/arch/riscv/kernel/perf_callchain.c +@@ -56,10 +56,11 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry, + void perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + unsigned long fp = 0; + + /* RISC-V does not support perf in guest mode. */ +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) ++ if (guest_cbs && guest_cbs->is_in_guest()) + return; + + fp = regs->s0; +@@ -78,8 +79,10 @@ static bool fill_callchain(void *entry, unsigned long pc) + void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); ++ + /* RISC-V does not support perf in guest mode. */ +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + pr_warn("RISC-V does not support perf in guest mode!"); + return; + } +diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c +index b9620e5f00baf..6c5caf5eb9061 100644 +--- a/arch/riscv/kernel/setup.c ++++ b/arch/riscv/kernel/setup.c +@@ -59,6 +59,16 @@ atomic_t hart_lottery __section(".sdata") + unsigned long boot_cpu_hartid; + static DEFINE_PER_CPU(struct cpu, cpu_devices); + ++void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out) ++{ ++ int cpu; ++ ++ cpumask_clear(out); ++ for_each_cpu(cpu, in) ++ cpumask_set_cpu(cpuid_to_hartid_map(cpu), out); ++} ++EXPORT_SYMBOL_GPL(riscv_cpuid_to_hartid_mask); ++ + /* + * Place kernel memory regions on the resource tree so that + * kexec-tools can retrieve them from /proc/iomem. While there +diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c +index 921d9d7df4001..d0147294691d9 100644 +--- a/arch/riscv/kernel/smp.c ++++ b/arch/riscv/kernel/smp.c +@@ -59,16 +59,6 @@ int riscv_hartid_to_cpuid(int hartid) + return -ENOENT; + } + +-void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out) +-{ +- int cpu; +- +- cpumask_clear(out); +- for_each_cpu(cpu, in) +- cpumask_set_cpu(cpuid_to_hartid_map(cpu), out); +-} +-EXPORT_SYMBOL_GPL(riscv_cpuid_to_hartid_mask); +- + bool arch_match_cpu_phys_id(int cpu, u64 phys_id) + { + return phys_id == cpuid_to_hartid_map(cpu); +diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c +index 315db3d0229bf..c2601150b91c8 100644 +--- a/arch/riscv/kernel/stacktrace.c ++++ b/arch/riscv/kernel/stacktrace.c +@@ -22,15 +22,16 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + bool (*fn)(void *, unsigned long), void *arg) + { + unsigned long fp, sp, pc; ++ int level = 0; + + if (regs) { + fp = frame_pointer(regs); + sp = user_stack_pointer(regs); + pc = instruction_pointer(regs); + } else if (task == NULL || task == current) { +- fp = (unsigned long)__builtin_frame_address(1); +- sp = (unsigned long)__builtin_frame_address(0); +- pc = (unsigned long)__builtin_return_address(0); ++ fp = (unsigned long)__builtin_frame_address(0); ++ sp = sp_in_global; ++ pc = (unsigned long)walk_stackframe; + } else { + /* task blocked in __switch_to */ + fp = task->thread.s[0]; +@@ -42,7 +43,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, + unsigned long low, high; + struct stackframe *frame; + +- if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc))) ++ if (unlikely(!__kernel_text_address(pc) || (level++ >= 1 && !fn(arg, pc)))) + break; + + /* Validate frame pointer */ +diff --git a/arch/riscv/kernel/trace_irq.c b/arch/riscv/kernel/trace_irq.c +new file mode 100644 +index 0000000000000..095ac976d7da1 +--- /dev/null ++++ b/arch/riscv/kernel/trace_irq.c +@@ -0,0 +1,27 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 Changbin Du <changbin.du@gmail.com> ++ */ ++ ++#include <linux/irqflags.h> ++#include <linux/kprobes.h> ++#include "trace_irq.h" ++ ++/* ++ * trace_hardirqs_on/off require the caller to setup frame pointer properly. ++ * Otherwise, CALLER_ADDR1 might trigger an pagging exception in kernel. ++ * Here we add one extra level so they can be safely called by low ++ * level entry code which $fp is used for other purpose. ++ */ ++ ++void __trace_hardirqs_on(void) ++{ ++ trace_hardirqs_on(); ++} ++NOKPROBE_SYMBOL(__trace_hardirqs_on); ++ ++void __trace_hardirqs_off(void) ++{ ++ trace_hardirqs_off(); ++} ++NOKPROBE_SYMBOL(__trace_hardirqs_off); +diff --git a/arch/riscv/kernel/trace_irq.h b/arch/riscv/kernel/trace_irq.h +new file mode 100644 +index 0000000000000..99fe67377e5ed +--- /dev/null ++++ b/arch/riscv/kernel/trace_irq.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2022 Changbin Du <changbin.du@gmail.com> ++ */ ++#ifndef __TRACE_IRQ_H ++#define __TRACE_IRQ_H ++ ++void __trace_hardirqs_on(void); ++void __trace_hardirqs_off(void); ++ ++#endif /* __TRACE_IRQ_H */ +diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile +index 7ebaef10ea1b6..ac7a25298a04a 100644 +--- a/arch/riscv/mm/Makefile ++++ b/arch/riscv/mm/Makefile +@@ -24,6 +24,9 @@ obj-$(CONFIG_KASAN) += kasan_init.o + ifdef CONFIG_KASAN + KASAN_SANITIZE_kasan_init.o := n + KASAN_SANITIZE_init.o := n ++ifdef CONFIG_DEBUG_VIRTUAL ++KASAN_SANITIZE_physaddr.o := n ++endif + endif + + obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o +diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c +index c0cddf0fc22db..3de593b26850e 100644 +--- a/arch/riscv/mm/init.c ++++ b/arch/riscv/mm/init.c +@@ -187,10 +187,10 @@ static void __init setup_bootmem(void) + + + phys_ram_end = memblock_end_of_DRAM(); +-#ifndef CONFIG_64BIT + #ifndef CONFIG_XIP_KERNEL + phys_ram_base = memblock_start_of_DRAM(); + #endif ++#ifndef CONFIG_64BIT + /* + * memblock allocator is not aware of the fact that last 4K bytes of + * the addressable memory can not be mapped because of IS_ERR_VALUE +@@ -451,6 +451,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) + } + + #ifdef CONFIG_XIP_KERNEL ++#define phys_ram_base (*(phys_addr_t *)XIP_FIXUP(&phys_ram_base)) + /* called from head.S with MMU off */ + asmlinkage void __init __copy_data(void) + { +@@ -813,13 +814,22 @@ static void __init reserve_crashkernel(void) + /* + * Current riscv boot protocol requires 2MB alignment for + * RV64 and 4MB alignment for RV32 (hugepage size) ++ * ++ * Try to alloc from 32bit addressible physical memory so that ++ * swiotlb can work on the crash kernel. + */ + crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE, +- search_start, search_end); ++ search_start, ++ min(search_end, (unsigned long) SZ_4G)); + if (crash_base == 0) { +- pr_warn("crashkernel: couldn't allocate %lldKB\n", +- crash_size >> 10); +- return; ++ /* Try again without restricting region to 32bit addressible memory */ ++ crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE, ++ search_start, search_end); ++ if (crash_base == 0) { ++ pr_warn("crashkernel: couldn't allocate %lldKB\n", ++ crash_size >> 10); ++ return; ++ } + } + + pr_info("crashkernel: reserved 0x%016llx - 0x%016llx (%lld MB)\n", +diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c +index 54294f83513d1..e26e367a3d9ef 100644 +--- a/arch/riscv/mm/kasan_init.c ++++ b/arch/riscv/mm/kasan_init.c +@@ -22,8 +22,7 @@ asmlinkage void __init kasan_early_init(void) + + for (i = 0; i < PTRS_PER_PTE; ++i) + set_pte(kasan_early_shadow_pte + i, +- mk_pte(virt_to_page(kasan_early_shadow_page), +- PAGE_KERNEL)); ++ pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL)); + + for (i = 0; i < PTRS_PER_PMD; ++i) + set_pmd(kasan_early_shadow_pmd + i, +diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig +index b86de61b8caa2..797041b5109a2 100644 +--- a/arch/s390/Kconfig ++++ b/arch/s390/Kconfig +@@ -47,7 +47,7 @@ config ARCH_SUPPORTS_UPROBES + config KASAN_SHADOW_OFFSET + hex + depends on KASAN +- default 0x18000000000000 ++ default 0x1C000000000000 + + config S390 + def_bool y +diff --git a/arch/s390/Makefile b/arch/s390/Makefile +index 450b351dfa8ef..d4fd1426a8226 100644 +--- a/arch/s390/Makefile ++++ b/arch/s390/Makefile +@@ -79,10 +79,12 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(aflags-y) + KBUILD_CFLAGS_DECOMPRESSOR += $(cflags-y) + + ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),) +-cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE) +-ifeq ($(call cc-option,-mstack-size=8192),) +-cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD) +-endif ++ CC_FLAGS_CHECK_STACK := -mstack-size=$(STACK_SIZE) ++ ifeq ($(call cc-option,-mstack-size=8192),) ++ CC_FLAGS_CHECK_STACK += -mstack-guard=$(CONFIG_STACK_GUARD) ++ endif ++ export CC_FLAGS_CHECK_STACK ++ cflags-$(CONFIG_CHECK_STACK) += $(CC_FLAGS_CHECK_STACK) + endif + + ifdef CONFIG_EXPOLINE +diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c +index 6dc8d0a538640..b13352dd1e1cf 100644 +--- a/arch/s390/boot/startup.c ++++ b/arch/s390/boot/startup.c +@@ -148,82 +148,56 @@ static void setup_ident_map_size(unsigned long max_physmem_end) + + static void setup_kernel_memory_layout(void) + { +- bool vmalloc_size_verified = false; +- unsigned long vmemmap_off; +- unsigned long vspace_left; ++ unsigned long vmemmap_start; + unsigned long rte_size; + unsigned long pages; +- unsigned long vmax; + + pages = ident_map_size / PAGE_SIZE; + /* vmemmap contains a multiple of PAGES_PER_SECTION struct pages */ + vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page); + + /* choose kernel address space layout: 4 or 3 levels. */ +- vmemmap_off = round_up(ident_map_size, _REGION3_SIZE); ++ vmemmap_start = round_up(ident_map_size, _REGION3_SIZE); + if (IS_ENABLED(CONFIG_KASAN) || + vmalloc_size > _REGION2_SIZE || +- vmemmap_off + vmemmap_size + vmalloc_size + MODULES_LEN > _REGION2_SIZE) +- vmax = _REGION1_SIZE; +- else +- vmax = _REGION2_SIZE; +- +- /* keep vmemmap_off aligned to a top level region table entry */ +- rte_size = vmax == _REGION1_SIZE ? _REGION2_SIZE : _REGION3_SIZE; +- MODULES_END = vmax; +- if (is_prot_virt_host()) { +- /* +- * forcing modules and vmalloc area under the ultravisor +- * secure storage limit, so that any vmalloc allocation +- * we do could be used to back secure guest storage. +- */ +- adjust_to_uv_max(&MODULES_END); +- } +- +-#ifdef CONFIG_KASAN +- if (MODULES_END < vmax) { +- /* force vmalloc and modules below kasan shadow */ +- MODULES_END = min(MODULES_END, KASAN_SHADOW_START); ++ vmemmap_start + vmemmap_size + vmalloc_size + MODULES_LEN > ++ _REGION2_SIZE) { ++ MODULES_END = _REGION1_SIZE; ++ rte_size = _REGION2_SIZE; + } else { +- /* +- * leave vmalloc and modules above kasan shadow but make +- * sure they don't overlap with it +- */ +- vmalloc_size = min(vmalloc_size, vmax - KASAN_SHADOW_END - MODULES_LEN); +- vmalloc_size_verified = true; +- vspace_left = KASAN_SHADOW_START; ++ MODULES_END = _REGION2_SIZE; ++ rte_size = _REGION3_SIZE; + } ++ /* ++ * forcing modules and vmalloc area under the ultravisor ++ * secure storage limit, so that any vmalloc allocation ++ * we do could be used to back secure guest storage. ++ */ ++ adjust_to_uv_max(&MODULES_END); ++#ifdef CONFIG_KASAN ++ /* force vmalloc and modules below kasan shadow */ ++ MODULES_END = min(MODULES_END, KASAN_SHADOW_START); + #endif + MODULES_VADDR = MODULES_END - MODULES_LEN; + VMALLOC_END = MODULES_VADDR; + +- if (vmalloc_size_verified) { +- VMALLOC_START = VMALLOC_END - vmalloc_size; +- } else { +- vmemmap_off = round_up(ident_map_size, rte_size); +- +- if (vmemmap_off + vmemmap_size > VMALLOC_END || +- vmalloc_size > VMALLOC_END - vmemmap_off - vmemmap_size) { +- /* +- * allow vmalloc area to occupy up to 1/2 of +- * the rest virtual space left. +- */ +- vmalloc_size = min(vmalloc_size, VMALLOC_END / 2); +- } +- VMALLOC_START = VMALLOC_END - vmalloc_size; +- vspace_left = VMALLOC_START; +- } ++ /* allow vmalloc area to occupy up to about 1/2 of the rest virtual space left */ ++ vmalloc_size = min(vmalloc_size, round_down(VMALLOC_END / 2, _REGION3_SIZE)); ++ VMALLOC_START = VMALLOC_END - vmalloc_size; + +- pages = vspace_left / (PAGE_SIZE + sizeof(struct page)); ++ /* split remaining virtual space between 1:1 mapping & vmemmap array */ ++ pages = VMALLOC_START / (PAGE_SIZE + sizeof(struct page)); + pages = SECTION_ALIGN_UP(pages); +- vmemmap_off = round_up(vspace_left - pages * sizeof(struct page), rte_size); +- /* keep vmemmap left most starting from a fresh region table entry */ +- vmemmap_off = min(vmemmap_off, round_up(ident_map_size, rte_size)); +- /* take care that identity map is lower then vmemmap */ +- ident_map_size = min(ident_map_size, vmemmap_off); ++ /* keep vmemmap_start aligned to a top level region table entry */ ++ vmemmap_start = round_down(VMALLOC_START - pages * sizeof(struct page), rte_size); ++ /* vmemmap_start is the future VMEM_MAX_PHYS, make sure it is within MAX_PHYSMEM */ ++ vmemmap_start = min(vmemmap_start, 1UL << MAX_PHYSMEM_BITS); ++ /* make sure identity map doesn't overlay with vmemmap */ ++ ident_map_size = min(ident_map_size, vmemmap_start); + vmemmap_size = SECTION_ALIGN_UP(ident_map_size / PAGE_SIZE) * sizeof(struct page); +- VMALLOC_START = max(vmemmap_off + vmemmap_size, VMALLOC_START); +- vmemmap = (struct page *)vmemmap_off; ++ /* make sure vmemmap doesn't overlay with vmalloc area */ ++ VMALLOC_START = max(vmemmap_start + vmemmap_size, VMALLOC_START); ++ vmemmap = (struct page *)vmemmap_start; + } + + /* +diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c +index 33f973ff97442..e8f15dbb89d02 100644 +--- a/arch/s390/hypfs/hypfs_vm.c ++++ b/arch/s390/hypfs/hypfs_vm.c +@@ -20,6 +20,7 @@ + + static char local_guest[] = " "; + static char all_guests[] = "* "; ++static char *all_groups = all_guests; + static char *guest_query; + + struct diag2fc_data { +@@ -62,10 +63,11 @@ static int diag2fc(int size, char* query, void *addr) + + memcpy(parm_list.userid, query, NAME_LEN); + ASCEBC(parm_list.userid, NAME_LEN); +- parm_list.addr = (unsigned long) addr ; ++ memcpy(parm_list.aci_grp, all_groups, NAME_LEN); ++ ASCEBC(parm_list.aci_grp, NAME_LEN); ++ parm_list.addr = (unsigned long)addr; + parm_list.size = size; + parm_list.fmt = 0x02; +- memset(parm_list.aci_grp, 0x40, NAME_LEN); + rc = -1; + + diag_stat_inc(DIAG_STAT_X2FC); +diff --git a/arch/s390/include/asm/extable.h b/arch/s390/include/asm/extable.h +index 16dc57dd90b30..8511f0e59290f 100644 +--- a/arch/s390/include/asm/extable.h ++++ b/arch/s390/include/asm/extable.h +@@ -69,8 +69,13 @@ static inline void swap_ex_entry_fixup(struct exception_table_entry *a, + { + a->fixup = b->fixup + delta; + b->fixup = tmp.fixup - delta; +- a->handler = b->handler + delta; +- b->handler = tmp.handler - delta; ++ a->handler = b->handler; ++ if (a->handler) ++ a->handler += delta; ++ b->handler = tmp.handler; ++ if (b->handler) ++ b->handler -= delta; + } ++#define swap_ex_entry_fixup swap_ex_entry_fixup + + #endif +diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h +index ea398a05f6432..7f3c9ac34bd8d 100644 +--- a/arch/s390/include/asm/kexec.h ++++ b/arch/s390/include/asm/kexec.h +@@ -74,6 +74,12 @@ void *kexec_file_add_components(struct kimage *image, + int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val, + unsigned long addr); + ++#define ARCH_HAS_KIMAGE_ARCH ++ ++struct kimage_arch { ++ void *ipl_buf; ++}; ++ + extern const struct kexec_file_ops s390_kexec_image_ops; + extern const struct kexec_file_ops s390_kexec_elf_ops; + +diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h +index e4dc64cc9c555..287bb88f76986 100644 +--- a/arch/s390/include/asm/pci_io.h ++++ b/arch/s390/include/asm/pci_io.h +@@ -14,12 +14,13 @@ + + /* I/O Map */ + #define ZPCI_IOMAP_SHIFT 48 +-#define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000UL ++#define ZPCI_IOMAP_ADDR_SHIFT 62 ++#define ZPCI_IOMAP_ADDR_BASE (1UL << ZPCI_IOMAP_ADDR_SHIFT) + #define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1) + #define ZPCI_IOMAP_MAX_ENTRIES \ +- ((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT)) ++ (1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT)) + #define ZPCI_IOMAP_ADDR_IDX_MASK \ +- (~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE) ++ ((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK) + + struct zpci_iomap_entry { + u32 fh; +diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c +index d72a6df058d79..785d54c9350c4 100644 +--- a/arch/s390/kernel/crash_dump.c ++++ b/arch/s390/kernel/crash_dump.c +@@ -191,8 +191,8 @@ static int copy_oldmem_user(void __user *dst, void *src, size_t count) + return rc; + } else { + /* Check for swapped kdump oldmem areas */ +- if (oldmem_data.start && from - oldmem_data.size < oldmem_data.size) { +- from -= oldmem_data.size; ++ if (oldmem_data.start && from - oldmem_data.start < oldmem_data.size) { ++ from -= oldmem_data.start; + len = min(count, oldmem_data.size - from); + } else if (oldmem_data.start && from < oldmem_data.size) { + len = min(count, oldmem_data.size - from); +diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c +index e2cc35775b996..5ad1dde23dc59 100644 +--- a/arch/s390/kernel/ipl.c ++++ b/arch/s390/kernel/ipl.c +@@ -2156,7 +2156,7 @@ void *ipl_report_finish(struct ipl_report *report) + + buf = vzalloc(report->size); + if (!buf) +- return ERR_PTR(-ENOMEM); ++ goto out; + ptr = buf; + + memcpy(ptr, report->ipib, report->ipib->hdr.len); +@@ -2195,6 +2195,7 @@ void *ipl_report_finish(struct ipl_report *report) + } + + BUG_ON(ptr > buf + report->size); ++out: + return buf; + } + +diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c +index 3a3145c4a3ba4..be5d432b902e0 100644 +--- a/arch/s390/kernel/irq.c ++++ b/arch/s390/kernel/irq.c +@@ -138,7 +138,7 @@ void noinstr do_io_irq(struct pt_regs *regs) + struct pt_regs *old_regs = set_irq_regs(regs); + int from_idle; + +- irq_enter(); ++ irq_enter_rcu(); + + if (user_mode(regs)) + update_timer_sys(); +@@ -155,7 +155,8 @@ void noinstr do_io_irq(struct pt_regs *regs) + do_irq_async(regs, IO_INTERRUPT); + } while (MACHINE_IS_LPAR && irq_pending(regs)); + +- irq_exit(); ++ irq_exit_rcu(); ++ + set_irq_regs(old_regs); + irqentry_exit(regs, state); + +@@ -169,7 +170,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) + struct pt_regs *old_regs = set_irq_regs(regs); + int from_idle; + +- irq_enter(); ++ irq_enter_rcu(); + + if (user_mode(regs)) + update_timer_sys(); +@@ -184,7 +185,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) + + do_irq_async(regs, EXT_INTERRUPT); + +- irq_exit(); ++ irq_exit_rcu(); + set_irq_regs(old_regs); + irqentry_exit(regs, state); + +diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c +index f9e4baa64b675..a81d6c43b9b61 100644 +--- a/arch/s390/kernel/machine_kexec_file.c ++++ b/arch/s390/kernel/machine_kexec_file.c +@@ -12,6 +12,7 @@ + #include <linux/kexec.h> + #include <linux/module_signature.h> + #include <linux/verification.h> ++#include <linux/vmalloc.h> + #include <asm/boot_data.h> + #include <asm/ipl.h> + #include <asm/setup.h> +@@ -170,6 +171,7 @@ static int kexec_file_add_ipl_report(struct kimage *image, + struct kexec_buf buf; + unsigned long addr; + void *ptr, *end; ++ int ret; + + buf.image = image; + +@@ -199,9 +201,13 @@ static int kexec_file_add_ipl_report(struct kimage *image, + ptr += len; + } + ++ ret = -ENOMEM; + buf.buffer = ipl_report_finish(data->report); ++ if (!buf.buffer) ++ goto out; + buf.bufsz = data->report->size; + buf.memsz = buf.bufsz; ++ image->arch.ipl_buf = buf.buffer; + + data->memsz += buf.memsz; + +@@ -209,7 +215,9 @@ static int kexec_file_add_ipl_report(struct kimage *image, + data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr); + *lc_ipl_parmblock_ptr = (__u32)buf.mem; + +- return kexec_add_buffer(&buf); ++ ret = kexec_add_buffer(&buf); ++out: ++ return ret; + } + + void *kexec_file_add_components(struct kimage *image, +@@ -269,6 +277,7 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, + { + Elf_Rela *relas; + int i, r_type; ++ int ret; + + relas = (void *)pi->ehdr + relsec->sh_offset; + +@@ -303,7 +312,15 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, + addr = section->sh_addr + relas[i].r_offset; + + r_type = ELF64_R_TYPE(relas[i].r_info); +- arch_kexec_do_relocs(r_type, loc, val, addr); ++ ++ if (r_type == R_390_PLT32DBL) ++ r_type = R_390_PC32DBL; ++ ++ ret = arch_kexec_do_relocs(r_type, loc, val, addr); ++ if (ret) { ++ pr_err("Unknown rela relocation: %d\n", r_type); ++ return -ENOEXEC; ++ } + } + return 0; + } +@@ -321,3 +338,11 @@ int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, + + return kexec_image_probe_default(image, buf, buf_len); + } ++ ++int arch_kimage_file_post_load_cleanup(struct kimage *image) ++{ ++ vfree(image->arch.ipl_buf); ++ image->arch.ipl_buf = NULL; ++ ++ return kexec_image_post_load_cleanup_default(image); ++} +diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c +index b01ba460b7cad..b032e556eeb71 100644 +--- a/arch/s390/kernel/module.c ++++ b/arch/s390/kernel/module.c +@@ -33,18 +33,19 @@ + #define DEBUGP(fmt , ...) + #endif + +-#define PLT_ENTRY_SIZE 20 ++#define PLT_ENTRY_SIZE 22 + + void *module_alloc(unsigned long size) + { ++ gfp_t gfp_mask = GFP_KERNEL; + void *p; + + if (PAGE_ALIGN(size) > MODULES_LEN) + return NULL; + p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, MODULES_END, +- GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, ++ gfp_mask, PAGE_KERNEL_EXEC, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, + __builtin_return_address(0)); +- if (p && (kasan_module_alloc(p, size) < 0)) { ++ if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { + vfree(p); + return NULL; + } +@@ -340,27 +341,26 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, + case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */ + case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */ + if (info->plt_initialized == 0) { +- unsigned int insn[5]; +- unsigned int *ip = me->core_layout.base + +- me->arch.plt_offset + +- info->plt_offset; +- +- insn[0] = 0x0d10e310; /* basr 1,0 */ +- insn[1] = 0x100a0004; /* lg 1,10(1) */ ++ unsigned char insn[PLT_ENTRY_SIZE]; ++ char *plt_base; ++ char *ip; ++ ++ plt_base = me->core_layout.base + me->arch.plt_offset; ++ ip = plt_base + info->plt_offset; ++ *(int *)insn = 0x0d10e310; /* basr 1,0 */ ++ *(int *)&insn[4] = 0x100c0004; /* lg 1,12(1) */ + if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable) { +- unsigned int *ij; +- ij = me->core_layout.base + +- me->arch.plt_offset + +- me->arch.plt_size - PLT_ENTRY_SIZE; +- insn[2] = 0xa7f40000 + /* j __jump_r1 */ +- (unsigned int)(u16) +- (((unsigned long) ij - 8 - +- (unsigned long) ip) / 2); ++ char *jump_r1; ++ ++ jump_r1 = plt_base + me->arch.plt_size - ++ PLT_ENTRY_SIZE; ++ /* brcl 0xf,__jump_r1 */ ++ *(short *)&insn[8] = 0xc0f4; ++ *(int *)&insn[10] = (jump_r1 - (ip + 8)) / 2; + } else { +- insn[2] = 0x07f10000; /* br %r1 */ ++ *(int *)&insn[8] = 0x07f10000; /* br %r1 */ + } +- insn[3] = (unsigned int) (val >> 32); +- insn[4] = (unsigned int) val; ++ *(long *)&insn[14] = val; + + write(ip, insn, sizeof(insn)); + info->plt_initialized = 1; +diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c +index 20f8e1868853f..a50f2ff1b00e8 100644 +--- a/arch/s390/kernel/nmi.c ++++ b/arch/s390/kernel/nmi.c +@@ -273,7 +273,14 @@ static int notrace s390_validate_registers(union mci mci, int umode) + /* Validate vector registers */ + union ctlreg0 cr0; + +- if (!mci.vr) { ++ /* ++ * The vector validity must only be checked if not running a ++ * KVM guest. For KVM guests the machine check is forwarded by ++ * KVM and it is the responsibility of the guest to take ++ * appropriate actions. The host vector or FPU values have been ++ * saved by KVM and will be restored by KVM. ++ */ ++ if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST)) { + /* + * Vector registers can't be restored. If the kernel + * currently uses vector registers the system is +@@ -316,11 +323,21 @@ static int notrace s390_validate_registers(union mci mci, int umode) + if (cr2.gse) { + if (!mci.gs) { + /* +- * Guarded storage register can't be restored and +- * the current processes uses guarded storage. +- * It has to be terminated. ++ * 2 cases: ++ * - machine check in kernel or userspace ++ * - machine check while running SIE (KVM guest) ++ * For kernel or userspace the userspace values of ++ * guarded storage control can not be recreated, the ++ * process must be terminated. ++ * For SIE the guest values of guarded storage can not ++ * be recreated. This is either due to a bug or due to ++ * GS being disabled in the guest. The guest will be ++ * notified by KVM code and the guests machine check ++ * handling must take care of this. The host values ++ * are saved by KVM and are not affected. + */ +- kill_task = 1; ++ if (!test_cpu_flag(CIF_MCCK_GUEST)) ++ kill_task = 1; + } else { + load_gs_cb((struct gs_cb *)mcesa->guarded_storage_save_area); + } +diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c +index 4a99154fe6514..cceb8ec707e4b 100644 +--- a/arch/s390/kernel/perf_cpum_cf.c ++++ b/arch/s390/kernel/perf_cpum_cf.c +@@ -687,8 +687,10 @@ static void cpumf_pmu_stop(struct perf_event *event, int flags) + false); + if (cfdiag_diffctr(cpuhw, event->hw.config_base)) + cfdiag_push_sample(event, cpuhw); +- } else ++ } else if (cpuhw->flags & PMU_F_RESERVED) { ++ /* Only update when PMU not hotplugged off */ + hw_perf_event_update(event); ++ } + hwc->state |= PERF_HES_UPTODATE; + } + } +diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c +index 67e5fff96ee06..ee67215a678a5 100644 +--- a/arch/s390/kernel/setup.c ++++ b/arch/s390/kernel/setup.c +@@ -633,14 +633,6 @@ static struct notifier_block kdump_mem_nb = { + + #endif + +-/* +- * Make sure that the area above identity mapping is protected +- */ +-static void __init reserve_above_ident_map(void) +-{ +- memblock_reserve(ident_map_size, ULONG_MAX); +-} +- + /* + * Reserve memory for kdump kernel to be loaded with kexec + */ +@@ -824,9 +816,6 @@ static void __init setup_memory(void) + storage_key_init_range(start, end); + + psw_set_key(PAGE_DEFAULT_KEY); +- +- /* Only cosmetics */ +- memblock_enforce_memory_limit(memblock_end_of_DRAM()); + } + + static void __init relocate_amode31_section(void) +@@ -1005,11 +994,11 @@ void __init setup_arch(char **cmdline_p) + setup_control_program_code(); + + /* Do some memory reservations *before* memory is added to memblock */ +- reserve_above_ident_map(); + reserve_kernel(); + reserve_initrd(); + reserve_certificate_list(); + reserve_mem_detect_info(); ++ memblock_set_current_limit(ident_map_size); + memblock_allow_resize(); + + /* Get information about *all* installed memory */ +diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c +index bcefc2173de45..12d28ff5281fa 100644 +--- a/arch/s390/kernel/traps.c ++++ b/arch/s390/kernel/traps.c +@@ -84,7 +84,7 @@ static void default_trap_handler(struct pt_regs *regs) + { + if (user_mode(regs)) { + report_user_fault(regs, SIGSEGV, 0); +- do_exit(SIGSEGV); ++ force_exit_sig(SIGSEGV); + } else + die(regs, "Unknown program exception"); + } +diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c +index 5a656c7b7a67a..f95ccbd396925 100644 +--- a/arch/s390/kernel/uv.c ++++ b/arch/s390/kernel/uv.c +@@ -212,7 +212,7 @@ again: + uaddr = __gmap_translate(gmap, gaddr); + if (IS_ERR_VALUE(uaddr)) + goto out; +- vma = find_vma(gmap->mm, uaddr); ++ vma = vma_lookup(gmap->mm, uaddr); + if (!vma) + goto out; + /* +diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile +index 6568de2367010..0dea82b87e54b 100644 +--- a/arch/s390/kernel/vdso64/Makefile ++++ b/arch/s390/kernel/vdso64/Makefile +@@ -8,8 +8,9 @@ ARCH_REL_TYPE_ABS += R_390_GOT|R_390_PLT + include $(srctree)/lib/vdso/Makefile + obj-vdso64 = vdso_user_wrapper.o note.o + obj-cvdso64 = vdso64_generic.o getcpu.o +-CFLAGS_REMOVE_getcpu.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) +-CFLAGS_REMOVE_vdso64_generic.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) ++VDSO_CFLAGS_REMOVE := -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) $(CC_FLAGS_CHECK_STACK) ++CFLAGS_REMOVE_getcpu.o = $(VDSO_CFLAGS_REMOVE) ++CFLAGS_REMOVE_vdso64_generic.o = $(VDSO_CFLAGS_REMOVE) + + # Build rules + +diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c +index 2245f4b8d3629..8ce03a5ca8634 100644 +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -2115,6 +2115,13 @@ int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu) + return test_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs); + } + ++int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu) ++{ ++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; ++ ++ return test_bit(IRQ_PEND_RESTART, &li->pending_irqs); ++} ++ + void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu) + { + struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; +diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c +index 1c97493d21e10..402597f9d0505 100644 +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -3447,7 +3447,7 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu) + { + /* do not poll with more than halt_poll_max_steal percent of steal time */ + if (S390_lowcore.avg_steal_timer * 100 / (TICK_USEC << 12) >= +- halt_poll_max_steal) { ++ READ_ONCE(halt_poll_max_steal)) { + vcpu->stat.halt_no_poll_steal++; + return true; + } +@@ -4642,10 +4642,15 @@ int kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu) + } + } + +- /* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */ ++ /* ++ * Set the VCPU to STOPPED and THEN clear the interrupt flag, ++ * now that the SIGP STOP and SIGP STOP AND STORE STATUS orders ++ * have been fully processed. This will ensure that the VCPU ++ * is kept BUSY if another VCPU is inquiring with SIGP SENSE. ++ */ ++ kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED); + kvm_s390_clear_stop_irq(vcpu); + +- kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED); + __disable_ibs_on_vcpu(vcpu); + + for (i = 0; i < online_vcpus; i++) { +@@ -4703,6 +4708,8 @@ static long kvm_s390_guest_sida_op(struct kvm_vcpu *vcpu, + return -EINVAL; + if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block)) + return -E2BIG; ++ if (!kvm_s390_pv_cpu_is_protected(vcpu)) ++ return -EINVAL; + + switch (mop->op) { + case KVM_S390_MEMOP_SIDA_READ: +diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h +index 52bc8fbaa60ac..1539dd981104f 100644 +--- a/arch/s390/kvm/kvm-s390.h ++++ b/arch/s390/kvm/kvm-s390.h +@@ -418,6 +418,7 @@ void kvm_s390_destroy_adapters(struct kvm *kvm); + int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu); + extern struct kvm_device_ops kvm_flic_ops; + int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu); ++int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu); + void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu); + int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu, + void __user *buf, int len); +diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c +index 53da4ceb16a3a..417154b314a64 100644 +--- a/arch/s390/kvm/priv.c ++++ b/arch/s390/kvm/priv.c +@@ -397,6 +397,8 @@ static int handle_sske(struct kvm_vcpu *vcpu) + mmap_read_unlock(current->mm); + if (rc == -EFAULT) + return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); ++ if (rc == -EAGAIN) ++ continue; + if (rc < 0) + return rc; + start += PAGE_SIZE; +diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c +index c8841f476e913..00d272d134c24 100644 +--- a/arch/s390/kvm/pv.c ++++ b/arch/s390/kvm/pv.c +@@ -16,18 +16,17 @@ + + int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc) + { +- int cc = 0; ++ int cc; + +- if (kvm_s390_pv_cpu_get_handle(vcpu)) { +- cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu), +- UVC_CMD_DESTROY_SEC_CPU, rc, rrc); ++ if (!kvm_s390_pv_cpu_get_handle(vcpu)) ++ return 0; ++ ++ cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu), UVC_CMD_DESTROY_SEC_CPU, rc, rrc); ++ ++ KVM_UV_EVENT(vcpu->kvm, 3, "PROTVIRT DESTROY VCPU %d: rc %x rrc %x", ++ vcpu->vcpu_id, *rc, *rrc); ++ WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", *rc, *rrc); + +- KVM_UV_EVENT(vcpu->kvm, 3, +- "PROTVIRT DESTROY VCPU %d: rc %x rrc %x", +- vcpu->vcpu_id, *rc, *rrc); +- WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x", +- *rc, *rrc); +- } + /* Intended memory leak for something that should never happen. */ + if (!cc) + free_pages(vcpu->arch.pv.stor_base, +@@ -196,7 +195,7 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) + uvcb.conf_base_stor_origin = (u64)kvm->arch.pv.stor_base; + uvcb.conf_virt_stor_origin = (u64)kvm->arch.pv.stor_var; + +- cc = uv_call(0, (u64)&uvcb); ++ cc = uv_call_sched(0, (u64)&uvcb); + *rc = uvcb.header.rc; + *rrc = uvcb.header.rrc; + KVM_UV_EVENT(kvm, 3, "PROTVIRT CREATE VM: handle %llx len %llx rc %x rrc %x", +diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c +index 683036c1c92a8..3dc921e853b6e 100644 +--- a/arch/s390/kvm/sigp.c ++++ b/arch/s390/kvm/sigp.c +@@ -288,6 +288,34 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code, + if (!dst_vcpu) + return SIGP_CC_NOT_OPERATIONAL; + ++ /* ++ * SIGP RESTART, SIGP STOP, and SIGP STOP AND STORE STATUS orders ++ * are processed asynchronously. Until the affected VCPU finishes ++ * its work and calls back into KVM to clear the (RESTART or STOP) ++ * interrupt, we need to return any new non-reset orders "busy". ++ * ++ * This is important because a single VCPU could issue: ++ * 1) SIGP STOP $DESTINATION ++ * 2) SIGP SENSE $DESTINATION ++ * ++ * If the SIGP SENSE would not be rejected as "busy", it could ++ * return an incorrect answer as to whether the VCPU is STOPPED ++ * or OPERATING. ++ */ ++ if (order_code != SIGP_INITIAL_CPU_RESET && ++ order_code != SIGP_CPU_RESET) { ++ /* ++ * Lockless check. Both SIGP STOP and SIGP (RE)START ++ * properly synchronize everything while processing ++ * their orders, while the guest cannot observe a ++ * difference when issuing other orders from two ++ * different VCPUs. ++ */ ++ if (kvm_s390_is_stop_irq_pending(dst_vcpu) || ++ kvm_s390_is_restart_irq_pending(dst_vcpu)) ++ return SIGP_CC_BUSY; ++ } ++ + switch (order_code) { + case SIGP_SENSE: + vcpu->stat.instruction_sigp_sense++; +diff --git a/arch/s390/lib/test_unwind.c b/arch/s390/lib/test_unwind.c +index ecf327d743a03..c0635cf787e31 100644 +--- a/arch/s390/lib/test_unwind.c ++++ b/arch/s390/lib/test_unwind.c +@@ -171,10 +171,11 @@ static noinline int unwindme_func4(struct unwindme *u) + } + + /* +- * trigger specification exception ++ * Trigger operation exception; use insn notation to bypass ++ * llvm's integrated assembler sanity checks. + */ + asm volatile( +- " mvcl %%r1,%%r1\n" ++ " .insn e,0x0000\n" /* illegal opcode */ + "0: nopr %%r7\n" + EX_TABLE(0b, 0b) + :); +diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c +index 4d3b33ce81c62..d63c0ccc5ccda 100644 +--- a/arch/s390/mm/gmap.c ++++ b/arch/s390/mm/gmap.c +@@ -672,6 +672,7 @@ EXPORT_SYMBOL_GPL(gmap_fault); + */ + void __gmap_zap(struct gmap *gmap, unsigned long gaddr) + { ++ struct vm_area_struct *vma; + unsigned long vmaddr; + spinlock_t *ptl; + pte_t *ptep; +@@ -681,11 +682,17 @@ void __gmap_zap(struct gmap *gmap, unsigned long gaddr) + gaddr >> PMD_SHIFT); + if (vmaddr) { + vmaddr |= gaddr & ~PMD_MASK; ++ ++ vma = vma_lookup(gmap->mm, vmaddr); ++ if (!vma || is_vm_hugetlb_page(vma)) ++ return; ++ + /* Get pointer to the page table entry */ + ptep = get_locked_pte(gmap->mm, vmaddr, &ptl); +- if (likely(ptep)) ++ if (likely(ptep)) { + ptep_zap_unused(gmap->mm, vmaddr, ptep, 0); +- pte_unmap_unlock(ptep, ptl); ++ pte_unmap_unlock(ptep, ptl); ++ } + } + } + EXPORT_SYMBOL_GPL(__gmap_zap); +diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c +index 781965f7210eb..91e478e09b54b 100644 +--- a/arch/s390/mm/pgalloc.c ++++ b/arch/s390/mm/pgalloc.c +@@ -244,13 +244,15 @@ void page_table_free(struct mm_struct *mm, unsigned long *table) + /* Free 2K page table fragment of a 4K page */ + bit = ((unsigned long) table & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)); + spin_lock_bh(&mm->context.lock); +- mask = atomic_xor_bits(&page->_refcount, 1U << (bit + 24)); ++ mask = atomic_xor_bits(&page->_refcount, 0x11U << (bit + 24)); + mask >>= 24; + if (mask & 3) + list_add(&page->lru, &mm->context.pgtable_list); + else + list_del(&page->lru); + spin_unlock_bh(&mm->context.lock); ++ mask = atomic_xor_bits(&page->_refcount, 0x10U << (bit + 24)); ++ mask >>= 24; + if (mask != 0) + return; + } else { +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index 034721a68d8fd..6ad634a27d5b9 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -429,22 +429,36 @@ static inline pmd_t pmdp_flush_lazy(struct mm_struct *mm, + } + + #ifdef CONFIG_PGSTE +-static pmd_t *pmd_alloc_map(struct mm_struct *mm, unsigned long addr) ++static int pmd_lookup(struct mm_struct *mm, unsigned long addr, pmd_t **pmdp) + { ++ struct vm_area_struct *vma; + pgd_t *pgd; + p4d_t *p4d; + pud_t *pud; +- pmd_t *pmd; ++ ++ /* We need a valid VMA, otherwise this is clearly a fault. */ ++ vma = vma_lookup(mm, addr); ++ if (!vma) ++ return -EFAULT; + + pgd = pgd_offset(mm, addr); +- p4d = p4d_alloc(mm, pgd, addr); +- if (!p4d) +- return NULL; +- pud = pud_alloc(mm, p4d, addr); +- if (!pud) +- return NULL; +- pmd = pmd_alloc(mm, pud, addr); +- return pmd; ++ if (!pgd_present(*pgd)) ++ return -ENOENT; ++ ++ p4d = p4d_offset(pgd, addr); ++ if (!p4d_present(*p4d)) ++ return -ENOENT; ++ ++ pud = pud_offset(p4d, addr); ++ if (!pud_present(*pud)) ++ return -ENOENT; ++ ++ /* Large PUDs are not supported yet. */ ++ if (pud_large(*pud)) ++ return -EFAULT; ++ ++ *pmdp = pmd_offset(pud, addr); ++ return 0; + } + #endif + +@@ -778,8 +792,7 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp; + pte_t *ptep; + +- pmdp = pmd_alloc_map(mm, addr); +- if (unlikely(!pmdp)) ++ if (pmd_lookup(mm, addr, &pmdp)) + return -EFAULT; + + ptl = pmd_lock(mm, pmdp); +@@ -881,8 +894,7 @@ int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr) + pte_t *ptep; + int cc = 0; + +- pmdp = pmd_alloc_map(mm, addr); +- if (unlikely(!pmdp)) ++ if (pmd_lookup(mm, addr, &pmdp)) + return -EFAULT; + + ptl = pmd_lock(mm, pmdp); +@@ -935,15 +947,24 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp; + pte_t *ptep; + +- pmdp = pmd_alloc_map(mm, addr); +- if (unlikely(!pmdp)) ++ /* ++ * If we don't have a PTE table and if there is no huge page mapped, ++ * the storage key is 0. ++ */ ++ *key = 0; ++ ++ switch (pmd_lookup(mm, addr, &pmdp)) { ++ case -ENOENT: ++ return 0; ++ case 0: ++ break; ++ default: + return -EFAULT; ++ } + + ptl = pmd_lock(mm, pmdp); + if (!pmd_present(*pmdp)) { +- /* Not yet mapped memory has a zero key */ + spin_unlock(ptl); +- *key = 0; + return 0; + } + +@@ -988,6 +1009,7 @@ EXPORT_SYMBOL(get_guest_storage_key); + int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, + unsigned long *oldpte, unsigned long *oldpgste) + { ++ struct vm_area_struct *vma; + unsigned long pgstev; + spinlock_t *ptl; + pgste_t pgste; +@@ -997,6 +1019,10 @@ int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, + WARN_ON_ONCE(orc > ESSA_MAX); + if (unlikely(orc > ESSA_MAX)) + return -EINVAL; ++ ++ vma = vma_lookup(mm, hva); ++ if (!vma || is_vm_hugetlb_page(vma)) ++ return -EFAULT; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; +@@ -1089,10 +1115,14 @@ EXPORT_SYMBOL(pgste_perform_essa); + int set_pgste_bits(struct mm_struct *mm, unsigned long hva, + unsigned long bits, unsigned long value) + { ++ struct vm_area_struct *vma; + spinlock_t *ptl; + pgste_t new; + pte_t *ptep; + ++ vma = vma_lookup(mm, hva); ++ if (!vma || is_vm_hugetlb_page(vma)) ++ return -EFAULT; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; +@@ -1117,9 +1147,13 @@ EXPORT_SYMBOL(set_pgste_bits); + */ + int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep) + { ++ struct vm_area_struct *vma; + spinlock_t *ptl; + pte_t *ptep; + ++ vma = vma_lookup(mm, hva); ++ if (!vma || is_vm_hugetlb_page(vma)) ++ return -EFAULT; + ptep = get_locked_pte(mm, hva, &ptl); + if (unlikely(!ptep)) + return -EFAULT; +diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug +index 958f790273ab9..10290e5c1f438 100644 +--- a/arch/sh/Kconfig.debug ++++ b/arch/sh/Kconfig.debug +@@ -54,6 +54,7 @@ config DUMP_CODE + + config DWARF_UNWINDER + bool "Enable the DWARF unwinder for stacktraces" ++ depends on DEBUG_KERNEL + select FRAME_POINTER + default n + help +diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig +index ba887f1351be6..cd5c58916c65a 100644 +--- a/arch/sh/configs/titan_defconfig ++++ b/arch/sh/configs/titan_defconfig +@@ -242,7 +242,6 @@ CONFIG_NFSD=y + CONFIG_NFSD_V3=y + CONFIG_SMB_FS=m + CONFIG_CIFS=m +-CONFIG_CIFS_WEAK_PW_HASH=y + CONFIG_PARTITION_ADVANCED=y + CONFIG_NLS_CODEPAGE_437=m + CONFIG_NLS_ASCII=m +diff --git a/arch/sh/include/asm/sfp-machine.h b/arch/sh/include/asm/sfp-machine.h +index cbc7cf8c97ce6..2d2423478b71d 100644 +--- a/arch/sh/include/asm/sfp-machine.h ++++ b/arch/sh/include/asm/sfp-machine.h +@@ -13,6 +13,14 @@ + #ifndef _SFP_MACHINE_H + #define _SFP_MACHINE_H + ++#ifdef __BIG_ENDIAN__ ++#define __BYTE_ORDER __BIG_ENDIAN ++#define __LITTLE_ENDIAN 0 ++#else ++#define __BYTE_ORDER __LITTLE_ENDIAN ++#define __BIG_ENDIAN 0 ++#endif ++ + #define _FP_W_TYPE_SIZE 32 + #define _FP_W_TYPE unsigned long + #define _FP_WS_TYPE signed long +diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c +index ae354a2931e7e..fd6db0ab19288 100644 +--- a/arch/sh/kernel/cpu/fpu.c ++++ b/arch/sh/kernel/cpu/fpu.c +@@ -62,18 +62,20 @@ void fpu_state_restore(struct pt_regs *regs) + } + + if (!tsk_used_math(tsk)) { +- local_irq_enable(); ++ int ret; + /* + * does a slab alloc which can sleep + */ +- if (init_fpu(tsk)) { ++ local_irq_enable(); ++ ret = init_fpu(tsk); ++ local_irq_disable(); ++ if (ret) { + /* + * ran out of memory! + */ +- do_group_exit(SIGKILL); ++ force_sig(SIGKILL); + return; + } +- local_irq_disable(); + } + + grab_fpu(regs); +diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c +index f8a2bec0f260b..1261dc7b84e8b 100644 +--- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c ++++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c +@@ -73,8 +73,9 @@ static void shx3_prepare_cpus(unsigned int max_cpus) + BUILD_BUG_ON(SMP_MSG_NR >= 8); + + for (i = 0; i < SMP_MSG_NR; i++) +- request_irq(104 + i, ipi_interrupt_handler, +- IRQF_PERCPU, "IPI", (void *)(long)i); ++ if (request_irq(104 + i, ipi_interrupt_handler, ++ IRQF_PERCPU, "IPI", (void *)(long)i)) ++ pr_err("Failed to request irq %d\n", i); + + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); +diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c +index e8be0eca0444a..615ba932c398e 100644 +--- a/arch/sh/math-emu/math.c ++++ b/arch/sh/math-emu/math.c +@@ -467,109 +467,6 @@ static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_reg + return id_sys(fregs, regs, code); + } + +-/** +- * denormal_to_double - Given denormalized float number, +- * store double float +- * +- * @fpu: Pointer to sh_fpu_soft structure +- * @n: Index to FP register +- */ +-static void denormal_to_double(struct sh_fpu_soft_struct *fpu, int n) +-{ +- unsigned long du, dl; +- unsigned long x = fpu->fpul; +- int exp = 1023 - 126; +- +- if (x != 0 && (x & 0x7f800000) == 0) { +- du = (x & 0x80000000); +- while ((x & 0x00800000) == 0) { +- x <<= 1; +- exp--; +- } +- x &= 0x007fffff; +- du |= (exp << 20) | (x >> 3); +- dl = x << 29; +- +- fpu->fp_regs[n] = du; +- fpu->fp_regs[n+1] = dl; +- } +-} +- +-/** +- * ieee_fpe_handler - Handle denormalized number exception +- * +- * @regs: Pointer to register structure +- * +- * Returns 1 when it's handled (should not cause exception). +- */ +-static int ieee_fpe_handler(struct pt_regs *regs) +-{ +- unsigned short insn = *(unsigned short *)regs->pc; +- unsigned short finsn; +- unsigned long nextpc; +- int nib[4] = { +- (insn >> 12) & 0xf, +- (insn >> 8) & 0xf, +- (insn >> 4) & 0xf, +- insn & 0xf}; +- +- if (nib[0] == 0xb || +- (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ +- regs->pr = regs->pc + 4; +- +- if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ +- nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); +- finsn = *(unsigned short *) (regs->pc + 2); +- } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */ +- if (regs->sr & 1) +- nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); +- else +- nextpc = regs->pc + 4; +- finsn = *(unsigned short *) (regs->pc + 2); +- } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */ +- if (regs->sr & 1) +- nextpc = regs->pc + 4; +- else +- nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); +- finsn = *(unsigned short *) (regs->pc + 2); +- } else if (nib[0] == 0x4 && nib[3] == 0xb && +- (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */ +- nextpc = regs->regs[nib[1]]; +- finsn = *(unsigned short *) (regs->pc + 2); +- } else if (nib[0] == 0x0 && nib[3] == 0x3 && +- (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */ +- nextpc = regs->pc + 4 + regs->regs[nib[1]]; +- finsn = *(unsigned short *) (regs->pc + 2); +- } else if (insn == 0x000b) { /* rts */ +- nextpc = regs->pr; +- finsn = *(unsigned short *) (regs->pc + 2); +- } else { +- nextpc = regs->pc + 2; +- finsn = insn; +- } +- +- if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ +- struct task_struct *tsk = current; +- +- if ((tsk->thread.xstate->softfpu.fpscr & (1 << 17))) { +- /* FPU error */ +- denormal_to_double (&tsk->thread.xstate->softfpu, +- (finsn >> 8) & 0xf); +- tsk->thread.xstate->softfpu.fpscr &= +- ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); +- task_thread_info(tsk)->status |= TS_USEDFPU; +- } else { +- force_sig_fault(SIGFPE, FPE_FLTINV, +- (void __user *)regs->pc); +- } +- +- regs->pc = nextpc; +- return 1; +- } +- +- return 0; +-} +- + /** + * fpu_init - Initialize FPU registers + * @fpu: Pointer to software emulated FPU registers. +diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile +index 849236d4eca48..45e5c76d449ea 100644 +--- a/arch/sparc/boot/Makefile ++++ b/arch/sparc/boot/Makefile +@@ -22,7 +22,7 @@ ifeq ($(CONFIG_SPARC64),y) + + # Actual linking + +-$(obj)/zImage: $(obj)/image ++$(obj)/zImage: $(obj)/image FORCE + $(call if_changed,gzip) + @echo ' kernel: $@ is ready' + +@@ -31,7 +31,7 @@ $(obj)/vmlinux.aout: vmlinux FORCE + @echo ' kernel: $@ is ready' + else + +-$(obj)/zImage: $(obj)/image ++$(obj)/zImage: $(obj)/image FORCE + $(call if_changed,strip) + @echo ' kernel: $@ is ready' + +@@ -44,7 +44,7 @@ OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment + $(obj)/image.bin: $(obj)/image FORCE + $(call if_changed,objcopy) + +-$(obj)/image.gz: $(obj)/image.bin ++$(obj)/image.gz: $(obj)/image.bin FORCE + $(call if_changed,gzip) + + UIMAGE_LOADADDR = $(CONFIG_UBOOT_LOAD_ADDR) +@@ -56,7 +56,7 @@ quiet_cmd_uimage.o = UIMAGE.O $@ + -r -b binary $@ -o $@.o + + targets += uImage +-$(obj)/uImage: $(obj)/image.gz ++$(obj)/uImage: $(obj)/image.gz FORCE + $(call if_changed,uimage) + $(call if_changed,uimage.o) + @echo ' Image $@ is ready' +diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c +index 02f3ad55dfe31..ffab16369beac 100644 +--- a/arch/sparc/kernel/signal_32.c ++++ b/arch/sparc/kernel/signal_32.c +@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *ksig, struct pt_regs *regs, + get_sigframe(ksig, regs, sigframe_size); + + if (invalid_frame_pointer(sf, sigframe_size)) { +- do_exit(SIGILL); ++ force_exit_sig(SIGILL); + return -EINVAL; + } + +@@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs, + sf = (struct rt_signal_frame __user *) + get_sigframe(ksig, regs, sigframe_size); + if (invalid_frame_pointer(sf, sigframe_size)) { +- do_exit(SIGILL); ++ force_exit_sig(SIGILL); + return -EINVAL; + } + +diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c +index 69a6ba6e92937..8f20862ccc83e 100644 +--- a/arch/sparc/kernel/windows.c ++++ b/arch/sparc/kernel/windows.c +@@ -121,8 +121,10 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who) + + if ((sp & 7) || + copy_to_user((char __user *) sp, &tp->reg_window[window], +- sizeof(struct reg_window32))) +- do_exit(SIGILL); ++ sizeof(struct reg_window32))) { ++ force_exit_sig(SIGILL); ++ return; ++ } + } + tp->w_saved = 0; + } +diff --git a/arch/um/.gitignore b/arch/um/.gitignore +index 6323e5571887e..d69ea5b562cee 100644 +--- a/arch/um/.gitignore ++++ b/arch/um/.gitignore +@@ -2,3 +2,4 @@ + kernel/config.c + kernel/config.tmp + kernel/vmlinux.lds ++kernel/capflags.c +diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c +index c080666330234..0ab58016db22f 100644 +--- a/arch/um/drivers/virt-pci.c ++++ b/arch/um/drivers/virt-pci.c +@@ -181,15 +181,15 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, + /* buf->data is maximum size - we may only use parts of it */ + struct um_pci_message_buffer *buf; + u8 *data; +- unsigned long ret = ~0ULL; ++ unsigned long ret = ULONG_MAX; + + if (!dev) +- return ~0ULL; ++ return ULONG_MAX; + + buf = get_cpu_var(um_pci_msg_bufs); + data = buf->data; + +- memset(data, 0xff, sizeof(data)); ++ memset(buf->data, 0xff, sizeof(buf->data)); + + switch (size) { + case 1: +@@ -304,7 +304,7 @@ static unsigned long um_pci_bar_read(void *priv, unsigned int offset, + /* buf->data is maximum size - we may only use parts of it */ + struct um_pci_message_buffer *buf; + u8 *data; +- unsigned long ret = ~0ULL; ++ unsigned long ret = ULONG_MAX; + + buf = get_cpu_var(um_pci_msg_bufs); + data = buf->data; +diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c +index d51e445df7976..7755cb4ff9fc6 100644 +--- a/arch/um/drivers/virtio_uml.c ++++ b/arch/um/drivers/virtio_uml.c +@@ -1090,6 +1090,8 @@ static void virtio_uml_release_dev(struct device *d) + container_of(d, struct virtio_device, dev); + struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev); + ++ time_travel_propagate_time(); ++ + /* might not have been opened due to not negotiating the feature */ + if (vu_dev->req_fd >= 0) { + um_free_irq(vu_dev->irq, vu_dev); +@@ -1136,6 +1138,8 @@ static int virtio_uml_probe(struct platform_device *pdev) + vu_dev->pdev = pdev; + vu_dev->req_fd = -1; + ++ time_travel_propagate_time(); ++ + do { + rc = os_connect_socket(pdata->socket_path); + } while (rc == -EINTR); +diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h +index 56fc2b8f2dd01..e79b2ab6f40c8 100644 +--- a/arch/um/include/asm/delay.h ++++ b/arch/um/include/asm/delay.h +@@ -14,7 +14,7 @@ static inline void um_ndelay(unsigned long nsecs) + ndelay(nsecs); + } + #undef ndelay +-#define ndelay um_ndelay ++#define ndelay(n) um_ndelay(n) + + static inline void um_udelay(unsigned long usecs) + { +@@ -26,5 +26,5 @@ static inline void um_udelay(unsigned long usecs) + udelay(usecs); + } + #undef udelay +-#define udelay um_udelay ++#define udelay(n) um_udelay(n) + #endif /* __UM_DELAY_H */ +diff --git a/arch/um/include/asm/irqflags.h b/arch/um/include/asm/irqflags.h +index dab5744e9253d..1e69ef5bc35e0 100644 +--- a/arch/um/include/asm/irqflags.h ++++ b/arch/um/include/asm/irqflags.h +@@ -3,7 +3,7 @@ + #define __UM_IRQFLAGS_H + + extern int signals_enabled; +-int set_signals(int enable); ++int um_set_signals(int enable); + void block_signals(void); + void unblock_signals(void); + +@@ -16,7 +16,7 @@ static inline unsigned long arch_local_save_flags(void) + #define arch_local_irq_restore arch_local_irq_restore + static inline void arch_local_irq_restore(unsigned long flags) + { +- set_signals(flags); ++ um_set_signals(flags); + } + + #define arch_local_irq_enable arch_local_irq_enable +diff --git a/arch/um/include/shared/longjmp.h b/arch/um/include/shared/longjmp.h +index bdb2869b72b31..8863319039f3d 100644 +--- a/arch/um/include/shared/longjmp.h ++++ b/arch/um/include/shared/longjmp.h +@@ -18,7 +18,7 @@ extern void longjmp(jmp_buf, int); + enable = *(volatile int *)&signals_enabled; \ + n = setjmp(*buf); \ + if(n != 0) \ +- set_signals_trace(enable); \ ++ um_set_signals_trace(enable); \ + n; }) + + #endif +diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h +index 96d400387c93e..03ffbdddcc480 100644 +--- a/arch/um/include/shared/os.h ++++ b/arch/um/include/shared/os.h +@@ -238,8 +238,8 @@ extern void send_sigio_to_self(void); + extern int change_sig(int signal, int on); + extern void block_signals(void); + extern void unblock_signals(void); +-extern int set_signals(int enable); +-extern int set_signals_trace(int enable); ++extern int um_set_signals(int enable); ++extern int um_set_signals_trace(int enable); + extern int os_is_signal_stack(void); + extern void deliver_alarm(void); + extern void register_pm_wake_signal(void); +diff --git a/arch/um/include/shared/registers.h b/arch/um/include/shared/registers.h +index 0c50fa6e8a55b..fbb709a222839 100644 +--- a/arch/um/include/shared/registers.h ++++ b/arch/um/include/shared/registers.h +@@ -16,8 +16,8 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs); + extern int save_fpx_registers(int pid, unsigned long *fp_regs); + extern int restore_fpx_registers(int pid, unsigned long *fp_regs); + extern int save_registers(int pid, struct uml_pt_regs *regs); +-extern int restore_registers(int pid, struct uml_pt_regs *regs); +-extern int init_registers(int pid); ++extern int restore_pid_registers(int pid, struct uml_pt_regs *regs); ++extern int init_pid_registers(int pid); + extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs); + extern unsigned long get_thread_reg(int reg, jmp_buf *buf); + extern int get_fp_registers(int pid, unsigned long *regs); +diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c +index b1e5634398d09..3a85bde3e1734 100644 +--- a/arch/um/kernel/ksyms.c ++++ b/arch/um/kernel/ksyms.c +@@ -6,7 +6,7 @@ + #include <linux/module.h> + #include <os.h> + +-EXPORT_SYMBOL(set_signals); ++EXPORT_SYMBOL(um_set_signals); + EXPORT_SYMBOL(signals_enabled); + + EXPORT_SYMBOL(os_stat_fd); +diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c +index 3198c47673879..c32efb09db214 100644 +--- a/arch/um/kernel/trap.c ++++ b/arch/um/kernel/trap.c +@@ -158,7 +158,7 @@ static void bad_segv(struct faultinfo fi, unsigned long ip) + + void fatal_sigsegv(void) + { +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + do_signal(¤t->thread.regs); + /* + * This is to tell gcc that we're not returning - do_signal +diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c +index 2d9270508e156..b123955be7acc 100644 +--- a/arch/um/os-Linux/registers.c ++++ b/arch/um/os-Linux/registers.c +@@ -21,7 +21,7 @@ int save_registers(int pid, struct uml_pt_regs *regs) + return 0; + } + +-int restore_registers(int pid, struct uml_pt_regs *regs) ++int restore_pid_registers(int pid, struct uml_pt_regs *regs) + { + int err; + +@@ -36,7 +36,7 @@ int restore_registers(int pid, struct uml_pt_regs *regs) + static unsigned long exec_regs[MAX_REG_NR]; + static unsigned long exec_fp_regs[FP_SIZE]; + +-int init_registers(int pid) ++int init_pid_registers(int pid) + { + int err; + +diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c +index 6597ea1986ffa..9e71794839e87 100644 +--- a/arch/um/os-Linux/sigio.c ++++ b/arch/um/os-Linux/sigio.c +@@ -132,7 +132,7 @@ static void update_thread(void) + int n; + char c; + +- flags = set_signals_trace(0); ++ flags = um_set_signals_trace(0); + CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c))); + if (n != sizeof(c)) { + printk(UM_KERN_ERR "update_thread : write failed, err = %d\n", +@@ -147,7 +147,7 @@ static void update_thread(void) + goto fail; + } + +- set_signals_trace(flags); ++ um_set_signals_trace(flags); + return; + fail: + /* Critical section start */ +@@ -161,7 +161,7 @@ static void update_thread(void) + close(write_sigio_fds[0]); + close(write_sigio_fds[1]); + /* Critical section end */ +- set_signals_trace(flags); ++ um_set_signals_trace(flags); + } + + int __add_sigio_fd(int fd) +diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c +index 6cf098c23a394..24a403a70a020 100644 +--- a/arch/um/os-Linux/signal.c ++++ b/arch/um/os-Linux/signal.c +@@ -94,7 +94,7 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) + + sig_handler_common(sig, si, mc); + +- set_signals_trace(enabled); ++ um_set_signals_trace(enabled); + } + + static void timer_real_alarm_handler(mcontext_t *mc) +@@ -126,7 +126,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) + + signals_active &= ~SIGALRM_MASK; + +- set_signals_trace(enabled); ++ um_set_signals_trace(enabled); + } + + void deliver_alarm(void) { +@@ -348,7 +348,7 @@ void unblock_signals(void) + } + } + +-int set_signals(int enable) ++int um_set_signals(int enable) + { + int ret; + if (signals_enabled == enable) +@@ -362,7 +362,7 @@ int set_signals(int enable) + return ret; + } + +-int set_signals_trace(int enable) ++int um_set_signals_trace(int enable) + { + int ret; + if (signals_enabled == enable) +diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c +index 8a72c99994eb1..e3ee4db58b40d 100644 +--- a/arch/um/os-Linux/start_up.c ++++ b/arch/um/os-Linux/start_up.c +@@ -368,7 +368,7 @@ void __init os_early_checks(void) + check_tmpexec(); + + pid = start_ptraced_child(); +- if (init_registers(pid)) ++ if (init_pid_registers(pid)) + fatal("Failed to initialize default registers"); + stop_ptraced_child(pid, 1, 1); + } +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index d9830e7e1060f..1f96809606ac5 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1256,7 +1256,8 @@ config TOSHIBA + + config I8K + tristate "Dell i8k legacy laptop support" +- select HWMON ++ depends on HWMON ++ depends on PROC_FS + select SENSORS_DELL_SMM + help + This option enables legacy /proc/i8k userspace interface in hwmon +@@ -1518,6 +1519,7 @@ config AMD_MEM_ENCRYPT + select ARCH_HAS_FORCE_DMA_UNENCRYPTED + select INSTRUCTION_DECODER + select ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS ++ select ARCH_HAS_CC_PLATFORM + help + Say yes to enable support for the encryption of system memory. + This requires an AMD processor that supports Secure Memory +@@ -1917,6 +1919,7 @@ config EFI + depends on ACPI + select UCS2_STRING + select EFI_RUNTIME_WRAPPERS ++ select ARCH_USE_MEMREMAP_PROT + help + This enables the kernel to use EFI runtime services that are + available (such as the EFI variable services). +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index 431bf7f846c3c..e118136460518 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -28,7 +28,11 @@ KCOV_INSTRUMENT := n + targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \ + vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4 vmlinux.bin.zst + +-KBUILD_CFLAGS := -m$(BITS) -O2 ++# CLANG_FLAGS must come before any cc-disable-warning or cc-option calls in ++# case of cross compiling, as it has the '--target=' flag, which is needed to ++# avoid errors with '-march=i386', and future flags may depend on the target to ++# be valid. ++KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS) + KBUILD_CFLAGS += -fno-strict-aliasing -fPIE + KBUILD_CFLAGS += -Wundef + KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING +@@ -47,7 +51,6 @@ KBUILD_CFLAGS += -D__DISABLE_EXPORTS + # Disable relocation relaxation in case the link is not PIE. + KBUILD_CFLAGS += $(call as-option,-Wa$(comma)-mrelax-relocations=no) + KBUILD_CFLAGS += -include $(srctree)/include/linux/hidden.h +-KBUILD_CFLAGS += $(CLANG_FLAGS) + + # sev.c indirectly inludes inat-table.h which is generated during + # compilation and stored in $(objtree). Add the directory to the includes so +diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig +index e81885384f604..99398cbdae434 100644 +--- a/arch/x86/configs/i386_defconfig ++++ b/arch/x86/configs/i386_defconfig +@@ -262,3 +262,4 @@ CONFIG_BLK_DEV_IO_TRACE=y + CONFIG_PROVIDE_OHCI1394_DMA_INIT=y + CONFIG_EARLY_PRINTK_DBGP=y + CONFIG_DEBUG_BOOT_PARAMS=y ++CONFIG_KALLSYMS_ALL=y +diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig +index e8a7a0af2bdaa..d7298b104a456 100644 +--- a/arch/x86/configs/x86_64_defconfig ++++ b/arch/x86/configs/x86_64_defconfig +@@ -258,3 +258,4 @@ CONFIG_BLK_DEV_IO_TRACE=y + CONFIG_PROVIDE_OHCI1394_DMA_INIT=y + CONFIG_EARLY_PRINTK_DBGP=y + CONFIG_DEBUG_BOOT_PARAMS=y ++CONFIG_KALLSYMS_ALL=y +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index 0fc961bef299c..41901ba9d3a2c 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -866,7 +866,7 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt) + req = &subreq; + + err = skcipher_walk_virt(&walk, req, false); +- if (err) ++ if (!walk.nbytes) + return err; + } else { + tail = 0; +@@ -1107,7 +1107,7 @@ static struct aead_alg aesni_aeads[] = { { + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct aesni_rfc4106_gcm_ctx), +- .cra_alignmask = AESNI_ALIGN - 1, ++ .cra_alignmask = 0, + .cra_module = THIS_MODULE, + }, + }, { +@@ -1124,7 +1124,7 @@ static struct aead_alg aesni_aeads[] = { { + .cra_flags = CRYPTO_ALG_INTERNAL, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct generic_gcmaes_ctx), +- .cra_alignmask = AESNI_ALIGN - 1, ++ .cra_alignmask = 0, + .cra_module = THIS_MODULE, + }, + } }; +diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S +index e38a4cf795d96..97b1f84bb53f8 100644 +--- a/arch/x86/entry/entry_64.S ++++ b/arch/x86/entry/entry_64.S +@@ -574,6 +574,10 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) + ud2 + 1: + #endif ++#ifdef CONFIG_XEN_PV ++ ALTERNATIVE "", "jmp xenpv_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV ++#endif ++ + POP_REGS pop_rdi=0 + + /* +@@ -890,6 +894,7 @@ SYM_CODE_START_LOCAL(paranoid_entry) + .Lparanoid_entry_checkgs: + /* EBX = 1 -> kernel GSBASE active, no restore required */ + movl $1, %ebx ++ + /* + * The kernel-enforced convention is a negative GSBASE indicates + * a kernel value. No SWAPGS needed on entry and exit. +@@ -897,21 +902,14 @@ SYM_CODE_START_LOCAL(paranoid_entry) + movl $MSR_GS_BASE, %ecx + rdmsr + testl %edx, %edx +- jns .Lparanoid_entry_swapgs +- ret ++ js .Lparanoid_kernel_gsbase + +-.Lparanoid_entry_swapgs: ++ /* EBX = 0 -> SWAPGS required on exit */ ++ xorl %ebx, %ebx + swapgs ++.Lparanoid_kernel_gsbase: + +- /* +- * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an +- * unconditional CR3 write, even in the PTI case. So do an lfence +- * to prevent GS speculation, regardless of whether PTI is enabled. +- */ + FENCE_SWAPGS_KERNEL_ENTRY +- +- /* EBX = 0 -> SWAPGS required on exit */ +- xorl %ebx, %ebx + ret + SYM_CODE_END(paranoid_entry) + +@@ -993,11 +991,6 @@ SYM_CODE_START_LOCAL(error_entry) + pushq %r12 + ret + +-.Lerror_entry_done_lfence: +- FENCE_SWAPGS_KERNEL_ENTRY +-.Lerror_entry_done: +- ret +- + /* + * There are two places in the kernel that can potentially fault with + * usergs. Handle them here. B stepping K8s sometimes report a +@@ -1020,8 +1013,14 @@ SYM_CODE_START_LOCAL(error_entry) + * .Lgs_change's error handler with kernel gsbase. + */ + SWAPGS +- FENCE_SWAPGS_USER_ENTRY +- jmp .Lerror_entry_done ++ ++ /* ++ * Issue an LFENCE to prevent GS speculation, regardless of whether it is a ++ * kernel or user gsbase. ++ */ ++.Lerror_entry_done_lfence: ++ FENCE_SWAPGS_KERNEL_ENTRY ++ ret + + .Lbstep_iret: + /* Fix truncated RIP */ +diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c +index 1b40b92970831..fd2ee9408e914 100644 +--- a/arch/x86/entry/vsyscall/vsyscall_64.c ++++ b/arch/x86/entry/vsyscall/vsyscall_64.c +@@ -226,7 +226,8 @@ bool emulate_vsyscall(unsigned long error_code, + if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { + warn_bad_vsyscall(KERN_DEBUG, regs, + "seccomp tried to change syscall nr or ip"); +- do_exit(SIGSYS); ++ force_exit_sig(SIGSYS); ++ return true; + } + regs->orig_ax = -1; + if (tmp) +diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c +index 6dfa8ddaa60f7..81d5e0a1f48cd 100644 +--- a/arch/x86/events/core.c ++++ b/arch/x86/events/core.c +@@ -2762,10 +2762,11 @@ static bool perf_hw_regs(struct pt_regs *regs) + void + perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct unwind_state state; + unsigned long addr; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* TODO: We don't support guest os callchain now */ + return; + } +@@ -2865,10 +2866,11 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent + void + perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + struct stack_frame frame; + const struct stack_frame __user *fp; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { ++ if (guest_cbs && guest_cbs->is_in_guest()) { + /* TODO: We don't support guest os callchain now */ + return; + } +@@ -2945,18 +2947,21 @@ static unsigned long code_segment_base(struct pt_regs *regs) + + unsigned long perf_instruction_pointer(struct pt_regs *regs) + { +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) +- return perf_guest_cbs->get_guest_ip(); ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); ++ ++ if (guest_cbs && guest_cbs->is_in_guest()) ++ return guest_cbs->get_guest_ip(); + + return regs->ip + code_segment_base(regs); + } + + unsigned long perf_misc_flags(struct pt_regs *regs) + { ++ struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs(); + int misc = 0; + +- if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { +- if (perf_guest_cbs->is_user_mode()) ++ if (guest_cbs && guest_cbs->is_in_guest()) { ++ if (guest_cbs->is_user_mode()) + misc |= PERF_RECORD_MISC_GUEST_USER; + else + misc |= PERF_RECORD_MISC_GUEST_KERNEL; +diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c +index 9a044438072ba..97ede6fb15f26 100644 +--- a/arch/x86/events/intel/core.c ++++ b/arch/x86/events/intel/core.c +@@ -243,7 +243,8 @@ static struct extra_reg intel_skl_extra_regs[] __read_mostly = { + + static struct event_constraint intel_icl_event_constraints[] = { + FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ +- FIXED_EVENT_CONSTRAINT(0x01c0, 0), /* INST_RETIRED.PREC_DIST */ ++ FIXED_EVENT_CONSTRAINT(0x01c0, 0), /* old INST_RETIRED.PREC_DIST */ ++ FIXED_EVENT_CONSTRAINT(0x0100, 0), /* INST_RETIRED.PREC_DIST */ + FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ + FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ + FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */ +@@ -288,7 +289,7 @@ static struct extra_reg intel_spr_extra_regs[] __read_mostly = { + + static struct event_constraint intel_spr_event_constraints[] = { + FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ +- FIXED_EVENT_CONSTRAINT(0x01c0, 0), /* INST_RETIRED.PREC_DIST */ ++ FIXED_EVENT_CONSTRAINT(0x0100, 0), /* INST_RETIRED.PREC_DIST */ + FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ + FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */ + FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */ +@@ -2787,6 +2788,7 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status) + { + struct perf_sample_data data; + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); ++ struct perf_guest_info_callbacks *guest_cbs; + int bit; + int handled = 0; + u64 intel_ctrl = hybrid(cpuc->pmu, intel_ctrl); +@@ -2853,9 +2855,11 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status) + */ + if (__test_and_clear_bit(GLOBAL_STATUS_TRACE_TOPAPMI_BIT, (unsigned long *)&status)) { + handled++; +- if (unlikely(perf_guest_cbs && perf_guest_cbs->is_in_guest() && +- perf_guest_cbs->handle_intel_pt_intr)) +- perf_guest_cbs->handle_intel_pt_intr(); ++ ++ guest_cbs = perf_get_guest_cbs(); ++ if (unlikely(guest_cbs && guest_cbs->is_in_guest() && ++ guest_cbs->handle_intel_pt_intr)) ++ guest_cbs->handle_intel_pt_intr(); + else + intel_pt_interrupt(); + } +@@ -2998,8 +3002,10 @@ intel_vlbr_constraints(struct perf_event *event) + { + struct event_constraint *c = &vlbr_constraint; + +- if (unlikely(constraint_match(c, event->hw.config))) ++ if (unlikely(constraint_match(c, event->hw.config))) { ++ event->hw.flags |= c->flags; + return c; ++ } + + return NULL; + } +@@ -4648,6 +4654,19 @@ static __initconst const struct x86_pmu intel_pmu = { + .lbr_read = intel_pmu_lbr_read_64, + .lbr_save = intel_pmu_lbr_save, + .lbr_restore = intel_pmu_lbr_restore, ++ ++ /* ++ * SMM has access to all 4 rings and while traditionally SMM code only ++ * ran in CPL0, 2021-era firmware is starting to make use of CPL3 in SMM. ++ * ++ * Since the EVENTSEL.{USR,OS} CPL filtering makes no distinction ++ * between SMM or not, this results in what should be pure userspace ++ * counters including SMM data. ++ * ++ * This is a clear privilege issue, therefore globally disable ++ * counting SMM by default. ++ */ ++ .attr_freeze_on_smi = 1, + }; + + static __init void intel_clovertown_quirk(void) +@@ -6181,6 +6200,19 @@ __init int intel_pmu_init(void) + pmu->num_counters = x86_pmu.num_counters; + pmu->num_counters_fixed = x86_pmu.num_counters_fixed; + } ++ ++ /* ++ * Quirk: For some Alder Lake machine, when all E-cores are disabled in ++ * a BIOS, the leaf 0xA will enumerate all counters of P-cores. However, ++ * the X86_FEATURE_HYBRID_CPU is still set. The above codes will ++ * mistakenly add extra counters for P-cores. Correct the number of ++ * counters here. ++ */ ++ if ((pmu->num_counters > 8) || (pmu->num_counters_fixed > 4)) { ++ pmu->num_counters = x86_pmu.num_counters; ++ pmu->num_counters_fixed = x86_pmu.num_counters_fixed; ++ } ++ + pmu->max_pebs_events = min_t(unsigned, MAX_PEBS_EVENTS, pmu->num_counters); + pmu->unconstrained = (struct event_constraint) + __EVENT_CONSTRAINT(0, (1ULL << pmu->num_counters) - 1, +diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c +index 8647713276a73..4dbb55a43dad2 100644 +--- a/arch/x86/events/intel/ds.c ++++ b/arch/x86/events/intel/ds.c +@@ -923,7 +923,8 @@ struct event_constraint intel_skl_pebs_event_constraints[] = { + }; + + struct event_constraint intel_icl_pebs_event_constraints[] = { +- INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ ++ INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x100000000ULL), /* old INST_RETIRED.PREC_DIST */ ++ INTEL_FLAGS_UEVENT_CONSTRAINT(0x0100, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ + INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), /* SLOTS */ + + INTEL_PLD_CONSTRAINT(0x1cd, 0xff), /* MEM_TRANS_RETIRED.LOAD_LATENCY */ +@@ -943,7 +944,7 @@ struct event_constraint intel_icl_pebs_event_constraints[] = { + }; + + struct event_constraint intel_spr_pebs_event_constraints[] = { +- INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x100000000ULL), ++ INTEL_FLAGS_UEVENT_CONSTRAINT(0x100, 0x100000000ULL), /* INST_RETIRED.PREC_DIST */ + INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), + + INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xfe), +diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c +index 9e6d6eaeb4cb6..f455dd93f9219 100644 +--- a/arch/x86/events/intel/lbr.c ++++ b/arch/x86/events/intel/lbr.c +@@ -1734,6 +1734,9 @@ static bool is_arch_lbr_xsave_available(void) + * Check the LBR state with the corresponding software structure. + * Disable LBR XSAVES support if the size doesn't match. + */ ++ if (xfeature_size(XFEATURE_LBR) == 0) ++ return false; ++ + if (WARN_ON(xfeature_size(XFEATURE_LBR) != get_lbr_state_size())) + return false; + +diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c +index 7f406c14715fd..2d33bba9a1440 100644 +--- a/arch/x86/events/intel/pt.c ++++ b/arch/x86/events/intel/pt.c +@@ -897,8 +897,9 @@ static void pt_handle_status(struct pt *pt) + * means we are already losing data; need to let the decoder + * know. + */ +- if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || +- buf->output_off == pt_buffer_region_size(buf)) { ++ if (!buf->single && ++ (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) || ++ buf->output_off == pt_buffer_region_size(buf))) { + perf_aux_output_flag(&pt->handle, + PERF_AUX_FLAG_TRUNCATED); + advance++; +diff --git a/arch/x86/events/intel/uncore_discovery.h b/arch/x86/events/intel/uncore_discovery.h +index 7280c8a3c8310..6d735611c281c 100644 +--- a/arch/x86/events/intel/uncore_discovery.h ++++ b/arch/x86/events/intel/uncore_discovery.h +@@ -30,7 +30,7 @@ + + + #define uncore_discovery_invalid_unit(unit) \ +- (!unit.table1 || !unit.ctl || !unit.table3 || \ ++ (!unit.table1 || !unit.ctl || \ + unit.table1 == -1ULL || unit.ctl == -1ULL || \ + unit.table3 == -1ULL) + +diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c +index 5ddc0f30db6fc..ed869443efb21 100644 +--- a/arch/x86/events/intel/uncore_snbep.c ++++ b/arch/x86/events/intel/uncore_snbep.c +@@ -452,7 +452,7 @@ + #define ICX_M3UPI_PCI_PMON_BOX_CTL 0xa0 + + /* ICX IMC */ +-#define ICX_NUMBER_IMC_CHN 2 ++#define ICX_NUMBER_IMC_CHN 3 + #define ICX_IMC_MEM_STRIDE 0x4 + + /* SPR */ +@@ -3608,6 +3608,9 @@ static int skx_cha_hw_config(struct intel_uncore_box *box, struct perf_event *ev + struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; + struct extra_reg *er; + int idx = 0; ++ /* Any of the CHA events may be filtered by Thread/Core-ID.*/ ++ if (event->hw.config & SNBEP_CBO_PMON_CTL_TID_EN) ++ idx = SKX_CHA_MSR_PMON_BOX_FILTER_TID; + + for (er = skx_uncore_cha_extra_regs; er->msr; er++) { + if (er->event != (event->hw.config & er->config_mask)) +@@ -3675,6 +3678,7 @@ static struct event_constraint skx_uncore_iio_constraints[] = { + UNCORE_EVENT_CONSTRAINT(0xc0, 0xc), + UNCORE_EVENT_CONSTRAINT(0xc5, 0xc), + UNCORE_EVENT_CONSTRAINT(0xd4, 0xc), ++ UNCORE_EVENT_CONSTRAINT(0xd5, 0xc), + EVENT_CONSTRAINT_END + }; + +@@ -4525,6 +4529,13 @@ static void snr_iio_cleanup_mapping(struct intel_uncore_type *type) + pmu_iio_cleanup_mapping(type, &snr_iio_mapping_group); + } + ++static struct event_constraint snr_uncore_iio_constraints[] = { ++ UNCORE_EVENT_CONSTRAINT(0x83, 0x3), ++ UNCORE_EVENT_CONSTRAINT(0xc0, 0xc), ++ UNCORE_EVENT_CONSTRAINT(0xd5, 0xc), ++ EVENT_CONSTRAINT_END ++}; ++ + static struct intel_uncore_type snr_uncore_iio = { + .name = "iio", + .num_counters = 4, +@@ -4536,6 +4547,7 @@ static struct intel_uncore_type snr_uncore_iio = { + .event_mask_ext = SNR_IIO_PMON_RAW_EVENT_MASK_EXT, + .box_ctl = SNR_IIO_MSR_PMON_BOX_CTL, + .msr_offset = SNR_IIO_MSR_OFFSET, ++ .constraints = snr_uncore_iio_constraints, + .ops = &ivbep_uncore_msr_ops, + .format_group = &snr_uncore_iio_format_group, + .attr_update = snr_iio_attr_update, +@@ -5076,8 +5088,10 @@ static struct event_constraint icx_uncore_iio_constraints[] = { + UNCORE_EVENT_CONSTRAINT(0x02, 0x3), + UNCORE_EVENT_CONSTRAINT(0x03, 0x3), + UNCORE_EVENT_CONSTRAINT(0x83, 0x3), ++ UNCORE_EVENT_CONSTRAINT(0x88, 0xc), + UNCORE_EVENT_CONSTRAINT(0xc0, 0xc), + UNCORE_EVENT_CONSTRAINT(0xc5, 0xc), ++ UNCORE_EVENT_CONSTRAINT(0xd5, 0xc), + EVENT_CONSTRAINT_END + }; + +@@ -5463,12 +5477,12 @@ static struct intel_uncore_ops icx_uncore_mmio_ops = { + static struct intel_uncore_type icx_uncore_imc = { + .name = "imc", + .num_counters = 4, +- .num_boxes = 8, ++ .num_boxes = 12, + .perf_ctr_bits = 48, + .fixed_ctr_bits = 48, + .fixed_ctr = SNR_IMC_MMIO_PMON_FIXED_CTR, + .fixed_ctl = SNR_IMC_MMIO_PMON_FIXED_CTL, +- .event_descs = hswep_uncore_imc_events, ++ .event_descs = snr_uncore_imc_events, + .perf_ctr = SNR_IMC_MMIO_PMON_CTR0, + .event_ctl = SNR_IMC_MMIO_PMON_CTL0, + .event_mask = SNBEP_PMON_RAW_EVENT_MASK, +@@ -5647,6 +5661,7 @@ static struct intel_uncore_type spr_uncore_chabox = { + .event_mask = SPR_CHA_PMON_EVENT_MASK, + .event_mask_ext = SPR_RAW_EVENT_MASK_EXT, + .num_shared_regs = 1, ++ .constraints = skx_uncore_chabox_constraints, + .ops = &spr_uncore_chabox_ops, + .format_group = &spr_uncore_chabox_format_group, + .attr_update = uncore_alias_groups, +@@ -5658,6 +5673,7 @@ static struct intel_uncore_type spr_uncore_iio = { + .event_mask_ext = SNR_IIO_PMON_RAW_EVENT_MASK_EXT, + .format_group = &snr_uncore_iio_format_group, + .attr_update = uncore_alias_groups, ++ .constraints = icx_uncore_iio_constraints, + }; + + static struct attribute *spr_uncore_raw_formats_attr[] = { +@@ -5686,9 +5702,16 @@ static struct intel_uncore_type spr_uncore_irp = { + + }; + ++static struct event_constraint spr_uncore_m2pcie_constraints[] = { ++ UNCORE_EVENT_CONSTRAINT(0x14, 0x3), ++ UNCORE_EVENT_CONSTRAINT(0x2d, 0x3), ++ EVENT_CONSTRAINT_END ++}; ++ + static struct intel_uncore_type spr_uncore_m2pcie = { + SPR_UNCORE_COMMON_FORMAT(), + .name = "m2pcie", ++ .constraints = spr_uncore_m2pcie_constraints, + }; + + static struct intel_uncore_type spr_uncore_pcu = { +@@ -5765,6 +5788,7 @@ static struct intel_uncore_type spr_uncore_upi = { + static struct intel_uncore_type spr_uncore_m3upi = { + SPR_UNCORE_PCI_COMMON_FORMAT(), + .name = "m3upi", ++ .constraints = icx_uncore_m3upi_constraints, + }; + + static struct intel_uncore_type spr_uncore_mdf = { +diff --git a/arch/x86/events/rapl.c b/arch/x86/events/rapl.c +index 85feafacc445d..77e3a47af5ad5 100644 +--- a/arch/x86/events/rapl.c ++++ b/arch/x86/events/rapl.c +@@ -536,11 +536,14 @@ static struct perf_msr intel_rapl_spr_msrs[] = { + * - perf_msr_probe(PERF_RAPL_MAX) + * - want to use same event codes across both architectures + */ +-static struct perf_msr amd_rapl_msrs[PERF_RAPL_MAX] = { +- [PERF_RAPL_PKG] = { MSR_AMD_PKG_ENERGY_STATUS, &rapl_events_pkg_group, test_msr }, ++static struct perf_msr amd_rapl_msrs[] = { ++ [PERF_RAPL_PP0] = { 0, &rapl_events_cores_group, 0, false, 0 }, ++ [PERF_RAPL_PKG] = { MSR_AMD_PKG_ENERGY_STATUS, &rapl_events_pkg_group, test_msr, false, RAPL_MSR_MASK }, ++ [PERF_RAPL_RAM] = { 0, &rapl_events_ram_group, 0, false, 0 }, ++ [PERF_RAPL_PP1] = { 0, &rapl_events_gpu_group, 0, false, 0 }, ++ [PERF_RAPL_PSYS] = { 0, &rapl_events_psys_group, 0, false, 0 }, + }; + +- + static int rapl_cpu_offline(unsigned int cpu) + { + struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu); +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +index 708a2712a516d..b6d48ca5b0f17 100644 +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -139,7 +139,6 @@ void set_hv_tscchange_cb(void (*cb)(void)) + struct hv_reenlightenment_control re_ctrl = { + .vector = HYPERV_REENLIGHTENMENT_VECTOR, + .enabled = 1, +- .target_vp = hv_vp_index[smp_processor_id()] + }; + struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1}; + +@@ -148,13 +147,20 @@ void set_hv_tscchange_cb(void (*cb)(void)) + return; + } + ++ if (!hv_vp_index) ++ return; ++ + hv_reenlightenment_cb = cb; + + /* Make sure callback is registered before we write to MSRs */ + wmb(); + ++ re_ctrl.target_vp = hv_vp_index[get_cpu()]; ++ + wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl)); + wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl)); ++ ++ put_cpu(); + } + EXPORT_SYMBOL_GPL(set_hv_tscchange_cb); + +@@ -342,20 +348,13 @@ static void __init hv_get_partition_id(void) + */ + void __init hyperv_init(void) + { +- u64 guest_id, required_msrs; ++ u64 guest_id; + union hv_x64_msr_hypercall_contents hypercall_msr; + int cpuhp; + + if (x86_hyper_type != X86_HYPER_MS_HYPERV) + return; + +- /* Absolutely required MSRs */ +- required_msrs = HV_MSR_HYPERCALL_AVAILABLE | +- HV_MSR_VP_INDEX_AVAILABLE; +- +- if ((ms_hyperv.features & required_msrs) != required_msrs) +- return; +- + if (hv_common_init()) + return; + +diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c +index bd13736d0c054..0ad2378fe6ad7 100644 +--- a/arch/x86/hyperv/mmu.c ++++ b/arch/x86/hyperv/mmu.c +@@ -68,15 +68,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, + + local_irq_save(flags); + +- /* +- * Only check the mask _after_ interrupt has been disabled to avoid the +- * mask changing under our feet. +- */ +- if (cpumask_empty(cpus)) { +- local_irq_restore(flags); +- return; +- } +- + flush_pcpu = (struct hv_tlb_flush **) + this_cpu_ptr(hyperv_pcpu_input_arg); + +@@ -115,7 +106,9 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, + * must. We will also check all VP numbers when walking the + * supplied CPU set to remain correct in all cases. + */ +- if (hv_cpu_number_to_vp_number(cpumask_last(cpus)) >= 64) ++ cpu = cpumask_last(cpus); ++ ++ if (cpu < nr_cpumask_bits && hv_cpu_number_to_vp_number(cpu) >= 64) + goto do_ex_hypercall; + + for_each_cpu(cpu, cpus) { +@@ -131,6 +124,12 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, + __set_bit(vcpu, (unsigned long *) + &flush->processor_mask); + } ++ ++ /* nothing to flush if 'processor_mask' ends up being empty */ ++ if (!flush->processor_mask) { ++ local_irq_restore(flags); ++ return; ++ } + } + + /* +diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h +index 84b87538a15de..bab883c0b6fee 100644 +--- a/arch/x86/include/asm/bug.h ++++ b/arch/x86/include/asm/bug.h +@@ -22,7 +22,7 @@ + + #ifdef CONFIG_DEBUG_BUGVERBOSE + +-#define _BUG_FLAGS(ins, flags) \ ++#define _BUG_FLAGS(ins, flags, extra) \ + do { \ + asm_inline volatile("1:\t" ins "\n" \ + ".pushsection __bug_table,\"aw\"\n" \ +@@ -31,7 +31,8 @@ do { \ + "\t.word %c1" "\t# bug_entry::line\n" \ + "\t.word %c2" "\t# bug_entry::flags\n" \ + "\t.org 2b+%c3\n" \ +- ".popsection" \ ++ ".popsection\n" \ ++ extra \ + : : "i" (__FILE__), "i" (__LINE__), \ + "i" (flags), \ + "i" (sizeof(struct bug_entry))); \ +@@ -39,14 +40,15 @@ do { \ + + #else /* !CONFIG_DEBUG_BUGVERBOSE */ + +-#define _BUG_FLAGS(ins, flags) \ ++#define _BUG_FLAGS(ins, flags, extra) \ + do { \ + asm_inline volatile("1:\t" ins "\n" \ + ".pushsection __bug_table,\"aw\"\n" \ + "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ + "\t.word %c0" "\t# bug_entry::flags\n" \ + "\t.org 2b+%c1\n" \ +- ".popsection" \ ++ ".popsection\n" \ ++ extra \ + : : "i" (flags), \ + "i" (sizeof(struct bug_entry))); \ + } while (0) +@@ -55,7 +57,7 @@ do { \ + + #else + +-#define _BUG_FLAGS(ins, flags) asm volatile(ins) ++#define _BUG_FLAGS(ins, flags, extra) asm volatile(ins) + + #endif /* CONFIG_GENERIC_BUG */ + +@@ -63,8 +65,8 @@ do { \ + #define BUG() \ + do { \ + instrumentation_begin(); \ +- _BUG_FLAGS(ASM_UD2, 0); \ +- unreachable(); \ ++ _BUG_FLAGS(ASM_UD2, 0, ""); \ ++ __builtin_unreachable(); \ + } while (0) + + /* +@@ -75,9 +77,9 @@ do { \ + */ + #define __WARN_FLAGS(flags) \ + do { \ ++ __auto_type f = BUGFLAG_WARNING|(flags); \ + instrumentation_begin(); \ +- _BUG_FLAGS(ASM_UD2, BUGFLAG_WARNING|(flags)); \ +- annotate_reachable(); \ ++ _BUG_FLAGS(ASM_UD2, f, ASM_REACHABLE); \ + instrumentation_end(); \ + } while (0) + +diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h +index 3d52b094850a9..dd5ea1bdf04c5 100644 +--- a/arch/x86/include/asm/cpu_entry_area.h ++++ b/arch/x86/include/asm/cpu_entry_area.h +@@ -10,6 +10,12 @@ + + #ifdef CONFIG_X86_64 + ++#ifdef CONFIG_AMD_MEM_ENCRYPT ++#define VC_EXCEPTION_STKSZ EXCEPTION_STKSZ ++#else ++#define VC_EXCEPTION_STKSZ 0 ++#endif ++ + /* Macro to enforce the same ordering and stack sizes */ + #define ESTACKS_MEMBERS(guardsize, optional_stack_size) \ + char DF_stack_guard[guardsize]; \ +@@ -28,7 +34,7 @@ + + /* The exception stacks' physical storage. No guard pages required */ + struct exception_stacks { +- ESTACKS_MEMBERS(0, 0) ++ ESTACKS_MEMBERS(0, VC_EXCEPTION_STKSZ) + }; + + /* The effective cpu entry area mapping with guard pages. */ +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index d0ce5cfd3ac14..4423759f619cc 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -204,7 +204,7 @@ + /* FREE! ( 7*32+10) */ + #define X86_FEATURE_PTI ( 7*32+11) /* Kernel Page Table Isolation enabled */ + #define X86_FEATURE_RETPOLINE ( 7*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */ +-#define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */ ++#define X86_FEATURE_RETPOLINE_LFENCE ( 7*32+13) /* "" Use LFENCE for Spectre variant 2 */ + #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ + #define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */ + #define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */ +diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h +index 4d0b126835b8a..63158fd558567 100644 +--- a/arch/x86/include/asm/efi.h ++++ b/arch/x86/include/asm/efi.h +@@ -197,8 +197,6 @@ static inline bool efi_runtime_supported(void) + + extern void parse_efi_setup(u64 phys_addr, u32 data_len); + +-extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); +- + extern void efi_thunk_runtime_setup(void); + efi_status_t efi_set_virtual_address_map(unsigned long memory_map_size, + unsigned long descriptor_size, +diff --git a/arch/x86/include/asm/insn-eval.h b/arch/x86/include/asm/insn-eval.h +index 91d7182ad2d6e..4ec3613551e3b 100644 +--- a/arch/x86/include/asm/insn-eval.h ++++ b/arch/x86/include/asm/insn-eval.h +@@ -21,6 +21,7 @@ int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs); + int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs); + unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); + int insn_get_code_seg_params(struct pt_regs *regs); ++int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip); + int insn_fetch_from_user(struct pt_regs *regs, + unsigned char buf[MAX_INSN_SIZE]); + int insn_fetch_from_user_inatomic(struct pt_regs *regs, +diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h +index 562854c608082..8d55bd11848cb 100644 +--- a/arch/x86/include/asm/irq_stack.h ++++ b/arch/x86/include/asm/irq_stack.h +@@ -77,11 +77,11 @@ + * Function calls can clobber anything except the callee-saved + * registers. Tell the compiler. + */ +-#define call_on_irqstack(func, asm_call, argconstr...) \ ++#define call_on_stack(stack, func, asm_call, argconstr...) \ + { \ + register void *tos asm("r11"); \ + \ +- tos = ((void *)__this_cpu_read(hardirq_stack_ptr)); \ ++ tos = ((void *)(stack)); \ + \ + asm_inline volatile( \ + "movq %%rsp, (%[tos]) \n" \ +@@ -98,6 +98,25 @@ + ); \ + } + ++#define ASM_CALL_ARG0 \ ++ "call %P[__func] \n" ++ ++#define ASM_CALL_ARG1 \ ++ "movq %[arg1], %%rdi \n" \ ++ ASM_CALL_ARG0 ++ ++#define ASM_CALL_ARG2 \ ++ "movq %[arg2], %%rsi \n" \ ++ ASM_CALL_ARG1 ++ ++#define ASM_CALL_ARG3 \ ++ "movq %[arg3], %%rdx \n" \ ++ ASM_CALL_ARG2 ++ ++#define call_on_irqstack(func, asm_call, argconstr...) \ ++ call_on_stack(__this_cpu_read(hardirq_stack_ptr), \ ++ func, asm_call, argconstr) ++ + /* Macros to assert type correctness for run_*_on_irqstack macros */ + #define assert_function_type(func, proto) \ + static_assert(__builtin_types_compatible_p(typeof(&func), proto)) +@@ -147,8 +166,7 @@ + */ + #define ASM_CALL_SYSVEC \ + "call irq_enter_rcu \n" \ +- "movq %[arg1], %%rdi \n" \ +- "call %P[__func] \n" \ ++ ASM_CALL_ARG1 \ + "call irq_exit_rcu \n" + + #define SYSVEC_CONSTRAINTS , [arg1] "r" (regs) +@@ -168,12 +186,10 @@ + */ + #define ASM_CALL_IRQ \ + "call irq_enter_rcu \n" \ +- "movq %[arg1], %%rdi \n" \ +- "movl %[arg2], %%esi \n" \ +- "call %P[__func] \n" \ ++ ASM_CALL_ARG2 \ + "call irq_exit_rcu \n" + +-#define IRQ_CONSTRAINTS , [arg1] "r" (regs), [arg2] "r" (vector) ++#define IRQ_CONSTRAINTS , [arg1] "r" (regs), [arg2] "r" ((unsigned long)vector) + + #define run_irq_on_irqstack_cond(func, regs, vector) \ + { \ +@@ -185,9 +201,6 @@ + IRQ_CONSTRAINTS, regs, vector); \ + } + +-#define ASM_CALL_SOFTIRQ \ +- "call %P[__func] \n" +- + /* + * Macro to invoke __do_softirq on the irq stack. This is only called from + * task context when bottom halves are about to be reenabled and soft +@@ -197,7 +210,7 @@ + #define do_softirq_own_stack() \ + { \ + __this_cpu_write(hardirq_stack_inuse, true); \ +- call_on_irqstack(__do_softirq, ASM_CALL_SOFTIRQ); \ ++ call_on_irqstack(__do_softirq, ASM_CALL_ARG0); \ + __this_cpu_write(hardirq_stack_inuse, false); \ + } + +diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h +index cefe1d81e2e8b..9e50da3ed01a3 100644 +--- a/arch/x86/include/asm/kvm-x86-ops.h ++++ b/arch/x86/include/asm/kvm-x86-ops.h +@@ -47,6 +47,7 @@ KVM_X86_OP(set_dr7) + KVM_X86_OP(cache_reg) + KVM_X86_OP(get_rflags) + KVM_X86_OP(set_rflags) ++KVM_X86_OP(get_if_flag) + KVM_X86_OP(tlb_flush_all) + KVM_X86_OP(tlb_flush_current) + KVM_X86_OP_NULL(tlb_remote_flush) +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 13f64654dfff8..01759199d7238 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -98,7 +98,7 @@ + KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) + #define KVM_REQ_TLB_FLUSH_CURRENT KVM_ARCH_REQ(26) + #define KVM_REQ_TLB_FLUSH_GUEST \ +- KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_NO_WAKEUP) ++ KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) + #define KVM_REQ_APF_READY KVM_ARCH_REQ(28) + #define KVM_REQ_MSR_FILTER_CHANGED KVM_ARCH_REQ(29) + #define KVM_REQ_UPDATE_CPU_DIRTY_LOGGING \ +@@ -364,6 +364,7 @@ union kvm_mmu_extended_role { + unsigned int cr4_smap:1; + unsigned int cr4_smep:1; + unsigned int cr4_la57:1; ++ unsigned int efer_lma:1; + }; + }; + +@@ -751,7 +752,7 @@ struct kvm_vcpu_arch { + u8 preempted; + u64 msr_val; + u64 last_steal; +- struct gfn_to_pfn_cache cache; ++ struct gfn_to_hva_cache cache; + } st; + + u64 l1_tsc_offset; +@@ -1340,6 +1341,7 @@ struct kvm_x86_ops { + void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); + unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); + void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags); ++ bool (*get_if_flag)(struct kvm_vcpu *vcpu); + + void (*tlb_flush_all)(struct kvm_vcpu *vcpu); + void (*tlb_flush_current)(struct kvm_vcpu *vcpu); +@@ -1485,6 +1487,7 @@ struct kvm_x86_ops { + }; + + struct kvm_x86_nested_ops { ++ void (*leave_nested)(struct kvm_vcpu *vcpu); + int (*check_events)(struct kvm_vcpu *vcpu); + bool (*hv_timer_pending)(struct kvm_vcpu *vcpu); + void (*triple_fault)(struct kvm_vcpu *vcpu); +@@ -1507,6 +1510,7 @@ struct kvm_x86_init_ops { + int (*disabled_by_bios)(void); + int (*check_processor_compatibility)(void); + int (*hardware_setup)(void); ++ bool (*intel_pt_intr_in_guest)(void); + + struct kvm_x86_ops *runtime_ops; + }; +diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h +index 9c80c68d75b54..3fb9f5ebefa42 100644 +--- a/arch/x86/include/asm/mem_encrypt.h ++++ b/arch/x86/include/asm/mem_encrypt.h +@@ -13,6 +13,7 @@ + #ifndef __ASSEMBLY__ + + #include <linux/init.h> ++#include <linux/cc_platform.h> + + #include <asm/bootparam.h> + +diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h +index ec2d5c8c66947..b3dd514f80a0b 100644 +--- a/arch/x86/include/asm/nospec-branch.h ++++ b/arch/x86/include/asm/nospec-branch.h +@@ -81,7 +81,7 @@ + #ifdef CONFIG_RETPOLINE + ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ + __stringify(jmp __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ +- __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_AMD ++ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE + #else + jmp *%\reg + #endif +@@ -91,7 +91,7 @@ + #ifdef CONFIG_RETPOLINE + ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *%\reg), \ + __stringify(call __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ +- __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *%\reg), X86_FEATURE_RETPOLINE_AMD ++ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *%\reg), X86_FEATURE_RETPOLINE_LFENCE + #else + call *%\reg + #endif +@@ -133,7 +133,7 @@ + "lfence;\n" \ + ANNOTATE_RETPOLINE_SAFE \ + "call *%[thunk_target]\n", \ +- X86_FEATURE_RETPOLINE_AMD) ++ X86_FEATURE_RETPOLINE_LFENCE) + + # define THUNK_TARGET(addr) [thunk_target] "r" (addr) + +@@ -163,7 +163,7 @@ + "lfence;\n" \ + ANNOTATE_RETPOLINE_SAFE \ + "call *%[thunk_target]\n", \ +- X86_FEATURE_RETPOLINE_AMD) ++ X86_FEATURE_RETPOLINE_LFENCE) + + # define THUNK_TARGET(addr) [thunk_target] "rm" (addr) + #endif +@@ -175,9 +175,11 @@ + /* The Spectre V2 mitigation variants */ + enum spectre_v2_mitigation { + SPECTRE_V2_NONE, +- SPECTRE_V2_RETPOLINE_GENERIC, +- SPECTRE_V2_RETPOLINE_AMD, +- SPECTRE_V2_IBRS_ENHANCED, ++ SPECTRE_V2_RETPOLINE, ++ SPECTRE_V2_LFENCE, ++ SPECTRE_V2_EIBRS, ++ SPECTRE_V2_EIBRS_RETPOLINE, ++ SPECTRE_V2_EIBRS_LFENCE, + }; + + /* The indirect branch speculation control variants */ +diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h +index a8d4ad8565681..e9e2c3ba59239 100644 +--- a/arch/x86/include/asm/page_64_types.h ++++ b/arch/x86/include/asm/page_64_types.h +@@ -15,7 +15,7 @@ + #define THREAD_SIZE_ORDER (2 + KASAN_STACK_ORDER) + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + +-#define EXCEPTION_STACK_ORDER (0 + KASAN_STACK_ORDER) ++#define EXCEPTION_STACK_ORDER (1 + KASAN_STACK_ORDER) + #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER) + + #define IRQ_STACK_ORDER (2 + KASAN_STACK_ORDER) +diff --git a/arch/x86/include/asm/pkru.h b/arch/x86/include/asm/pkru.h +index ccc539faa5bbc..4d8b9448fe8d2 100644 +--- a/arch/x86/include/asm/pkru.h ++++ b/arch/x86/include/asm/pkru.h +@@ -4,8 +4,8 @@ + + #include <asm/fpu/xstate.h> + +-#define PKRU_AD_BIT 0x1 +-#define PKRU_WD_BIT 0x2 ++#define PKRU_AD_BIT 0x1u ++#define PKRU_WD_BIT 0x2u + #define PKRU_BITS_PER_PKEY 2 + + #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS +diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h +index 9ad2acaaae9b8..577f342dbfb27 100644 +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -518,6 +518,7 @@ struct thread_struct { + */ + unsigned long iopl_emul; + ++ unsigned int iopl_warn:1; + unsigned int sig_on_uaccess_err:1; + + /* +diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h +index 5db5d083c8732..331474b150f16 100644 +--- a/arch/x86/include/asm/realmode.h ++++ b/arch/x86/include/asm/realmode.h +@@ -89,6 +89,7 @@ static inline void set_real_mode_mem(phys_addr_t mem) + } + + void reserve_real_mode(void); ++void load_trampoline_pgtable(void); + + #endif /* __ASSEMBLY__ */ + +diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h +index f248eb2ac2d4a..3881b5333eb81 100644 +--- a/arch/x86/include/asm/stacktrace.h ++++ b/arch/x86/include/asm/stacktrace.h +@@ -38,6 +38,16 @@ int get_stack_info(unsigned long *stack, struct task_struct *task, + bool get_stack_info_noinstr(unsigned long *stack, struct task_struct *task, + struct stack_info *info); + ++static __always_inline ++bool get_stack_guard_info(unsigned long *stack, struct stack_info *info) ++{ ++ /* make sure it's not in the stack proper */ ++ if (get_stack_info_noinstr(stack, current, info)) ++ return false; ++ /* but if it is in the page below it, we hit a guard */ ++ return get_stack_info_noinstr((void *)stack + PAGE_SIZE, current, info); ++} ++ + const char *stack_type_name(enum stack_type type); + + static inline bool on_stack(struct stack_info *info, void *addr, size_t len) +diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h +index 9239399e54914..55160445ea78b 100644 +--- a/arch/x86/include/asm/topology.h ++++ b/arch/x86/include/asm/topology.h +@@ -218,7 +218,7 @@ static inline void arch_set_max_freq_ratio(bool turbo_disabled) + } + #endif + +-#ifdef CONFIG_ACPI_CPPC_LIB ++#if defined(CONFIG_ACPI_CPPC_LIB) && defined(CONFIG_SMP) + void init_freq_invariance_cppc(void); + #define init_freq_invariance_cppc init_freq_invariance_cppc + #endif +diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h +index 7f7200021bd13..6221be7cafc3b 100644 +--- a/arch/x86/include/asm/traps.h ++++ b/arch/x86/include/asm/traps.h +@@ -40,9 +40,9 @@ void math_emulate(struct math_emu_info *); + bool fault_in_kernel_space(unsigned long address); + + #ifdef CONFIG_VMAP_STACK +-void __noreturn handle_stack_overflow(const char *message, +- struct pt_regs *regs, +- unsigned long fault_address); ++void __noreturn handle_stack_overflow(struct pt_regs *regs, ++ unsigned long fault_address, ++ struct stack_info *info); + #endif + + #endif /* _ASM_X86_TRAPS_H */ +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 5c95d242f38d7..bb1430283c726 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -314,11 +314,12 @@ do { \ + do { \ + __chk_user_ptr(ptr); \ + switch (size) { \ +- unsigned char x_u8__; \ +- case 1: \ ++ case 1: { \ ++ unsigned char x_u8__; \ + __get_user_asm(x_u8__, ptr, "b", "=q", label); \ + (x) = x_u8__; \ + break; \ ++ } \ + case 2: \ + __get_user_asm(x, ptr, "w", "=r", label); \ + break; \ +diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h +index ff4b52e37e60d..5adab895127e1 100644 +--- a/arch/x86/include/asm/xen/hypervisor.h ++++ b/arch/x86/include/asm/xen/hypervisor.h +@@ -62,4 +62,9 @@ void xen_arch_register_cpu(int num); + void xen_arch_unregister_cpu(int num); + #endif + ++#ifdef CONFIG_PVH ++void __init xen_pvh_init(struct boot_params *boot_params); ++void __init mem_map_via_hcall(struct boot_params *boot_params_p); ++#endif ++ + #endif /* _ASM_X86_XEN_HYPERVISOR_H */ +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 8f4e8fa6ed759..2ff3e600f4269 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -21,6 +21,7 @@ CFLAGS_REMOVE_ftrace.o = -pg + CFLAGS_REMOVE_early_printk.o = -pg + CFLAGS_REMOVE_head64.o = -pg + CFLAGS_REMOVE_sev.o = -pg ++CFLAGS_REMOVE_cc_platform.o = -pg + endif + + KASAN_SANITIZE_head$(BITS).o := n +@@ -29,6 +30,7 @@ KASAN_SANITIZE_dumpstack_$(BITS).o := n + KASAN_SANITIZE_stacktrace.o := n + KASAN_SANITIZE_paravirt.o := n + KASAN_SANITIZE_sev.o := n ++KASAN_SANITIZE_cc_platform.o := n + + # With some compiler versions the generated code results in boot hangs, caused + # by several compilation units. To be safe, disable all instrumentation. +@@ -47,6 +49,7 @@ endif + KCOV_INSTRUMENT := n + + CFLAGS_head$(BITS).o += -fno-stack-protector ++CFLAGS_cc_platform.o += -fno-stack-protector + + CFLAGS_irq.o := -I $(srctree)/$(src)/../include/asm/trace + +@@ -147,6 +150,9 @@ obj-$(CONFIG_UNWINDER_FRAME_POINTER) += unwind_frame.o + obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o + + obj-$(CONFIG_AMD_MEM_ENCRYPT) += sev.o ++ ++obj-$(CONFIG_ARCH_HAS_CC_PLATFORM) += cc_platform.o ++ + ### + # 64 bit specific files + ifeq ($(CONFIG_X86_64),y) +diff --git a/arch/x86/kernel/cc_platform.c b/arch/x86/kernel/cc_platform.c +new file mode 100644 +index 0000000000000..03bb2f343ddb7 +--- /dev/null ++++ b/arch/x86/kernel/cc_platform.c +@@ -0,0 +1,69 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Confidential Computing Platform Capability checks ++ * ++ * Copyright (C) 2021 Advanced Micro Devices, Inc. ++ * ++ * Author: Tom Lendacky <thomas.lendacky@amd.com> ++ */ ++ ++#include <linux/export.h> ++#include <linux/cc_platform.h> ++#include <linux/mem_encrypt.h> ++ ++#include <asm/processor.h> ++ ++static bool __maybe_unused intel_cc_platform_has(enum cc_attr attr) ++{ ++#ifdef CONFIG_INTEL_TDX_GUEST ++ return false; ++#else ++ return false; ++#endif ++} ++ ++/* ++ * SME and SEV are very similar but they are not the same, so there are ++ * times that the kernel will need to distinguish between SME and SEV. The ++ * cc_platform_has() function is used for this. When a distinction isn't ++ * needed, the CC_ATTR_MEM_ENCRYPT attribute can be used. ++ * ++ * The trampoline code is a good example for this requirement. Before ++ * paging is activated, SME will access all memory as decrypted, but SEV ++ * will access all memory as encrypted. So, when APs are being brought ++ * up under SME the trampoline area cannot be encrypted, whereas under SEV ++ * the trampoline area must be encrypted. ++ */ ++static bool amd_cc_platform_has(enum cc_attr attr) ++{ ++#ifdef CONFIG_AMD_MEM_ENCRYPT ++ switch (attr) { ++ case CC_ATTR_MEM_ENCRYPT: ++ return sme_me_mask; ++ ++ case CC_ATTR_HOST_MEM_ENCRYPT: ++ return sme_me_mask && !(sev_status & MSR_AMD64_SEV_ENABLED); ++ ++ case CC_ATTR_GUEST_MEM_ENCRYPT: ++ return sev_status & MSR_AMD64_SEV_ENABLED; ++ ++ case CC_ATTR_GUEST_STATE_ENCRYPT: ++ return sev_status & MSR_AMD64_SEV_ES_ENABLED; ++ ++ default: ++ return false; ++ } ++#else ++ return false; ++#endif ++} ++ ++ ++bool cc_platform_has(enum cc_attr attr) ++{ ++ if (sme_me_mask) ++ return amd_cc_platform_has(attr); ++ ++ return false; ++} ++EXPORT_SYMBOL_GPL(cc_platform_has); +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +index 2131af9f2fa23..4edb6f0f628c2 100644 +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -989,6 +989,8 @@ static void init_amd(struct cpuinfo_x86 *c) + if (cpu_has(c, X86_FEATURE_IRPERF) && + !cpu_has_amd_erratum(c, amd_erratum_1054)) + msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT); ++ ++ check_null_seg_clears_base(c); + } + + #ifdef CONFIG_X86_32 +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index ecfca3bbcd968..13320a06e14bd 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -16,6 +16,7 @@ + #include <linux/prctl.h> + #include <linux/sched/smt.h> + #include <linux/pgtable.h> ++#include <linux/bpf.h> + + #include <asm/spec-ctrl.h> + #include <asm/cmdline.h> +@@ -650,6 +651,32 @@ static inline const char *spectre_v2_module_string(void) + static inline const char *spectre_v2_module_string(void) { return ""; } + #endif + ++#define SPECTRE_V2_LFENCE_MSG "WARNING: LFENCE mitigation is not recommended for this CPU, data leaks possible!\n" ++#define SPECTRE_V2_EIBRS_EBPF_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!\n" ++#define SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS+LFENCE mitigation and SMT, data leaks possible via Spectre v2 BHB attacks!\n" ++ ++#ifdef CONFIG_BPF_SYSCALL ++void unpriv_ebpf_notify(int new_state) ++{ ++ if (new_state) ++ return; ++ ++ /* Unprivileged eBPF is enabled */ ++ ++ switch (spectre_v2_enabled) { ++ case SPECTRE_V2_EIBRS: ++ pr_err(SPECTRE_V2_EIBRS_EBPF_MSG); ++ break; ++ case SPECTRE_V2_EIBRS_LFENCE: ++ if (sched_smt_active()) ++ pr_err(SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG); ++ break; ++ default: ++ break; ++ } ++} ++#endif ++ + static inline bool match_option(const char *arg, int arglen, const char *opt) + { + int len = strlen(opt); +@@ -664,7 +691,10 @@ enum spectre_v2_mitigation_cmd { + SPECTRE_V2_CMD_FORCE, + SPECTRE_V2_CMD_RETPOLINE, + SPECTRE_V2_CMD_RETPOLINE_GENERIC, +- SPECTRE_V2_CMD_RETPOLINE_AMD, ++ SPECTRE_V2_CMD_RETPOLINE_LFENCE, ++ SPECTRE_V2_CMD_EIBRS, ++ SPECTRE_V2_CMD_EIBRS_RETPOLINE, ++ SPECTRE_V2_CMD_EIBRS_LFENCE, + }; + + enum spectre_v2_user_cmd { +@@ -737,6 +767,13 @@ spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd) + return SPECTRE_V2_USER_CMD_AUTO; + } + ++static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode) ++{ ++ return (mode == SPECTRE_V2_EIBRS || ++ mode == SPECTRE_V2_EIBRS_RETPOLINE || ++ mode == SPECTRE_V2_EIBRS_LFENCE); ++} ++ + static void __init + spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) + { +@@ -804,7 +841,7 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) + */ + if (!boot_cpu_has(X86_FEATURE_STIBP) || + !smt_possible || +- spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED) ++ spectre_v2_in_eibrs_mode(spectre_v2_enabled)) + return; + + /* +@@ -824,9 +861,11 @@ set_mode: + + static const char * const spectre_v2_strings[] = { + [SPECTRE_V2_NONE] = "Vulnerable", +- [SPECTRE_V2_RETPOLINE_GENERIC] = "Mitigation: Full generic retpoline", +- [SPECTRE_V2_RETPOLINE_AMD] = "Mitigation: Full AMD retpoline", +- [SPECTRE_V2_IBRS_ENHANCED] = "Mitigation: Enhanced IBRS", ++ [SPECTRE_V2_RETPOLINE] = "Mitigation: Retpolines", ++ [SPECTRE_V2_LFENCE] = "Mitigation: LFENCE", ++ [SPECTRE_V2_EIBRS] = "Mitigation: Enhanced IBRS", ++ [SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced IBRS + LFENCE", ++ [SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced IBRS + Retpolines", + }; + + static const struct { +@@ -837,8 +876,12 @@ static const struct { + { "off", SPECTRE_V2_CMD_NONE, false }, + { "on", SPECTRE_V2_CMD_FORCE, true }, + { "retpoline", SPECTRE_V2_CMD_RETPOLINE, false }, +- { "retpoline,amd", SPECTRE_V2_CMD_RETPOLINE_AMD, false }, ++ { "retpoline,amd", SPECTRE_V2_CMD_RETPOLINE_LFENCE, false }, ++ { "retpoline,lfence", SPECTRE_V2_CMD_RETPOLINE_LFENCE, false }, + { "retpoline,generic", SPECTRE_V2_CMD_RETPOLINE_GENERIC, false }, ++ { "eibrs", SPECTRE_V2_CMD_EIBRS, false }, ++ { "eibrs,lfence", SPECTRE_V2_CMD_EIBRS_LFENCE, false }, ++ { "eibrs,retpoline", SPECTRE_V2_CMD_EIBRS_RETPOLINE, false }, + { "auto", SPECTRE_V2_CMD_AUTO, false }, + }; + +@@ -875,17 +918,30 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) + } + + if ((cmd == SPECTRE_V2_CMD_RETPOLINE || +- cmd == SPECTRE_V2_CMD_RETPOLINE_AMD || +- cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC) && ++ cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE || ++ cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC || ++ cmd == SPECTRE_V2_CMD_EIBRS_LFENCE || ++ cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE) && + !IS_ENABLED(CONFIG_RETPOLINE)) { +- pr_err("%s selected but not compiled in. Switching to AUTO select\n", mitigation_options[i].option); ++ pr_err("%s selected but not compiled in. Switching to AUTO select\n", ++ mitigation_options[i].option); + return SPECTRE_V2_CMD_AUTO; + } + +- if (cmd == SPECTRE_V2_CMD_RETPOLINE_AMD && +- boot_cpu_data.x86_vendor != X86_VENDOR_HYGON && +- boot_cpu_data.x86_vendor != X86_VENDOR_AMD) { +- pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n"); ++ if ((cmd == SPECTRE_V2_CMD_EIBRS || ++ cmd == SPECTRE_V2_CMD_EIBRS_LFENCE || ++ cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE) && ++ !boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) { ++ pr_err("%s selected but CPU doesn't have eIBRS. Switching to AUTO select\n", ++ mitigation_options[i].option); ++ return SPECTRE_V2_CMD_AUTO; ++ } ++ ++ if ((cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE || ++ cmd == SPECTRE_V2_CMD_EIBRS_LFENCE) && ++ !boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) { ++ pr_err("%s selected, but CPU doesn't have a serializing LFENCE. Switching to AUTO select\n", ++ mitigation_options[i].option); + return SPECTRE_V2_CMD_AUTO; + } + +@@ -894,6 +950,16 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) + return cmd; + } + ++static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void) ++{ ++ if (!IS_ENABLED(CONFIG_RETPOLINE)) { ++ pr_err("Kernel not compiled with retpoline; no mitigation available!"); ++ return SPECTRE_V2_NONE; ++ } ++ ++ return SPECTRE_V2_RETPOLINE; ++} ++ + static void __init spectre_v2_select_mitigation(void) + { + enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); +@@ -914,49 +980,64 @@ static void __init spectre_v2_select_mitigation(void) + case SPECTRE_V2_CMD_FORCE: + case SPECTRE_V2_CMD_AUTO: + if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) { +- mode = SPECTRE_V2_IBRS_ENHANCED; +- /* Force it so VMEXIT will restore correctly */ +- x86_spec_ctrl_base |= SPEC_CTRL_IBRS; +- wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base); +- goto specv2_set_mode; ++ mode = SPECTRE_V2_EIBRS; ++ break; + } +- if (IS_ENABLED(CONFIG_RETPOLINE)) +- goto retpoline_auto; ++ ++ mode = spectre_v2_select_retpoline(); + break; +- case SPECTRE_V2_CMD_RETPOLINE_AMD: +- if (IS_ENABLED(CONFIG_RETPOLINE)) +- goto retpoline_amd; ++ ++ case SPECTRE_V2_CMD_RETPOLINE_LFENCE: ++ pr_err(SPECTRE_V2_LFENCE_MSG); ++ mode = SPECTRE_V2_LFENCE; + break; ++ + case SPECTRE_V2_CMD_RETPOLINE_GENERIC: +- if (IS_ENABLED(CONFIG_RETPOLINE)) +- goto retpoline_generic; ++ mode = SPECTRE_V2_RETPOLINE; + break; ++ + case SPECTRE_V2_CMD_RETPOLINE: +- if (IS_ENABLED(CONFIG_RETPOLINE)) +- goto retpoline_auto; ++ mode = spectre_v2_select_retpoline(); ++ break; ++ ++ case SPECTRE_V2_CMD_EIBRS: ++ mode = SPECTRE_V2_EIBRS; ++ break; ++ ++ case SPECTRE_V2_CMD_EIBRS_LFENCE: ++ mode = SPECTRE_V2_EIBRS_LFENCE; ++ break; ++ ++ case SPECTRE_V2_CMD_EIBRS_RETPOLINE: ++ mode = SPECTRE_V2_EIBRS_RETPOLINE; + break; + } +- pr_err("Spectre mitigation: kernel not compiled with retpoline; no mitigation available!"); +- return; + +-retpoline_auto: +- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || +- boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { +- retpoline_amd: +- if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) { +- pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n"); +- goto retpoline_generic; +- } +- mode = SPECTRE_V2_RETPOLINE_AMD; +- setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD); +- setup_force_cpu_cap(X86_FEATURE_RETPOLINE); +- } else { +- retpoline_generic: +- mode = SPECTRE_V2_RETPOLINE_GENERIC; ++ if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled()) ++ pr_err(SPECTRE_V2_EIBRS_EBPF_MSG); ++ ++ if (spectre_v2_in_eibrs_mode(mode)) { ++ /* Force it so VMEXIT will restore correctly */ ++ x86_spec_ctrl_base |= SPEC_CTRL_IBRS; ++ wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base); ++ } ++ ++ switch (mode) { ++ case SPECTRE_V2_NONE: ++ case SPECTRE_V2_EIBRS: ++ break; ++ ++ case SPECTRE_V2_LFENCE: ++ case SPECTRE_V2_EIBRS_LFENCE: ++ setup_force_cpu_cap(X86_FEATURE_RETPOLINE_LFENCE); ++ fallthrough; ++ ++ case SPECTRE_V2_RETPOLINE: ++ case SPECTRE_V2_EIBRS_RETPOLINE: + setup_force_cpu_cap(X86_FEATURE_RETPOLINE); ++ break; + } + +-specv2_set_mode: + spectre_v2_enabled = mode; + pr_info("%s\n", spectre_v2_strings[mode]); + +@@ -982,7 +1063,7 @@ specv2_set_mode: + * the CPU supports Enhanced IBRS, kernel might un-intentionally not + * enable IBRS around firmware calls. + */ +- if (boot_cpu_has(X86_FEATURE_IBRS) && mode != SPECTRE_V2_IBRS_ENHANCED) { ++ if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_eibrs_mode(mode)) { + setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW); + pr_info("Enabling Restricted Speculation for firmware calls\n"); + } +@@ -1052,6 +1133,10 @@ void cpu_bugs_smt_update(void) + { + mutex_lock(&spec_ctrl_mutex); + ++ if (sched_smt_active() && unprivileged_ebpf_enabled() && ++ spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) ++ pr_warn_once(SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG); ++ + switch (spectre_v2_user_stibp) { + case SPECTRE_V2_USER_NONE: + break; +@@ -1691,7 +1776,7 @@ static ssize_t tsx_async_abort_show_state(char *buf) + + static char *stibp_state(void) + { +- if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED) ++ if (spectre_v2_in_eibrs_mode(spectre_v2_enabled)) + return ""; + + switch (spectre_v2_user_stibp) { +@@ -1721,6 +1806,27 @@ static char *ibpb_state(void) + return ""; + } + ++static ssize_t spectre_v2_show_state(char *buf) ++{ ++ if (spectre_v2_enabled == SPECTRE_V2_LFENCE) ++ return sprintf(buf, "Vulnerable: LFENCE\n"); ++ ++ if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled()) ++ return sprintf(buf, "Vulnerable: eIBRS with unprivileged eBPF\n"); ++ ++ if (sched_smt_active() && unprivileged_ebpf_enabled() && ++ spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) ++ return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n"); ++ ++ return sprintf(buf, "%s%s%s%s%s%s\n", ++ spectre_v2_strings[spectre_v2_enabled], ++ ibpb_state(), ++ boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "", ++ stibp_state(), ++ boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "", ++ spectre_v2_module_string()); ++} ++ + static ssize_t srbds_show_state(char *buf) + { + return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]); +@@ -1746,12 +1852,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr + return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]); + + case X86_BUG_SPECTRE_V2: +- return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], +- ibpb_state(), +- boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "", +- stibp_state(), +- boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "", +- spectre_v2_module_string()); ++ return spectre_v2_show_state(buf); + + case X86_BUG_SPEC_STORE_BYPASS: + return sprintf(buf, "%s\n", ssb_strings[ssb_mode]); +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index b3410f1ac2175..58b1416c05da4 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1396,9 +1396,8 @@ void __init early_cpu_init(void) + early_identify_cpu(&boot_cpu_data); + } + +-static void detect_null_seg_behavior(struct cpuinfo_x86 *c) ++static bool detect_null_seg_behavior(void) + { +-#ifdef CONFIG_X86_64 + /* + * Empirically, writing zero to a segment selector on AMD does + * not clear the base, whereas writing zero to a segment +@@ -1419,10 +1418,43 @@ static void detect_null_seg_behavior(struct cpuinfo_x86 *c) + wrmsrl(MSR_FS_BASE, 1); + loadsegment(fs, 0); + rdmsrl(MSR_FS_BASE, tmp); +- if (tmp != 0) +- set_cpu_bug(c, X86_BUG_NULL_SEG); + wrmsrl(MSR_FS_BASE, old_base); +-#endif ++ return tmp == 0; ++} ++ ++void check_null_seg_clears_base(struct cpuinfo_x86 *c) ++{ ++ /* BUG_NULL_SEG is only relevant with 64bit userspace */ ++ if (!IS_ENABLED(CONFIG_X86_64)) ++ return; ++ ++ /* Zen3 CPUs advertise Null Selector Clears Base in CPUID. */ ++ if (c->extended_cpuid_level >= 0x80000021 && ++ cpuid_eax(0x80000021) & BIT(6)) ++ return; ++ ++ /* ++ * CPUID bit above wasn't set. If this kernel is still running ++ * as a HV guest, then the HV has decided not to advertize ++ * that CPUID bit for whatever reason. For example, one ++ * member of the migration pool might be vulnerable. Which ++ * means, the bug is present: set the BUG flag and return. ++ */ ++ if (cpu_has(c, X86_FEATURE_HYPERVISOR)) { ++ set_cpu_bug(c, X86_BUG_NULL_SEG); ++ return; ++ } ++ ++ /* ++ * Zen2 CPUs also have this behaviour, but no CPUID bit. ++ * 0x18 is the respective family for Hygon. ++ */ ++ if ((c->x86 == 0x17 || c->x86 == 0x18) && ++ detect_null_seg_behavior()) ++ return; ++ ++ /* All the remaining ones are affected */ ++ set_cpu_bug(c, X86_BUG_NULL_SEG); + } + + static void generic_identify(struct cpuinfo_x86 *c) +@@ -1458,8 +1490,6 @@ static void generic_identify(struct cpuinfo_x86 *c) + + get_model_name(c); /* Default name */ + +- detect_null_seg_behavior(c); +- + /* + * ESPFIX is a strange bug. All real CPUs have it. Paravirt + * systems that run Linux at CPL > 0 may or may not have the +diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h +index 95521302630d4..ee6f23f7587d4 100644 +--- a/arch/x86/kernel/cpu/cpu.h ++++ b/arch/x86/kernel/cpu/cpu.h +@@ -75,6 +75,7 @@ extern int detect_extended_topology_early(struct cpuinfo_x86 *c); + extern int detect_extended_topology(struct cpuinfo_x86 *c); + extern int detect_ht_early(struct cpuinfo_x86 *c); + extern void detect_ht(struct cpuinfo_x86 *c); ++extern void check_null_seg_clears_base(struct cpuinfo_x86 *c); + + unsigned int aperfmperf_get_khz(int cpu); + +diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c +index 6d50136f7ab98..3fcdda4c1e114 100644 +--- a/arch/x86/kernel/cpu/hygon.c ++++ b/arch/x86/kernel/cpu/hygon.c +@@ -335,6 +335,8 @@ static void init_hygon(struct cpuinfo_x86 *c) + /* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */ + if (!cpu_has(c, X86_FEATURE_XENPV)) + set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); ++ ++ check_null_seg_clears_base(c); + } + + static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c) +diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c +index 08831acc1d036..c0c57bd05f02d 100644 +--- a/arch/x86/kernel/cpu/mce/amd.c ++++ b/arch/x86/kernel/cpu/mce/amd.c +@@ -400,7 +400,7 @@ static void threshold_restart_bank(void *_tr) + u32 hi, lo; + + /* sysfs write might race against an offline operation */ +- if (this_cpu_read(threshold_banks)) ++ if (!this_cpu_read(threshold_banks) && !tr->set_lvt_off) + return; + + rdmsr(tr->b->address, lo, hi); +diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c +index 193204aee8801..e23e74e2f928d 100644 +--- a/arch/x86/kernel/cpu/mce/core.c ++++ b/arch/x86/kernel/cpu/mce/core.c +@@ -295,11 +295,17 @@ static void wait_for_panic(void) + panic("Panicing machine check CPU died"); + } + +-static void mce_panic(const char *msg, struct mce *final, char *exp) ++static noinstr void mce_panic(const char *msg, struct mce *final, char *exp) + { +- int apei_err = 0; + struct llist_node *pending; + struct mce_evt_llist *l; ++ int apei_err = 0; ++ ++ /* ++ * Allow instrumentation around external facilities usage. Not that it ++ * matters a whole lot since the machine is going to panic anyway. ++ */ ++ instrumentation_begin(); + + if (!fake_panic) { + /* +@@ -314,7 +320,7 @@ static void mce_panic(const char *msg, struct mce *final, char *exp) + } else { + /* Don't log too much for fake panic */ + if (atomic_inc_return(&mce_fake_panicked) > 1) +- return; ++ goto out; + } + pending = mce_gen_pool_prepare_records(); + /* First print corrected ones that are still unlogged */ +@@ -352,6 +358,9 @@ static void mce_panic(const char *msg, struct mce *final, char *exp) + panic(msg); + } else + pr_emerg(HW_ERR "Fake kernel panic: %s\n", msg); ++ ++out: ++ instrumentation_end(); + } + + /* Support code for software error injection */ +@@ -682,7 +691,7 @@ static struct notifier_block mce_default_nb = { + /* + * Read ADDR and MISC registers. + */ +-static void mce_read_aux(struct mce *m, int i) ++static noinstr void mce_read_aux(struct mce *m, int i) + { + if (m->status & MCI_STATUS_MISCV) + m->misc = mce_rdmsrl(msr_ops.misc(i)); +@@ -1072,10 +1081,13 @@ static int mce_start(int *no_way_out) + * Synchronize between CPUs after main scanning loop. + * This invokes the bulk of the Monarch processing. + */ +-static int mce_end(int order) ++static noinstr int mce_end(int order) + { +- int ret = -1; + u64 timeout = (u64)mca_cfg.monarch_timeout * NSEC_PER_USEC; ++ int ret = -1; ++ ++ /* Allow instrumentation around external facilities. */ ++ instrumentation_begin(); + + if (!timeout) + goto reset; +@@ -1119,7 +1131,8 @@ static int mce_end(int order) + /* + * Don't reset anything. That's done by the Monarch. + */ +- return 0; ++ ret = 0; ++ goto out; + } + + /* +@@ -1135,6 +1148,10 @@ reset: + * Let others run again. + */ + atomic_set(&mce_executing, 0); ++ ++out: ++ instrumentation_end(); ++ + return ret; + } + +@@ -1454,6 +1471,14 @@ noinstr void do_machine_check(struct pt_regs *regs) + if (worst != MCE_AR_SEVERITY && !kill_current_task) + goto out; + ++ /* ++ * Enable instrumentation around the external facilities like ++ * task_work_add() (via queue_task_work()), fixup_exception() etc. ++ * For now, that is. Fixing this properly would need a lot more involved ++ * reorganization. ++ */ ++ instrumentation_begin(); ++ + /* Fault was in user mode and we need to take some action */ + if ((m.cs & 3) == 3) { + /* If this triggers there is no way to recover. Die hard. */ +@@ -1479,6 +1504,9 @@ noinstr void do_machine_check(struct pt_regs *regs) + if (m.kflags & MCE_IN_KERNEL_COPYIN) + queue_task_work(&m, msg, kill_current_task); + } ++ ++ instrumentation_end(); ++ + out: + mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); + } +diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c +index 0bfc14041bbb4..b63b548497c14 100644 +--- a/arch/x86/kernel/cpu/mce/inject.c ++++ b/arch/x86/kernel/cpu/mce/inject.c +@@ -350,7 +350,7 @@ static ssize_t flags_write(struct file *filp, const char __user *ubuf, + char buf[MAX_FLAG_OPT_SIZE], *__buf; + int err; + +- if (cnt > MAX_FLAG_OPT_SIZE) ++ if (!cnt || cnt > MAX_FLAG_OPT_SIZE) + return -EINVAL; + + if (copy_from_user(&buf, ubuf, cnt)) +diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c +index acfd5d9f93c68..baafbb37be678 100644 +--- a/arch/x86/kernel/cpu/mce/intel.c ++++ b/arch/x86/kernel/cpu/mce/intel.c +@@ -486,6 +486,7 @@ static void intel_ppin_init(struct cpuinfo_x86 *c) + case INTEL_FAM6_BROADWELL_X: + case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_ICELAKE_X: ++ case INTEL_FAM6_ICELAKE_D: + case INTEL_FAM6_SAPPHIRERAPIDS_X: + case INTEL_FAM6_XEON_PHI_KNL: + case INTEL_FAM6_XEON_PHI_KNM: +@@ -547,12 +548,13 @@ bool intel_filter_mce(struct mce *m) + { + struct cpuinfo_x86 *c = &boot_cpu_data; + +- /* MCE errata HSD131, HSM142, HSW131, BDM48, and HSM142 */ ++ /* MCE errata HSD131, HSM142, HSW131, BDM48, HSM142 and SKX37 */ + if ((c->x86 == 6) && + ((c->x86_model == INTEL_FAM6_HASWELL) || + (c->x86_model == INTEL_FAM6_HASWELL_L) || + (c->x86_model == INTEL_FAM6_BROADWELL) || +- (c->x86_model == INTEL_FAM6_HASWELL_G)) && ++ (c->x86_model == INTEL_FAM6_HASWELL_G) || ++ (c->x86_model == INTEL_FAM6_SKYLAKE_X)) && + (m->bank == 0) && + ((m->status & 0xa0000000ffffffff) == 0x80000000000f0005)) + return true; +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +index e095c28d27ae8..ef6316fef99ff 100644 +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -163,12 +163,22 @@ static uint32_t __init ms_hyperv_platform(void) + cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, + &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); + +- if (eax >= HYPERV_CPUID_MIN && +- eax <= HYPERV_CPUID_MAX && +- !memcmp("Microsoft Hv", hyp_signature, 12)) +- return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS; ++ if (eax < HYPERV_CPUID_MIN || eax > HYPERV_CPUID_MAX || ++ memcmp("Microsoft Hv", hyp_signature, 12)) ++ return 0; + +- return 0; ++ /* HYPERCALL and VP_INDEX MSRs are mandatory for all features. */ ++ eax = cpuid_eax(HYPERV_CPUID_FEATURES); ++ if (!(eax & HV_MSR_HYPERCALL_AVAILABLE)) { ++ pr_warn("x86/hyperv: HYPERCALL MSR not available.\n"); ++ return 0; ++ } ++ if (!(eax & HV_MSR_VP_INDEX_AVAILABLE)) { ++ pr_warn("x86/hyperv: VP_INDEX MSR not available.\n"); ++ return 0; ++ } ++ ++ return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS; + } + + static unsigned char hv_get_nmi_reason(void) +diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c +index 001808e3901cc..48afe96ae0f0f 100644 +--- a/arch/x86/kernel/cpu/sgx/encl.c ++++ b/arch/x86/kernel/cpu/sgx/encl.c +@@ -410,6 +410,8 @@ void sgx_encl_release(struct kref *ref) + } + + kfree(entry); ++ /* Invoke scheduler to prevent soft lockups. */ ++ cond_resched(); + } + + xa_destroy(&encl->page_array); +diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c +index 63d3de02bbccb..8471a8b9b48e8 100644 +--- a/arch/x86/kernel/cpu/sgx/main.c ++++ b/arch/x86/kernel/cpu/sgx/main.c +@@ -28,8 +28,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ksgxd_waitq); + static LIST_HEAD(sgx_active_page_list); + static DEFINE_SPINLOCK(sgx_reclaimer_lock); + +-/* The free page list lock protected variables prepend the lock. */ +-static unsigned long sgx_nr_free_pages; ++static atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0); + + /* Nodes with one or more EPC sections. */ + static nodemask_t sgx_numa_mask; +@@ -403,14 +402,15 @@ skip: + + spin_lock(&node->lock); + list_add_tail(&epc_page->list, &node->free_page_list); +- sgx_nr_free_pages++; + spin_unlock(&node->lock); ++ atomic_long_inc(&sgx_nr_free_pages); + } + } + + static bool sgx_should_reclaim(unsigned long watermark) + { +- return sgx_nr_free_pages < watermark && !list_empty(&sgx_active_page_list); ++ return atomic_long_read(&sgx_nr_free_pages) < watermark && ++ !list_empty(&sgx_active_page_list); + } + + static int ksgxd(void *p) +@@ -471,9 +471,9 @@ static struct sgx_epc_page *__sgx_alloc_epc_page_from_node(int nid) + + page = list_first_entry(&node->free_page_list, struct sgx_epc_page, list); + list_del_init(&page->list); +- sgx_nr_free_pages--; + + spin_unlock(&node->lock); ++ atomic_long_dec(&sgx_nr_free_pages); + + return page; + } +@@ -625,9 +625,9 @@ void sgx_free_epc_page(struct sgx_epc_page *page) + spin_lock(&node->lock); + + list_add_tail(&page->list, &node->free_page_list); +- sgx_nr_free_pages++; + + spin_unlock(&node->lock); ++ atomic_long_inc(&sgx_nr_free_pages); + } + + static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index 5601b95944fae..6c5defd6569a3 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -32,9 +32,15 @@ const char *stack_type_name(enum stack_type type) + { + BUILD_BUG_ON(N_EXCEPTION_STACKS != 6); + ++ if (type == STACK_TYPE_TASK) ++ return "TASK"; ++ + if (type == STACK_TYPE_IRQ) + return "IRQ"; + ++ if (type == STACK_TYPE_SOFTIRQ) ++ return "SOFTIRQ"; ++ + if (type == STACK_TYPE_ENTRY) { + /* + * On 64-bit, we have a generic entry stack that we +diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c +index 391a4e2b86049..8690fab95ae4b 100644 +--- a/arch/x86/kernel/early-quirks.c ++++ b/arch/x86/kernel/early-quirks.c +@@ -515,6 +515,7 @@ static const struct intel_early_ops gen11_early_ops __initconst = { + .stolen_size = gen9_stolen_size, + }; + ++/* Intel integrated GPUs for which we need to reserve "stolen memory" */ + static const struct pci_device_id intel_early_ids[] __initconst = { + INTEL_I830_IDS(&i830_early_ops), + INTEL_I845G_IDS(&i845_early_ops), +@@ -591,6 +592,13 @@ static void __init intel_graphics_quirks(int num, int slot, int func) + u16 device; + int i; + ++ /* ++ * Reserve "stolen memory" for an integrated GPU. If we've already ++ * found one, there's nothing to do for other (discrete) GPUs. ++ */ ++ if (resource_size(&intel_graphics_stolen_res)) ++ return; ++ + device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); + + for (i = 0; i < ARRAY_SIZE(intel_early_ids); i++) { +@@ -703,7 +711,7 @@ static struct chipset early_qrk[] __initdata = { + { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, + PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, + { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID, +- QFLAG_APPLY_ONCE, intel_graphics_quirks }, ++ 0, intel_graphics_quirks }, + /* + * HPET on the current version of the Baytrail platform has accuracy + * problems: it will halt in deep idle state - so we disable it. +diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c +index 66ed317ebc0d3..125cbbe10fefa 100644 +--- a/arch/x86/kernel/fpu/regset.c ++++ b/arch/x86/kernel/fpu/regset.c +@@ -87,11 +87,9 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, + const void *kbuf, const void __user *ubuf) + { + struct fpu *fpu = &target->thread.fpu; +- struct user32_fxsr_struct newstate; ++ struct fxregs_state newstate; + int ret; + +- BUILD_BUG_ON(sizeof(newstate) != sizeof(struct fxregs_state)); +- + if (!cpu_feature_enabled(X86_FEATURE_FXSR)) + return -ENODEV; + +@@ -112,9 +110,10 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, + /* Copy the state */ + memcpy(&fpu->state.fxsave, &newstate, sizeof(newstate)); + +- /* Clear xmm8..15 */ ++ /* Clear xmm8..15 for 32-bit callers */ + BUILD_BUG_ON(sizeof(fpu->state.fxsave.xmm_space) != 16 * 16); +- memset(&fpu->state.fxsave.xmm_space[8], 0, 8 * 16); ++ if (in_ia32_syscall()) ++ memset(&fpu->state.fxsave.xmm_space[8*4], 0, 8 * 16); + + /* Mark FP and SSE as in use when XSAVE is enabled */ + if (use_xsave()) +diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c +index e28f6a5d14f1b..766ffe3ba3137 100644 +--- a/arch/x86/kernel/irq.c ++++ b/arch/x86/kernel/irq.c +@@ -291,8 +291,10 @@ void kvm_set_posted_intr_wakeup_handler(void (*handler)(void)) + { + if (handler) + kvm_posted_intr_wakeup_handler = handler; +- else ++ else { + kvm_posted_intr_wakeup_handler = dummy_handler; ++ synchronize_rcu(); ++ } + } + EXPORT_SYMBOL_GPL(kvm_set_posted_intr_wakeup_handler); + +diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c +index 5e9a34b5bd741..867a341a0c7e8 100644 +--- a/arch/x86/kernel/module.c ++++ b/arch/x86/kernel/module.c +@@ -67,6 +67,7 @@ static unsigned long int get_module_load_offset(void) + + void *module_alloc(unsigned long size) + { ++ gfp_t gfp_mask = GFP_KERNEL; + void *p; + + if (PAGE_ALIGN(size) > MODULES_LEN) +@@ -74,10 +75,10 @@ void *module_alloc(unsigned long size) + + p = __vmalloc_node_range(size, MODULE_ALIGN, + MODULES_VADDR + get_module_load_offset(), +- MODULES_END, GFP_KERNEL, +- PAGE_KERNEL, 0, NUMA_NO_NODE, ++ MODULES_END, gfp_mask, ++ PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, + __builtin_return_address(0)); +- if (p && (kasan_module_alloc(p, size) < 0)) { ++ if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { + vfree(p); + return NULL; + } +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 1d9463e3096b6..f2f733bcb2b95 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -132,6 +132,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, + frame->ret_addr = (unsigned long) ret_from_fork; + p->thread.sp = (unsigned long) fork_frame; + p->thread.io_bitmap = NULL; ++ p->thread.iopl_warn = 0; + memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); + + #ifdef CONFIG_X86_64 +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 4c208ea3bd9f3..033d9c6a94689 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -1224,7 +1224,7 @@ static struct user_regset x86_64_regsets[] __ro_after_init = { + }, + [REGSET_FP] = { + .core_note_type = NT_PRFPREG, +- .n = sizeof(struct user_i387_struct) / sizeof(long), ++ .n = sizeof(struct fxregs_state) / sizeof(long), + .size = sizeof(long), .align = sizeof(long), + .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set + }, +@@ -1271,7 +1271,7 @@ static struct user_regset x86_32_regsets[] __ro_after_init = { + }, + [REGSET_XFP] = { + .core_note_type = NT_PRXFPREG, +- .n = sizeof(struct user32_fxsr_struct) / sizeof(u32), ++ .n = sizeof(struct fxregs_state) / sizeof(u32), + .size = sizeof(u32), .align = sizeof(u32), + .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set + }, +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index 0a40df66a40de..fa700b46588e0 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -113,17 +113,9 @@ void __noreturn machine_real_restart(unsigned int type) + spin_unlock(&rtc_lock); + + /* +- * Switch back to the initial page table. ++ * Switch to the trampoline page table. + */ +-#ifdef CONFIG_X86_32 +- load_cr3(initial_page_table); +-#else +- write_cr3(real_mode_header->trampoline_pgd); +- +- /* Exiting long mode will fail if CR4.PCIDE is set. */ +- if (boot_cpu_has(X86_FEATURE_PCID)) +- cr4_clear_bits(X86_CR4_PCIDE); +-#endif ++ load_trampoline_pgtable(); + + /* Jump to the identity-mapped low memory code */ + #ifdef CONFIG_X86_32 +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index 40ed44ead0631..48596f9fddf45 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -713,9 +713,6 @@ static void __init early_reserve_memory(void) + + early_reserve_initrd(); + +- if (efi_enabled(EFI_BOOT)) +- efi_memblock_x86_reserve_range(); +- + memblock_x86_reserve_range_setup_data(); + + reserve_ibft_region(); +@@ -890,6 +887,9 @@ void __init setup_arch(char **cmdline_p) + + parse_early_param(); + ++ if (efi_enabled(EFI_BOOT)) ++ efi_memblock_x86_reserve_range(); ++ + #ifdef CONFIG_MEMORY_HOTPLUG + /* + * Memory used by the kernel cannot be hot-removed because Linux +diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c +index a6895e440bc35..a0064cf77e562 100644 +--- a/arch/x86/kernel/sev.c ++++ b/arch/x86/kernel/sev.c +@@ -46,16 +46,6 @@ static struct ghcb __initdata *boot_ghcb; + struct sev_es_runtime_data { + struct ghcb ghcb_page; + +- /* Physical storage for the per-CPU IST stack of the #VC handler */ +- char ist_stack[EXCEPTION_STKSZ] __aligned(PAGE_SIZE); +- +- /* +- * Physical storage for the per-CPU fall-back stack of the #VC handler. +- * The fall-back stack is used when it is not safe to switch back to the +- * interrupted stack in the #VC entry code. +- */ +- char fallback_stack[EXCEPTION_STKSZ] __aligned(PAGE_SIZE); +- + /* + * Reserve one page per CPU as backup storage for the unencrypted GHCB. + * It is needed when an NMI happens while the #VC handler uses the real +@@ -99,27 +89,6 @@ DEFINE_STATIC_KEY_FALSE(sev_es_enable_key); + /* Needed in vc_early_forward_exception */ + void do_early_exception(struct pt_regs *regs, int trapnr); + +-static void __init setup_vc_stacks(int cpu) +-{ +- struct sev_es_runtime_data *data; +- struct cpu_entry_area *cea; +- unsigned long vaddr; +- phys_addr_t pa; +- +- data = per_cpu(runtime_data, cpu); +- cea = get_cpu_entry_area(cpu); +- +- /* Map #VC IST stack */ +- vaddr = CEA_ESTACK_BOT(&cea->estacks, VC); +- pa = __pa(data->ist_stack); +- cea_set_pte((void *)vaddr, pa, PAGE_KERNEL); +- +- /* Map VC fall-back stack */ +- vaddr = CEA_ESTACK_BOT(&cea->estacks, VC2); +- pa = __pa(data->fallback_stack); +- cea_set_pte((void *)vaddr, pa, PAGE_KERNEL); +-} +- + static __always_inline bool on_vc_stack(struct pt_regs *regs) + { + unsigned long sp = regs->sp; +@@ -325,11 +294,6 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt, + char *dst, char *buf, size_t size) + { + unsigned long error_code = X86_PF_PROT | X86_PF_WRITE; +- char __user *target = (char __user *)dst; +- u64 d8; +- u32 d4; +- u16 d2; +- u8 d1; + + /* + * This function uses __put_user() independent of whether kernel or user +@@ -351,26 +315,42 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt, + * instructions here would cause infinite nesting. + */ + switch (size) { +- case 1: ++ case 1: { ++ u8 d1; ++ u8 __user *target = (u8 __user *)dst; ++ + memcpy(&d1, buf, 1); + if (__put_user(d1, target)) + goto fault; + break; +- case 2: ++ } ++ case 2: { ++ u16 d2; ++ u16 __user *target = (u16 __user *)dst; ++ + memcpy(&d2, buf, 2); + if (__put_user(d2, target)) + goto fault; + break; +- case 4: ++ } ++ case 4: { ++ u32 d4; ++ u32 __user *target = (u32 __user *)dst; ++ + memcpy(&d4, buf, 4); + if (__put_user(d4, target)) + goto fault; + break; +- case 8: ++ } ++ case 8: { ++ u64 d8; ++ u64 __user *target = (u64 __user *)dst; ++ + memcpy(&d8, buf, 8); + if (__put_user(d8, target)) + goto fault; + break; ++ } + default: + WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); + return ES_UNSUPPORTED; +@@ -393,11 +373,6 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, + char *src, char *buf, size_t size) + { + unsigned long error_code = X86_PF_PROT; +- char __user *s = (char __user *)src; +- u64 d8; +- u32 d4; +- u16 d2; +- u8 d1; + + /* + * This function uses __get_user() independent of whether kernel or user +@@ -419,26 +394,41 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, + * instructions here would cause infinite nesting. + */ + switch (size) { +- case 1: ++ case 1: { ++ u8 d1; ++ u8 __user *s = (u8 __user *)src; ++ + if (__get_user(d1, s)) + goto fault; + memcpy(buf, &d1, 1); + break; +- case 2: ++ } ++ case 2: { ++ u16 d2; ++ u16 __user *s = (u16 __user *)src; ++ + if (__get_user(d2, s)) + goto fault; + memcpy(buf, &d2, 2); + break; +- case 4: ++ } ++ case 4: { ++ u32 d4; ++ u32 __user *s = (u32 __user *)src; ++ + if (__get_user(d4, s)) + goto fault; + memcpy(buf, &d4, 4); + break; +- case 8: ++ } ++ case 8: { ++ u64 d8; ++ u64 __user *s = (u64 __user *)src; + if (__get_user(d8, s)) + goto fault; + memcpy(buf, &d8, 8); + break; ++ } + default: + WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); + return ES_UNSUPPORTED; +@@ -787,7 +777,6 @@ void __init sev_es_init_vc_handling(void) + for_each_possible_cpu(cpu) { + alloc_runtime_data(cpu); + init_ghcb(cpu); +- setup_vc_stacks(cpu); + } + + sev_es_setup_play_dead(); +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index a58800973aed3..5b1984d468227 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -313,17 +313,19 @@ out: + } + + #ifdef CONFIG_VMAP_STACK +-__visible void __noreturn handle_stack_overflow(const char *message, +- struct pt_regs *regs, +- unsigned long fault_address) ++__visible void __noreturn handle_stack_overflow(struct pt_regs *regs, ++ unsigned long fault_address, ++ struct stack_info *info) + { +- printk(KERN_EMERG "BUG: stack guard page was hit at %p (stack is %p..%p)\n", +- (void *)fault_address, current->stack, +- (char *)current->stack + THREAD_SIZE - 1); +- die(message, regs, 0); ++ const char *name = stack_type_name(info->type); ++ ++ printk(KERN_EMERG "BUG: %s stack guard page was hit at %p (stack is %p..%p)\n", ++ name, (void *)fault_address, info->begin, info->end); ++ ++ die("stack guard page", regs, 0); + + /* Be absolutely certain we don't return. */ +- panic("%s", message); ++ panic("%s stack guard hit", name); + } + #endif + +@@ -353,6 +355,7 @@ DEFINE_IDTENTRY_DF(exc_double_fault) + + #ifdef CONFIG_VMAP_STACK + unsigned long address = read_cr2(); ++ struct stack_info info; + #endif + + #ifdef CONFIG_X86_ESPFIX64 +@@ -455,10 +458,8 @@ DEFINE_IDTENTRY_DF(exc_double_fault) + * stack even if the actual trigger for the double fault was + * something else. + */ +- if ((unsigned long)task_stack_page(tsk) - 1 - address < PAGE_SIZE) { +- handle_stack_overflow("kernel stack overflow (double-fault)", +- regs, address); +- } ++ if (get_stack_guard_info((void *)address, &info)) ++ handle_stack_overflow(regs, address, &info); + #endif + + pr_emerg("PANIC: double fault, error_code: 0x%lx\n", error_code); +@@ -528,6 +529,36 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs, + + #define GPFSTR "general protection fault" + ++static bool fixup_iopl_exception(struct pt_regs *regs) ++{ ++ struct thread_struct *t = ¤t->thread; ++ unsigned char byte; ++ unsigned long ip; ++ ++ if (!IS_ENABLED(CONFIG_X86_IOPL_IOPERM) || t->iopl_emul != 3) ++ return false; ++ ++ if (insn_get_effective_ip(regs, &ip)) ++ return false; ++ ++ if (get_user(byte, (const char __user *)ip)) ++ return false; ++ ++ if (byte != 0xfa && byte != 0xfb) ++ return false; ++ ++ if (!t->iopl_warn && printk_ratelimit()) { ++ pr_err("%s[%d] attempts to use CLI/STI, pretending it's a NOP, ip:%lx", ++ current->comm, task_pid_nr(current), ip); ++ print_vma_addr(KERN_CONT " in ", ip); ++ pr_cont("\n"); ++ t->iopl_warn = 1; ++ } ++ ++ regs->ip += 1; ++ return true; ++} ++ + DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) + { + char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR; +@@ -553,6 +584,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) + tsk = current; + + if (user_mode(regs)) { ++ if (fixup_iopl_exception(regs)) ++ goto exit; ++ + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = X86_TRAP_GP; + +@@ -709,7 +743,7 @@ asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *r + stack = (unsigned long *)sp; + + if (!get_stack_info_noinstr(stack, current, &info) || info.type == STACK_TYPE_ENTRY || +- info.type >= STACK_TYPE_EXCEPTION_LAST) ++ info.type > STACK_TYPE_EXCEPTION_LAST) + sp = __this_cpu_ist_top_va(VC2); + + sync: +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index 2e076a459a0c0..a698196377be9 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -1180,6 +1180,12 @@ void mark_tsc_unstable(char *reason) + + EXPORT_SYMBOL_GPL(mark_tsc_unstable); + ++static void __init tsc_disable_clocksource_watchdog(void) ++{ ++ clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; ++ clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; ++} ++ + static void __init check_system_tsc_reliable(void) + { + #if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC) +@@ -1196,6 +1202,23 @@ static void __init check_system_tsc_reliable(void) + #endif + if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) + tsc_clocksource_reliable = 1; ++ ++ /* ++ * Disable the clocksource watchdog when the system has: ++ * - TSC running at constant frequency ++ * - TSC which does not stop in C-States ++ * - the TSC_ADJUST register which allows to detect even minimal ++ * modifications ++ * - not more than two sockets. As the number of sockets cannot be ++ * evaluated at the early boot stage where this has to be ++ * invoked, check the number of online memory nodes as a ++ * fallback solution which is an reasonable estimate. ++ */ ++ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && ++ boot_cpu_has(X86_FEATURE_NONSTOP_TSC) && ++ boot_cpu_has(X86_FEATURE_TSC_ADJUST) && ++ nr_online_nodes <= 2) ++ tsc_disable_clocksource_watchdog(); + } + + /* +@@ -1387,9 +1410,6 @@ static int __init init_tsc_clocksource(void) + if (tsc_unstable) + goto unreg; + +- if (tsc_clocksource_reliable || no_tsc_watchdog) +- clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; +- + if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) + clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; + +@@ -1527,7 +1547,7 @@ void __init tsc_init(void) + } + + if (tsc_clocksource_reliable || no_tsc_watchdog) +- clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; ++ tsc_disable_clocksource_watchdog(); + + clocksource_register_khz(&clocksource_tsc_early, tsc_khz); + detect_art(); +diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c +index 50a4515fe0ad1..9452dc9664b51 100644 +--- a/arch/x86/kernel/tsc_sync.c ++++ b/arch/x86/kernel/tsc_sync.c +@@ -30,6 +30,7 @@ struct tsc_adjust { + }; + + static DEFINE_PER_CPU(struct tsc_adjust, tsc_adjust); ++static struct timer_list tsc_sync_check_timer; + + /* + * TSC's on different sockets may be reset asynchronously. +@@ -77,6 +78,46 @@ void tsc_verify_tsc_adjust(bool resume) + } + } + ++/* ++ * Normally the tsc_sync will be checked every time system enters idle ++ * state, but there is still caveat that a system won't enter idle, ++ * either because it's too busy or configured purposely to not enter ++ * idle. ++ * ++ * So setup a periodic timer (every 10 minutes) to make sure the check ++ * is always on. ++ */ ++ ++#define SYNC_CHECK_INTERVAL (HZ * 600) ++ ++static void tsc_sync_check_timer_fn(struct timer_list *unused) ++{ ++ int next_cpu; ++ ++ tsc_verify_tsc_adjust(false); ++ ++ /* Run the check for all onlined CPUs in turn */ ++ next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask); ++ if (next_cpu >= nr_cpu_ids) ++ next_cpu = cpumask_first(cpu_online_mask); ++ ++ tsc_sync_check_timer.expires += SYNC_CHECK_INTERVAL; ++ add_timer_on(&tsc_sync_check_timer, next_cpu); ++} ++ ++static int __init start_sync_check_timer(void) ++{ ++ if (!cpu_feature_enabled(X86_FEATURE_TSC_ADJUST) || tsc_clocksource_reliable) ++ return 0; ++ ++ timer_setup(&tsc_sync_check_timer, tsc_sync_check_timer_fn, 0); ++ tsc_sync_check_timer.expires = jiffies + SYNC_CHECK_INTERVAL; ++ add_timer(&tsc_sync_check_timer); ++ ++ return 0; ++} ++late_initcall(start_sync_check_timer); ++ + static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval, + unsigned int cpu, bool bootcpu) + { +diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c +index e5a7a10a0164d..17d58740891e2 100644 +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -142,6 +142,7 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval) + + user_access_end(); + ++exit_vm86: + preempt_disable(); + tsk->thread.sp0 = vm86->saved_sp0; + tsk->thread.sysenter_cs = __KERNEL_CS; +@@ -161,7 +162,8 @@ Efault_end: + user_access_end(); + Efault: + pr_alert("could not access userspace vm86 info\n"); +- do_exit(SIGSEGV); ++ force_exit_sig(SIGSEGV); ++ goto exit_vm86; + } + + static int do_vm86_irq_handling(int subfunction, int irqnumber); +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index 751aa85a30012..5f1d4a5aa8716 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -232,6 +232,25 @@ u64 kvm_vcpu_reserved_gpa_bits_raw(struct kvm_vcpu *vcpu) + return rsvd_bits(cpuid_maxphyaddr(vcpu), 63); + } + ++static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2, ++ int nent) ++{ ++ int r; ++ ++ r = kvm_check_cpuid(e2, nent); ++ if (r) ++ return r; ++ ++ kvfree(vcpu->arch.cpuid_entries); ++ vcpu->arch.cpuid_entries = e2; ++ vcpu->arch.cpuid_nent = nent; ++ ++ kvm_update_cpuid_runtime(vcpu); ++ kvm_vcpu_after_set_cpuid(vcpu); ++ ++ return 0; ++} ++ + /* when an old userspace process fills a new kernel module */ + int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, + struct kvm_cpuid *cpuid, +@@ -268,18 +287,9 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, + e2[i].padding[2] = 0; + } + +- r = kvm_check_cpuid(e2, cpuid->nent); +- if (r) { ++ r = kvm_set_cpuid(vcpu, e2, cpuid->nent); ++ if (r) + kvfree(e2); +- goto out_free_cpuid; +- } +- +- kvfree(vcpu->arch.cpuid_entries); +- vcpu->arch.cpuid_entries = e2; +- vcpu->arch.cpuid_nent = cpuid->nent; +- +- kvm_update_cpuid_runtime(vcpu); +- kvm_vcpu_after_set_cpuid(vcpu); + + out_free_cpuid: + kvfree(e); +@@ -303,20 +313,11 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, + return PTR_ERR(e2); + } + +- r = kvm_check_cpuid(e2, cpuid->nent); +- if (r) { ++ r = kvm_set_cpuid(vcpu, e2, cpuid->nent); ++ if (r) + kvfree(e2); +- return r; +- } +- +- kvfree(vcpu->arch.cpuid_entries); +- vcpu->arch.cpuid_entries = e2; +- vcpu->arch.cpuid_nent = cpuid->nent; + +- kvm_update_cpuid_runtime(vcpu); +- kvm_vcpu_after_set_cpuid(vcpu); +- +- return 0; ++ return r; + } + + int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, +@@ -420,12 +421,13 @@ void kvm_set_cpu_caps(void) + ); + + kvm_cpu_cap_mask(CPUID_7_0_EBX, +- F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) | +- F(BMI2) | F(ERMS) | F(INVPCID) | F(RTM) | 0 /*MPX*/ | F(RDSEED) | +- F(ADX) | F(SMAP) | F(AVX512IFMA) | F(AVX512F) | F(AVX512PF) | +- F(AVX512ER) | F(AVX512CD) | F(CLFLUSHOPT) | F(CLWB) | F(AVX512DQ) | +- F(SHA_NI) | F(AVX512BW) | F(AVX512VL) | 0 /*INTEL_PT*/ +- ); ++ F(FSGSBASE) | F(SGX) | F(BMI1) | F(HLE) | F(AVX2) | ++ F(FDP_EXCPTN_ONLY) | F(SMEP) | F(BMI2) | F(ERMS) | F(INVPCID) | ++ F(RTM) | F(ZERO_FCS_FDS) | 0 /*MPX*/ | F(AVX512F) | ++ F(AVX512DQ) | F(RDSEED) | F(ADX) | F(SMAP) | F(AVX512IFMA) | ++ F(CLFLUSHOPT) | F(CLWB) | 0 /*INTEL_PT*/ | F(AVX512PF) | ++ F(AVX512ER) | F(AVX512CD) | F(SHA_NI) | F(AVX512BW) | ++ F(AVX512VL)); + + kvm_cpu_cap_mask(CPUID_7_ECX, + F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) | +diff --git a/arch/x86/kvm/debugfs.c b/arch/x86/kvm/debugfs.c +index 54a83a7445384..f33c804a922ac 100644 +--- a/arch/x86/kvm/debugfs.c ++++ b/arch/x86/kvm/debugfs.c +@@ -95,6 +95,9 @@ static int kvm_mmu_rmaps_stat_show(struct seq_file *m, void *v) + unsigned int *log[KVM_NR_PAGE_SIZES], *cur; + int i, j, k, l, ret; + ++ if (!kvm_memslots_have_rmaps(kvm)) ++ return 0; ++ + ret = -ENOMEM; + memset(log, 0, sizeof(log)); + for (i = 0; i < KVM_NR_PAGE_SIZES; i++) { +diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c +index d5124b520f761..2092834efba11 100644 +--- a/arch/x86/kvm/hyperv.c ++++ b/arch/x86/kvm/hyperv.c +@@ -1922,11 +1922,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool + + all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL; + ++ if (all_cpus) ++ goto check_and_send_ipi; ++ + if (!sparse_banks_len) + goto ret_success; + +- if (!all_cpus && +- kvm_read_guest(kvm, ++ if (kvm_read_guest(kvm, + hc->ingpa + offsetof(struct hv_send_ipi_ex, + vp_set.bank_contents), + sparse_banks, +@@ -1934,6 +1936,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool + return HV_STATUS_INVALID_HYPERCALL_INPUT; + } + ++check_and_send_ipi: + if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + +@@ -2022,7 +2025,7 @@ static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result) + { + bool longmode; + +- longmode = is_64_bit_mode(vcpu); ++ longmode = is_64_bit_hypercall(vcpu); + if (longmode) + kvm_rax_write(vcpu, result); + else { +@@ -2171,7 +2174,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) + } + + #ifdef CONFIG_X86_64 +- if (is_64_bit_mode(vcpu)) { ++ if (is_64_bit_hypercall(vcpu)) { + hc.param = kvm_rcx_read(vcpu); + hc.ingpa = kvm_rdx_read(vcpu); + hc.outgpa = kvm_r8_read(vcpu); +diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c +index 8c065da73f8e5..4e0f52660842b 100644 +--- a/arch/x86/kvm/ioapic.c ++++ b/arch/x86/kvm/ioapic.c +@@ -96,7 +96,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, + static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) + { + ioapic->rtc_status.pending_eoi = 0; +- bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID + 1); ++ bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID); + } + + static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic); +diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h +index bbd4a5d18b5dc..f1b2b2a6ff4db 100644 +--- a/arch/x86/kvm/ioapic.h ++++ b/arch/x86/kvm/ioapic.h +@@ -39,13 +39,13 @@ struct kvm_vcpu; + + struct dest_map { + /* vcpu bitmap where IRQ has been sent */ +- DECLARE_BITMAP(map, KVM_MAX_VCPU_ID + 1); ++ DECLARE_BITMAP(map, KVM_MAX_VCPU_ID); + + /* + * Vector sent to a given vcpu, only valid when + * the vcpu's bit in map is set + */ +- u8 vectors[KVM_MAX_VCPU_ID + 1]; ++ u8 vectors[KVM_MAX_VCPU_ID]; + }; + + +@@ -81,7 +81,6 @@ struct kvm_ioapic { + unsigned long irq_states[IOAPIC_NUM_PINS]; + struct kvm_io_device dev; + struct kvm *kvm; +- void (*ack_notifier)(void *opaque, int irq); + spinlock_t lock; + struct rtc_status rtc_status; + struct delayed_work eoi_inject; +diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h +index 650642b18d151..c2d7cfe82d004 100644 +--- a/arch/x86/kvm/irq.h ++++ b/arch/x86/kvm/irq.h +@@ -56,7 +56,6 @@ struct kvm_pic { + struct kvm_io_device dev_master; + struct kvm_io_device dev_slave; + struct kvm_io_device dev_elcr; +- void (*ack_notifier)(void *opaque, int irq); + unsigned long irq_states[PIC_NUM_PINS]; + }; + +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index d6ac32f3f650c..91c2dc9f198df 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -676,38 +676,32 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu) + static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu) + { + u8 val; +- if (pv_eoi_get_user(vcpu, &val) < 0) { +- printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n", +- (unsigned long long)vcpu->arch.pv_eoi.msr_val); ++ if (pv_eoi_get_user(vcpu, &val) < 0) + return false; +- } ++ + return val & KVM_PV_EOI_ENABLED; + } + + static void pv_eoi_set_pending(struct kvm_vcpu *vcpu) + { +- if (pv_eoi_put_user(vcpu, KVM_PV_EOI_ENABLED) < 0) { +- printk(KERN_WARNING "Can't set EOI MSR value: 0x%llx\n", +- (unsigned long long)vcpu->arch.pv_eoi.msr_val); ++ if (pv_eoi_put_user(vcpu, KVM_PV_EOI_ENABLED) < 0) + return; +- } ++ + __set_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention); + } + + static void pv_eoi_clr_pending(struct kvm_vcpu *vcpu) + { +- if (pv_eoi_put_user(vcpu, KVM_PV_EOI_DISABLED) < 0) { +- printk(KERN_WARNING "Can't clear EOI MSR value: 0x%llx\n", +- (unsigned long long)vcpu->arch.pv_eoi.msr_val); ++ if (pv_eoi_put_user(vcpu, KVM_PV_EOI_DISABLED) < 0) + return; +- } ++ + __clear_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention); + } + + static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr) + { + int highest_irr; +- if (apic->vcpu->arch.apicv_active) ++ if (kvm_x86_ops.sync_pir_to_irr) + highest_irr = static_call(kvm_x86_sync_pir_to_irr)(apic->vcpu); + else + highest_irr = apic_find_highest_irr(apic); +@@ -2629,7 +2623,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s) + kvm_apic_set_version(vcpu); + + apic_update_ppr(apic); +- hrtimer_cancel(&apic->lapic_timer.timer); ++ cancel_apic_timer(apic); + apic->lapic_timer.expired_tscdeadline = 0; + apic_update_lvtt(apic); + apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0)); +diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c +index 0cc58901bf7a7..2297dd90fe4a5 100644 +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -1592,7 +1592,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) + flush = kvm_handle_gfn_range(kvm, range, kvm_unmap_rmapp); + + if (is_tdp_mmu_enabled(kvm)) +- flush |= kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); ++ flush = kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); + + return flush; + } +@@ -2188,10 +2188,10 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato + iterator->shadow_addr = root; + iterator->level = vcpu->arch.mmu->shadow_root_level; + +- if (iterator->level == PT64_ROOT_4LEVEL && ++ if (iterator->level >= PT64_ROOT_4LEVEL && + vcpu->arch.mmu->root_level < PT64_ROOT_4LEVEL && + !vcpu->arch.mmu->direct_map) +- --iterator->level; ++ iterator->level = PT32E_ROOT_LEVEL; + + if (iterator->level == PT32E_ROOT_LEVEL) { + /* +@@ -3579,7 +3579,7 @@ set_root_pgd: + out_unlock: + write_unlock(&vcpu->kvm->mmu_lock); + +- return 0; ++ return r; + } + + static int mmu_alloc_special_roots(struct kvm_vcpu *vcpu) +@@ -3889,12 +3889,23 @@ static void shadow_page_table_clear_flood(struct kvm_vcpu *vcpu, gva_t addr) + walk_shadow_page_lockless_end(vcpu); + } + ++static u32 alloc_apf_token(struct kvm_vcpu *vcpu) ++{ ++ /* make sure the token value is not 0 */ ++ u32 id = vcpu->arch.apf.id; ++ ++ if (id << 12 == 0) ++ vcpu->arch.apf.id = 1; ++ ++ return (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id; ++} ++ + static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + gfn_t gfn) + { + struct kvm_arch_async_pf arch; + +- arch.token = (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id; ++ arch.token = alloc_apf_token(vcpu); + arch.gfn = gfn; + arch.direct_map = vcpu->arch.mmu->direct_map; + arch.cr3 = vcpu->arch.mmu->get_guest_pgd(vcpu); +@@ -4679,6 +4690,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu, + /* PKEY and LA57 are active iff long mode is active. */ + ext.cr4_pke = ____is_efer_lma(regs) && ____is_cr4_pke(regs); + ext.cr4_la57 = ____is_efer_lma(regs) && ____is_cr4_la57(regs); ++ ext.efer_lma = ____is_efer_lma(regs); + } + + ext.valid = 1; +@@ -4851,7 +4863,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0, + struct kvm_mmu *context = &vcpu->arch.guest_mmu; + struct kvm_mmu_role_regs regs = { + .cr0 = cr0, +- .cr4 = cr4, ++ .cr4 = cr4 & ~X86_CR4_PKE, + .efer = efer, + }; + union kvm_mmu_role new_role; +@@ -4915,7 +4927,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, + context->direct_map = false; + + update_permission_bitmask(context, true); +- update_pkru_bitmask(context); ++ context->pkru_mask = 0; + reset_rsvds_bits_mask_ept(vcpu, context, execonly); + reset_ept_shadow_zero_bits_mask(vcpu, context, execonly); + } +@@ -5368,7 +5380,7 @@ void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, + + void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva) + { +- kvm_mmu_invalidate_gva(vcpu, vcpu->arch.mmu, gva, INVALID_PAGE); ++ kvm_mmu_invalidate_gva(vcpu, vcpu->arch.walk_mmu, gva, INVALID_PAGE); + ++vcpu->stat.invlpg; + } + EXPORT_SYMBOL_GPL(kvm_mmu_invlpg); +@@ -5473,8 +5485,8 @@ slot_handle_level(struct kvm *kvm, const struct kvm_memory_slot *memslot, + } + + static __always_inline bool +-slot_handle_leaf(struct kvm *kvm, const struct kvm_memory_slot *memslot, +- slot_level_handler fn, bool flush_on_yield) ++slot_handle_level_4k(struct kvm *kvm, const struct kvm_memory_slot *memslot, ++ slot_level_handler fn, bool flush_on_yield) + { + return slot_handle_level(kvm, memslot, fn, PG_LEVEL_4K, + PG_LEVEL_4K, flush_on_yield); +@@ -5758,13 +5770,11 @@ void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end) + for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) + flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, gfn_start, + gfn_end, flush); +- if (flush) +- kvm_flush_remote_tlbs_with_address(kvm, gfn_start, +- gfn_end - gfn_start); + } + + if (flush) +- kvm_flush_remote_tlbs_with_address(kvm, gfn_start, gfn_end); ++ kvm_flush_remote_tlbs_with_address(kvm, gfn_start, ++ gfn_end - gfn_start); + + kvm_dec_notifier_count(kvm, gfn_start, gfn_end); + +@@ -5856,21 +5866,21 @@ restart: + void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm, + const struct kvm_memory_slot *slot) + { +- bool flush = false; +- + if (kvm_memslots_have_rmaps(kvm)) { + write_lock(&kvm->mmu_lock); +- flush = slot_handle_leaf(kvm, slot, kvm_mmu_zap_collapsible_spte, true); +- if (flush) ++ /* ++ * Zap only 4k SPTEs since the legacy MMU only supports dirty ++ * logging at a 4k granularity and never creates collapsible ++ * 2m SPTEs during dirty logging. ++ */ ++ if (slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true)) + kvm_arch_flush_remote_tlbs_memslot(kvm, slot); + write_unlock(&kvm->mmu_lock); + } + + if (is_tdp_mmu_enabled(kvm)) { + read_lock(&kvm->mmu_lock); +- flush = kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot, flush); +- if (flush) +- kvm_arch_flush_remote_tlbs_memslot(kvm, slot); ++ kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot); + read_unlock(&kvm->mmu_lock); + } + } +@@ -5897,8 +5907,11 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm, + + if (kvm_memslots_have_rmaps(kvm)) { + write_lock(&kvm->mmu_lock); +- flush = slot_handle_leaf(kvm, memslot, __rmap_clear_dirty, +- false); ++ /* ++ * Clear dirty bits only on 4k SPTEs since the legacy MMU only ++ * support dirty logging at a 4k granularity. ++ */ ++ flush = slot_handle_level_4k(kvm, memslot, __rmap_clear_dirty, false); + write_unlock(&kvm->mmu_lock); + } + +diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h +index eb7b227fc6cfe..31d6456d8ac33 100644 +--- a/arch/x86/kvm/mmu/spte.h ++++ b/arch/x86/kvm/mmu/spte.h +@@ -310,12 +310,7 @@ static inline bool __is_bad_mt_xwr(struct rsvd_bits_validate *rsvd_check, + static __always_inline bool is_rsvd_spte(struct rsvd_bits_validate *rsvd_check, + u64 spte, int level) + { +- /* +- * Use a bitwise-OR instead of a logical-OR to aggregate the reserved +- * bits and EPT's invalid memtype/XWR checks to avoid an extra Jcc +- * (this is extremely unlikely to be short-circuited as true). +- */ +- return __is_bad_mt_xwr(rsvd_check, spte) | ++ return __is_bad_mt_xwr(rsvd_check, spte) || + __is_rsvd_bits_set(rsvd_check, spte, level); + } + +diff --git a/arch/x86/kvm/mmu/tdp_iter.c b/arch/x86/kvm/mmu/tdp_iter.c +index b3ed302c1a359..caa96c270b954 100644 +--- a/arch/x86/kvm/mmu/tdp_iter.c ++++ b/arch/x86/kvm/mmu/tdp_iter.c +@@ -26,6 +26,7 @@ static gfn_t round_gfn_for_level(gfn_t gfn, int level) + */ + void tdp_iter_restart(struct tdp_iter *iter) + { ++ iter->yielded = false; + iter->yielded_gfn = iter->next_last_level_gfn; + iter->level = iter->root_level; + +@@ -160,6 +161,11 @@ static bool try_step_up(struct tdp_iter *iter) + */ + void tdp_iter_next(struct tdp_iter *iter) + { ++ if (iter->yielded) { ++ tdp_iter_restart(iter); ++ return; ++ } ++ + if (try_step_down(iter)) + return; + +diff --git a/arch/x86/kvm/mmu/tdp_iter.h b/arch/x86/kvm/mmu/tdp_iter.h +index b1748b988d3ae..e19cabbcb65c8 100644 +--- a/arch/x86/kvm/mmu/tdp_iter.h ++++ b/arch/x86/kvm/mmu/tdp_iter.h +@@ -45,6 +45,12 @@ struct tdp_iter { + * iterator walks off the end of the paging structure. + */ + bool valid; ++ /* ++ * True if KVM dropped mmu_lock and yielded in the middle of a walk, in ++ * which case tdp_iter_next() needs to restart the walk at the root ++ * level instead of advancing to the next entry. ++ */ ++ bool yielded; + }; + + /* +diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c +index 64ccfc1fa5535..d479b2b121259 100644 +--- a/arch/x86/kvm/mmu/tdp_mmu.c ++++ b/arch/x86/kvm/mmu/tdp_mmu.c +@@ -316,9 +316,6 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, + struct kvm_mmu_page *sp = sptep_to_sp(rcu_dereference(pt)); + int level = sp->role.level; + gfn_t base_gfn = sp->gfn; +- u64 old_child_spte; +- u64 *sptep; +- gfn_t gfn; + int i; + + trace_kvm_mmu_prepare_zap_page(sp); +@@ -326,8 +323,9 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, + tdp_mmu_unlink_page(kvm, sp, shared); + + for (i = 0; i < PT64_ENT_PER_PAGE; i++) { +- sptep = rcu_dereference(pt) + i; +- gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); ++ u64 *sptep = rcu_dereference(pt) + i; ++ gfn_t gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); ++ u64 old_child_spte; + + if (shared) { + /* +@@ -373,7 +371,7 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, + shared); + } + +- kvm_flush_remote_tlbs_with_address(kvm, gfn, ++ kvm_flush_remote_tlbs_with_address(kvm, base_gfn, + KVM_PAGES_PER_HPAGE(level + 1)); + + call_rcu(&sp->rcu_head, tdp_mmu_free_sp_rcu_callback); +@@ -503,6 +501,8 @@ static inline bool tdp_mmu_set_spte_atomic_no_dirty_log(struct kvm *kvm, + struct tdp_iter *iter, + u64 new_spte) + { ++ WARN_ON_ONCE(iter->yielded); ++ + lockdep_assert_held_read(&kvm->mmu_lock); + + /* +@@ -613,6 +613,8 @@ static inline void __tdp_mmu_set_spte(struct kvm *kvm, struct tdp_iter *iter, + u64 new_spte, bool record_acc_track, + bool record_dirty_log) + { ++ WARN_ON_ONCE(iter->yielded); ++ + lockdep_assert_held_write(&kvm->mmu_lock); + + /* +@@ -678,18 +680,19 @@ static inline void tdp_mmu_set_spte_no_dirty_log(struct kvm *kvm, + * If this function should yield and flush is set, it will perform a remote + * TLB flush before yielding. + * +- * If this function yields, it will also reset the tdp_iter's walk over the +- * paging structure and the calling function should skip to the next +- * iteration to allow the iterator to continue its traversal from the +- * paging structure root. ++ * If this function yields, iter->yielded is set and the caller must skip to ++ * the next iteration, where tdp_iter_next() will reset the tdp_iter's walk ++ * over the paging structures to allow the iterator to continue its traversal ++ * from the paging structure root. + * +- * Return true if this function yielded and the iterator's traversal was reset. +- * Return false if a yield was not needed. ++ * Returns true if this function yielded. + */ +-static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm, +- struct tdp_iter *iter, bool flush, +- bool shared) ++static inline bool __must_check tdp_mmu_iter_cond_resched(struct kvm *kvm, ++ struct tdp_iter *iter, ++ bool flush, bool shared) + { ++ WARN_ON(iter->yielded); ++ + /* Ensure forward progress has been made before yielding. */ + if (iter->next_last_level_gfn == iter->yielded_gfn) + return false; +@@ -709,12 +712,10 @@ static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm, + + WARN_ON(iter->gfn > iter->next_last_level_gfn); + +- tdp_iter_restart(iter); +- +- return true; ++ iter->yielded = true; + } + +- return false; ++ return iter->yielded; + } + + /* +@@ -1083,8 +1084,8 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range, + struct kvm_mmu_page *root; + + for_each_tdp_mmu_root(kvm, root, range->slot->as_id) +- flush |= zap_gfn_range(kvm, root, range->start, range->end, +- range->may_block, flush, false); ++ flush = zap_gfn_range(kvm, root, range->start, range->end, ++ range->may_block, flush, false); + + return flush; + } +@@ -1415,10 +1416,9 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, + * Clear leaf entries which could be replaced by large mappings, for + * GFNs within the slot. + */ +-static bool zap_collapsible_spte_range(struct kvm *kvm, ++static void zap_collapsible_spte_range(struct kvm *kvm, + struct kvm_mmu_page *root, +- const struct kvm_memory_slot *slot, +- bool flush) ++ const struct kvm_memory_slot *slot) + { + gfn_t start = slot->base_gfn; + gfn_t end = start + slot->npages; +@@ -1429,10 +1429,8 @@ static bool zap_collapsible_spte_range(struct kvm *kvm, + + tdp_root_for_each_pte(iter, root, start, end) { + retry: +- if (tdp_mmu_iter_cond_resched(kvm, &iter, flush, true)) { +- flush = false; ++ if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true)) + continue; +- } + + if (!is_shadow_present_pte(iter.old_spte) || + !is_last_spte(iter.old_spte, iter.level)) +@@ -1444,6 +1442,7 @@ retry: + pfn, PG_LEVEL_NUM)) + continue; + ++ /* Note, a successful atomic zap also does a remote TLB flush. */ + if (!tdp_mmu_zap_spte_atomic(kvm, &iter)) { + /* + * The iter must explicitly re-read the SPTE because +@@ -1452,30 +1451,24 @@ retry: + iter.old_spte = READ_ONCE(*rcu_dereference(iter.sptep)); + goto retry; + } +- flush = true; + } + + rcu_read_unlock(); +- +- return flush; + } + + /* + * Clear non-leaf entries (and free associated page tables) which could + * be replaced by large mappings, for GFNs within the slot. + */ +-bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, +- const struct kvm_memory_slot *slot, +- bool flush) ++void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, ++ const struct kvm_memory_slot *slot) + { + struct kvm_mmu_page *root; + + lockdep_assert_held_read(&kvm->mmu_lock); + + for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true) +- flush = zap_collapsible_spte_range(kvm, root, slot, flush); +- +- return flush; ++ zap_collapsible_spte_range(kvm, root, slot); + } + + /* +@@ -1500,12 +1493,12 @@ static bool write_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root, + !is_last_spte(iter.old_spte, iter.level)) + continue; + +- if (!is_writable_pte(iter.old_spte)) +- break; +- + new_spte = iter.old_spte & + ~(PT_WRITABLE_MASK | shadow_mmu_writable_mask); + ++ if (new_spte == iter.old_spte) ++ break; ++ + tdp_mmu_set_spte(kvm, &iter, new_spte); + spte_set = true; + } +diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h +index 358f447d40120..ba3681cd38ab4 100644 +--- a/arch/x86/kvm/mmu/tdp_mmu.h ++++ b/arch/x86/kvm/mmu/tdp_mmu.h +@@ -66,9 +66,8 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, + struct kvm_memory_slot *slot, + gfn_t gfn, unsigned long mask, + bool wrprot); +-bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, +- const struct kvm_memory_slot *slot, +- bool flush); ++void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, ++ const struct kvm_memory_slot *slot); + + bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm, + struct kvm_memory_slot *slot, gfn_t gfn, +diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c +index 0772bad9165c5..f256f01056bdb 100644 +--- a/arch/x86/kvm/pmu.c ++++ b/arch/x86/kvm/pmu.c +@@ -95,7 +95,7 @@ static void kvm_perf_overflow_intr(struct perf_event *perf_event, + } + + static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type, +- unsigned config, bool exclude_user, ++ u64 config, bool exclude_user, + bool exclude_kernel, bool intr, + bool in_tx, bool in_tx_cp) + { +@@ -173,8 +173,8 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc) + + void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel) + { +- unsigned config, type = PERF_TYPE_RAW; +- u8 event_select, unit_mask; ++ u64 config; ++ u32 type = PERF_TYPE_RAW; + struct kvm *kvm = pmc->vcpu->kvm; + struct kvm_pmu_event_filter *filter; + int i; +@@ -206,23 +206,18 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel) + if (!allow_event) + return; + +- event_select = eventsel & ARCH_PERFMON_EVENTSEL_EVENT; +- unit_mask = (eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; +- + if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE | + ARCH_PERFMON_EVENTSEL_INV | + ARCH_PERFMON_EVENTSEL_CMASK | + HSW_IN_TX | + HSW_IN_TX_CHECKPOINTED))) { +- config = kvm_x86_ops.pmu_ops->find_arch_event(pmc_to_pmu(pmc), +- event_select, +- unit_mask); ++ config = kvm_x86_ops.pmu_ops->pmc_perf_hw_id(pmc); + if (config != PERF_COUNT_HW_MAX) + type = PERF_TYPE_HARDWARE; + } + + if (type == PERF_TYPE_RAW) +- config = eventsel & X86_RAW_EVENT_MASK; ++ config = eventsel & AMD64_RAW_EVENT_MASK; + + if (pmc->current_config == eventsel && pmc_resume_counter(pmc)) + return; +diff --git a/arch/x86/kvm/pmu.h b/arch/x86/kvm/pmu.h +index 0e4f2b1fa9fbd..a06d95165ac7c 100644 +--- a/arch/x86/kvm/pmu.h ++++ b/arch/x86/kvm/pmu.h +@@ -24,8 +24,7 @@ struct kvm_event_hw_type_mapping { + }; + + struct kvm_pmu_ops { +- unsigned (*find_arch_event)(struct kvm_pmu *pmu, u8 event_select, +- u8 unit_mask); ++ unsigned int (*pmc_perf_hw_id)(struct kvm_pmc *pmc); + unsigned (*find_fixed_event)(int idx); + bool (*pmc_is_enabled)(struct kvm_pmc *pmc); + struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx); +diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c +index 8052d92069e01..cdbb48e12745c 100644 +--- a/arch/x86/kvm/svm/avic.c ++++ b/arch/x86/kvm/svm/avic.c +@@ -342,8 +342,6 @@ int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu) + avic_kick_target_vcpus(vcpu->kvm, apic, icrl, icrh); + break; + case AVIC_IPI_FAILURE_INVALID_TARGET: +- WARN_ONCE(1, "Invalid IPI target: index=%u, vcpu=%d, icr=%#0x:%#0x\n", +- index, vcpu->vcpu_id, icrh, icrl); + break; + case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE: + WARN_ONCE(1, "Invalid backing page\n"); +@@ -988,16 +986,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu) + static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run) + { + struct vcpu_svm *svm = to_svm(vcpu); ++ int cpu = get_cpu(); + ++ WARN_ON(cpu != vcpu->cpu); + svm->avic_is_running = is_run; + +- if (!kvm_vcpu_apicv_active(vcpu)) +- return; +- +- if (is_run) +- avic_vcpu_load(vcpu, vcpu->cpu); +- else +- avic_vcpu_put(vcpu); ++ if (kvm_vcpu_apicv_active(vcpu)) { ++ if (is_run) ++ avic_vcpu_load(vcpu, cpu); ++ else ++ avic_vcpu_put(vcpu); ++ } ++ put_cpu(); + } + + void svm_vcpu_blocking(struct kvm_vcpu *vcpu) +diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c +index 510b833cbd399..556e7a3f35627 100644 +--- a/arch/x86/kvm/svm/nested.c ++++ b/arch/x86/kvm/svm/nested.c +@@ -942,9 +942,9 @@ void svm_free_nested(struct vcpu_svm *svm) + /* + * Forcibly leave nested mode in order to be able to reset the VCPU later on. + */ +-void svm_leave_nested(struct vcpu_svm *svm) ++void svm_leave_nested(struct kvm_vcpu *vcpu) + { +- struct kvm_vcpu *vcpu = &svm->vcpu; ++ struct vcpu_svm *svm = to_svm(vcpu); + + if (is_guest_mode(vcpu)) { + svm->nested.nested_run_pending = 0; +@@ -1313,7 +1313,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, + return -EINVAL; + + if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) { +- svm_leave_nested(svm); ++ svm_leave_nested(vcpu); + svm_set_gif(svm, !!(kvm_state->flags & KVM_STATE_NESTED_GIF_SET)); + return 0; + } +@@ -1357,18 +1357,6 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, + !nested_vmcb_valid_sregs(vcpu, save)) + goto out_free; + +- /* +- * While the nested guest CR3 is already checked and set by +- * KVM_SET_SREGS, it was set when nested state was yet loaded, +- * thus MMU might not be initialized correctly. +- * Set it again to fix this. +- */ +- +- ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3, +- nested_npt_enabled(svm), false); +- if (WARN_ON_ONCE(ret)) +- goto out_free; +- + + /* + * All checks done, we can enter guest mode. Userspace provides +@@ -1378,7 +1366,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, + */ + + if (is_guest_mode(vcpu)) +- svm_leave_nested(svm); ++ svm_leave_nested(vcpu); + else + svm->nested.vmcb02.ptr->save = svm->vmcb01.ptr->save; + +@@ -1394,6 +1382,20 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, + + svm_switch_vmcb(svm, &svm->nested.vmcb02); + nested_vmcb02_prepare_control(svm); ++ ++ /* ++ * While the nested guest CR3 is already checked and set by ++ * KVM_SET_SREGS, it was set when nested state was yet loaded, ++ * thus MMU might not be initialized correctly. ++ * Set it again to fix this. ++ */ ++ ++ ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3, ++ nested_npt_enabled(svm), false); ++ if (WARN_ON_ONCE(ret)) ++ goto out_free; ++ ++ + kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); + ret = 0; + out_free: +@@ -1432,6 +1434,7 @@ static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu) + } + + struct kvm_x86_nested_ops svm_nested_ops = { ++ .leave_nested = svm_leave_nested, + .check_events = svm_check_nested_events, + .triple_fault = nested_svm_triple_fault, + .get_nested_state_pages = svm_get_nested_state_pages, +diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c +index fdf587f19c5fb..06f8034f62e4f 100644 +--- a/arch/x86/kvm/svm/pmu.c ++++ b/arch/x86/kvm/svm/pmu.c +@@ -134,10 +134,10 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, + return &pmu->gp_counters[msr_to_index(msr)]; + } + +-static unsigned amd_find_arch_event(struct kvm_pmu *pmu, +- u8 event_select, +- u8 unit_mask) ++static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc) + { ++ u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT; ++ u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; + int i; + + for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++) +@@ -282,7 +282,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) + pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS; + + pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1; +- pmu->reserved_bits = 0xffffffff00200000ull; ++ pmu->reserved_bits = 0xfffffff000280000ull; + pmu->version = 1; + /* not applicable to AMD; but clean them to prevent any fall out */ + pmu->counter_bitmask[KVM_PMC_FIXED] = 0; +@@ -320,7 +320,7 @@ static void amd_pmu_reset(struct kvm_vcpu *vcpu) + } + + struct kvm_pmu_ops amd_pmu_ops = { +- .find_arch_event = amd_find_arch_event, ++ .pmc_perf_hw_id = amd_pmc_perf_hw_id, + .find_fixed_event = amd_find_fixed_event, + .pmc_is_enabled = amd_pmc_is_enabled, + .pmc_idx_to_pmc = amd_pmc_idx_to_pmc, +diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c +index 7e34d7163adab..134c4ea5e6ad8 100644 +--- a/arch/x86/kvm/svm/sev.c ++++ b/arch/x86/kvm/svm/sev.c +@@ -1787,7 +1787,12 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) + mutex_unlock(&source_kvm->lock); + mutex_lock(&kvm->lock); + +- if (sev_guest(kvm)) { ++ /* ++ * Disallow out-of-band SEV/SEV-ES init if the target is already an ++ * SEV guest, or if vCPUs have been created. KVM relies on vCPUs being ++ * created after SEV/SEV-ES initialization, e.g. to init intercepts. ++ */ ++ if (sev_guest(kvm) || kvm->created_vcpus) { + ret = -EINVAL; + goto e_mirror_unlock; + } +@@ -1800,6 +1805,7 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) + mirror_sev->fd = source_sev.fd; + mirror_sev->es_active = source_sev.es_active; + mirror_sev->handle = source_sev.handle; ++ INIT_LIST_HEAD(&mirror_sev->regions_list); + /* + * Do not copy ap_jump_table. Since the mirror does not share the same + * KVM contexts as the original, and they may have different +@@ -2311,7 +2317,7 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) + } + + #define GHCB_SCRATCH_AREA_LIMIT (16ULL * PAGE_SIZE) +-static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) ++static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) + { + struct vmcb_control_area *control = &svm->vmcb->control; + struct ghcb *ghcb = svm->ghcb; +@@ -2322,14 +2328,14 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) + scratch_gpa_beg = ghcb_get_sw_scratch(ghcb); + if (!scratch_gpa_beg) { + pr_err("vmgexit: scratch gpa not provided\n"); +- return false; ++ return -EINVAL; + } + + scratch_gpa_end = scratch_gpa_beg + len; + if (scratch_gpa_end < scratch_gpa_beg) { + pr_err("vmgexit: scratch length (%#llx) not valid for scratch address (%#llx)\n", + len, scratch_gpa_beg); +- return false; ++ return -EINVAL; + } + + if ((scratch_gpa_beg & PAGE_MASK) == control->ghcb_gpa) { +@@ -2347,7 +2353,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) + scratch_gpa_end > ghcb_scratch_end) { + pr_err("vmgexit: scratch area is outside of GHCB shared buffer area (%#llx - %#llx)\n", + scratch_gpa_beg, scratch_gpa_end); +- return false; ++ return -EINVAL; + } + + scratch_va = (void *)svm->ghcb; +@@ -2360,18 +2366,18 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) + if (len > GHCB_SCRATCH_AREA_LIMIT) { + pr_err("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n", + len, GHCB_SCRATCH_AREA_LIMIT); +- return false; ++ return -EINVAL; + } + scratch_va = kzalloc(len, GFP_KERNEL_ACCOUNT); + if (!scratch_va) +- return false; ++ return -ENOMEM; + + if (kvm_read_guest(svm->vcpu.kvm, scratch_gpa_beg, scratch_va, len)) { + /* Unable to copy scratch area from guest */ + pr_err("vmgexit: kvm_read_guest for scratch area failed\n"); + + kfree(scratch_va); +- return false; ++ return -EFAULT; + } + + /* +@@ -2387,7 +2393,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) + svm->ghcb_sa = scratch_va; + svm->ghcb_sa_len = len; + +- return true; ++ return 0; + } + + static void set_ghcb_msr_bits(struct vcpu_svm *svm, u64 value, u64 mask, +@@ -2526,10 +2532,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) + ghcb_set_sw_exit_info_1(ghcb, 0); + ghcb_set_sw_exit_info_2(ghcb, 0); + +- ret = -EINVAL; + switch (exit_code) { + case SVM_VMGEXIT_MMIO_READ: +- if (!setup_vmgexit_scratch(svm, true, control->exit_info_2)) ++ ret = setup_vmgexit_scratch(svm, true, control->exit_info_2); ++ if (ret) + break; + + ret = kvm_sev_es_mmio_read(vcpu, +@@ -2538,7 +2544,8 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) + svm->ghcb_sa); + break; + case SVM_VMGEXIT_MMIO_WRITE: +- if (!setup_vmgexit_scratch(svm, false, control->exit_info_2)) ++ ret = setup_vmgexit_scratch(svm, false, control->exit_info_2); ++ if (ret) + break; + + ret = kvm_sev_es_mmio_write(vcpu, +@@ -2581,6 +2588,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) + vcpu_unimpl(vcpu, + "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n", + control->exit_info_1, control->exit_info_2); ++ ret = -EINVAL; + break; + default: + ret = svm_invoke_exit_handler(vcpu, exit_code); +@@ -2593,6 +2601,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) + { + int count; + int bytes; ++ int r; + + if (svm->vmcb->control.exit_info_2 > INT_MAX) + return -EINVAL; +@@ -2601,8 +2610,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) + if (unlikely(check_mul_overflow(count, size, &bytes))) + return -EINVAL; + +- if (!setup_vmgexit_scratch(svm, in, bytes)) +- return -EINVAL; ++ r = setup_vmgexit_scratch(svm, in, bytes); ++ if (r) ++ return r; + + return kvm_sev_es_string_io(&svm->vcpu, size, port, svm->ghcb_sa, count, in); + } +diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c +index 989685098b3ea..26f2da1590eda 100644 +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -281,7 +281,7 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) + + if ((old_efer & EFER_SVME) != (efer & EFER_SVME)) { + if (!(efer & EFER_SVME)) { +- svm_leave_nested(svm); ++ svm_leave_nested(vcpu); + svm_set_gif(svm, true); + /* #GP intercept is still needed for vmware backdoor */ + if (!enable_vmware_backdoor) +@@ -303,7 +303,11 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) + return ret; + } + +- if (svm_gp_erratum_intercept) ++ /* ++ * Never intercept #GP for SEV guests, KVM can't ++ * decrypt guest memory to workaround the erratum. ++ */ ++ if (svm_gp_erratum_intercept && !sev_guest(vcpu->kvm)) + set_exception_intercept(svm, GP_VECTOR); + } + } +@@ -1176,9 +1180,10 @@ static void init_vmcb(struct kvm_vcpu *vcpu) + * Guest access to VMware backdoor ports could legitimately + * trigger #GP because of TSS I/O permission bitmap. + * We intercept those #GP and allow access to them anyway +- * as VMware does. ++ * as VMware does. Don't intercept #GP for SEV guests as KVM can't ++ * decrypt guest memory to decode the faulting instruction. + */ +- if (enable_vmware_backdoor) ++ if (enable_vmware_backdoor && !sev_guest(vcpu->kvm)) + set_exception_intercept(svm, GP_VECTOR); + + svm_set_intercept(svm, INTERCEPT_INTR); +@@ -1517,6 +1522,15 @@ static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) + to_svm(vcpu)->vmcb->save.rflags = rflags; + } + ++static bool svm_get_if_flag(struct kvm_vcpu *vcpu) ++{ ++ struct vmcb *vmcb = to_svm(vcpu)->vmcb; ++ ++ return sev_es_guest(vcpu->kvm) ++ ? vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK ++ : kvm_get_rflags(vcpu) & X86_EFLAGS_IF; ++} ++ + static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg) + { + switch (reg) { +@@ -1713,6 +1727,7 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) + { + struct vcpu_svm *svm = to_svm(vcpu); + u64 hcr0 = cr0; ++ bool old_paging = is_paging(vcpu); + + #ifdef CONFIG_X86_64 + if (vcpu->arch.efer & EFER_LME && !vcpu->arch.guest_state_protected) { +@@ -1729,8 +1744,11 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) + #endif + vcpu->arch.cr0 = cr0; + +- if (!npt_enabled) ++ if (!npt_enabled) { + hcr0 |= X86_CR0_PG | X86_CR0_WP; ++ if (old_paging != is_paging(vcpu)) ++ svm_set_cr4(vcpu, kvm_read_cr4(vcpu)); ++ } + + /* + * re-enable caching here because the QEMU bios +@@ -1774,8 +1792,12 @@ void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) + svm_flush_tlb(vcpu); + + vcpu->arch.cr4 = cr4; +- if (!npt_enabled) ++ if (!npt_enabled) { + cr4 |= X86_CR4_PAE; ++ ++ if (!is_paging(vcpu)) ++ cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE); ++ } + cr4 |= host_cr4_mce; + to_svm(vcpu)->vmcb->save.cr4 = cr4; + vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR); +@@ -2224,10 +2246,6 @@ static int gp_interception(struct kvm_vcpu *vcpu) + if (error_code) + goto reinject; + +- /* All SVM instructions expect page aligned RAX */ +- if (svm->vmcb->save.rax & ~PAGE_MASK) +- goto reinject; +- + /* Decode the instruction for usage later */ + if (x86_decode_emulated_instruction(vcpu, 0, NULL, 0) != EMULATION_OK) + goto reinject; +@@ -2245,8 +2263,13 @@ static int gp_interception(struct kvm_vcpu *vcpu) + if (!is_guest_mode(vcpu)) + return kvm_emulate_instruction(vcpu, + EMULTYPE_VMWARE_GP | EMULTYPE_NO_DECODE); +- } else ++ } else { ++ /* All SVM instructions expect page aligned RAX */ ++ if (svm->vmcb->save.rax & ~PAGE_MASK) ++ goto reinject; ++ + return emulate_svm_instr(vcpu, opcode); ++ } + + reinject: + kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); +@@ -3485,14 +3508,7 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu) + if (!gif_set(svm)) + return true; + +- if (sev_es_guest(vcpu->kvm)) { +- /* +- * SEV-ES guests to not expose RFLAGS. Use the VMCB interrupt mask +- * bit to determine the state of the IF flag. +- */ +- if (!(vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK)) +- return true; +- } else if (is_guest_mode(vcpu)) { ++ if (is_guest_mode(vcpu)) { + /* As long as interrupts are being delivered... */ + if ((svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK) + ? !(svm->vmcb01.ptr->save.rflags & X86_EFLAGS_IF) +@@ -3503,7 +3519,7 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu) + if (nested_exit_on_intr(svm)) + return false; + } else { +- if (!(kvm_get_rflags(vcpu) & X86_EFLAGS_IF)) ++ if (!svm_get_if_flag(vcpu)) + return true; + } + +@@ -4376,10 +4392,17 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) + * Enter the nested guest now + */ + ++ vmcb_mark_all_dirty(svm->vmcb01.ptr); ++ + vmcb12 = map.hva; + nested_load_control_from_vmcb12(svm, &vmcb12->control); + ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false); + ++ if (ret) ++ goto unmap_save; ++ ++ svm->nested.nested_run_pending = 1; ++ + unmap_save: + kvm_vcpu_unmap(vcpu, &map_save, true); + unmap_map: +@@ -4405,8 +4428,13 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, void *insn, int i + bool smep, smap, is_user; + unsigned long cr4; + ++ /* Emulation is always possible when KVM has access to all guest state. */ ++ if (!sev_guest(vcpu->kvm)) ++ return true; ++ + /* +- * When the guest is an SEV-ES guest, emulation is not possible. ++ * Emulation is impossible for SEV-ES guests as KVM doesn't have access ++ * to guest register state. + */ + if (sev_es_guest(vcpu->kvm)) + return false; +@@ -4454,23 +4482,27 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, void *insn, int i + if (likely(!insn || insn_len)) + return true; + +- /* +- * If RIP is invalid, go ahead with emulation which will cause an +- * internal error exit. +- */ +- if (!kvm_vcpu_gfn_to_memslot(vcpu, kvm_rip_read(vcpu) >> PAGE_SHIFT)) +- return true; +- + cr4 = kvm_read_cr4(vcpu); + smep = cr4 & X86_CR4_SMEP; + smap = cr4 & X86_CR4_SMAP; + is_user = svm_get_cpl(vcpu) == 3; + if (smap && (!smep || is_user)) { +- if (!sev_guest(vcpu->kvm)) +- return true; +- + pr_err_ratelimited("KVM: SEV Guest triggered AMD Erratum 1096\n"); +- kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); ++ ++ /* ++ * If the fault occurred in userspace, arbitrarily inject #GP ++ * to avoid killing the guest and to hopefully avoid confusing ++ * the guest kernel too much, e.g. injecting #PF would not be ++ * coherent with respect to the guest's page tables. Request ++ * triple fault if the fault occurred in the kernel as there's ++ * no fault that KVM can inject without confusing the guest. ++ * In practice, the triple fault is moot as no sane SEV kernel ++ * will execute from user memory while also running with SMAP=1. ++ */ ++ if (is_user) ++ kvm_inject_gp(vcpu, 0); ++ else ++ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + } + + return false; +@@ -4562,6 +4594,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { + .cache_reg = svm_cache_reg, + .get_rflags = svm_get_rflags, + .set_rflags = svm_set_rflags, ++ .get_if_flag = svm_get_if_flag, + + .tlb_flush_all = svm_flush_tlb, + .tlb_flush_current = svm_flush_tlb, +@@ -4592,7 +4625,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { + .load_eoi_exitmap = svm_load_eoi_exitmap, + .hwapic_irr_update = svm_hwapic_irr_update, + .hwapic_isr_update = svm_hwapic_isr_update, +- .sync_pir_to_irr = kvm_lapic_find_highest_irr, + .apicv_post_state_restore = avic_post_state_restore, + + .set_tss_addr = svm_set_tss_addr, +diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h +index 5d30db599e10d..ff0855c03c917 100644 +--- a/arch/x86/kvm/svm/svm.h ++++ b/arch/x86/kvm/svm/svm.h +@@ -461,7 +461,7 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *svm) + + int enter_svm_guest_mode(struct kvm_vcpu *vcpu, + u64 vmcb_gpa, struct vmcb *vmcb12, bool from_vmrun); +-void svm_leave_nested(struct vcpu_svm *svm); ++void svm_leave_nested(struct kvm_vcpu *vcpu); + void svm_free_nested(struct vcpu_svm *svm); + int svm_allocate_nested(struct vcpu_svm *svm); + int nested_svm_vmrun(struct kvm_vcpu *vcpu); +diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c +index ba6f99f584ac3..a7ed30d5647af 100644 +--- a/arch/x86/kvm/vmx/evmcs.c ++++ b/arch/x86/kvm/vmx/evmcs.c +@@ -362,6 +362,7 @@ void nested_evmcs_filter_control_msr(u32 msr_index, u64 *pdata) + case MSR_IA32_VMX_PROCBASED_CTLS2: + ctl_high &= ~EVMCS1_UNSUPPORTED_2NDEXEC; + break; ++ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: + case MSR_IA32_VMX_PINBASED_CTLS: + ctl_high &= ~EVMCS1_UNSUPPORTED_PINCTRL; + break; +diff --git a/arch/x86/kvm/vmx/evmcs.h b/arch/x86/kvm/vmx/evmcs.h +index 152ab0aa82cf6..b43976e4b9636 100644 +--- a/arch/x86/kvm/vmx/evmcs.h ++++ b/arch/x86/kvm/vmx/evmcs.h +@@ -59,7 +59,9 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs); + SECONDARY_EXEC_SHADOW_VMCS | \ + SECONDARY_EXEC_TSC_SCALING | \ + SECONDARY_EXEC_PAUSE_LOOP_EXITING) +-#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL (VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) ++#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL \ ++ (VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | \ ++ VM_EXIT_SAVE_VMX_PREEMPTION_TIMER) + #define EVMCS1_UNSUPPORTED_VMENTRY_CTRL (VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) + #define EVMCS1_UNSUPPORTED_VMFUNC (VMX_VMFUNC_EPTP_SWITCHING) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index eedcebf580041..a0193b11c381d 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -523,29 +523,6 @@ static int nested_vmx_check_tpr_shadow_controls(struct kvm_vcpu *vcpu, + return 0; + } + +-/* +- * Check if MSR is intercepted for L01 MSR bitmap. +- */ +-static bool msr_write_intercepted_l01(struct kvm_vcpu *vcpu, u32 msr) +-{ +- unsigned long *msr_bitmap; +- int f = sizeof(unsigned long); +- +- if (!cpu_has_vmx_msr_bitmap()) +- return true; +- +- msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap; +- +- if (msr <= 0x1fff) { +- return !!test_bit(msr, msr_bitmap + 0x800 / f); +- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { +- msr &= 0x1fff; +- return !!test_bit(msr, msr_bitmap + 0xc00 / f); +- } +- +- return true; +-} +- + /* + * If a msr is allowed by L0, we should check whether it is allowed by L1. + * The corresponding bit will be cleared unless both of L0 and L1 allow it. +@@ -599,6 +576,34 @@ static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) + } + } + ++#define BUILD_NVMX_MSR_INTERCEPT_HELPER(rw) \ ++static inline \ ++void nested_vmx_set_msr_##rw##_intercept(struct vcpu_vmx *vmx, \ ++ unsigned long *msr_bitmap_l1, \ ++ unsigned long *msr_bitmap_l0, u32 msr) \ ++{ \ ++ if (vmx_test_msr_bitmap_##rw(vmx->vmcs01.msr_bitmap, msr) || \ ++ vmx_test_msr_bitmap_##rw(msr_bitmap_l1, msr)) \ ++ vmx_set_msr_bitmap_##rw(msr_bitmap_l0, msr); \ ++ else \ ++ vmx_clear_msr_bitmap_##rw(msr_bitmap_l0, msr); \ ++} ++BUILD_NVMX_MSR_INTERCEPT_HELPER(read) ++BUILD_NVMX_MSR_INTERCEPT_HELPER(write) ++ ++static inline void nested_vmx_set_intercept_for_msr(struct vcpu_vmx *vmx, ++ unsigned long *msr_bitmap_l1, ++ unsigned long *msr_bitmap_l0, ++ u32 msr, int types) ++{ ++ if (types & MSR_TYPE_R) ++ nested_vmx_set_msr_read_intercept(vmx, msr_bitmap_l1, ++ msr_bitmap_l0, msr); ++ if (types & MSR_TYPE_W) ++ nested_vmx_set_msr_write_intercept(vmx, msr_bitmap_l1, ++ msr_bitmap_l0, msr); ++} ++ + /* + * Merge L0's and L1's MSR bitmap, return false to indicate that + * we do not use the hardware. +@@ -606,10 +611,11 @@ static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) + static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12) + { ++ struct vcpu_vmx *vmx = to_vmx(vcpu); + int msr; + unsigned long *msr_bitmap_l1; +- unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap; +- struct kvm_host_map *map = &to_vmx(vcpu)->nested.msr_bitmap_map; ++ unsigned long *msr_bitmap_l0 = vmx->nested.vmcs02.msr_bitmap; ++ struct kvm_host_map *map = &vmx->nested.msr_bitmap_map; + + /* Nothing to do if the MSR bitmap is not in use. */ + if (!cpu_has_vmx_msr_bitmap() || +@@ -660,44 +666,27 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, + } + } + +- /* KVM unconditionally exposes the FS/GS base MSRs to L1. */ ++ /* ++ * Always check vmcs01's bitmap to honor userspace MSR filters and any ++ * other runtime changes to vmcs01's bitmap, e.g. dynamic pass-through. ++ */ + #ifdef CONFIG_X86_64 +- nested_vmx_disable_intercept_for_msr(msr_bitmap_l1, msr_bitmap_l0, +- MSR_FS_BASE, MSR_TYPE_RW); ++ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, ++ MSR_FS_BASE, MSR_TYPE_RW); + +- nested_vmx_disable_intercept_for_msr(msr_bitmap_l1, msr_bitmap_l0, +- MSR_GS_BASE, MSR_TYPE_RW); ++ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, ++ MSR_GS_BASE, MSR_TYPE_RW); + +- nested_vmx_disable_intercept_for_msr(msr_bitmap_l1, msr_bitmap_l0, +- MSR_KERNEL_GS_BASE, MSR_TYPE_RW); ++ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, ++ MSR_KERNEL_GS_BASE, MSR_TYPE_RW); + #endif ++ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, ++ MSR_IA32_SPEC_CTRL, MSR_TYPE_RW); + +- /* +- * Checking the L0->L1 bitmap is trying to verify two things: +- * +- * 1. L0 gave a permission to L1 to actually passthrough the MSR. This +- * ensures that we do not accidentally generate an L02 MSR bitmap +- * from the L12 MSR bitmap that is too permissive. +- * 2. That L1 or L2s have actually used the MSR. This avoids +- * unnecessarily merging of the bitmap if the MSR is unused. This +- * works properly because we only update the L01 MSR bitmap lazily. +- * So even if L0 should pass L1 these MSRs, the L01 bitmap is only +- * updated to reflect this when L1 (or its L2s) actually write to +- * the MSR. +- */ +- if (!msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL)) +- nested_vmx_disable_intercept_for_msr( +- msr_bitmap_l1, msr_bitmap_l0, +- MSR_IA32_SPEC_CTRL, +- MSR_TYPE_R | MSR_TYPE_W); +- +- if (!msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD)) +- nested_vmx_disable_intercept_for_msr( +- msr_bitmap_l1, msr_bitmap_l0, +- MSR_IA32_PRED_CMD, +- MSR_TYPE_W); ++ nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0, ++ MSR_IA32_PRED_CMD, MSR_TYPE_W); + +- kvm_vcpu_unmap(vcpu, &to_vmx(vcpu)->nested.msr_bitmap_map, false); ++ kvm_vcpu_unmap(vcpu, &vmx->nested.msr_bitmap_map, false); + + return true; + } +@@ -1191,29 +1180,26 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu, + WARN_ON(!enable_vpid); + + /* +- * If VPID is enabled and used by vmc12, but L2 does not have a unique +- * TLB tag (ASID), i.e. EPT is disabled and KVM was unable to allocate +- * a VPID for L2, flush the current context as the effective ASID is +- * common to both L1 and L2. +- * +- * Defer the flush so that it runs after vmcs02.EPTP has been set by +- * KVM_REQ_LOAD_MMU_PGD (if nested EPT is enabled) and to avoid +- * redundant flushes further down the nested pipeline. +- * +- * If a TLB flush isn't required due to any of the above, and vpid12 is +- * changing then the new "virtual" VPID (vpid12) will reuse the same +- * "real" VPID (vpid02), and so needs to be flushed. There's no direct +- * mapping between vpid02 and vpid12, vpid02 is per-vCPU and reused for +- * all nested vCPUs. Remember, a flush on VM-Enter does not invalidate +- * guest-physical mappings, so there is no need to sync the nEPT MMU. ++ * VPID is enabled and in use by vmcs12. If vpid12 is changing, then ++ * emulate a guest TLB flush as KVM does not track vpid12 history nor ++ * is the VPID incorporated into the MMU context. I.e. KVM must assume ++ * that the new vpid12 has never been used and thus represents a new ++ * guest ASID that cannot have entries in the TLB. + */ +- if (!nested_has_guest_tlb_tag(vcpu)) { +- kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); +- } else if (is_vmenter && +- vmcs12->virtual_processor_id != vmx->nested.last_vpid) { ++ if (is_vmenter && vmcs12->virtual_processor_id != vmx->nested.last_vpid) { + vmx->nested.last_vpid = vmcs12->virtual_processor_id; +- vpid_sync_context(nested_get_vpid02(vcpu)); ++ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); ++ return; + } ++ ++ /* ++ * If VPID is enabled, used by vmc12, and vpid12 is not changing but ++ * does not have a unique TLB tag (ASID), i.e. EPT is disabled and ++ * KVM was unable to allocate a VPID for L2, flush the current context ++ * as the effective ASID is common to both L1 and L2. ++ */ ++ if (!nested_has_guest_tlb_tag(vcpu)) ++ kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); + } + + static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask) +@@ -2623,8 +2609,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, + + if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && + WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, +- vmcs12->guest_ia32_perf_global_ctrl))) ++ vmcs12->guest_ia32_perf_global_ctrl))) { ++ *entry_failure_code = ENTRY_FAIL_DEFAULT; + return -EINVAL; ++ } + + kvm_rsp_write(vcpu, vmcs12->guest_rsp); + kvm_rip_write(vcpu, vmcs12->guest_rip); +@@ -2865,6 +2853,17 @@ static int nested_vmx_check_controls(struct kvm_vcpu *vcpu, + return 0; + } + ++static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu, ++ struct vmcs12 *vmcs12) ++{ ++#ifdef CONFIG_X86_64 ++ if (CC(!!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE) != ++ !!(vcpu->arch.efer & EFER_LMA))) ++ return -EINVAL; ++#endif ++ return 0; ++} ++ + static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12) + { +@@ -2889,18 +2888,16 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu, + return -EINVAL; + + #ifdef CONFIG_X86_64 +- ia32e = !!(vcpu->arch.efer & EFER_LMA); ++ ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE); + #else + ia32e = false; + #endif + + if (ia32e) { +- if (CC(!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)) || +- CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) ++ if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE))) + return -EINVAL; + } else { +- if (CC(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE) || +- CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) || ++ if (CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) || + CC(vmcs12->host_cr4 & X86_CR4_PCIDE) || + CC((vmcs12->host_rip) >> 32)) + return -EINVAL; +@@ -3360,8 +3357,7 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, + }; + u32 failed_index; + +- if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) +- kvm_vcpu_flush_tlb_current(vcpu); ++ kvm_service_local_tlb_flush_requests(vcpu); + + evaluate_pending_interrupts = exec_controls_get(vmx) & + (CPU_BASED_INTR_WINDOW_EXITING | CPU_BASED_NMI_WINDOW_EXITING); +@@ -3570,6 +3566,9 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) + if (nested_vmx_check_controls(vcpu, vmcs12)) + return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); + ++ if (nested_vmx_check_address_space_size(vcpu, vmcs12)) ++ return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); ++ + if (nested_vmx_check_host_state(vcpu, vmcs12)) + return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD); + +@@ -4515,9 +4514,8 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, + (void)nested_get_evmcs_page(vcpu); + } + +- /* Service the TLB flush request for L2 before switching to L1. */ +- if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) +- kvm_vcpu_flush_tlb_current(vcpu); ++ /* Service pending TLB flush requests for L2 before switching to L1. */ ++ kvm_service_local_tlb_flush_requests(vcpu); + + /* + * VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between +@@ -6750,6 +6748,7 @@ __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *)) + } + + struct kvm_x86_nested_ops vmx_nested_ops = { ++ .leave_nested = vmx_leave_nested, + .check_events = vmx_check_nested_events, + .hv_timer_pending = nested_vmx_preemption_timer_pending, + .triple_fault = nested_vmx_triple_fault, +diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c +index 10cc4f65c4efd..6427d95de01cf 100644 +--- a/arch/x86/kvm/vmx/pmu_intel.c ++++ b/arch/x86/kvm/vmx/pmu_intel.c +@@ -68,10 +68,11 @@ static void global_ctrl_changed(struct kvm_pmu *pmu, u64 data) + reprogram_counter(pmu, bit); + } + +-static unsigned intel_find_arch_event(struct kvm_pmu *pmu, +- u8 event_select, +- u8 unit_mask) ++static unsigned int intel_pmc_perf_hw_id(struct kvm_pmc *pmc) + { ++ struct kvm_pmu *pmu = pmc_to_pmu(pmc); ++ u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT; ++ u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; + int i; + + for (i = 0; i < ARRAY_SIZE(intel_arch_events); i++) +@@ -706,7 +707,7 @@ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu) + } + + struct kvm_pmu_ops intel_pmu_ops = { +- .find_arch_event = intel_find_arch_event, ++ .pmc_perf_hw_id = intel_pmc_perf_hw_id, + .find_fixed_event = intel_find_fixed_event, + .pmc_is_enabled = intel_pmc_is_enabled, + .pmc_idx_to_pmc = intel_pmc_idx_to_pmc, +diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c +index 5f81ef092bd43..46fb83d6a286e 100644 +--- a/arch/x86/kvm/vmx/posted_intr.c ++++ b/arch/x86/kvm/vmx/posted_intr.c +@@ -5,6 +5,7 @@ + #include <asm/cpu.h> + + #include "lapic.h" ++#include "irq.h" + #include "posted_intr.h" + #include "trace.h" + #include "vmx.h" +@@ -14,7 +15,7 @@ + * can find which vCPU should be waken up. + */ + static DEFINE_PER_CPU(struct list_head, blocked_vcpu_on_cpu); +-static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock); ++static DEFINE_PER_CPU(raw_spinlock_t, blocked_vcpu_on_cpu_lock); + + static inline struct pi_desc *vcpu_to_pi_desc(struct kvm_vcpu *vcpu) + { +@@ -50,7 +51,7 @@ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu) + + /* The full case. */ + do { +- old.control = new.control = pi_desc->control; ++ old.control = new.control = READ_ONCE(pi_desc->control); + + dest = cpu_physical_id(cpu); + +@@ -77,13 +78,18 @@ after_clear_sn: + pi_set_on(pi_desc); + } + ++static bool vmx_can_use_vtd_pi(struct kvm *kvm) ++{ ++ return irqchip_in_kernel(kvm) && enable_apicv && ++ kvm_arch_has_assigned_device(kvm) && ++ irq_remapping_cap(IRQ_POSTING_CAP); ++} ++ + void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu) + { + struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); + +- if (!kvm_arch_has_assigned_device(vcpu->kvm) || +- !irq_remapping_cap(IRQ_POSTING_CAP) || +- !kvm_vcpu_apicv_active(vcpu)) ++ if (!vmx_can_use_vtd_pi(vcpu->kvm)) + return; + + /* Set SN when the vCPU is preempted */ +@@ -98,7 +104,7 @@ static void __pi_post_block(struct kvm_vcpu *vcpu) + unsigned int dest; + + do { +- old.control = new.control = pi_desc->control; ++ old.control = new.control = READ_ONCE(pi_desc->control); + WARN(old.nv != POSTED_INTR_WAKEUP_VECTOR, + "Wakeup handler not enabled while the VCPU is blocked\n"); + +@@ -115,9 +121,9 @@ static void __pi_post_block(struct kvm_vcpu *vcpu) + new.control) != old.control); + + if (!WARN_ON_ONCE(vcpu->pre_pcpu == -1)) { +- spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); ++ raw_spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); + list_del(&vcpu->blocked_vcpu_list); +- spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); ++ raw_spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); + vcpu->pre_pcpu = -1; + } + } +@@ -141,24 +147,23 @@ int pi_pre_block(struct kvm_vcpu *vcpu) + struct pi_desc old, new; + struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); + +- if (!kvm_arch_has_assigned_device(vcpu->kvm) || +- !irq_remapping_cap(IRQ_POSTING_CAP) || +- !kvm_vcpu_apicv_active(vcpu)) ++ if (!vmx_can_use_vtd_pi(vcpu->kvm) || ++ vmx_interrupt_blocked(vcpu)) + return 0; + + WARN_ON(irqs_disabled()); + local_irq_disable(); + if (!WARN_ON_ONCE(vcpu->pre_pcpu != -1)) { + vcpu->pre_pcpu = vcpu->cpu; +- spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); ++ raw_spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); + list_add_tail(&vcpu->blocked_vcpu_list, + &per_cpu(blocked_vcpu_on_cpu, + vcpu->pre_pcpu)); +- spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); ++ raw_spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, vcpu->pre_pcpu)); + } + + do { +- old.control = new.control = pi_desc->control; ++ old.control = new.control = READ_ONCE(pi_desc->control); + + WARN((pi_desc->sn == 1), + "Warning: SN field of posted-interrupts " +@@ -211,7 +216,7 @@ void pi_wakeup_handler(void) + struct kvm_vcpu *vcpu; + int cpu = smp_processor_id(); + +- spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu)); ++ raw_spin_lock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu)); + list_for_each_entry(vcpu, &per_cpu(blocked_vcpu_on_cpu, cpu), + blocked_vcpu_list) { + struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); +@@ -219,13 +224,13 @@ void pi_wakeup_handler(void) + if (pi_test_on(pi_desc) == 1) + kvm_vcpu_kick(vcpu); + } +- spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu)); ++ raw_spin_unlock(&per_cpu(blocked_vcpu_on_cpu_lock, cpu)); + } + + void __init pi_init_cpu(int cpu) + { + INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu)); +- spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu)); ++ raw_spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu)); + } + + bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu) +@@ -270,9 +275,7 @@ int pi_update_irte(struct kvm *kvm, unsigned int host_irq, uint32_t guest_irq, + struct vcpu_data vcpu_info; + int idx, ret = 0; + +- if (!kvm_arch_has_assigned_device(kvm) || +- !irq_remapping_cap(IRQ_POSTING_CAP) || +- !kvm_vcpu_apicv_active(kvm->vcpus[0])) ++ if (!vmx_can_use_vtd_pi(kvm)) + return 0; + + idx = srcu_read_lock(&kvm->irq_srcu); +diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c +index 7d595effb66f0..322485ab9271c 100644 +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -769,24 +769,13 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu) + /* + * Check if MSR is intercepted for currently loaded MSR bitmap. + */ +-static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr) ++static bool msr_write_intercepted(struct vcpu_vmx *vmx, u32 msr) + { +- unsigned long *msr_bitmap; +- int f = sizeof(unsigned long); +- +- if (!cpu_has_vmx_msr_bitmap()) ++ if (!(exec_controls_get(vmx) & CPU_BASED_USE_MSR_BITMAPS)) + return true; + +- msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap; +- +- if (msr <= 0x1fff) { +- return !!test_bit(msr, msr_bitmap + 0x800 / f); +- } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) { +- msr &= 0x1fff; +- return !!test_bit(msr, msr_bitmap + 0xc00 / f); +- } +- +- return true; ++ return vmx_test_msr_bitmap_write(vmx->loaded_vmcs->msr_bitmap, ++ MSR_IA32_SPEC_CTRL); + } + + static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx, +@@ -1370,6 +1359,11 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) + vmx->emulation_required = vmx_emulation_required(vcpu); + } + ++static bool vmx_get_if_flag(struct kvm_vcpu *vcpu) ++{ ++ return vmx_get_rflags(vcpu) & X86_EFLAGS_IF; ++} ++ + u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu) + { + u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); +@@ -2927,6 +2921,13 @@ static void vmx_flush_tlb_all(struct kvm_vcpu *vcpu) + } + } + ++static inline int vmx_get_current_vpid(struct kvm_vcpu *vcpu) ++{ ++ if (is_guest_mode(vcpu)) ++ return nested_get_vpid02(vcpu); ++ return to_vmx(vcpu)->vpid; ++} ++ + static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) + { + struct kvm_mmu *mmu = vcpu->arch.mmu; +@@ -2939,31 +2940,29 @@ static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) + if (enable_ept) + ept_sync_context(construct_eptp(vcpu, root_hpa, + mmu->shadow_root_level)); +- else if (!is_guest_mode(vcpu)) +- vpid_sync_context(to_vmx(vcpu)->vpid); + else +- vpid_sync_context(nested_get_vpid02(vcpu)); ++ vpid_sync_context(vmx_get_current_vpid(vcpu)); + } + + static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr) + { + /* +- * vpid_sync_vcpu_addr() is a nop if vmx->vpid==0, see the comment in ++ * vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in + * vmx_flush_tlb_guest() for an explanation of why this is ok. + */ +- vpid_sync_vcpu_addr(to_vmx(vcpu)->vpid, addr); ++ vpid_sync_vcpu_addr(vmx_get_current_vpid(vcpu), addr); + } + + static void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu) + { + /* +- * vpid_sync_context() is a nop if vmx->vpid==0, e.g. if enable_vpid==0 +- * or a vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit +- * are required to flush GVA->{G,H}PA mappings from the TLB if vpid is ++ * vpid_sync_context() is a nop if vpid==0, e.g. if enable_vpid==0 or a ++ * vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit are ++ * required to flush GVA->{G,H}PA mappings from the TLB if vpid is + * disabled (VM-Enter with vpid enabled and vpid==0 is disallowed), + * i.e. no explicit INVVPID is necessary. + */ +- vpid_sync_context(to_vmx(vcpu)->vpid); ++ vpid_sync_context(vmx_get_current_vpid(vcpu)); + } + + void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu) +@@ -3695,46 +3694,6 @@ void free_vpid(int vpid) + spin_unlock(&vmx_vpid_lock); + } + +-static void vmx_clear_msr_bitmap_read(ulong *msr_bitmap, u32 msr) +-{ +- int f = sizeof(unsigned long); +- +- if (msr <= 0x1fff) +- __clear_bit(msr, msr_bitmap + 0x000 / f); +- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) +- __clear_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); +-} +- +-static void vmx_clear_msr_bitmap_write(ulong *msr_bitmap, u32 msr) +-{ +- int f = sizeof(unsigned long); +- +- if (msr <= 0x1fff) +- __clear_bit(msr, msr_bitmap + 0x800 / f); +- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) +- __clear_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); +-} +- +-static void vmx_set_msr_bitmap_read(ulong *msr_bitmap, u32 msr) +-{ +- int f = sizeof(unsigned long); +- +- if (msr <= 0x1fff) +- __set_bit(msr, msr_bitmap + 0x000 / f); +- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) +- __set_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); +-} +- +-static void vmx_set_msr_bitmap_write(ulong *msr_bitmap, u32 msr) +-{ +- int f = sizeof(unsigned long); +- +- if (msr <= 0x1fff) +- __set_bit(msr, msr_bitmap + 0x800 / f); +- else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) +- __set_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); +-} +- + void vmx_disable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type) + { + struct vcpu_vmx *vmx = to_vmx(vcpu); +@@ -4012,8 +3971,7 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector) + if (pi_test_and_set_on(&vmx->pi_desc)) + return 0; + +- if (vcpu != kvm_get_running_vcpu() && +- !kvm_vcpu_trigger_posted_interrupt(vcpu, false)) ++ if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false)) + kvm_vcpu_kick(vcpu); + + return 0; +@@ -4833,8 +4791,33 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) + dr6 = vmx_get_exit_qual(vcpu); + if (!(vcpu->guest_debug & + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) { ++ /* ++ * If the #DB was due to ICEBP, a.k.a. INT1, skip the ++ * instruction. ICEBP generates a trap-like #DB, but ++ * despite its interception control being tied to #DB, ++ * is an instruction intercept, i.e. the VM-Exit occurs ++ * on the ICEBP itself. Note, skipping ICEBP also ++ * clears STI and MOVSS blocking. ++ * ++ * For all other #DBs, set vmcs.PENDING_DBG_EXCEPTIONS.BS ++ * if single-step is enabled in RFLAGS and STI or MOVSS ++ * blocking is active, as the CPU doesn't set the bit ++ * on VM-Exit due to #DB interception. VM-Entry has a ++ * consistency check that a single-step #DB is pending ++ * in this scenario as the previous instruction cannot ++ * have toggled RFLAGS.TF 0=>1 (because STI and POP/MOV ++ * don't modify RFLAGS), therefore the one instruction ++ * delay when activating single-step breakpoints must ++ * have already expired. Note, the CPU sets/clears BS ++ * as appropriate for all other VM-Exits types. ++ */ + if (is_icebp(intr_info)) + WARN_ON(!skip_emulated_instruction(vcpu)); ++ else if ((vmx_get_rflags(vcpu) & X86_EFLAGS_TF) && ++ (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & ++ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS))) ++ vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, ++ vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS) | DR6_BS); + + kvm_queue_exception_p(vcpu, DB_VECTOR, dr6); + return 1; +@@ -5907,18 +5890,14 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) + vmx_flush_pml_buffer(vcpu); + + /* +- * We should never reach this point with a pending nested VM-Enter, and +- * more specifically emulation of L2 due to invalid guest state (see +- * below) should never happen as that means we incorrectly allowed a +- * nested VM-Enter with an invalid vmcs12. ++ * KVM should never reach this point with a pending nested VM-Enter. ++ * More specifically, short-circuiting VM-Entry to emulate L2 due to ++ * invalid guest state should never happen as that means KVM knowingly ++ * allowed a nested VM-Enter with an invalid vmcs12. More below. + */ + if (KVM_BUG_ON(vmx->nested.nested_run_pending, vcpu->kvm)) + return -EIO; + +- /* If guest state is invalid, start emulating */ +- if (vmx->emulation_required) +- return handle_invalid_guest_state(vcpu); +- + if (is_guest_mode(vcpu)) { + /* + * PML is never enabled when running L2, bail immediately if a +@@ -5940,10 +5919,30 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) + */ + nested_mark_vmcs12_pages_dirty(vcpu); + ++ /* ++ * Synthesize a triple fault if L2 state is invalid. In normal ++ * operation, nested VM-Enter rejects any attempt to enter L2 ++ * with invalid state. However, those checks are skipped if ++ * state is being stuffed via RSM or KVM_SET_NESTED_STATE. If ++ * L2 state is invalid, it means either L1 modified SMRAM state ++ * or userspace provided bad state. Synthesize TRIPLE_FAULT as ++ * doing so is architecturally allowed in the RSM case, and is ++ * the least awful solution for the userspace case without ++ * risking false positives. ++ */ ++ if (vmx->emulation_required) { ++ nested_vmx_vmexit(vcpu, EXIT_REASON_TRIPLE_FAULT, 0, 0); ++ return 1; ++ } ++ + if (nested_vmx_reflect_vmexit(vcpu)) + return 1; + } + ++ /* If guest state is invalid, start emulating. L2 is handled above. */ ++ if (vmx->emulation_required) ++ return handle_invalid_guest_state(vcpu); ++ + if (exit_reason.failed_vmentry) { + dump_vmcs(vcpu); + vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY; +@@ -6288,9 +6287,9 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu) + { + struct vcpu_vmx *vmx = to_vmx(vcpu); + int max_irr; +- bool max_irr_updated; ++ bool got_posted_interrupt; + +- if (KVM_BUG_ON(!vcpu->arch.apicv_active, vcpu->kvm)) ++ if (KVM_BUG_ON(!enable_apicv, vcpu->kvm)) + return -EIO; + + if (pi_test_on(&vmx->pi_desc)) { +@@ -6300,22 +6299,33 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu) + * But on x86 this is just a compiler barrier anyway. + */ + smp_mb__after_atomic(); +- max_irr_updated = ++ got_posted_interrupt = + kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr); +- +- /* +- * If we are running L2 and L1 has a new pending interrupt +- * which can be injected, this may cause a vmexit or it may +- * be injected into L2. Either way, this interrupt will be +- * processed via KVM_REQ_EVENT, not RVI, because we do not use +- * virtual interrupt delivery to inject L1 interrupts into L2. +- */ +- if (is_guest_mode(vcpu) && max_irr_updated) +- kvm_make_request(KVM_REQ_EVENT, vcpu); + } else { + max_irr = kvm_lapic_find_highest_irr(vcpu); ++ got_posted_interrupt = false; + } +- vmx_hwapic_irr_update(vcpu, max_irr); ++ ++ /* ++ * Newly recognized interrupts are injected via either virtual interrupt ++ * delivery (RVI) or KVM_REQ_EVENT. Virtual interrupt delivery is ++ * disabled in two cases: ++ * ++ * 1) If L2 is running and the vCPU has a new pending interrupt. If L1 ++ * wants to exit on interrupts, KVM_REQ_EVENT is needed to synthesize a ++ * VM-Exit to L1. If L1 doesn't want to exit, the interrupt is injected ++ * into L2, but KVM doesn't use virtual interrupt delivery to inject ++ * interrupts into L2, and so KVM_REQ_EVENT is again needed. ++ * ++ * 2) If APICv is disabled for this vCPU, assigned devices may still ++ * attempt to post interrupts. The posted interrupt vector will cause ++ * a VM-Exit and the subsequent entry will call sync_pir_to_irr. ++ */ ++ if (!is_guest_mode(vcpu) && kvm_vcpu_apicv_active(vcpu)) ++ vmx_set_rvi(max_irr); ++ else if (got_posted_interrupt) ++ kvm_make_request(KVM_REQ_EVENT, vcpu); ++ + return max_irr; + } + +@@ -6626,9 +6636,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) + * consistency check VM-Exit due to invalid guest state and bail. + */ + if (unlikely(vmx->emulation_required)) { +- +- /* We don't emulate invalid state of a nested guest */ +- vmx->fail = is_guest_mode(vcpu); ++ vmx->fail = 0; + + vmx->exit_reason.full = EXIT_REASON_INVALID_STATE; + vmx->exit_reason.failed_vmentry = 1; +@@ -6720,7 +6728,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) + * If the L02 MSR bitmap does not intercept the MSR, then we need to + * save it. + */ +- if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))) ++ if (unlikely(!msr_write_intercepted(vmx, MSR_IA32_SPEC_CTRL))) + vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL); + + x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0); +@@ -7524,6 +7532,7 @@ static int vmx_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) + if (ret) + return ret; + ++ vmx->nested.nested_run_pending = 1; + vmx->nested.smm.guest_mode = false; + } + return 0; +@@ -7551,6 +7560,8 @@ static void vmx_migrate_timers(struct kvm_vcpu *vcpu) + + static void hardware_unsetup(void) + { ++ kvm_set_posted_intr_wakeup_handler(NULL); ++ + if (nested) + nested_vmx_hardware_unsetup(); + +@@ -7606,6 +7617,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { + .cache_reg = vmx_cache_reg, + .get_rflags = vmx_get_rflags, + .set_rflags = vmx_set_rflags, ++ .get_if_flag = vmx_get_if_flag, + + .tlb_flush_all = vmx_flush_tlb_all, + .tlb_flush_current = vmx_flush_tlb_current, +@@ -7809,10 +7821,10 @@ static __init int hardware_setup(void) + ple_window_shrink = 0; + } + +- if (!cpu_has_vmx_apicv()) { ++ if (!cpu_has_vmx_apicv()) + enable_apicv = 0; ++ if (!enable_apicv) + vmx_x86_ops.sync_pir_to_irr = NULL; +- } + + if (cpu_has_vmx_tsc_scaling()) { + kvm_has_tsc_control = true; +@@ -7879,8 +7891,6 @@ static __init int hardware_setup(void) + vmx_x86_ops.request_immediate_exit = __kvm_request_immediate_exit; + } + +- kvm_set_posted_intr_wakeup_handler(pi_wakeup_handler); +- + kvm_mce_cap_supported |= MCG_LMCE_P; + + if (pt_mode != PT_MODE_SYSTEM && pt_mode != PT_MODE_HOST_GUEST) +@@ -7904,6 +7914,9 @@ static __init int hardware_setup(void) + r = alloc_kvm_area(); + if (r) + nested_vmx_hardware_unsetup(); ++ ++ kvm_set_posted_intr_wakeup_handler(pi_wakeup_handler); ++ + return r; + } + +@@ -7912,6 +7925,7 @@ static struct kvm_x86_init_ops vmx_init_ops __initdata = { + .disabled_by_bios = vmx_disabled_by_bios, + .check_processor_compatibility = vmx_check_processor_compat, + .hardware_setup = hardware_setup, ++ .intel_pt_intr_in_guest = vmx_pt_mode_is_host_guest, + + .runtime_ops = &vmx_x86_ops, + }; +diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h +index 592217fd7d920..3f9c8548625d6 100644 +--- a/arch/x86/kvm/vmx/vmx.h ++++ b/arch/x86/kvm/vmx/vmx.h +@@ -400,6 +400,69 @@ static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, + + void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu); + ++static inline bool vmx_test_msr_bitmap_read(ulong *msr_bitmap, u32 msr) ++{ ++ int f = sizeof(unsigned long); ++ ++ if (msr <= 0x1fff) ++ return test_bit(msr, msr_bitmap + 0x000 / f); ++ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) ++ return test_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); ++ return true; ++} ++ ++static inline bool vmx_test_msr_bitmap_write(ulong *msr_bitmap, u32 msr) ++{ ++ int f = sizeof(unsigned long); ++ ++ if (msr <= 0x1fff) ++ return test_bit(msr, msr_bitmap + 0x800 / f); ++ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) ++ return test_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); ++ return true; ++} ++ ++static inline void vmx_clear_msr_bitmap_read(ulong *msr_bitmap, u32 msr) ++{ ++ int f = sizeof(unsigned long); ++ ++ if (msr <= 0x1fff) ++ __clear_bit(msr, msr_bitmap + 0x000 / f); ++ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) ++ __clear_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); ++} ++ ++static inline void vmx_clear_msr_bitmap_write(ulong *msr_bitmap, u32 msr) ++{ ++ int f = sizeof(unsigned long); ++ ++ if (msr <= 0x1fff) ++ __clear_bit(msr, msr_bitmap + 0x800 / f); ++ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) ++ __clear_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); ++} ++ ++static inline void vmx_set_msr_bitmap_read(ulong *msr_bitmap, u32 msr) ++{ ++ int f = sizeof(unsigned long); ++ ++ if (msr <= 0x1fff) ++ __set_bit(msr, msr_bitmap + 0x000 / f); ++ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) ++ __set_bit(msr & 0x1fff, msr_bitmap + 0x400 / f); ++} ++ ++static inline void vmx_set_msr_bitmap_write(ulong *msr_bitmap, u32 msr) ++{ ++ int f = sizeof(unsigned long); ++ ++ if (msr <= 0x1fff) ++ __set_bit(msr, msr_bitmap + 0x800 / f); ++ else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) ++ __set_bit(msr & 0x1fff, msr_bitmap + 0xc00 / f); ++} ++ ++ + static inline u8 vmx_get_rvi(void) + { + return vmcs_read16(GUEST_INTR_STATUS) & 0xff; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index bfe0de3008a60..8213f7fb71a7b 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -848,6 +848,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3) + + memcpy(mmu->pdptrs, pdpte, sizeof(mmu->pdptrs)); + kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR); ++ kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu); + vcpu->arch.pdptrs_from_userspace = false; + + out: +@@ -1091,6 +1092,18 @@ static void kvm_invalidate_pcid(struct kvm_vcpu *vcpu, unsigned long pcid) + unsigned long roots_to_free = 0; + int i; + ++ /* ++ * MOV CR3 and INVPCID are usually not intercepted when using TDP, but ++ * this is reachable when running EPT=1 and unrestricted_guest=0, and ++ * also via the emulator. KVM's TDP page tables are not in the scope of ++ * the invalidation, but the guest's TLB entries need to be flushed as ++ * the CPU may have cached entries in its TLB for the target PCID. ++ */ ++ if (unlikely(tdp_enabled)) { ++ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); ++ return; ++ } ++ + /* + * If neither the current CR3 nor any of the prev_roots use the given + * PCID, then nothing needs to be done here because a resync will +@@ -1311,7 +1324,7 @@ static const u32 msrs_to_save_all[] = { + MSR_IA32_UMWAIT_CONTROL, + + MSR_ARCH_PERFMON_FIXED_CTR0, MSR_ARCH_PERFMON_FIXED_CTR1, +- MSR_ARCH_PERFMON_FIXED_CTR0 + 2, MSR_ARCH_PERFMON_FIXED_CTR0 + 3, ++ MSR_ARCH_PERFMON_FIXED_CTR0 + 2, + MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS, + MSR_CORE_PERF_GLOBAL_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL, + MSR_ARCH_PERFMON_PERFCTR0, MSR_ARCH_PERFMON_PERFCTR1, +@@ -3193,10 +3206,36 @@ static void kvm_vcpu_flush_tlb_guest(struct kvm_vcpu *vcpu) + static_call(kvm_x86_tlb_flush_guest)(vcpu); + } + ++ ++static inline void kvm_vcpu_flush_tlb_current(struct kvm_vcpu *vcpu) ++{ ++ ++vcpu->stat.tlb_flush; ++ static_call(kvm_x86_tlb_flush_current)(vcpu); ++} ++ ++/* ++ * Service "local" TLB flush requests, which are specific to the current MMU ++ * context. In addition to the generic event handling in vcpu_enter_guest(), ++ * TLB flushes that are targeted at an MMU context also need to be serviced ++ * prior before nested VM-Enter/VM-Exit. ++ */ ++void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu) ++{ ++ if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) ++ kvm_vcpu_flush_tlb_current(vcpu); ++ ++ if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) ++ kvm_vcpu_flush_tlb_guest(vcpu); ++} ++EXPORT_SYMBOL_GPL(kvm_service_local_tlb_flush_requests); ++ + static void record_steal_time(struct kvm_vcpu *vcpu) + { +- struct kvm_host_map map; +- struct kvm_steal_time *st; ++ struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache; ++ struct kvm_steal_time __user *st; ++ struct kvm_memslots *slots; ++ u64 steal; ++ u32 version; + + if (kvm_xen_msr_enabled(vcpu->kvm)) { + kvm_xen_runstate_set_running(vcpu); +@@ -3206,47 +3245,86 @@ static void record_steal_time(struct kvm_vcpu *vcpu) + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) + return; + +- /* -EAGAIN is returned in atomic context so we can just return. */ +- if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, +- &map, &vcpu->arch.st.cache, false)) ++ if (WARN_ON_ONCE(current->mm != vcpu->kvm->mm)) + return; + +- st = map.hva + +- offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); ++ slots = kvm_memslots(vcpu->kvm); ++ ++ if (unlikely(slots->generation != ghc->generation || ++ kvm_is_error_hva(ghc->hva) || !ghc->memslot)) { ++ gfn_t gfn = vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS; + ++ /* We rely on the fact that it fits in a single page. */ ++ BUILD_BUG_ON((sizeof(*st) - 1) & KVM_STEAL_VALID_BITS); ++ ++ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, gfn, sizeof(*st)) || ++ kvm_is_error_hva(ghc->hva) || !ghc->memslot) ++ return; ++ } ++ ++ st = (struct kvm_steal_time __user *)ghc->hva; + /* + * Doing a TLB flush here, on the guest's behalf, can avoid + * expensive IPIs. + */ + if (guest_pv_has(vcpu, KVM_FEATURE_PV_TLB_FLUSH)) { +- u8 st_preempted = xchg(&st->preempted, 0); ++ u8 st_preempted = 0; ++ int err = -EFAULT; ++ ++ if (!user_access_begin(st, sizeof(*st))) ++ return; ++ ++ asm volatile("1: xchgb %0, %2\n" ++ "xor %1, %1\n" ++ "2:\n" ++ _ASM_EXTABLE_UA(1b, 2b) ++ : "+q" (st_preempted), ++ "+&r" (err), ++ "+m" (st->preempted)); ++ if (err) ++ goto out; ++ ++ user_access_end(); ++ ++ vcpu->arch.st.preempted = 0; + + trace_kvm_pv_tlb_flush(vcpu->vcpu_id, + st_preempted & KVM_VCPU_FLUSH_TLB); + if (st_preempted & KVM_VCPU_FLUSH_TLB) + kvm_vcpu_flush_tlb_guest(vcpu); ++ ++ if (!user_access_begin(st, sizeof(*st))) ++ goto dirty; + } else { +- st->preempted = 0; +- } ++ if (!user_access_begin(st, sizeof(*st))) ++ return; + +- vcpu->arch.st.preempted = 0; ++ unsafe_put_user(0, &st->preempted, out); ++ vcpu->arch.st.preempted = 0; ++ } + +- if (st->version & 1) +- st->version += 1; /* first time write, random junk */ ++ unsafe_get_user(version, &st->version, out); ++ if (version & 1) ++ version += 1; /* first time write, random junk */ + +- st->version += 1; ++ version += 1; ++ unsafe_put_user(version, &st->version, out); + + smp_wmb(); + +- st->steal += current->sched_info.run_delay - ++ unsafe_get_user(steal, &st->steal, out); ++ steal += current->sched_info.run_delay - + vcpu->arch.st.last_steal; + vcpu->arch.st.last_steal = current->sched_info.run_delay; ++ unsafe_put_user(steal, &st->steal, out); + +- smp_wmb(); +- +- st->version += 1; ++ version += 1; ++ unsafe_put_user(version, &st->version, out); + +- kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false); ++ out: ++ user_access_end(); ++ dirty: ++ mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa)); + } + + int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) +@@ -3282,7 +3360,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + + if (!msr_info->host_initiated) + return 1; +- if (guest_cpuid_has(vcpu, X86_FEATURE_PDCM) && kvm_get_msr_feature(&msr_ent)) ++ if (kvm_get_msr_feature(&msr_ent)) + return 1; + if (data & ~msr_ent.data) + return 1; +@@ -3376,6 +3454,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + if (data & ~supported_xss) + return 1; + vcpu->arch.ia32_xss = data; ++ kvm_update_cpuid_runtime(vcpu); + break; + case MSR_SMI_COUNT: + if (!msr_info->host_initiated) +@@ -4285,8 +4364,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) + + static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + { +- struct kvm_host_map map; +- struct kvm_steal_time *st; ++ struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache; ++ struct kvm_steal_time __user *st; ++ struct kvm_memslots *slots; ++ static const u8 preempted = KVM_VCPU_PREEMPTED; + + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) + return; +@@ -4294,16 +4375,23 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + if (vcpu->arch.st.preempted) + return; + +- if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, +- &vcpu->arch.st.cache, true)) ++ /* This happens on process exit */ ++ if (unlikely(current->mm != vcpu->kvm->mm)) ++ return; ++ ++ slots = kvm_memslots(vcpu->kvm); ++ ++ if (unlikely(slots->generation != ghc->generation || ++ kvm_is_error_hva(ghc->hva) || !ghc->memslot)) + return; + +- st = map.hva + +- offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); ++ st = (struct kvm_steal_time __user *)ghc->hva; ++ BUILD_BUG_ON(sizeof(st->preempted) != sizeof(preempted)); + +- st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED; ++ if (!copy_to_user_nofault(&st->preempted, &preempted, sizeof(preempted))) ++ vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED; + +- kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true); ++ mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa)); + } + + void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) +@@ -4331,8 +4419,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) + static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu, + struct kvm_lapic_state *s) + { +- if (vcpu->arch.apicv_active) +- static_call(kvm_x86_sync_pir_to_irr)(vcpu); ++ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); + + return kvm_apic_get_state(vcpu, s); + } +@@ -4642,8 +4729,10 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, + vcpu->arch.apic->sipi_vector = events->sipi_vector; + + if (events->flags & KVM_VCPUEVENT_VALID_SMM) { +- if (!!(vcpu->arch.hflags & HF_SMM_MASK) != events->smi.smm) ++ if (!!(vcpu->arch.hflags & HF_SMM_MASK) != events->smi.smm) { ++ kvm_x86_ops.nested_ops->leave_nested(vcpu); + kvm_smm_changed(vcpu, events->smi.smm); ++ } + + vcpu->arch.smi_pending = events->smi.pending; + +@@ -6948,7 +7037,13 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, + unsigned short port, void *val, unsigned int count) + { + if (vcpu->arch.pio.count) { +- /* Complete previous iteration. */ ++ /* ++ * Complete a previous iteration that required userspace I/O. ++ * Note, @count isn't guaranteed to match pio.count as userspace ++ * can modify ECX before rerunning the vCPU. Ignore any such ++ * shenanigans as KVM doesn't support modifying the rep count, ++ * and the emulator ensures @count doesn't overflow the buffer. ++ */ + } else { + int r = __emulator_pio_in(vcpu, size, port, count); + if (!r) +@@ -6957,7 +7052,6 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, + /* Results already available, fall through. */ + } + +- WARN_ON(count != vcpu->arch.pio.count); + complete_emulator_pio_in(vcpu, val); + return 1; + } +@@ -7905,7 +7999,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, + * updating interruptibility state and injecting single-step #DBs. + */ + if (emulation_type & EMULTYPE_SKIP) { +- kvm_rip_write(vcpu, ctxt->_eip); ++ if (ctxt->mode != X86EMUL_MODE_PROT64) ++ ctxt->eip = (u32)ctxt->_eip; ++ else ++ ctxt->eip = ctxt->_eip; ++ ++ kvm_rip_write(vcpu, ctxt->eip); + if (ctxt->eflags & X86_EFLAGS_RF) + kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF); + return 1; +@@ -7969,6 +8068,9 @@ restart: + writeback = false; + r = 0; + vcpu->arch.complete_userspace_io = complete_emulated_mmio; ++ } else if (vcpu->arch.complete_userspace_io) { ++ writeback = false; ++ r = 0; + } else if (r == EMULATION_RESTART) + goto restart; + else +@@ -8340,7 +8442,7 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = { + .is_in_guest = kvm_is_in_guest, + .is_user_mode = kvm_is_user_mode, + .get_guest_ip = kvm_get_guest_ip, +- .handle_intel_pt_intr = kvm_handle_intel_pt_intr, ++ .handle_intel_pt_intr = NULL, + }; + + #ifdef CONFIG_X86_64 +@@ -8461,8 +8563,6 @@ int kvm_arch_init(void *opaque) + + kvm_timer_init(); + +- perf_register_guest_info_callbacks(&kvm_guest_cbs); +- + if (boot_cpu_has(X86_FEATURE_XSAVE)) { + host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); + supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0; +@@ -8496,7 +8596,6 @@ void kvm_arch_exit(void) + clear_hv_tscchange_cb(); + #endif + kvm_lapic_exit(); +- perf_unregister_guest_info_callbacks(&kvm_guest_cbs); + + if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) + cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, +@@ -8686,7 +8785,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) + + trace_kvm_hypercall(nr, a0, a1, a2, a3); + +- op_64_bit = is_64_bit_mode(vcpu); ++ op_64_bit = is_64_bit_hypercall(vcpu); + if (!op_64_bit) { + nr &= 0xFFFFFFFF; + a0 &= 0xFFFFFFFF; +@@ -8790,14 +8889,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) + { + struct kvm_run *kvm_run = vcpu->run; + +- /* +- * if_flag is obsolete and useless, so do not bother +- * setting it for SEV-ES guests. Userspace can just +- * use kvm_run->ready_for_interrupt_injection. +- */ +- kvm_run->if_flag = !vcpu->arch.guest_state_protected +- && (kvm_get_rflags(vcpu) & X86_EFLAGS_IF) != 0; +- ++ kvm_run->if_flag = static_call(kvm_x86_get_if_flag)(vcpu); + kvm_run->cr8 = kvm_get_cr8(vcpu); + kvm_run->apic_base = kvm_get_apic_base(vcpu); + +@@ -9359,8 +9451,7 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu) + if (irqchip_split(vcpu->kvm)) + kvm_scan_ioapic_routes(vcpu, vcpu->arch.ioapic_handled_vectors); + else { +- if (vcpu->arch.apicv_active) +- static_call(kvm_x86_sync_pir_to_irr)(vcpu); ++ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); + if (ioapic_in_kernel(vcpu->kvm)) + kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors); + } +@@ -9378,12 +9469,16 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu) + if (!kvm_apic_hw_enabled(vcpu->arch.apic)) + return; + +- if (to_hv_vcpu(vcpu)) ++ if (to_hv_vcpu(vcpu)) { + bitmap_or((ulong *)eoi_exit_bitmap, + vcpu->arch.ioapic_handled_vectors, + to_hv_synic(vcpu)->vec_bitmap, 256); ++ static_call(kvm_x86_load_eoi_exitmap)(vcpu, eoi_exit_bitmap); ++ return; ++ } + +- static_call(kvm_x86_load_eoi_exitmap)(vcpu, eoi_exit_bitmap); ++ static_call(kvm_x86_load_eoi_exitmap)( ++ vcpu, (u64 *)vcpu->arch.ioapic_handled_vectors); + } + + void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm, +@@ -9475,10 +9570,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + /* Flushing all ASIDs flushes the current ASID... */ + kvm_clear_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); + } +- if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) +- kvm_vcpu_flush_tlb_current(vcpu); +- if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) +- kvm_vcpu_flush_tlb_guest(vcpu); ++ kvm_service_local_tlb_flush_requests(vcpu); + + if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) { + vcpu->run->exit_reason = KVM_EXIT_TPR_ACCESS; +@@ -9629,10 +9721,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + + /* + * This handles the case where a posted interrupt was +- * notified with kvm_vcpu_kick. ++ * notified with kvm_vcpu_kick. Assigned devices can ++ * use the POSTED_INTR_VECTOR even if APICv is disabled, ++ * so do it even if APICv is disabled on this vCPU. + */ +- if (kvm_lapic_enabled(vcpu) && vcpu->arch.apicv_active) +- static_call(kvm_x86_sync_pir_to_irr)(vcpu); ++ if (kvm_lapic_enabled(vcpu)) ++ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); + + if (kvm_vcpu_exit_request(vcpu)) { + vcpu->mode = OUTSIDE_GUEST_MODE; +@@ -9668,8 +9762,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) + if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST)) + break; + +- if (vcpu->arch.apicv_active) +- static_call(kvm_x86_sync_pir_to_irr)(vcpu); ++ if (kvm_lapic_enabled(vcpu)) ++ static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); + + if (unlikely(kvm_vcpu_exit_request(vcpu))) { + exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED; +@@ -10817,11 +10911,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) + + void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) + { +- struct gfn_to_pfn_cache *cache = &vcpu->arch.st.cache; + int idx; + +- kvm_release_pfn(cache->pfn, cache->dirty, cache); +- + kvmclock_reset(vcpu); + + static_call(kvm_x86_vcpu_free)(vcpu); +@@ -10908,7 +10999,8 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) + + vcpu->arch.msr_misc_features_enables = 0; + +- vcpu->arch.xcr0 = XFEATURE_MASK_FP; ++ __kvm_set_xcr(vcpu, 0, XFEATURE_MASK_FP); ++ __kvm_set_msr(vcpu, MSR_IA32_XSS, 0, true); + } + + memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); +@@ -10927,8 +11019,6 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) + eax = 0x600; + kvm_rdx_write(vcpu, eax); + +- vcpu->arch.ia32_xss = 0; +- + static_call(kvm_x86_vcpu_reset)(vcpu, init_event); + + kvm_set_rflags(vcpu, X86_EFLAGS_FIXED); +@@ -11104,6 +11194,10 @@ int kvm_arch_hardware_setup(void *opaque) + memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops)); + kvm_ops_static_call_update(); + ++ if (ops->intel_pt_intr_in_guest && ops->intel_pt_intr_in_guest()) ++ kvm_guest_cbs.handle_intel_pt_intr = kvm_handle_intel_pt_intr; ++ perf_register_guest_info_callbacks(&kvm_guest_cbs); ++ + if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES)) + supported_xss = 0; + +@@ -11131,6 +11225,9 @@ int kvm_arch_hardware_setup(void *opaque) + + void kvm_arch_hardware_unsetup(void) + { ++ perf_unregister_guest_info_callbacks(&kvm_guest_cbs); ++ kvm_guest_cbs.handle_intel_pt_intr = NULL; ++ + static_call(kvm_x86_hardware_unsetup)(); + } + +diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h +index 7d66d63dc55a6..bc7ef6820ac8f 100644 +--- a/arch/x86/kvm/x86.h ++++ b/arch/x86/kvm/x86.h +@@ -103,6 +103,7 @@ static inline unsigned int __shrink_ple_window(unsigned int val, + + #define MSR_IA32_CR_PAT_DEFAULT 0x0007040600070406ULL + ++void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu); + int kvm_check_nested_events(struct kvm_vcpu *vcpu); + + static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu) +@@ -153,12 +154,24 @@ static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu) + { + int cs_db, cs_l; + ++ WARN_ON_ONCE(vcpu->arch.guest_state_protected); ++ + if (!is_long_mode(vcpu)) + return false; + static_call(kvm_x86_get_cs_db_l_bits)(vcpu, &cs_db, &cs_l); + return cs_l; + } + ++static inline bool is_64_bit_hypercall(struct kvm_vcpu *vcpu) ++{ ++ /* ++ * If running with protected guest state, the CS register is not ++ * accessible. The hypercall register values will have had to been ++ * provided in 64-bit mode, so assume the guest is in 64-bit. ++ */ ++ return vcpu->arch.guest_state_protected || is_64_bit_mode(vcpu); ++} ++ + static inline bool x86_exception_has_error_code(unsigned int vector) + { + static u32 exception_has_error_code = BIT(DF_VECTOR) | BIT(TS_VECTOR) | +@@ -173,12 +186,6 @@ static inline bool mmu_is_nested(struct kvm_vcpu *vcpu) + return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu; + } + +-static inline void kvm_vcpu_flush_tlb_current(struct kvm_vcpu *vcpu) +-{ +- ++vcpu->stat.tlb_flush; +- static_call(kvm_x86_tlb_flush_current)(vcpu); +-} +- + static inline int is_pae(struct kvm_vcpu *vcpu) + { + return kvm_read_cr4_bits(vcpu, X86_CR4_PAE); +diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c +index 8f62baebd0286..ab9f88de6deb9 100644 +--- a/arch/x86/kvm/xen.c ++++ b/arch/x86/kvm/xen.c +@@ -93,32 +93,57 @@ static void kvm_xen_update_runstate(struct kvm_vcpu *v, int state) + void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state) + { + struct kvm_vcpu_xen *vx = &v->arch.xen; ++ struct gfn_to_hva_cache *ghc = &vx->runstate_cache; ++ struct kvm_memslots *slots = kvm_memslots(v->kvm); ++ bool atomic = (state == RUNSTATE_runnable); + uint64_t state_entry_time; +- unsigned int offset; ++ int __user *user_state; ++ uint64_t __user *user_times; + + kvm_xen_update_runstate(v, state); + + if (!vx->runstate_set) + return; + +- BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); ++ if (unlikely(slots->generation != ghc->generation || kvm_is_error_hva(ghc->hva)) && ++ kvm_gfn_to_hva_cache_init(v->kvm, ghc, ghc->gpa, ghc->len)) ++ return; ++ ++ /* We made sure it fits in a single page */ ++ BUG_ON(!ghc->memslot); ++ ++ if (atomic) ++ pagefault_disable(); + +- offset = offsetof(struct compat_vcpu_runstate_info, state_entry_time); +-#ifdef CONFIG_X86_64 + /* +- * The only difference is alignment of uint64_t in 32-bit. +- * So the first field 'state' is accessed directly using +- * offsetof() (where its offset happens to be zero), while the +- * remaining fields which are all uint64_t, start at 'offset' +- * which we tweak here by adding 4. ++ * The only difference between 32-bit and 64-bit versions of the ++ * runstate struct us the alignment of uint64_t in 32-bit, which ++ * means that the 64-bit version has an additional 4 bytes of ++ * padding after the first field 'state'. ++ * ++ * So we use 'int __user *user_state' to point to the state field, ++ * and 'uint64_t __user *user_times' for runstate_entry_time. So ++ * the actual array of time[] in each state starts at user_times[1]. + */ ++ BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) != 0); ++ BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state) != 0); ++ user_state = (int __user *)ghc->hva; ++ ++ BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c); ++ ++ user_times = (uint64_t __user *)(ghc->hva + ++ offsetof(struct compat_vcpu_runstate_info, ++ state_entry_time)); ++#ifdef CONFIG_X86_64 + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) != + offsetof(struct compat_vcpu_runstate_info, state_entry_time) + 4); + BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, time) != + offsetof(struct compat_vcpu_runstate_info, time) + 4); + + if (v->kvm->arch.xen.long_mode) +- offset = offsetof(struct vcpu_runstate_info, state_entry_time); ++ user_times = (uint64_t __user *)(ghc->hva + ++ offsetof(struct vcpu_runstate_info, ++ state_entry_time)); + #endif + /* + * First write the updated state_entry_time at the appropriate +@@ -132,10 +157,8 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state) + BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state_entry_time) != + sizeof(state_entry_time)); + +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &state_entry_time, offset, +- sizeof(state_entry_time))) +- return; ++ if (__put_user(state_entry_time, user_times)) ++ goto out; + smp_wmb(); + + /* +@@ -149,11 +172,8 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state) + BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state) != + sizeof(vx->current_runstate)); + +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &vx->current_runstate, +- offsetof(struct vcpu_runstate_info, state), +- sizeof(vx->current_runstate))) +- return; ++ if (__put_user(vx->current_runstate, user_state)) ++ goto out; + + /* + * Write the actual runstate times immediately after the +@@ -168,24 +188,23 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state) + BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) != + sizeof(vx->runstate_times)); + +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &vx->runstate_times[0], +- offset + sizeof(u64), +- sizeof(vx->runstate_times))) +- return; +- ++ if (__copy_to_user(user_times + 1, vx->runstate_times, sizeof(vx->runstate_times))) ++ goto out; + smp_wmb(); + + /* + * Finally, clear the XEN_RUNSTATE_UPDATE bit in the guest's + * runstate_entry_time field. + */ +- + state_entry_time &= ~XEN_RUNSTATE_UPDATE; +- if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache, +- &state_entry_time, offset, +- sizeof(state_entry_time))) +- return; ++ __put_user(state_entry_time, user_times); ++ smp_wmb(); ++ ++ out: ++ mark_page_dirty_in_slot(v->kvm, ghc->memslot, ghc->gpa >> PAGE_SHIFT); ++ ++ if (atomic) ++ pagefault_enable(); + } + + int __kvm_xen_has_interrupt(struct kvm_vcpu *v) +@@ -299,7 +318,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data) + break; + + case KVM_XEN_ATTR_TYPE_SHARED_INFO: +- data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_gfn); ++ data->u.shared_info.gfn = kvm->arch.xen.shinfo_gfn; + r = 0; + break; + +@@ -337,6 +356,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) + break; + } + ++ /* It must fit within a single page */ ++ if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct vcpu_info) > PAGE_SIZE) { ++ r = -EINVAL; ++ break; ++ } ++ + r = kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.xen.vcpu_info_cache, + data->u.gpa, +@@ -354,6 +379,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) + break; + } + ++ /* It must fit within a single page */ ++ if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct pvclock_vcpu_time_info) > PAGE_SIZE) { ++ r = -EINVAL; ++ break; ++ } ++ + r = kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.xen.vcpu_time_info_cache, + data->u.gpa, +@@ -375,6 +406,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) + break; + } + ++ /* It must fit within a single page */ ++ if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct vcpu_runstate_info) > PAGE_SIZE) { ++ r = -EINVAL; ++ break; ++ } ++ + r = kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.xen.runstate_cache, + data->u.gpa, +@@ -698,7 +735,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu) + kvm_hv_hypercall_enabled(vcpu)) + return kvm_hv_hypercall(vcpu); + +- longmode = is_64_bit_mode(vcpu); ++ longmode = is_64_bit_hypercall(vcpu); + if (!longmode) { + params[0] = (u32)kvm_rbx_read(vcpu); + params[1] = (u32)kvm_rcx_read(vcpu); +diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c +index a1d24fdc07cf0..eb3ccffb9b9dc 100644 +--- a/arch/x86/lib/insn-eval.c ++++ b/arch/x86/lib/insn-eval.c +@@ -1417,7 +1417,7 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs) + } + } + +-static int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip) ++int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip) + { + unsigned long seg_base = 0; + +diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c +index c565def611e24..55e371cc69fd5 100644 +--- a/arch/x86/lib/insn.c ++++ b/arch/x86/lib/insn.c +@@ -13,6 +13,7 @@ + #endif + #include <asm/inat.h> /*__ignore_sync_check__ */ + #include <asm/insn.h> /* __ignore_sync_check__ */ ++#include <asm/unaligned.h> /* __ignore_sync_check__ */ + + #include <linux/errno.h> + #include <linux/kconfig.h> +@@ -37,10 +38,10 @@ + ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr) + + #define __get_next(t, insn) \ +- ({ t r; memcpy(&r, insn->next_byte, sizeof(t)); insn->next_byte += sizeof(t); leXX_to_cpu(t, r); }) ++ ({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); }) + + #define __peek_nbyte_next(t, insn, n) \ +- ({ t r; memcpy(&r, (insn)->next_byte + n, sizeof(t)); leXX_to_cpu(t, r); }) ++ ({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); }) + + #define get_next(t, insn) \ + ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); }) +diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S +index ec9922cba30a4..5385d26af6e45 100644 +--- a/arch/x86/lib/retpoline.S ++++ b/arch/x86/lib/retpoline.S +@@ -34,7 +34,7 @@ SYM_FUNC_START(__x86_indirect_thunk_\reg) + + ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ + __stringify(RETPOLINE \reg), X86_FEATURE_RETPOLINE, \ +- __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_AMD ++ __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE + + SYM_FUNC_END(__x86_indirect_thunk_\reg) + +diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c +index f5e1e60c9095f..6c2f1b76a0b61 100644 +--- a/arch/x86/mm/cpu_entry_area.c ++++ b/arch/x86/mm/cpu_entry_area.c +@@ -110,6 +110,13 @@ static void __init percpu_setup_exception_stacks(unsigned int cpu) + cea_map_stack(NMI); + cea_map_stack(DB); + cea_map_stack(MCE); ++ ++ if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) { ++ if (cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) { ++ cea_map_stack(VC); ++ cea_map_stack(VC2); ++ } ++ } + } + #else + static inline void percpu_setup_exception_stacks(unsigned int cpu) +diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c +index 84a2c8c4af735..4bfed53e210ec 100644 +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -32,6 +32,7 @@ + #include <asm/pgtable_areas.h> /* VMALLOC_START, ... */ + #include <asm/kvm_para.h> /* kvm_handle_async_pf */ + #include <asm/vdso.h> /* fixup_vdso_exception() */ ++#include <asm/irq_stack.h> + + #define CREATE_TRACE_POINTS + #include <asm/trace/exceptions.h> +@@ -631,6 +632,9 @@ static noinline void + page_fault_oops(struct pt_regs *regs, unsigned long error_code, + unsigned long address) + { ++#ifdef CONFIG_VMAP_STACK ++ struct stack_info info; ++#endif + unsigned long flags; + int sig; + +@@ -649,9 +653,7 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code, + * that we're in vmalloc space to avoid this. + */ + if (is_vmalloc_addr((void *)address) && +- (((unsigned long)current->stack - 1 - address < PAGE_SIZE) || +- address - ((unsigned long)current->stack + THREAD_SIZE) < PAGE_SIZE)) { +- unsigned long stack = __this_cpu_ist_top_va(DF) - sizeof(void *); ++ get_stack_guard_info((void *)address, &info)) { + /* + * We're likely to be running with very little stack space + * left. It's plausible that we'd hit this condition but +@@ -662,13 +664,11 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code, + * and then double-fault, though, because we're likely to + * break the console driver and lose most of the stack dump. + */ +- asm volatile ("movq %[stack], %%rsp\n\t" +- "call handle_stack_overflow\n\t" +- "1: jmp 1b" +- : ASM_CALL_CONSTRAINT +- : "D" ("kernel stack overflow (page fault)"), +- "S" (regs), "d" (address), +- [stack] "rm" (stack)); ++ call_on_stack(__this_cpu_ist_top_va(DF) - sizeof(void*), ++ handle_stack_overflow, ++ ASM_CALL_ARG3, ++ , [arg1] "r" (regs), [arg2] "r" (address), [arg3] "r" (&info)); ++ + unreachable(); + } + #endif +diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c +index ff08dc4636347..e29b1418d00c7 100644 +--- a/arch/x86/mm/mem_encrypt.c ++++ b/arch/x86/mm/mem_encrypt.c +@@ -20,6 +20,7 @@ + #include <linux/bitops.h> + #include <linux/dma-mapping.h> + #include <linux/virtio_config.h> ++#include <linux/cc_platform.h> + + #include <asm/tlbflush.h> + #include <asm/fixmap.h> +diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c +index 470b202084306..700ce8fdea87c 100644 +--- a/arch/x86/mm/mem_encrypt_identity.c ++++ b/arch/x86/mm/mem_encrypt_identity.c +@@ -27,6 +27,15 @@ + #undef CONFIG_PARAVIRT_XXL + #undef CONFIG_PARAVIRT_SPINLOCKS + ++/* ++ * This code runs before CPU feature bits are set. By default, the ++ * pgtable_l5_enabled() function uses bit X86_FEATURE_LA57 to determine if ++ * 5-level paging is active, so that won't work here. USE_EARLY_PGTABLE_L5 ++ * is provided to handle this situation and, instead, use a variable that ++ * has been set by the early boot code. ++ */ ++#define USE_EARLY_PGTABLE_L5 ++ + #include <linux/kernel.h> + #include <linux/mm.h> + #include <linux/mem_encrypt.h> +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index 9ea57389c554b..d99434dc215c2 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -721,6 +721,20 @@ static void maybe_emit_mod(u8 **pprog, u32 dst_reg, u32 src_reg, bool is64) + *pprog = prog; + } + ++/* ++ * Similar version of maybe_emit_mod() for a single register ++ */ ++static void maybe_emit_1mod(u8 **pprog, u32 reg, bool is64) ++{ ++ u8 *prog = *pprog; ++ ++ if (is64) ++ EMIT1(add_1mod(0x48, reg)); ++ else if (is_ereg(reg)) ++ EMIT1(add_1mod(0x40, reg)); ++ *pprog = prog; ++} ++ + /* LDX: dst_reg = *(u8*)(src_reg + off) */ + static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off) + { +@@ -951,10 +965,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, + /* neg dst */ + case BPF_ALU | BPF_NEG: + case BPF_ALU64 | BPF_NEG: +- if (BPF_CLASS(insn->code) == BPF_ALU64) +- EMIT1(add_1mod(0x48, dst_reg)); +- else if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); ++ maybe_emit_1mod(&prog, dst_reg, ++ BPF_CLASS(insn->code) == BPF_ALU64); + EMIT2(0xF7, add_1reg(0xD8, dst_reg)); + break; + +@@ -968,10 +980,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, + case BPF_ALU64 | BPF_AND | BPF_K: + case BPF_ALU64 | BPF_OR | BPF_K: + case BPF_ALU64 | BPF_XOR | BPF_K: +- if (BPF_CLASS(insn->code) == BPF_ALU64) +- EMIT1(add_1mod(0x48, dst_reg)); +- else if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); ++ maybe_emit_1mod(&prog, dst_reg, ++ BPF_CLASS(insn->code) == BPF_ALU64); + + /* + * b3 holds 'normal' opcode, b2 short form only valid +@@ -1112,10 +1122,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, + case BPF_ALU64 | BPF_LSH | BPF_K: + case BPF_ALU64 | BPF_RSH | BPF_K: + case BPF_ALU64 | BPF_ARSH | BPF_K: +- if (BPF_CLASS(insn->code) == BPF_ALU64) +- EMIT1(add_1mod(0x48, dst_reg)); +- else if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); ++ maybe_emit_1mod(&prog, dst_reg, ++ BPF_CLASS(insn->code) == BPF_ALU64); + + b3 = simple_alu_opcodes[BPF_OP(insn->code)]; + if (imm32 == 1) +@@ -1146,10 +1154,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, + } + + /* shl %rax, %cl | shr %rax, %cl | sar %rax, %cl */ +- if (BPF_CLASS(insn->code) == BPF_ALU64) +- EMIT1(add_1mod(0x48, dst_reg)); +- else if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); ++ maybe_emit_1mod(&prog, dst_reg, ++ BPF_CLASS(insn->code) == BPF_ALU64); + + b3 = simple_alu_opcodes[BPF_OP(insn->code)]; + EMIT2(0xD3, add_1reg(b3, dst_reg)); +@@ -1274,19 +1280,54 @@ st: if (is_imm8(insn->off)) + case BPF_LDX | BPF_MEM | BPF_DW: + case BPF_LDX | BPF_PROBE_MEM | BPF_DW: + if (BPF_MODE(insn->code) == BPF_PROBE_MEM) { +- /* test src_reg, src_reg */ +- maybe_emit_mod(&prog, src_reg, src_reg, true); /* always 1 byte */ +- EMIT2(0x85, add_2reg(0xC0, src_reg, src_reg)); +- /* jne start_of_ldx */ +- EMIT2(X86_JNE, 0); ++ /* Though the verifier prevents negative insn->off in BPF_PROBE_MEM ++ * add abs(insn->off) to the limit to make sure that negative ++ * offset won't be an issue. ++ * insn->off is s16, so it won't affect valid pointers. ++ */ ++ u64 limit = TASK_SIZE_MAX + PAGE_SIZE + abs(insn->off); ++ u8 *end_of_jmp1, *end_of_jmp2; ++ ++ /* Conservatively check that src_reg + insn->off is a kernel address: ++ * 1. src_reg + insn->off >= limit ++ * 2. src_reg + insn->off doesn't become small positive. ++ * Cannot do src_reg + insn->off >= limit in one branch, ++ * since it needs two spare registers, but JIT has only one. ++ */ ++ ++ /* movabsq r11, limit */ ++ EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG)); ++ EMIT((u32)limit, 4); ++ EMIT(limit >> 32, 4); ++ /* cmp src_reg, r11 */ ++ maybe_emit_mod(&prog, src_reg, AUX_REG, true); ++ EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG)); ++ /* if unsigned '<' goto end_of_jmp2 */ ++ EMIT2(X86_JB, 0); ++ end_of_jmp1 = prog; ++ ++ /* mov r11, src_reg */ ++ emit_mov_reg(&prog, true, AUX_REG, src_reg); ++ /* add r11, insn->off */ ++ maybe_emit_1mod(&prog, AUX_REG, true); ++ EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off); ++ /* jmp if not carry to start_of_ldx ++ * Otherwise ERR_PTR(-EINVAL) + 128 will be the user addr ++ * that has to be rejected. ++ */ ++ EMIT2(0x73 /* JNC */, 0); ++ end_of_jmp2 = prog; ++ + /* xor dst_reg, dst_reg */ + emit_mov_imm32(&prog, false, dst_reg, 0); + /* jmp byte_after_ldx */ + EMIT2(0xEB, 0); + +- /* populate jmp_offset for JNE above */ +- temp[4] = prog - temp - 5 /* sizeof(test + jne) */; ++ /* populate jmp_offset for JB above to jump to xor dst_reg */ ++ end_of_jmp1[-1] = end_of_jmp2 - end_of_jmp1; ++ /* populate jmp_offset for JNC above to jump to start_of_ldx */ + start_of_ldx = prog; ++ end_of_jmp2[-1] = start_of_ldx - end_of_jmp2; + } + emit_ldx(&prog, BPF_SIZE(insn->code), dst_reg, src_reg, insn->off); + if (BPF_MODE(insn->code) == BPF_PROBE_MEM) { +@@ -1332,7 +1373,7 @@ st: if (is_imm8(insn->off)) + * End result: x86 insn "mov rbx, qword ptr [rax+0x14]" + * of 4 bytes will be ignored and rbx will be zero inited. + */ +- ex->fixup = (prog - temp) | (reg2pt_regs[dst_reg] << 8); ++ ex->fixup = (prog - start_of_ldx) | (reg2pt_regs[dst_reg] << 8); + } + break; + +@@ -1459,10 +1500,8 @@ st: if (is_imm8(insn->off)) + case BPF_JMP | BPF_JSET | BPF_K: + case BPF_JMP32 | BPF_JSET | BPF_K: + /* test dst_reg, imm32 */ +- if (BPF_CLASS(insn->code) == BPF_JMP) +- EMIT1(add_1mod(0x48, dst_reg)); +- else if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); ++ maybe_emit_1mod(&prog, dst_reg, ++ BPF_CLASS(insn->code) == BPF_JMP); + EMIT2_off32(0xF7, add_1reg(0xC0, dst_reg), imm32); + goto emit_cond_jmp; + +@@ -1495,10 +1534,8 @@ st: if (is_imm8(insn->off)) + } + + /* cmp dst_reg, imm8/32 */ +- if (BPF_CLASS(insn->code) == BPF_JMP) +- EMIT1(add_1mod(0x48, dst_reg)); +- else if (is_ereg(dst_reg)) +- EMIT1(add_1mod(0x40, dst_reg)); ++ maybe_emit_1mod(&prog, dst_reg, ++ BPF_CLASS(insn->code) == BPF_JMP); + + if (is_imm8(imm32)) + EMIT3(0x83, add_1reg(0xF8, dst_reg), imm32); +diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c +index 2edd86649468f..615a76d700194 100644 +--- a/arch/x86/pci/fixup.c ++++ b/arch/x86/pci/fixup.c +@@ -353,8 +353,8 @@ static void pci_fixup_video(struct pci_dev *pdev) + } + } + } +-DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, +- PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); ++DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, ++ PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); + + + static const struct dmi_system_id msi_k8t_dmi_table[] = { +diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c +index b15ebfe40a73e..b0b848d6933af 100644 +--- a/arch/x86/platform/efi/quirks.c ++++ b/arch/x86/platform/efi/quirks.c +@@ -277,7 +277,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) + return; + } + +- new = early_memremap(data.phys_map, data.size); ++ new = early_memremap_prot(data.phys_map, data.size, ++ pgprot_val(pgprot_encrypted(FIXMAP_PAGE_NORMAL))); + if (!new) { + pr_err("Failed to map new boot services memmap\n"); + return; +diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c +index 31b5856010cba..1d20ed4b28729 100644 +--- a/arch/x86/realmode/init.c ++++ b/arch/x86/realmode/init.c +@@ -17,6 +17,32 @@ u32 *trampoline_cr4_features; + /* Hold the pgd entry used on booting additional CPUs */ + pgd_t trampoline_pgd_entry; + ++void load_trampoline_pgtable(void) ++{ ++#ifdef CONFIG_X86_32 ++ load_cr3(initial_page_table); ++#else ++ /* ++ * This function is called before exiting to real-mode and that will ++ * fail with CR4.PCIDE still set. ++ */ ++ if (boot_cpu_has(X86_FEATURE_PCID)) ++ cr4_clear_bits(X86_CR4_PCIDE); ++ ++ write_cr3(real_mode_header->trampoline_pgd); ++#endif ++ ++ /* ++ * The CR3 write above will not flush global TLB entries. ++ * Stale, global entries from previous page tables may still be ++ * present. Flush those stale entries. ++ * ++ * This ensures that memory accessed while running with ++ * trampoline_pgd is *actually* mapped into trampoline_pgd. ++ */ ++ __flush_tlb_all(); ++} ++ + void __init reserve_real_mode(void) + { + phys_addr_t mem; +@@ -72,6 +98,7 @@ static void __init setup_real_mode(void) + #ifdef CONFIG_X86_64 + u64 *trampoline_pgd; + u64 efer; ++ int i; + #endif + + base = (unsigned char *)real_mode_header; +@@ -128,8 +155,17 @@ static void __init setup_real_mode(void) + trampoline_header->flags = 0; + + trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); ++ ++ /* Map the real mode stub as virtual == physical */ + trampoline_pgd[0] = trampoline_pgd_entry.pgd; +- trampoline_pgd[511] = init_top_pgt[511].pgd; ++ ++ /* ++ * Include the entirety of the kernel mapping into the trampoline ++ * PGD. This way, all mappings present in the normal kernel page ++ * tables are usable while running on trampoline_pgd. ++ */ ++ for (i = pgd_index(__PAGE_OFFSET); i < PTRS_PER_PGD; i++) ++ trampoline_pgd[i] = init_top_pgt[i].pgd; + #endif + + sme_sev_setup_real_mode(trampoline_header); +diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c +index 58f51667e2e4b..8249685b40960 100644 +--- a/arch/x86/um/syscalls_64.c ++++ b/arch/x86/um/syscalls_64.c +@@ -11,6 +11,7 @@ + #include <linux/uaccess.h> + #include <asm/prctl.h> /* XXX This should get the constants from libc */ + #include <os.h> ++#include <registers.h> + + long arch_prctl(struct task_struct *task, int option, + unsigned long __user *arg2) +@@ -35,7 +36,7 @@ long arch_prctl(struct task_struct *task, int option, + switch (option) { + case ARCH_SET_FS: + case ARCH_SET_GS: +- ret = restore_registers(pid, ¤t->thread.regs.regs); ++ ret = restore_pid_registers(pid, ¤t->thread.regs.regs); + if (ret) + return ret; + break; +diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c +index a7b7d674f5005..133ef31639df1 100644 +--- a/arch/x86/xen/enlighten_pv.c ++++ b/arch/x86/xen/enlighten_pv.c +@@ -1364,10 +1364,6 @@ asmlinkage __visible void __init xen_start_kernel(void) + + xen_acpi_sleep_register(); + +- /* Avoid searching for BIOS MP tables */ +- x86_init.mpparse.find_smp_config = x86_init_noop; +- x86_init.mpparse.get_smp_config = x86_init_uint_noop; +- + xen_boot_params_init_edd(); + + #ifdef CONFIG_ACPI +diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c +index 7ed56c6075b0c..477c484eb202c 100644 +--- a/arch/x86/xen/smp_pv.c ++++ b/arch/x86/xen/smp_pv.c +@@ -148,28 +148,12 @@ int xen_smp_intr_init_pv(unsigned int cpu) + return rc; + } + +-static void __init xen_fill_possible_map(void) +-{ +- int i, rc; +- +- if (xen_initial_domain()) +- return; +- +- for (i = 0; i < nr_cpu_ids; i++) { +- rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL); +- if (rc >= 0) { +- num_processors++; +- set_cpu_possible(i, true); +- } +- } +-} +- +-static void __init xen_filter_cpu_maps(void) ++static void __init _get_smp_config(unsigned int early) + { + int i, rc; + unsigned int subtract = 0; + +- if (!xen_initial_domain()) ++ if (early) + return; + + num_processors = 0; +@@ -210,7 +194,6 @@ static void __init xen_pv_smp_prepare_boot_cpu(void) + * sure the old memory can be recycled. */ + make_lowmem_page_readwrite(xen_initial_gdt); + +- xen_filter_cpu_maps(); + xen_setup_vcpu_info_placement(); + + /* +@@ -486,5 +469,8 @@ static const struct smp_ops xen_smp_ops __initconst = { + void __init xen_smp_init(void) + { + smp_ops = xen_smp_ops; +- xen_fill_possible_map(); ++ ++ /* Avoid searching for BIOS MP tables */ ++ x86_init.mpparse.find_smp_config = x86_init_noop; ++ x86_init.mpparse.get_smp_config = _get_smp_config; + } +diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S +index 1e626444712be..3bebf66569b48 100644 +--- a/arch/x86/xen/xen-asm.S ++++ b/arch/x86/xen/xen-asm.S +@@ -20,6 +20,7 @@ + + #include <linux/init.h> + #include <linux/linkage.h> ++#include <../entry/calling.h> + + /* + * Enable events. This clears the event mask and tests the pending +@@ -191,6 +192,25 @@ SYM_CODE_START(xen_iret) + jmp hypercall_iret + SYM_CODE_END(xen_iret) + ++/* ++ * XEN pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is ++ * also the kernel stack. Reusing swapgs_restore_regs_and_return_to_usermode() ++ * in XEN pv would cause %rsp to move up to the top of the kernel stack and ++ * leave the IRET frame below %rsp, which is dangerous to be corrupted if #NMI ++ * interrupts. And swapgs_restore_regs_and_return_to_usermode() pushing the IRET ++ * frame at the same address is useless. ++ */ ++SYM_CODE_START(xenpv_restore_regs_and_return_to_usermode) ++ UNWIND_HINT_REGS ++ POP_REGS ++ ++ /* stackleak_erase() can work safely on the kernel stack. */ ++ STACKLEAK_ERASE_NOCLOBBER ++ ++ addq $8, %rsp /* skip regs->orig_ax */ ++ jmp xen_iret ++SYM_CODE_END(xenpv_restore_regs_and_return_to_usermode) ++ + /* + * Xen handles syscall callbacks much like ordinary exceptions, which + * means we have: +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 480e1a1348596..e66970bf27dbe 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -5991,48 +5991,7 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, + + spin_lock_irq(&bfqd->lock); + bfqq = bfq_init_rq(rq); +- +- /* +- * Reqs with at_head or passthrough flags set are to be put +- * directly into dispatch list. Additional case for putting rq +- * directly into the dispatch queue: the only active +- * bfq_queues are bfqq and either its waker bfq_queue or one +- * of its woken bfq_queues. The rationale behind this +- * additional condition is as follows: +- * - consider a bfq_queue, say Q1, detected as a waker of +- * another bfq_queue, say Q2 +- * - by definition of a waker, Q1 blocks the I/O of Q2, i.e., +- * some I/O of Q1 needs to be completed for new I/O of Q2 +- * to arrive. A notable example of waker is journald +- * - so, Q1 and Q2 are in any respect the queues of two +- * cooperating processes (or of two cooperating sets of +- * processes): the goal of Q1's I/O is doing what needs to +- * be done so that new Q2's I/O can finally be +- * issued. Therefore, if the service of Q1's I/O is delayed, +- * then Q2's I/O is delayed too. Conversely, if Q2's I/O is +- * delayed, the goal of Q1's I/O is hindered. +- * - as a consequence, if some I/O of Q1/Q2 arrives while +- * Q2/Q1 is the only queue in service, there is absolutely +- * no point in delaying the service of such an I/O. The +- * only possible result is a throughput loss +- * - so, when the above condition holds, the best option is to +- * have the new I/O dispatched as soon as possible +- * - the most effective and efficient way to attain the above +- * goal is to put the new I/O directly in the dispatch +- * list +- * - as an additional restriction, Q1 and Q2 must be the only +- * busy queues for this commit to put the I/O of Q2/Q1 in +- * the dispatch list. This is necessary, because, if also +- * other queues are waiting for service, then putting new +- * I/O directly in the dispatch list may evidently cause a +- * violation of service guarantees for the other queues +- */ +- if (!bfqq || +- (bfqq != bfqd->in_service_queue && +- bfqd->in_service_queue != NULL && +- bfq_tot_busy_queues(bfqd) == 1 + bfq_bfqq_busy(bfqq) && +- (bfqq->waker_bfqq == bfqd->in_service_queue || +- bfqd->in_service_queue->waker_bfqq == bfqq)) || at_head) { ++ if (!bfqq || at_head) { + if (at_head) + list_add(&rq->queuelist, &bfqd->dispatch); + else +@@ -6059,7 +6018,6 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, + * merge). + */ + cmd_flags = rq->cmd_flags; +- + spin_unlock_irq(&bfqd->lock); + + bfq_update_insert_stats(q, bfqq, idle_timer_disabled, +@@ -6920,6 +6878,8 @@ static void bfq_exit_queue(struct elevator_queue *e) + spin_unlock_irq(&bfqd->lock); + #endif + ++ wbt_enable_default(bfqd->queue); ++ + kfree(bfqd); + } + +diff --git a/block/bio-integrity.c b/block/bio-integrity.c +index 6b47cddbbca17..4a7c33ed9a661 100644 +--- a/block/bio-integrity.c ++++ b/block/bio-integrity.c +@@ -373,7 +373,7 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done) + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9); + +- bip->bip_iter.bi_sector += bytes_done >> 9; ++ bip->bip_iter.bi_sector += bio_integrity_intervals(bi, bytes_done >> 9); + bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes); + } + +diff --git a/block/bio.c b/block/bio.c +index a6fb6a0b42955..25f1ed261100b 100644 +--- a/block/bio.c ++++ b/block/bio.c +@@ -567,7 +567,8 @@ void bio_truncate(struct bio *bio, unsigned new_size) + offset = new_size - done; + else + offset = 0; +- zero_user(bv.bv_page, offset, bv.bv_len - offset); ++ zero_user(bv.bv_page, bv.bv_offset + offset, ++ bv.bv_len - offset); + truncated = true; + } + done += bv.bv_len; +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index 9a1c5839dd469..0eec59e4df65c 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -633,6 +633,14 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, + + q = bdev->bd_disk->queue; + ++ /* ++ * blkcg_deactivate_policy() requires queue to be frozen, we can grab ++ * q_usage_counter to prevent concurrent with blkcg_deactivate_policy(). ++ */ ++ ret = blk_queue_enter(q, 0); ++ if (ret) ++ goto fail; ++ + rcu_read_lock(); + spin_lock_irq(&q->queue_lock); + +@@ -667,13 +675,13 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, + new_blkg = blkg_alloc(pos, q, GFP_KERNEL); + if (unlikely(!new_blkg)) { + ret = -ENOMEM; +- goto fail; ++ goto fail_exit_queue; + } + + if (radix_tree_preload(GFP_KERNEL)) { + blkg_free(new_blkg); + ret = -ENOMEM; +- goto fail; ++ goto fail_exit_queue; + } + + rcu_read_lock(); +@@ -702,6 +710,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, + goto success; + } + success: ++ blk_queue_exit(q); + ctx->bdev = bdev; + ctx->blkg = blkg; + ctx->body = input; +@@ -712,6 +721,8 @@ fail_preloaded: + fail_unlock: + spin_unlock_irq(&q->queue_lock); + rcu_read_unlock(); ++fail_exit_queue: ++ blk_queue_exit(q); + fail: + blkdev_put_no_open(bdev); + /* +diff --git a/block/blk-core.c b/block/blk-core.c +index 4d8f5fe915887..42ac3a985c2d7 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -350,13 +350,6 @@ void blk_queue_start_drain(struct request_queue *q) + wake_up_all(&q->mq_freeze_wq); + } + +-void blk_set_queue_dying(struct request_queue *q) +-{ +- blk_queue_flag_set(QUEUE_FLAG_DYING, q); +- blk_queue_start_drain(q); +-} +-EXPORT_SYMBOL_GPL(blk_set_queue_dying); +- + /** + * blk_cleanup_queue - shutdown a request queue + * @q: request queue to shutdown +@@ -374,7 +367,8 @@ void blk_cleanup_queue(struct request_queue *q) + WARN_ON_ONCE(blk_queue_registered(q)); + + /* mark @q DYING, no new request or merges will be allowed afterwards */ +- blk_set_queue_dying(q); ++ blk_queue_flag_set(QUEUE_FLAG_DYING, q); ++ blk_queue_start_drain(q); + + blk_queue_flag_set(QUEUE_FLAG_NOMERGES, q); + blk_queue_flag_set(QUEUE_FLAG_NOXMERGES, q); +@@ -389,8 +383,10 @@ void blk_cleanup_queue(struct request_queue *q) + blk_queue_flag_set(QUEUE_FLAG_DEAD, q); + + blk_sync_queue(q); +- if (queue_is_mq(q)) ++ if (queue_is_mq(q)) { ++ blk_mq_cancel_work_sync(q); + blk_mq_exit_queue(q); ++ } + + /* + * In theory, request pool of sched_tags belongs to request queue. +@@ -887,10 +883,8 @@ static noinline_for_stack bool submit_bio_checks(struct bio *bio) + if (unlikely(!current->io_context)) + create_task_io_context(current, GFP_ATOMIC, q->node); + +- if (blk_throtl_bio(bio)) { +- blkcg_bio_issue_init(bio); ++ if (blk_throtl_bio(bio)) + return false; +- } + + blk_cgroup_bio_start(bio); + blkcg_bio_issue_init(bio); +@@ -1293,20 +1287,32 @@ void blk_account_io_start(struct request *rq) + } + + static unsigned long __part_start_io_acct(struct block_device *part, +- unsigned int sectors, unsigned int op) ++ unsigned int sectors, unsigned int op, ++ unsigned long start_time) + { + const int sgrp = op_stat_group(op); +- unsigned long now = READ_ONCE(jiffies); + + part_stat_lock(); +- update_io_ticks(part, now, false); ++ update_io_ticks(part, start_time, false); + part_stat_inc(part, ios[sgrp]); + part_stat_add(part, sectors[sgrp], sectors); + part_stat_local_inc(part, in_flight[op_is_write(op)]); + part_stat_unlock(); + +- return now; ++ return start_time; ++} ++ ++/** ++ * bio_start_io_acct_time - start I/O accounting for bio based drivers ++ * @bio: bio to start account for ++ * @start_time: start time that should be passed back to bio_end_io_acct(). ++ */ ++void bio_start_io_acct_time(struct bio *bio, unsigned long start_time) ++{ ++ __part_start_io_acct(bio->bi_bdev, bio_sectors(bio), ++ bio_op(bio), start_time); + } ++EXPORT_SYMBOL_GPL(bio_start_io_acct_time); + + /** + * bio_start_io_acct - start I/O accounting for bio based drivers +@@ -1316,14 +1322,15 @@ static unsigned long __part_start_io_acct(struct block_device *part, + */ + unsigned long bio_start_io_acct(struct bio *bio) + { +- return __part_start_io_acct(bio->bi_bdev, bio_sectors(bio), bio_op(bio)); ++ return __part_start_io_acct(bio->bi_bdev, bio_sectors(bio), ++ bio_op(bio), jiffies); + } + EXPORT_SYMBOL_GPL(bio_start_io_acct); + + unsigned long disk_start_io_acct(struct gendisk *disk, unsigned int sectors, + unsigned int op) + { +- return __part_start_io_acct(disk->part0, sectors, op); ++ return __part_start_io_acct(disk->part0, sectors, op, jiffies); + } + EXPORT_SYMBOL(disk_start_io_acct); + +diff --git a/block/blk-flush.c b/block/blk-flush.c +index 4201728bf3a5a..94a86acbb7f67 100644 +--- a/block/blk-flush.c ++++ b/block/blk-flush.c +@@ -235,8 +235,10 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) + * avoiding use-after-free. + */ + WRITE_ONCE(flush_rq->state, MQ_RQ_IDLE); +- if (fq->rq_status != BLK_STS_OK) ++ if (fq->rq_status != BLK_STS_OK) { + error = fq->rq_status; ++ fq->rq_status = BLK_STS_OK; ++ } + + if (!q->elevator) { + flush_rq->tag = BLK_MQ_NO_TAG; +diff --git a/block/blk-iocost.c b/block/blk-iocost.c +index b3880e4ba22a1..eb7b0d6bd11f6 100644 +--- a/block/blk-iocost.c ++++ b/block/blk-iocost.c +@@ -2311,7 +2311,14 @@ static void ioc_timer_fn(struct timer_list *timer) + hwm = current_hweight_max(iocg); + new_hwi = hweight_after_donation(iocg, old_hwi, hwm, + usage, &now); +- if (new_hwi < hwm) { ++ /* ++ * Donation calculation assumes hweight_after_donation ++ * to be positive, a condition that a donor w/ hwa < 2 ++ * can't meet. Don't bother with donation if hwa is ++ * below 2. It's not gonna make a meaningful difference ++ * anyway. ++ */ ++ if (new_hwi < hwm && hwa >= 2) { + iocg->hweight_donating = hwa; + iocg->hweight_after_donation = new_hwi; + list_add(&iocg->surplus_list, &surpluses); +diff --git a/block/blk-map.c b/block/blk-map.c +index 4526adde01564..c7f71d83eff18 100644 +--- a/block/blk-map.c ++++ b/block/blk-map.c +@@ -446,7 +446,7 @@ static struct bio *bio_copy_kern(struct request_queue *q, void *data, + if (bytes > len) + bytes = len; + +- page = alloc_page(GFP_NOIO | gfp_mask); ++ page = alloc_page(GFP_NOIO | __GFP_ZERO | gfp_mask); + if (!page) + goto cleanup; + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 652a31fc3bb38..82de39926a9f6 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -763,7 +763,6 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list) + /* this request will be re-inserted to io scheduler queue */ + blk_mq_sched_requeue_request(rq); + +- BUG_ON(!list_empty(&rq->queuelist)); + blk_mq_add_to_requeue_list(rq, true, kick_requeue_list); + } + EXPORT_SYMBOL(blk_mq_requeue_request); +@@ -2148,14 +2147,14 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq) + } + + /* +- * Allow 4x BLK_MAX_REQUEST_COUNT requests on plug queue for multiple ++ * Allow 2x BLK_MAX_REQUEST_COUNT requests on plug queue for multiple + * queues. This is important for md arrays to benefit from merging + * requests. + */ + static inline unsigned short blk_plug_max_rq_count(struct blk_plug *plug) + { + if (plug->multiple_queues) +- return BLK_MAX_REQUEST_COUNT * 4; ++ return BLK_MAX_REQUEST_COUNT * 2; + return BLK_MAX_REQUEST_COUNT; + } + +@@ -4019,6 +4018,19 @@ unsigned int blk_mq_rq_cpu(struct request *rq) + } + EXPORT_SYMBOL(blk_mq_rq_cpu); + ++void blk_mq_cancel_work_sync(struct request_queue *q) ++{ ++ if (queue_is_mq(q)) { ++ struct blk_mq_hw_ctx *hctx; ++ int i; ++ ++ cancel_delayed_work_sync(&q->requeue_work); ++ ++ queue_for_each_hw_ctx(q, hctx, i) ++ cancel_delayed_work_sync(&hctx->run_work); ++ } ++} ++ + static int __init blk_mq_init(void) + { + int i; +diff --git a/block/blk-mq.h b/block/blk-mq.h +index d08779f77a265..7cdca23b6263d 100644 +--- a/block/blk-mq.h ++++ b/block/blk-mq.h +@@ -129,6 +129,8 @@ extern int blk_mq_sysfs_register(struct request_queue *q); + extern void blk_mq_sysfs_unregister(struct request_queue *q); + extern void blk_mq_hctx_kobj_init(struct blk_mq_hw_ctx *hctx); + ++void blk_mq_cancel_work_sync(struct request_queue *q); ++ + void blk_mq_release(struct request_queue *q); + + static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q, +diff --git a/block/blk-pm.c b/block/blk-pm.c +index 17bd020268d42..2dad62cc15727 100644 +--- a/block/blk-pm.c ++++ b/block/blk-pm.c +@@ -163,27 +163,19 @@ EXPORT_SYMBOL(blk_pre_runtime_resume); + /** + * blk_post_runtime_resume - Post runtime resume processing + * @q: the queue of the device +- * @err: return value of the device's runtime_resume function + * + * Description: +- * Update the queue's runtime status according to the return value of the +- * device's runtime_resume function. If the resume was successful, call +- * blk_set_runtime_active() to do the real work of restarting the queue. ++ * For historical reasons, this routine merely calls blk_set_runtime_active() ++ * to do the real work of restarting the queue. It does this regardless of ++ * whether the device's runtime-resume succeeded; even if it failed the ++ * driver or error handler will need to communicate with the device. + * + * This function should be called near the end of the device's + * runtime_resume callback. + */ +-void blk_post_runtime_resume(struct request_queue *q, int err) ++void blk_post_runtime_resume(struct request_queue *q) + { +- if (!q->dev) +- return; +- if (!err) { +- blk_set_runtime_active(q); +- } else { +- spin_lock_irq(&q->queue_lock); +- q->rpm_status = RPM_SUSPENDED; +- spin_unlock_irq(&q->queue_lock); +- } ++ blk_set_runtime_active(q); + } + EXPORT_SYMBOL(blk_post_runtime_resume); + +@@ -201,7 +193,7 @@ EXPORT_SYMBOL(blk_post_runtime_resume); + * runtime PM status and re-enable peeking requests from the queue. It + * should be called before first request is added to the queue. + * +- * This function is also called by blk_post_runtime_resume() for successful ++ * This function is also called by blk_post_runtime_resume() for + * runtime resumes. It does everything necessary to restart the queue. + */ + void blk_set_runtime_active(struct request_queue *q) +diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c +index 614d9d47de36b..4737ec024ee9b 100644 +--- a/block/blk-sysfs.c ++++ b/block/blk-sysfs.c +@@ -805,16 +805,6 @@ static void blk_release_queue(struct kobject *kobj) + + blk_free_queue_stats(q->stats); + +- if (queue_is_mq(q)) { +- struct blk_mq_hw_ctx *hctx; +- int i; +- +- cancel_delayed_work_sync(&q->requeue_work); +- +- queue_for_each_hw_ctx(q, hctx, i) +- cancel_delayed_work_sync(&hctx->run_work); +- } +- + blk_exit_queue(q); + + blk_queue_free_zone_bitmaps(q); +diff --git a/block/blk-wbt.c b/block/blk-wbt.c +index 874c1c37bf0c6..0c119be0e8133 100644 +--- a/block/blk-wbt.c ++++ b/block/blk-wbt.c +@@ -357,6 +357,9 @@ static void wb_timer_fn(struct blk_stat_callback *cb) + unsigned int inflight = wbt_inflight(rwb); + int status; + ++ if (!rwb->rqos.q->disk) ++ return; ++ + status = latency_exceeded(rwb, cb->stat); + + trace_wbt_timer(rwb->rqos.q->disk->bdi, status, rqd->scale_step, +diff --git a/block/blk-zoned.c b/block/blk-zoned.c +index 1d0c76c18fc52..774ecc598bee2 100644 +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -429,9 +429,10 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode, + op = REQ_OP_ZONE_RESET; + + /* Invalidate the page cache, including dirty pages. */ ++ filemap_invalidate_lock(bdev->bd_inode->i_mapping); + ret = blkdev_truncate_zone_range(bdev, mode, &zrange); + if (ret) +- return ret; ++ goto fail; + break; + case BLKOPENZONE: + op = REQ_OP_ZONE_OPEN; +@@ -449,15 +450,9 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode, + ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors, + GFP_KERNEL); + +- /* +- * Invalidate the page cache again for zone reset: writes can only be +- * direct for zoned devices so concurrent writes would not add any page +- * to the page cache after/during reset. The page cache may be filled +- * again due to concurrent reads though and dropping the pages for +- * these is fine. +- */ +- if (!ret && cmd == BLKRESETZONE) +- ret = blkdev_truncate_zone_range(bdev, mode, &zrange); ++fail: ++ if (cmd == BLKRESETZONE) ++ filemap_invalidate_unlock(bdev->bd_inode->i_mapping); + + return ret; + } +diff --git a/block/blk.h b/block/blk.h +index 6c3c00a8fe19d..aab72194d2266 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -184,6 +184,12 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list, + void blk_account_io_start(struct request *req); + void blk_account_io_done(struct request *req, u64 now); + ++/* ++ * Plug flush limits ++ */ ++#define BLK_MAX_REQUEST_COUNT 32 ++#define BLK_PLUG_FLUSH_SIZE (128 * 1024) ++ + /* + * Internal elevator interface + */ +diff --git a/block/elevator.c b/block/elevator.c +index ff45d8388f487..1b5e57f6115f3 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -523,8 +523,6 @@ void elv_unregister_queue(struct request_queue *q) + kobject_del(&e->kobj); + + e->registered = 0; +- /* Re-enable throttling in case elevator disabled it */ +- wbt_enable_default(q); + } + } + +@@ -694,12 +692,18 @@ void elevator_init_mq(struct request_queue *q) + if (!e) + return; + ++ /* ++ * We are called before adding disk, when there isn't any FS I/O, ++ * so freezing queue plus canceling dispatch work is enough to ++ * drain any dispatch activities originated from passthrough ++ * requests, then no need to quiesce queue which may add long boot ++ * latency, especially when lots of disks are involved. ++ */ + blk_mq_freeze_queue(q); +- blk_mq_quiesce_queue(q); ++ blk_mq_cancel_work_sync(q); + + err = blk_mq_init_sched(q, e); + +- blk_mq_unquiesce_queue(q); + blk_mq_unfreeze_queue(q); + + if (err) { +diff --git a/block/genhd.c b/block/genhd.c +index ab12ae6e636e8..2dcedbe4ef046 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -420,6 +420,8 @@ int device_add_disk(struct device *parent, struct gendisk *disk, + DISK_MAX_PARTS); + disk->minors = DISK_MAX_PARTS; + } ++ if (disk->first_minor + disk->minors > MINORMASK + 1) ++ return -EINVAL; + } else { + if (WARN_ON(disk->minors)) + return -EINVAL; +@@ -432,10 +434,6 @@ int device_add_disk(struct device *parent, struct gendisk *disk, + disk->flags |= GENHD_FL_EXT_DEVT; + } + +- ret = disk_alloc_events(disk); +- if (ret) +- goto out_free_ext_minor; +- + /* delay uevents, until we scanned partition table */ + dev_set_uevent_suppress(ddev, 1); + +@@ -446,7 +444,12 @@ int device_add_disk(struct device *parent, struct gendisk *disk, + ddev->devt = MKDEV(disk->major, disk->first_minor); + ret = device_add(ddev); + if (ret) +- goto out_disk_release_events; ++ goto out_free_ext_minor; ++ ++ ret = disk_alloc_events(disk); ++ if (ret) ++ goto out_device_del; ++ + if (!sysfs_deprecated) { + ret = sysfs_create_link(block_depr, &ddev->kobj, + kobject_name(&ddev->kobj)); +@@ -467,11 +470,15 @@ int device_add_disk(struct device *parent, struct gendisk *disk, + + disk->part0->bd_holder_dir = + kobject_create_and_add("holders", &ddev->kobj); +- if (!disk->part0->bd_holder_dir) ++ if (!disk->part0->bd_holder_dir) { ++ ret = -ENOMEM; + goto out_del_integrity; ++ } + disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); +- if (!disk->slave_dir) ++ if (!disk->slave_dir) { ++ ret = -ENOMEM; + goto out_put_holder_dir; ++ } + + ret = bd_register_pending_holders(disk); + if (ret < 0) +@@ -530,8 +537,6 @@ out_del_block_link: + sysfs_remove_link(block_depr, dev_name(ddev)); + out_device_del: + device_del(ddev); +-out_disk_release_events: +- disk_release_events(disk); + out_free_ext_minor: + if (disk->major == BLOCK_EXT_MAJOR) + blk_free_ext_minor(disk->first_minor); +@@ -539,6 +544,20 @@ out_free_ext_minor: + } + EXPORT_SYMBOL(device_add_disk); + ++/** ++ * blk_mark_disk_dead - mark a disk as dead ++ * @disk: disk to mark as dead ++ * ++ * Mark as disk as dead (e.g. surprise removed) and don't accept any new I/O ++ * to this disk. ++ */ ++void blk_mark_disk_dead(struct gendisk *disk) ++{ ++ set_bit(GD_DEAD, &disk->state); ++ blk_queue_start_drain(disk->queue); ++} ++EXPORT_SYMBOL_GPL(blk_mark_disk_dead); ++ + /** + * del_gendisk - remove the gendisk + * @disk: the struct gendisk to remove +@@ -1082,6 +1101,8 @@ static void disk_release(struct device *dev) + might_sleep(); + WARN_ON_ONCE(disk_live(disk)); + ++ blk_mq_cancel_work_sync(disk->queue); ++ + disk_release_events(disk); + kfree(disk->random); + xa_destroy(&disk->part_tbl); +diff --git a/block/ioctl.c b/block/ioctl.c +index eb0491e90b9a0..a31be7fa31a51 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -113,6 +113,7 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, + uint64_t range[2]; + uint64_t start, len; + struct request_queue *q = bdev_get_queue(bdev); ++ struct inode *inode = bdev->bd_inode; + int err; + + if (!(mode & FMODE_WRITE)) +@@ -135,12 +136,17 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode, + if (start + len > i_size_read(bdev->bd_inode)) + return -EINVAL; + ++ filemap_invalidate_lock(inode->i_mapping); + err = truncate_bdev_range(bdev, mode, start, start + len - 1); + if (err) +- return err; ++ goto fail; + +- return blkdev_issue_discard(bdev, start >> 9, len >> 9, +- GFP_KERNEL, flags); ++ err = blkdev_issue_discard(bdev, start >> 9, len >> 9, ++ GFP_KERNEL, flags); ++ ++fail: ++ filemap_invalidate_unlock(inode->i_mapping); ++ return err; + } + + static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, +@@ -148,6 +154,7 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, + { + uint64_t range[2]; + uint64_t start, end, len; ++ struct inode *inode = bdev->bd_inode; + int err; + + if (!(mode & FMODE_WRITE)) +@@ -170,12 +177,17 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, + return -EINVAL; + + /* Invalidate the page cache, including dirty pages */ ++ filemap_invalidate_lock(inode->i_mapping); + err = truncate_bdev_range(bdev, mode, start, end); + if (err) +- return err; ++ goto fail; ++ ++ err = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, ++ BLKDEV_ZERO_NOUNMAP); + +- return blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, +- BLKDEV_ZERO_NOUNMAP); ++fail: ++ filemap_invalidate_unlock(inode->i_mapping); ++ return err; + } + + static int put_ushort(unsigned short __user *argp, unsigned short val) +diff --git a/block/ioprio.c b/block/ioprio.c +index 0e4ff245f2bf2..6f01d35a5145a 100644 +--- a/block/ioprio.c ++++ b/block/ioprio.c +@@ -69,7 +69,14 @@ int ioprio_check_cap(int ioprio) + + switch (class) { + case IOPRIO_CLASS_RT: +- if (!capable(CAP_SYS_NICE) && !capable(CAP_SYS_ADMIN)) ++ /* ++ * Originally this only checked for CAP_SYS_ADMIN, ++ * which was implicitly allowed for pid 0 by security ++ * modules such as SELinux. Make sure we check ++ * CAP_SYS_ADMIN first to avoid a denial/avc for ++ * possibly missing CAP_SYS_NICE permission. ++ */ ++ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_NICE)) + return -EPERM; + fallthrough; + /* rt has prio field too */ +@@ -213,6 +220,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) + pgrp = task_pgrp(current); + else + pgrp = find_vpid(who); ++ read_lock(&tasklist_lock); + do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { + tmpio = get_task_ioprio(p); + if (tmpio < 0) +@@ -222,6 +230,8 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) + else + ret = ioprio_best(ret, tmpio); + } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); ++ read_unlock(&tasklist_lock); ++ + break; + case IOPRIO_WHO_USER: + uid = make_kuid(current_user_ns(), who); +diff --git a/block/mq-deadline.c b/block/mq-deadline.c +index 7f3c3932b723e..cd2342d297048 100644 +--- a/block/mq-deadline.c ++++ b/block/mq-deadline.c +@@ -811,7 +811,7 @@ SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]); + SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]); + SHOW_INT(deadline_writes_starved_show, dd->writes_starved); + SHOW_INT(deadline_front_merges_show, dd->front_merges); +-SHOW_INT(deadline_async_depth_show, dd->front_merges); ++SHOW_INT(deadline_async_depth_show, dd->async_depth); + SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch); + #undef SHOW_INT + #undef SHOW_JIFFIES +@@ -840,7 +840,7 @@ STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX) + STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX); + STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX); + STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1); +-STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX); ++STORE_INT(deadline_async_depth_store, &dd->async_depth, 1, INT_MAX); + STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX); + #undef STORE_FUNCTION + #undef STORE_INT +diff --git a/crypto/Kconfig b/crypto/Kconfig +index 536df4b6b825c..285f82647d2b7 100644 +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -233,12 +233,12 @@ config CRYPTO_DH + + config CRYPTO_ECC + tristate ++ select CRYPTO_RNG_DEFAULT + + config CRYPTO_ECDH + tristate "ECDH algorithm" + select CRYPTO_ECC + select CRYPTO_KPP +- select CRYPTO_RNG_DEFAULT + help + Generic implementation of the ECDH algorithm + +diff --git a/crypto/algapi.c b/crypto/algapi.c +index 43f999dba4dc0..f3d95af3e4284 100644 +--- a/crypto/algapi.c ++++ b/crypto/algapi.c +@@ -1277,3 +1277,4 @@ module_exit(crypto_algapi_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Cryptographic algorithms API"); ++MODULE_SOFTDEP("pre: cryptomgr"); +diff --git a/crypto/api.c b/crypto/api.c +index c4eda56cff891..5ffcd3ab4a753 100644 +--- a/crypto/api.c ++++ b/crypto/api.c +@@ -603,4 +603,3 @@ EXPORT_SYMBOL_GPL(crypto_req_done); + + MODULE_DESCRIPTION("Cryptographic core API"); + MODULE_LICENSE("GPL"); +-MODULE_SOFTDEP("pre: cryptomgr"); +diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c +index a11b3208760f3..f6d3a84e3c214 100644 +--- a/crypto/jitterentropy.c ++++ b/crypto/jitterentropy.c +@@ -265,7 +265,6 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta) + { + __u64 delta2 = jent_delta(ec->last_delta, current_delta); + __u64 delta3 = jent_delta(ec->last_delta2, delta2); +- unsigned int delta_masked = current_delta & JENT_APT_WORD_MASK; + + ec->last_delta = current_delta; + ec->last_delta2 = delta2; +@@ -274,7 +273,7 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta) + * Insert the result of the comparison of two back-to-back time + * deltas. + */ +- jent_apt_insert(ec, delta_masked); ++ jent_apt_insert(ec, current_delta); + + if (!current_delta || !delta2 || !delta3) { + /* RCT with a stuck bit */ +diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c +index d569c7ed6c800..9d10b846ccf73 100644 +--- a/crypto/pcrypt.c ++++ b/crypto/pcrypt.c +@@ -78,12 +78,14 @@ static void pcrypt_aead_enc(struct padata_priv *padata) + { + struct pcrypt_request *preq = pcrypt_padata_request(padata); + struct aead_request *req = pcrypt_request_ctx(preq); ++ int ret; + +- padata->info = crypto_aead_encrypt(req); ++ ret = crypto_aead_encrypt(req); + +- if (padata->info == -EINPROGRESS) ++ if (ret == -EINPROGRESS) + return; + ++ padata->info = ret; + padata_do_serial(padata); + } + +@@ -123,12 +125,14 @@ static void pcrypt_aead_dec(struct padata_priv *padata) + { + struct pcrypt_request *preq = pcrypt_padata_request(padata); + struct aead_request *req = pcrypt_request_ctx(preq); ++ int ret; + +- padata->info = crypto_aead_decrypt(req); ++ ret = crypto_aead_decrypt(req); + +- if (padata->info == -EINPROGRESS) ++ if (ret == -EINPROGRESS) + return; + ++ padata->info = ret; + padata_do_serial(padata); + } + +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index 82b0400985a51..00149657a4bc1 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -1333,7 +1333,7 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, + + if (bs > XBUFSIZE * PAGE_SIZE) { + pr_err("template (%u) too big for buffer (%lu)\n", +- *b_size, XBUFSIZE * PAGE_SIZE); ++ bs, XBUFSIZE * PAGE_SIZE); + goto out; + } + +@@ -1386,8 +1386,7 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, + memset(cur->xbuf[p], 0xff, k); + + skcipher_request_set_crypt(cur->req, cur->sg, +- cur->sg, *b_size, +- iv); ++ cur->sg, bs, iv); + } + + if (secs) { +diff --git a/drivers/Makefile b/drivers/Makefile +index be5d40ae14882..a110338c860c7 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -41,8 +41,7 @@ obj-$(CONFIG_DMADEVICES) += dma/ + # SOC specific infrastructure drivers. + obj-y += soc/ + +-obj-$(CONFIG_VIRTIO) += virtio/ +-obj-$(CONFIG_VIRTIO_PCI_LIB) += virtio/ ++obj-y += virtio/ + obj-$(CONFIG_VDPA) += vdpa/ + obj-$(CONFIG_XEN) += xen/ + +diff --git a/drivers/accessibility/speakup/speakup_dectlk.c b/drivers/accessibility/speakup/speakup_dectlk.c +index 580ec796816bc..78ca4987e619e 100644 +--- a/drivers/accessibility/speakup/speakup_dectlk.c ++++ b/drivers/accessibility/speakup/speakup_dectlk.c +@@ -44,6 +44,7 @@ static struct var_t vars[] = { + { CAPS_START, .u.s = {"[:dv ap 160] " } }, + { CAPS_STOP, .u.s = {"[:dv ap 100 ] " } }, + { RATE, .u.n = {"[:ra %d] ", 180, 75, 650, 0, 0, NULL } }, ++ { PITCH, .u.n = {"[:dv ap %d] ", 122, 50, 350, 0, 0, NULL } }, + { INFLECTION, .u.n = {"[:dv pr %d] ", 100, 0, 10000, 0, 0, NULL } }, + { VOL, .u.n = {"[:dv g5 %d] ", 86, 60, 86, 0, 0, NULL } }, + { PUNCT, .u.n = {"[:pu %c] ", 0, 0, 2, 0, 0, "nsa" } }, +diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c +index b0cb662233f1a..81aff651a0d49 100644 +--- a/drivers/acpi/ac.c ++++ b/drivers/acpi/ac.c +@@ -61,6 +61,7 @@ static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); + + static int ac_sleep_before_get_state_ms; + static int ac_check_pmic = 1; ++static int ac_only; + + static struct acpi_driver acpi_ac_driver = { + .name = "ac", +@@ -93,6 +94,11 @@ static int acpi_ac_get_state(struct acpi_ac *ac) + if (!ac) + return -EINVAL; + ++ if (ac_only) { ++ ac->state = 1; ++ return 0; ++ } ++ + status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, + &ac->state); + if (ACPI_FAILURE(status)) { +@@ -200,6 +206,12 @@ static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d) + return 0; + } + ++static int __init ac_only_quirk(const struct dmi_system_id *d) ++{ ++ ac_only = 1; ++ return 0; ++} ++ + /* Please keep this list alphabetically sorted */ + static const struct dmi_system_id ac_dmi_table[] __initconst = { + { +@@ -209,6 +221,13 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), + }, + }, ++ { ++ /* Kodlix GK45 returning incorrect state */ ++ .callback = ac_only_quirk, ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_NAME, "GK45"), ++ }, ++ }, + { + /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ + .callback = ac_do_not_check_pmic_quirk, +diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h +index d41b810e367c4..4366d36ef1198 100644 +--- a/drivers/acpi/acpica/acglobal.h ++++ b/drivers/acpi/acpica/acglobal.h +@@ -226,6 +226,8 @@ extern struct acpi_bit_register_info + acpi_gbl_bit_register_info[ACPI_NUM_BITREG]; + ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a); + ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b); ++ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a_s0); ++ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b_s0); + + /***************************************************************************** + * +diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c +index 06f3c9df1e22d..8618500f23b39 100644 +--- a/drivers/acpi/acpica/exfield.c ++++ b/drivers/acpi/acpica/exfield.c +@@ -330,12 +330,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, + obj_desc->field.base_byte_offset, + source_desc->buffer.pointer, data_length); + +- if ((obj_desc->field.region_obj->region.address == +- PCC_MASTER_SUBSPACE +- && MASTER_SUBSPACE_COMMAND(obj_desc->field. +- base_byte_offset)) +- || GENERIC_SUBSPACE_COMMAND(obj_desc->field. +- base_byte_offset)) { ++ if (MASTER_SUBSPACE_COMMAND(obj_desc->field.base_byte_offset)) { + + /* Perform the write */ + +diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c +index b639e930d6429..44b7c350ed5ca 100644 +--- a/drivers/acpi/acpica/exoparg1.c ++++ b/drivers/acpi/acpica/exoparg1.c +@@ -1007,7 +1007,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) + (walk_state, return_desc, + &temp_desc); + if (ACPI_FAILURE(status)) { +- goto cleanup; ++ return_ACPI_STATUS ++ (status); + } + + return_desc = temp_desc; +diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c +index 803402aefaeb6..7ee2939c08cd4 100644 +--- a/drivers/acpi/acpica/hwesleep.c ++++ b/drivers/acpi/acpica/hwesleep.c +@@ -104,7 +104,9 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) + + /* Flush caches, as per ACPI specification */ + +- ACPI_FLUSH_CPU_CACHE(); ++ if (sleep_state < ACPI_STATE_S4) { ++ ACPI_FLUSH_CPU_CACHE(); ++ } + + status = acpi_os_enter_sleep(sleep_state, sleep_control, 0); + if (status == AE_CTRL_TERMINATE) { +@@ -147,17 +149,13 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) + + acpi_status acpi_hw_extended_wake_prep(u8 sleep_state) + { +- acpi_status status; + u8 sleep_type_value; + + ACPI_FUNCTION_TRACE(hw_extended_wake_prep); + +- status = acpi_get_sleep_type_data(ACPI_STATE_S0, +- &acpi_gbl_sleep_type_a, +- &acpi_gbl_sleep_type_b); +- if (ACPI_SUCCESS(status)) { ++ if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { + sleep_type_value = +- ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & ++ ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + (void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), +diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c +index 14baa13bf8482..5efa3d8e483e0 100644 +--- a/drivers/acpi/acpica/hwsleep.c ++++ b/drivers/acpi/acpica/hwsleep.c +@@ -110,7 +110,9 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) + + /* Flush caches, as per ACPI specification */ + +- ACPI_FLUSH_CPU_CACHE(); ++ if (sleep_state < ACPI_STATE_S4) { ++ ACPI_FLUSH_CPU_CACHE(); ++ } + + status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control); + if (status == AE_CTRL_TERMINATE) { +@@ -179,7 +181,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) + + acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) + { +- acpi_status status; ++ acpi_status status = AE_OK; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + u32 pm1a_control; +@@ -192,10 +194,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) + * This is unclear from the ACPI Spec, but it is required + * by some machines. + */ +- status = acpi_get_sleep_type_data(ACPI_STATE_S0, +- &acpi_gbl_sleep_type_a, +- &acpi_gbl_sleep_type_b); +- if (ACPI_SUCCESS(status)) { ++ if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) { + sleep_type_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); + sleep_enable_reg_info = +@@ -216,9 +215,9 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state) + + /* Insert the SLP_TYP bits */ + +- pm1a_control |= (acpi_gbl_sleep_type_a << ++ pm1a_control |= (acpi_gbl_sleep_type_a_s0 << + sleep_type_reg_info->bit_position); +- pm1b_control |= (acpi_gbl_sleep_type_b << ++ pm1b_control |= (acpi_gbl_sleep_type_b_s0 << + sleep_type_reg_info->bit_position); + + /* Write the control registers and ignore any errors */ +diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c +index 89b12afed564e..ba77598ee43e8 100644 +--- a/drivers/acpi/acpica/hwxfsleep.c ++++ b/drivers/acpi/acpica/hwxfsleep.c +@@ -162,8 +162,6 @@ acpi_status acpi_enter_sleep_state_s4bios(void) + return_ACPI_STATUS(status); + } + +- ACPI_FLUSH_CPU_CACHE(); +- + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, + (u32)acpi_gbl_FADT.s4_bios_request, 8); + if (ACPI_FAILURE(status)) { +@@ -217,6 +215,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) + return_ACPI_STATUS(status); + } + ++ status = acpi_get_sleep_type_data(ACPI_STATE_S0, ++ &acpi_gbl_sleep_type_a_s0, ++ &acpi_gbl_sleep_type_b_s0); ++ if (ACPI_FAILURE(status)) { ++ acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID; ++ } ++ + /* Execute the _PTS method (Prepare To Sleep) */ + + arg_list.count = 1; +diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c +index e5ba9795ec696..8d7736d2d2699 100644 +--- a/drivers/acpi/acpica/utdelete.c ++++ b/drivers/acpi/acpica/utdelete.c +@@ -422,6 +422,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) + ACPI_WARNING((AE_INFO, + "Obj %p, Reference Count is already zero, cannot decrement\n", + object)); ++ return; + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS, +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index 3b23fb775ac45..f2f8f05662deb 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -1361,9 +1361,17 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res, + res[0].start = pmcg->page0_base_address; + res[0].end = pmcg->page0_base_address + SZ_4K - 1; + res[0].flags = IORESOURCE_MEM; +- res[1].start = pmcg->page1_base_address; +- res[1].end = pmcg->page1_base_address + SZ_4K - 1; +- res[1].flags = IORESOURCE_MEM; ++ /* ++ * The initial version in DEN0049C lacked a way to describe register ++ * page 1, which makes it broken for most PMCG implementations; in ++ * that case, just let the driver fail gracefully if it expects to ++ * find a second memory resource. ++ */ ++ if (node->revision > 0) { ++ res[1].start = pmcg->page1_base_address; ++ res[1].end = pmcg->page1_base_address + SZ_4K - 1; ++ res[1].flags = IORESOURCE_MEM; ++ } + + if (pmcg->overflow_gsiv) + acpi_iort_register_irq(pmcg->overflow_gsiv, "overflow", +diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c +index dae91f906cea9..ead0114f27c9f 100644 +--- a/drivers/acpi/battery.c ++++ b/drivers/acpi/battery.c +@@ -53,6 +53,7 @@ static int battery_bix_broken_package; + static int battery_notification_delay_ms; + static int battery_ac_is_broken; + static int battery_check_pmic = 1; ++static int battery_quirk_notcharging; + static unsigned int cache_time = 1000; + module_param(cache_time, uint, 0644); + MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); +@@ -169,7 +170,7 @@ static int acpi_battery_is_charged(struct acpi_battery *battery) + return 1; + + /* fallback to using design values for broken batteries */ +- if (battery->design_capacity == battery->capacity_now) ++ if (battery->design_capacity <= battery->capacity_now) + return 1; + + /* we don't do any sort of metric based on percentages */ +@@ -217,6 +218,8 @@ static int acpi_battery_get_property(struct power_supply *psy, + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else if (acpi_battery_is_charged(battery)) + val->intval = POWER_SUPPLY_STATUS_FULL; ++ else if (battery_quirk_notcharging) ++ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + break; +@@ -1111,6 +1114,12 @@ battery_do_not_check_pmic_quirk(const struct dmi_system_id *d) + return 0; + } + ++static int __init battery_quirk_not_charging(const struct dmi_system_id *d) ++{ ++ battery_quirk_notcharging = 1; ++ return 0; ++} ++ + static const struct dmi_system_id bat_dmi_table[] __initconst = { + { + /* NEC LZ750/LS */ +@@ -1155,6 +1164,19 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), + }, + }, ++ { ++ /* ++ * On Lenovo ThinkPads the BIOS specification defines ++ * a state when the bits for charging and discharging ++ * are both set to 0. That state is "Not Charging". ++ */ ++ .callback = battery_quirk_not_charging, ++ .ident = "Lenovo ThinkPad", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"), ++ }, ++ }, + {}, + }; + +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index fa923a9292244..dd535b4b9a160 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -98,8 +98,8 @@ int acpi_bus_get_status(struct acpi_device *device) + acpi_status status; + unsigned long long sta; + +- if (acpi_device_always_present(device)) { +- acpi_set_device_status(device, ACPI_STA_DEFAULT); ++ if (acpi_device_override_status(device, &sta)) { ++ acpi_set_device_status(device, sta); + return 0; + } + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index bd482108310cf..6fe28a2d387bd 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -411,7 +411,7 @@ bool acpi_cpc_valid(void) + struct cpc_desc *cpc_ptr; + int cpu; + +- for_each_possible_cpu(cpu) { ++ for_each_present_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + if (!cpc_ptr) + return false; +@@ -1011,7 +1011,14 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) + static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf) + { + struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum); +- struct cpc_register_resource *reg = &cpc_desc->cpc_regs[reg_idx]; ++ struct cpc_register_resource *reg; ++ ++ if (!cpc_desc) { ++ pr_debug("No CPC descriptor for CPU:%d\n", cpunum); ++ return -ENODEV; ++ } ++ ++ reg = &cpc_desc->cpc_regs[reg_idx]; + + if (CPC_IN_PCC(reg)) { + int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index e629e891d1bb3..9b859ff976e89 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -166,6 +166,7 @@ struct acpi_ec_query { + struct transaction transaction; + struct work_struct work; + struct acpi_ec_query_handler *handler; ++ struct acpi_ec *ec; + }; + + static int acpi_ec_query(struct acpi_ec *ec, u8 *data); +@@ -452,6 +453,7 @@ static void acpi_ec_submit_query(struct acpi_ec *ec) + ec_dbg_evt("Command(%s) submitted/blocked", + acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); + ec->nr_pending_queries++; ++ ec->events_in_progress++; + queue_work(ec_wq, &ec->work); + } + } +@@ -518,7 +520,7 @@ static void acpi_ec_enable_event(struct acpi_ec *ec) + #ifdef CONFIG_PM_SLEEP + static void __acpi_ec_flush_work(void) + { +- drain_workqueue(ec_wq); /* flush ec->work */ ++ flush_workqueue(ec_wq); /* flush ec->work */ + flush_workqueue(ec_query_wq); /* flush queries */ + } + +@@ -1103,7 +1105,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) + } + EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); + +-static struct acpi_ec_query *acpi_ec_create_query(u8 *pval) ++static struct acpi_ec_query *acpi_ec_create_query(struct acpi_ec *ec, u8 *pval) + { + struct acpi_ec_query *q; + struct transaction *t; +@@ -1111,11 +1113,13 @@ static struct acpi_ec_query *acpi_ec_create_query(u8 *pval) + q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL); + if (!q) + return NULL; ++ + INIT_WORK(&q->work, acpi_ec_event_processor); + t = &q->transaction; + t->command = ACPI_EC_COMMAND_QUERY; + t->rdata = pval; + t->rlen = 1; ++ q->ec = ec; + return q; + } + +@@ -1132,13 +1136,21 @@ static void acpi_ec_event_processor(struct work_struct *work) + { + struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work); + struct acpi_ec_query_handler *handler = q->handler; ++ struct acpi_ec *ec = q->ec; + + ec_dbg_evt("Query(0x%02x) started", handler->query_bit); ++ + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); ++ + ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); ++ ++ spin_lock_irq(&ec->lock); ++ ec->queries_in_progress--; ++ spin_unlock_irq(&ec->lock); ++ + acpi_ec_delete_query(q); + } + +@@ -1148,7 +1160,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data) + int result; + struct acpi_ec_query *q; + +- q = acpi_ec_create_query(&value); ++ q = acpi_ec_create_query(ec, &value); + if (!q) + return -ENOMEM; + +@@ -1170,19 +1182,20 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data) + } + + /* +- * It is reported that _Qxx are evaluated in a parallel way on +- * Windows: ++ * It is reported that _Qxx are evaluated in a parallel way on Windows: + * https://bugzilla.kernel.org/show_bug.cgi?id=94411 + * +- * Put this log entry before schedule_work() in order to make +- * it appearing before any other log entries occurred during the +- * work queue execution. ++ * Put this log entry before queue_work() to make it appear in the log ++ * before any other messages emitted during workqueue handling. + */ + ec_dbg_evt("Query(0x%02x) scheduled", value); +- if (!queue_work(ec_query_wq, &q->work)) { +- ec_dbg_evt("Query(0x%02x) overlapped", value); +- result = -EBUSY; +- } ++ ++ spin_lock_irq(&ec->lock); ++ ++ ec->queries_in_progress++; ++ queue_work(ec_query_wq, &q->work); ++ ++ spin_unlock_irq(&ec->lock); + + err_exit: + if (result) +@@ -1240,6 +1253,10 @@ static void acpi_ec_event_handler(struct work_struct *work) + ec_dbg_evt("Event stopped"); + + acpi_ec_check_event(ec); ++ ++ spin_lock_irqsave(&ec->lock, flags); ++ ec->events_in_progress--; ++ spin_unlock_irqrestore(&ec->lock, flags); + } + + static void acpi_ec_handle_interrupt(struct acpi_ec *ec) +@@ -2021,6 +2038,7 @@ void acpi_ec_set_gpe_wake_mask(u8 action) + + bool acpi_ec_dispatch_gpe(void) + { ++ bool work_in_progress; + u32 ret; + + if (!first_ec) +@@ -2041,8 +2059,19 @@ bool acpi_ec_dispatch_gpe(void) + if (ret == ACPI_INTERRUPT_HANDLED) + pm_pr_dbg("ACPI EC GPE dispatched\n"); + +- /* Flush the event and query workqueues. */ +- acpi_ec_flush_work(); ++ /* Drain EC work. */ ++ do { ++ acpi_ec_flush_work(); ++ ++ pm_pr_dbg("ACPI EC work flushed\n"); ++ ++ spin_lock_irq(&first_ec->lock); ++ ++ work_in_progress = first_ec->events_in_progress + ++ first_ec->queries_in_progress > 0; ++ ++ spin_unlock_irq(&first_ec->lock); ++ } while (work_in_progress && !pm_wakeup_pending()); + + return false; + } +diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h +index d91b560e88674..54b2be94d23dc 100644 +--- a/drivers/acpi/internal.h ++++ b/drivers/acpi/internal.h +@@ -183,6 +183,8 @@ struct acpi_ec { + struct work_struct work; + unsigned long timestamp; + unsigned long nr_pending_queries; ++ unsigned int events_in_progress; ++ unsigned int queries_in_progress; + bool busy_polling; + unsigned int polling_guard; + }; +diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c +index a371f273f99dd..9cde299eba880 100644 +--- a/drivers/acpi/pmic/intel_pmic.c ++++ b/drivers/acpi/pmic/intel_pmic.c +@@ -211,31 +211,36 @@ static acpi_status intel_pmic_regs_handler(u32 function, + void *handler_context, void *region_context) + { + struct intel_pmic_opregion *opregion = region_context; +- int result = 0; ++ int result = -EINVAL; ++ ++ if (function == ACPI_WRITE) { ++ switch (address) { ++ case 0: ++ return AE_OK; ++ case 1: ++ opregion->ctx.addr |= (*value64 & 0xff) << 8; ++ return AE_OK; ++ case 2: ++ opregion->ctx.addr |= *value64 & 0xff; ++ return AE_OK; ++ case 3: ++ opregion->ctx.val = *value64 & 0xff; ++ return AE_OK; ++ case 4: ++ if (*value64) { ++ result = regmap_write(opregion->regmap, opregion->ctx.addr, ++ opregion->ctx.val); ++ } else { ++ result = regmap_read(opregion->regmap, opregion->ctx.addr, ++ &opregion->ctx.val); ++ } ++ opregion->ctx.addr = 0; ++ } ++ } + +- switch (address) { +- case 0: +- return AE_OK; +- case 1: +- opregion->ctx.addr |= (*value64 & 0xff) << 8; +- return AE_OK; +- case 2: +- opregion->ctx.addr |= *value64 & 0xff; ++ if (function == ACPI_READ && address == 3) { ++ *value64 = opregion->ctx.val; + return AE_OK; +- case 3: +- opregion->ctx.val = *value64 & 0xff; +- return AE_OK; +- case 4: +- if (*value64) { +- result = regmap_write(opregion->regmap, opregion->ctx.addr, +- opregion->ctx.val); +- } else { +- result = regmap_read(opregion->regmap, opregion->ctx.addr, +- &opregion->ctx.val); +- if (result == 0) +- *value64 = opregion->ctx.val; +- } +- memset(&opregion->ctx, 0x00, sizeof(opregion->ctx)); + } + + if (result < 0) { +diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c +index f0ed4414edb1f..c95eedd58f5bf 100644 +--- a/drivers/acpi/power.c ++++ b/drivers/acpi/power.c +@@ -52,7 +52,6 @@ struct acpi_power_resource { + u32 order; + unsigned int ref_count; + u8 state; +- bool wakeup_enabled; + struct mutex resource_lock; + struct list_head dependents; + }; +@@ -615,20 +614,19 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p) + + list_for_each_entry(entry, list, node) { + struct acpi_power_resource *resource = entry->resource; +- int result; + u8 state; + + mutex_lock(&resource->resource_lock); + +- result = acpi_power_get_state(resource, &state); +- if (result) { +- mutex_unlock(&resource->resource_lock); +- return result; +- } +- if (state == ACPI_POWER_RESOURCE_STATE_ON) { +- resource->ref_count++; +- resource->wakeup_enabled = true; +- } ++ /* ++ * Make sure that the power resource state and its reference ++ * counter value are consistent with each other. ++ */ ++ if (!resource->ref_count && ++ !acpi_power_get_state(resource, &state) && ++ state == ACPI_POWER_RESOURCE_STATE_ON) ++ __acpi_power_off(resource); ++ + if (system_level > resource->system_level) + system_level = resource->system_level; + +@@ -711,7 +709,6 @@ int acpi_device_sleep_wake(struct acpi_device *dev, + */ + int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) + { +- struct acpi_power_resource_entry *entry; + int err = 0; + + if (!dev || !dev->wakeup.flags.valid) +@@ -722,26 +719,13 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) + if (dev->wakeup.prepare_count++) + goto out; + +- list_for_each_entry(entry, &dev->wakeup.resources, node) { +- struct acpi_power_resource *resource = entry->resource; +- +- mutex_lock(&resource->resource_lock); +- +- if (!resource->wakeup_enabled) { +- err = acpi_power_on_unlocked(resource); +- if (!err) +- resource->wakeup_enabled = true; +- } +- +- mutex_unlock(&resource->resource_lock); +- +- if (err) { +- dev_err(&dev->dev, +- "Cannot turn wakeup power resources on\n"); +- dev->wakeup.flags.valid = 0; +- goto out; +- } ++ err = acpi_power_on_list(&dev->wakeup.resources); ++ if (err) { ++ dev_err(&dev->dev, "Cannot turn on wakeup power resources\n"); ++ dev->wakeup.flags.valid = 0; ++ goto out; + } ++ + /* + * Passing 3 as the third argument below means the device may be + * put into arbitrary power state afterward. +@@ -771,39 +755,31 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) + + mutex_lock(&acpi_device_lock); + +- if (--dev->wakeup.prepare_count > 0) ++ /* Do nothing if wakeup power has not been enabled for this device. */ ++ if (dev->wakeup.prepare_count <= 0) + goto out; + +- /* +- * Executing the code below even if prepare_count is already zero when +- * the function is called may be useful, for example for initialisation. +- */ +- if (dev->wakeup.prepare_count < 0) +- dev->wakeup.prepare_count = 0; ++ if (--dev->wakeup.prepare_count > 0) ++ goto out; + + err = acpi_device_sleep_wake(dev, 0, 0, 0); + if (err) + goto out; + ++ /* ++ * All of the power resources in the list need to be turned off even if ++ * there are errors. ++ */ + list_for_each_entry(entry, &dev->wakeup.resources, node) { +- struct acpi_power_resource *resource = entry->resource; +- +- mutex_lock(&resource->resource_lock); +- +- if (resource->wakeup_enabled) { +- err = acpi_power_off_unlocked(resource); +- if (!err) +- resource->wakeup_enabled = false; +- } +- +- mutex_unlock(&resource->resource_lock); ++ int ret; + +- if (err) { +- dev_err(&dev->dev, +- "Cannot turn wakeup power resources off\n"); +- dev->wakeup.flags.valid = 0; +- break; +- } ++ ret = acpi_power_off(entry->resource); ++ if (ret && !err) ++ err = ret; ++ } ++ if (err) { ++ dev_err(&dev->dev, "Cannot turn off wakeup power resources\n"); ++ dev->wakeup.flags.valid = 0; + } + + out: +diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c +index e312ebaed8db4..781e312f45342 100644 +--- a/drivers/acpi/property.c ++++ b/drivers/acpi/property.c +@@ -1090,15 +1090,10 @@ struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode) + /* All data nodes have parent pointer so just return that */ + return to_acpi_data_node(fwnode)->parent; + } else if (is_acpi_device_node(fwnode)) { +- acpi_handle handle, parent_handle; ++ struct device *dev = to_acpi_device_node(fwnode)->dev.parent; + +- handle = to_acpi_device_node(fwnode)->handle; +- if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) { +- struct acpi_device *adev; +- +- if (!acpi_bus_get_device(parent_handle, &adev)) +- return acpi_fwnode_handle(adev); +- } ++ if (dev) ++ return acpi_fwnode_handle(to_acpi_device(dev)); + } + + return NULL; +diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c +index ee78a210c6068..3c25ce8c95ba1 100644 +--- a/drivers/acpi/resource.c ++++ b/drivers/acpi/resource.c +@@ -16,6 +16,7 @@ + #include <linux/ioport.h> + #include <linux/slab.h> + #include <linux/irq.h> ++#include <linux/dmi.h> + + #ifdef CONFIG_X86 + #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) +@@ -380,9 +381,58 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) + } + EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); + ++static const struct dmi_system_id medion_laptop[] = { ++ { ++ .ident = "MEDION P15651", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), ++ DMI_MATCH(DMI_BOARD_NAME, "M15T"), ++ }, ++ }, ++ { ++ .ident = "MEDION S17405", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), ++ DMI_MATCH(DMI_BOARD_NAME, "M17T"), ++ }, ++ }, ++ { } ++}; ++ ++struct irq_override_cmp { ++ const struct dmi_system_id *system; ++ unsigned char irq; ++ unsigned char triggering; ++ unsigned char polarity; ++ unsigned char shareable; ++}; ++ ++static const struct irq_override_cmp skip_override_table[] = { ++ { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 }, ++}; ++ ++static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, ++ u8 shareable) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(skip_override_table); i++) { ++ const struct irq_override_cmp *entry = &skip_override_table[i]; ++ ++ if (dmi_check_system(entry->system) && ++ entry->irq == gsi && ++ entry->triggering == triggering && ++ entry->polarity == polarity && ++ entry->shareable == shareable) ++ return false; ++ } ++ ++ return true; ++} ++ + static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, + u8 triggering, u8 polarity, u8 shareable, +- bool legacy) ++ bool check_override) + { + int irq, p, t; + +@@ -401,7 +451,9 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, + * using extended IRQ descriptors we take the IRQ configuration + * from _CRS directly. + */ +- if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { ++ if (check_override && ++ acpi_dev_irq_override(gsi, triggering, polarity, shareable) && ++ !acpi_get_override_irq(gsi, &t, &p)) { + u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; + u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; + +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 5b54c80b9d32a..6e9cd41c5f9b1 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -1690,6 +1690,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) + { + struct list_head resource_list; + bool is_serial_bus_slave = false; ++ static const struct acpi_device_id ignore_serial_bus_ids[] = { + /* + * These devices have multiple I2cSerialBus resources and an i2c-client + * must be instantiated for each, each with its own i2c_device_id. +@@ -1698,11 +1699,18 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) + * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows + * which i2c_device_id to use for each resource. + */ +- static const struct acpi_device_id i2c_multi_instantiate_ids[] = { + {"BSG1160", }, + {"BSG2150", }, + {"INT33FE", }, + {"INT3515", }, ++ /* ++ * HIDs of device with an UartSerialBusV2 resource for which userspace ++ * expects a regular tty cdev to be created (instead of the in kernel ++ * serdev) and which have a kernel driver which expects a platform_dev ++ * such as the rfkill-gpio driver. ++ */ ++ {"BCM4752", }, ++ {"LNV4752", }, + {} + }; + +@@ -1716,8 +1724,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) + fwnode_property_present(&device->fwnode, "baud"))) + return true; + +- /* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */ +- if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids)) ++ if (!acpi_match_device_ids(device, ignore_serial_bus_ids)) + return false; + + INIT_LIST_HEAD(&resource_list); +diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c +index 3023224515abe..7ae09e4b45927 100644 +--- a/drivers/acpi/sleep.c ++++ b/drivers/acpi/sleep.c +@@ -767,6 +767,7 @@ bool acpi_s2idle_wake(void) + return true; + } + ++ pm_wakeup_clear(acpi_sci_irq); + rearm_wake_irq(acpi_sci_irq); + } + +diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c +index 1c48358b43ba3..e0185e841b2a3 100644 +--- a/drivers/acpi/x86/s2idle.c ++++ b/drivers/acpi/x86/s2idle.c +@@ -424,15 +424,11 @@ static int lps0_device_attach(struct acpi_device *adev, + mem_sleep_current = PM_SUSPEND_TO_IDLE; + + /* +- * Some Intel based LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U don't +- * use intel-hid or intel-vbtn but require the EC GPE to be enabled while +- * suspended for certain wakeup devices to work, so mark it as wakeup-capable. +- * +- * Only enable on !AMD as enabling this universally causes problems for a number +- * of AMD based systems. ++ * Some LPS0 systems, like ASUS Zenbook UX430UNR/i7-8550U, require the ++ * EC GPE to be enabled while suspended for certain wakeup devices to ++ * work, so mark it as wakeup-capable. + */ +- if (!acpi_s2idle_vendor_amd()) +- acpi_ec_mark_gpe_for_wake(); ++ acpi_ec_mark_gpe_for_wake(); + + return 0; + } +diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c +index f22f23933063b..b3fb428461c6f 100644 +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -22,58 +22,71 @@ + * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows + * driver bugs. We use DMI matching to match known cases of this. + * +- * We work around this by always reporting ACPI_STA_DEFAULT for these +- * devices. Note this MUST only be done for devices where this is safe. ++ * Likewise sometimes some not-actually present devices are sometimes ++ * reported as present, which may cause issues. + * +- * This forcing of devices to be present is limited to specific CPU (SoC) +- * models both to avoid potentially causing trouble on other models and +- * because some HIDs are re-used on different SoCs for completely +- * different devices. ++ * We work around this by using the below quirk list to override the status ++ * reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0). ++ * Note this MUST only be done for devices where this is safe. ++ * ++ * This status overriding is limited to specific CPU (SoC) models both to ++ * avoid potentially causing trouble on other models and because some HIDs ++ * are re-used on different SoCs for completely different devices. + */ +-struct always_present_id { ++struct override_status_id { + struct acpi_device_id hid[2]; + struct x86_cpu_id cpu_ids[2]; + struct dmi_system_id dmi_ids[2]; /* Optional */ + const char *uid; ++ const char *path; ++ unsigned long long status; + }; + +-#define X86_MATCH(model) X86_MATCH_INTEL_FAM6_MODEL(model, NULL) +- +-#define ENTRY(hid, uid, cpu_models, dmi...) { \ ++#define ENTRY(status, hid, uid, path, cpu_model, dmi...) { \ + { { hid, }, {} }, \ +- { cpu_models, {} }, \ ++ { X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} }, \ + { { .matches = dmi }, {} }, \ + uid, \ ++ path, \ ++ status, \ + } + +-static const struct always_present_id always_present_ids[] = { ++#define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \ ++ ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi) ++ ++#define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \ ++ ENTRY(0, hid, uid, NULL, cpu_model, dmi) ++ ++#define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \ ++ ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi) ++ ++#define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \ ++ ENTRY(0, "", NULL, path, cpu_model, dmi) ++ ++static const struct override_status_id override_status_ids[] = { + /* + * Bay / Cherry Trail PWM directly poked by GPU driver in win10, + * but Linux uses a separate PWM driver, harmless if not used. + */ +- ENTRY("80860F09", "1", X86_MATCH(ATOM_SILVERMONT), {}), +- ENTRY("80862288", "1", X86_MATCH(ATOM_AIRMONT), {}), ++ PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}), ++ PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}), + +- /* Lenovo Yoga Book uses PWM2 for keyboard backlight control */ +- ENTRY("80862289", "2", X86_MATCH(ATOM_AIRMONT), { +- DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"), +- }), + /* + * The INT0002 device is necessary to clear wakeup interrupt sources + * on Cherry Trail devices, without it we get nobody cared IRQ msgs. + */ +- ENTRY("INT0002", "1", X86_MATCH(ATOM_AIRMONT), {}), ++ PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}), + /* + * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides + * the touchscreen ACPI device until a certain time + * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed + * *and* _STA has been called at least 3 times since. + */ +- ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), { ++ PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"), + }), +- ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), { ++ PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"), + }), +@@ -81,54 +94,83 @@ static const struct always_present_id always_present_ids[] = { + /* + * The GPD win BIOS dated 20170221 has disabled the accelerometer, the + * drivers sometimes cause crashes under Windows and this is how the +- * manufacturer has solved this :| Note that the the DMI data is less +- * generic then it seems, a board_vendor of "AMI Corporation" is quite +- * rare and a board_name of "Default String" also is rare. ++ * manufacturer has solved this :| The DMI match may not seem unique, ++ * but it is. In the 67000+ DMI decode dumps from linux-hardware.org ++ * only 116 have board_vendor set to "AMI Corporation" and of those 116 ++ * only the GPD win and pocket entries' board_name is "Default string". + * + * Unfortunately the GPD pocket also uses these strings and its BIOS + * was copy-pasted from the GPD win, so it has a disabled KIOX000A + * node which we should not enable, thus we also check the BIOS date. + */ +- ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), { ++ PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + DMI_MATCH(DMI_BIOS_DATE, "02/21/2017") + }), +- ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), { ++ PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + DMI_MATCH(DMI_BIOS_DATE, "03/20/2017") + }), +- ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), { ++ PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + DMI_MATCH(DMI_BIOS_DATE, "05/25/2017") + }), ++ ++ /* ++ * The GPD win/pocket have a PCI wifi card, but its DSDT has the SDIO ++ * mmc controller enabled and that has a child-device which _PS3 ++ * method sets a GPIO causing the PCI wifi card to turn off. ++ * See above remark about uniqueness of the DMI match. ++ */ ++ NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1", ATOM_AIRMONT, { ++ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), ++ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), ++ DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), ++ }), + }; + +-bool acpi_device_always_present(struct acpi_device *adev) ++bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status) + { + bool ret = false; + unsigned int i; + +- for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) { +- if (acpi_match_device_ids(adev, always_present_ids[i].hid)) ++ for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) { ++ if (!x86_match_cpu(override_status_ids[i].cpu_ids)) + continue; + +- if (!adev->pnp.unique_id || +- strcmp(adev->pnp.unique_id, always_present_ids[i].uid)) ++ if (override_status_ids[i].dmi_ids[0].matches[0].slot && ++ !dmi_check_system(override_status_ids[i].dmi_ids)) + continue; + +- if (!x86_match_cpu(always_present_ids[i].cpu_ids)) +- continue; ++ if (override_status_ids[i].path) { ++ struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL }; ++ bool match; + +- if (always_present_ids[i].dmi_ids[0].matches[0].slot && +- !dmi_check_system(always_present_ids[i].dmi_ids)) +- continue; ++ if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path)) ++ continue; ++ ++ match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0; ++ kfree(path.pointer); ++ ++ if (!match) ++ continue; ++ } else { ++ if (acpi_match_device_ids(adev, override_status_ids[i].hid)) ++ continue; ++ ++ if (!adev->pnp.unique_id || ++ strcmp(adev->pnp.unique_id, override_status_ids[i].uid)) ++ continue; ++ } + ++ *status = override_status_ids[i].status; + ret = true; + break; + } +diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c +index 962041148482c..6c0f7f4f7d1de 100644 +--- a/drivers/amba/bus.c ++++ b/drivers/amba/bus.c +@@ -377,9 +377,6 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent) + void __iomem *tmp; + int i, ret; + +- WARN_ON(dev->irq[0] == (unsigned int)-1); +- WARN_ON(dev->irq[1] == (unsigned int)-1); +- + ret = request_resource(parent, &dev->res); + if (ret) + goto err_out; +diff --git a/drivers/android/binder.c b/drivers/android/binder.c +index 9edacc8b97688..99ae919255f4d 100644 +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -1608,15 +1608,21 @@ static void binder_cleanup_transaction(struct binder_transaction *t, + /** + * binder_get_object() - gets object and checks for valid metadata + * @proc: binder_proc owning the buffer ++ * @u: sender's user pointer to base of buffer + * @buffer: binder_buffer that we're parsing. + * @offset: offset in the @buffer at which to validate an object. + * @object: struct binder_object to read into + * +- * Return: If there's a valid metadata object at @offset in @buffer, the ++ * Copy the binder object at the given offset into @object. If @u is ++ * provided then the copy is from the sender's buffer. If not, then ++ * it is copied from the target's @buffer. ++ * ++ * Return: If there's a valid metadata object at @offset, the + * size of that object. Otherwise, it returns zero. The object + * is read into the struct binder_object pointed to by @object. + */ + static size_t binder_get_object(struct binder_proc *proc, ++ const void __user *u, + struct binder_buffer *buffer, + unsigned long offset, + struct binder_object *object) +@@ -1626,10 +1632,16 @@ static size_t binder_get_object(struct binder_proc *proc, + size_t object_size = 0; + + read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); +- if (offset > buffer->data_size || read_size < sizeof(*hdr) || +- binder_alloc_copy_from_buffer(&proc->alloc, object, buffer, +- offset, read_size)) ++ if (offset > buffer->data_size || read_size < sizeof(*hdr)) + return 0; ++ if (u) { ++ if (copy_from_user(object, u + offset, read_size)) ++ return 0; ++ } else { ++ if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer, ++ offset, read_size)) ++ return 0; ++ } + + /* Ok, now see if we read a complete object. */ + hdr = &object->hdr; +@@ -1702,7 +1714,7 @@ static struct binder_buffer_object *binder_validate_ptr( + b, buffer_offset, + sizeof(object_offset))) + return NULL; +- object_size = binder_get_object(proc, b, object_offset, object); ++ object_size = binder_get_object(proc, NULL, b, object_offset, object); + if (!object_size || object->hdr.type != BINDER_TYPE_PTR) + return NULL; + if (object_offsetp) +@@ -1767,7 +1779,8 @@ static bool binder_validate_fixup(struct binder_proc *proc, + unsigned long buffer_offset; + struct binder_object last_object; + struct binder_buffer_object *last_bbo; +- size_t object_size = binder_get_object(proc, b, last_obj_offset, ++ size_t object_size = binder_get_object(proc, NULL, b, ++ last_obj_offset, + &last_object); + if (object_size != sizeof(*last_bbo)) + return false; +@@ -1870,7 +1883,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, + binder_dec_node(buffer->target_node, 1, 0); + + off_start_offset = ALIGN(buffer->data_size, sizeof(void *)); +- off_end_offset = is_failure ? failed_at : ++ off_end_offset = is_failure && failed_at ? failed_at : + off_start_offset + buffer->offsets_size; + for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; + buffer_offset += sizeof(binder_size_t)) { +@@ -1882,7 +1895,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, + if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, + buffer, buffer_offset, + sizeof(object_offset))) +- object_size = binder_get_object(proc, buffer, ++ object_size = binder_get_object(proc, NULL, buffer, + object_offset, &object); + if (object_size == 0) { + pr_err("transaction release %d bad object at offset %lld, size %zd\n", +@@ -1956,9 +1969,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, + binder_size_t fd_buf_size; + binder_size_t num_valid; + +- if (proc->tsk != current->group_leader) { ++ if (is_failure) { + /* +- * Nothing to do if running in sender context + * The fd fixups have not been applied so no + * fds need to be closed. + */ +@@ -2056,7 +2068,7 @@ static int binder_translate_binder(struct flat_binder_object *fp, + ret = -EINVAL; + goto done; + } +- if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { ++ if (security_binder_transfer_binder(proc->cred, target_proc->cred)) { + ret = -EPERM; + goto done; + } +@@ -2102,7 +2114,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, + proc->pid, thread->pid, fp->handle); + return -EINVAL; + } +- if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { ++ if (security_binder_transfer_binder(proc->cred, target_proc->cred)) { + ret = -EPERM; + goto done; + } +@@ -2190,7 +2202,7 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset, + ret = -EBADF; + goto err_fget; + } +- ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file); ++ ret = security_binder_transfer_file(proc->cred, target_proc->cred, file); + if (ret < 0) { + ret = -EPERM; + goto err_security; +@@ -2270,8 +2282,8 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, + if (!ret) + ret = binder_translate_fd(fd, offset, t, thread, + in_reply_to); +- if (ret < 0) +- return ret; ++ if (ret) ++ return ret > 0 ? -EINVAL : ret; + } + return 0; + } +@@ -2456,6 +2468,7 @@ static void binder_transaction(struct binder_proc *proc, + binder_size_t off_start_offset, off_end_offset; + binder_size_t off_min; + binder_size_t sg_buf_offset, sg_buf_end_offset; ++ binder_size_t user_offset = 0; + struct binder_proc *target_proc = NULL; + struct binder_thread *target_thread = NULL; + struct binder_node *target_node = NULL; +@@ -2470,6 +2483,8 @@ static void binder_transaction(struct binder_proc *proc, + int t_debug_id = atomic_inc_return(&binder_last_id); + char *secctx = NULL; + u32 secctx_sz = 0; ++ const void __user *user_buffer = (const void __user *) ++ (uintptr_t)tr->data.ptr.buffer; + + e = binder_transaction_log_add(&binder_transaction_log); + e->debug_id = t_debug_id; +@@ -2595,8 +2610,8 @@ static void binder_transaction(struct binder_proc *proc, + return_error_line = __LINE__; + goto err_invalid_target_handle; + } +- if (security_binder_transaction(proc->tsk, +- target_proc->tsk) < 0) { ++ if (security_binder_transaction(proc->cred, ++ target_proc->cred) < 0) { + return_error = BR_FAILED_REPLY; + return_error_param = -EPERM; + return_error_line = __LINE__; +@@ -2722,16 +2737,7 @@ static void binder_transaction(struct binder_proc *proc, + u32 secid; + size_t added_size; + +- /* +- * Arguably this should be the task's subjective LSM secid but +- * we can't reliably access the subjective creds of a task +- * other than our own so we must use the objective creds, which +- * are safe to access. The downside is that if a task is +- * temporarily overriding it's creds it will not be reflected +- * here; however, it isn't clear that binder would handle that +- * case well anyway. +- */ +- security_task_getsecid_obj(proc->tsk, &secid); ++ security_cred_getsecid(proc->cred, &secid); + ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); + if (ret) { + return_error = BR_FAILED_REPLY; +@@ -2790,19 +2796,6 @@ static void binder_transaction(struct binder_proc *proc, + t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF); + trace_binder_transaction_alloc_buf(t->buffer); + +- if (binder_alloc_copy_user_to_buffer( +- &target_proc->alloc, +- t->buffer, 0, +- (const void __user *) +- (uintptr_t)tr->data.ptr.buffer, +- tr->data_size)) { +- binder_user_error("%d:%d got transaction with invalid data ptr\n", +- proc->pid, thread->pid); +- return_error = BR_FAILED_REPLY; +- return_error_param = -EFAULT; +- return_error_line = __LINE__; +- goto err_copy_data_failed; +- } + if (binder_alloc_copy_user_to_buffer( + &target_proc->alloc, + t->buffer, +@@ -2847,6 +2840,7 @@ static void binder_transaction(struct binder_proc *proc, + size_t object_size; + struct binder_object object; + binder_size_t object_offset; ++ binder_size_t copy_size; + + if (binder_alloc_copy_from_buffer(&target_proc->alloc, + &object_offset, +@@ -2858,8 +2852,27 @@ static void binder_transaction(struct binder_proc *proc, + return_error_line = __LINE__; + goto err_bad_offset; + } +- object_size = binder_get_object(target_proc, t->buffer, +- object_offset, &object); ++ ++ /* ++ * Copy the source user buffer up to the next object ++ * that will be processed. ++ */ ++ copy_size = object_offset - user_offset; ++ if (copy_size && (user_offset > object_offset || ++ binder_alloc_copy_user_to_buffer( ++ &target_proc->alloc, ++ t->buffer, user_offset, ++ user_buffer + user_offset, ++ copy_size))) { ++ binder_user_error("%d:%d got transaction with invalid data ptr\n", ++ proc->pid, thread->pid); ++ return_error = BR_FAILED_REPLY; ++ return_error_param = -EFAULT; ++ return_error_line = __LINE__; ++ goto err_copy_data_failed; ++ } ++ object_size = binder_get_object(target_proc, user_buffer, ++ t->buffer, object_offset, &object); + if (object_size == 0 || object_offset < off_min) { + binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n", + proc->pid, thread->pid, +@@ -2871,6 +2884,11 @@ static void binder_transaction(struct binder_proc *proc, + return_error_line = __LINE__; + goto err_bad_offset; + } ++ /* ++ * Set offset to the next buffer fragment to be ++ * copied ++ */ ++ user_offset = object_offset + object_size; + + hdr = &object.hdr; + off_min = object_offset + object_size; +@@ -2966,9 +2984,14 @@ static void binder_transaction(struct binder_proc *proc, + } + ret = binder_translate_fd_array(fda, parent, t, thread, + in_reply_to); +- if (ret < 0) { ++ if (!ret) ++ ret = binder_alloc_copy_to_buffer(&target_proc->alloc, ++ t->buffer, ++ object_offset, ++ fda, sizeof(*fda)); ++ if (ret) { + return_error = BR_FAILED_REPLY; +- return_error_param = ret; ++ return_error_param = ret > 0 ? -EINVAL : ret; + return_error_line = __LINE__; + goto err_translate_failed; + } +@@ -3038,6 +3061,19 @@ static void binder_transaction(struct binder_proc *proc, + goto err_bad_object_type; + } + } ++ /* Done processing objects, copy the rest of the buffer */ ++ if (binder_alloc_copy_user_to_buffer( ++ &target_proc->alloc, ++ t->buffer, user_offset, ++ user_buffer + user_offset, ++ tr->data_size - user_offset)) { ++ binder_user_error("%d:%d got transaction with invalid data ptr\n", ++ proc->pid, thread->pid); ++ return_error = BR_FAILED_REPLY; ++ return_error_param = -EFAULT; ++ return_error_line = __LINE__; ++ goto err_copy_data_failed; ++ } + if (t->buffer->oneway_spam_suspect) + tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT; + else +@@ -3185,6 +3221,7 @@ err_invalid_target_handle: + * binder_free_buf() - free the specified buffer + * @proc: binder proc that owns buffer + * @buffer: buffer to be freed ++ * @is_failure: failed to send transaction + * + * If buffer for an async transaction, enqueue the next async + * transaction from the node. +@@ -3194,7 +3231,7 @@ err_invalid_target_handle: + static void + binder_free_buf(struct binder_proc *proc, + struct binder_thread *thread, +- struct binder_buffer *buffer) ++ struct binder_buffer *buffer, bool is_failure) + { + binder_inner_proc_lock(proc); + if (buffer->transaction) { +@@ -3222,7 +3259,7 @@ binder_free_buf(struct binder_proc *proc, + binder_node_inner_unlock(buf_node); + } + trace_binder_transaction_buffer_release(buffer); +- binder_transaction_buffer_release(proc, thread, buffer, 0, false); ++ binder_transaction_buffer_release(proc, thread, buffer, 0, is_failure); + binder_alloc_free_buf(&proc->alloc, buffer); + } + +@@ -3424,7 +3461,7 @@ static int binder_thread_write(struct binder_proc *proc, + proc->pid, thread->pid, (u64)data_ptr, + buffer->debug_id, + buffer->transaction ? "active" : "finished"); +- binder_free_buf(proc, thread, buffer); ++ binder_free_buf(proc, thread, buffer, false); + break; + } + +@@ -4117,7 +4154,7 @@ retry: + buffer->transaction = NULL; + binder_cleanup_transaction(t, "fd fixups failed", + BR_FAILED_REPLY); +- binder_free_buf(proc, thread, buffer); ++ binder_free_buf(proc, thread, buffer, true); + binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, + "%d:%d %stransaction %d fd fixups failed %d/%d, line %d\n", + proc->pid, thread->pid, +@@ -4353,6 +4390,7 @@ static void binder_free_proc(struct binder_proc *proc) + } + binder_alloc_deferred_release(&proc->alloc); + put_task_struct(proc->tsk); ++ put_cred(proc->cred); + binder_stats_deleted(BINDER_STAT_PROC); + kfree(proc); + } +@@ -4430,23 +4468,20 @@ static int binder_thread_release(struct binder_proc *proc, + __release(&t->lock); + + /* +- * If this thread used poll, make sure we remove the waitqueue +- * from any epoll data structures holding it with POLLFREE. +- * waitqueue_active() is safe to use here because we're holding +- * the inner lock. ++ * If this thread used poll, make sure we remove the waitqueue from any ++ * poll data structures holding it. + */ +- if ((thread->looper & BINDER_LOOPER_STATE_POLL) && +- waitqueue_active(&thread->wait)) { +- wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE); +- } ++ if (thread->looper & BINDER_LOOPER_STATE_POLL) ++ wake_up_pollfree(&thread->wait); + + binder_inner_proc_unlock(thread->proc); + + /* +- * This is needed to avoid races between wake_up_poll() above and +- * and ep_remove_waitqueue() called for other reasons (eg the epoll file +- * descriptor being closed); ep_remove_waitqueue() holds an RCU read +- * lock, so we can be sure it's done after calling synchronize_rcu(). ++ * This is needed to avoid races between wake_up_pollfree() above and ++ * someone else removing the last entry from the queue for other reasons ++ * (e.g. ep_remove_wait_queue() being called due to an epoll file ++ * descriptor being closed). Such other users hold an RCU read lock, so ++ * we can be sure they're done after we call synchronize_rcu(). + */ + if (thread->looper & BINDER_LOOPER_STATE_POLL) + synchronize_rcu(); +@@ -4564,7 +4599,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp, + ret = -EBUSY; + goto out; + } +- ret = security_binder_set_context_mgr(proc->tsk); ++ ret = security_binder_set_context_mgr(proc->cred); + if (ret < 0) + goto out; + if (uid_valid(context->binder_context_mgr_uid)) { +@@ -5055,6 +5090,7 @@ static int binder_open(struct inode *nodp, struct file *filp) + spin_lock_init(&proc->outer_lock); + get_task_struct(current->group_leader); + proc->tsk = current->group_leader; ++ proc->cred = get_cred(filp->f_cred); + INIT_LIST_HEAD(&proc->todo); + init_waitqueue_head(&proc->freeze_wait); + proc->default_priority = task_nice(current); +diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c +index 340515f54498c..47bc74a8c7b6f 100644 +--- a/drivers/android/binder_alloc.c ++++ b/drivers/android/binder_alloc.c +@@ -671,7 +671,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, + BUG_ON(buffer->user_data > alloc->buffer + alloc->buffer_size); + + if (buffer->async_transaction) { +- alloc->free_async_space += size + sizeof(struct binder_buffer); ++ alloc->free_async_space += buffer_size + sizeof(struct binder_buffer); + + binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC, + "%d: binder_free_buf size %zd async free %zd\n", +diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h +index 402c4d4362a83..d6b6b8cb73465 100644 +--- a/drivers/android/binder_internal.h ++++ b/drivers/android/binder_internal.h +@@ -364,6 +364,9 @@ struct binder_ref { + * (invariant after initialized) + * @tsk task_struct for group_leader of process + * (invariant after initialized) ++ * @cred struct cred associated with the `struct file` ++ * in binder_open() ++ * (invariant after initialized) + * @deferred_work_node: element for binder_deferred_list + * (protected by binder_deferred_lock) + * @deferred_work: bitmap of deferred work to perform +@@ -426,6 +429,7 @@ struct binder_proc { + struct list_head waiting_threads; + int pid; + struct task_struct *tsk; ++ const struct cred *cred; + struct hlist_node deferred_work_node; + int deferred_work; + int outstanding_txns; +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 186cbf90c8ead..812731e80f8e0 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -442,6 +442,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { + /* AMD */ + { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ + { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ ++ { PCI_VDEVICE(AMD, 0x7901), board_ahci_mobile }, /* AMD Green Sardine */ + /* AMD is using RAID class only for ahci controllers */ + { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 5b3fa2cbe7223..395772fa39432 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -2305,6 +2305,18 @@ int ahci_port_resume(struct ata_port *ap) + EXPORT_SYMBOL_GPL(ahci_port_resume); + + #ifdef CONFIG_PM ++static void ahci_handle_s2idle(struct ata_port *ap) ++{ ++ void __iomem *port_mmio = ahci_port_base(ap); ++ u32 devslp; ++ ++ if (pm_suspend_via_firmware()) ++ return; ++ devslp = readl(port_mmio + PORT_DEVSLP); ++ if ((devslp & PORT_DEVSLP_ADSE)) ++ ata_msleep(ap, devslp_idle_timeout); ++} ++ + static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) + { + const char *emsg = NULL; +@@ -2318,6 +2330,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) + ata_port_freeze(ap); + } + ++ if (acpi_storage_d3(ap->host->dev)) ++ ahci_handle_s2idle(ap); ++ + ahci_rpm_put_port(ap); + return rc; + } +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index eed65311b5d1d..24b67d78cb83d 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2007,7 +2007,7 @@ unsigned int ata_read_log_page(struct ata_device *dev, u8 log, + + retry: + ata_tf_init(dev, &tf); +- if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) && ++ if (ata_dma_enabled(dev) && ata_id_has_read_log_dma_ext(dev->id) && + !(dev->horkage & ATA_HORKAGE_NO_DMA_LOG)) { + tf.command = ATA_CMD_READ_LOG_DMA_EXT; + tf.protocol = ATA_PROT_DMA; +@@ -2031,8 +2031,9 @@ retry: + dev->horkage |= ATA_HORKAGE_NO_DMA_LOG; + goto retry; + } +- ata_dev_err(dev, "Read log page 0x%02x failed, Emask 0x%x\n", +- (unsigned int)page, err_mask); ++ ata_dev_err(dev, ++ "Read log 0x%02x page 0x%02x failed, Emask 0x%x\n", ++ (unsigned int)log, (unsigned int)page, err_mask); + } + + return err_mask; +@@ -2166,6 +2167,9 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev) + struct ata_port *ap = dev->link->ap; + unsigned int err_mask; + ++ if (!ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS)) ++ return; ++ + err_mask = ata_read_log_page(dev, + ATA_LOG_IDENTIFY_DEVICE, + ATA_LOG_SATA_SETTINGS, +@@ -2442,7 +2446,8 @@ static void ata_dev_config_devslp(struct ata_device *dev) + * Check device sleep capability. Get DevSlp timing variables + * from SATA Settings page of Identify Device Data Log. + */ +- if (!ata_id_has_devslp(dev->id)) ++ if (!ata_id_has_devslp(dev->id) || ++ !ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS)) + return; + + err_mask = ata_read_log_page(dev, +@@ -3851,6 +3856,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "VRFDFC22048UCHC-TE*", NULL, ATA_HORKAGE_NODMA }, + /* Odd clown on sil3726/4726 PMPs */ + { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, ++ /* Similar story with ASMedia 1092 */ ++ { "ASMT109x- Config", NULL, ATA_HORKAGE_DISABLE }, + + /* Weird ATAPI devices */ + { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, +@@ -4007,6 +4014,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + + /* devices that don't properly handle TRIM commands */ + { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, }, ++ { "M88V29*", NULL, ATA_HORKAGE_NOTRIM, }, + + /* + * As defined, the DRAT (Deterministic Read After Trim) and RZAT +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index bf9c4b6c5c3d4..1d4a6f1e88cd1 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -93,6 +93,12 @@ static const unsigned long ata_eh_identify_timeouts[] = { + ULONG_MAX, + }; + ++static const unsigned long ata_eh_revalidate_timeouts[] = { ++ 15000, /* Some drives are slow to read log pages when waking-up */ ++ 15000, /* combined time till here is enough even for media access */ ++ ULONG_MAX, ++}; ++ + static const unsigned long ata_eh_flush_timeouts[] = { + 15000, /* be generous with flush */ + 15000, /* ditto */ +@@ -129,6 +135,8 @@ static const struct ata_eh_cmd_timeout_ent + ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = { + { .commands = CMDS(ATA_CMD_ID_ATA, ATA_CMD_ID_ATAPI), + .timeouts = ata_eh_identify_timeouts, }, ++ { .commands = CMDS(ATA_CMD_READ_LOG_EXT, ATA_CMD_READ_LOG_DMA_EXT), ++ .timeouts = ata_eh_revalidate_timeouts, }, + { .commands = CMDS(ATA_CMD_READ_NATIVE_MAX, ATA_CMD_READ_NATIVE_MAX_EXT), + .timeouts = ata_eh_other_timeouts, }, + { .commands = CMDS(ATA_CMD_SET_MAX, ATA_CMD_SET_MAX_EXT), +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index 1fb4611f7eeb9..10303611d17b9 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -2826,8 +2826,19 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) + goto invalid_fld; + } + +- if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0) +- tf->protocol = ATA_PROT_NCQ_NODATA; ++ if ((cdb[2 + cdb_offset] & 0x3) == 0) { ++ /* ++ * When T_LENGTH is zero (No data is transferred), dir should ++ * be DMA_NONE. ++ */ ++ if (scmd->sc_data_direction != DMA_NONE) { ++ fp = 2 + cdb_offset; ++ goto invalid_fld; ++ } ++ ++ if (ata_is_ncq(tf->protocol)) ++ tf->protocol = ATA_PROT_NCQ_NODATA; ++ } + + /* enable LBA */ + tf->flags |= ATA_TFLAG_LBA; +diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c +index f242157bc81bb..9d371859e81ed 100644 +--- a/drivers/ata/pata_hpt37x.c ++++ b/drivers/ata/pata_hpt37x.c +@@ -919,6 +919,20 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) + irqmask &= ~0x10; + pci_write_config_byte(dev, 0x5a, irqmask); + ++ /* ++ * HPT371 chips physically have only one channel, the secondary one, ++ * but the primary channel registers do exist! Go figure... ++ * So, we manually disable the non-existing channel here ++ * (if the BIOS hasn't done this already). ++ */ ++ if (dev->device == PCI_DEVICE_ID_TTI_HPT371) { ++ u8 mcr1; ++ ++ pci_read_config_byte(dev, 0x50, &mcr1); ++ mcr1 &= ~0x04; ++ pci_write_config_byte(dev, 0x50, mcr1); ++ } ++ + /* + * default to pci clock. make sure MA15/16 are set to output + * to prevent drives having problems with 40-pin cables. Needed +@@ -950,14 +964,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) + + if ((freq >> 12) != 0xABCDE) { + int i; +- u8 sr; ++ u16 sr; + u32 total = 0; + + pr_warn("BIOS has not set timing clocks\n"); + + /* This is the process the HPT371 BIOS is reported to use */ + for (i = 0; i < 128; i++) { +- pci_read_config_byte(dev, 0x78, &sr); ++ pci_read_config_word(dev, 0x78, &sr); + total += sr & 0x1FF; + udelay(15); + } +diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c +index e5838b23c9e0a..3b31a4f596d86 100644 +--- a/drivers/ata/sata_fsl.c ++++ b/drivers/ata/sata_fsl.c +@@ -1394,6 +1394,14 @@ static int sata_fsl_init_controller(struct ata_host *host) + return 0; + } + ++static void sata_fsl_host_stop(struct ata_host *host) ++{ ++ struct sata_fsl_host_priv *host_priv = host->private_data; ++ ++ iounmap(host_priv->hcr_base); ++ kfree(host_priv); ++} ++ + /* + * scsi mid-layer and libata interface structures + */ +@@ -1426,6 +1434,8 @@ static struct ata_port_operations sata_fsl_ops = { + .port_start = sata_fsl_port_start, + .port_stop = sata_fsl_port_stop, + ++ .host_stop = sata_fsl_host_stop, ++ + .pmp_attach = sata_fsl_pmp_attach, + .pmp_detach = sata_fsl_pmp_detach, + }; +@@ -1480,9 +1490,9 @@ static int sata_fsl_probe(struct platform_device *ofdev) + host_priv->ssr_base = ssr_base; + host_priv->csr_base = csr_base; + +- irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); +- if (!irq) { +- dev_err(&ofdev->dev, "invalid irq from platform\n"); ++ irq = platform_get_irq(ofdev, 0); ++ if (irq < 0) { ++ retval = irq; + goto error_exit_with_cleanup; + } + host_priv->irq = irq; +@@ -1557,10 +1567,6 @@ static int sata_fsl_remove(struct platform_device *ofdev) + + ata_host_detach(host); + +- irq_dispose_mapping(host_priv->irq); +- iounmap(host_priv->hcr_base); +- kfree(host_priv); +- + return 0; + } + +diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c +index 304accde365c8..6c010d4efa4ae 100644 +--- a/drivers/auxdisplay/charlcd.c ++++ b/drivers/auxdisplay/charlcd.c +@@ -578,6 +578,9 @@ static int charlcd_init(struct charlcd *lcd) + * Since charlcd_init_display() needs to write data, we have to + * enable mark the LCD initialized just before. + */ ++ if (WARN_ON(!lcd->ops->init_display)) ++ return -EINVAL; ++ + ret = lcd->ops->init_display(lcd); + if (ret) + return ret; +diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c +index 1e69cc6d21a0d..ed58083499907 100644 +--- a/drivers/auxdisplay/ht16k33.c ++++ b/drivers/auxdisplay/ht16k33.c +@@ -219,6 +219,15 @@ static const struct backlight_ops ht16k33_bl_ops = { + .check_fb = ht16k33_bl_check_fb, + }; + ++/* ++ * Blank events will be passed to the actual device handling the backlight when ++ * we return zero here. ++ */ ++static int ht16k33_blank(int blank, struct fb_info *info) ++{ ++ return 0; ++} ++ + static int ht16k33_mmap(struct fb_info *info, struct vm_area_struct *vma) + { + struct ht16k33_priv *priv = info->par; +@@ -231,6 +240,7 @@ static const struct fb_ops ht16k33_fb_ops = { + .owner = THIS_MODULE, + .fb_read = fb_sys_read, + .fb_write = fb_sys_write, ++ .fb_blank = ht16k33_blank, + .fb_fillrect = sys_fillrect, + .fb_copyarea = sys_copyarea, + .fb_imageblit = sys_imageblit, +@@ -413,6 +423,33 @@ static int ht16k33_probe(struct i2c_client *client, + if (err) + return err; + ++ /* Backlight */ ++ memset(&bl_props, 0, sizeof(struct backlight_properties)); ++ bl_props.type = BACKLIGHT_RAW; ++ bl_props.max_brightness = MAX_BRIGHTNESS; ++ ++ bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl", ++ &client->dev, priv, ++ &ht16k33_bl_ops, &bl_props); ++ if (IS_ERR(bl)) { ++ dev_err(&client->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++ err = of_property_read_u32(node, "default-brightness-level", ++ &dft_brightness); ++ if (err) { ++ dft_brightness = MAX_BRIGHTNESS; ++ } else if (dft_brightness > MAX_BRIGHTNESS) { ++ dev_warn(&client->dev, ++ "invalid default brightness level: %u, using %u\n", ++ dft_brightness, MAX_BRIGHTNESS); ++ dft_brightness = MAX_BRIGHTNESS; ++ } ++ ++ bl->props.brightness = dft_brightness; ++ ht16k33_bl_update_status(bl); ++ + /* Framebuffer (2 bytes per column) */ + BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE); + fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL); +@@ -445,6 +482,7 @@ static int ht16k33_probe(struct i2c_client *client, + fbdev->info->screen_size = HT16K33_FB_SIZE; + fbdev->info->fix = ht16k33_fb_fix; + fbdev->info->var = ht16k33_fb_var; ++ fbdev->info->bl_dev = bl; + fbdev->info->pseudo_palette = NULL; + fbdev->info->flags = FBINFO_FLAG_DEFAULT; + fbdev->info->par = priv; +@@ -460,34 +498,6 @@ static int ht16k33_probe(struct i2c_client *client, + goto err_fbdev_unregister; + } + +- /* Backlight */ +- memset(&bl_props, 0, sizeof(struct backlight_properties)); +- bl_props.type = BACKLIGHT_RAW; +- bl_props.max_brightness = MAX_BRIGHTNESS; +- +- bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl", +- &client->dev, priv, +- &ht16k33_bl_ops, &bl_props); +- if (IS_ERR(bl)) { +- dev_err(&client->dev, "failed to register backlight\n"); +- err = PTR_ERR(bl); +- goto err_fbdev_unregister; +- } +- +- err = of_property_read_u32(node, "default-brightness-level", +- &dft_brightness); +- if (err) { +- dft_brightness = MAX_BRIGHTNESS; +- } else if (dft_brightness > MAX_BRIGHTNESS) { +- dev_warn(&client->dev, +- "invalid default brightness level: %u, using %u\n", +- dft_brightness, MAX_BRIGHTNESS); +- dft_brightness = MAX_BRIGHTNESS; +- } +- +- bl->props.brightness = dft_brightness; +- ht16k33_bl_update_status(bl); +- + ht16k33_fb_queue(priv); + return 0; + +diff --git a/drivers/auxdisplay/img-ascii-lcd.c b/drivers/auxdisplay/img-ascii-lcd.c +index 1cce409ce5cac..e33ce0151cdfd 100644 +--- a/drivers/auxdisplay/img-ascii-lcd.c ++++ b/drivers/auxdisplay/img-ascii-lcd.c +@@ -280,6 +280,16 @@ static int img_ascii_lcd_display(struct img_ascii_lcd_ctx *ctx, + if (msg[count - 1] == '\n') + count--; + ++ if (!count) { ++ /* clear the LCD */ ++ devm_kfree(&ctx->pdev->dev, ctx->message); ++ ctx->message = NULL; ++ ctx->message_len = 0; ++ memset(ctx->curr, ' ', ctx->cfg->num_chars); ++ ctx->cfg->update(ctx); ++ return 0; ++ } ++ + new_msg = devm_kmalloc(&ctx->pdev->dev, count + 1, GFP_KERNEL); + if (!new_msg) + return -ENOMEM; +diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c +index 38ba08628ccb3..2578b2d454397 100644 +--- a/drivers/auxdisplay/lcd2s.c ++++ b/drivers/auxdisplay/lcd2s.c +@@ -238,7 +238,7 @@ static int lcd2s_redefine_char(struct charlcd *lcd, char *esc) + if (buf[1] > 7) + return 1; + +- i = 0; ++ i = 2; + shift = 0; + value = 0; + while (*esc && i < LCD2S_CHARACTER_SIZE + 2) { +@@ -298,6 +298,10 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c, + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) + return -EIO; + ++ lcd2s = devm_kzalloc(&i2c->dev, sizeof(*lcd2s), GFP_KERNEL); ++ if (!lcd2s) ++ return -ENOMEM; ++ + /* Test, if the display is responding */ + err = lcd2s_i2c_smbus_write_byte(i2c, LCD2S_CMD_DISPLAY_OFF); + if (err < 0) +@@ -307,12 +311,6 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c, + if (!lcd) + return -ENOMEM; + +- lcd2s = kzalloc(sizeof(struct lcd2s_data), GFP_KERNEL); +- if (!lcd2s) { +- err = -ENOMEM; +- goto fail1; +- } +- + lcd->drvdata = lcd2s; + lcd2s->i2c = i2c; + lcd2s->charlcd = lcd; +@@ -321,26 +319,24 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c, + err = device_property_read_u32(&i2c->dev, "display-height-chars", + &lcd->height); + if (err) +- goto fail2; ++ goto fail1; + + err = device_property_read_u32(&i2c->dev, "display-width-chars", + &lcd->width); + if (err) +- goto fail2; ++ goto fail1; + + lcd->ops = &lcd2s_ops; + + err = charlcd_register(lcd2s->charlcd); + if (err) +- goto fail2; ++ goto fail1; + + i2c_set_clientdata(i2c, lcd2s); + return 0; + +-fail2: +- kfree(lcd2s); + fail1: +- kfree(lcd); ++ charlcd_free(lcd2s->charlcd); + return err; + } + +@@ -349,7 +345,7 @@ static int lcd2s_i2c_remove(struct i2c_client *i2c) + struct lcd2s_data *lcd2s = i2c_get_clientdata(i2c); + + charlcd_unregister(lcd2s->charlcd); +- kfree(lcd2s->charlcd); ++ charlcd_free(lcd2s->charlcd); + return 0; + } + +diff --git a/drivers/base/component.c b/drivers/base/component.c +index 5e79299f6c3ff..870485cbbb87c 100644 +--- a/drivers/base/component.c ++++ b/drivers/base/component.c +@@ -246,7 +246,7 @@ static int try_to_bring_up_master(struct master *master, + return 0; + } + +- if (!devres_open_group(master->parent, NULL, GFP_KERNEL)) ++ if (!devres_open_group(master->parent, master, GFP_KERNEL)) + return -ENOMEM; + + /* Found all components */ +@@ -258,6 +258,7 @@ static int try_to_bring_up_master(struct master *master, + return ret; + } + ++ devres_close_group(master->parent, NULL); + master->bound = true; + return 1; + } +@@ -282,7 +283,7 @@ static void take_down_master(struct master *master) + { + if (master->bound) { + master->ops->unbind(master->parent); +- devres_release_group(master->parent, NULL); ++ devres_release_group(master->parent, master); + master->bound = false; + } + } +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 249da496581a0..8e73a34e10055 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -485,8 +485,7 @@ static void device_link_release_fn(struct work_struct *work) + /* Ensure that all references to the link object have been dropped. */ + device_link_synchronize_removal(); + +- while (refcount_dec_not_one(&link->rpm_active)) +- pm_runtime_put(link->supplier); ++ pm_runtime_release_supplier(link, true); + + put_device(link->consumer); + put_device(link->supplier); +@@ -821,9 +820,7 @@ struct device_link *device_link_add(struct device *consumer, + dev_bus_name(supplier), dev_name(supplier), + dev_bus_name(consumer), dev_name(consumer)); + if (device_register(&link->link_dev)) { +- put_device(consumer); +- put_device(supplier); +- kfree(link); ++ put_device(&link->link_dev); + link = NULL; + goto out; + } +diff --git a/drivers/base/dd.c b/drivers/base/dd.c +index 68ea1f949daa9..6b66306932016 100644 +--- a/drivers/base/dd.c ++++ b/drivers/base/dd.c +@@ -629,6 +629,9 @@ re_probe: + drv->remove(dev); + + devres_release_all(dev); ++ arch_teardown_dma_ops(dev); ++ kfree(dev->dma_range_map); ++ dev->dma_range_map = NULL; + driver_sysfs_remove(dev); + dev->driver = NULL; + dev_set_drvdata(dev, NULL); +@@ -1208,6 +1211,8 @@ static void __device_release_driver(struct device *dev, struct device *parent) + + devres_release_all(dev); + arch_teardown_dma_ops(dev); ++ kfree(dev->dma_range_map); ++ dev->dma_range_map = NULL; + dev->driver = NULL; + dev_set_drvdata(dev, NULL); + if (dev->pm_domain && dev->pm_domain->dismiss) +diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c +index 8be352ab4ddbf..fa13ad49d2116 100644 +--- a/drivers/base/devtmpfs.c ++++ b/drivers/base/devtmpfs.c +@@ -59,8 +59,15 @@ static struct dentry *public_dev_mount(struct file_system_type *fs_type, int fla + const char *dev_name, void *data) + { + struct super_block *s = mnt->mnt_sb; ++ int err; ++ + atomic_inc(&s->s_active); + down_write(&s->s_umount); ++ err = reconfigure_single(s, flags, data); ++ if (err < 0) { ++ deactivate_locked_super(s); ++ return ERR_PTR(err); ++ } + return dget(s->s_root); + } + +diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c +index bdbedc6660a87..ef904b8b112e6 100644 +--- a/drivers/base/firmware_loader/main.c ++++ b/drivers/base/firmware_loader/main.c +@@ -100,12 +100,15 @@ static struct firmware_cache fw_cache; + extern struct builtin_fw __start_builtin_fw[]; + extern struct builtin_fw __end_builtin_fw[]; + +-static void fw_copy_to_prealloc_buf(struct firmware *fw, ++static bool fw_copy_to_prealloc_buf(struct firmware *fw, + void *buf, size_t size) + { +- if (!buf || size < fw->size) +- return; ++ if (!buf) ++ return true; ++ if (size < fw->size) ++ return false; + memcpy(buf, fw->data, fw->size); ++ return true; + } + + static bool fw_get_builtin_firmware(struct firmware *fw, const char *name, +@@ -117,9 +120,7 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name, + if (strcmp(name, b_fw->name) == 0) { + fw->size = b_fw->size; + fw->data = b_fw->data; +- fw_copy_to_prealloc_buf(fw, buf, size); +- +- return true; ++ return fw_copy_to_prealloc_buf(fw, buf, size); + } + } + +diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c +index cbea78e79f3df..6bce40e2506e5 100644 +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -711,6 +711,7 @@ static void dpm_noirq_resume_devices(pm_message_t state) + dev = to_device(dpm_noirq_list.next); + get_device(dev); + list_move_tail(&dev->power.entry, &dpm_late_early_list); ++ + mutex_unlock(&dpm_list_mtx); + + if (!is_async(dev)) { +@@ -725,8 +726,9 @@ static void dpm_noirq_resume_devices(pm_message_t state) + } + } + +- mutex_lock(&dpm_list_mtx); + put_device(dev); ++ ++ mutex_lock(&dpm_list_mtx); + } + mutex_unlock(&dpm_list_mtx); + async_synchronize_full(); +@@ -852,6 +854,7 @@ void dpm_resume_early(pm_message_t state) + dev = to_device(dpm_late_early_list.next); + get_device(dev); + list_move_tail(&dev->power.entry, &dpm_suspended_list); ++ + mutex_unlock(&dpm_list_mtx); + + if (!is_async(dev)) { +@@ -865,8 +868,10 @@ void dpm_resume_early(pm_message_t state) + pm_dev_err(dev, state, " early", error); + } + } +- mutex_lock(&dpm_list_mtx); ++ + put_device(dev); ++ ++ mutex_lock(&dpm_list_mtx); + } + mutex_unlock(&dpm_list_mtx); + async_synchronize_full(); +@@ -1029,7 +1034,12 @@ void dpm_resume(pm_message_t state) + } + if (!list_empty(&dev->power.entry)) + list_move_tail(&dev->power.entry, &dpm_prepared_list); ++ ++ mutex_unlock(&dpm_list_mtx); ++ + put_device(dev); ++ ++ mutex_lock(&dpm_list_mtx); + } + mutex_unlock(&dpm_list_mtx); + async_synchronize_full(); +@@ -1051,7 +1061,7 @@ static void device_complete(struct device *dev, pm_message_t state) + const char *info = NULL; + + if (dev->power.syscore) +- return; ++ goto out; + + device_lock(dev); + +@@ -1081,6 +1091,7 @@ static void device_complete(struct device *dev, pm_message_t state) + + device_unlock(dev); + ++out: + pm_runtime_put(dev); + } + +@@ -1106,14 +1117,16 @@ void dpm_complete(pm_message_t state) + get_device(dev); + dev->power.is_prepared = false; + list_move(&dev->power.entry, &list); ++ + mutex_unlock(&dpm_list_mtx); + + trace_device_pm_callback_start(dev, "", state.event); + device_complete(dev, state); + trace_device_pm_callback_end(dev, 0); + +- mutex_lock(&dpm_list_mtx); + put_device(dev); ++ ++ mutex_lock(&dpm_list_mtx); + } + list_splice(&list, &dpm_list); + mutex_unlock(&dpm_list_mtx); +@@ -1298,17 +1311,21 @@ static int dpm_noirq_suspend_devices(pm_message_t state) + error = device_suspend_noirq(dev); + + mutex_lock(&dpm_list_mtx); ++ + if (error) { + pm_dev_err(dev, state, " noirq", error); + dpm_save_failed_dev(dev_name(dev)); +- put_device(dev); +- break; +- } +- if (!list_empty(&dev->power.entry)) ++ } else if (!list_empty(&dev->power.entry)) { + list_move(&dev->power.entry, &dpm_noirq_list); ++ } ++ ++ mutex_unlock(&dpm_list_mtx); ++ + put_device(dev); + +- if (async_error) ++ mutex_lock(&dpm_list_mtx); ++ ++ if (error || async_error) + break; + } + mutex_unlock(&dpm_list_mtx); +@@ -1475,23 +1492,28 @@ int dpm_suspend_late(pm_message_t state) + struct device *dev = to_device(dpm_suspended_list.prev); + + get_device(dev); ++ + mutex_unlock(&dpm_list_mtx); + + error = device_suspend_late(dev); + + mutex_lock(&dpm_list_mtx); ++ + if (!list_empty(&dev->power.entry)) + list_move(&dev->power.entry, &dpm_late_early_list); + + if (error) { + pm_dev_err(dev, state, " late", error); + dpm_save_failed_dev(dev_name(dev)); +- put_device(dev); +- break; + } ++ ++ mutex_unlock(&dpm_list_mtx); ++ + put_device(dev); + +- if (async_error) ++ mutex_lock(&dpm_list_mtx); ++ ++ if (error || async_error) + break; + } + mutex_unlock(&dpm_list_mtx); +@@ -1751,21 +1773,27 @@ int dpm_suspend(pm_message_t state) + struct device *dev = to_device(dpm_prepared_list.prev); + + get_device(dev); ++ + mutex_unlock(&dpm_list_mtx); + + error = device_suspend(dev); + + mutex_lock(&dpm_list_mtx); ++ + if (error) { + pm_dev_err(dev, state, "", error); + dpm_save_failed_dev(dev_name(dev)); +- put_device(dev); +- break; +- } +- if (!list_empty(&dev->power.entry)) ++ } else if (!list_empty(&dev->power.entry)) { + list_move(&dev->power.entry, &dpm_suspended_list); ++ } ++ ++ mutex_unlock(&dpm_list_mtx); ++ + put_device(dev); +- if (async_error) ++ ++ mutex_lock(&dpm_list_mtx); ++ ++ if (error || async_error) + break; + } + mutex_unlock(&dpm_list_mtx); +@@ -1794,9 +1822,6 @@ static int device_prepare(struct device *dev, pm_message_t state) + int (*callback)(struct device *) = NULL; + int ret = 0; + +- if (dev->power.syscore) +- return 0; +- + /* + * If a device's parent goes into runtime suspend at the wrong time, + * it won't be possible to resume the device. To prevent this we +@@ -1805,6 +1830,9 @@ static int device_prepare(struct device *dev, pm_message_t state) + */ + pm_runtime_get_noresume(dev); + ++ if (dev->power.syscore) ++ return 0; ++ + device_lock(dev); + + dev->power.wakeup_path = false; +@@ -1878,10 +1906,11 @@ int dpm_prepare(pm_message_t state) + device_block_probing(); + + mutex_lock(&dpm_list_mtx); +- while (!list_empty(&dpm_list)) { ++ while (!list_empty(&dpm_list) && !error) { + struct device *dev = to_device(dpm_list.next); + + get_device(dev); ++ + mutex_unlock(&dpm_list_mtx); + + trace_device_pm_callback_start(dev, "", state.event); +@@ -1889,21 +1918,23 @@ int dpm_prepare(pm_message_t state) + trace_device_pm_callback_end(dev, error); + + mutex_lock(&dpm_list_mtx); +- if (error) { +- if (error == -EAGAIN) { +- put_device(dev); +- error = 0; +- continue; +- } ++ ++ if (!error) { ++ dev->power.is_prepared = true; ++ if (!list_empty(&dev->power.entry)) ++ list_move_tail(&dev->power.entry, &dpm_prepared_list); ++ } else if (error == -EAGAIN) { ++ error = 0; ++ } else { + dev_info(dev, "not prepared for power transition: code %d\n", + error); +- put_device(dev); +- break; + } +- dev->power.is_prepared = true; +- if (!list_empty(&dev->power.entry)) +- list_move_tail(&dev->power.entry, &dpm_prepared_list); ++ ++ mutex_unlock(&dpm_list_mtx); ++ + put_device(dev); ++ ++ mutex_lock(&dpm_list_mtx); + } + mutex_unlock(&dpm_list_mtx); + trace_suspend_resume(TPS("dpm_prepare"), state.event, false); +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index ec94049442b99..44ae3909e64bb 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -305,19 +305,40 @@ static int rpm_get_suppliers(struct device *dev) + return 0; + } + ++/** ++ * pm_runtime_release_supplier - Drop references to device link's supplier. ++ * @link: Target device link. ++ * @check_idle: Whether or not to check if the supplier device is idle. ++ * ++ * Drop all runtime PM references associated with @link to its supplier device ++ * and if @check_idle is set, check if that device is idle (and so it can be ++ * suspended). ++ */ ++void pm_runtime_release_supplier(struct device_link *link, bool check_idle) ++{ ++ struct device *supplier = link->supplier; ++ ++ /* ++ * The additional power.usage_count check is a safety net in case ++ * the rpm_active refcount becomes saturated, in which case ++ * refcount_dec_not_one() would return true forever, but it is not ++ * strictly necessary. ++ */ ++ while (refcount_dec_not_one(&link->rpm_active) && ++ atomic_read(&supplier->power.usage_count) > 0) ++ pm_runtime_put_noidle(supplier); ++ ++ if (check_idle) ++ pm_request_idle(supplier); ++} ++ + static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend) + { + struct device_link *link; + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, +- device_links_read_lock_held()) { +- +- while (refcount_dec_not_one(&link->rpm_active)) +- pm_runtime_put_noidle(link->supplier); +- +- if (try_to_suspend) +- pm_request_idle(link->supplier); +- } ++ device_links_read_lock_held()) ++ pm_runtime_release_supplier(link, try_to_suspend); + } + + static void rpm_put_suppliers(struct device *dev) +@@ -1770,9 +1791,7 @@ void pm_runtime_drop_link(struct device_link *link) + return; + + pm_runtime_drop_link_count(link->consumer); +- +- while (refcount_dec_not_one(&link->rpm_active)) +- pm_runtime_put(link->supplier); ++ pm_runtime_release_supplier(link, true); + } + + static bool pm_runtime_need_not_resume(struct device *dev) +diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c +index 99bda0da23a82..8666590201c9a 100644 +--- a/drivers/base/power/wakeup.c ++++ b/drivers/base/power/wakeup.c +@@ -34,7 +34,8 @@ suspend_state_t pm_suspend_target_state; + bool events_check_enabled __read_mostly; + + /* First wakeup IRQ seen by the kernel in the last cycle. */ +-unsigned int pm_wakeup_irq __read_mostly; ++static unsigned int wakeup_irq[2] __read_mostly; ++static DEFINE_RAW_SPINLOCK(wakeup_irq_lock); + + /* If greater than 0 and the system is suspending, terminate the suspend. */ + static atomic_t pm_abort_suspend __read_mostly; +@@ -942,19 +943,45 @@ void pm_system_cancel_wakeup(void) + atomic_dec_if_positive(&pm_abort_suspend); + } + +-void pm_wakeup_clear(bool reset) ++void pm_wakeup_clear(unsigned int irq_number) + { +- pm_wakeup_irq = 0; +- if (reset) ++ raw_spin_lock_irq(&wakeup_irq_lock); ++ ++ if (irq_number && wakeup_irq[0] == irq_number) ++ wakeup_irq[0] = wakeup_irq[1]; ++ else ++ wakeup_irq[0] = 0; ++ ++ wakeup_irq[1] = 0; ++ ++ raw_spin_unlock_irq(&wakeup_irq_lock); ++ ++ if (!irq_number) + atomic_set(&pm_abort_suspend, 0); + } + + void pm_system_irq_wakeup(unsigned int irq_number) + { +- if (pm_wakeup_irq == 0) { +- pm_wakeup_irq = irq_number; ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&wakeup_irq_lock, flags); ++ ++ if (wakeup_irq[0] == 0) ++ wakeup_irq[0] = irq_number; ++ else if (wakeup_irq[1] == 0) ++ wakeup_irq[1] = irq_number; ++ else ++ irq_number = 0; ++ ++ raw_spin_unlock_irqrestore(&wakeup_irq_lock, flags); ++ ++ if (irq_number) + pm_system_wakeup(); +- } ++} ++ ++unsigned int pm_wakeup_irq(void) ++{ ++ return wakeup_irq[0]; + } + + /** +diff --git a/drivers/base/property.c b/drivers/base/property.c +index 453918eb7390c..4c77837769c6e 100644 +--- a/drivers/base/property.c ++++ b/drivers/base/property.c +@@ -1269,8 +1269,10 @@ fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, + + fwnode_graph_for_each_endpoint(fwnode, ep) { + node = fwnode_graph_get_remote_port_parent(ep); +- if (!fwnode_device_is_available(node)) ++ if (!fwnode_device_is_available(node)) { ++ fwnode_handle_put(node); + continue; ++ } + + ret = match(node, con_id, data); + fwnode_handle_put(node); +diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c +index d2656581a6085..4a446259a184e 100644 +--- a/drivers/base/regmap/regmap-irq.c ++++ b/drivers/base/regmap/regmap-irq.c +@@ -189,11 +189,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data) + ret = regmap_write(map, reg, d->mask_buf[i]); + if (d->chip->clear_ack) { + if (d->chip->ack_invert && !ret) +- ret = regmap_write(map, reg, +- d->mask_buf[i]); ++ ret = regmap_write(map, reg, UINT_MAX); + else if (!ret) +- ret = regmap_write(map, reg, +- ~d->mask_buf[i]); ++ ret = regmap_write(map, reg, 0); + } + if (ret != 0) + dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", +@@ -556,11 +554,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) + data->status_buf[i]); + if (chip->clear_ack) { + if (chip->ack_invert && !ret) +- ret = regmap_write(map, reg, +- data->status_buf[i]); ++ ret = regmap_write(map, reg, UINT_MAX); + else if (!ret) +- ret = regmap_write(map, reg, +- ~data->status_buf[i]); ++ ret = regmap_write(map, reg, 0); + } + if (ret != 0) + dev_err(map->dev, "Failed to ack 0x%x: %d\n", +@@ -817,13 +813,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, + d->status_buf[i] & d->mask_buf[i]); + if (chip->clear_ack) { + if (chip->ack_invert && !ret) +- ret = regmap_write(map, reg, +- (d->status_buf[i] & +- d->mask_buf[i])); ++ ret = regmap_write(map, reg, UINT_MAX); + else if (!ret) +- ret = regmap_write(map, reg, +- ~(d->status_buf[i] & +- d->mask_buf[i])); ++ ret = regmap_write(map, reg, 0); + } + if (ret != 0) { + dev_err(map->dev, "Failed to ack 0x%x: %d\n", +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index 21a0c2562ec06..f7811641ed5ae 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -647,6 +647,7 @@ int regmap_attach_dev(struct device *dev, struct regmap *map, + if (ret) + return ret; + ++ regmap_debugfs_exit(map); + regmap_debugfs_init(map); + + /* Add a devres resource for dev_get_regmap() */ +diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c +index c46f6a8e14d23..3ba1232ce8451 100644 +--- a/drivers/base/swnode.c ++++ b/drivers/base/swnode.c +@@ -535,7 +535,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode, + return -ENOENT; + + if (nargs_prop) { +- error = property_entry_read_int_array(swnode->node->properties, ++ error = property_entry_read_int_array(ref->node->properties, + nargs_prop, sizeof(u32), + &nargs_prop_val, 1); + if (error) +diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c +index a093644ac39fb..aab48b292a3bb 100644 +--- a/drivers/block/ataflop.c ++++ b/drivers/block/ataflop.c +@@ -298,6 +298,7 @@ static struct atari_floppy_struct { + disk change detection) */ + int flags; /* flags */ + struct gendisk *disk[NUM_DISK_MINORS]; ++ bool registered[NUM_DISK_MINORS]; + int ref; + int type; + struct blk_mq_tag_set tag_set; +@@ -456,10 +457,20 @@ static DEFINE_TIMER(fd_timer, check_change); + + static void fd_end_request_cur(blk_status_t err) + { ++ DPRINT(("fd_end_request_cur(), bytes %d of %d\n", ++ blk_rq_cur_bytes(fd_request), ++ blk_rq_bytes(fd_request))); ++ + if (!blk_update_request(fd_request, err, + blk_rq_cur_bytes(fd_request))) { ++ DPRINT(("calling __blk_mq_end_request()\n")); + __blk_mq_end_request(fd_request, err); + fd_request = NULL; ++ } else { ++ /* requeue rest of request */ ++ DPRINT(("calling blk_mq_requeue_request()\n")); ++ blk_mq_requeue_request(fd_request, true); ++ fd_request = NULL; + } + } + +@@ -653,9 +664,6 @@ static inline void copy_buffer(void *from, void *to) + *p2++ = *p1++; + } + +- +- +- + /* General Interrupt Handling */ + + static void (*FloppyIRQHandler)( int status ) = NULL; +@@ -700,12 +708,21 @@ static void fd_error( void ) + if (fd_request->error_count >= MAX_ERRORS) { + printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); + fd_end_request_cur(BLK_STS_IOERR); ++ finish_fdc(); ++ return; + } + else if (fd_request->error_count == RECALIBRATE_ERRORS) { + printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); + if (SelectedDrive != -1) + SUD.track = -1; + } ++ /* need to re-run request to recalibrate */ ++ atari_disable_irq( IRQ_MFP_FDC ); ++ ++ setup_req_params( SelectedDrive ); ++ do_fd_action( SelectedDrive ); ++ ++ atari_enable_irq( IRQ_MFP_FDC ); + } + + +@@ -732,8 +749,10 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) + if (type) { + type--; + if (type >= NUM_DISK_MINORS || +- minor2disktype[type].drive_types > DriveType) ++ minor2disktype[type].drive_types > DriveType) { ++ finish_fdc(); + return -EINVAL; ++ } + } + + q = unit[drive].disk[type]->queue; +@@ -751,6 +770,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) + } + + if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { ++ finish_fdc(); + ret = -EINVAL; + goto out; + } +@@ -791,6 +811,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) + + wait_for_completion(&format_wait); + ++ finish_fdc(); + ret = FormatError ? -EIO : 0; + out: + blk_mq_unquiesce_queue(q); +@@ -825,6 +846,7 @@ static void do_fd_action( int drive ) + else { + /* all sectors finished */ + fd_end_request_cur(BLK_STS_OK); ++ finish_fdc(); + return; + } + } +@@ -1229,6 +1251,7 @@ static void fd_rwsec_done1(int status) + else { + /* all sectors finished */ + fd_end_request_cur(BLK_STS_OK); ++ finish_fdc(); + } + return; + +@@ -1350,7 +1373,7 @@ static void fd_times_out(struct timer_list *unused) + + static void finish_fdc( void ) + { +- if (!NeedSeek) { ++ if (!NeedSeek || !stdma_is_locked_by(floppy_irq)) { + finish_fdc_done( 0 ); + } + else { +@@ -1385,7 +1408,8 @@ static void finish_fdc_done( int dummy ) + start_motor_off_timer(); + + local_irq_save(flags); +- stdma_release(); ++ if (stdma_is_locked_by(floppy_irq)) ++ stdma_release(); + local_irq_restore(flags); + + DPRINT(("finish_fdc() finished\n")); +@@ -1475,15 +1499,6 @@ static void setup_req_params( int drive ) + ReqTrack, ReqSector, (unsigned long)ReqData )); + } + +-static void ataflop_commit_rqs(struct blk_mq_hw_ctx *hctx) +-{ +- spin_lock_irq(&ataflop_lock); +- atari_disable_irq(IRQ_MFP_FDC); +- finish_fdc(); +- atari_enable_irq(IRQ_MFP_FDC); +- spin_unlock_irq(&ataflop_lock); +-} +- + static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + const struct blk_mq_queue_data *bd) + { +@@ -1491,6 +1506,10 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + int drive = floppy - unit; + int type = floppy->type; + ++ DPRINT(("Queue request: drive %d type %d sectors %d of %d last %d\n", ++ drive, type, blk_rq_cur_sectors(bd->rq), ++ blk_rq_sectors(bd->rq), bd->last)); ++ + spin_lock_irq(&ataflop_lock); + if (fd_request) { + spin_unlock_irq(&ataflop_lock); +@@ -1511,6 +1530,7 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + /* drive not connected */ + printk(KERN_ERR "Unknown Device: fd%d\n", drive ); + fd_end_request_cur(BLK_STS_IOERR); ++ stdma_release(); + goto out; + } + +@@ -1527,11 +1547,13 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + if (--type >= NUM_DISK_MINORS) { + printk(KERN_WARNING "fd%d: invalid disk format", drive ); + fd_end_request_cur(BLK_STS_IOERR); ++ stdma_release(); + goto out; + } + if (minor2disktype[type].drive_types > DriveType) { + printk(KERN_WARNING "fd%d: unsupported disk format", drive ); + fd_end_request_cur(BLK_STS_IOERR); ++ stdma_release(); + goto out; + } + type = minor2disktype[type].index; +@@ -1550,8 +1572,6 @@ static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx, + setup_req_params( drive ); + do_fd_action( drive ); + +- if (bd->last) +- finish_fdc(); + atari_enable_irq( IRQ_MFP_FDC ); + + out: +@@ -1634,6 +1654,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, + /* what if type > 0 here? Overwrite specified entry ? */ + if (type) { + /* refuse to re-set a predefined type for now */ ++ finish_fdc(); + return -EINVAL; + } + +@@ -1701,8 +1722,10 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, + + /* sanity check */ + if (setprm.track != dtp->blocks/dtp->spt/2 || +- setprm.head != 2) ++ setprm.head != 2) { ++ finish_fdc(); + return -EINVAL; ++ } + + UDT = dtp; + set_capacity(disk, UDT->blocks); +@@ -1962,7 +1985,6 @@ static const struct block_device_operations floppy_fops = { + + static const struct blk_mq_ops ataflop_mq_ops = { + .queue_rq = ataflop_queue_rq, +- .commit_rqs = ataflop_commit_rqs, + }; + + static int ataflop_alloc_disk(unsigned int drive, unsigned int type) +@@ -1986,8 +2008,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type) + return 0; + } + +-static DEFINE_MUTEX(ataflop_probe_lock); +- + static void ataflop_probe(dev_t dev) + { + int drive = MINOR(dev) & 3; +@@ -1998,12 +2018,46 @@ static void ataflop_probe(dev_t dev) + + if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS) + return; +- mutex_lock(&ataflop_probe_lock); + if (!unit[drive].disk[type]) { +- if (ataflop_alloc_disk(drive, type) == 0) ++ if (ataflop_alloc_disk(drive, type) == 0) { + add_disk(unit[drive].disk[type]); ++ unit[drive].registered[type] = true; ++ } ++ } ++} ++ ++static void atari_floppy_cleanup(void) ++{ ++ int i; ++ int type; ++ ++ for (i = 0; i < FD_MAX_UNITS; i++) { ++ for (type = 0; type < NUM_DISK_MINORS; type++) { ++ if (!unit[i].disk[type]) ++ continue; ++ del_gendisk(unit[i].disk[type]); ++ blk_cleanup_queue(unit[i].disk[type]->queue); ++ put_disk(unit[i].disk[type]); ++ } ++ blk_mq_free_tag_set(&unit[i].tag_set); ++ } ++ ++ del_timer_sync(&fd_timer); ++ atari_stram_free(DMABuffer); ++} ++ ++static void atari_cleanup_floppy_disk(struct atari_floppy_struct *fs) ++{ ++ int type; ++ ++ for (type = 0; type < NUM_DISK_MINORS; type++) { ++ if (!fs->disk[type]) ++ continue; ++ if (fs->registered[type]) ++ del_gendisk(fs->disk[type]); ++ blk_cleanup_disk(fs->disk[type]); + } +- mutex_unlock(&ataflop_probe_lock); ++ blk_mq_free_tag_set(&fs->tag_set); + } + + static int __init atari_floppy_init (void) +@@ -2015,11 +2069,6 @@ static int __init atari_floppy_init (void) + /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */ + return -ENODEV; + +- mutex_lock(&ataflop_probe_lock); +- ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe); +- if (ret) +- goto out_unlock; +- + for (i = 0; i < FD_MAX_UNITS; i++) { + memset(&unit[i].tag_set, 0, sizeof(unit[i].tag_set)); + unit[i].tag_set.ops = &ataflop_mq_ops; +@@ -2065,6 +2114,7 @@ static int __init atari_floppy_init (void) + unit[i].track = -1; + unit[i].flags = 0; + add_disk(unit[i].disk[0]); ++ unit[i].registered[0] = true; + } + + printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n", +@@ -2072,18 +2122,17 @@ static int __init atari_floppy_init (void) + UseTrackbuffer ? "" : "no "); + config_types(); + +- return 0; ++ ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe); ++ if (ret) { ++ printk(KERN_ERR "atari_floppy_init: cannot register block device\n"); ++ atari_floppy_cleanup(); ++ } ++ return ret; + + err: +- while (--i >= 0) { +- blk_cleanup_queue(unit[i].disk[0]->queue); +- put_disk(unit[i].disk[0]); +- blk_mq_free_tag_set(&unit[i].tag_set); +- } ++ while (--i >= 0) ++ atari_cleanup_floppy_disk(&unit[i]); + +- unregister_blkdev(FLOPPY_MAJOR, "fd"); +-out_unlock: +- mutex_unlock(&ataflop_probe_lock); + return ret; + } + +@@ -2128,22 +2177,8 @@ __setup("floppy=", atari_floppy_setup); + + static void __exit atari_floppy_exit(void) + { +- int i, type; +- +- for (i = 0; i < FD_MAX_UNITS; i++) { +- for (type = 0; type < NUM_DISK_MINORS; type++) { +- if (!unit[i].disk[type]) +- continue; +- del_gendisk(unit[i].disk[type]); +- blk_cleanup_queue(unit[i].disk[type]->queue); +- put_disk(unit[i].disk[type]); +- } +- blk_mq_free_tag_set(&unit[i].tag_set); +- } + unregister_blkdev(FLOPPY_MAJOR, "fd"); +- +- del_timer_sync(&fd_timer); +- atari_stram_free( DMABuffer ); ++ atari_floppy_cleanup(); + } + + module_init(atari_floppy_init) +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index fef79ea52e3ed..4a6a74177b3c9 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -1014,7 +1014,7 @@ static DECLARE_DELAYED_WORK(fd_timer, fd_timer_workfn); + static void cancel_activity(void) + { + do_floppy = NULL; +- cancel_delayed_work_sync(&fd_timer); ++ cancel_delayed_work(&fd_timer); + cancel_work_sync(&floppy_work); + } + +@@ -3080,6 +3080,8 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr) + } + } + ++#define MAX_LEN (1UL << MAX_ORDER << PAGE_SHIFT) ++ + static int raw_cmd_copyin(int cmd, void __user *param, + struct floppy_raw_cmd **rcmd) + { +@@ -3107,7 +3109,7 @@ loop: + ptr->resultcode = 0; + + if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { +- if (ptr->length <= 0) ++ if (ptr->length <= 0 || ptr->length >= MAX_LEN) + return -EINVAL; + ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length); + fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length); +@@ -4478,6 +4480,7 @@ static const struct blk_mq_ops floppy_mq_ops = { + }; + + static struct platform_device floppy_device[N_DRIVE]; ++static bool registered[N_DRIVE]; + + static bool floppy_available(int drive) + { +@@ -4693,6 +4696,8 @@ static int __init do_floppy_init(void) + if (err) + goto out_remove_drives; + ++ registered[drive] = true; ++ + device_add_disk(&floppy_device[drive].dev, disks[drive][0], + NULL); + } +@@ -4703,7 +4708,8 @@ out_remove_drives: + while (drive--) { + if (floppy_available(drive)) { + del_gendisk(disks[drive][0]); +- platform_device_unregister(&floppy_device[drive]); ++ if (registered[drive]) ++ platform_device_unregister(&floppy_device[drive]); + } + } + out_release_dma: +@@ -4946,7 +4952,8 @@ static void __exit floppy_module_exit(void) + if (disks[drive][i]) + del_gendisk(disks[drive][i]); + } +- platform_device_unregister(&floppy_device[drive]); ++ if (registered[drive]) ++ platform_device_unregister(&floppy_device[drive]); + } + for (i = 0; i < ARRAY_SIZE(floppy_type); i++) { + if (disks[drive][i]) +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 7bf4686af774e..92f9d32bfae5e 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -79,6 +79,7 @@ + #include <linux/ioprio.h> + #include <linux/blk-cgroup.h> + #include <linux/sched/mm.h> ++#include <linux/statfs.h> + + #include "loop.h" + +@@ -272,19 +273,6 @@ static void __loop_update_dio(struct loop_device *lo, bool dio) + blk_mq_unfreeze_queue(lo->lo_queue); + } + +-/** +- * loop_validate_block_size() - validates the passed in block size +- * @bsize: size to validate +- */ +-static int +-loop_validate_block_size(unsigned short bsize) +-{ +- if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) +- return -EINVAL; +- +- return 0; +-} +- + /** + * loop_set_size() - sets device size and notifies userspace + * @lo: struct loop_device to set the size for +@@ -952,8 +940,13 @@ static void loop_config_discard(struct loop_device *lo) + granularity = 0; + + } else { ++ struct kstatfs sbuf; ++ + max_discard_sectors = UINT_MAX >> 9; +- granularity = inode->i_sb->s_blocksize; ++ if (!vfs_statfs(&file->f_path, &sbuf)) ++ granularity = sbuf.f_bsize; ++ else ++ max_discard_sectors = 0; + } + + if (max_discard_sectors) { +@@ -1236,7 +1229,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + } + + if (config->block_size) { +- error = loop_validate_block_size(config->block_size); ++ error = blk_validate_block_size(config->block_size); + if (error) + goto out_unlock; + } +@@ -1759,7 +1752,7 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg) + if (lo->lo_state != Lo_bound) + return -ENXIO; + +- err = loop_validate_block_size(arg); ++ err = blk_validate_block_size(arg); + if (err) + return err; + +@@ -2442,7 +2435,7 @@ static int loop_control_remove(int idx) + int ret; + + if (idx < 0) { +- pr_warn("deleting an unspecified loop device is not supported.\n"); ++ pr_warn_once("deleting an unspecified loop device is not supported.\n"); + return -EINVAL; + } + +diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c +index 901855717cb53..ba61e72741eab 100644 +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -4112,7 +4112,7 @@ static void mtip_pci_remove(struct pci_dev *pdev) + "Completion workers still active!\n"); + } + +- blk_set_queue_dying(dd->queue); ++ blk_mark_disk_dead(dd->disk); + set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag); + + /* Clean up the block layer. */ +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 1183f7872b713..577c7dba5d78d 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -122,10 +122,10 @@ struct nbd_device { + struct work_struct remove_work; + + struct list_head list; +- struct task_struct *task_recv; + struct task_struct *task_setup; + + unsigned long flags; ++ pid_t pid; /* pid of nbd-client, if attached */ + + char *backend; + }; +@@ -217,7 +217,7 @@ static ssize_t pid_show(struct device *dev, + struct gendisk *disk = dev_to_disk(dev); + struct nbd_device *nbd = (struct nbd_device *)disk->private_data; + +- return sprintf(buf, "%d\n", task_pid_nr(nbd->task_recv)); ++ return sprintf(buf, "%d\n", nbd->pid); + } + + static const struct device_attribute pid_attr = { +@@ -329,7 +329,7 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, + nbd->config->bytesize = bytesize; + nbd->config->blksize_bits = __ffs(blksize); + +- if (!nbd->task_recv) ++ if (!nbd->pid) + return 0; + + if (nbd->config->flags & NBD_FLAG_SEND_TRIM) { +@@ -1241,7 +1241,7 @@ static void nbd_config_put(struct nbd_device *nbd) + if (test_and_clear_bit(NBD_RT_HAS_PID_FILE, + &config->runtime_flags)) + device_remove_file(disk_to_dev(nbd->disk), &pid_attr); +- nbd->task_recv = NULL; ++ nbd->pid = 0; + if (test_and_clear_bit(NBD_RT_HAS_BACKEND_FILE, + &config->runtime_flags)) { + device_remove_file(disk_to_dev(nbd->disk), &backend_attr); +@@ -1282,7 +1282,7 @@ static int nbd_start_device(struct nbd_device *nbd) + int num_connections = config->num_connections; + int error = 0, i; + +- if (nbd->task_recv) ++ if (nbd->pid) + return -EBUSY; + if (!config->socks) + return -EINVAL; +@@ -1301,7 +1301,7 @@ static int nbd_start_device(struct nbd_device *nbd) + } + + blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections); +- nbd->task_recv = current; ++ nbd->pid = task_pid_nr(current); + + nbd_parse_flags(nbd); + +@@ -1557,8 +1557,8 @@ static int nbd_dbg_tasks_show(struct seq_file *s, void *unused) + { + struct nbd_device *nbd = s->private; + +- if (nbd->task_recv) +- seq_printf(s, "recv: %d\n", task_pid_nr(nbd->task_recv)); ++ if (nbd->pid) ++ seq_printf(s, "recv: %d\n", nbd->pid); + + return 0; + } +@@ -1749,11 +1749,11 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) + disk->major = NBD_MAJOR; + + /* Too big first_minor can cause duplicate creation of +- * sysfs files/links, since first_minor will be truncated to +- * byte in __device_add_disk(). ++ * sysfs files/links, since index << part_shift might overflow, or ++ * MKDEV() expect that the max bits of first_minor is 20. + */ + disk->first_minor = index << part_shift; +- if (disk->first_minor > 0xff) { ++ if (disk->first_minor < index || disk->first_minor > MINORMASK) { + err = -EINVAL; + goto out_free_idr; + } +@@ -2135,7 +2135,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) + mutex_lock(&nbd->config_lock); + config = nbd->config; + if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) || +- !nbd->task_recv) { ++ !nbd->pid) { + dev_err(nbd_to_dev(nbd), + "not configured, cannot reconfigure\n"); + ret = -EINVAL; +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index e65c9d706f6fb..c4a52f33604dc 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -7182,7 +7182,7 @@ static ssize_t do_rbd_remove(struct bus_type *bus, + * IO to complete/fail. + */ + blk_mq_freeze_queue(rbd_dev->disk->queue); +- blk_set_queue_dying(rbd_dev->disk->queue); ++ blk_mark_disk_dead(rbd_dev->disk); + } + + del_gendisk(rbd_dev->disk); +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index 72902104f1112..1becbbb3be139 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1290,7 +1290,8 @@ free_shadow: + rinfo->ring_ref[i] = GRANT_INVALID_REF; + } + } +- free_pages((unsigned long)rinfo->ring.sring, get_order(info->nr_ring_pages * XEN_PAGE_SIZE)); ++ free_pages_exact(rinfo->ring.sring, ++ info->nr_ring_pages * XEN_PAGE_SIZE); + rinfo->ring.sring = NULL; + + if (rinfo->irq) +@@ -1374,9 +1375,15 @@ static int blkif_get_final_status(enum blk_req_status s1, + return BLKIF_RSP_OKAY; + } + +-static bool blkif_completion(unsigned long *id, +- struct blkfront_ring_info *rinfo, +- struct blkif_response *bret) ++/* ++ * Return values: ++ * 1 response processed. ++ * 0 missing further responses. ++ * -1 error while processing. ++ */ ++static int blkif_completion(unsigned long *id, ++ struct blkfront_ring_info *rinfo, ++ struct blkif_response *bret) + { + int i = 0; + struct scatterlist *sg; +@@ -1399,7 +1406,7 @@ static bool blkif_completion(unsigned long *id, + + /* Wait the second response if not yet here. */ + if (s2->status < REQ_DONE) +- return false; ++ return 0; + + bret->status = blkif_get_final_status(s->status, + s2->status); +@@ -1450,42 +1457,43 @@ static bool blkif_completion(unsigned long *id, + } + /* Add the persistent grant into the list of free grants */ + for (i = 0; i < num_grant; i++) { +- if (gnttab_query_foreign_access(s->grants_used[i]->gref)) { ++ if (!gnttab_try_end_foreign_access(s->grants_used[i]->gref)) { + /* + * If the grant is still mapped by the backend (the + * backend has chosen to make this grant persistent) + * we add it at the head of the list, so it will be + * reused first. + */ +- if (!info->feature_persistent) +- pr_alert_ratelimited("backed has not unmapped grant: %u\n", +- s->grants_used[i]->gref); ++ if (!info->feature_persistent) { ++ pr_alert("backed has not unmapped grant: %u\n", ++ s->grants_used[i]->gref); ++ return -1; ++ } + list_add(&s->grants_used[i]->node, &rinfo->grants); + rinfo->persistent_gnts_c++; + } else { + /* +- * If the grant is not mapped by the backend we end the +- * foreign access and add it to the tail of the list, +- * so it will not be picked again unless we run out of +- * persistent grants. ++ * If the grant is not mapped by the backend we add it ++ * to the tail of the list, so it will not be picked ++ * again unless we run out of persistent grants. + */ +- gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 0UL); + s->grants_used[i]->gref = GRANT_INVALID_REF; + list_add_tail(&s->grants_used[i]->node, &rinfo->grants); + } + } + if (s->req.operation == BLKIF_OP_INDIRECT) { + for (i = 0; i < INDIRECT_GREFS(num_grant); i++) { +- if (gnttab_query_foreign_access(s->indirect_grants[i]->gref)) { +- if (!info->feature_persistent) +- pr_alert_ratelimited("backed has not unmapped grant: %u\n", +- s->indirect_grants[i]->gref); ++ if (!gnttab_try_end_foreign_access(s->indirect_grants[i]->gref)) { ++ if (!info->feature_persistent) { ++ pr_alert("backed has not unmapped grant: %u\n", ++ s->indirect_grants[i]->gref); ++ return -1; ++ } + list_add(&s->indirect_grants[i]->node, &rinfo->grants); + rinfo->persistent_gnts_c++; + } else { + struct page *indirect_page; + +- gnttab_end_foreign_access(s->indirect_grants[i]->gref, 0, 0UL); + /* + * Add the used indirect page back to the list of + * available pages for indirect grefs. +@@ -1500,7 +1508,7 @@ static bool blkif_completion(unsigned long *id, + } + } + +- return true; ++ return 1; + } + + static irqreturn_t blkif_interrupt(int irq, void *dev_id) +@@ -1511,9 +1519,12 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + unsigned long flags; + struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id; + struct blkfront_info *info = rinfo->dev_info; ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; + +- if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) ++ if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { ++ xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS); + return IRQ_HANDLED; ++ } + + spin_lock_irqsave(&rinfo->ring_lock, flags); + again: +@@ -1529,6 +1540,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + unsigned long id; + unsigned int op; + ++ eoiflag = 0; ++ + RING_COPY_RESPONSE(&rinfo->ring, i, &bret); + id = bret.id; + +@@ -1561,12 +1574,17 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + } + + if (bret.operation != BLKIF_OP_DISCARD) { ++ int ret; ++ + /* + * We may need to wait for an extra response if the + * I/O request is split in 2 + */ +- if (!blkif_completion(&id, rinfo, &bret)) ++ ret = blkif_completion(&id, rinfo, &bret); ++ if (!ret) + continue; ++ if (unlikely(ret < 0)) ++ goto err; + } + + if (add_id_to_freelist(rinfo, id)) { +@@ -1645,6 +1663,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + + spin_unlock_irqrestore(&rinfo->ring_lock, flags); + ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + + err: +@@ -1652,6 +1672,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + + spin_unlock_irqrestore(&rinfo->ring_lock, flags); + ++ /* No EOI in order to avoid further interrupts. */ ++ + pr_alert("%s disabled for further use\n", info->gd->disk_name); + return IRQ_HANDLED; + } +@@ -1669,8 +1691,7 @@ static int setup_blkring(struct xenbus_device *dev, + for (i = 0; i < info->nr_ring_pages; i++) + rinfo->ring_ref[i] = GRANT_INVALID_REF; + +- sring = (struct blkif_sring *)__get_free_pages(GFP_NOIO | __GFP_HIGH, +- get_order(ring_size)); ++ sring = alloc_pages_exact(ring_size, GFP_NOIO); + if (!sring) { + xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); + return -ENOMEM; +@@ -1680,7 +1701,7 @@ static int setup_blkring(struct xenbus_device *dev, + + err = xenbus_grant_ring(dev, rinfo->ring.sring, info->nr_ring_pages, gref); + if (err < 0) { +- free_pages((unsigned long)sring, get_order(ring_size)); ++ free_pages_exact(sring, ring_size); + rinfo->ring.sring = NULL; + goto fail; + } +@@ -1691,8 +1712,8 @@ static int setup_blkring(struct xenbus_device *dev, + if (err) + goto fail; + +- err = bind_evtchn_to_irqhandler(rinfo->evtchn, blkif_interrupt, 0, +- "blkif", rinfo); ++ err = bind_evtchn_to_irqhandler_lateeoi(rinfo->evtchn, blkif_interrupt, ++ 0, "blkif", rinfo); + if (err <= 0) { + xenbus_dev_fatal(dev, err, + "bind_evtchn_to_irqhandler failed"); +@@ -2119,7 +2140,7 @@ static void blkfront_closing(struct blkfront_info *info) + + /* No more blkif_request(). */ + blk_mq_stop_hw_queues(info->rq); +- blk_set_queue_dying(info->rq); ++ blk_mark_disk_dead(info->gd); + set_capacity(info->gd, 0); + + for_each_rinfo(info, rinfo, i) { +@@ -2520,11 +2541,10 @@ static void purge_persistent_grants(struct blkfront_info *info) + list_for_each_entry_safe(gnt_list_entry, tmp, &rinfo->grants, + node) { + if (gnt_list_entry->gref == GRANT_INVALID_REF || +- gnttab_query_foreign_access(gnt_list_entry->gref)) ++ !gnttab_try_end_foreign_access(gnt_list_entry->gref)) + continue; + + list_del(&gnt_list_entry->node); +- gnttab_end_foreign_access(gnt_list_entry->gref, 0, 0UL); + rinfo->persistent_gnts_c--; + gnt_list_entry->gref = GRANT_INVALID_REF; + list_add_tail(&gnt_list_entry->node, &rinfo->grants); +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index fcaf2750f68f7..6383c81ac5b37 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -910,7 +910,7 @@ static ssize_t read_block_state(struct file *file, char __user *buf, + zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.', + zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.'); + +- if (count < copied) { ++ if (count <= copied) { + zram_slot_unlock(zram, index); + break; + } +diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c +index 5a321b4076aab..cab93935cc7f1 100644 +--- a/drivers/bluetooth/bfusb.c ++++ b/drivers/bluetooth/bfusb.c +@@ -628,6 +628,9 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i + data->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress; + data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize); + ++ if (!data->bulk_pkt_size) ++ goto done; ++ + rwlock_init(&data->lock); + + data->reassembly = NULL; +diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c +index e4182acee488c..d9ceca7a7935c 100644 +--- a/drivers/bluetooth/btbcm.c ++++ b/drivers/bluetooth/btbcm.c +@@ -8,6 +8,7 @@ + + #include <linux/module.h> + #include <linux/firmware.h> ++#include <linux/dmi.h> + #include <asm/unaligned.h> + + #include <net/bluetooth/bluetooth.h> +@@ -343,6 +344,52 @@ static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) + return skb; + } + ++static const struct dmi_system_id disable_broken_read_transmit_power[] = { ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,1"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,2"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,1"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,2"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2"), ++ }, ++ }, ++ { } ++}; ++ + static int btbcm_read_info(struct hci_dev *hdev) + { + struct sk_buff *skb; +@@ -363,6 +410,10 @@ static int btbcm_read_info(struct hci_dev *hdev) + bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]); + kfree_skb(skb); + ++ /* Read DMI and disable broken Read LE Min/Max Tx Power */ ++ if (dmi_first_match(disable_broken_read_transmit_power)) ++ set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks); ++ + return 0; + } + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index f1705b46fc889..e73d4c719b0ad 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -2193,8 +2193,15 @@ static int btintel_setup_combined(struct hci_dev *hdev) + * As a workaround, send HCI Reset command first which will reset the + * number of completed commands and allow normal command processing + * from now on. ++ * ++ * Regarding the INTEL_BROKEN_SHUTDOWN_LED flag, these devices maybe ++ * in the SW_RFKILL ON state as a workaround of fixing LED issue during ++ * the shutdown() procedure, and once the device is in SW_RFKILL ON ++ * state, the only way to exit out of it is sending the HCI_Reset ++ * command. + */ +- if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD)) { ++ if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD) || ++ btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { +@@ -2263,12 +2270,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + &hdev->quirks); + +- /* These devices have an issue with LED which doesn't +- * go off immediately during shutdown. Set the flag +- * here to send the LED OFF command during shutdown. +- */ +- btintel_set_flag(hdev, INTEL_BROKEN_LED); +- + err = btintel_legacy_rom_setup(hdev, &ver); + break; + case 0x0b: /* SfP */ +@@ -2329,10 +2330,14 @@ static int btintel_setup_combined(struct hci_dev *hdev) + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ +- /* Some legacy bootloader devices from JfP supports both old +- * and TLV based HCI_Intel_Read_Version command. But we don't +- * want to use the TLV based setup routines for those legacy +- * bootloader device. ++ /* Some legacy bootloader devices starting from JfP, ++ * the operational firmware supports both old and TLV based ++ * HCI_Intel_Read_Version command based on the command ++ * parameter. ++ * ++ * For upgrading firmware case, the TLV based version cannot ++ * be used because the firmware filename for legacy bootloader ++ * is based on the old format. + * + * Also, it is not easy to convert TLV based version from the + * legacy version format. +@@ -2344,6 +2349,20 @@ static int btintel_setup_combined(struct hci_dev *hdev) + err = btintel_read_version(hdev, &ver); + if (err) + return err; ++ ++ /* Apply the device specific HCI quirks ++ * ++ * All Legacy bootloader devices support WBS ++ */ ++ set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); ++ ++ /* Valid LE States quirk for JfP/ThP familiy */ ++ if (ver.hw_variant == 0x11 || ver.hw_variant == 0x12) ++ set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); ++ ++ /* Setup MSFT Extension support */ ++ btintel_set_msft_opcode(hdev, ver.hw_variant); ++ + err = btintel_bootloader_setup(hdev, &ver); + break; + case 0x17: +@@ -2399,9 +2418,10 @@ static int btintel_shutdown_combined(struct hci_dev *hdev) + + /* Some platforms have an issue with BT LED when the interface is + * down or BT radio is turned off, which takes 5 seconds to BT LED +- * goes off. This command turns off the BT LED immediately. ++ * goes off. As a workaround, sends HCI_Intel_SW_RFKILL to put the ++ * device in the RFKILL ON state which turns off the BT LED immediately. + */ +- if (btintel_test_flag(hdev, INTEL_BROKEN_LED)) { ++ if (btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { + skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); +diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h +index aa64072bbe68d..704e3b7bcb77c 100644 +--- a/drivers/bluetooth/btintel.h ++++ b/drivers/bluetooth/btintel.h +@@ -145,7 +145,7 @@ enum { + INTEL_FIRMWARE_FAILED, + INTEL_BOOTING, + INTEL_BROKEN_INITIAL_NCMD, +- INTEL_BROKEN_LED, ++ INTEL_BROKEN_SHUTDOWN_LED, + INTEL_ROM_LEGACY, + + __INTEL_NUM_FLAGS, +diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c +index 9872ef18f9fea..1cbdeca1fdc4a 100644 +--- a/drivers/bluetooth/btmtksdio.c ++++ b/drivers/bluetooth/btmtksdio.c +@@ -1042,6 +1042,8 @@ static int btmtksdio_runtime_suspend(struct device *dev) + if (!bdev) + return 0; + ++ sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ + sdio_claim_host(bdev->func); + + sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err); +diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c +index e9d91d7c0db48..9ba22b13b4fa0 100644 +--- a/drivers/bluetooth/btmtkuart.c ++++ b/drivers/bluetooth/btmtkuart.c +@@ -158,8 +158,10 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, + int err; + + hlen = sizeof(*hdr) + wmt_params->dlen; +- if (hlen > 255) +- return -EINVAL; ++ if (hlen > 255) { ++ err = -EINVAL; ++ goto err_free_skb; ++ } + + hdr = (struct mtk_wmt_hdr *)&wc; + hdr->dir = 1; +@@ -173,7 +175,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, + err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc); + if (err < 0) { + clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); +- return err; ++ goto err_free_skb; + } + + /* The vendor specific WMT commands are all answered by a vendor +@@ -190,13 +192,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, + if (err == -EINTR) { + bt_dev_err(hdev, "Execution of wmt command interrupted"); + clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); +- return err; ++ goto err_free_skb; + } + + if (err) { + bt_dev_err(hdev, "Execution of wmt command timed out"); + clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); +- return -ETIMEDOUT; ++ err = -ETIMEDOUT; ++ goto err_free_skb; + } + + /* Parse and handle the return WMT event */ +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 60d2fce59a71d..ac90392cce339 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -59,6 +59,7 @@ static struct usb_driver btusb_driver; + #define BTUSB_WIDEBAND_SPEECH 0x400000 + #define BTUSB_VALID_LE_STATES 0x800000 + #define BTUSB_QCA_WCN6855 0x1000000 ++#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED 0x2000000 + #define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000 + + static const struct usb_device_id btusb_table[] = { +@@ -295,6 +296,24 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x0489, 0xe0cc), .driver_info = BTUSB_QCA_WCN6855 | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x0489, 0xe0d6), .driver_info = BTUSB_QCA_WCN6855 | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x0489, 0xe0e3), .driver_info = BTUSB_QCA_WCN6855 | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x10ab, 0x9309), .driver_info = BTUSB_QCA_WCN6855 | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x10ab, 0x9409), .driver_info = BTUSB_QCA_WCN6855 | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x0489, 0xe0d0), .driver_info = BTUSB_QCA_WCN6855 | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, + + /* Broadcom BCM2035 */ + { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, +@@ -365,10 +384,13 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED }, + { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, + { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED | +- BTUSB_INTEL_BROKEN_INITIAL_NCMD }, +- { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED }, ++ BTUSB_INTEL_BROKEN_INITIAL_NCMD | ++ BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, ++ { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED | ++ BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, + { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED }, +- { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED }, ++ { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | ++ BTUSB_INTEL_BROKEN_SHUTDOWN_LED }, + { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED }, + + /* Other Intel Bluetooth devices */ +@@ -384,6 +406,14 @@ static const struct usb_device_id blacklist_table[] = { + /* Realtek 8852AE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x0bda, 0x4852), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x04c5, 0x165c), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ { USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, + + /* Realtek Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), +@@ -410,10 +440,21 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, + { USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, + ++ /* MediaTek MT7922A Bluetooth devices */ ++ { USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ { USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK | ++ BTUSB_WIDEBAND_SPEECH | ++ BTUSB_VALID_LE_STATES }, ++ + /* Additional Realtek 8723AE Bluetooth devices */ + { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK }, +@@ -433,6 +474,10 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK }, + ++ /* Additional Realtek 8761B Bluetooth devices */ ++ { USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK | ++ BTUSB_WIDEBAND_SPEECH }, ++ + /* Additional Realtek 8761BU Bluetooth devices */ + { USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, +@@ -451,10 +496,6 @@ static const struct usb_device_id blacklist_table[] = { + /* Additional Realtek 8822CE Bluetooth devices */ + { USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, +- /* Bluetooth component of Realtek 8852AE device */ +- { USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK | +- BTUSB_WIDEBAND_SPEECH }, +- + { USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK | +@@ -2217,6 +2258,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb) + skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC); + if (!skb) { + hdev->stat.err_rx++; ++ kfree(urb->setup_packet); + return; + } + +@@ -2237,6 +2279,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb) + data->evt_skb = skb_clone(skb, GFP_ATOMIC); + if (!data->evt_skb) { + kfree_skb(skb); ++ kfree(urb->setup_packet); + return; + } + } +@@ -2245,6 +2288,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb) + if (err < 0) { + kfree_skb(data->evt_skb); + data->evt_skb = NULL; ++ kfree(urb->setup_packet); + return; + } + +@@ -2255,6 +2299,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb) + wake_up_bit(&data->flags, + BTUSB_TX_WAIT_VND_EVT); + } ++ kfree(urb->setup_packet); + return; + } else if (urb->status == -ENOENT) { + /* Avoid suspend failed when usb_kill_urb */ +@@ -2275,6 +2320,7 @@ static void btusb_mtk_wmt_recv(struct urb *urb) + usb_anchor_urb(urb, &data->ctrl_anchor); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { ++ kfree(urb->setup_packet); + /* -EPERM: urb is being killed; + * -ENODEV: device got disconnected + */ +@@ -2515,6 +2561,7 @@ static int btusb_mtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwnam + } else { + bt_dev_err(hdev, "Failed wmt patch dwnld status (%d)", + status); ++ err = -EIO; + goto err_release_fw; + } + } +@@ -2804,11 +2851,16 @@ static int btusb_mtk_setup(struct hci_dev *hdev) + case 0x7668: + fwname = FIRMWARE_MT7668; + break; ++ case 0x7922: + case 0x7961: + snprintf(fw_bin_name, sizeof(fw_bin_name), + "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", + dev_id & 0xffff, (fw_version & 0xff) + 1); + err = btusb_mtk_setup_firmware_79xx(hdev, fw_bin_name); ++ if (err < 0) { ++ bt_dev_err(hdev, "Failed to set up firmware (%d)", err); ++ return err; ++ } + + /* It's Device EndPoint Reset Option Register */ + btusb_mtk_uhw_reg_write(data, MTK_EP_RST_OPT, MTK_EP_RST_IN_OUT_OPT); +@@ -2828,6 +2880,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev) + } + + hci_set_msft_opcode(hdev, 0xFD30); ++ hci_set_aosp_capable(hdev); + goto done; + default: + bt_dev_err(hdev, "Unsupported hardware variant (%08x)", +@@ -3808,6 +3861,9 @@ static int btusb_probe(struct usb_interface *intf, + + if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD) + btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD); ++ ++ if (id->driver_info & BTUSB_INTEL_BROKEN_SHUTDOWN_LED) ++ btintel_set_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED); + } + + if (id->driver_info & BTUSB_MARVELL) +diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c +index ef54afa293574..7abf99f0ee399 100644 +--- a/drivers/bluetooth/hci_bcm.c ++++ b/drivers/bluetooth/hci_bcm.c +@@ -1188,7 +1188,12 @@ static int bcm_probe(struct platform_device *pdev) + return -ENOMEM; + + dev->dev = &pdev->dev; +- dev->irq = platform_get_irq(pdev, 0); ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret < 0) ++ return ret; ++ ++ dev->irq = ret; + + /* Initialize routing field to an unused value */ + dev->pcm_int_params[0] = 0xff; +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 0c0dedece59c5..d49a39d17d7dc 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -587,9 +587,11 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count) + count -= processed; + } + +- pm_runtime_get(&hu->serdev->dev); +- pm_runtime_mark_last_busy(&hu->serdev->dev); +- pm_runtime_put_autosuspend(&hu->serdev->dev); ++ if (hu->serdev) { ++ pm_runtime_get(&hu->serdev->dev); ++ pm_runtime_mark_last_busy(&hu->serdev->dev); ++ pm_runtime_put_autosuspend(&hu->serdev->dev); ++ } + + return 0; + } +@@ -846,6 +848,8 @@ static int h5_serdev_probe(struct serdev_device *serdev) + h5->vnd = data->vnd; + } + ++ if (data->driver_info & H5_INFO_WAKEUP_DISABLE) ++ set_bit(H5_WAKEUP_DISABLE, &h5->flags); + + h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(h5->enable_gpio)) +@@ -860,9 +864,6 @@ static int h5_serdev_probe(struct serdev_device *serdev) + if (err) + return err; + +- if (data->driver_info & H5_INFO_WAKEUP_DISABLE) +- set_bit(H5_WAKEUP_DISABLE, &h5->flags); +- + return 0; + } + +@@ -962,11 +963,13 @@ static void h5_btrtl_open(struct h5 *h5) + serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN); + serdev_device_set_baudrate(h5->hu->serdev, 115200); + +- pm_runtime_set_active(&h5->hu->serdev->dev); +- pm_runtime_use_autosuspend(&h5->hu->serdev->dev); +- pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev, +- SUSPEND_TIMEOUT_MS); +- pm_runtime_enable(&h5->hu->serdev->dev); ++ if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) { ++ pm_runtime_set_active(&h5->hu->serdev->dev); ++ pm_runtime_use_autosuspend(&h5->hu->serdev->dev); ++ pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev, ++ SUSPEND_TIMEOUT_MS); ++ pm_runtime_enable(&h5->hu->serdev->dev); ++ } + + /* The controller needs up to 500ms to wakeup */ + gpiod_set_value_cansleep(h5->enable_gpio, 1); +@@ -976,7 +979,8 @@ static void h5_btrtl_open(struct h5 *h5) + + static void h5_btrtl_close(struct h5 *h5) + { +- pm_runtime_disable(&h5->hu->serdev->dev); ++ if (!test_bit(H5_WAKEUP_DISABLE, &h5->flags)) ++ pm_runtime_disable(&h5->hu->serdev->dev); + + gpiod_set_value_cansleep(h5->device_wake_gpio, 0); + gpiod_set_value_cansleep(h5->enable_gpio, 0); +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 53deea2eb7b4d..8eb7fddfb9300 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1927,6 +1927,9 @@ static int qca_power_off(struct hci_dev *hdev) + hu->hdev->hw_error = NULL; + hu->hdev->cmd_timeout = NULL; + ++ del_timer_sync(&qca->wake_retrans_timer); ++ del_timer_sync(&qca->tx_idle_timer); ++ + /* Stop sending shutdown command if soc crashes. */ + if (soc_type != QCA_ROME + && qca->memdump_state == QCA_MEMDUMP_IDLE) { +@@ -2055,14 +2058,14 @@ static int qca_serdev_probe(struct serdev_device *serdev) + + qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", + GPIOD_OUT_LOW); +- if (!qcadev->bt_en && data->soc_type == QCA_WCN6750) { ++ if (IS_ERR_OR_NULL(qcadev->bt_en) && data->soc_type == QCA_WCN6750) { + dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); + power_ctrl_enabled = false; + } + + qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", + GPIOD_IN); +- if (!qcadev->sw_ctrl && data->soc_type == QCA_WCN6750) ++ if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && data->soc_type == QCA_WCN6750) + dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); + + qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); +@@ -2084,7 +2087,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) + + qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", + GPIOD_OUT_LOW); +- if (!qcadev->bt_en) { ++ if (IS_ERR_OR_NULL(qcadev->bt_en)) { + dev_warn(&serdev->dev, "failed to acquire enable gpio\n"); + power_ctrl_enabled = false; + } +diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c +index 8ab26dec5f6e8..8469f9876dd26 100644 +--- a/drivers/bluetooth/hci_vhci.c ++++ b/drivers/bluetooth/hci_vhci.c +@@ -121,6 +121,8 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) + if (opcode & 0x80) + set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + ++ set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); ++ + if (hci_register_dev(hdev) < 0) { + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); +diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c +index 57908ce4fae85..076e4942a3f0e 100644 +--- a/drivers/bluetooth/virtio_bt.c ++++ b/drivers/bluetooth/virtio_bt.c +@@ -202,6 +202,9 @@ static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb) + hci_skb_pkt_type(skb) = pkt_type; + hci_recv_frame(vbt->hdev, skb); + break; ++ default: ++ kfree_skb(skb); ++ break; + } + } + +diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c +index 5aaca6d0f52b2..f1ec344175928 100644 +--- a/drivers/bus/mhi/core/init.c ++++ b/drivers/bus/mhi/core/init.c +@@ -788,6 +788,7 @@ static int parse_ch_cfg(struct mhi_controller *mhi_cntrl, + mhi_chan->offload_ch = ch_cfg->offload_channel; + mhi_chan->db_cfg.reset_req = ch_cfg->doorbell_mode_switch; + mhi_chan->pre_alloc = ch_cfg->auto_queue; ++ mhi_chan->wake_capable = ch_cfg->wake_capable; + + /* + * If MHI host allocates buffers, then the channel direction +diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c +index fb99e3727155b..bb9a2043f3a20 100644 +--- a/drivers/bus/mhi/core/pm.c ++++ b/drivers/bus/mhi/core/pm.c +@@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) + } + EXPORT_SYMBOL_GPL(mhi_pm_suspend); + +-int mhi_pm_resume(struct mhi_controller *mhi_cntrl) ++static int __mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force) + { + struct mhi_chan *itr, *tmp; + struct device *dev = &mhi_cntrl->mhi_dev->dev; +@@ -898,8 +898,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) + if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) + return -EIO; + +- if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) +- return -EINVAL; ++ if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) { ++ dev_warn(dev, "Resuming from non M3 state (%s)\n", ++ TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); ++ if (!force) ++ return -EINVAL; ++ } + + /* Notify clients about exiting LPM */ + list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { +@@ -940,8 +944,19 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) + + return 0; + } ++ ++int mhi_pm_resume(struct mhi_controller *mhi_cntrl) ++{ ++ return __mhi_pm_resume(mhi_cntrl, false); ++} + EXPORT_SYMBOL_GPL(mhi_pm_resume); + ++int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl) ++{ ++ return __mhi_pm_resume(mhi_cntrl, true); ++} ++EXPORT_SYMBOL_GPL(mhi_pm_resume_force); ++ + int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) + { + int ret; +@@ -1038,7 +1053,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) + enum mhi_ee_type current_ee; + enum dev_st_transition next_state; + struct device *dev = &mhi_cntrl->mhi_dev->dev; +- u32 val; ++ u32 interval_us = 25000; /* poll register field every 25 milliseconds */ + int ret; + + dev_info(dev, "Requested to power ON\n"); +@@ -1055,10 +1070,6 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) + mutex_lock(&mhi_cntrl->pm_mutex); + mhi_cntrl->pm_state = MHI_PM_DISABLE; + +- ret = mhi_init_irq_setup(mhi_cntrl); +- if (ret) +- goto error_setup_irq; +- + /* Setup BHI INTVEC */ + write_lock_irq(&mhi_cntrl->pm_lock); + mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0); +@@ -1072,7 +1083,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) + dev_err(dev, "%s is not a valid EE for power on\n", + TO_MHI_EXEC_STR(current_ee)); + ret = -EIO; +- goto error_async_power_up; ++ goto error_exit; + } + + state = mhi_get_mhi_state(mhi_cntrl); +@@ -1081,20 +1092,12 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) + + if (state == MHI_STATE_SYS_ERR) { + mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); +- ret = wait_event_timeout(mhi_cntrl->state_event, +- MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state) || +- mhi_read_reg_field(mhi_cntrl, +- mhi_cntrl->regs, +- MHICTRL, +- MHICTRL_RESET_MASK, +- MHICTRL_RESET_SHIFT, +- &val) || +- !val, +- msecs_to_jiffies(mhi_cntrl->timeout_ms)); +- if (!ret) { +- ret = -EIO; ++ ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, ++ MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 0, ++ interval_us); ++ if (ret) { + dev_info(dev, "Failed to reset MHI due to syserr state\n"); +- goto error_async_power_up; ++ goto error_exit; + } + + /* +@@ -1104,6 +1107,10 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) + mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0); + } + ++ ret = mhi_init_irq_setup(mhi_cntrl); ++ if (ret) ++ goto error_exit; ++ + /* Transition to next state */ + next_state = MHI_IN_PBL(current_ee) ? + DEV_ST_TRANSITION_PBL : DEV_ST_TRANSITION_READY; +@@ -1116,10 +1123,7 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl) + + return 0; + +-error_async_power_up: +- mhi_deinit_free_irq(mhi_cntrl); +- +-error_setup_irq: ++error_exit: + mhi_cntrl->pm_state = MHI_PM_DISABLE; + mutex_unlock(&mhi_cntrl->pm_mutex); + +diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c +index 59a4896a80309..d340d6864e13a 100644 +--- a/drivers/bus/mhi/pci_generic.c ++++ b/drivers/bus/mhi/pci_generic.c +@@ -20,7 +20,7 @@ + + #define MHI_PCI_DEFAULT_BAR_NUM 0 + +-#define MHI_POST_RESET_DELAY_MS 500 ++#define MHI_POST_RESET_DELAY_MS 2000 + + #define HEALTH_CHECK_PERIOD (HZ * 2) + +@@ -366,6 +366,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = { + .config = &modem_foxconn_sdx55_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, ++ .mru_default = 32768, + .sideband_wake = false, + }; + +@@ -401,6 +402,7 @@ static const struct mhi_pci_dev_info mhi_mv31_info = { + .config = &modem_mv31_config, + .bar_num = MHI_PCI_DEFAULT_BAR_NUM, + .dma_data_width = 32, ++ .mru_default = 32768, + }; + + static const struct pci_device_id mhi_pci_id_table[] = { +@@ -1018,7 +1020,7 @@ static int __maybe_unused mhi_pci_freeze(struct device *dev) + * context. + */ + if (test_and_clear_bit(MHI_PCI_DEV_STARTED, &mhi_pdev->status)) { +- mhi_power_down(mhi_cntrl, false); ++ mhi_power_down(mhi_cntrl, true); + mhi_unprepare_after_power_down(mhi_cntrl); + } + +diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c +index 6f225dddc74f4..4566e730ef2b8 100644 +--- a/drivers/bus/sunxi-rsb.c ++++ b/drivers/bus/sunxi-rsb.c +@@ -687,11 +687,11 @@ err_clk_disable: + + static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) + { +- /* Keep the clock and PM reference counts consistent. */ +- if (pm_runtime_status_suspended(rsb->dev)) +- pm_runtime_resume(rsb->dev); + reset_control_assert(rsb->rstc); +- clk_disable_unprepare(rsb->clk); ++ ++ /* Keep the clock and PM reference counts consistent. */ ++ if (!pm_runtime_status_suspended(rsb->dev)) ++ clk_disable_unprepare(rsb->clk); + } + + static int __maybe_unused sunxi_rsb_runtime_suspend(struct device *dev) +diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c +index 6a8b7fb5be58d..ebf22929ff328 100644 +--- a/drivers/bus/ti-sysc.c ++++ b/drivers/bus/ti-sysc.c +@@ -6,6 +6,7 @@ + #include <linux/io.h> + #include <linux/clk.h> + #include <linux/clkdev.h> ++#include <linux/cpu_pm.h> + #include <linux/delay.h> + #include <linux/list.h> + #include <linux/module.h> +@@ -17,6 +18,7 @@ + #include <linux/of_platform.h> + #include <linux/slab.h> + #include <linux/sys_soc.h> ++#include <linux/timekeeping.h> + #include <linux/iopoll.h> + + #include <linux/platform_data/ti-sysc.h> +@@ -51,11 +53,18 @@ struct sysc_address { + struct list_head node; + }; + ++struct sysc_module { ++ struct sysc *ddata; ++ struct list_head node; ++}; ++ + struct sysc_soc_info { + unsigned long general_purpose:1; + enum sysc_soc soc; +- struct mutex list_lock; /* disabled modules list lock */ ++ struct mutex list_lock; /* disabled and restored modules list lock */ + struct list_head disabled_modules; ++ struct list_head restored_modules; ++ struct notifier_block nb; + }; + + enum sysc_clocks { +@@ -223,37 +232,77 @@ static u32 sysc_read_sysstatus(struct sysc *ddata) + return sysc_read(ddata, offset); + } + +-/* Poll on reset status */ +-static int sysc_wait_softreset(struct sysc *ddata) ++static int sysc_poll_reset_sysstatus(struct sysc *ddata) + { +- u32 sysc_mask, syss_done, rstval; +- int syss_offset, error = 0; +- +- if (ddata->cap->regbits->srst_shift < 0) +- return 0; +- +- syss_offset = ddata->offsets[SYSC_SYSSTATUS]; +- sysc_mask = BIT(ddata->cap->regbits->srst_shift); ++ int error, retries; ++ u32 syss_done, rstval; + + if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED) + syss_done = 0; + else + syss_done = ddata->cfg.syss_mask; + +- if (syss_offset >= 0) { ++ if (likely(!timekeeping_suspended)) { + error = readx_poll_timeout_atomic(sysc_read_sysstatus, ddata, + rstval, (rstval & ddata->cfg.syss_mask) == + syss_done, 100, MAX_MODULE_SOFTRESET_WAIT); ++ } else { ++ retries = MAX_MODULE_SOFTRESET_WAIT; ++ while (retries--) { ++ rstval = sysc_read_sysstatus(ddata); ++ if ((rstval & ddata->cfg.syss_mask) == syss_done) ++ return 0; ++ udelay(2); /* Account for udelay flakeyness */ ++ } ++ error = -ETIMEDOUT; ++ } ++ ++ return error; ++} ++ ++static int sysc_poll_reset_sysconfig(struct sysc *ddata) ++{ ++ int error, retries; ++ u32 sysc_mask, rstval; ++ ++ sysc_mask = BIT(ddata->cap->regbits->srst_shift); + +- } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) { ++ if (likely(!timekeeping_suspended)) { + error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata, + rstval, !(rstval & sysc_mask), + 100, MAX_MODULE_SOFTRESET_WAIT); ++ } else { ++ retries = MAX_MODULE_SOFTRESET_WAIT; ++ while (retries--) { ++ rstval = sysc_read_sysconfig(ddata); ++ if (!(rstval & sysc_mask)) ++ return 0; ++ udelay(2); /* Account for udelay flakeyness */ ++ } ++ error = -ETIMEDOUT; + } + + return error; + } + ++/* Poll on reset status */ ++static int sysc_wait_softreset(struct sysc *ddata) ++{ ++ int syss_offset, error = 0; ++ ++ if (ddata->cap->regbits->srst_shift < 0) ++ return 0; ++ ++ syss_offset = ddata->offsets[SYSC_SYSSTATUS]; ++ ++ if (syss_offset >= 0) ++ error = sysc_poll_reset_sysstatus(ddata); ++ else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) ++ error = sysc_poll_reset_sysconfig(ddata); ++ ++ return error; ++} ++ + static int sysc_add_named_clock_from_child(struct sysc *ddata, + const char *name, + const char *optfck_name) +@@ -1518,7 +1567,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { + 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY), + SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff, + SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY | +- SYSC_QUIRK_REINIT_ON_RESUME), ++ SYSC_QUIRK_REINIT_ON_CTX_LOST), + SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, + SYSC_MODULE_QUIRK_WDT), + /* PRUSS on am3, am4 and am5 */ +@@ -2401,6 +2450,78 @@ static struct dev_pm_domain sysc_child_pm_domain = { + } + }; + ++/* Caller needs to take list_lock if ever used outside of cpu_pm */ ++static void sysc_reinit_modules(struct sysc_soc_info *soc) ++{ ++ struct sysc_module *module; ++ struct list_head *pos; ++ struct sysc *ddata; ++ ++ list_for_each(pos, &sysc_soc->restored_modules) { ++ module = list_entry(pos, struct sysc_module, node); ++ ddata = module->ddata; ++ sysc_reinit_module(ddata, ddata->enabled); ++ } ++} ++ ++/** ++ * sysc_context_notifier - optionally reset and restore module after idle ++ * @nb: notifier block ++ * @cmd: unused ++ * @v: unused ++ * ++ * Some interconnect target modules need to be restored, or reset and restored ++ * on CPU_PM CPU_PM_CLUSTER_EXIT notifier. This is needed at least for am335x ++ * OTG and GPMC target modules even if the modules are unused. ++ */ ++static int sysc_context_notifier(struct notifier_block *nb, unsigned long cmd, ++ void *v) ++{ ++ struct sysc_soc_info *soc; ++ ++ soc = container_of(nb, struct sysc_soc_info, nb); ++ ++ switch (cmd) { ++ case CPU_CLUSTER_PM_ENTER: ++ break; ++ case CPU_CLUSTER_PM_ENTER_FAILED: /* No need to restore context */ ++ break; ++ case CPU_CLUSTER_PM_EXIT: ++ sysc_reinit_modules(soc); ++ break; ++ } ++ ++ return NOTIFY_OK; ++} ++ ++/** ++ * sysc_add_restored - optionally add reset and restore quirk hanlling ++ * @ddata: device data ++ */ ++static void sysc_add_restored(struct sysc *ddata) ++{ ++ struct sysc_module *restored_module; ++ ++ restored_module = kzalloc(sizeof(*restored_module), GFP_KERNEL); ++ if (!restored_module) ++ return; ++ ++ restored_module->ddata = ddata; ++ ++ mutex_lock(&sysc_soc->list_lock); ++ ++ list_add(&restored_module->node, &sysc_soc->restored_modules); ++ ++ if (sysc_soc->nb.notifier_call) ++ goto out_unlock; ++ ++ sysc_soc->nb.notifier_call = sysc_context_notifier; ++ cpu_pm_register_notifier(&sysc_soc->nb); ++ ++out_unlock: ++ mutex_unlock(&sysc_soc->list_lock); ++} ++ + /** + * sysc_legacy_idle_quirk - handle children in omap_device compatible way + * @ddata: device driver data +@@ -2900,12 +3021,14 @@ static int sysc_add_disabled(unsigned long base) + } + + /* +- * One time init to detect the booted SoC and disable unavailable features. ++ * One time init to detect the booted SoC, disable unavailable features ++ * and initialize list for optional cpu_pm notifier. ++ * + * Note that we initialize static data shared across all ti-sysc instances + * so ddata is only used for SoC type. This can be called from module_init + * once we no longer need to rely on platform data. + */ +-static int sysc_init_soc(struct sysc *ddata) ++static int sysc_init_static_data(struct sysc *ddata) + { + const struct soc_device_attribute *match; + struct ti_sysc_platform_data *pdata; +@@ -2921,6 +3044,7 @@ static int sysc_init_soc(struct sysc *ddata) + + mutex_init(&sysc_soc->list_lock); + INIT_LIST_HEAD(&sysc_soc->disabled_modules); ++ INIT_LIST_HEAD(&sysc_soc->restored_modules); + sysc_soc->general_purpose = true; + + pdata = dev_get_platdata(ddata->dev); +@@ -2985,15 +3109,24 @@ static int sysc_init_soc(struct sysc *ddata) + return 0; + } + +-static void sysc_cleanup_soc(void) ++static void sysc_cleanup_static_data(void) + { ++ struct sysc_module *restored_module; + struct sysc_address *disabled_module; + struct list_head *pos, *tmp; + + if (!sysc_soc) + return; + ++ if (sysc_soc->nb.notifier_call) ++ cpu_pm_unregister_notifier(&sysc_soc->nb); ++ + mutex_lock(&sysc_soc->list_lock); ++ list_for_each_safe(pos, tmp, &sysc_soc->restored_modules) { ++ restored_module = list_entry(pos, struct sysc_module, node); ++ list_del(pos); ++ kfree(restored_module); ++ } + list_for_each_safe(pos, tmp, &sysc_soc->disabled_modules) { + disabled_module = list_entry(pos, struct sysc_address, node); + list_del(pos); +@@ -3061,7 +3194,7 @@ static int sysc_probe(struct platform_device *pdev) + ddata->dev = &pdev->dev; + platform_set_drvdata(pdev, ddata); + +- error = sysc_init_soc(ddata); ++ error = sysc_init_static_data(ddata); + if (error) + return error; + +@@ -3159,6 +3292,9 @@ static int sysc_probe(struct platform_device *pdev) + pm_runtime_put(&pdev->dev); + } + ++ if (ddata->cfg.quirks & SYSC_QUIRK_REINIT_ON_CTX_LOST) ++ sysc_add_restored(ddata); ++ + return 0; + + err: +@@ -3240,7 +3376,7 @@ static void __exit sysc_exit(void) + { + bus_unregister_notifier(&platform_bus_type, &sysc_nb); + platform_driver_unregister(&sysc_driver); +- sysc_cleanup_soc(); ++ sysc_cleanup_static_data(); + } + module_exit(sysc_exit); + +diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c +index ed3c4c42fc23b..d68d05d5d3838 100644 +--- a/drivers/char/agp/parisc-agp.c ++++ b/drivers/char/agp/parisc-agp.c +@@ -281,7 +281,7 @@ agp_ioc_init(void __iomem *ioc_regs) + return 0; + } + +-static int ++static int __init + lba_find_capability(int cap) + { + struct _parisc_agp_info *info = &parisc_agp_info; +@@ -366,7 +366,7 @@ fail: + return error; + } + +-static int ++static int __init + find_quicksilver(struct device *dev, void *data) + { + struct parisc_device **lba = data; +@@ -378,7 +378,7 @@ find_quicksilver(struct device *dev, void *data) + return 0; + } + +-static int ++static int __init + parisc_agp_init(void) + { + extern struct sba_device *sba_list; +diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c +index 8ad7b515a51b8..6c00ea0085553 100644 +--- a/drivers/char/hw_random/mtk-rng.c ++++ b/drivers/char/hw_random/mtk-rng.c +@@ -166,8 +166,13 @@ static int mtk_rng_runtime_resume(struct device *dev) + return mtk_rng_init(&priv->rng); + } + +-static UNIVERSAL_DEV_PM_OPS(mtk_rng_pm_ops, mtk_rng_runtime_suspend, +- mtk_rng_runtime_resume, NULL); ++static const struct dev_pm_ops mtk_rng_pm_ops = { ++ SET_RUNTIME_PM_OPS(mtk_rng_runtime_suspend, ++ mtk_rng_runtime_resume, NULL) ++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, ++ pm_runtime_force_resume) ++}; ++ + #define MTK_RNG_PM_OPS (&mtk_rng_pm_ops) + #else /* CONFIG_PM */ + #define MTK_RNG_PM_OPS NULL +diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c +index e96cb5c4f97a3..fe91090e04a46 100644 +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -191,6 +191,8 @@ struct ipmi_user { + struct work_struct remove_work; + }; + ++static struct workqueue_struct *remove_work_wq; ++ + static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user, int *index) + __acquires(user->release_barrier) + { +@@ -1261,7 +1263,7 @@ static void free_user(struct kref *ref) + struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount); + + /* SRCU cleanup must happen in task context. */ +- schedule_work(&user->remove_work); ++ queue_work(remove_work_wq, &user->remove_work); + } + + static void _ipmi_destroy_user(struct ipmi_user *user) +@@ -2930,7 +2932,7 @@ cleanup_bmc_device(struct kref *ref) + * with removing the device attributes while reading a device + * attribute. + */ +- schedule_work(&bmc->remove_work); ++ queue_work(remove_work_wq, &bmc->remove_work); + } + + /* +@@ -4789,7 +4791,9 @@ static atomic_t recv_msg_inuse_count = ATOMIC_INIT(0); + static void free_smi_msg(struct ipmi_smi_msg *msg) + { + atomic_dec(&smi_msg_inuse_count); +- kfree(msg); ++ /* Try to keep as much stuff out of the panic path as possible. */ ++ if (!oops_in_progress) ++ kfree(msg); + } + + struct ipmi_smi_msg *ipmi_alloc_smi_msg(void) +@@ -4808,7 +4812,9 @@ EXPORT_SYMBOL(ipmi_alloc_smi_msg); + static void free_recv_msg(struct ipmi_recv_msg *msg) + { + atomic_dec(&recv_msg_inuse_count); +- kfree(msg); ++ /* Try to keep as much stuff out of the panic path as possible. */ ++ if (!oops_in_progress) ++ kfree(msg); + } + + static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) +@@ -4826,7 +4832,7 @@ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) + + void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) + { +- if (msg->user) ++ if (msg->user && !oops_in_progress) + kref_put(&msg->user->refcount, free_user); + msg->done(msg); + } +@@ -5142,7 +5148,16 @@ static int ipmi_init_msghandler(void) + if (initialized) + goto out; + +- init_srcu_struct(&ipmi_interfaces_srcu); ++ rv = init_srcu_struct(&ipmi_interfaces_srcu); ++ if (rv) ++ goto out; ++ ++ remove_work_wq = create_singlethread_workqueue("ipmi-msghandler-remove-wq"); ++ if (!remove_work_wq) { ++ pr_err("unable to create ipmi-msghandler-remove-wq workqueue"); ++ rv = -ENOMEM; ++ goto out_wq; ++ } + + timer_setup(&ipmi_timer, ipmi_timeout, 0); + mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); +@@ -5151,6 +5166,9 @@ static int ipmi_init_msghandler(void) + + initialized = true; + ++out_wq: ++ if (rv) ++ cleanup_srcu_struct(&ipmi_interfaces_srcu); + out: + mutex_unlock(&ipmi_interfaces_mutex); + return rv; +@@ -5174,6 +5192,8 @@ static void __exit cleanup_ipmi(void) + int count; + + if (initialized) { ++ destroy_workqueue(remove_work_wq); ++ + atomic_notifier_chain_unregister(&panic_notifier_list, + &panic_block); + +diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c +index 20d5af92966d4..8d7a8898e80b0 100644 +--- a/drivers/char/ipmi/ipmi_ssif.c ++++ b/drivers/char/ipmi/ipmi_ssif.c +@@ -1659,6 +1659,9 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) + } + } + ++ ssif_info->client = client; ++ i2c_set_clientdata(client, ssif_info); ++ + rv = ssif_check_and_remove(client, ssif_info); + /* If rv is 0 and addr source is not SI_ACPI, continue probing */ + if (!rv && ssif_info->addr_source == SI_ACPI) { +@@ -1679,9 +1682,6 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) + ipmi_addr_src_to_str(ssif_info->addr_source), + client->addr, client->adapter->name, slave_addr); + +- ssif_info->client = client; +- i2c_set_clientdata(client, ssif_info); +- + /* Now check for system interface capabilities */ + msg[0] = IPMI_NETFN_APP_REQUEST << 2; + msg[1] = IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD; +@@ -1881,6 +1881,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) + + dev_err(&ssif_info->client->dev, + "Unable to start IPMI SSIF: %d\n", rv); ++ i2c_set_clientdata(client, NULL); + kfree(ssif_info); + } + kfree(resp); +diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c +index e4ff3b50de7f3..883b4a3410122 100644 +--- a/drivers/char/ipmi/ipmi_watchdog.c ++++ b/drivers/char/ipmi/ipmi_watchdog.c +@@ -342,13 +342,17 @@ static atomic_t msg_tofree = ATOMIC_INIT(0); + static DECLARE_COMPLETION(msg_wait); + static void msg_free_smi(struct ipmi_smi_msg *msg) + { +- if (atomic_dec_and_test(&msg_tofree)) +- complete(&msg_wait); ++ if (atomic_dec_and_test(&msg_tofree)) { ++ if (!oops_in_progress) ++ complete(&msg_wait); ++ } + } + static void msg_free_recv(struct ipmi_recv_msg *msg) + { +- if (atomic_dec_and_test(&msg_tofree)) +- complete(&msg_wait); ++ if (atomic_dec_and_test(&msg_tofree)) { ++ if (!oops_in_progress) ++ complete(&msg_wait); ++ } + } + static struct ipmi_smi_msg smi_msg = { + .done = msg_free_smi +@@ -434,8 +438,10 @@ static int _ipmi_set_timeout(int do_heartbeat) + rv = __ipmi_set_timeout(&smi_msg, + &recv_msg, + &send_heartbeat_now); +- if (rv) ++ if (rv) { ++ atomic_set(&msg_tofree, 0); + return rv; ++ } + + wait_for_completion(&msg_wait); + +@@ -497,7 +503,7 @@ static void panic_halt_ipmi_heartbeat(void) + msg.cmd = IPMI_WDOG_RESET_TIMER; + msg.data = NULL; + msg.data_len = 0; +- atomic_inc(&panic_done_count); ++ atomic_add(2, &panic_done_count); + rv = ipmi_request_supply_msgs(watchdog_user, + (struct ipmi_addr *) &addr, + 0, +@@ -507,7 +513,7 @@ static void panic_halt_ipmi_heartbeat(void) + &panic_halt_heartbeat_recv_msg, + 1); + if (rv) +- atomic_dec(&panic_done_count); ++ atomic_sub(2, &panic_done_count); + } + + static struct ipmi_smi_msg panic_halt_smi_msg = { +@@ -531,12 +537,12 @@ static void panic_halt_ipmi_set_timeout(void) + /* Wait for the messages to be free. */ + while (atomic_read(&panic_done_count) != 0) + ipmi_poll_interface(watchdog_user); +- atomic_inc(&panic_done_count); ++ atomic_add(2, &panic_done_count); + rv = __ipmi_set_timeout(&panic_halt_smi_msg, + &panic_halt_recv_msg, + &send_heartbeat_now); + if (rv) { +- atomic_dec(&panic_done_count); ++ atomic_sub(2, &panic_done_count); + pr_warn("Unable to extend the watchdog timeout\n"); + } else { + if (send_heartbeat_now) +@@ -580,6 +586,7 @@ restart: + &recv_msg, + 1); + if (rv) { ++ atomic_set(&msg_tofree, 0); + pr_warn("heartbeat send failure: %d\n", rv); + return rv; + } +diff --git a/drivers/char/ipmi/kcs_bmc_serio.c b/drivers/char/ipmi/kcs_bmc_serio.c +index 7948cabde50b4..7e2067628a6ce 100644 +--- a/drivers/char/ipmi/kcs_bmc_serio.c ++++ b/drivers/char/ipmi/kcs_bmc_serio.c +@@ -73,10 +73,12 @@ static int kcs_bmc_serio_add_device(struct kcs_bmc_device *kcs_bmc) + struct serio *port; + + priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; + + /* Use kzalloc() as the allocation is cleaned up with kfree() via serio_unregister_port() */ + port = kzalloc(sizeof(*port), GFP_KERNEL); +- if (!(priv && port)) ++ if (!port) + return -ENOMEM; + + port->id.type = SERIO_8042; +diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h +index 9ccb6b270b071..95164246afd1a 100644 +--- a/drivers/char/mwave/3780i.h ++++ b/drivers/char/mwave/3780i.h +@@ -68,7 +68,7 @@ typedef struct { + unsigned char ClockControl:1; /* RW: Clock control: 0=normal, 1=stop 3780i clocks */ + unsigned char SoftReset:1; /* RW: Soft reset 0=normal, 1=soft reset active */ + unsigned char ConfigMode:1; /* RW: Configuration mode, 0=normal, 1=config mode */ +- unsigned char Reserved:5; /* 0: Reserved */ ++ unsigned short Reserved:13; /* 0: Reserved */ + } DSP_ISA_SLAVE_CONTROL; + + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 605969ed0f965..ebe86de9d0acc 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -461,6 +461,7 @@ static struct crng_state primary_crng = { + * its value (from 0->1->2). + */ + static int crng_init = 0; ++static bool crng_need_final_init = false; + #define crng_ready() (likely(crng_init > 1)) + static int crng_init_cnt = 0; + static unsigned long crng_global_init_time = 0; +@@ -828,6 +829,36 @@ static void __init crng_initialize_primary(struct crng_state *crng) + crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; + } + ++static void crng_finalize_init(struct crng_state *crng) ++{ ++ if (crng != &primary_crng || crng_init >= 2) ++ return; ++ if (!system_wq) { ++ /* We can't call numa_crng_init until we have workqueues, ++ * so mark this for processing later. */ ++ crng_need_final_init = true; ++ return; ++ } ++ ++ invalidate_batched_entropy(); ++ numa_crng_init(); ++ crng_init = 2; ++ process_random_ready_list(); ++ wake_up_interruptible(&crng_init_wait); ++ kill_fasync(&fasync, SIGIO, POLL_IN); ++ pr_notice("crng init done\n"); ++ if (unseeded_warning.missed) { ++ pr_notice("%d get_random_xx warning(s) missed due to ratelimiting\n", ++ unseeded_warning.missed); ++ unseeded_warning.missed = 0; ++ } ++ if (urandom_warning.missed) { ++ pr_notice("%d urandom warning(s) missed due to ratelimiting\n", ++ urandom_warning.missed); ++ urandom_warning.missed = 0; ++ } ++} ++ + #ifdef CONFIG_NUMA + static void do_numa_crng_init(struct work_struct *work) + { +@@ -843,8 +874,8 @@ static void do_numa_crng_init(struct work_struct *work) + crng_initialize_secondary(crng); + pool[i] = crng; + } +- mb(); +- if (cmpxchg(&crng_node_pool, NULL, pool)) { ++ /* pairs with READ_ONCE() in select_crng() */ ++ if (cmpxchg_release(&crng_node_pool, NULL, pool) != NULL) { + for_each_node(i) + kfree(pool[i]); + kfree(pool); +@@ -857,18 +888,38 @@ static void numa_crng_init(void) + { + schedule_work(&numa_crng_init_work); + } ++ ++static struct crng_state *select_crng(void) ++{ ++ struct crng_state **pool; ++ int nid = numa_node_id(); ++ ++ /* pairs with cmpxchg_release() in do_numa_crng_init() */ ++ pool = READ_ONCE(crng_node_pool); ++ if (pool && pool[nid]) ++ return pool[nid]; ++ ++ return &primary_crng; ++} + #else + static void numa_crng_init(void) {} ++ ++static struct crng_state *select_crng(void) ++{ ++ return &primary_crng; ++} + #endif + + /* + * crng_fast_load() can be called by code in the interrupt service +- * path. So we can't afford to dilly-dally. ++ * path. So we can't afford to dilly-dally. Returns the number of ++ * bytes processed from cp. + */ +-static int crng_fast_load(const char *cp, size_t len) ++static size_t crng_fast_load(const char *cp, size_t len) + { + unsigned long flags; + char *p; ++ size_t ret = 0; + + if (!spin_trylock_irqsave(&primary_crng.lock, flags)) + return 0; +@@ -879,7 +930,7 @@ static int crng_fast_load(const char *cp, size_t len) + p = (unsigned char *) &primary_crng.state[4]; + while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) { + p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp; +- cp++; crng_init_cnt++; len--; ++ cp++; crng_init_cnt++; len--; ret++; + } + spin_unlock_irqrestore(&primary_crng.lock, flags); + if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) { +@@ -887,7 +938,7 @@ static int crng_fast_load(const char *cp, size_t len) + crng_init = 1; + pr_notice("fast init done\n"); + } +- return 1; ++ return ret; + } + + /* +@@ -962,38 +1013,23 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) + crng->state[i+4] ^= buf.key[i] ^ rv; + } + memzero_explicit(&buf, sizeof(buf)); +- crng->init_time = jiffies; ++ WRITE_ONCE(crng->init_time, jiffies); + spin_unlock_irqrestore(&crng->lock, flags); +- if (crng == &primary_crng && crng_init < 2) { +- invalidate_batched_entropy(); +- numa_crng_init(); +- crng_init = 2; +- process_random_ready_list(); +- wake_up_interruptible(&crng_init_wait); +- kill_fasync(&fasync, SIGIO, POLL_IN); +- pr_notice("crng init done\n"); +- if (unseeded_warning.missed) { +- pr_notice("%d get_random_xx warning(s) missed due to ratelimiting\n", +- unseeded_warning.missed); +- unseeded_warning.missed = 0; +- } +- if (urandom_warning.missed) { +- pr_notice("%d urandom warning(s) missed due to ratelimiting\n", +- urandom_warning.missed); +- urandom_warning.missed = 0; +- } +- } ++ crng_finalize_init(crng); + } + + static void _extract_crng(struct crng_state *crng, + __u8 out[CHACHA_BLOCK_SIZE]) + { +- unsigned long v, flags; +- +- if (crng_ready() && +- (time_after(crng_global_init_time, crng->init_time) || +- time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))) +- crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL); ++ unsigned long v, flags, init_time; ++ ++ if (crng_ready()) { ++ init_time = READ_ONCE(crng->init_time); ++ if (time_after(READ_ONCE(crng_global_init_time), init_time) || ++ time_after(jiffies, init_time + CRNG_RESEED_INTERVAL)) ++ crng_reseed(crng, crng == &primary_crng ? ++ &input_pool : NULL); ++ } + spin_lock_irqsave(&crng->lock, flags); + if (arch_get_random_long(&v)) + crng->state[14] ^= v; +@@ -1005,15 +1041,7 @@ static void _extract_crng(struct crng_state *crng, + + static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE]) + { +- struct crng_state *crng = NULL; +- +-#ifdef CONFIG_NUMA +- if (crng_node_pool) +- crng = crng_node_pool[numa_node_id()]; +- if (crng == NULL) +-#endif +- crng = &primary_crng; +- _extract_crng(crng, out); ++ _extract_crng(select_crng(), out); + } + + /* +@@ -1042,15 +1070,7 @@ static void _crng_backtrack_protect(struct crng_state *crng, + + static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used) + { +- struct crng_state *crng = NULL; +- +-#ifdef CONFIG_NUMA +- if (crng_node_pool) +- crng = crng_node_pool[numa_node_id()]; +- if (crng == NULL) +-#endif +- crng = &primary_crng; +- _crng_backtrack_protect(crng, tmp, used); ++ _crng_backtrack_protect(select_crng(), tmp, used); + } + + static ssize_t extract_crng_user(void __user *buf, size_t nbytes) +@@ -1269,7 +1289,7 @@ void add_interrupt_randomness(int irq, int irq_flags) + if (unlikely(crng_init == 0)) { + if ((fast_pool->count >= 64) && + crng_fast_load((char *) fast_pool->pool, +- sizeof(fast_pool->pool))) { ++ sizeof(fast_pool->pool)) > 0) { + fast_pool->count = 0; + fast_pool->last = now; + } +@@ -1775,6 +1795,8 @@ static void __init init_std_data(struct entropy_store *r) + int __init rand_initialize(void) + { + init_std_data(&input_pool); ++ if (crng_need_final_init) ++ crng_finalize_init(&primary_crng); + crng_initialize_primary(&primary_crng); + crng_global_init_time = jiffies; + if (ratelimit_disable) { +@@ -1941,7 +1963,10 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; +- input_pool.entropy_count = 0; ++ if (xchg(&input_pool.entropy_count, 0) && random_write_wakeup_bits) { ++ wake_up_interruptible(&random_write_wait); ++ kill_fasync(&fasync, SIGIO, POLL_OUT); ++ } + return 0; + case RNDRESEEDCRNG: + if (!capable(CAP_SYS_ADMIN)) +@@ -1949,7 +1974,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) + if (crng_init < 2) + return -ENODATA; + crng_reseed(&primary_crng, &input_pool); +- crng_global_init_time = jiffies - 1; ++ WRITE_ONCE(crng_global_init_time, jiffies - 1); + return 0; + default: + return -EINVAL; +@@ -2275,15 +2300,19 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, + struct entropy_store *poolp = &input_pool; + + if (unlikely(crng_init == 0)) { +- crng_fast_load(buffer, count); +- return; ++ size_t ret = crng_fast_load(buffer, count); ++ count -= ret; ++ buffer += ret; ++ if (!count || crng_init == 0) ++ return; + } + + /* Suspend writing if we're above the trickle threshold. + * We'll be woken up again once below random_write_wakeup_thresh, + * or when the calling thread is about to terminate. + */ +- wait_event_interruptible(random_write_wait, kthread_should_stop() || ++ wait_event_interruptible(random_write_wait, ++ !system_wq || kthread_should_stop() || + ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits); + mix_pool_bytes(poolp, buffer, count); + credit_entropy_bits(poolp, entropy); +diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c +index ddaeceb7e1091..df37e7b6a10a5 100644 +--- a/drivers/char/tpm/tpm-chip.c ++++ b/drivers/char/tpm/tpm-chip.c +@@ -474,13 +474,21 @@ static void tpm_del_char_device(struct tpm_chip *chip) + + /* Make the driver uncallable. */ + down_write(&chip->ops_sem); +- if (chip->flags & TPM_CHIP_FLAG_TPM2) { +- if (!tpm_chip_start(chip)) { +- tpm2_shutdown(chip, TPM2_SU_CLEAR); +- tpm_chip_stop(chip); ++ ++ /* ++ * Check if chip->ops is still valid: In case that the controller ++ * drivers shutdown handler unregisters the controller in its ++ * shutdown handler we are called twice and chip->ops to NULL. ++ */ ++ if (chip->ops) { ++ if (chip->flags & TPM_CHIP_FLAG_TPM2) { ++ if (!tpm_chip_start(chip)) { ++ tpm2_shutdown(chip, TPM2_SU_CLEAR); ++ tpm_chip_stop(chip); ++ } + } ++ chip->ops = NULL; + } +- chip->ops = NULL; + up_write(&chip->ops_sem); + } + +diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c +index 784b8b3cb903f..97e916856cf3e 100644 +--- a/drivers/char/tpm/tpm2-space.c ++++ b/drivers/char/tpm/tpm2-space.c +@@ -455,6 +455,9 @@ static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp, + if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES) + return 0; + ++ if (be32_to_cpu(data->count) > (UINT_MAX - TPM_HEADER_SIZE - 9) / 4) ++ return -EFAULT; ++ + if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count)) + return -EFAULT; + +diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c +index 69579efb247b3..dc56b976d8162 100644 +--- a/drivers/char/tpm/tpm_tis_core.c ++++ b/drivers/char/tpm/tpm_tis_core.c +@@ -48,6 +48,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, + unsigned long timeout, wait_queue_head_t *queue, + bool check_cancel) + { ++ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + unsigned long stop; + long rc; + u8 status; +@@ -80,8 +81,8 @@ again: + } + } else { + do { +- usleep_range(TPM_TIMEOUT_USECS_MIN, +- TPM_TIMEOUT_USECS_MAX); ++ usleep_range(priv->timeout_min, ++ priv->timeout_max); + status = chip->ops->status(chip); + if ((status & mask) == mask) + return 0; +@@ -945,9 +946,24 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, + chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); + chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); + chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); ++ priv->timeout_min = TPM_TIMEOUT_USECS_MIN; ++ priv->timeout_max = TPM_TIMEOUT_USECS_MAX; + priv->phy_ops = phy_ops; ++ + dev_set_drvdata(&chip->dev, priv); + ++ rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); ++ if (rc < 0) ++ return rc; ++ ++ priv->manufacturer_id = vendor; ++ ++ if (priv->manufacturer_id == TPM_VID_ATML && ++ !(chip->flags & TPM_CHIP_FLAG_TPM2)) { ++ priv->timeout_min = TIS_TIMEOUT_MIN_ATML; ++ priv->timeout_max = TIS_TIMEOUT_MAX_ATML; ++ } ++ + if (is_bsw()) { + priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, + ILB_REMAP_SIZE); +@@ -978,7 +994,15 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, + intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | + TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; + intmask &= ~TPM_GLOBAL_INT_ENABLE; ++ ++ rc = request_locality(chip, 0); ++ if (rc < 0) { ++ rc = -ENODEV; ++ goto out_err; ++ } ++ + tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); ++ release_locality(chip, 0); + + rc = tpm_chip_start(chip); + if (rc) +@@ -988,12 +1012,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, + if (rc) + goto out_err; + +- rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); +- if (rc < 0) +- goto out_err; +- +- priv->manufacturer_id = vendor; +- + rc = tpm_tis_read8(priv, TPM_RID(0), &rid); + if (rc < 0) + goto out_err; +diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h +index b2a3c6c72882d..3be24f221e32a 100644 +--- a/drivers/char/tpm/tpm_tis_core.h ++++ b/drivers/char/tpm/tpm_tis_core.h +@@ -54,6 +54,8 @@ enum tis_defaults { + TIS_MEM_LEN = 0x5000, + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 2000, /* 2 sec */ ++ TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ ++ TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ + }; + + /* Some timeout values are needed before it is known whether the chip is +@@ -98,6 +100,8 @@ struct tpm_tis_data { + wait_queue_head_t read_queue; + const struct tpm_tis_phy_ops *phy_ops; + unsigned short rng_quality; ++ unsigned int timeout_min; /* usecs */ ++ unsigned int timeout_max; /* usecs */ + }; + + struct tpm_tis_phy_ops { +diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c +index 54584b4b00d19..aaa59a00eeaef 100644 +--- a/drivers/char/tpm/tpm_tis_spi_main.c ++++ b/drivers/char/tpm/tpm_tis_spi_main.c +@@ -267,6 +267,7 @@ static const struct spi_device_id tpm_tis_spi_id[] = { + { "st33htpm-spi", (unsigned long)tpm_tis_spi_probe }, + { "slb9670", (unsigned long)tpm_tis_spi_probe }, + { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe }, ++ { "tpm_tis-spi", (unsigned long)tpm_tis_spi_probe }, + { "cr50", (unsigned long)cr50_spi_probe }, + {} + }; +diff --git a/drivers/char/xillybus/xillyusb.c b/drivers/char/xillybus/xillyusb.c +index e7f88f35c7028..dc3551796e5ed 100644 +--- a/drivers/char/xillybus/xillyusb.c ++++ b/drivers/char/xillybus/xillyusb.c +@@ -1912,6 +1912,7 @@ static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev) + + dealloc: + endpoint_dealloc(xdev->msg_ep); /* Also frees FIFO mem if allocated */ ++ xdev->msg_ep = NULL; + return -ENOMEM; + } + +diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c +index a80427980bf73..04d0dd8385945 100644 +--- a/drivers/clk/at91/clk-master.c ++++ b/drivers/clk/at91/clk-master.c +@@ -280,7 +280,7 @@ static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate, + + else if (pres == 3) + pres = MASTER_PRES_MAX; +- else ++ else if (pres) + pres = ffs(pres) - 1; + + spin_lock_irqsave(master->lock, flags); +@@ -309,7 +309,7 @@ static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw, + spin_unlock_irqrestore(master->lock, flags); + + pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK; +- if (pres == 3 && characteristics->have_div3_pres) ++ if (pres == MASTER_PRES_MAX && characteristics->have_div3_pres) + pres = 3; + else + pres = (1 << pres); +@@ -610,7 +610,7 @@ static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate, + + if (div == 3) + div = MASTER_PRES_MAX; +- else ++ else if (div) + div = ffs(div) - 1; + + spin_lock_irqsave(master->lock, flags); +diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c +index 34e3ab13741ac..1f52409475e9c 100644 +--- a/drivers/clk/at91/clk-sam9x60-pll.c ++++ b/drivers/clk/at91/clk-sam9x60-pll.c +@@ -71,8 +71,8 @@ static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw, + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw); + struct sam9x60_frac *frac = to_sam9x60_frac(core); + +- return (parent_rate * (frac->mul + 1) + +- ((u64)parent_rate * frac->frac >> 22)); ++ return parent_rate * (frac->mul + 1) + ++ DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22)); + } + + static int sam9x60_frac_pll_prepare(struct clk_hw *hw) +diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c +index 20ee9dccee787..b40035b011d0a 100644 +--- a/drivers/clk/at91/pmc.c ++++ b/drivers/clk/at91/pmc.c +@@ -267,6 +267,11 @@ static int __init pmc_register_ops(void) + if (!np) + return -ENODEV; + ++ if (!of_device_is_available(np)) { ++ of_node_put(np); ++ return -ENODEV; ++ } ++ + pmcreg = device_node_to_regmap(np); + of_node_put(np); + if (IS_ERR(pmcreg)) +diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c +index cf8c079aa086a..019e712f90d6f 100644 +--- a/drivers/clk/at91/sama7g5.c ++++ b/drivers/clk/at91/sama7g5.c +@@ -982,16 +982,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np) + } + + parent_names[0] = "cpupll_divpmcck"; +- hw = at91_clk_register_master_pres(regmap, "cpuck", 1, parent_names, +- &mck0_layout, &mck0_characteristics, +- &pmc_mck0_lock, +- CLK_SET_RATE_PARENT, 0); +- if (IS_ERR(hw)) +- goto err_free; +- +- sama7g5_pmc->chws[PMC_CPU] = hw; +- +- hw = at91_clk_register_master_div(regmap, "mck0", "cpuck", ++ hw = at91_clk_register_master_div(regmap, "mck0", "cpupll_divpmcck", + &mck0_layout, &mck0_characteristics, + &pmc_mck0_lock, 0); + if (IS_ERR(hw)) +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index a254512965eb8..3667b4d731e71 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -932,8 +932,7 @@ static int bcm2835_clock_is_on(struct clk_hw *hw) + + static u32 bcm2835_clock_choose_div(struct clk_hw *hw, + unsigned long rate, +- unsigned long parent_rate, +- bool round_up) ++ unsigned long parent_rate) + { + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + const struct bcm2835_clock_data *data = clock->data; +@@ -945,10 +944,6 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, + + rem = do_div(temp, rate); + div = temp; +- +- /* Round up and mask off the unused bits */ +- if (round_up && ((div & unused_frac_mask) != 0 || rem != 0)) +- div += unused_frac_mask + 1; + div &= ~unused_frac_mask; + + /* different clamping limits apply for a mash clock */ +@@ -1079,7 +1074,7 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw, + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; + const struct bcm2835_clock_data *data = clock->data; +- u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false); ++ u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate); + u32 ctl; + + spin_lock(&cprman->regs_lock); +@@ -1130,7 +1125,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + + if (!(BIT(parent_idx) & data->set_rate_parent)) { + *prate = clk_hw_get_rate(parent); +- *div = bcm2835_clock_choose_div(hw, rate, *prate, true); ++ *div = bcm2835_clock_choose_div(hw, rate, *prate); + + *avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div); + +@@ -1216,7 +1211,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, + rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate, + &div, &prate, + &avgrate); +- if (rate > best_rate && rate <= req->rate) { ++ if (abs(req->rate - rate) < abs(req->rate - best_rate)) { + best_parent = parent; + best_prate = prate; + best_rate = rate; +diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c +index bc3be5f3eae15..24dab2312bc6f 100644 +--- a/drivers/clk/clk-ast2600.c ++++ b/drivers/clk/clk-ast2600.c +@@ -51,6 +51,8 @@ static DEFINE_SPINLOCK(aspeed_g6_clk_lock); + static struct clk_hw_onecell_data *aspeed_g6_clk_data; + + static void __iomem *scu_g6_base; ++/* AST2600 revision: A0, A1, A2, etc */ ++static u8 soc_rev; + + /* + * Clocks marked with CLK_IS_CRITICAL: +@@ -191,9 +193,8 @@ static struct clk_hw *ast2600_calc_pll(const char *name, u32 val) + static struct clk_hw *ast2600_calc_apll(const char *name, u32 val) + { + unsigned int mult, div; +- u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV); + +- if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) { ++ if (soc_rev >= 2) { + if (val & BIT(24)) { + /* Pass through mode */ + mult = div = 1; +@@ -707,7 +708,7 @@ static const u32 ast2600_a1_axi_ahb200_tbl[] = { + static void __init aspeed_g6_cc(struct regmap *map) + { + struct clk_hw *hw; +- u32 val, div, divbits, chip_id, axi_div, ahb_div; ++ u32 val, div, divbits, axi_div, ahb_div; + + clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, 25000000); + +@@ -738,8 +739,7 @@ static void __init aspeed_g6_cc(struct regmap *map) + axi_div = 2; + + divbits = (val >> 11) & 0x3; +- regmap_read(map, ASPEED_G6_SILICON_REV, &chip_id); +- if (chip_id & BIT(16)) { ++ if (soc_rev >= 1) { + if (!divbits) { + ahb_div = ast2600_a1_axi_ahb200_tbl[(val >> 8) & 0x3]; + if (val & BIT(16)) +@@ -784,6 +784,8 @@ static void __init aspeed_g6_cc_init(struct device_node *np) + if (!scu_g6_base) + return; + ++ soc_rev = (readl(scu_g6_base + ASPEED_G6_SILICON_REV) & CHIP_REVISION_ID) >> 16; ++ + aspeed_g6_clk_data = kzalloc(struct_size(aspeed_g6_clk_data, hws, + ASPEED_G6_NUM_CLKS), GFP_KERNEL); + if (!aspeed_g6_clk_data) +diff --git a/drivers/clk/clk-bm1880.c b/drivers/clk/clk-bm1880.c +index e6d6599d310a1..fad78a22218e8 100644 +--- a/drivers/clk/clk-bm1880.c ++++ b/drivers/clk/clk-bm1880.c +@@ -522,14 +522,6 @@ static struct clk_hw *bm1880_clk_register_pll(struct bm1880_pll_hw_clock *pll_cl + return hw; + } + +-static void bm1880_clk_unregister_pll(struct clk_hw *hw) +-{ +- struct bm1880_pll_hw_clock *pll_hw = to_bm1880_pll_clk(hw); +- +- clk_hw_unregister(hw); +- kfree(pll_hw); +-} +- + static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks, + int num_clks, + struct bm1880_clock_data *data) +@@ -555,7 +547,7 @@ static int bm1880_clk_register_plls(struct bm1880_pll_hw_clock *clks, + + err_clk: + while (i--) +- bm1880_clk_unregister_pll(data->hw_data.hws[clks[i].pll.id]); ++ clk_hw_unregister(data->hw_data.hws[clks[i].pll.id]); + + return PTR_ERR(hw); + } +@@ -695,14 +687,6 @@ static struct clk_hw *bm1880_clk_register_div(struct bm1880_div_hw_clock *div_cl + return hw; + } + +-static void bm1880_clk_unregister_div(struct clk_hw *hw) +-{ +- struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw); +- +- clk_hw_unregister(hw); +- kfree(div_hw); +-} +- + static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks, + int num_clks, + struct bm1880_clock_data *data) +@@ -729,7 +713,7 @@ static int bm1880_clk_register_divs(struct bm1880_div_hw_clock *clks, + + err_clk: + while (i--) +- bm1880_clk_unregister_div(data->hw_data.hws[clks[i].div.id]); ++ clk_hw_unregister(data->hw_data.hws[clks[i].div.id]); + + return PTR_ERR(hw); + } +diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c +index 57ae183982d8c..f7b41366666e5 100644 +--- a/drivers/clk/clk-si5341.c ++++ b/drivers/clk/clk-si5341.c +@@ -1740,7 +1740,7 @@ static int si5341_probe(struct i2c_client *client, + clk_prepare(data->clk[i].hw.clk); + } + +- err = of_clk_add_hw_provider(client->dev.of_node, of_clk_si5341_get, ++ err = devm_of_clk_add_hw_provider(&client->dev, of_clk_si5341_get, + data); + if (err) { + dev_err(&client->dev, "unable to add clk provider\n"); +diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c +index af46176ad0539..473dfe632cc57 100644 +--- a/drivers/clk/clk-stm32f4.c ++++ b/drivers/clk/clk-stm32f4.c +@@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = { + { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, +- { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, + }; + + static const struct stm32f4_gate_data stm32f469_gates[] __initconst = { +@@ -211,7 +210,6 @@ static const struct stm32f4_gate_data stm32f469_gates[] __initconst = { + { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, +- { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, + }; + + static const struct stm32f4_gate_data stm32f746_gates[] __initconst = { +@@ -286,7 +284,6 @@ static const struct stm32f4_gate_data stm32f746_gates[] __initconst = { + { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" }, +- { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, + }; + + static const struct stm32f4_gate_data stm32f769_gates[] __initconst = { +@@ -364,7 +361,6 @@ static const struct stm32f4_gate_data stm32f769_gates[] __initconst = { + { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" }, +- { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, + { STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" }, + }; + +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index 65508eb89ec99..ac11cefc31911 100644 +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -3340,6 +3340,24 @@ static int __init clk_debug_init(void) + { + struct clk_core *core; + ++#ifdef CLOCK_ALLOW_WRITE_DEBUGFS ++ pr_warn("\n"); ++ pr_warn("********************************************************************\n"); ++ pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n"); ++ pr_warn("** **\n"); ++ pr_warn("** WRITEABLE clk DebugFS SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n"); ++ pr_warn("** **\n"); ++ pr_warn("** This means that this kernel is built to expose clk operations **\n"); ++ pr_warn("** such as parent or rate setting, enabling, disabling, etc. **\n"); ++ pr_warn("** to userspace, which may compromise security on your system. **\n"); ++ pr_warn("** **\n"); ++ pr_warn("** If you see this message and you are not debugging the **\n"); ++ pr_warn("** kernel, report this immediately to your vendor! **\n"); ++ pr_warn("** **\n"); ++ pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n"); ++ pr_warn("********************************************************************\n"); ++#endif ++ + rootdir = debugfs_create_dir("clk", NULL); + + debugfs_create_file("clk_summary", 0444, rootdir, &all_lists, +@@ -3415,6 +3433,14 @@ static int __clk_core_init(struct clk_core *core) + + clk_prepare_lock(); + ++ /* ++ * Set hw->core after grabbing the prepare_lock to synchronize with ++ * callers of clk_core_fill_parent_index() where we treat hw->core ++ * being NULL as the clk not being registered yet. This is crucial so ++ * that clks aren't parented until their parent is fully registered. ++ */ ++ core->hw->core = core; ++ + ret = clk_pm_runtime_get(core); + if (ret) + goto unlock; +@@ -3579,8 +3605,10 @@ static int __clk_core_init(struct clk_core *core) + out: + clk_pm_runtime_put(core); + unlock: +- if (ret) ++ if (ret) { + hlist_del_init(&core->child_node); ++ core->hw->core = NULL; ++ } + + clk_prepare_unlock(); + +@@ -3844,7 +3872,6 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) + core->num_parents = init->num_parents; + core->min_rate = 0; + core->max_rate = ULONG_MAX; +- hw->core = core; + + ret = clk_core_populate_parent_map(core, init); + if (ret) +@@ -3862,7 +3889,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) + goto fail_create_clk; + } + +- clk_core_link_consumer(hw->core, hw->clk); ++ clk_core_link_consumer(core, hw->clk); + + ret = __clk_core_init(core); + if (!ret) +diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c +index 5dbb6a9377324..206e4c43f68f8 100644 +--- a/drivers/clk/imx/clk-imx6ul.c ++++ b/drivers/clk/imx/clk-imx6ul.c +@@ -161,7 +161,6 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) + hws[IMX6UL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX6UL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX6UL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT); +- hws[IMX6UL_CLK_CSI_SEL] = imx_clk_hw_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT); + + /* Do not bypass PLLs initially */ + clk_set_parent(hws[IMX6UL_PLL1_BYPASS]->clk, hws[IMX6UL_CLK_PLL1]->clk); +@@ -270,6 +269,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) + hws[IMX6UL_CLK_ECSPI_SEL] = imx_clk_hw_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); + hws[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_hw_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT); + hws[IMX6UL_CLK_LCDIF_SEL] = imx_clk_hw_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels)); ++ hws[IMX6UL_CLK_CSI_SEL] = imx_clk_hw_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); + + hws[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_hw_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels)); + hws[IMX6UL_CLK_LDB_DI1_DIV_SEL] = imx_clk_hw_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels)); +diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c +index c55577604e16a..021355a247081 100644 +--- a/drivers/clk/imx/clk-imx8mn.c ++++ b/drivers/clk/imx/clk-imx8mn.c +@@ -277,9 +277,9 @@ static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audi + + static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", }; + +-static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", +- "sys_pll1_200m", "audio_pll2_out", "vpu_pll", +- "sys_pll1_80m", }; ++static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", ++ "sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m", ++ "dummy", "sys_pll1_80m", }; + static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", + "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", + "video_pll1_out", "osc_32k", }; +diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c +index d3e905cf867d7..b23758083ce52 100644 +--- a/drivers/clk/imx/clk-imx8qxp-lpcg.c ++++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c +@@ -370,7 +370,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { + .probe = imx8qxp_lpcg_clk_probe, + }; + +-builtin_platform_driver(imx8qxp_lpcg_clk_driver); ++module_platform_driver(imx8qxp_lpcg_clk_driver); + + MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); + MODULE_DESCRIPTION("NXP i.MX8QXP LPCG clock driver"); +diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c +index c53a688d8ccca..40a2efb1329be 100644 +--- a/drivers/clk/imx/clk-imx8qxp.c ++++ b/drivers/clk/imx/clk-imx8qxp.c +@@ -308,7 +308,7 @@ static struct platform_driver imx8qxp_clk_driver = { + }, + .probe = imx8qxp_clk_probe, + }; +-builtin_platform_driver(imx8qxp_clk_driver); ++module_platform_driver(imx8qxp_clk_driver); + + MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); + MODULE_DESCRIPTION("NXP i.MX8QXP clock driver"); +diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c +index 266c7595d3302..af31633a8862e 100644 +--- a/drivers/clk/ingenic/cgu.c ++++ b/drivers/clk/ingenic/cgu.c +@@ -453,15 +453,15 @@ ingenic_clk_calc_div(struct clk_hw *hw, + } + + /* Impose hardware constraints */ +- div = min_t(unsigned, div, 1 << clk_info->div.bits); +- div = max_t(unsigned, div, 1); ++ div = clamp_t(unsigned int, div, clk_info->div.div, ++ clk_info->div.div << clk_info->div.bits); + + /* + * If the divider value itself must be divided before being written to + * the divider register, we must ensure we don't have any bits set that + * would be lost as a result of doing so. + */ +- div /= clk_info->div.div; ++ div = DIV_ROUND_UP(div, clk_info->div.div); + div *= clk_info->div.div; + + return div; +diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c +index 5154b0cf8ad6c..66ff141da0a42 100644 +--- a/drivers/clk/ingenic/jz4725b-cgu.c ++++ b/drivers/clk/ingenic/jz4725b-cgu.c +@@ -139,11 +139,10 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { + }, + + [JZ4725B_CLK_I2S] = { +- "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, ++ "i2s", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 }, + .mux = { CGU_REG_CPCCR, 31, 1 }, + .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 }, +- .gate = { CGU_REG_CLKGR, 6 }, + }, + + [JZ4725B_CLK_SPI] = { +diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c +index d6eed760327d0..608e0e8ca49a8 100644 +--- a/drivers/clk/meson/gxbb.c ++++ b/drivers/clk/meson/gxbb.c +@@ -713,6 +713,35 @@ static struct clk_regmap gxbb_mpll_prediv = { + }; + + static struct clk_regmap gxbb_mpll0_div = { ++ .data = &(struct meson_clk_mpll_data){ ++ .sdm = { ++ .reg_off = HHI_MPLL_CNTL7, ++ .shift = 0, ++ .width = 14, ++ }, ++ .sdm_en = { ++ .reg_off = HHI_MPLL_CNTL, ++ .shift = 25, ++ .width = 1, ++ }, ++ .n2 = { ++ .reg_off = HHI_MPLL_CNTL7, ++ .shift = 16, ++ .width = 9, ++ }, ++ .lock = &meson_clk_lock, ++ }, ++ .hw.init = &(struct clk_init_data){ ++ .name = "mpll0_div", ++ .ops = &meson_clk_mpll_ops, ++ .parent_hws = (const struct clk_hw *[]) { ++ &gxbb_mpll_prediv.hw ++ }, ++ .num_parents = 1, ++ }, ++}; ++ ++static struct clk_regmap gxl_mpll0_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL7, +@@ -749,7 +778,16 @@ static struct clk_regmap gxbb_mpll0 = { + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &clk_regmap_gate_ops, +- .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw }, ++ .parent_data = &(const struct clk_parent_data) { ++ /* ++ * Note: ++ * GXL and GXBB have different SDM_EN registers. We ++ * fallback to the global naming string mechanism so ++ * mpll0_div picks up the appropriate one. ++ */ ++ .name = "mpll0_div", ++ .index = -1, ++ }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +@@ -3044,7 +3082,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { + [CLKID_VAPB_1] = &gxbb_vapb_1.hw, + [CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw, + [CLKID_VAPB] = &gxbb_vapb.hw, +- [CLKID_MPLL0_DIV] = &gxbb_mpll0_div.hw, ++ [CLKID_MPLL0_DIV] = &gxl_mpll0_div.hw, + [CLKID_MPLL1_DIV] = &gxbb_mpll1_div.hw, + [CLKID_MPLL2_DIV] = &gxbb_mpll2_div.hw, + [CLKID_MPLL_PREDIV] = &gxbb_mpll_prediv.hw, +@@ -3439,7 +3477,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = { + &gxbb_mpll0, + &gxbb_mpll1, + &gxbb_mpll2, +- &gxbb_mpll0_div, ++ &gxl_mpll0_div, + &gxbb_mpll1_div, + &gxbb_mpll2_div, + &gxbb_cts_amclk_div, +diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c +index 08ba59ec3fb17..71bdd7c3ff034 100644 +--- a/drivers/clk/mvebu/ap-cpu-clk.c ++++ b/drivers/clk/mvebu/ap-cpu-clk.c +@@ -256,12 +256,15 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) + int cpu, err; + + err = of_property_read_u32(dn, "reg", &cpu); +- if (WARN_ON(err)) ++ if (WARN_ON(err)) { ++ of_node_put(dn); + return err; ++ } + + /* If cpu2 or cpu3 is enabled */ + if (cpu & APN806_CLUSTER_NUM_MASK) { + nclusters = 2; ++ of_node_put(dn); + break; + } + } +@@ -288,8 +291,10 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) + int cpu, err; + + err = of_property_read_u32(dn, "reg", &cpu); +- if (WARN_ON(err)) ++ if (WARN_ON(err)) { ++ of_node_put(dn); + return err; ++ } + + cluster_index = cpu & APN806_CLUSTER_NUM_MASK; + cluster_index >>= APN806_CLUSTER_NUM_OFFSET; +@@ -301,6 +306,7 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) + parent = of_clk_get(np, cluster_index); + if (IS_ERR(parent)) { + dev_err(dev, "Could not get the clock parent\n"); ++ of_node_put(dn); + return -EINVAL; + } + parent_name = __clk_get_name(parent); +@@ -319,8 +325,10 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) + init.parent_names = &parent_name; + + ret = devm_clk_hw_register(dev, &ap_cpu_clk[cluster_index].hw); +- if (ret) ++ if (ret) { ++ of_node_put(dn); + return ret; ++ } + ap_cpu_data->hws[cluster_index] = &ap_cpu_clk[cluster_index].hw; + } + +diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c +index eaedcceb766f9..8f65b9bdafce4 100644 +--- a/drivers/clk/qcom/clk-alpha-pll.c ++++ b/drivers/clk/qcom/clk-alpha-pll.c +@@ -1429,6 +1429,15 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); + void clk_trion_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("Trion 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); +diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c +index b2d00b4519634..45d9cca28064f 100644 +--- a/drivers/clk/qcom/clk-regmap-mux.c ++++ b/drivers/clk/qcom/clk-regmap-mux.c +@@ -28,7 +28,7 @@ static u8 mux_get_parent(struct clk_hw *hw) + val &= mask; + + if (mux->parent_map) +- return qcom_find_src_index(hw, mux->parent_map, val); ++ return qcom_find_cfg_index(hw, mux->parent_map, val); + + return val; + } +diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c +index 60d2a78d13950..2af04fc4abfa9 100644 +--- a/drivers/clk/qcom/common.c ++++ b/drivers/clk/qcom/common.c +@@ -69,6 +69,18 @@ int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src) + } + EXPORT_SYMBOL_GPL(qcom_find_src_index); + ++int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, u8 cfg) ++{ ++ int i, num_parents = clk_hw_get_num_parents(hw); ++ ++ for (i = 0; i < num_parents; i++) ++ if (cfg == map[i].cfg) ++ return i; ++ ++ return -ENOENT; ++} ++EXPORT_SYMBOL_GPL(qcom_find_cfg_index); ++ + struct regmap * + qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) + { +diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h +index bb39a7e106d8a..9c8f7b798d9fc 100644 +--- a/drivers/clk/qcom/common.h ++++ b/drivers/clk/qcom/common.h +@@ -49,6 +49,8 @@ extern void + qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count); + extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, + u8 src); ++extern int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, ++ u8 cfg); + + extern int qcom_cc_register_board_clk(struct device *dev, const char *path, + const char *name, unsigned long rate); +diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c +index 3c3a7ff045621..9b1674b28d45d 100644 +--- a/drivers/clk/qcom/gcc-msm8996.c ++++ b/drivers/clk/qcom/gcc-msm8996.c +@@ -2937,20 +2937,6 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = { + }, + }; + +-static struct clk_branch gcc_aggre1_pnoc_ahb_clk = { +- .halt_reg = 0x82014, +- .clkr = { +- .enable_reg = 0x82014, +- .enable_mask = BIT(0), +- .hw.init = &(struct clk_init_data){ +- .name = "gcc_aggre1_pnoc_ahb_clk", +- .parent_names = (const char *[]){ "periph_noc_clk_src" }, +- .num_parents = 1, +- .ops = &clk_branch2_ops, +- }, +- }, +-}; +- + static struct clk_branch gcc_aggre2_ufs_axi_clk = { + .halt_reg = 0x83014, + .clkr = { +@@ -3474,7 +3460,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { + [GCC_AGGRE0_CNOC_AHB_CLK] = &gcc_aggre0_cnoc_ahb_clk.clkr, + [GCC_SMMU_AGGRE0_AXI_CLK] = &gcc_smmu_aggre0_axi_clk.clkr, + [GCC_SMMU_AGGRE0_AHB_CLK] = &gcc_smmu_aggre0_ahb_clk.clkr, +- [GCC_AGGRE1_PNOC_AHB_CLK] = &gcc_aggre1_pnoc_ahb_clk.clkr, + [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr, + [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr, + [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr, +diff --git a/drivers/clk/qcom/gcc-sc7280.c b/drivers/clk/qcom/gcc-sc7280.c +index 6cefcdc869905..ce7c5ba2b9b7a 100644 +--- a/drivers/clk/qcom/gcc-sc7280.c ++++ b/drivers/clk/qcom/gcc-sc7280.c +@@ -2998,7 +2998,7 @@ static struct clk_branch gcc_cfg_noc_lpass_clk = { + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_lpass_clk", +- .ops = &clk_branch2_ops, ++ .ops = &clk_branch2_aon_ops, + }, + }, + }; +diff --git a/drivers/clk/qcom/gcc-sm6125.c b/drivers/clk/qcom/gcc-sm6125.c +index 543cfab7561f9..431b55bb0d2f7 100644 +--- a/drivers/clk/qcom/gcc-sm6125.c ++++ b/drivers/clk/qcom/gcc-sm6125.c +@@ -1121,7 +1121,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_floor_ops, + }, + }; + +@@ -1143,7 +1143,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), +- .ops = &clk_rcg2_floor_ops, ++ .ops = &clk_rcg2_ops, + }, + }; + +diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c +index 761922ea5db76..1c92e73cd2b8c 100644 +--- a/drivers/clk/renesas/rzg2l-cpg.c ++++ b/drivers/clk/renesas/rzg2l-cpg.c +@@ -638,10 +638,16 @@ static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device + pm_clk_destroy(dev); + } + ++static void rzg2l_cpg_genpd_remove(void *data) ++{ ++ pm_genpd_remove(data); ++} ++ + static int __init rzg2l_cpg_add_clk_domain(struct device *dev) + { + struct device_node *np = dev->of_node; + struct generic_pm_domain *genpd; ++ int ret; + + genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL); + if (!genpd) +@@ -652,10 +658,15 @@ static int __init rzg2l_cpg_add_clk_domain(struct device *dev) + GENPD_FLAG_ACTIVE_WAKEUP; + genpd->attach_dev = rzg2l_cpg_attach_dev; + genpd->detach_dev = rzg2l_cpg_detach_dev; +- pm_genpd_init(genpd, &pm_domain_always_on_gov, false); ++ ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false); ++ if (ret) ++ return ret; + +- of_genpd_add_provider_simple(np, genpd); +- return 0; ++ ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, genpd); ++ if (ret) ++ return ret; ++ ++ return of_genpd_add_provider_simple(np, genpd); + } + + static int __init rzg2l_cpg_probe(struct platform_device *pdev) +diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +index f32366d9336e7..bd9a8782fec3d 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c ++++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +@@ -1464,7 +1464,7 @@ static void __init sun4i_ccu_init(struct device_node *node, + val &= ~GENMASK(7, 6); + writel(val | (2 << 6), reg + SUN4I_AHB_REG); + +- sunxi_ccu_probe(node, reg, desc); ++ of_sunxi_ccu_probe(node, reg, desc); + } + + static void __init sun4i_a10_ccu_setup(struct device_node *node) +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c +index a56142b909938..6f2a589705561 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c +@@ -196,7 +196,7 @@ static int sun50i_a100_r_ccu_probe(struct platform_device *pdev) + if (IS_ERR(reg)) + return PTR_ERR(reg); + +- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc); ++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_r_ccu_desc); + } + + static const struct of_device_id sun50i_a100_r_ccu_ids[] = { +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c +index 81b48c73d389f..913bb08e6dee8 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c +@@ -1247,7 +1247,7 @@ static int sun50i_a100_ccu_probe(struct platform_device *pdev) + writel(val, reg + sun50i_a100_usb2_clk_regs[i]); + } + +- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc); ++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc); + if (ret) + return ret; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index 149cfde817cba..54f25c624f020 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -955,7 +955,7 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev) + + writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); + +- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); ++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc); + if (ret) + return ret; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +index f8909a7ed5539..f30d7eb5424d8 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +@@ -232,7 +232,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, + return; + } + +- sunxi_ccu_probe(node, reg, desc); ++ of_sunxi_ccu_probe(node, reg, desc); + } + + static void __init sun50i_h6_r_ccu_setup(struct device_node *node) +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +index bff446b782907..c0800da2fa3d7 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +@@ -1240,7 +1240,7 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) + val |= BIT(24); + writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); + +- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc); ++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); + } + + static const struct of_device_id sun50i_h6_ccu_ids[] = { +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +index 225307305880e..22eb18079a154 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +@@ -1141,9 +1141,7 @@ static void __init sun50i_h616_ccu_setup(struct device_node *node) + val |= BIT(24); + writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); + +- i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); +- if (i) +- pr_err("%pOF: probing clocks fails: %d\n", node, i); ++ of_sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); + } + + CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu", +diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c +index b78e9b507c1c6..1f4bc0e773a7e 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun5i.c ++++ b/drivers/clk/sunxi-ng/ccu-sun5i.c +@@ -1012,7 +1012,7 @@ static void __init sun5i_ccu_init(struct device_node *node, + val &= ~GENMASK(7, 6); + writel(val | (2 << 6), reg + SUN5I_AHB_REG); + +- sunxi_ccu_probe(node, reg, desc); ++ of_sunxi_ccu_probe(node, reg, desc); + } + + static void __init sun5i_a10s_ccu_setup(struct device_node *node) +diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +index 9b40d53266a3f..3df5c0b415804 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c ++++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +@@ -1257,7 +1257,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) + val |= 0x3 << 12; + writel(val, reg + SUN6I_A31_AHB1_REG); + +- sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); ++ of_sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc); + + ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, + &sun6i_a31_cpu_nb); +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +index 103aa504f6c8a..577bb235d6584 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +@@ -745,7 +745,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) + val &= ~BIT(16); + writel(val, reg + SUN8I_A23_PLL_MIPI_REG); + +- sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); ++ of_sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc); + } + CLK_OF_DECLARE(sun8i_a23_ccu, "allwinner,sun8i-a23-ccu", + sun8i_a23_ccu_setup); +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +index 91838cd110377..8f65cd03f5acc 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +@@ -805,7 +805,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node) + val &= ~BIT(16); + writel(val, reg + SUN8I_A33_PLL_MIPI_REG); + +- sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); ++ of_sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc); + + /* Gate then ungate PLL CPU after any rate changes */ + ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb); +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +index 2b434521c5ccf..c2ddcd2ddab4e 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +@@ -906,7 +906,7 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev) + sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG); + sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG); + +- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_a83t_ccu_desc); ++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc); + } + + static const struct of_device_id sun8i_a83t_ccu_ids[] = { +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +index 524f33275bc73..4b94b6041b271 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +@@ -342,7 +342,7 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev) + goto err_disable_mod_clk; + } + +- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc); ++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc); + if (ret) + goto err_assert_reset; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +index 7e629a4493afd..d2fc2903787d8 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +@@ -1154,7 +1154,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, + val &= ~GENMASK(19, 16); + writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); + +- sunxi_ccu_probe(node, reg, desc); ++ of_sunxi_ccu_probe(node, reg, desc); + + /* Gate then ungate PLL CPU after any rate changes */ + ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb); +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c +index 4c8c491b87c27..9e754d1f754a1 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c +@@ -265,7 +265,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, + return; + } + +- sunxi_ccu_probe(node, reg, desc); ++ of_sunxi_ccu_probe(node, reg, desc); + } + + static void __init sun8i_a83t_r_ccu_setup(struct device_node *node) +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +index 84153418453f4..002e0c3a04dbe 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +@@ -1346,7 +1346,7 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + +- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc); ++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_r40_ccu_desc); + if (ret) + return ret; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +index f49724a22540e..ce150f83ab54e 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c ++++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +@@ -822,7 +822,7 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node, + val &= ~GENMASK(19, 16); + writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG); + +- sunxi_ccu_probe(node, reg, ccu_desc); ++ of_sunxi_ccu_probe(node, reg, ccu_desc); + } + + static void __init sun8i_v3s_ccu_setup(struct device_node *node) +diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c +index 6616e8114f623..261e64416f26a 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c ++++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c +@@ -246,8 +246,7 @@ static int sun9i_a80_de_clk_probe(struct platform_device *pdev) + goto err_disable_clk; + } + +- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, +- &sun9i_a80_de_clk_desc); ++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc); + if (ret) + goto err_assert_reset; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c +index 4b4a507d04edf..596243b3e0fa3 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c ++++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c +@@ -117,8 +117,7 @@ static int sun9i_a80_usb_clk_probe(struct platform_device *pdev) + return ret; + } + +- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, +- &sun9i_a80_usb_clk_desc); ++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_usb_clk_desc); + if (ret) + goto err_disable_clk; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c +index ef29582676f6e..97aaed0e68500 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c ++++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c +@@ -1231,7 +1231,7 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev) + sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG); + sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG); + +- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc); ++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc); + } + + static const struct of_device_id sun9i_a80_ccu_ids[] = { +diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c +index 7ecc3a5a5b5e1..61ad7ee91c114 100644 +--- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c ++++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c +@@ -538,7 +538,7 @@ static void __init suniv_f1c100s_ccu_setup(struct device_node *node) + val &= ~GENMASK(19, 16); + writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG); + +- sunxi_ccu_probe(node, reg, &suniv_ccu_desc); ++ of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc); + + /* Gate then ungate PLL CPU after any rate changes */ + ccu_pll_notifier_register(&suniv_pll_cpu_nb); +diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c +index 2e20e650b6c01..88cb569e58358 100644 +--- a/drivers/clk/sunxi-ng/ccu_common.c ++++ b/drivers/clk/sunxi-ng/ccu_common.c +@@ -7,6 +7,7 @@ + + #include <linux/clk.h> + #include <linux/clk-provider.h> ++#include <linux/device.h> + #include <linux/iopoll.h> + #include <linux/slab.h> + +@@ -14,6 +15,11 @@ + #include "ccu_gate.h" + #include "ccu_reset.h" + ++struct sunxi_ccu { ++ const struct sunxi_ccu_desc *desc; ++ struct ccu_reset reset; ++}; ++ + static DEFINE_SPINLOCK(ccu_lock); + + void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) +@@ -79,12 +85,15 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb) + &pll_nb->clk_nb); + } + +-int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, +- const struct sunxi_ccu_desc *desc) ++static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, ++ struct device_node *node, void __iomem *reg, ++ const struct sunxi_ccu_desc *desc) + { + struct ccu_reset *reset; + int i, ret; + ++ ccu->desc = desc; ++ + for (i = 0; i < desc->num_ccu_clks; i++) { + struct ccu_common *cclk = desc->ccu_clks[i]; + +@@ -103,7 +112,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + continue; + + name = hw->init->name; +- ret = of_clk_hw_register(node, hw); ++ if (dev) ++ ret = clk_hw_register(dev, hw); ++ else ++ ret = of_clk_hw_register(node, hw); + if (ret) { + pr_err("Couldn't register clock %d - %s\n", i, name); + goto err_clk_unreg; +@@ -115,15 +127,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + if (ret) + goto err_clk_unreg; + +- reset = kzalloc(sizeof(*reset), GFP_KERNEL); +- if (!reset) { +- ret = -ENOMEM; +- goto err_alloc_reset; +- } +- ++ reset = &ccu->reset; + reset->rcdev.of_node = node; + reset->rcdev.ops = &ccu_reset_ops; +- reset->rcdev.owner = THIS_MODULE; ++ reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE; + reset->rcdev.nr_resets = desc->num_resets; + reset->base = reg; + reset->lock = &ccu_lock; +@@ -131,13 +138,11 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + + ret = reset_controller_register(&reset->rcdev); + if (ret) +- goto err_of_clk_unreg; ++ goto err_del_provider; + + return 0; + +-err_of_clk_unreg: +- kfree(reset); +-err_alloc_reset: ++err_del_provider: + of_clk_del_provider(node); + err_clk_unreg: + while (--i >= 0) { +@@ -149,3 +154,59 @@ err_clk_unreg: + } + return ret; + } ++ ++static void devm_sunxi_ccu_release(struct device *dev, void *res) ++{ ++ struct sunxi_ccu *ccu = res; ++ const struct sunxi_ccu_desc *desc = ccu->desc; ++ int i; ++ ++ reset_controller_unregister(&ccu->reset.rcdev); ++ of_clk_del_provider(dev->of_node); ++ ++ for (i = 0; i < desc->hw_clks->num; i++) { ++ struct clk_hw *hw = desc->hw_clks->hws[i]; ++ ++ if (!hw) ++ continue; ++ clk_hw_unregister(hw); ++ } ++} ++ ++int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, ++ const struct sunxi_ccu_desc *desc) ++{ ++ struct sunxi_ccu *ccu; ++ int ret; ++ ++ ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL); ++ if (!ccu) ++ return -ENOMEM; ++ ++ ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc); ++ if (ret) { ++ devres_free(ccu); ++ return ret; ++ } ++ ++ devres_add(dev, ccu); ++ ++ return 0; ++} ++ ++void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, ++ const struct sunxi_ccu_desc *desc) ++{ ++ struct sunxi_ccu *ccu; ++ int ret; ++ ++ ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); ++ if (!ccu) ++ return; ++ ++ ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc); ++ if (ret) { ++ pr_err("%pOF: probing clocks failed: %d\n", node, ret); ++ kfree(ccu); ++ } ++} +diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h +index 04e7a12200a21..98a1834b58bb4 100644 +--- a/drivers/clk/sunxi-ng/ccu_common.h ++++ b/drivers/clk/sunxi-ng/ccu_common.h +@@ -63,7 +63,9 @@ struct ccu_pll_nb { + + int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb); + +-int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, +- const struct sunxi_ccu_desc *desc); ++int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, ++ const struct sunxi_ccu_desc *desc); ++void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, ++ const struct sunxi_ccu_desc *desc); + + #endif /* _COMMON_H_ */ +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 0f5e3983951a8..08f8cb944a2ac 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -24,6 +24,7 @@ config I8253_LOCK + + config OMAP_DM_TIMER + bool ++ select TIMER_OF + + config CLKBLD_I8253 + def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK +diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c +index 3819ef5b70989..3245eb0c602d2 100644 +--- a/drivers/clocksource/dw_apb_timer_of.c ++++ b/drivers/clocksource/dw_apb_timer_of.c +@@ -47,7 +47,7 @@ static int __init timer_get_base_and_rate(struct device_node *np, + pr_warn("pclk for %pOFn is present, but could not be activated\n", + np); + +- if (!of_property_read_u32(np, "clock-freq", rate) && ++ if (!of_property_read_u32(np, "clock-freq", rate) || + !of_property_read_u32(np, "clock-frequency", rate)) + return 0; + +diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c +index b6f97960d8ee0..1fccb457fcc54 100644 +--- a/drivers/clocksource/timer-ti-dm-systimer.c ++++ b/drivers/clocksource/timer-ti-dm-systimer.c +@@ -241,8 +241,7 @@ static void __init dmtimer_systimer_assign_alwon(void) + bool quirk_unreliable_oscillator = false; + + /* Quirk unreliable 32 KiHz oscillator with incomplete dts */ +- if (of_machine_is_compatible("ti,omap3-beagle") || +- of_machine_is_compatible("timll,omap3-devkit8000")) { ++ if (of_machine_is_compatible("ti,omap3-beagle-ab4")) { + quirk_unreliable_oscillator = true; + counter_32k = -ENODEV; + } +diff --git a/drivers/comedi/drivers/dt9812.c b/drivers/comedi/drivers/dt9812.c +index 634f57730c1e0..704b04d2980d3 100644 +--- a/drivers/comedi/drivers/dt9812.c ++++ b/drivers/comedi/drivers/dt9812.c +@@ -32,6 +32,7 @@ + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/errno.h> ++#include <linux/slab.h> + #include <linux/uaccess.h> + + #include "../comedi_usb.h" +@@ -237,22 +238,42 @@ static int dt9812_read_info(struct comedi_device *dev, + { + struct usb_device *usb = comedi_to_usb_dev(dev); + struct dt9812_private *devpriv = dev->private; +- struct dt9812_usb_cmd cmd; ++ struct dt9812_usb_cmd *cmd; ++ size_t tbuf_size; + int count, ret; ++ void *tbuf; + +- cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA); +- cmd.u.flash_data_info.address = ++ tbuf_size = max(sizeof(*cmd), buf_size); ++ ++ tbuf = kzalloc(tbuf_size, GFP_KERNEL); ++ if (!tbuf) ++ return -ENOMEM; ++ ++ cmd = tbuf; ++ ++ cmd->cmd = cpu_to_le32(DT9812_R_FLASH_DATA); ++ cmd->u.flash_data_info.address = + cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset); +- cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size); ++ cmd->u.flash_data_info.numbytes = cpu_to_le16(buf_size); + + /* DT9812 only responds to 32 byte writes!! */ + ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), +- &cmd, 32, &count, DT9812_USB_TIMEOUT); ++ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); + if (ret) +- return ret; ++ goto out; ++ ++ ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), ++ tbuf, buf_size, &count, DT9812_USB_TIMEOUT); ++ if (!ret) { ++ if (count == buf_size) ++ memcpy(buf, tbuf, buf_size); ++ else ++ ret = -EREMOTEIO; ++ } ++out: ++ kfree(tbuf); + +- return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), +- buf, buf_size, &count, DT9812_USB_TIMEOUT); ++ return ret; + } + + static int dt9812_read_multiple_registers(struct comedi_device *dev, +@@ -261,22 +282,42 @@ static int dt9812_read_multiple_registers(struct comedi_device *dev, + { + struct usb_device *usb = comedi_to_usb_dev(dev); + struct dt9812_private *devpriv = dev->private; +- struct dt9812_usb_cmd cmd; ++ struct dt9812_usb_cmd *cmd; + int i, count, ret; ++ size_t buf_size; ++ void *buf; + +- cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG); +- cmd.u.read_multi_info.count = reg_count; ++ buf_size = max_t(size_t, sizeof(*cmd), reg_count); ++ ++ buf = kzalloc(buf_size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ cmd = buf; ++ ++ cmd->cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG); ++ cmd->u.read_multi_info.count = reg_count; + for (i = 0; i < reg_count; i++) +- cmd.u.read_multi_info.address[i] = address[i]; ++ cmd->u.read_multi_info.address[i] = address[i]; + + /* DT9812 only responds to 32 byte writes!! */ + ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), +- &cmd, 32, &count, DT9812_USB_TIMEOUT); ++ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); + if (ret) +- return ret; ++ goto out; ++ ++ ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), ++ buf, reg_count, &count, DT9812_USB_TIMEOUT); ++ if (!ret) { ++ if (count == reg_count) ++ memcpy(value, buf, reg_count); ++ else ++ ret = -EREMOTEIO; ++ } ++out: ++ kfree(buf); + +- return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), +- value, reg_count, &count, DT9812_USB_TIMEOUT); ++ return ret; + } + + static int dt9812_write_multiple_registers(struct comedi_device *dev, +@@ -285,19 +326,27 @@ static int dt9812_write_multiple_registers(struct comedi_device *dev, + { + struct usb_device *usb = comedi_to_usb_dev(dev); + struct dt9812_private *devpriv = dev->private; +- struct dt9812_usb_cmd cmd; ++ struct dt9812_usb_cmd *cmd; + int i, count; ++ int ret; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; + +- cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG); +- cmd.u.read_multi_info.count = reg_count; ++ cmd->cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG); ++ cmd->u.read_multi_info.count = reg_count; + for (i = 0; i < reg_count; i++) { +- cmd.u.write_multi_info.write[i].address = address[i]; +- cmd.u.write_multi_info.write[i].value = value[i]; ++ cmd->u.write_multi_info.write[i].address = address[i]; ++ cmd->u.write_multi_info.write[i].value = value[i]; + } + + /* DT9812 only responds to 32 byte writes!! */ +- return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), +- &cmd, 32, &count, DT9812_USB_TIMEOUT); ++ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), ++ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); ++ kfree(cmd); ++ ++ return ret; + } + + static int dt9812_rmw_multiple_registers(struct comedi_device *dev, +@@ -306,17 +355,25 @@ static int dt9812_rmw_multiple_registers(struct comedi_device *dev, + { + struct usb_device *usb = comedi_to_usb_dev(dev); + struct dt9812_private *devpriv = dev->private; +- struct dt9812_usb_cmd cmd; ++ struct dt9812_usb_cmd *cmd; + int i, count; ++ int ret; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; + +- cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG); +- cmd.u.rmw_multi_info.count = reg_count; ++ cmd->cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG); ++ cmd->u.rmw_multi_info.count = reg_count; + for (i = 0; i < reg_count; i++) +- cmd.u.rmw_multi_info.rmw[i] = rmw[i]; ++ cmd->u.rmw_multi_info.rmw[i] = rmw[i]; + + /* DT9812 only responds to 32 byte writes!! */ +- return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), +- &cmd, 32, &count, DT9812_USB_TIMEOUT); ++ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), ++ cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); ++ kfree(cmd); ++ ++ return ret; + } + + static int dt9812_digital_in(struct comedi_device *dev, u8 *bits) +diff --git a/drivers/comedi/drivers/ni_usb6501.c b/drivers/comedi/drivers/ni_usb6501.c +index 5b6d9d783b2f7..c42987b74b1dc 100644 +--- a/drivers/comedi/drivers/ni_usb6501.c ++++ b/drivers/comedi/drivers/ni_usb6501.c +@@ -144,6 +144,10 @@ static const u8 READ_COUNTER_RESPONSE[] = {0x00, 0x01, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00}; + ++/* Largest supported packets */ ++static const size_t TX_MAX_SIZE = sizeof(SET_PORT_DIR_REQUEST); ++static const size_t RX_MAX_SIZE = sizeof(READ_PORT_RESPONSE); ++ + enum commands { + READ_PORT, + WRITE_PORT, +@@ -501,6 +505,12 @@ static int ni6501_find_endpoints(struct comedi_device *dev) + if (!devpriv->ep_rx || !devpriv->ep_tx) + return -ENODEV; + ++ if (usb_endpoint_maxp(devpriv->ep_rx) < RX_MAX_SIZE) ++ return -ENODEV; ++ ++ if (usb_endpoint_maxp(devpriv->ep_tx) < TX_MAX_SIZE) ++ return -ENODEV; ++ + return 0; + } + +diff --git a/drivers/comedi/drivers/vmk80xx.c b/drivers/comedi/drivers/vmk80xx.c +index 9f920819cd742..4b00a9ea611ab 100644 +--- a/drivers/comedi/drivers/vmk80xx.c ++++ b/drivers/comedi/drivers/vmk80xx.c +@@ -90,6 +90,9 @@ enum { + #define IC3_VERSION BIT(0) + #define IC6_VERSION BIT(1) + ++#define MIN_BUF_SIZE 64 ++#define PACKET_TIMEOUT 10000 /* ms */ ++ + enum vmk80xx_model { + VMK8055_MODEL, + VMK8061_MODEL +@@ -157,22 +160,21 @@ static void vmk80xx_do_bulk_msg(struct comedi_device *dev) + __u8 rx_addr; + unsigned int tx_pipe; + unsigned int rx_pipe; +- size_t size; ++ size_t tx_size; ++ size_t rx_size; + + tx_addr = devpriv->ep_tx->bEndpointAddress; + rx_addr = devpriv->ep_rx->bEndpointAddress; + tx_pipe = usb_sndbulkpipe(usb, tx_addr); + rx_pipe = usb_rcvbulkpipe(usb, rx_addr); ++ tx_size = usb_endpoint_maxp(devpriv->ep_tx); ++ rx_size = usb_endpoint_maxp(devpriv->ep_rx); + +- /* +- * The max packet size attributes of the K8061 +- * input/output endpoints are identical +- */ +- size = usb_endpoint_maxp(devpriv->ep_tx); ++ usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, tx_size, NULL, ++ PACKET_TIMEOUT); + +- usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, +- size, NULL, devpriv->ep_tx->bInterval); +- usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, size, NULL, HZ * 10); ++ usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, rx_size, NULL, ++ PACKET_TIMEOUT); + } + + static int vmk80xx_read_packet(struct comedi_device *dev) +@@ -191,7 +193,7 @@ static int vmk80xx_read_packet(struct comedi_device *dev) + pipe = usb_rcvintpipe(usb, ep->bEndpointAddress); + return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf, + usb_endpoint_maxp(ep), NULL, +- HZ * 10); ++ PACKET_TIMEOUT); + } + + static int vmk80xx_write_packet(struct comedi_device *dev, int cmd) +@@ -212,7 +214,7 @@ static int vmk80xx_write_packet(struct comedi_device *dev, int cmd) + pipe = usb_sndintpipe(usb, ep->bEndpointAddress); + return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf, + usb_endpoint_maxp(ep), NULL, +- HZ * 10); ++ PACKET_TIMEOUT); + } + + static int vmk80xx_reset_device(struct comedi_device *dev) +@@ -678,12 +680,12 @@ static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev) + struct vmk80xx_private *devpriv = dev->private; + size_t size; + +- size = usb_endpoint_maxp(devpriv->ep_rx); ++ size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE); + devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL); + if (!devpriv->usb_rx_buf) + return -ENOMEM; + +- size = usb_endpoint_maxp(devpriv->ep_tx); ++ size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE); + devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL); + if (!devpriv->usb_tx_buf) + return -ENOMEM; +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 5782b15a8caad..eeac6d8092298 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -1004,10 +1004,9 @@ static struct kobj_type ktype_cpufreq = { + .release = cpufreq_sysfs_release, + }; + +-static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu) ++static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu, ++ struct device *dev) + { +- struct device *dev = get_cpu_device(cpu); +- + if (unlikely(!dev)) + return; + +@@ -1391,7 +1390,7 @@ static int cpufreq_online(unsigned int cpu) + if (new_policy) { + for_each_cpu(j, policy->related_cpus) { + per_cpu(cpufreq_cpu_data, j) = policy; +- add_cpu_dev_symlink(policy, j); ++ add_cpu_dev_symlink(policy, j, get_cpu_device(j)); + } + + policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req), +@@ -1403,7 +1402,7 @@ static int cpufreq_online(unsigned int cpu) + + ret = freq_qos_add_request(&policy->constraints, + policy->min_freq_req, FREQ_QOS_MIN, +- policy->min); ++ FREQ_QOS_MIN_DEFAULT_VALUE); + if (ret < 0) { + /* + * So we don't call freq_qos_remove_request() for an +@@ -1423,7 +1422,7 @@ static int cpufreq_online(unsigned int cpu) + + ret = freq_qos_add_request(&policy->constraints, + policy->max_freq_req, FREQ_QOS_MAX, +- policy->max); ++ FREQ_QOS_MAX_DEFAULT_VALUE); + if (ret < 0) { + policy->max_freq_req = NULL; + goto out_destroy_policy; +@@ -1565,7 +1564,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) + /* Create sysfs link on CPU registration */ + policy = per_cpu(cpufreq_cpu_data, cpu); + if (policy) +- add_cpu_dev_symlink(policy, cpu); ++ add_cpu_dev_symlink(policy, cpu, dev); + + return 0; + } +@@ -2523,8 +2522,15 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, + if (ret) + return ret; + ++ /* ++ * Resolve policy min/max to available frequencies. It ensures ++ * no frequency resolution will neither overshoot the requested maximum ++ * nor undershoot the requested minimum. ++ */ + policy->min = new_data.min; + policy->max = new_data.max; ++ policy->min = __resolve_freq(policy, policy->min, CPUFREQ_RELATION_L); ++ policy->max = __resolve_freq(policy, policy->max, CPUFREQ_RELATION_H); + trace_cpu_frequency_limits(policy); + + policy->cached_target_freq = UINT_MAX; +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index 8c176b7dae415..e15c3bc17a55c 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -537,7 +537,8 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) + * scaling factor is too high, so recompute it to make the HWP_CAP + * highest performance correspond to the maximum turbo frequency. + */ +- if (turbo_freq < cpu->pstate.turbo_pstate * scaling) { ++ cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling; ++ if (turbo_freq < cpu->pstate.turbo_freq) { + cpu->pstate.turbo_freq = turbo_freq; + scaling = DIV_ROUND_UP(turbo_freq, cpu->pstate.turbo_pstate); + cpu->pstate.scaling = scaling; +@@ -998,9 +999,22 @@ static void intel_pstate_hwp_offline(struct cpudata *cpu) + */ + value &= ~GENMASK_ULL(31, 24); + value |= HWP_ENERGY_PERF_PREFERENCE(cpu->epp_cached); +- WRITE_ONCE(cpu->hwp_req_cached, value); ++ /* ++ * However, make sure that EPP will be set to "performance" when ++ * the CPU is brought back online again and the "performance" ++ * scaling algorithm is still in effect. ++ */ ++ cpu->epp_policy = CPUFREQ_POLICY_UNKNOWN; + } + ++ /* ++ * Clear the desired perf field in the cached HWP request value to ++ * prevent nonzero desired values from being leaked into the active ++ * mode. ++ */ ++ value &= ~HWP_DESIRED_PERF(~0L); ++ WRITE_ONCE(cpu->hwp_req_cached, value); ++ + value &= ~GENMASK_ULL(31, 0); + min_perf = HWP_LOWEST_PERF(READ_ONCE(cpu->hwp_cap_cached)); + +@@ -2241,6 +2255,7 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = { + X86_MATCH(BROADWELL_D, core_funcs), + X86_MATCH(BROADWELL_X, core_funcs), + X86_MATCH(SKYLAKE_X, core_funcs), ++ X86_MATCH(ICELAKE_X, core_funcs), + {} + }; + +@@ -2902,6 +2917,27 @@ static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy) + return intel_pstate_cpu_exit(policy); + } + ++static int intel_cpufreq_suspend(struct cpufreq_policy *policy) ++{ ++ intel_pstate_suspend(policy); ++ ++ if (hwp_active) { ++ struct cpudata *cpu = all_cpu_data[policy->cpu]; ++ u64 value = READ_ONCE(cpu->hwp_req_cached); ++ ++ /* ++ * Clear the desired perf field in MSR_HWP_REQUEST in case ++ * intel_cpufreq_adjust_perf() is in use and the last value ++ * written by it may not be suitable. ++ */ ++ value &= ~HWP_DESIRED_PERF(~0L); ++ wrmsrl_on_cpu(cpu->cpu, MSR_HWP_REQUEST, value); ++ WRITE_ONCE(cpu->hwp_req_cached, value); ++ } ++ ++ return 0; ++} ++ + static struct cpufreq_driver intel_cpufreq = { + .flags = CPUFREQ_CONST_LOOPS, + .verify = intel_cpufreq_verify_policy, +@@ -2911,7 +2947,7 @@ static struct cpufreq_driver intel_cpufreq = { + .exit = intel_cpufreq_cpu_exit, + .offline = intel_cpufreq_cpu_offline, + .online = intel_pstate_cpu_online, +- .suspend = intel_pstate_suspend, ++ .suspend = intel_cpufreq_suspend, + .resume = intel_pstate_resume, + .update_limits = intel_pstate_update_limits, + .name = "intel_cpufreq", +diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c +index a2be0df7e1747..35d93361fda1a 100644 +--- a/drivers/cpufreq/qcom-cpufreq-hw.c ++++ b/drivers/cpufreq/qcom-cpufreq-hw.c +@@ -304,7 +304,8 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) + if (capacity > max_capacity) + capacity = max_capacity; + +- arch_set_thermal_pressure(policy->cpus, max_capacity - capacity); ++ arch_set_thermal_pressure(policy->related_cpus, ++ max_capacity - capacity); + + /* + * In the unlikely case policy is unregistered do not enable +@@ -342,9 +343,9 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data) + + /* Disable interrupt and enable polling */ + disable_irq_nosync(c_data->throttle_irq); +- qcom_lmh_dcvs_notify(c_data); ++ schedule_delayed_work(&c_data->throttle_work, 0); + +- return 0; ++ return IRQ_HANDLED; + } + + static const struct qcom_cpufreq_soc_data qcom_soc_data = { +diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c +index 53ec9585ccd44..469e18547d06c 100644 +--- a/drivers/cpuidle/sysfs.c ++++ b/drivers/cpuidle/sysfs.c +@@ -488,6 +488,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) + &kdev->kobj, "state%d", i); + if (ret) { + kobject_put(&kobj->kobj); ++ kfree(kobj); + goto error_state; + } + cpuidle_add_s2idle_attr_group(kobj); +@@ -619,6 +620,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) + &kdev->kobj, "driver"); + if (ret) { + kobject_put(&kdrv->kobj); ++ kfree(kdrv); + return ret; + } + +@@ -705,7 +707,6 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev) + if (!kdev) + return -ENOMEM; + kdev->dev = dev; +- dev->kobj_dev = kdev; + + init_completion(&kdev->kobj_unregister); + +@@ -713,9 +714,11 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev) + "cpuidle"); + if (error) { + kobject_put(&kdev->kobj); ++ kfree(kdev); + return error; + } + ++ dev->kobj_dev = kdev; + kobject_uevent(&kdev->kobj, KOBJ_ADD); + + return 0; +diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c +index 9391ccc03382d..fe05584031914 100644 +--- a/drivers/crypto/atmel-aes.c ++++ b/drivers/crypto/atmel-aes.c +@@ -960,6 +960,7 @@ static int atmel_aes_handle_queue(struct atmel_aes_dev *dd, + ctx = crypto_tfm_ctx(areq->tfm); + + dd->areq = areq; ++ dd->ctx = ctx; + start_async = (areq != new_areq); + dd->is_async = start_async; + +@@ -1274,7 +1275,6 @@ static int atmel_aes_init_tfm(struct crypto_skcipher *tfm) + + crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_aes_reqctx)); + ctx->base.dd = dd; +- ctx->base.dd->ctx = &ctx->base; + ctx->base.start = atmel_aes_start; + + return 0; +@@ -1291,7 +1291,6 @@ static int atmel_aes_ctr_init_tfm(struct crypto_skcipher *tfm) + + crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_aes_reqctx)); + ctx->base.dd = dd; +- ctx->base.dd->ctx = &ctx->base; + ctx->base.start = atmel_aes_ctr_start; + + return 0; +@@ -1783,7 +1782,6 @@ static int atmel_aes_gcm_init(struct crypto_aead *tfm) + + crypto_aead_set_reqsize(tfm, sizeof(struct atmel_aes_reqctx)); + ctx->base.dd = dd; +- ctx->base.dd->ctx = &ctx->base; + ctx->base.start = atmel_aes_gcm_start; + + return 0; +@@ -1927,7 +1925,6 @@ static int atmel_aes_xts_init_tfm(struct crypto_skcipher *tfm) + crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_aes_reqctx) + + crypto_skcipher_reqsize(ctx->fallback_tfm)); + ctx->base.dd = dd; +- ctx->base.dd->ctx = &ctx->base; + ctx->base.start = atmel_aes_xts_start; + + return 0; +@@ -2154,7 +2151,6 @@ static int atmel_aes_authenc_init_tfm(struct crypto_aead *tfm, + crypto_aead_set_reqsize(tfm, (sizeof(struct atmel_aes_authenc_reqctx) + + auth_reqsize)); + ctx->base.dd = dd; +- ctx->base.dd->ctx = &ctx->base; + ctx->base.start = atmel_aes_authenc_start; + + return 0; +diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c +index 8697ae53b0633..d3d8bb0a69900 100644 +--- a/drivers/crypto/caam/caamalg.c ++++ b/drivers/crypto/caam/caamalg.c +@@ -1533,6 +1533,9 @@ static int aead_do_one_req(struct crypto_engine *engine, void *areq) + + ret = caam_jr_enqueue(ctx->jrdev, desc, aead_crypt_done, req); + ++ if (ret == -ENOSPC && engine->retry_support) ++ return ret; ++ + if (ret != -EINPROGRESS) { + aead_unmap(ctx->jrdev, rctx->edesc, req); + kfree(rctx->edesc); +@@ -1762,6 +1765,9 @@ static int skcipher_do_one_req(struct crypto_engine *engine, void *areq) + + ret = caam_jr_enqueue(ctx->jrdev, desc, skcipher_crypt_done, req); + ++ if (ret == -ENOSPC && engine->retry_support) ++ return ret; ++ + if (ret != -EINPROGRESS) { + skcipher_unmap(ctx->jrdev, rctx->edesc, req); + kfree(rctx->edesc); +diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c +index 8b8ed77d8715d..6753f0e6e55d1 100644 +--- a/drivers/crypto/caam/caamalg_qi2.c ++++ b/drivers/crypto/caam/caamalg_qi2.c +@@ -5470,7 +5470,7 @@ int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req) + dpaa2_fd_set_len(&fd, dpaa2_fl_get_len(&req->fd_flt[1])); + dpaa2_fd_set_flc(&fd, req->flc_dma); + +- ppriv = this_cpu_ptr(priv->ppriv); ++ ppriv = raw_cpu_ptr(priv->ppriv); + for (i = 0; i < (priv->dpseci_attr.num_tx_queues << 1); i++) { + err = dpaa2_io_service_enqueue_fq(ppriv->dpio, ppriv->req_fqid, + &fd); +diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c +index e8a6d8bc43b5d..36ef738e4a181 100644 +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -765,6 +765,9 @@ static int ahash_do_one_req(struct crypto_engine *engine, void *areq) + + ret = caam_jr_enqueue(jrdev, desc, state->ahash_op_done, req); + ++ if (ret == -ENOSPC && engine->retry_support) ++ return ret; ++ + if (ret != -EINPROGRESS) { + ahash_unmap(jrdev, state->edesc, req, 0); + kfree(state->edesc); +diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c +index e313233ec6de7..8867275767101 100644 +--- a/drivers/crypto/caam/caampkc.c ++++ b/drivers/crypto/caam/caampkc.c +@@ -380,6 +380,9 @@ static int akcipher_do_one_req(struct crypto_engine *engine, void *areq) + + ret = caam_jr_enqueue(jrdev, desc, req_ctx->akcipher_op_done, req); + ++ if (ret == -ENOSPC && engine->retry_support) ++ return ret; ++ + if (ret != -EINPROGRESS) { + rsa_pub_unmap(jrdev, req_ctx->edesc, req); + rsa_io_unmap(jrdev, req_ctx->edesc, req); +@@ -1153,16 +1156,27 @@ static struct caam_akcipher_alg caam_rsa = { + int caam_pkc_init(struct device *ctrldev) + { + struct caam_drv_private *priv = dev_get_drvdata(ctrldev); +- u32 pk_inst; ++ u32 pk_inst, pkha; + int err; + init_done = false; + + /* Determine public key hardware accelerator presence. */ +- if (priv->era < 10) ++ if (priv->era < 10) { + pk_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & + CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT; +- else +- pk_inst = rd_reg32(&priv->ctrl->vreg.pkha) & CHA_VER_NUM_MASK; ++ } else { ++ pkha = rd_reg32(&priv->ctrl->vreg.pkha); ++ pk_inst = pkha & CHA_VER_NUM_MASK; ++ ++ /* ++ * Newer CAAMs support partially disabled functionality. If this is the ++ * case, the number is non-zero, but this bit is set to indicate that ++ * no encryption or decryption is supported. Only signing and verifying ++ * is supported. ++ */ ++ if (pkha & CHA_VER_MISC_PKHA_NO_CRYPT) ++ pk_inst = 0; ++ } + + /* Do not register algorithms if PKHA is not present. */ + if (!pk_inst) +diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h +index af61f3a2c0d46..3738625c02509 100644 +--- a/drivers/crypto/caam/regs.h ++++ b/drivers/crypto/caam/regs.h +@@ -322,6 +322,9 @@ struct version_regs { + /* CHA Miscellaneous Information - AESA_MISC specific */ + #define CHA_VER_MISC_AES_GCM BIT(1 + CHA_VER_MISC_SHIFT) + ++/* CHA Miscellaneous Information - PKHA_MISC specific */ ++#define CHA_VER_MISC_PKHA_NO_CRYPT BIT(7 + CHA_VER_MISC_SHIFT) ++ + /* + * caam_perfmon - Performance Monitor/Secure Memory Status/ + * CAAM Global Status/Component Version IDs +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 2ecb0e1f65d8d..e2806ca3300a8 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -241,7 +241,7 @@ static int __sev_platform_init_locked(int *error) + struct psp_device *psp = psp_master; + struct sev_data_init data; + struct sev_device *sev; +- int rc = 0; ++ int psp_ret, rc = 0; + + if (!psp || !psp->sev_data) + return -ENODEV; +@@ -266,7 +266,21 @@ static int __sev_platform_init_locked(int *error) + data.tmr_len = SEV_ES_TMR_SIZE; + } + +- rc = __sev_do_cmd_locked(SEV_CMD_INIT, &data, error); ++ rc = __sev_do_cmd_locked(SEV_CMD_INIT, &data, &psp_ret); ++ if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) { ++ /* ++ * Initialization command returned an integrity check failure ++ * status code, meaning that firmware load and validation of SEV ++ * related persistent data has failed. Retrying the ++ * initialization function should succeed by replacing the state ++ * with a reset state. ++ */ ++ dev_dbg(sev->dev, "SEV: retrying INIT command"); ++ rc = __sev_do_cmd_locked(SEV_CMD_INIT, &data, &psp_ret); ++ } ++ if (error) ++ *error = psp_ret; ++ + if (rc) + return rc; + +@@ -1091,18 +1105,6 @@ void sev_pci_init(void) + + /* Initialize the platform */ + rc = sev_platform_init(&error); +- if (rc && (error == SEV_RET_SECURE_DATA_INVALID)) { +- /* +- * INIT command returned an integrity check failure +- * status code, meaning that firmware load and +- * validation of SEV related persistent data has +- * failed and persistent state has been erased. +- * Retrying INIT command here should succeed. +- */ +- dev_dbg(sev->dev, "SEV: retrying INIT command"); +- rc = sev_platform_init(&error); +- } +- + if (rc) { + dev_err(sev->dev, "SEV: failed to INIT error %#x\n", error); + return; +diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c +index e599ac6dc162a..790fa9058a36d 100644 +--- a/drivers/crypto/ccree/cc_driver.c ++++ b/drivers/crypto/ccree/cc_driver.c +@@ -103,7 +103,8 @@ MODULE_DEVICE_TABLE(of, arm_ccree_dev_of_match); + static void init_cc_cache_params(struct cc_drvdata *drvdata) + { + struct device *dev = drvdata_to_dev(drvdata); +- u32 cache_params, ace_const, val, mask; ++ u32 cache_params, ace_const, val; ++ u64 mask; + + /* compute CC_AXIM_CACHE_PARAMS */ + cache_params = cc_ioread(drvdata, CC_REG(AXIM_CACHE_PARAMS)); +diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c +index a032c192ef1d6..7ba7641723a0b 100644 +--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c ++++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c +@@ -1865,7 +1865,7 @@ static int hpre_curve25519_src_init(struct hpre_asym_request *hpre_req, + */ + if (memcmp(ptr, p, ctx->key_sz) == 0) { + dev_err(dev, "gx is p!\n"); +- return -EINVAL; ++ goto err; + } else if (memcmp(ptr, p, ctx->key_sz) > 0) { + hpre_curve25519_src_modulo_p(ptr); + } +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index 369562d34d66a..ff1122153fbec 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -5986,7 +5986,7 @@ int hisi_qm_resume(struct device *dev) + if (ret) + pci_err(pdev, "failed to start qm(%d)\n", ret); + +- return 0; ++ return ret; + } + EXPORT_SYMBOL_GPL(hisi_qm_resume); + +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c +index 146a55ac4b9b0..be1ad55a208f6 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c +@@ -494,12 +494,11 @@ static ssize_t kvf_limits_store(struct device *dev, + { + struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); + int lfs_num; ++ int ret; + +- if (kstrtoint(buf, 0, &lfs_num)) { +- dev_err(dev, "lfs count %d must be in range [1 - %d]\n", +- lfs_num, num_online_cpus()); +- return -EINVAL; +- } ++ ret = kstrtoint(buf, 0, &lfs_num); ++ if (ret) ++ return ret; + if (lfs_num < 1 || lfs_num > num_online_cpus()) { + dev_err(dev, "lfs count %d must be in range [1 - %d]\n", + lfs_num, num_online_cpus()); +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +index dff34b3ec09e1..7c1b92aaab398 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +@@ -29,7 +29,8 @@ static struct otx2_cpt_bitmap get_cores_bmap(struct device *dev, + bool found = false; + int i; + +- if (eng_grp->g->engs_num > OTX2_CPT_MAX_ENGINES) { ++ if (eng_grp->g->engs_num < 0 || ++ eng_grp->g->engs_num > OTX2_CPT_MAX_ENGINES) { + dev_err(dev, "unsupported number of engines %d on octeontx2\n", + eng_grp->g->engs_num); + return bmap; +diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c +index a72723455df72..877a948469bd1 100644 +--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c ++++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c +@@ -1274,6 +1274,7 @@ static int aead_do_fallback(struct aead_request *req, bool is_enc) + req->base.complete, req->base.data); + aead_request_set_crypt(&rctx->fbk_req, req->src, + req->dst, req->cryptlen, req->iv); ++ aead_request_set_ad(&rctx->fbk_req, req->assoclen); + ret = is_enc ? crypto_aead_encrypt(&rctx->fbk_req) : + crypto_aead_decrypt(&rctx->fbk_req); + } else { +diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c +index 9b968ac4ee7b6..a196bb8b17010 100644 +--- a/drivers/crypto/omap-aes.c ++++ b/drivers/crypto/omap-aes.c +@@ -1302,7 +1302,7 @@ static int omap_aes_suspend(struct device *dev) + + static int omap_aes_resume(struct device *dev) + { +- pm_runtime_resume_and_get(dev); ++ pm_runtime_get_sync(dev); + return 0; + } + #endif +diff --git a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c +index 33d8e50dcbdac..88c0ded411f15 100644 +--- a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c ++++ b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) + /* Copyright(c) 2020 Intel Corporation */ ++#include <linux/iopoll.h> + #include <adf_accel_devices.h> + #include <adf_common_drv.h> + #include <adf_pf2vf_msg.h> +@@ -161,6 +162,35 @@ static void adf_enable_ints(struct adf_accel_dev *accel_dev) + ADF_CSR_WR(addr, ADF_4XXX_SMIAPF_MASK_OFFSET, 0); + } + ++static int adf_init_device(struct adf_accel_dev *accel_dev) ++{ ++ void __iomem *addr; ++ u32 status; ++ u32 csr; ++ int ret; ++ ++ addr = (&GET_BARS(accel_dev)[ADF_4XXX_PMISC_BAR])->virt_addr; ++ ++ /* Temporarily mask PM interrupt */ ++ csr = ADF_CSR_RD(addr, ADF_4XXX_ERRMSK2); ++ csr |= ADF_4XXX_PM_SOU; ++ ADF_CSR_WR(addr, ADF_4XXX_ERRMSK2, csr); ++ ++ /* Set DRV_ACTIVE bit to power up the device */ ++ ADF_CSR_WR(addr, ADF_4XXX_PM_INTERRUPT, ADF_4XXX_PM_DRV_ACTIVE); ++ ++ /* Poll status register to make sure the device is powered up */ ++ ret = read_poll_timeout(ADF_CSR_RD, status, ++ status & ADF_4XXX_PM_INIT_STATE, ++ ADF_4XXX_PM_POLL_DELAY_US, ++ ADF_4XXX_PM_POLL_TIMEOUT_US, true, addr, ++ ADF_4XXX_PM_STATUS); ++ if (ret) ++ dev_err(&GET_DEV(accel_dev), "Failed to power up the device\n"); ++ ++ return ret; ++} ++ + static int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev) + { + return 0; +@@ -215,6 +245,7 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data) + hw_data->exit_arb = adf_exit_arb; + hw_data->get_arb_mapping = adf_get_arbiter_mapping; + hw_data->enable_ints = adf_enable_ints; ++ hw_data->init_device = adf_init_device; + hw_data->reset_device = adf_reset_flr; + hw_data->admin_ae_mask = ADF_4XXX_ADMIN_AE_MASK; + hw_data->uof_get_num_objs = uof_get_num_objs; +diff --git a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h +index 4fe2a776293c2..924bac6feb372 100644 +--- a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h ++++ b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h +@@ -62,6 +62,16 @@ + #define ADF_4XXX_ADMINMSGLR_OFFSET (0x500578) + #define ADF_4XXX_MAILBOX_BASE_OFFSET (0x600970) + ++/* Power management */ ++#define ADF_4XXX_PM_POLL_DELAY_US 20 ++#define ADF_4XXX_PM_POLL_TIMEOUT_US USEC_PER_SEC ++#define ADF_4XXX_PM_STATUS (0x50A00C) ++#define ADF_4XXX_PM_INTERRUPT (0x50A028) ++#define ADF_4XXX_PM_DRV_ACTIVE BIT(20) ++#define ADF_4XXX_PM_INIT_STATE BIT(21) ++/* Power management source in ERRSOU2 and ERRMSK2 */ ++#define ADF_4XXX_PM_SOU BIT(18) ++ + /* Firmware Binaries */ + #define ADF_4XXX_FW "qat_4xxx.bin" + #define ADF_4XXX_MMP "qat_4xxx_mmp.bin" +diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h +index 38c0af6d4e43e..580566cfcb04c 100644 +--- a/drivers/crypto/qat/qat_common/adf_accel_devices.h ++++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h +@@ -166,6 +166,7 @@ struct adf_hw_device_data { + int (*init_arb)(struct adf_accel_dev *accel_dev); + void (*exit_arb)(struct adf_accel_dev *accel_dev); + const u32 *(*get_arb_mapping)(void); ++ int (*init_device)(struct adf_accel_dev *accel_dev); + void (*disable_iov)(struct adf_accel_dev *accel_dev); + void (*configure_iov_threads)(struct adf_accel_dev *accel_dev, + bool enable); +diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c +index 60bc7b991d351..e3749e5817d94 100644 +--- a/drivers/crypto/qat/qat_common/adf_init.c ++++ b/drivers/crypto/qat/qat_common/adf_init.c +@@ -79,6 +79,11 @@ int adf_dev_init(struct adf_accel_dev *accel_dev) + return -EFAULT; + } + ++ if (hw_data->init_device && hw_data->init_device(accel_dev)) { ++ dev_err(&GET_DEV(accel_dev), "Failed to initialize device\n"); ++ return -EFAULT; ++ } ++ + if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) { + dev_err(&GET_DEV(accel_dev), "Failed initialize admin comms\n"); + return -EFAULT; +diff --git a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c +index 976b9ab7617cd..7ec81989beb03 100644 +--- a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c ++++ b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c +@@ -117,37 +117,19 @@ static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr) + + mutex_lock(lock); + +- /* Check if PF2VF CSR is in use by remote function */ ++ /* Check if the PFVF CSR is in use by remote function */ + val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset); + if ((val & remote_in_use_mask) == remote_in_use_pattern) { + dev_dbg(&GET_DEV(accel_dev), +- "PF2VF CSR in use by remote function\n"); ++ "PFVF CSR in use by remote function\n"); + ret = -EBUSY; + goto out; + } + +- /* Attempt to get ownership of PF2VF CSR */ + msg &= ~local_in_use_mask; + msg |= local_in_use_pattern; +- ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg); + +- /* Wait in case remote func also attempting to get ownership */ +- msleep(ADF_IOV_MSG_COLLISION_DETECT_DELAY); +- +- val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset); +- if ((val & local_in_use_mask) != local_in_use_pattern) { +- dev_dbg(&GET_DEV(accel_dev), +- "PF2VF CSR in use by remote - collision detected\n"); +- ret = -EBUSY; +- goto out; +- } +- +- /* +- * This function now owns the PV2VF CSR. The IN_USE_BY pattern must +- * remain in the PF2VF CSR for all writes including ACK from remote +- * until this local function relinquishes the CSR. Send the message +- * by interrupting the remote. +- */ ++ /* Attempt to get ownership of the PFVF CSR */ + ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg | int_bit); + + /* Wait for confirmation from remote func it received the message */ +@@ -162,7 +144,14 @@ static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr) + ret = -EIO; + } + +- /* Finished with PF2VF CSR; relinquish it and leave msg in CSR */ ++ if (val != msg) { ++ dev_dbg(&GET_DEV(accel_dev), ++ "Collision - PFVF CSR overwritten by remote function\n"); ++ ret = -EIO; ++ goto out; ++ } ++ ++ /* Finished with the PFVF CSR; relinquish it and leave msg in CSR */ + ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, val & ~local_in_use_mask); + out: + mutex_unlock(lock); +@@ -170,12 +159,13 @@ out: + } + + /** +- * adf_iov_putmsg() - send PF2VF message ++ * adf_iov_putmsg() - send PFVF message + * @accel_dev: Pointer to acceleration device. + * @msg: Message to send +- * @vf_nr: VF number to which the message will be sent ++ * @vf_nr: VF number to which the message will be sent if on PF, ignored ++ * otherwise + * +- * Function sends a message from the PF to a VF ++ * Function sends a message through the PFVF channel + * + * Return: 0 on success, error code otherwise. + */ +@@ -204,6 +194,11 @@ void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info) + + /* Read message from the VF */ + msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr)); ++ if (!(msg & ADF_VF2PF_INT)) { ++ dev_info(&GET_DEV(accel_dev), ++ "Spurious VF2PF interrupt, msg %X. Ignored\n", msg); ++ goto out; ++ } + + /* To ACK, clear the VF2PFINT bit */ + msg &= ~ADF_VF2PF_INT; +@@ -287,6 +282,7 @@ void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info) + if (resp && adf_iov_putmsg(accel_dev, resp, vf_nr)) + dev_err(&GET_DEV(accel_dev), "Failed to send response to VF\n"); + ++out: + /* re-enable interrupt on PF from this VF */ + adf_enable_vf2pf_interrupts(accel_dev, (1 << vf_nr)); + +diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c +index 7828a6573f3e2..2e300c255ab94 100644 +--- a/drivers/crypto/qat/qat_common/adf_vf_isr.c ++++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c +@@ -101,6 +101,11 @@ static void adf_pf2vf_bh_handler(void *data) + + /* Read the message from PF */ + msg = ADF_CSR_RD(pmisc_bar_addr, hw_data->get_pf2vf_offset(0)); ++ if (!(msg & ADF_PF2VF_INT)) { ++ dev_info(&GET_DEV(accel_dev), ++ "Spurious PF2VF interrupt, msg %X. Ignored\n", msg); ++ goto out; ++ } + + if (!(msg & ADF_PF2VF_MSGORIGIN_SYSTEM)) + /* Ignore legacy non-system (non-kernel) PF2VF messages */ +@@ -149,6 +154,7 @@ static void adf_pf2vf_bh_handler(void *data) + msg &= ~ADF_PF2VF_INT; + ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg); + ++out: + /* Re-enable PF2VF interrupts */ + adf_enable_pf2vf_interrupts(accel_dev); + return; +diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c +index 290e2446a2f35..97a530171f07a 100644 +--- a/drivers/crypto/qce/aead.c ++++ b/drivers/crypto/qce/aead.c +@@ -802,8 +802,8 @@ static int qce_aead_register_one(const struct qce_aead_def *def, struct qce_devi + + ret = crypto_register_aead(alg); + if (ret) { +- kfree(tmpl); + dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); ++ kfree(tmpl); + return ret; + } + +diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c +index 8e6fcf2c21cc0..59159f5e64e52 100644 +--- a/drivers/crypto/qce/sha.c ++++ b/drivers/crypto/qce/sha.c +@@ -498,8 +498,8 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, + + ret = crypto_register_ahash(alg); + if (ret) { +- kfree(tmpl); + dev_err(qce->dev, "%s registration failed\n", base->cra_name); ++ kfree(tmpl); + return ret; + } + +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 8ff10928f581d..3d27cd5210ef5 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -484,8 +484,8 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, + + ret = crypto_register_skcipher(alg); + if (ret) { +- kfree(tmpl); + dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); ++ kfree(tmpl); + return ret; + } + +diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c +index 55aa3a71169b0..7717e9e5977bb 100644 +--- a/drivers/crypto/s5p-sss.c ++++ b/drivers/crypto/s5p-sss.c +@@ -2171,6 +2171,8 @@ static int s5p_aes_probe(struct platform_device *pdev) + + variant = find_s5p_sss_version(pdev); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; + + /* + * Note: HASH and PRNG uses the same registers in secss, avoid +diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c +index 75867c0b00172..be1bf39a317de 100644 +--- a/drivers/crypto/stm32/stm32-crc32.c ++++ b/drivers/crypto/stm32/stm32-crc32.c +@@ -279,7 +279,7 @@ static struct shash_alg algs[] = { + .digestsize = CHKSUM_DIGEST_SIZE, + .base = { + .cra_name = "crc32", +- .cra_driver_name = DRIVER_NAME, ++ .cra_driver_name = "stm32-crc32-crc32", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, +@@ -301,7 +301,7 @@ static struct shash_alg algs[] = { + .digestsize = CHKSUM_DIGEST_SIZE, + .base = { + .cra_name = "crc32c", +- .cra_driver_name = DRIVER_NAME, ++ .cra_driver_name = "stm32-crc32-crc32c", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, +diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c +index 7389a0536ff02..81eb136b6c11d 100644 +--- a/drivers/crypto/stm32/stm32-cryp.c ++++ b/drivers/crypto/stm32/stm32-cryp.c +@@ -37,7 +37,6 @@ + /* Mode mask = bits [15..0] */ + #define FLG_MODE_MASK GENMASK(15, 0) + /* Bit [31..16] status */ +-#define FLG_CCM_PADDED_WA BIT(16) + + /* Registers */ + #define CRYP_CR 0x00000000 +@@ -105,8 +104,6 @@ + /* Misc */ + #define AES_BLOCK_32 (AES_BLOCK_SIZE / sizeof(u32)) + #define GCM_CTR_INIT 2 +-#define _walked_in (cryp->in_walk.offset - cryp->in_sg->offset) +-#define _walked_out (cryp->out_walk.offset - cryp->out_sg->offset) + #define CRYP_AUTOSUSPEND_DELAY 50 + + struct stm32_cryp_caps { +@@ -144,26 +141,16 @@ struct stm32_cryp { + size_t authsize; + size_t hw_blocksize; + +- size_t total_in; +- size_t total_in_save; +- size_t total_out; +- size_t total_out_save; ++ size_t payload_in; ++ size_t header_in; ++ size_t payload_out; + +- struct scatterlist *in_sg; + struct scatterlist *out_sg; +- struct scatterlist *out_sg_save; +- +- struct scatterlist in_sgl; +- struct scatterlist out_sgl; +- bool sgs_copied; +- +- int in_sg_len; +- int out_sg_len; + + struct scatter_walk in_walk; + struct scatter_walk out_walk; + +- u32 last_ctr[4]; ++ __be32 last_ctr[4]; + u32 gcm_ctr; + }; + +@@ -262,6 +249,7 @@ static inline int stm32_cryp_wait_output(struct stm32_cryp *cryp) + } + + static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp); ++static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err); + + static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx) + { +@@ -283,103 +271,6 @@ static struct stm32_cryp *stm32_cryp_find_dev(struct stm32_cryp_ctx *ctx) + return cryp; + } + +-static int stm32_cryp_check_aligned(struct scatterlist *sg, size_t total, +- size_t align) +-{ +- int len = 0; +- +- if (!total) +- return 0; +- +- if (!IS_ALIGNED(total, align)) +- return -EINVAL; +- +- while (sg) { +- if (!IS_ALIGNED(sg->offset, sizeof(u32))) +- return -EINVAL; +- +- if (!IS_ALIGNED(sg->length, align)) +- return -EINVAL; +- +- len += sg->length; +- sg = sg_next(sg); +- } +- +- if (len != total) +- return -EINVAL; +- +- return 0; +-} +- +-static int stm32_cryp_check_io_aligned(struct stm32_cryp *cryp) +-{ +- int ret; +- +- ret = stm32_cryp_check_aligned(cryp->in_sg, cryp->total_in, +- cryp->hw_blocksize); +- if (ret) +- return ret; +- +- ret = stm32_cryp_check_aligned(cryp->out_sg, cryp->total_out, +- cryp->hw_blocksize); +- +- return ret; +-} +- +-static void sg_copy_buf(void *buf, struct scatterlist *sg, +- unsigned int start, unsigned int nbytes, int out) +-{ +- struct scatter_walk walk; +- +- if (!nbytes) +- return; +- +- scatterwalk_start(&walk, sg); +- scatterwalk_advance(&walk, start); +- scatterwalk_copychunks(buf, &walk, nbytes, out); +- scatterwalk_done(&walk, out, 0); +-} +- +-static int stm32_cryp_copy_sgs(struct stm32_cryp *cryp) +-{ +- void *buf_in, *buf_out; +- int pages, total_in, total_out; +- +- if (!stm32_cryp_check_io_aligned(cryp)) { +- cryp->sgs_copied = 0; +- return 0; +- } +- +- total_in = ALIGN(cryp->total_in, cryp->hw_blocksize); +- pages = total_in ? get_order(total_in) : 1; +- buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages); +- +- total_out = ALIGN(cryp->total_out, cryp->hw_blocksize); +- pages = total_out ? get_order(total_out) : 1; +- buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages); +- +- if (!buf_in || !buf_out) { +- dev_err(cryp->dev, "Can't allocate pages when unaligned\n"); +- cryp->sgs_copied = 0; +- return -EFAULT; +- } +- +- sg_copy_buf(buf_in, cryp->in_sg, 0, cryp->total_in, 0); +- +- sg_init_one(&cryp->in_sgl, buf_in, total_in); +- cryp->in_sg = &cryp->in_sgl; +- cryp->in_sg_len = 1; +- +- sg_init_one(&cryp->out_sgl, buf_out, total_out); +- cryp->out_sg_save = cryp->out_sg; +- cryp->out_sg = &cryp->out_sgl; +- cryp->out_sg_len = 1; +- +- cryp->sgs_copied = 1; +- +- return 0; +-} +- + static void stm32_cryp_hw_write_iv(struct stm32_cryp *cryp, __be32 *iv) + { + if (!iv) +@@ -481,16 +372,99 @@ static int stm32_cryp_gcm_init(struct stm32_cryp *cryp, u32 cfg) + + /* Wait for end of processing */ + ret = stm32_cryp_wait_enable(cryp); +- if (ret) ++ if (ret) { + dev_err(cryp->dev, "Timeout (gcm init)\n"); ++ return ret; ++ } + +- return ret; ++ /* Prepare next phase */ ++ if (cryp->areq->assoclen) { ++ cfg |= CR_PH_HEADER; ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ } else if (stm32_cryp_get_input_text_len(cryp)) { ++ cfg |= CR_PH_PAYLOAD; ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ } ++ ++ return 0; ++} ++ ++static void stm32_crypt_gcmccm_end_header(struct stm32_cryp *cryp) ++{ ++ u32 cfg; ++ int err; ++ ++ /* Check if whole header written */ ++ if (!cryp->header_in) { ++ /* Wait for completion */ ++ err = stm32_cryp_wait_busy(cryp); ++ if (err) { ++ dev_err(cryp->dev, "Timeout (gcm/ccm header)\n"); ++ stm32_cryp_write(cryp, CRYP_IMSCR, 0); ++ stm32_cryp_finish_req(cryp, err); ++ return; ++ } ++ ++ if (stm32_cryp_get_input_text_len(cryp)) { ++ /* Phase 3 : payload */ ++ cfg = stm32_cryp_read(cryp, CRYP_CR); ++ cfg &= ~CR_CRYPEN; ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ ++ cfg &= ~CR_PH_MASK; ++ cfg |= CR_PH_PAYLOAD | CR_CRYPEN; ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ } else { ++ /* ++ * Phase 4 : tag. ++ * Nothing to read, nothing to write, caller have to ++ * end request ++ */ ++ } ++ } ++} ++ ++static void stm32_cryp_write_ccm_first_header(struct stm32_cryp *cryp) ++{ ++ unsigned int i; ++ size_t written; ++ size_t len; ++ u32 alen = cryp->areq->assoclen; ++ u32 block[AES_BLOCK_32] = {0}; ++ u8 *b8 = (u8 *)block; ++ ++ if (alen <= 65280) { ++ /* Write first u32 of B1 */ ++ b8[0] = (alen >> 8) & 0xFF; ++ b8[1] = alen & 0xFF; ++ len = 2; ++ } else { ++ /* Build the two first u32 of B1 */ ++ b8[0] = 0xFF; ++ b8[1] = 0xFE; ++ b8[2] = (alen & 0xFF000000) >> 24; ++ b8[3] = (alen & 0x00FF0000) >> 16; ++ b8[4] = (alen & 0x0000FF00) >> 8; ++ b8[5] = alen & 0x000000FF; ++ len = 6; ++ } ++ ++ written = min_t(size_t, AES_BLOCK_SIZE - len, alen); ++ ++ scatterwalk_copychunks((char *)block + len, &cryp->in_walk, written, 0); ++ for (i = 0; i < AES_BLOCK_32; i++) ++ stm32_cryp_write(cryp, CRYP_DIN, block[i]); ++ ++ cryp->header_in -= written; ++ ++ stm32_crypt_gcmccm_end_header(cryp); + } + + static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg) + { + int ret; +- u8 iv[AES_BLOCK_SIZE], b0[AES_BLOCK_SIZE]; ++ u32 iv_32[AES_BLOCK_32], b0_32[AES_BLOCK_32]; ++ u8 *iv = (u8 *)iv_32, *b0 = (u8 *)b0_32; + __be32 *bd; + u32 *d; + unsigned int i, textlen; +@@ -531,10 +505,24 @@ static int stm32_cryp_ccm_init(struct stm32_cryp *cryp, u32 cfg) + + /* Wait for end of processing */ + ret = stm32_cryp_wait_enable(cryp); +- if (ret) ++ if (ret) { + dev_err(cryp->dev, "Timeout (ccm init)\n"); ++ return ret; ++ } + +- return ret; ++ /* Prepare next phase */ ++ if (cryp->areq->assoclen) { ++ cfg |= CR_PH_HEADER | CR_CRYPEN; ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ ++ /* Write first (special) block (may move to next phase [payload]) */ ++ stm32_cryp_write_ccm_first_header(cryp); ++ } else if (stm32_cryp_get_input_text_len(cryp)) { ++ cfg |= CR_PH_PAYLOAD; ++ stm32_cryp_write(cryp, CRYP_CR, cfg); ++ } ++ ++ return 0; + } + + static int stm32_cryp_hw_init(struct stm32_cryp *cryp) +@@ -542,7 +530,7 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) + int ret; + u32 cfg, hw_mode; + +- pm_runtime_resume_and_get(cryp->dev); ++ pm_runtime_get_sync(cryp->dev); + + /* Disable interrupt */ + stm32_cryp_write(cryp, CRYP_IMSCR, 0); +@@ -605,16 +593,6 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) + if (ret) + return ret; + +- /* Phase 2 : header (authenticated data) */ +- if (cryp->areq->assoclen) { +- cfg |= CR_PH_HEADER; +- } else if (stm32_cryp_get_input_text_len(cryp)) { +- cfg |= CR_PH_PAYLOAD; +- stm32_cryp_write(cryp, CRYP_CR, cfg); +- } else { +- cfg |= CR_PH_INIT; +- } +- + break; + + case CR_DES_CBC: +@@ -633,8 +611,6 @@ static int stm32_cryp_hw_init(struct stm32_cryp *cryp) + + stm32_cryp_write(cryp, CRYP_CR, cfg); + +- cryp->flags &= ~FLG_CCM_PADDED_WA; +- + return 0; + } + +@@ -644,28 +620,9 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) + /* Phase 4 : output tag */ + err = stm32_cryp_read_auth_tag(cryp); + +- if (!err && (!(is_gcm(cryp) || is_ccm(cryp)))) ++ if (!err && (!(is_gcm(cryp) || is_ccm(cryp) || is_ecb(cryp)))) + stm32_cryp_get_iv(cryp); + +- if (cryp->sgs_copied) { +- void *buf_in, *buf_out; +- int pages, len; +- +- buf_in = sg_virt(&cryp->in_sgl); +- buf_out = sg_virt(&cryp->out_sgl); +- +- sg_copy_buf(buf_out, cryp->out_sg_save, 0, +- cryp->total_out_save, 1); +- +- len = ALIGN(cryp->total_in_save, cryp->hw_blocksize); +- pages = len ? get_order(len) : 1; +- free_pages((unsigned long)buf_in, pages); +- +- len = ALIGN(cryp->total_out_save, cryp->hw_blocksize); +- pages = len ? get_order(len) : 1; +- free_pages((unsigned long)buf_out, pages); +- } +- + pm_runtime_mark_last_busy(cryp->dev); + pm_runtime_put_autosuspend(cryp->dev); + +@@ -674,8 +631,6 @@ static void stm32_cryp_finish_req(struct stm32_cryp *cryp, int err) + else + crypto_finalize_skcipher_request(cryp->engine, cryp->req, + err); +- +- memset(cryp->ctx->key, 0, cryp->ctx->keylen); + } + + static int stm32_cryp_cpu_start(struct stm32_cryp *cryp) +@@ -801,7 +756,20 @@ static int stm32_cryp_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key, + static int stm32_cryp_aes_gcm_setauthsize(struct crypto_aead *tfm, + unsigned int authsize) + { +- return authsize == AES_BLOCK_SIZE ? 0 : -EINVAL; ++ switch (authsize) { ++ case 4: ++ case 8: ++ case 12: ++ case 13: ++ case 14: ++ case 15: ++ case 16: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; + } + + static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, +@@ -825,31 +793,61 @@ static int stm32_cryp_aes_ccm_setauthsize(struct crypto_aead *tfm, + + static int stm32_cryp_aes_ecb_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % AES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_AES | FLG_ECB | FLG_ENCRYPT); + } + + static int stm32_cryp_aes_ecb_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % AES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_AES | FLG_ECB); + } + + static int stm32_cryp_aes_cbc_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % AES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_AES | FLG_CBC | FLG_ENCRYPT); + } + + static int stm32_cryp_aes_cbc_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % AES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_AES | FLG_CBC); + } + + static int stm32_cryp_aes_ctr_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_AES | FLG_CTR | FLG_ENCRYPT); + } + + static int stm32_cryp_aes_ctr_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_AES | FLG_CTR); + } + +@@ -863,53 +861,122 @@ static int stm32_cryp_aes_gcm_decrypt(struct aead_request *req) + return stm32_cryp_aead_crypt(req, FLG_AES | FLG_GCM); + } + ++static inline int crypto_ccm_check_iv(const u8 *iv) ++{ ++ /* 2 <= L <= 8, so 1 <= L' <= 7. */ ++ if (iv[0] < 1 || iv[0] > 7) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static int stm32_cryp_aes_ccm_encrypt(struct aead_request *req) + { ++ int err; ++ ++ err = crypto_ccm_check_iv(req->iv); ++ if (err) ++ return err; ++ + return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM | FLG_ENCRYPT); + } + + static int stm32_cryp_aes_ccm_decrypt(struct aead_request *req) + { ++ int err; ++ ++ err = crypto_ccm_check_iv(req->iv); ++ if (err) ++ return err; ++ + return stm32_cryp_aead_crypt(req, FLG_AES | FLG_CCM); + } + + static int stm32_cryp_des_ecb_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_DES | FLG_ECB | FLG_ENCRYPT); + } + + static int stm32_cryp_des_ecb_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_DES | FLG_ECB); + } + + static int stm32_cryp_des_cbc_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_DES | FLG_CBC | FLG_ENCRYPT); + } + + static int stm32_cryp_des_cbc_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_DES | FLG_CBC); + } + + static int stm32_cryp_tdes_ecb_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB | FLG_ENCRYPT); + } + + static int stm32_cryp_tdes_ecb_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_TDES | FLG_ECB); + } + + static int stm32_cryp_tdes_cbc_encrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC | FLG_ENCRYPT); + } + + static int stm32_cryp_tdes_cbc_decrypt(struct skcipher_request *req) + { ++ if (req->cryptlen % DES_BLOCK_SIZE) ++ return -EINVAL; ++ ++ if (req->cryptlen == 0) ++ return 0; ++ + return stm32_cryp_crypt(req, FLG_TDES | FLG_CBC); + } + +@@ -919,6 +986,7 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, + struct stm32_cryp_ctx *ctx; + struct stm32_cryp *cryp; + struct stm32_cryp_reqctx *rctx; ++ struct scatterlist *in_sg; + int ret; + + if (!req && !areq) +@@ -944,76 +1012,55 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, + if (req) { + cryp->req = req; + cryp->areq = NULL; +- cryp->total_in = req->cryptlen; +- cryp->total_out = cryp->total_in; ++ cryp->header_in = 0; ++ cryp->payload_in = req->cryptlen; ++ cryp->payload_out = req->cryptlen; ++ cryp->authsize = 0; + } else { + /* + * Length of input and output data: + * Encryption case: +- * INPUT = AssocData || PlainText ++ * INPUT = AssocData || PlainText + * <- assoclen -> <- cryptlen -> +- * <------- total_in -----------> + * +- * OUTPUT = AssocData || CipherText || AuthTag +- * <- assoclen -> <- cryptlen -> <- authsize -> +- * <---------------- total_out -----------------> ++ * OUTPUT = AssocData || CipherText || AuthTag ++ * <- assoclen -> <-- cryptlen --> <- authsize -> + * + * Decryption case: +- * INPUT = AssocData || CipherText || AuthTag +- * <- assoclen -> <--------- cryptlen ---------> +- * <- authsize -> +- * <---------------- total_in ------------------> ++ * INPUT = AssocData || CipherTex || AuthTag ++ * <- assoclen ---> <---------- cryptlen ----------> + * +- * OUTPUT = AssocData || PlainText +- * <- assoclen -> <- crypten - authsize -> +- * <---------- total_out -----------------> ++ * OUTPUT = AssocData || PlainText ++ * <- assoclen -> <- cryptlen - authsize -> + */ + cryp->areq = areq; + cryp->req = NULL; + cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq)); +- cryp->total_in = areq->assoclen + areq->cryptlen; +- if (is_encrypt(cryp)) +- /* Append auth tag to output */ +- cryp->total_out = cryp->total_in + cryp->authsize; +- else +- /* No auth tag in output */ +- cryp->total_out = cryp->total_in - cryp->authsize; ++ if (is_encrypt(cryp)) { ++ cryp->payload_in = areq->cryptlen; ++ cryp->header_in = areq->assoclen; ++ cryp->payload_out = areq->cryptlen; ++ } else { ++ cryp->payload_in = areq->cryptlen - cryp->authsize; ++ cryp->header_in = areq->assoclen; ++ cryp->payload_out = cryp->payload_in; ++ } + } + +- cryp->total_in_save = cryp->total_in; +- cryp->total_out_save = cryp->total_out; ++ in_sg = req ? req->src : areq->src; ++ scatterwalk_start(&cryp->in_walk, in_sg); + +- cryp->in_sg = req ? req->src : areq->src; + cryp->out_sg = req ? req->dst : areq->dst; +- cryp->out_sg_save = cryp->out_sg; +- +- cryp->in_sg_len = sg_nents_for_len(cryp->in_sg, cryp->total_in); +- if (cryp->in_sg_len < 0) { +- dev_err(cryp->dev, "Cannot get in_sg_len\n"); +- ret = cryp->in_sg_len; +- return ret; +- } +- +- cryp->out_sg_len = sg_nents_for_len(cryp->out_sg, cryp->total_out); +- if (cryp->out_sg_len < 0) { +- dev_err(cryp->dev, "Cannot get out_sg_len\n"); +- ret = cryp->out_sg_len; +- return ret; +- } +- +- ret = stm32_cryp_copy_sgs(cryp); +- if (ret) +- return ret; +- +- scatterwalk_start(&cryp->in_walk, cryp->in_sg); + scatterwalk_start(&cryp->out_walk, cryp->out_sg); + + if (is_gcm(cryp) || is_ccm(cryp)) { + /* In output, jump after assoc data */ +- scatterwalk_advance(&cryp->out_walk, cryp->areq->assoclen); +- cryp->total_out -= cryp->areq->assoclen; ++ scatterwalk_copychunks(NULL, &cryp->out_walk, cryp->areq->assoclen, 2); + } + ++ if (is_ctr(cryp)) ++ memset(cryp->last_ctr, 0, sizeof(cryp->last_ctr)); ++ + ret = stm32_cryp_hw_init(cryp); + return ret; + } +@@ -1061,8 +1108,7 @@ static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq) + if (!cryp) + return -ENODEV; + +- if (unlikely(!cryp->areq->assoclen && +- !stm32_cryp_get_input_text_len(cryp))) { ++ if (unlikely(!cryp->payload_in && !cryp->header_in)) { + /* No input data to process: get tag and finish */ + stm32_cryp_finish_req(cryp, 0); + return 0; +@@ -1071,43 +1117,10 @@ static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq) + return stm32_cryp_cpu_start(cryp); + } + +-static u32 *stm32_cryp_next_out(struct stm32_cryp *cryp, u32 *dst, +- unsigned int n) +-{ +- scatterwalk_advance(&cryp->out_walk, n); +- +- if (unlikely(cryp->out_sg->length == _walked_out)) { +- cryp->out_sg = sg_next(cryp->out_sg); +- if (cryp->out_sg) { +- scatterwalk_start(&cryp->out_walk, cryp->out_sg); +- return (sg_virt(cryp->out_sg) + _walked_out); +- } +- } +- +- return (u32 *)((u8 *)dst + n); +-} +- +-static u32 *stm32_cryp_next_in(struct stm32_cryp *cryp, u32 *src, +- unsigned int n) +-{ +- scatterwalk_advance(&cryp->in_walk, n); +- +- if (unlikely(cryp->in_sg->length == _walked_in)) { +- cryp->in_sg = sg_next(cryp->in_sg); +- if (cryp->in_sg) { +- scatterwalk_start(&cryp->in_walk, cryp->in_sg); +- return (sg_virt(cryp->in_sg) + _walked_in); +- } +- } +- +- return (u32 *)((u8 *)src + n); +-} +- + static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) + { +- u32 cfg, size_bit, *dst, d32; +- u8 *d8; +- unsigned int i, j; ++ u32 cfg, size_bit; ++ unsigned int i; + int ret = 0; + + /* Update Config */ +@@ -1130,7 +1143,7 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) + stm32_cryp_write(cryp, CRYP_DIN, size_bit); + + size_bit = is_encrypt(cryp) ? cryp->areq->cryptlen : +- cryp->areq->cryptlen - AES_BLOCK_SIZE; ++ cryp->areq->cryptlen - cryp->authsize; + size_bit *= 8; + if (cryp->caps->swap_final) + size_bit = (__force u32)cpu_to_be32(size_bit); +@@ -1139,11 +1152,9 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) + stm32_cryp_write(cryp, CRYP_DIN, size_bit); + } else { + /* CCM: write CTR0 */ +- u8 iv[AES_BLOCK_SIZE]; +- u32 *iv32 = (u32 *)iv; +- __be32 *biv; +- +- biv = (void *)iv; ++ u32 iv32[AES_BLOCK_32]; ++ u8 *iv = (u8 *)iv32; ++ __be32 *biv = (__be32 *)iv32; + + memcpy(iv, cryp->areq->iv, AES_BLOCK_SIZE); + memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1); +@@ -1165,39 +1176,18 @@ static int stm32_cryp_read_auth_tag(struct stm32_cryp *cryp) + } + + if (is_encrypt(cryp)) { ++ u32 out_tag[AES_BLOCK_32]; ++ + /* Get and write tag */ +- dst = sg_virt(cryp->out_sg) + _walked_out; ++ for (i = 0; i < AES_BLOCK_32; i++) ++ out_tag[i] = stm32_cryp_read(cryp, CRYP_DOUT); + +- for (i = 0; i < AES_BLOCK_32; i++) { +- if (cryp->total_out >= sizeof(u32)) { +- /* Read a full u32 */ +- *dst = stm32_cryp_read(cryp, CRYP_DOUT); +- +- dst = stm32_cryp_next_out(cryp, dst, +- sizeof(u32)); +- cryp->total_out -= sizeof(u32); +- } else if (!cryp->total_out) { +- /* Empty fifo out (data from input padding) */ +- stm32_cryp_read(cryp, CRYP_DOUT); +- } else { +- /* Read less than an u32 */ +- d32 = stm32_cryp_read(cryp, CRYP_DOUT); +- d8 = (u8 *)&d32; +- +- for (j = 0; j < cryp->total_out; j++) { +- *((u8 *)dst) = *(d8++); +- dst = stm32_cryp_next_out(cryp, dst, 1); +- } +- cryp->total_out = 0; +- } +- } ++ scatterwalk_copychunks(out_tag, &cryp->out_walk, cryp->authsize, 1); + } else { + /* Get and check tag */ + u32 in_tag[AES_BLOCK_32], out_tag[AES_BLOCK_32]; + +- scatterwalk_map_and_copy(in_tag, cryp->in_sg, +- cryp->total_in_save - cryp->authsize, +- cryp->authsize, 0); ++ scatterwalk_copychunks(in_tag, &cryp->in_walk, cryp->authsize, 0); + + for (i = 0; i < AES_BLOCK_32; i++) + out_tag[i] = stm32_cryp_read(cryp, CRYP_DOUT); +@@ -1217,115 +1207,59 @@ static void stm32_cryp_check_ctr_counter(struct stm32_cryp *cryp) + { + u32 cr; + +- if (unlikely(cryp->last_ctr[3] == 0xFFFFFFFF)) { +- cryp->last_ctr[3] = 0; +- cryp->last_ctr[2]++; +- if (!cryp->last_ctr[2]) { +- cryp->last_ctr[1]++; +- if (!cryp->last_ctr[1]) +- cryp->last_ctr[0]++; +- } ++ if (unlikely(cryp->last_ctr[3] == cpu_to_be32(0xFFFFFFFF))) { ++ /* ++ * In this case, we need to increment manually the ctr counter, ++ * as HW doesn't handle the U32 carry. ++ */ ++ crypto_inc((u8 *)cryp->last_ctr, sizeof(cryp->last_ctr)); + + cr = stm32_cryp_read(cryp, CRYP_CR); + stm32_cryp_write(cryp, CRYP_CR, cr & ~CR_CRYPEN); + +- stm32_cryp_hw_write_iv(cryp, (__be32 *)cryp->last_ctr); ++ stm32_cryp_hw_write_iv(cryp, cryp->last_ctr); + + stm32_cryp_write(cryp, CRYP_CR, cr); + } + +- cryp->last_ctr[0] = stm32_cryp_read(cryp, CRYP_IV0LR); +- cryp->last_ctr[1] = stm32_cryp_read(cryp, CRYP_IV0RR); +- cryp->last_ctr[2] = stm32_cryp_read(cryp, CRYP_IV1LR); +- cryp->last_ctr[3] = stm32_cryp_read(cryp, CRYP_IV1RR); ++ /* The IV registers are BE */ ++ cryp->last_ctr[0] = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV0LR)); ++ cryp->last_ctr[1] = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV0RR)); ++ cryp->last_ctr[2] = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV1LR)); ++ cryp->last_ctr[3] = cpu_to_be32(stm32_cryp_read(cryp, CRYP_IV1RR)); + } + +-static bool stm32_cryp_irq_read_data(struct stm32_cryp *cryp) ++static void stm32_cryp_irq_read_data(struct stm32_cryp *cryp) + { +- unsigned int i, j; +- u32 d32, *dst; +- u8 *d8; +- size_t tag_size; +- +- /* Do no read tag now (if any) */ +- if (is_encrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp))) +- tag_size = cryp->authsize; +- else +- tag_size = 0; +- +- dst = sg_virt(cryp->out_sg) + _walked_out; ++ unsigned int i; ++ u32 block[AES_BLOCK_32]; + +- for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { +- if (likely(cryp->total_out - tag_size >= sizeof(u32))) { +- /* Read a full u32 */ +- *dst = stm32_cryp_read(cryp, CRYP_DOUT); ++ for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) ++ block[i] = stm32_cryp_read(cryp, CRYP_DOUT); + +- dst = stm32_cryp_next_out(cryp, dst, sizeof(u32)); +- cryp->total_out -= sizeof(u32); +- } else if (cryp->total_out == tag_size) { +- /* Empty fifo out (data from input padding) */ +- d32 = stm32_cryp_read(cryp, CRYP_DOUT); +- } else { +- /* Read less than an u32 */ +- d32 = stm32_cryp_read(cryp, CRYP_DOUT); +- d8 = (u8 *)&d32; +- +- for (j = 0; j < cryp->total_out - tag_size; j++) { +- *((u8 *)dst) = *(d8++); +- dst = stm32_cryp_next_out(cryp, dst, 1); +- } +- cryp->total_out = tag_size; +- } +- } +- +- return !(cryp->total_out - tag_size) || !cryp->total_in; ++ scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize, ++ cryp->payload_out), 1); ++ cryp->payload_out -= min_t(size_t, cryp->hw_blocksize, ++ cryp->payload_out); + } + + static void stm32_cryp_irq_write_block(struct stm32_cryp *cryp) + { +- unsigned int i, j; +- u32 *src; +- u8 d8[4]; +- size_t tag_size; +- +- /* Do no write tag (if any) */ +- if (is_decrypt(cryp) && (is_gcm(cryp) || is_ccm(cryp))) +- tag_size = cryp->authsize; +- else +- tag_size = 0; +- +- src = sg_virt(cryp->in_sg) + _walked_in; ++ unsigned int i; ++ u32 block[AES_BLOCK_32] = {0}; + +- for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) { +- if (likely(cryp->total_in - tag_size >= sizeof(u32))) { +- /* Write a full u32 */ +- stm32_cryp_write(cryp, CRYP_DIN, *src); ++ scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, cryp->hw_blocksize, ++ cryp->payload_in), 0); ++ for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) ++ stm32_cryp_write(cryp, CRYP_DIN, block[i]); + +- src = stm32_cryp_next_in(cryp, src, sizeof(u32)); +- cryp->total_in -= sizeof(u32); +- } else if (cryp->total_in == tag_size) { +- /* Write padding data */ +- stm32_cryp_write(cryp, CRYP_DIN, 0); +- } else { +- /* Write less than an u32 */ +- memset(d8, 0, sizeof(u32)); +- for (j = 0; j < cryp->total_in - tag_size; j++) { +- d8[j] = *((u8 *)src); +- src = stm32_cryp_next_in(cryp, src, 1); +- } +- +- stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); +- cryp->total_in = tag_size; +- } +- } ++ cryp->payload_in -= min_t(size_t, cryp->hw_blocksize, cryp->payload_in); + } + + static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) + { + int err; +- u32 cfg, tmp[AES_BLOCK_32]; +- size_t total_in_ori = cryp->total_in; +- struct scatterlist *out_sg_ori = cryp->out_sg; ++ u32 cfg, block[AES_BLOCK_32] = {0}; + unsigned int i; + + /* 'Special workaround' procedure described in the datasheet */ +@@ -1350,18 +1284,25 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) + + /* b) pad and write the last block */ + stm32_cryp_irq_write_block(cryp); +- cryp->total_in = total_in_ori; ++ /* wait end of process */ + err = stm32_cryp_wait_output(cryp); + if (err) { +- dev_err(cryp->dev, "Timeout (write gcm header)\n"); ++ dev_err(cryp->dev, "Timeout (write gcm last data)\n"); + return stm32_cryp_finish_req(cryp, err); + } + + /* c) get and store encrypted data */ +- stm32_cryp_irq_read_data(cryp); +- scatterwalk_map_and_copy(tmp, out_sg_ori, +- cryp->total_in_save - total_in_ori, +- total_in_ori, 0); ++ /* ++ * Same code as stm32_cryp_irq_read_data(), but we want to store ++ * block value ++ */ ++ for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) ++ block[i] = stm32_cryp_read(cryp, CRYP_DOUT); ++ ++ scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize, ++ cryp->payload_out), 1); ++ cryp->payload_out -= min_t(size_t, cryp->hw_blocksize, ++ cryp->payload_out); + + /* d) change mode back to AES GCM */ + cfg &= ~CR_ALGO_MASK; +@@ -1374,19 +1315,13 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) + stm32_cryp_write(cryp, CRYP_CR, cfg); + + /* f) write padded data */ +- for (i = 0; i < AES_BLOCK_32; i++) { +- if (cryp->total_in) +- stm32_cryp_write(cryp, CRYP_DIN, tmp[i]); +- else +- stm32_cryp_write(cryp, CRYP_DIN, 0); +- +- cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in); +- } ++ for (i = 0; i < AES_BLOCK_32; i++) ++ stm32_cryp_write(cryp, CRYP_DIN, block[i]); + + /* g) Empty fifo out */ + err = stm32_cryp_wait_output(cryp); + if (err) { +- dev_err(cryp->dev, "Timeout (write gcm header)\n"); ++ dev_err(cryp->dev, "Timeout (write gcm padded data)\n"); + return stm32_cryp_finish_req(cryp, err); + } + +@@ -1399,16 +1334,14 @@ static void stm32_cryp_irq_write_gcm_padded_data(struct stm32_cryp *cryp) + + static void stm32_cryp_irq_set_npblb(struct stm32_cryp *cryp) + { +- u32 cfg, payload_bytes; ++ u32 cfg; + + /* disable ip, set NPBLB and reneable ip */ + cfg = stm32_cryp_read(cryp, CRYP_CR); + cfg &= ~CR_CRYPEN; + stm32_cryp_write(cryp, CRYP_CR, cfg); + +- payload_bytes = is_decrypt(cryp) ? cryp->total_in - cryp->authsize : +- cryp->total_in; +- cfg |= (cryp->hw_blocksize - payload_bytes) << CR_NBPBL_SHIFT; ++ cfg |= (cryp->hw_blocksize - cryp->payload_in) << CR_NBPBL_SHIFT; + cfg |= CR_CRYPEN; + stm32_cryp_write(cryp, CRYP_CR, cfg); + } +@@ -1417,13 +1350,11 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) + { + int err = 0; + u32 cfg, iv1tmp; +- u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32], tmp[AES_BLOCK_32]; +- size_t last_total_out, total_in_ori = cryp->total_in; +- struct scatterlist *out_sg_ori = cryp->out_sg; ++ u32 cstmp1[AES_BLOCK_32], cstmp2[AES_BLOCK_32]; ++ u32 block[AES_BLOCK_32] = {0}; + unsigned int i; + + /* 'Special workaround' procedure described in the datasheet */ +- cryp->flags |= FLG_CCM_PADDED_WA; + + /* a) disable ip */ + stm32_cryp_write(cryp, CRYP_IMSCR, 0); +@@ -1453,7 +1384,7 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) + + /* b) pad and write the last block */ + stm32_cryp_irq_write_block(cryp); +- cryp->total_in = total_in_ori; ++ /* wait end of process */ + err = stm32_cryp_wait_output(cryp); + if (err) { + dev_err(cryp->dev, "Timeout (wite ccm padded data)\n"); +@@ -1461,13 +1392,16 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) + } + + /* c) get and store decrypted data */ +- last_total_out = cryp->total_out; +- stm32_cryp_irq_read_data(cryp); ++ /* ++ * Same code as stm32_cryp_irq_read_data(), but we want to store ++ * block value ++ */ ++ for (i = 0; i < cryp->hw_blocksize / sizeof(u32); i++) ++ block[i] = stm32_cryp_read(cryp, CRYP_DOUT); + +- memset(tmp, 0, sizeof(tmp)); +- scatterwalk_map_and_copy(tmp, out_sg_ori, +- cryp->total_out_save - last_total_out, +- last_total_out, 0); ++ scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, cryp->hw_blocksize, ++ cryp->payload_out), 1); ++ cryp->payload_out -= min_t(size_t, cryp->hw_blocksize, cryp->payload_out); + + /* d) Load again CRYP_CSGCMCCMxR */ + for (i = 0; i < ARRAY_SIZE(cstmp2); i++) +@@ -1484,10 +1418,10 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) + stm32_cryp_write(cryp, CRYP_CR, cfg); + + /* g) XOR and write padded data */ +- for (i = 0; i < ARRAY_SIZE(tmp); i++) { +- tmp[i] ^= cstmp1[i]; +- tmp[i] ^= cstmp2[i]; +- stm32_cryp_write(cryp, CRYP_DIN, tmp[i]); ++ for (i = 0; i < ARRAY_SIZE(block); i++) { ++ block[i] ^= cstmp1[i]; ++ block[i] ^= cstmp2[i]; ++ stm32_cryp_write(cryp, CRYP_DIN, block[i]); + } + + /* h) wait for completion */ +@@ -1501,30 +1435,34 @@ static void stm32_cryp_irq_write_ccm_padded_data(struct stm32_cryp *cryp) + + static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp) + { +- if (unlikely(!cryp->total_in)) { ++ if (unlikely(!cryp->payload_in)) { + dev_warn(cryp->dev, "No more data to process\n"); + return; + } + +- if (unlikely(cryp->total_in < AES_BLOCK_SIZE && ++ if (unlikely(cryp->payload_in < AES_BLOCK_SIZE && + (stm32_cryp_get_hw_mode(cryp) == CR_AES_GCM) && + is_encrypt(cryp))) { + /* Padding for AES GCM encryption */ +- if (cryp->caps->padding_wa) ++ if (cryp->caps->padding_wa) { + /* Special case 1 */ +- return stm32_cryp_irq_write_gcm_padded_data(cryp); ++ stm32_cryp_irq_write_gcm_padded_data(cryp); ++ return; ++ } + + /* Setting padding bytes (NBBLB) */ + stm32_cryp_irq_set_npblb(cryp); + } + +- if (unlikely((cryp->total_in - cryp->authsize < AES_BLOCK_SIZE) && ++ if (unlikely((cryp->payload_in < AES_BLOCK_SIZE) && + (stm32_cryp_get_hw_mode(cryp) == CR_AES_CCM) && + is_decrypt(cryp))) { + /* Padding for AES CCM decryption */ +- if (cryp->caps->padding_wa) ++ if (cryp->caps->padding_wa) { + /* Special case 2 */ +- return stm32_cryp_irq_write_ccm_padded_data(cryp); ++ stm32_cryp_irq_write_ccm_padded_data(cryp); ++ return; ++ } + + /* Setting padding bytes (NBBLB) */ + stm32_cryp_irq_set_npblb(cryp); +@@ -1536,192 +1474,60 @@ static void stm32_cryp_irq_write_data(struct stm32_cryp *cryp) + stm32_cryp_irq_write_block(cryp); + } + +-static void stm32_cryp_irq_write_gcm_header(struct stm32_cryp *cryp) ++static void stm32_cryp_irq_write_gcmccm_header(struct stm32_cryp *cryp) + { +- int err; +- unsigned int i, j; +- u32 cfg, *src; +- +- src = sg_virt(cryp->in_sg) + _walked_in; +- +- for (i = 0; i < AES_BLOCK_32; i++) { +- stm32_cryp_write(cryp, CRYP_DIN, *src); +- +- src = stm32_cryp_next_in(cryp, src, sizeof(u32)); +- cryp->total_in -= min_t(size_t, sizeof(u32), cryp->total_in); +- +- /* Check if whole header written */ +- if ((cryp->total_in_save - cryp->total_in) == +- cryp->areq->assoclen) { +- /* Write padding if needed */ +- for (j = i + 1; j < AES_BLOCK_32; j++) +- stm32_cryp_write(cryp, CRYP_DIN, 0); +- +- /* Wait for completion */ +- err = stm32_cryp_wait_busy(cryp); +- if (err) { +- dev_err(cryp->dev, "Timeout (gcm header)\n"); +- return stm32_cryp_finish_req(cryp, err); +- } +- +- if (stm32_cryp_get_input_text_len(cryp)) { +- /* Phase 3 : payload */ +- cfg = stm32_cryp_read(cryp, CRYP_CR); +- cfg &= ~CR_CRYPEN; +- stm32_cryp_write(cryp, CRYP_CR, cfg); +- +- cfg &= ~CR_PH_MASK; +- cfg |= CR_PH_PAYLOAD; +- cfg |= CR_CRYPEN; +- stm32_cryp_write(cryp, CRYP_CR, cfg); +- } else { +- /* Phase 4 : tag */ +- stm32_cryp_write(cryp, CRYP_IMSCR, 0); +- stm32_cryp_finish_req(cryp, 0); +- } +- +- break; +- } +- +- if (!cryp->total_in) +- break; +- } +-} ++ unsigned int i; ++ u32 block[AES_BLOCK_32] = {0}; ++ size_t written; + +-static void stm32_cryp_irq_write_ccm_header(struct stm32_cryp *cryp) +-{ +- int err; +- unsigned int i = 0, j, k; +- u32 alen, cfg, *src; +- u8 d8[4]; +- +- src = sg_virt(cryp->in_sg) + _walked_in; +- alen = cryp->areq->assoclen; +- +- if (!_walked_in) { +- if (cryp->areq->assoclen <= 65280) { +- /* Write first u32 of B1 */ +- d8[0] = (alen >> 8) & 0xFF; +- d8[1] = alen & 0xFF; +- d8[2] = *((u8 *)src); +- src = stm32_cryp_next_in(cryp, src, 1); +- d8[3] = *((u8 *)src); +- src = stm32_cryp_next_in(cryp, src, 1); +- +- stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); +- i++; +- +- cryp->total_in -= min_t(size_t, 2, cryp->total_in); +- } else { +- /* Build the two first u32 of B1 */ +- d8[0] = 0xFF; +- d8[1] = 0xFE; +- d8[2] = alen & 0xFF000000; +- d8[3] = alen & 0x00FF0000; +- +- stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); +- i++; +- +- d8[0] = alen & 0x0000FF00; +- d8[1] = alen & 0x000000FF; +- d8[2] = *((u8 *)src); +- src = stm32_cryp_next_in(cryp, src, 1); +- d8[3] = *((u8 *)src); +- src = stm32_cryp_next_in(cryp, src, 1); +- +- stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); +- i++; +- +- cryp->total_in -= min_t(size_t, 2, cryp->total_in); +- } +- } ++ written = min_t(size_t, AES_BLOCK_SIZE, cryp->header_in); + +- /* Write next u32 */ +- for (; i < AES_BLOCK_32; i++) { +- /* Build an u32 */ +- memset(d8, 0, sizeof(u32)); +- for (k = 0; k < sizeof(u32); k++) { +- d8[k] = *((u8 *)src); +- src = stm32_cryp_next_in(cryp, src, 1); +- +- cryp->total_in -= min_t(size_t, 1, cryp->total_in); +- if ((cryp->total_in_save - cryp->total_in) == alen) +- break; +- } ++ scatterwalk_copychunks(block, &cryp->in_walk, written, 0); ++ for (i = 0; i < AES_BLOCK_32; i++) ++ stm32_cryp_write(cryp, CRYP_DIN, block[i]); + +- stm32_cryp_write(cryp, CRYP_DIN, *(u32 *)d8); +- +- if ((cryp->total_in_save - cryp->total_in) == alen) { +- /* Write padding if needed */ +- for (j = i + 1; j < AES_BLOCK_32; j++) +- stm32_cryp_write(cryp, CRYP_DIN, 0); +- +- /* Wait for completion */ +- err = stm32_cryp_wait_busy(cryp); +- if (err) { +- dev_err(cryp->dev, "Timeout (ccm header)\n"); +- return stm32_cryp_finish_req(cryp, err); +- } +- +- if (stm32_cryp_get_input_text_len(cryp)) { +- /* Phase 3 : payload */ +- cfg = stm32_cryp_read(cryp, CRYP_CR); +- cfg &= ~CR_CRYPEN; +- stm32_cryp_write(cryp, CRYP_CR, cfg); +- +- cfg &= ~CR_PH_MASK; +- cfg |= CR_PH_PAYLOAD; +- cfg |= CR_CRYPEN; +- stm32_cryp_write(cryp, CRYP_CR, cfg); +- } else { +- /* Phase 4 : tag */ +- stm32_cryp_write(cryp, CRYP_IMSCR, 0); +- stm32_cryp_finish_req(cryp, 0); +- } ++ cryp->header_in -= written; + +- break; +- } +- } ++ stm32_crypt_gcmccm_end_header(cryp); + } + + static irqreturn_t stm32_cryp_irq_thread(int irq, void *arg) + { + struct stm32_cryp *cryp = arg; + u32 ph; ++ u32 it_mask = stm32_cryp_read(cryp, CRYP_IMSCR); + + if (cryp->irq_status & MISR_OUT) + /* Output FIFO IRQ: read data */ +- if (unlikely(stm32_cryp_irq_read_data(cryp))) { +- /* All bytes processed, finish */ +- stm32_cryp_write(cryp, CRYP_IMSCR, 0); +- stm32_cryp_finish_req(cryp, 0); +- return IRQ_HANDLED; +- } ++ stm32_cryp_irq_read_data(cryp); + + if (cryp->irq_status & MISR_IN) { +- if (is_gcm(cryp)) { ++ if (is_gcm(cryp) || is_ccm(cryp)) { + ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK; + if (unlikely(ph == CR_PH_HEADER)) + /* Write Header */ +- stm32_cryp_irq_write_gcm_header(cryp); +- else +- /* Input FIFO IRQ: write data */ +- stm32_cryp_irq_write_data(cryp); +- cryp->gcm_ctr++; +- } else if (is_ccm(cryp)) { +- ph = stm32_cryp_read(cryp, CRYP_CR) & CR_PH_MASK; +- if (unlikely(ph == CR_PH_HEADER)) +- /* Write Header */ +- stm32_cryp_irq_write_ccm_header(cryp); ++ stm32_cryp_irq_write_gcmccm_header(cryp); + else + /* Input FIFO IRQ: write data */ + stm32_cryp_irq_write_data(cryp); ++ if (is_gcm(cryp)) ++ cryp->gcm_ctr++; + } else { + /* Input FIFO IRQ: write data */ + stm32_cryp_irq_write_data(cryp); + } + } + ++ /* Mask useless interrupts */ ++ if (!cryp->payload_in && !cryp->header_in) ++ it_mask &= ~IMSCR_IN; ++ if (!cryp->payload_out) ++ it_mask &= ~IMSCR_OUT; ++ stm32_cryp_write(cryp, CRYP_IMSCR, it_mask); ++ ++ if (!cryp->payload_in && !cryp->header_in && !cryp->payload_out) ++ stm32_cryp_finish_req(cryp, 0); ++ + return IRQ_HANDLED; + } + +@@ -1742,7 +1548,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1759,7 +1565,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1777,7 +1583,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1795,7 +1601,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1812,7 +1618,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1830,7 +1636,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1847,7 +1653,7 @@ static struct skcipher_alg crypto_algs[] = { + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .base.cra_alignmask = 0xf, ++ .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, +@@ -1877,7 +1683,7 @@ static struct aead_alg aead_algs[] = { + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .cra_alignmask = 0xf, ++ .cra_alignmask = 0, + .cra_module = THIS_MODULE, + }, + }, +@@ -1897,7 +1703,7 @@ static struct aead_alg aead_algs[] = { + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct stm32_cryp_ctx), +- .cra_alignmask = 0xf, ++ .cra_alignmask = 0, + .cra_module = THIS_MODULE, + }, + }, +@@ -2025,8 +1831,6 @@ err_engine1: + list_del(&cryp->list); + spin_unlock(&cryp_list.lock); + +- pm_runtime_disable(dev); +- pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + +diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c +index 389de9e3302d5..d33006d43f761 100644 +--- a/drivers/crypto/stm32/stm32-hash.c ++++ b/drivers/crypto/stm32/stm32-hash.c +@@ -813,7 +813,7 @@ static void stm32_hash_finish_req(struct ahash_request *req, int err) + static int stm32_hash_hw_init(struct stm32_hash_dev *hdev, + struct stm32_hash_request_ctx *rctx) + { +- pm_runtime_resume_and_get(hdev->dev); ++ pm_runtime_get_sync(hdev->dev); + + if (!(HASH_FLAGS_INIT & hdev->flags)) { + stm32_hash_write(hdev, HASH_CR, HASH_CR_INIT); +@@ -962,7 +962,7 @@ static int stm32_hash_export(struct ahash_request *req, void *out) + u32 *preg; + unsigned int i; + +- pm_runtime_resume_and_get(hdev->dev); ++ pm_runtime_get_sync(hdev->dev); + + while ((stm32_hash_read(hdev, HASH_SR) & HASH_SR_BUSY)) + cpu_relax(); +@@ -1000,7 +1000,7 @@ static int stm32_hash_import(struct ahash_request *req, const void *in) + + preg = rctx->hw_context; + +- pm_runtime_resume_and_get(hdev->dev); ++ pm_runtime_get_sync(hdev->dev); + + stm32_hash_write(hdev, HASH_IMR, *preg++); + stm32_hash_write(hdev, HASH_STR, *preg++); +diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c +index 8e45aa07d662f..5444b5a7fd3c4 100644 +--- a/drivers/cxl/pci.c ++++ b/drivers/cxl/pci.c +@@ -972,7 +972,7 @@ static void __iomem *cxl_mem_map_regblock(struct cxl_mem *cxlm, + if (pci_resource_len(pdev, bar) < offset) { + dev_err(dev, "BAR%d: %pr: too small (offset: %#llx)\n", bar, + &pdev->resource[bar], (unsigned long long)offset); +- return IOMEM_ERR_PTR(-ENXIO); ++ return NULL; + } + + addr = pci_iomap(pdev, bar, 0); +diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c +index 9652c3ee41e7f..2bb2f9a0499f7 100644 +--- a/drivers/cxl/pmem.c ++++ b/drivers/cxl/pmem.c +@@ -149,14 +149,24 @@ static void cxl_nvb_update_state(struct work_struct *work) + put_device(&cxl_nvb->dev); + } + ++static void cxl_nvdimm_bridge_state_work(struct cxl_nvdimm_bridge *cxl_nvb) ++{ ++ /* ++ * Take a reference that the workqueue will drop if new work ++ * gets queued. ++ */ ++ get_device(&cxl_nvb->dev); ++ if (!queue_work(cxl_pmem_wq, &cxl_nvb->state_work)) ++ put_device(&cxl_nvb->dev); ++} ++ + static void cxl_nvdimm_bridge_remove(struct device *dev) + { + struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev); + + if (cxl_nvb->state == CXL_NVB_ONLINE) + cxl_nvb->state = CXL_NVB_OFFLINE; +- if (queue_work(cxl_pmem_wq, &cxl_nvb->state_work)) +- get_device(&cxl_nvb->dev); ++ cxl_nvdimm_bridge_state_work(cxl_nvb); + } + + static int cxl_nvdimm_bridge_probe(struct device *dev) +@@ -177,8 +187,7 @@ static int cxl_nvdimm_bridge_probe(struct device *dev) + } + + cxl_nvb->state = CXL_NVB_ONLINE; +- if (queue_work(cxl_pmem_wq, &cxl_nvb->state_work)) +- get_device(&cxl_nvb->dev); ++ cxl_nvdimm_bridge_state_work(cxl_nvb); + + return 0; + } +diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c +index 63d32261b63ff..61e20ae7b08b7 100644 +--- a/drivers/dma-buf/dma-buf.c ++++ b/drivers/dma-buf/dma-buf.c +@@ -74,7 +74,7 @@ static void dma_buf_release(struct dentry *dentry) + * If you hit this BUG() it means someone dropped their ref to the + * dma-buf while still having pending operation to the buffer. + */ +- BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active); ++ BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active); + + dma_buf_stats_teardown(dmabuf); + dmabuf->ops->release(dmabuf); +@@ -82,6 +82,7 @@ static void dma_buf_release(struct dentry *dentry) + if (dmabuf->resv == (struct dma_resv *)&dmabuf[1]) + dma_resv_fini(dmabuf->resv); + ++ WARN_ON(!list_empty(&dmabuf->attachments)); + module_put(dmabuf->owner); + kfree(dmabuf->name); + kfree(dmabuf); +@@ -205,16 +206,55 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb) + wake_up_locked_poll(dcb->poll, dcb->active); + dcb->active = 0; + spin_unlock_irqrestore(&dcb->poll->lock, flags); ++ dma_fence_put(fence); ++} ++ ++static bool dma_buf_poll_shared(struct dma_resv *resv, ++ struct dma_buf_poll_cb_t *dcb) ++{ ++ struct dma_resv_list *fobj = dma_resv_shared_list(resv); ++ struct dma_fence *fence; ++ int i, r; ++ ++ if (!fobj) ++ return false; ++ ++ for (i = 0; i < fobj->shared_count; ++i) { ++ fence = rcu_dereference_protected(fobj->shared[i], ++ dma_resv_held(resv)); ++ dma_fence_get(fence); ++ r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb); ++ if (!r) ++ return true; ++ dma_fence_put(fence); ++ } ++ ++ return false; ++} ++ ++static bool dma_buf_poll_excl(struct dma_resv *resv, ++ struct dma_buf_poll_cb_t *dcb) ++{ ++ struct dma_fence *fence = dma_resv_excl_fence(resv); ++ int r; ++ ++ if (!fence) ++ return false; ++ ++ dma_fence_get(fence); ++ r = dma_fence_add_callback(fence, &dcb->cb, dma_buf_poll_cb); ++ if (!r) ++ return true; ++ dma_fence_put(fence); ++ ++ return false; + } + + static __poll_t dma_buf_poll(struct file *file, poll_table *poll) + { + struct dma_buf *dmabuf; + struct dma_resv *resv; +- struct dma_resv_list *fobj; +- struct dma_fence *fence_excl; + __poll_t events; +- unsigned shared_count, seq; + + dmabuf = file->private_data; + if (!dmabuf || !dmabuf->resv) +@@ -228,101 +268,50 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) + if (!events) + return 0; + +-retry: +- seq = read_seqcount_begin(&resv->seq); +- rcu_read_lock(); +- +- fobj = rcu_dereference(resv->fence); +- if (fobj) +- shared_count = fobj->shared_count; +- else +- shared_count = 0; +- fence_excl = dma_resv_excl_fence(resv); +- if (read_seqcount_retry(&resv->seq, seq)) { +- rcu_read_unlock(); +- goto retry; +- } +- +- if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) { +- struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl; +- __poll_t pevents = EPOLLIN; ++ dma_resv_lock(resv, NULL); + +- if (shared_count == 0) +- pevents |= EPOLLOUT; ++ if (events & EPOLLOUT) { ++ struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_out; + ++ /* Check that callback isn't busy */ + spin_lock_irq(&dmabuf->poll.lock); +- if (dcb->active) { +- dcb->active |= pevents; +- events &= ~pevents; +- } else +- dcb->active = pevents; ++ if (dcb->active) ++ events &= ~EPOLLOUT; ++ else ++ dcb->active = EPOLLOUT; + spin_unlock_irq(&dmabuf->poll.lock); + +- if (events & pevents) { +- if (!dma_fence_get_rcu(fence_excl)) { +- /* force a recheck */ +- events &= ~pevents; +- dma_buf_poll_cb(NULL, &dcb->cb); +- } else if (!dma_fence_add_callback(fence_excl, &dcb->cb, +- dma_buf_poll_cb)) { +- events &= ~pevents; +- dma_fence_put(fence_excl); +- } else { +- /* +- * No callback queued, wake up any additional +- * waiters. +- */ +- dma_fence_put(fence_excl); ++ if (events & EPOLLOUT) { ++ if (!dma_buf_poll_shared(resv, dcb) && ++ !dma_buf_poll_excl(resv, dcb)) ++ /* No callback queued, wake up any other waiters */ + dma_buf_poll_cb(NULL, &dcb->cb); +- } ++ else ++ events &= ~EPOLLOUT; + } + } + +- if ((events & EPOLLOUT) && shared_count > 0) { +- struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared; +- int i; ++ if (events & EPOLLIN) { ++ struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_in; + +- /* Only queue a new callback if no event has fired yet */ ++ /* Check that callback isn't busy */ + spin_lock_irq(&dmabuf->poll.lock); + if (dcb->active) +- events &= ~EPOLLOUT; ++ events &= ~EPOLLIN; + else +- dcb->active = EPOLLOUT; ++ dcb->active = EPOLLIN; + spin_unlock_irq(&dmabuf->poll.lock); + +- if (!(events & EPOLLOUT)) +- goto out; +- +- for (i = 0; i < shared_count; ++i) { +- struct dma_fence *fence = rcu_dereference(fobj->shared[i]); +- +- if (!dma_fence_get_rcu(fence)) { +- /* +- * fence refcount dropped to zero, this means +- * that fobj has been freed +- * +- * call dma_buf_poll_cb and force a recheck! +- */ +- events &= ~EPOLLOUT; ++ if (events & EPOLLIN) { ++ if (!dma_buf_poll_excl(resv, dcb)) ++ /* No callback queued, wake up any other waiters */ + dma_buf_poll_cb(NULL, &dcb->cb); +- break; +- } +- if (!dma_fence_add_callback(fence, &dcb->cb, +- dma_buf_poll_cb)) { +- dma_fence_put(fence); +- events &= ~EPOLLOUT; +- break; +- } +- dma_fence_put(fence); ++ else ++ events &= ~EPOLLIN; + } +- +- /* No callback queued, wake up any additional waiters. */ +- if (i == shared_count) +- dma_buf_poll_cb(NULL, &dcb->cb); + } + +-out: +- rcu_read_unlock(); ++ dma_resv_unlock(resv); + return events; + } + +@@ -565,8 +554,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) + dmabuf->owner = exp_info->owner; + spin_lock_init(&dmabuf->name_lock); + init_waitqueue_head(&dmabuf->poll); +- dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll; +- dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0; ++ dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll; ++ dmabuf->cb_in.active = dmabuf->cb_out.active = 0; + + if (!resv) { + resv = (struct dma_resv *)&dmabuf[1]; +diff --git a/drivers/dma-buf/dma-fence-array.c b/drivers/dma-buf/dma-fence-array.c +index d3fbd950be944..3e07f961e2f3d 100644 +--- a/drivers/dma-buf/dma-fence-array.c ++++ b/drivers/dma-buf/dma-fence-array.c +@@ -104,7 +104,11 @@ static bool dma_fence_array_signaled(struct dma_fence *fence) + { + struct dma_fence_array *array = to_dma_fence_array(fence); + +- return atomic_read(&array->num_pending) <= 0; ++ if (atomic_read(&array->num_pending) > 0) ++ return false; ++ ++ dma_fence_array_clear_pending_error(array); ++ return true; + } + + static void dma_fence_array_release(struct dma_fence *fence) +diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c +index 56bf5ad01ad54..8f5848aa144fe 100644 +--- a/drivers/dma-buf/dma-heap.c ++++ b/drivers/dma-buf/dma-heap.c +@@ -14,6 +14,7 @@ + #include <linux/xarray.h> + #include <linux/list.h> + #include <linux/slab.h> ++#include <linux/nospec.h> + #include <linux/uaccess.h> + #include <linux/syscalls.h> + #include <linux/dma-heap.h> +@@ -135,6 +136,7 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, + if (nr >= ARRAY_SIZE(dma_heap_ioctl_cmds)) + return -EINVAL; + ++ nr = array_index_nospec(nr, ARRAY_SIZE(dma_heap_ioctl_cmds)); + /* Get the kernel ioctl cmd that matches */ + kcmd = dma_heap_ioctl_cmds[nr]; + +diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c +index 0c05b79870f96..83f02bd51dda6 100644 +--- a/drivers/dma-buf/heaps/cma_heap.c ++++ b/drivers/dma-buf/heaps/cma_heap.c +@@ -124,10 +124,11 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + ++ mutex_lock(&buffer->lock); ++ + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + +- mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; +@@ -144,10 +145,11 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + ++ mutex_lock(&buffer->lock); ++ + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + +- mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; +diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c +index 23a7e74ef9666..8660508f3684f 100644 +--- a/drivers/dma-buf/heaps/system_heap.c ++++ b/drivers/dma-buf/heaps/system_heap.c +@@ -289,7 +289,7 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) + int i; + + table = &buffer->sg_table; +- for_each_sg(table->sgl, sg, table->nents, i) { ++ for_each_sgtable_sg(table, sg, i) { + struct page *page = sg_page(sg); + + __free_pages(page, compound_order(page)); +diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c +index ab78e0f6afd70..8177aed160060 100644 +--- a/drivers/dma/at_xdmac.c ++++ b/drivers/dma/at_xdmac.c +@@ -99,6 +99,7 @@ + #define AT_XDMAC_CNDC_NDE (0x1 << 0) /* Channel x Next Descriptor Enable */ + #define AT_XDMAC_CNDC_NDSUP (0x1 << 1) /* Channel x Next Descriptor Source Update */ + #define AT_XDMAC_CNDC_NDDUP (0x1 << 2) /* Channel x Next Descriptor Destination Update */ ++#define AT_XDMAC_CNDC_NDVIEW_MASK GENMASK(28, 27) + #define AT_XDMAC_CNDC_NDVIEW_NDV0 (0x0 << 3) /* Channel x Next Descriptor View 0 */ + #define AT_XDMAC_CNDC_NDVIEW_NDV1 (0x1 << 3) /* Channel x Next Descriptor View 1 */ + #define AT_XDMAC_CNDC_NDVIEW_NDV2 (0x2 << 3) /* Channel x Next Descriptor View 2 */ +@@ -155,7 +156,7 @@ + #define AT_XDMAC_CC_WRIP (0x1 << 23) /* Write in Progress (read only) */ + #define AT_XDMAC_CC_WRIP_DONE (0x0 << 23) + #define AT_XDMAC_CC_WRIP_IN_PROGRESS (0x1 << 23) +-#define AT_XDMAC_CC_PERID(i) (0x7f & (i) << 24) /* Channel Peripheral Identifier */ ++#define AT_XDMAC_CC_PERID(i) ((0x7f & (i)) << 24) /* Channel Peripheral Identifier */ + #define AT_XDMAC_CDS_MSP 0x2C /* Channel Data Stride Memory Set Pattern */ + #define AT_XDMAC_CSUS 0x30 /* Channel Source Microblock Stride */ + #define AT_XDMAC_CDUS 0x34 /* Channel Destination Microblock Stride */ +@@ -252,15 +253,15 @@ struct at_xdmac { + + /* Linked List Descriptor */ + struct at_xdmac_lld { +- dma_addr_t mbr_nda; /* Next Descriptor Member */ +- u32 mbr_ubc; /* Microblock Control Member */ +- dma_addr_t mbr_sa; /* Source Address Member */ +- dma_addr_t mbr_da; /* Destination Address Member */ +- u32 mbr_cfg; /* Configuration Register */ +- u32 mbr_bc; /* Block Control Register */ +- u32 mbr_ds; /* Data Stride Register */ +- u32 mbr_sus; /* Source Microblock Stride Register */ +- u32 mbr_dus; /* Destination Microblock Stride Register */ ++ u32 mbr_nda; /* Next Descriptor Member */ ++ u32 mbr_ubc; /* Microblock Control Member */ ++ u32 mbr_sa; /* Source Address Member */ ++ u32 mbr_da; /* Destination Address Member */ ++ u32 mbr_cfg; /* Configuration Register */ ++ u32 mbr_bc; /* Block Control Register */ ++ u32 mbr_ds; /* Data Stride Register */ ++ u32 mbr_sus; /* Source Microblock Stride Register */ ++ u32 mbr_dus; /* Destination Microblock Stride Register */ + }; + + /* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */ +@@ -385,9 +386,6 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan, + + dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first); + +- if (at_xdmac_chan_is_enabled(atchan)) +- return; +- + /* Set transfer as active to not try to start it again. */ + first->active_xfer = true; + +@@ -405,7 +403,8 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan, + */ + if (at_xdmac_chan_is_cyclic(atchan)) + reg = AT_XDMAC_CNDC_NDVIEW_NDV1; +- else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3) ++ else if ((first->lld.mbr_ubc & ++ AT_XDMAC_CNDC_NDVIEW_MASK) == AT_XDMAC_MBR_UBC_NDV3) + reg = AT_XDMAC_CNDC_NDVIEW_NDV3; + else + reg = AT_XDMAC_CNDC_NDVIEW_NDV2; +@@ -476,13 +475,12 @@ static dma_cookie_t at_xdmac_tx_submit(struct dma_async_tx_descriptor *tx) + spin_lock_irqsave(&atchan->lock, irqflags); + cookie = dma_cookie_assign(tx); + ++ list_add_tail(&desc->xfer_node, &atchan->xfers_list); ++ spin_unlock_irqrestore(&atchan->lock, irqflags); ++ + dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n", + __func__, atchan, desc); +- list_add_tail(&desc->xfer_node, &atchan->xfers_list); +- if (list_is_singular(&atchan->xfers_list)) +- at_xdmac_start_xfer(atchan, desc); + +- spin_unlock_irqrestore(&atchan->lock, irqflags); + return cookie; + } + +@@ -1623,14 +1621,17 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan) + struct at_xdmac_desc *desc; + struct dma_async_tx_descriptor *txd; + +- if (!list_empty(&atchan->xfers_list)) { +- desc = list_first_entry(&atchan->xfers_list, +- struct at_xdmac_desc, xfer_node); +- txd = &desc->tx_dma_desc; +- +- if (txd->flags & DMA_PREP_INTERRUPT) +- dmaengine_desc_get_callback_invoke(txd, NULL); ++ spin_lock_irq(&atchan->lock); ++ if (list_empty(&atchan->xfers_list)) { ++ spin_unlock_irq(&atchan->lock); ++ return; + } ++ desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, ++ xfer_node); ++ spin_unlock_irq(&atchan->lock); ++ txd = &desc->tx_dma_desc; ++ if (txd->flags & DMA_PREP_INTERRUPT) ++ dmaengine_desc_get_callback_invoke(txd, NULL); + } + + static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) +@@ -1784,11 +1785,9 @@ static void at_xdmac_issue_pending(struct dma_chan *chan) + + dev_dbg(chan2dev(&atchan->chan), "%s\n", __func__); + +- if (!at_xdmac_chan_is_cyclic(atchan)) { +- spin_lock_irqsave(&atchan->lock, flags); +- at_xdmac_advance_work(atchan); +- spin_unlock_irqrestore(&atchan->lock, flags); +- } ++ spin_lock_irqsave(&atchan->lock, flags); ++ at_xdmac_advance_work(atchan); ++ spin_unlock_irqrestore(&atchan->lock, flags); + + return; + } +@@ -1926,6 +1925,30 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan) + return; + } + ++static void at_xdmac_axi_config(struct platform_device *pdev) ++{ ++ struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev); ++ bool dev_m2m = false; ++ u32 dma_requests; ++ ++ if (!atxdmac->layout->axi_config) ++ return; /* Not supported */ ++ ++ if (!of_property_read_u32(pdev->dev.of_node, "dma-requests", ++ &dma_requests)) { ++ dev_info(&pdev->dev, "controller in mem2mem mode.\n"); ++ dev_m2m = true; ++ } ++ ++ if (dev_m2m) { ++ at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M); ++ at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M); ++ } else { ++ at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M); ++ at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M); ++ } ++} ++ + #ifdef CONFIG_PM + static int atmel_xdmac_prepare(struct device *dev) + { +@@ -1975,6 +1998,7 @@ static int atmel_xdmac_resume(struct device *dev) + struct at_xdmac *atxdmac = dev_get_drvdata(dev); + struct at_xdmac_chan *atchan; + struct dma_chan *chan, *_chan; ++ struct platform_device *pdev = container_of(dev, struct platform_device, dev); + int i; + int ret; + +@@ -1982,6 +2006,8 @@ static int atmel_xdmac_resume(struct device *dev) + if (ret) + return ret; + ++ at_xdmac_axi_config(pdev); ++ + /* Clear pending interrupts. */ + for (i = 0; i < atxdmac->dma.chancnt; i++) { + atchan = &atxdmac->chan[i]; +@@ -2007,30 +2033,6 @@ static int atmel_xdmac_resume(struct device *dev) + } + #endif /* CONFIG_PM_SLEEP */ + +-static void at_xdmac_axi_config(struct platform_device *pdev) +-{ +- struct at_xdmac *atxdmac = (struct at_xdmac *)platform_get_drvdata(pdev); +- bool dev_m2m = false; +- u32 dma_requests; +- +- if (!atxdmac->layout->axi_config) +- return; /* Not supported */ +- +- if (!of_property_read_u32(pdev->dev.of_node, "dma-requests", +- &dma_requests)) { +- dev_info(&pdev->dev, "controller in mem2mem mode.\n"); +- dev_m2m = true; +- } +- +- if (dev_m2m) { +- at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_M2M); +- at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_M2M); +- } else { +- at_xdmac_write(atxdmac, AT_XDMAC_GCFG, AT_XDMAC_GCFG_P2M); +- at_xdmac_write(atxdmac, AT_XDMAC_GWAC, AT_XDMAC_GWAC_P2M); +- } +-} +- + static int at_xdmac_probe(struct platform_device *pdev) + { + struct at_xdmac *atxdmac; +diff --git a/drivers/dma/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c +index 2fd87f83cf90b..e169f18da551f 100644 +--- a/drivers/dma/bestcomm/ata.c ++++ b/drivers/dma/bestcomm/ata.c +@@ -133,7 +133,7 @@ void bcom_ata_reset_bd(struct bcom_task *tsk) + struct bcom_ata_var *var; + + /* Reset all BD */ +- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); ++ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); + + tsk->index = 0; + tsk->outdex = 0; +diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c +index d91cbbe7a48fb..8c42e5ca00a99 100644 +--- a/drivers/dma/bestcomm/bestcomm.c ++++ b/drivers/dma/bestcomm/bestcomm.c +@@ -95,7 +95,7 @@ bcom_task_alloc(int bd_count, int bd_size, int priv_size) + tsk->bd = bcom_sram_alloc(bd_count * bd_size, 4, &tsk->bd_pa); + if (!tsk->bd) + goto error; +- memset(tsk->bd, 0x00, bd_count * bd_size); ++ memset_io(tsk->bd, 0x00, bd_count * bd_size); + + tsk->num_bd = bd_count; + tsk->bd_size = bd_size; +@@ -186,16 +186,16 @@ bcom_load_image(int task, u32 *task_image) + inc = bcom_task_inc(task); + + /* Clear & copy */ +- memset(var, 0x00, BCOM_VAR_SIZE); +- memset(inc, 0x00, BCOM_INC_SIZE); ++ memset_io(var, 0x00, BCOM_VAR_SIZE); ++ memset_io(inc, 0x00, BCOM_INC_SIZE); + + desc_src = (u32 *)(hdr + 1); + var_src = desc_src + hdr->desc_size; + inc_src = var_src + hdr->var_size; + +- memcpy(desc, desc_src, hdr->desc_size * sizeof(u32)); +- memcpy(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32)); +- memcpy(inc, inc_src, hdr->inc_size * sizeof(u32)); ++ memcpy_toio(desc, desc_src, hdr->desc_size * sizeof(u32)); ++ memcpy_toio(var + hdr->first_var, var_src, hdr->var_size * sizeof(u32)); ++ memcpy_toio(inc, inc_src, hdr->inc_size * sizeof(u32)); + + return 0; + } +@@ -302,13 +302,13 @@ static int bcom_engine_init(void) + return -ENOMEM; + } + +- memset(bcom_eng->tdt, 0x00, tdt_size); +- memset(bcom_eng->ctx, 0x00, ctx_size); +- memset(bcom_eng->var, 0x00, var_size); +- memset(bcom_eng->fdt, 0x00, fdt_size); ++ memset_io(bcom_eng->tdt, 0x00, tdt_size); ++ memset_io(bcom_eng->ctx, 0x00, ctx_size); ++ memset_io(bcom_eng->var, 0x00, var_size); ++ memset_io(bcom_eng->fdt, 0x00, fdt_size); + + /* Copy the FDT for the EU#3 */ +- memcpy(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops)); ++ memcpy_toio(&bcom_eng->fdt[48], fdt_ops, sizeof(fdt_ops)); + + /* Initialize Task base structure */ + for (task=0; task<BCOM_MAX_TASKS; task++) +diff --git a/drivers/dma/bestcomm/fec.c b/drivers/dma/bestcomm/fec.c +index 7f1fb1c999e43..d203618ac11fe 100644 +--- a/drivers/dma/bestcomm/fec.c ++++ b/drivers/dma/bestcomm/fec.c +@@ -140,7 +140,7 @@ bcom_fec_rx_reset(struct bcom_task *tsk) + tsk->index = 0; + tsk->outdex = 0; + +- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); ++ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); + + /* Configure some stuff */ + bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_RX_BD_PRAGMA); +@@ -241,7 +241,7 @@ bcom_fec_tx_reset(struct bcom_task *tsk) + tsk->index = 0; + tsk->outdex = 0; + +- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); ++ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); + + /* Configure some stuff */ + bcom_set_task_pragma(tsk->tasknum, BCOM_FEC_TX_BD_PRAGMA); +diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c +index 906ddba6a6f5d..8a24a5cbc2633 100644 +--- a/drivers/dma/bestcomm/gen_bd.c ++++ b/drivers/dma/bestcomm/gen_bd.c +@@ -142,7 +142,7 @@ bcom_gen_bd_rx_reset(struct bcom_task *tsk) + tsk->index = 0; + tsk->outdex = 0; + +- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); ++ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); + + /* Configure some stuff */ + bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA); +@@ -226,7 +226,7 @@ bcom_gen_bd_tx_reset(struct bcom_task *tsk) + tsk->index = 0; + tsk->outdex = 0; + +- memset(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); ++ memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size); + + /* Configure some stuff */ + bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA); +diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h +index 1bfbd64b13717..53f16d3f00294 100644 +--- a/drivers/dma/dmaengine.h ++++ b/drivers/dma/dmaengine.h +@@ -176,7 +176,7 @@ dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx, + static inline bool + dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb) + { +- return (cb->callback) ? true : false; ++ return cb->callback || cb->callback_result; + } + + struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); +diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c +index 83a5ff2ecf2a0..b468ca36d3a01 100644 +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -394,8 +394,6 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq) + lockdep_assert_held(&wq->wq_lock); + memset(wq->wqcfg, 0, idxd->wqcfg_size); + wq->type = IDXD_WQT_NONE; +- wq->size = 0; +- wq->group = NULL; + wq->threshold = 0; + wq->priority = 0; + wq->ats_dis = 0; +@@ -404,6 +402,15 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq) + memset(wq->name, 0, WQ_NAME_SIZE); + } + ++static void idxd_wq_device_reset_cleanup(struct idxd_wq *wq) ++{ ++ lockdep_assert_held(&wq->wq_lock); ++ ++ idxd_wq_disable_cleanup(wq); ++ wq->size = 0; ++ wq->group = NULL; ++} ++ + static void idxd_wq_ref_release(struct percpu_ref *ref) + { + struct idxd_wq *wq = container_of(ref, struct idxd_wq, wq_active); +@@ -427,7 +434,6 @@ void idxd_wq_quiesce(struct idxd_wq *wq) + { + percpu_ref_kill(&wq->wq_active); + wait_for_completion(&wq->wq_dead); +- percpu_ref_exit(&wq->wq_active); + } + + /* Device control bits */ +@@ -584,6 +590,8 @@ void idxd_device_reset(struct idxd_device *idxd) + spin_lock(&idxd->dev_lock); + idxd_device_clear_state(idxd); + idxd->state = IDXD_DEV_DISABLED; ++ idxd_unmask_error_interrupts(idxd); ++ idxd_msix_perm_setup(idxd); + spin_unlock(&idxd->dev_lock); + } + +@@ -710,6 +718,7 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd) + + if (wq->state == IDXD_WQ_ENABLED) { + idxd_wq_disable_cleanup(wq); ++ idxd_wq_device_reset_cleanup(wq); + wq->state = IDXD_WQ_DISABLED; + } + } +diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c +index e0f056c1d1f56..c39e9483206ad 100644 +--- a/drivers/dma/idxd/dma.c ++++ b/drivers/dma/idxd/dma.c +@@ -311,6 +311,7 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev) + + err_dma: + idxd_wq_quiesce(wq); ++ percpu_ref_exit(&wq->wq_active); + err_ref: + idxd_wq_free_resources(wq); + err_res_alloc: +@@ -328,9 +329,9 @@ static void idxd_dmaengine_drv_remove(struct idxd_dev *idxd_dev) + mutex_lock(&wq->wq_lock); + idxd_wq_quiesce(wq); + idxd_unregister_dma_channel(wq); +- __drv_disable_wq(wq); + idxd_wq_free_resources(wq); +- wq->type = IDXD_WQT_NONE; ++ __drv_disable_wq(wq); ++ percpu_ref_exit(&wq->wq_active); + mutex_unlock(&wq->wq_lock); + } + +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index eb09bc591c316..7bf03f371ce19 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -797,11 +797,19 @@ static void idxd_remove(struct pci_dev *pdev) + int msixcnt = pci_msix_vec_count(pdev); + int i; + +- dev_dbg(&pdev->dev, "%s called\n", __func__); ++ idxd_unregister_devices(idxd); ++ /* ++ * When ->release() is called for the idxd->conf_dev, it frees all the memory related ++ * to the idxd context. The driver still needs those bits in order to do the rest of ++ * the cleanup. However, we do need to unbound the idxd sub-driver. So take a ref ++ * on the device here to hold off the freeing while allowing the idxd sub-driver ++ * to unbind. ++ */ ++ get_device(idxd_confdev(idxd)); ++ device_unregister(idxd_confdev(idxd)); + idxd_shutdown(pdev); + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); +- idxd_unregister_devices(idxd); + + for (i = 0; i < msixcnt; i++) { + irq_entry = &idxd->irq_entries[i]; +@@ -815,7 +823,7 @@ static void idxd_remove(struct pci_dev *pdev) + pci_disable_device(pdev); + destroy_workqueue(idxd->wq); + perfmon_pmu_remove(idxd); +- device_unregister(idxd_confdev(idxd)); ++ put_device(idxd_confdev(idxd)); + } + + static struct pci_driver idxd_pci_driver = { +diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c +index ca88fa7a328e7..6d6af0dc3c0ec 100644 +--- a/drivers/dma/idxd/irq.c ++++ b/drivers/dma/idxd/irq.c +@@ -63,6 +63,9 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + int i; + bool err = false; + ++ if (cause & IDXD_INTC_HALT_STATE) ++ goto halt; ++ + if (cause & IDXD_INTC_ERR) { + spin_lock(&idxd->dev_lock); + for (i = 0; i < 4; i++) +@@ -121,6 +124,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + if (!err) + return 0; + ++halt: + gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET); + if (gensts.state == IDXD_DEVICE_STATE_HALT) { + idxd->state = IDXD_DEV_HALTED; +@@ -133,9 +137,10 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + INIT_WORK(&idxd->work, idxd_device_reinit); + queue_work(idxd->wq, &idxd->work); + } else { +- spin_lock(&idxd->dev_lock); ++ idxd->state = IDXD_DEV_HALTED; + idxd_wqs_quiesce(idxd); + idxd_wqs_unmap_portal(idxd); ++ spin_lock(&idxd->dev_lock); + idxd_device_clear_state(idxd); + dev_err(&idxd->pdev->dev, + "idxd halted, need %s.\n", +diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h +index ffc7550a77eeb..97ffb06de9b0d 100644 +--- a/drivers/dma/idxd/registers.h ++++ b/drivers/dma/idxd/registers.h +@@ -158,6 +158,7 @@ enum idxd_device_reset_type { + #define IDXD_INTC_CMD 0x02 + #define IDXD_INTC_OCCUPY 0x04 + #define IDXD_INTC_PERFMON_OVFL 0x08 ++#define IDXD_INTC_HALT_STATE 0x10 + + #define IDXD_CMD_OFFSET 0xa0 + union idxd_command_reg { +diff --git a/drivers/dma/idxd/submit.c b/drivers/dma/idxd/submit.c +index de76fb4abac24..83452fbbb168b 100644 +--- a/drivers/dma/idxd/submit.c ++++ b/drivers/dma/idxd/submit.c +@@ -106,6 +106,7 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, + { + struct idxd_desc *d, *t, *found = NULL; + struct llist_node *head; ++ LIST_HEAD(flist); + + desc->completion->status = IDXD_COMP_DESC_ABORT; + /* +@@ -120,7 +121,11 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, + found = desc; + continue; + } +- list_add_tail(&desc->list, &ie->work_list); ++ ++ if (d->completion->status) ++ list_add_tail(&d->list, &flist); ++ else ++ list_add_tail(&d->list, &ie->work_list); + } + } + +@@ -130,6 +135,17 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie, + + if (found) + complete_desc(found, IDXD_COMPLETE_ABORT); ++ ++ /* ++ * complete_desc() will return desc to allocator and the desc can be ++ * acquired by a different process and the desc->list can be modified. ++ * Delete desc from list so the list trasversing does not get corrupted ++ * by the other process. ++ */ ++ list_for_each_entry_safe(d, t, &flist, list) { ++ list_del_init(&d->list); ++ complete_desc(d, IDXD_COMPLETE_NORMAL); ++ } + } + + int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc) +diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c +index 89f1814ff27a0..26d11885c50ec 100644 +--- a/drivers/dma/mmp_pdma.c ++++ b/drivers/dma/mmp_pdma.c +@@ -727,12 +727,6 @@ static int mmp_pdma_config_write(struct dma_chan *dchan, + + chan->dir = direction; + chan->dev_addr = addr; +- /* FIXME: drivers should be ported over to use the filter +- * function. Once that's done, the following two lines can +- * be removed. +- */ +- if (cfg->slave_id) +- chan->drcmr = cfg->slave_id; + + return 0; + } +diff --git a/drivers/dma/ptdma/ptdma-dev.c b/drivers/dma/ptdma/ptdma-dev.c +index 8a6bf291a73fe..daafea5bc35d9 100644 +--- a/drivers/dma/ptdma/ptdma-dev.c ++++ b/drivers/dma/ptdma/ptdma-dev.c +@@ -207,7 +207,7 @@ int pt_core_init(struct pt_device *pt) + if (!cmd_q->qbase) { + dev_err(dev, "unable to allocate command queue\n"); + ret = -ENOMEM; +- goto e_dma_alloc; ++ goto e_destroy_pool; + } + + cmd_q->qidx = 0; +@@ -229,8 +229,10 @@ int pt_core_init(struct pt_device *pt) + + /* Request an irq */ + ret = request_irq(pt->pt_irq, pt_core_irq_handler, 0, dev_name(pt->dev), pt); +- if (ret) +- goto e_pool; ++ if (ret) { ++ dev_err(dev, "unable to allocate an IRQ\n"); ++ goto e_free_dma; ++ } + + /* Update the device registers with queue information. */ + cmd_q->qcontrol &= ~CMD_Q_SIZE; +@@ -250,21 +252,20 @@ int pt_core_init(struct pt_device *pt) + /* Register the DMA engine support */ + ret = pt_dmaengine_register(pt); + if (ret) +- goto e_dmaengine; ++ goto e_free_irq; + + /* Set up debugfs entries */ + ptdma_debugfs_setup(pt); + + return 0; + +-e_dmaengine: ++e_free_irq: + free_irq(pt->pt_irq, pt); + +-e_dma_alloc: ++e_free_dma: + dma_free_coherent(dev, cmd_q->qsize, cmd_q->qbase, cmd_q->qbase_dma); + +-e_pool: +- dev_err(dev, "unable to allocate an IRQ\n"); ++e_destroy_pool: + dma_pool_destroy(pt->cmd_q.dma_pool); + + return ret; +diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c +index 4a2a796e348c1..aa6e552249ab9 100644 +--- a/drivers/dma/pxa_dma.c ++++ b/drivers/dma/pxa_dma.c +@@ -910,13 +910,6 @@ static void pxad_get_config(struct pxad_chan *chan, + *dcmd |= PXA_DCMD_BURST16; + else if (maxburst == 32) + *dcmd |= PXA_DCMD_BURST32; +- +- /* FIXME: drivers should be ported over to use the filter +- * function. Once that's done, the following two lines can +- * be removed. +- */ +- if (chan->cfg.slave_id) +- chan->drcmr = chan->cfg.slave_id; + } + + static struct dma_async_tx_descriptor * +diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c +index 6885b3dcd7a97..f4c46b3b6d9d7 100644 +--- a/drivers/dma/sh/rcar-dmac.c ++++ b/drivers/dma/sh/rcar-dmac.c +@@ -1868,8 +1868,13 @@ static int rcar_dmac_probe(struct platform_device *pdev) + + dmac->dev = &pdev->dev; + platform_set_drvdata(pdev, dmac); +- dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK); +- dma_set_mask_and_coherent(dmac->dev, DMA_BIT_MASK(40)); ++ ret = dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK); ++ if (ret) ++ return ret; ++ ++ ret = dma_set_mask_and_coherent(dmac->dev, DMA_BIT_MASK(40)); ++ if (ret) ++ return ret; + + ret = rcar_dmac_parse_of(&pdev->dev, dmac); + if (ret < 0) +diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c +index 7f72b3f4cd1ae..19ac95c0098f0 100644 +--- a/drivers/dma/sh/shdma-base.c ++++ b/drivers/dma/sh/shdma-base.c +@@ -115,8 +115,10 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx) + ret = pm_runtime_get(schan->dev); + + spin_unlock_irq(&schan->chan_lock); +- if (ret < 0) ++ if (ret < 0) { + dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret); ++ pm_runtime_put(schan->dev); ++ } + + pm_runtime_barrier(schan->dev); + +diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c +index 962b6e05287b5..d95c421877fb7 100644 +--- a/drivers/dma/st_fdma.c ++++ b/drivers/dma/st_fdma.c +@@ -874,4 +874,4 @@ MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver"); + MODULE_AUTHOR("Ludovic.barre <Ludovic.barre@st.com>"); + MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>"); +-MODULE_ALIAS("platform: " DRIVER_NAME); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c +index 9063c727962ed..7dfc743ac4338 100644 +--- a/drivers/dma/stm32-dma.c ++++ b/drivers/dma/stm32-dma.c +@@ -270,7 +270,6 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, + u32 threshold) + { + enum dma_slave_buswidth max_width; +- u64 addr = buf_addr; + + if (threshold == STM32_DMA_FIFO_THRESHOLD_FULL) + max_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +@@ -281,7 +280,7 @@ static enum dma_slave_buswidth stm32_dma_get_max_width(u32 buf_len, + max_width > DMA_SLAVE_BUSWIDTH_1_BYTE) + max_width = max_width >> 1; + +- if (do_div(addr, max_width)) ++ if (buf_addr & (max_width - 1)) + max_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + + return max_width; +@@ -753,8 +752,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, + if (src_bus_width < 0) + return src_bus_width; + +- /* Set memory burst size */ +- src_maxburst = STM32_DMA_MAX_BURST; ++ /* ++ * Set memory burst size - burst not possible if address is not aligned on ++ * the address boundary equal to the size of the transfer ++ */ ++ if (buf_addr & (buf_len - 1)) ++ src_maxburst = 1; ++ else ++ src_maxburst = STM32_DMA_MAX_BURST; + src_best_burst = stm32_dma_get_best_burst(buf_len, + src_maxburst, + fifoth, +@@ -803,8 +808,14 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, + if (dst_bus_width < 0) + return dst_bus_width; + +- /* Set memory burst size */ +- dst_maxburst = STM32_DMA_MAX_BURST; ++ /* ++ * Set memory burst size - burst not possible if address is not aligned on ++ * the address boundary equal to the size of the transfer ++ */ ++ if (buf_addr & (buf_len - 1)) ++ dst_maxburst = 1; ++ else ++ dst_maxburst = STM32_DMA_MAX_BURST; + dst_best_burst = stm32_dma_get_best_burst(buf_len, + dst_maxburst, + fifoth, +diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c +index a42164389ebc2..d5d55732adba1 100644 +--- a/drivers/dma/stm32-dmamux.c ++++ b/drivers/dma/stm32-dmamux.c +@@ -292,10 +292,12 @@ static int stm32_dmamux_probe(struct platform_device *pdev) + ret = of_dma_router_register(node, stm32_dmamux_route_allocate, + &stm32_dmamux->dmarouter); + if (ret) +- goto err_clk; ++ goto pm_disable; + + return 0; + ++pm_disable: ++ pm_runtime_disable(&pdev->dev); + err_clk: + clk_disable_unprepare(stm32_dmamux->clk); + +diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c +index 18cbd1e43c2e8..f17a9ffcd00da 100644 +--- a/drivers/dma/stm32-mdma.c ++++ b/drivers/dma/stm32-mdma.c +@@ -184,7 +184,7 @@ + #define STM32_MDMA_CTBR(x) (0x68 + 0x40 * (x)) + #define STM32_MDMA_CTBR_DBUS BIT(17) + #define STM32_MDMA_CTBR_SBUS BIT(16) +-#define STM32_MDMA_CTBR_TSEL_MASK GENMASK(7, 0) ++#define STM32_MDMA_CTBR_TSEL_MASK GENMASK(5, 0) + #define STM32_MDMA_CTBR_TSEL(n) STM32_MDMA_SET(n, \ + STM32_MDMA_CTBR_TSEL_MASK) + +diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c +index b1115a6d1935c..d1dff3a29db59 100644 +--- a/drivers/dma/tegra210-adma.c ++++ b/drivers/dma/tegra210-adma.c +@@ -867,7 +867,7 @@ static int tegra_adma_probe(struct platform_device *pdev) + + pm_runtime_enable(&pdev->dev); + +- ret = pm_runtime_get_sync(&pdev->dev); ++ ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + goto rpm_disable; + +diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c +index a35858610780c..041d8e32d6300 100644 +--- a/drivers/dma/ti/k3-udma.c ++++ b/drivers/dma/ti/k3-udma.c +@@ -1348,6 +1348,7 @@ static int bcdma_get_bchan(struct udma_chan *uc) + { + struct udma_dev *ud = uc->ud; + enum udma_tp_level tpl; ++ int ret; + + if (uc->bchan) { + dev_dbg(ud->dev, "chan%d: already have bchan%d allocated\n", +@@ -1365,8 +1366,11 @@ static int bcdma_get_bchan(struct udma_chan *uc) + tpl = ud->bchan_tpl.levels - 1; + + uc->bchan = __udma_reserve_bchan(ud, tpl, -1); +- if (IS_ERR(uc->bchan)) +- return PTR_ERR(uc->bchan); ++ if (IS_ERR(uc->bchan)) { ++ ret = PTR_ERR(uc->bchan); ++ uc->bchan = NULL; ++ return ret; ++ } + + uc->tchan = uc->bchan; + +@@ -1376,6 +1380,7 @@ static int bcdma_get_bchan(struct udma_chan *uc) + static int udma_get_tchan(struct udma_chan *uc) + { + struct udma_dev *ud = uc->ud; ++ int ret; + + if (uc->tchan) { + dev_dbg(ud->dev, "chan%d: already have tchan%d allocated\n", +@@ -1390,8 +1395,11 @@ static int udma_get_tchan(struct udma_chan *uc) + */ + uc->tchan = __udma_reserve_tchan(ud, uc->config.channel_tpl, + uc->config.mapped_channel_id); +- if (IS_ERR(uc->tchan)) +- return PTR_ERR(uc->tchan); ++ if (IS_ERR(uc->tchan)) { ++ ret = PTR_ERR(uc->tchan); ++ uc->tchan = NULL; ++ return ret; ++ } + + if (ud->tflow_cnt) { + int tflow_id; +@@ -1421,6 +1429,7 @@ static int udma_get_tchan(struct udma_chan *uc) + static int udma_get_rchan(struct udma_chan *uc) + { + struct udma_dev *ud = uc->ud; ++ int ret; + + if (uc->rchan) { + dev_dbg(ud->dev, "chan%d: already have rchan%d allocated\n", +@@ -1435,8 +1444,13 @@ static int udma_get_rchan(struct udma_chan *uc) + */ + uc->rchan = __udma_reserve_rchan(ud, uc->config.channel_tpl, + uc->config.mapped_channel_id); ++ if (IS_ERR(uc->rchan)) { ++ ret = PTR_ERR(uc->rchan); ++ uc->rchan = NULL; ++ return ret; ++ } + +- return PTR_ERR_OR_ZERO(uc->rchan); ++ return 0; + } + + static int udma_get_chan_pair(struct udma_chan *uc) +@@ -1490,6 +1504,7 @@ static int udma_get_chan_pair(struct udma_chan *uc) + static int udma_get_rflow(struct udma_chan *uc, int flow_id) + { + struct udma_dev *ud = uc->ud; ++ int ret; + + if (!uc->rchan) { + dev_err(ud->dev, "chan%d: does not have rchan??\n", uc->id); +@@ -1503,8 +1518,13 @@ static int udma_get_rflow(struct udma_chan *uc, int flow_id) + } + + uc->rflow = __udma_get_rflow(ud, flow_id); ++ if (IS_ERR(uc->rflow)) { ++ ret = PTR_ERR(uc->rflow); ++ uc->rflow = NULL; ++ return ret; ++ } + +- return PTR_ERR_OR_ZERO(uc->rflow); ++ return 0; + } + + static void bcdma_put_bchan(struct udma_chan *uc) +diff --git a/drivers/dma/uniphier-xdmac.c b/drivers/dma/uniphier-xdmac.c +index d6b8a202474f4..290836b7e1be2 100644 +--- a/drivers/dma/uniphier-xdmac.c ++++ b/drivers/dma/uniphier-xdmac.c +@@ -131,8 +131,9 @@ uniphier_xdmac_next_desc(struct uniphier_xdmac_chan *xc) + static void uniphier_xdmac_chan_start(struct uniphier_xdmac_chan *xc, + struct uniphier_xdmac_desc *xd) + { +- u32 src_mode, src_addr, src_width; +- u32 dst_mode, dst_addr, dst_width; ++ u32 src_mode, src_width; ++ u32 dst_mode, dst_width; ++ dma_addr_t src_addr, dst_addr; + u32 val, its, tnum; + enum dma_slave_buswidth buswidth; + +diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c +index b280a53e8570a..ce5c66e6897d2 100644 +--- a/drivers/dma/xilinx/xilinx_dpdma.c ++++ b/drivers/dma/xilinx/xilinx_dpdma.c +@@ -271,9 +271,6 @@ struct xilinx_dpdma_device { + /* ----------------------------------------------------------------------------- + * DebugFS + */ +- +-#ifdef CONFIG_DEBUG_FS +- + #define XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE 32 + #define XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR "65535" + +@@ -299,7 +296,7 @@ struct xilinx_dpdma_debugfs_request { + + static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan) + { +- if (chan->id == dpdma_debugfs.chan_id) ++ if (IS_ENABLED(CONFIG_DEBUG_FS) && chan->id == dpdma_debugfs.chan_id) + dpdma_debugfs.xilinx_dpdma_irq_done_count++; + } + +@@ -462,16 +459,6 @@ static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev) + dev_err(xdev->dev, "Failed to create debugfs testcase file\n"); + } + +-#else +-static void xilinx_dpdma_debugfs_init(struct xilinx_dpdma_device *xdev) +-{ +-} +- +-static void xilinx_dpdma_debugfs_desc_done_irq(struct xilinx_dpdma_chan *chan) +-{ +-} +-#endif /* CONFIG_DEBUG_FS */ +- + /* ----------------------------------------------------------------------------- + * I/O Accessors + */ +diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c +index 3a6d2416cb0f6..5dd29789f97d3 100644 +--- a/drivers/edac/altera_edac.c ++++ b/drivers/edac/altera_edac.c +@@ -350,7 +350,7 @@ static int altr_sdram_probe(struct platform_device *pdev) + if (irq < 0) { + edac_printk(KERN_ERR, EDAC_MC, + "No irq %d in DT\n", irq); +- return -ENODEV; ++ return irq; + } + + /* Arria10 has a 2nd IRQ */ +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index 99b06a3e8fb12..4fce75013674f 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -1065,12 +1065,14 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) + #define CS_ODD_PRIMARY BIT(1) + #define CS_EVEN_SECONDARY BIT(2) + #define CS_ODD_SECONDARY BIT(3) ++#define CS_3R_INTERLEAVE BIT(4) + + #define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY) + #define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY) + + static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) + { ++ u8 base, count = 0; + int cs_mode = 0; + + if (csrow_enabled(2 * dimm, ctrl, pvt)) +@@ -1083,6 +1085,20 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) + if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt)) + cs_mode |= CS_ODD_SECONDARY; + ++ /* ++ * 3 Rank inteleaving support. ++ * There should be only three bases enabled and their two masks should ++ * be equal. ++ */ ++ for_each_chip_select(base, ctrl, pvt) ++ count += csrow_enabled(base, ctrl, pvt); ++ ++ if (count == 3 && ++ pvt->csels[ctrl].csmasks[0] == pvt->csels[ctrl].csmasks[1]) { ++ edac_dbg(1, "3R interleaving in use.\n"); ++ cs_mode |= CS_3R_INTERLEAVE; ++ } ++ + return cs_mode; + } + +@@ -1891,10 +1907,14 @@ static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, + * + * The MSB is the number of bits in the full mask because BIT[0] is + * always 0. ++ * ++ * In the special 3 Rank interleaving case, a single bit is flipped ++ * without swapping with the most significant bit. This can be handled ++ * by keeping the MSB where it is and ignoring the single zero bit. + */ + msb = fls(addr_mask_orig) - 1; + weight = hweight_long(addr_mask_orig); +- num_zero_bits = msb - weight; ++ num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE); + + /* Take the number of zero bits off from the top of the mask. */ + addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); +diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c +index 2c5975674723a..a859ddd9d4a13 100644 +--- a/drivers/edac/edac_mc.c ++++ b/drivers/edac/edac_mc.c +@@ -215,7 +215,7 @@ void *edac_align_ptr(void **p, unsigned int size, int n_elems) + else + return (char *)ptr; + +- r = (unsigned long)p % align; ++ r = (unsigned long)ptr % align; + + if (r == 0) + return (char *)ptr; +diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c +index 83345bfac246f..6cf50ee0b77c5 100644 +--- a/drivers/edac/i10nm_base.c ++++ b/drivers/edac/i10nm_base.c +@@ -358,6 +358,9 @@ static int i10nm_get_hbm_munits(void) + + mbase = ioremap(base + off, I10NM_HBM_IMC_MMIO_SIZE); + if (!mbase) { ++ pci_dev_put(d->imc[lmc].mdev); ++ d->imc[lmc].mdev = NULL; ++ + i10nm_printk(KERN_ERR, "Failed to ioremap for hbm mc 0x%llx\n", + base + off); + return -ENOMEM; +@@ -368,6 +371,12 @@ static int i10nm_get_hbm_munits(void) + + mcmtr = I10NM_GET_MCMTR(&d->imc[lmc], 0); + if (!I10NM_IS_HBM_IMC(mcmtr)) { ++ iounmap(d->imc[lmc].mbase); ++ d->imc[lmc].mbase = NULL; ++ d->imc[lmc].hbm_mc = false; ++ pci_dev_put(d->imc[lmc].mdev); ++ d->imc[lmc].mdev = NULL; ++ + i10nm_printk(KERN_ERR, "This isn't an hbm mc!\n"); + return -ENODEV; + } +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index 4c626fcd4dcbb..1522d4aa2ca62 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -1052,7 +1052,7 @@ static u64 haswell_get_tohm(struct sbridge_pvt *pvt) + pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, ®); + rc = ((reg << 6) | rc) << 26; + +- return rc | 0x1ffffff; ++ return rc | 0x3ffffff; + } + + static u64 knl_get_tolm(struct sbridge_pvt *pvt) +diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c +index 7d08627e738b3..a5486d86fdd2f 100644 +--- a/drivers/edac/synopsys_edac.c ++++ b/drivers/edac/synopsys_edac.c +@@ -1352,8 +1352,7 @@ static int mc_probe(struct platform_device *pdev) + } + } + +- if (of_device_is_compatible(pdev->dev.of_node, +- "xlnx,zynqmp-ddrc-2.40a")) ++ if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) + setup_address_map(priv); + #endif + +diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c +index 2ccd1db5e98ff..7197f9fa02457 100644 +--- a/drivers/edac/xgene_edac.c ++++ b/drivers/edac/xgene_edac.c +@@ -1919,7 +1919,7 @@ static int xgene_edac_probe(struct platform_device *pdev) + irq = platform_get_irq_optional(pdev, i); + if (irq < 0) { + dev_err(&pdev->dev, "No IRQ resource\n"); +- rc = -EINVAL; ++ rc = irq; + goto out_err; + } + rc = devm_request_irq(&pdev->dev, irq, +diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c +index de416f9e79213..f5219334fd3a5 100644 +--- a/drivers/firmware/arm_scmi/base.c ++++ b/drivers/firmware/arm_scmi/base.c +@@ -34,6 +34,12 @@ struct scmi_msg_resp_base_attributes { + __le16 reserved; + }; + ++struct scmi_msg_resp_base_discover_agent { ++ __le32 agent_id; ++ u8 name[SCMI_MAX_STR_SIZE]; ++}; ++ ++ + struct scmi_msg_base_error_notify { + __le32 event_control; + #define BASE_TP_NOTIFY_ALL BIT(0) +@@ -225,18 +231,21 @@ static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph, + int id, char *name) + { + int ret; ++ struct scmi_msg_resp_base_discover_agent *agent_info; + struct scmi_xfer *t; + + ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT, +- sizeof(__le32), SCMI_MAX_STR_SIZE, &t); ++ sizeof(__le32), sizeof(*agent_info), &t); + if (ret) + return ret; + + put_unaligned_le32(id, t->tx.buf); + + ret = ph->xops->do_xfer(ph, t); +- if (!ret) +- strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE); ++ if (!ret) { ++ agent_info = t->rx.buf; ++ strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE); ++ } + + ph->xops->xfer_put(ph, t); + +diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c +index b406b3f78f467..d76bab3aaac45 100644 +--- a/drivers/firmware/arm_scmi/driver.c ++++ b/drivers/firmware/arm_scmi/driver.c +@@ -2112,7 +2112,7 @@ static void __exit scmi_driver_exit(void) + } + module_exit(scmi_driver_exit); + +-MODULE_ALIAS("platform: arm-scmi"); ++MODULE_ALIAS("platform:arm-scmi"); + MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>"); + MODULE_DESCRIPTION("ARM SCMI protocol driver"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c +index 4371fdcd5a73f..581d34c957695 100644 +--- a/drivers/firmware/arm_scmi/scmi_pm_domain.c ++++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c +@@ -138,9 +138,7 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev) + scmi_pd_data->domains = domains; + scmi_pd_data->num_domains = num_domains; + +- of_genpd_add_provider_onecell(np, scmi_pd_data); +- +- return 0; ++ return of_genpd_add_provider_onecell(np, scmi_pd_data); + } + + static const struct scmi_device_id scmi_id_table[] = { +diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c +index 308471586381f..cdbb287bd8bcd 100644 +--- a/drivers/firmware/arm_scmi/sensors.c ++++ b/drivers/firmware/arm_scmi/sensors.c +@@ -637,7 +637,7 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph, + if (ret) + return ret; + +- put_unaligned_le32(cpu_to_le32(sensor_id), t->tx.buf); ++ put_unaligned_le32(sensor_id, t->tx.buf); + ret = ph->xops->do_xfer(ph, t); + if (!ret) { + struct sensors_info *si = ph->get_priv(ph); +diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c +index 11e8efb713751..87039c5c03fdb 100644 +--- a/drivers/firmware/arm_scmi/virtio.c ++++ b/drivers/firmware/arm_scmi/virtio.c +@@ -82,7 +82,8 @@ static bool scmi_vio_have_vq_rx(struct virtio_device *vdev) + } + + static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, +- struct scmi_vio_msg *msg) ++ struct scmi_vio_msg *msg, ++ struct device *dev) + { + struct scatterlist sg_in; + int rc; +@@ -94,8 +95,7 @@ static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, + + rc = virtqueue_add_inbuf(vioch->vqueue, &sg_in, 1, msg, GFP_ATOMIC); + if (rc) +- dev_err_once(vioch->cinfo->dev, +- "failed to add to virtqueue (%d)\n", rc); ++ dev_err_once(dev, "failed to add to virtqueue (%d)\n", rc); + else + virtqueue_kick(vioch->vqueue); + +@@ -108,7 +108,7 @@ static void scmi_finalize_message(struct scmi_vio_channel *vioch, + struct scmi_vio_msg *msg) + { + if (vioch->is_rx) { +- scmi_vio_feed_vq_rx(vioch, msg); ++ scmi_vio_feed_vq_rx(vioch, msg, vioch->cinfo->dev); + } else { + /* Here IRQs are assumed to be already disabled by the caller */ + spin_lock(&vioch->lock); +@@ -269,7 +269,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, + list_add_tail(&msg->list, &vioch->free_list); + spin_unlock_irqrestore(&vioch->lock, flags); + } else { +- scmi_vio_feed_vq_rx(vioch, msg); ++ scmi_vio_feed_vq_rx(vioch, msg, cinfo->dev); + } + } + +diff --git a/drivers/firmware/arm_scmi/voltage.c b/drivers/firmware/arm_scmi/voltage.c +index a5048956a0be9..ac08e819088bb 100644 +--- a/drivers/firmware/arm_scmi/voltage.c ++++ b/drivers/firmware/arm_scmi/voltage.c +@@ -156,7 +156,7 @@ static int scmi_voltage_descriptors_get(const struct scmi_protocol_handle *ph, + int cnt; + + cmd->domain_id = cpu_to_le32(v->id); +- cmd->level_index = desc_index; ++ cmd->level_index = cpu_to_le32(desc_index); + ret = ph->xops->do_xfer(ph, tl); + if (ret) + break; +diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c +index b19ce1a83f91a..b2c829e95bd14 100644 +--- a/drivers/firmware/efi/efi-init.c ++++ b/drivers/firmware/efi/efi-init.c +@@ -235,6 +235,11 @@ void __init efi_init(void) + } + + reserve_regions(); ++ /* ++ * For memblock manipulation, the cap should come after the memblock_add(). ++ * And now, memblock is fully populated, it is time to do capping. ++ */ ++ early_init_dt_check_for_usable_mem_range(); + efi_esrt_init(); + efi_mokvar_table_init(); + +diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c +index 847f33ffc4aed..9fa86288b78a9 100644 +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -719,6 +719,13 @@ void __init efi_systab_report_header(const efi_table_hdr_t *systab_hdr, + systab_hdr->revision >> 16, + systab_hdr->revision & 0xffff, + vendor); ++ ++ if (IS_ENABLED(CONFIG_X86_64) && ++ systab_hdr->revision > EFI_1_10_SYSTEM_TABLE_REVISION && ++ !strcmp(vendor, "Apple")) { ++ pr_info("Apple Mac detected, using EFI v1.10 runtime services only\n"); ++ efi.runtime_version = EFI_1_10_SYSTEM_TABLE_REVISION; ++ } + } + + static __initdata char memory_type_name[][13] = { +diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c +index 2363fee9211c9..9cc556013d085 100644 +--- a/drivers/firmware/efi/libstub/arm64-stub.c ++++ b/drivers/firmware/efi/libstub/arm64-stub.c +@@ -119,9 +119,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, + if (image->image_base != _text) + efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n"); + +- if (!IS_ALIGNED((u64)_text, EFI_KIMG_ALIGN)) +- efi_err("FIRMWARE BUG: kernel image not aligned on %ldk boundary\n", +- EFI_KIMG_ALIGN >> 10); ++ if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN)) ++ efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n", ++ SEGMENT_ALIGN >> 10); + + kernel_size = _edata - _text; + kernel_memsize = kernel_size + (_end - _edata); +diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c +index 380e4e2513994..9c460843442f5 100644 +--- a/drivers/firmware/efi/libstub/riscv-stub.c ++++ b/drivers/firmware/efi/libstub/riscv-stub.c +@@ -25,7 +25,7 @@ typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long); + + static u32 hartid; + +-static u32 get_boot_hartid_from_fdt(void) ++static int get_boot_hartid_from_fdt(void) + { + const void *fdt; + int chosen_node, len; +@@ -33,23 +33,26 @@ static u32 get_boot_hartid_from_fdt(void) + + fdt = get_efi_config_table(DEVICE_TREE_GUID); + if (!fdt) +- return U32_MAX; ++ return -EINVAL; + + chosen_node = fdt_path_offset(fdt, "/chosen"); + if (chosen_node < 0) +- return U32_MAX; ++ return -EINVAL; + + prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len); + if (!prop || len != sizeof(u32)) +- return U32_MAX; ++ return -EINVAL; + +- return fdt32_to_cpu(*prop); ++ hartid = fdt32_to_cpu(*prop); ++ return 0; + } + + efi_status_t check_platform_features(void) + { +- hartid = get_boot_hartid_from_fdt(); +- if (hartid == U32_MAX) { ++ int ret; ++ ++ ret = get_boot_hartid_from_fdt(); ++ if (ret) { + efi_err("/chosen/boot-hartid missing or invalid!\n"); + return EFI_UNSUPPORTED; + } +diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c +index abdc8a6a39631..cae590bd08f27 100644 +--- a/drivers/firmware/efi/vars.c ++++ b/drivers/firmware/efi/vars.c +@@ -742,6 +742,7 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes, + { + const struct efivar_operations *ops; + efi_status_t status; ++ unsigned long varsize; + + if (!__efivars) + return -EINVAL; +@@ -764,15 +765,17 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes, + return efivar_entry_set_nonblocking(name, vendor, attributes, + size, data); + ++ varsize = size + ucs2_strsize(name, 1024); + if (!block) { + if (down_trylock(&efivars_lock)) + return -EBUSY; ++ status = check_var_size_nonblocking(attributes, varsize); + } else { + if (down_interruptible(&efivars_lock)) + return -EINTR; ++ status = check_var_size(attributes, varsize); + } + +- status = check_var_size(attributes, size + ucs2_strsize(name, 1024)); + if (status != EFI_SUCCESS) { + up(&efivars_lock); + return -ENOSPC; +diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig +index 97968aece54f8..931544c9f63d4 100644 +--- a/drivers/firmware/google/Kconfig ++++ b/drivers/firmware/google/Kconfig +@@ -3,9 +3,9 @@ menuconfig GOOGLE_FIRMWARE + bool "Google Firmware Drivers" + default n + help +- These firmware drivers are used by Google's servers. They are +- only useful if you are working directly on one of their +- proprietary servers. If in doubt, say "N". ++ These firmware drivers are used by Google servers, ++ Chromebooks and other devices using coreboot firmware. ++ If in doubt, say "N". + + if GOOGLE_FIRMWARE + +diff --git a/drivers/firmware/psci/psci_checker.c b/drivers/firmware/psci/psci_checker.c +index 9a369a2eda71d..116eb465cdb42 100644 +--- a/drivers/firmware/psci/psci_checker.c ++++ b/drivers/firmware/psci/psci_checker.c +@@ -155,7 +155,7 @@ static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups) + if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) + return -ENOMEM; + +- cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups), ++ cpu_groups = kcalloc(nb_available_cpus, sizeof(*cpu_groups), + GFP_KERNEL); + if (!cpu_groups) { + free_cpumask_var(tmp); +diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c +index 2ee97bab74409..27a64de919817 100644 +--- a/drivers/firmware/qcom_scm.c ++++ b/drivers/firmware/qcom_scm.c +@@ -252,7 +252,7 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id, + break; + default: + pr_err("Unknown SMC convention being used\n"); +- return -EINVAL; ++ return false; + } + + ret = qcom_scm_call(dev, &desc, &res); +diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c +index 172c751a4f6c2..f08e056ed0ae4 100644 +--- a/drivers/firmware/qemu_fw_cfg.c ++++ b/drivers/firmware/qemu_fw_cfg.c +@@ -388,9 +388,7 @@ static void fw_cfg_sysfs_cache_cleanup(void) + struct fw_cfg_sysfs_entry *entry, *next; + + list_for_each_entry_safe(entry, next, &fw_cfg_entry_cache, list) { +- /* will end up invoking fw_cfg_sysfs_cache_delist() +- * via each object's release() method (i.e. destructor) +- */ ++ fw_cfg_sysfs_cache_delist(entry); + kobject_put(&entry->kobj); + } + } +@@ -448,7 +446,6 @@ static void fw_cfg_sysfs_release_entry(struct kobject *kobj) + { + struct fw_cfg_sysfs_entry *entry = to_entry(kobj); + +- fw_cfg_sysfs_cache_delist(entry); + kfree(entry); + } + +@@ -601,20 +598,18 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f) + /* set file entry information */ + entry->size = be32_to_cpu(f->size); + entry->select = be16_to_cpu(f->select); +- memcpy(entry->name, f->name, FW_CFG_MAX_FILE_PATH); ++ strscpy(entry->name, f->name, FW_CFG_MAX_FILE_PATH); + + /* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */ + err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype, + fw_cfg_sel_ko, "%d", entry->select); +- if (err) { +- kobject_put(&entry->kobj); +- return err; +- } ++ if (err) ++ goto err_put_entry; + + /* add raw binary content access */ + err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw); + if (err) +- goto err_add_raw; ++ goto err_del_entry; + + /* try adding "/sys/firmware/qemu_fw_cfg/by_name/" symlink */ + fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->name); +@@ -623,9 +618,10 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f) + fw_cfg_sysfs_cache_enlist(entry); + return 0; + +-err_add_raw: ++err_del_entry: + kobject_del(&entry->kobj); +- kfree(entry); ++err_put_entry: ++ kobject_put(&entry->kobj); + return err; + } + +diff --git a/drivers/firmware/scpi_pm_domain.c b/drivers/firmware/scpi_pm_domain.c +index 51201600d789b..800673910b511 100644 +--- a/drivers/firmware/scpi_pm_domain.c ++++ b/drivers/firmware/scpi_pm_domain.c +@@ -16,7 +16,6 @@ struct scpi_pm_domain { + struct generic_pm_domain genpd; + struct scpi_ops *ops; + u32 domain; +- char name[30]; + }; + + /* +@@ -110,8 +109,13 @@ static int scpi_pm_domain_probe(struct platform_device *pdev) + + scpi_pd->domain = i; + scpi_pd->ops = scpi_ops; +- sprintf(scpi_pd->name, "%pOFn.%d", np, i); +- scpi_pd->genpd.name = scpi_pd->name; ++ scpi_pd->genpd.name = devm_kasprintf(dev, GFP_KERNEL, ++ "%pOFn.%d", np, i); ++ if (!scpi_pd->genpd.name) { ++ dev_err(dev, "Failed to allocate genpd name:%pOFn.%d\n", ++ np, i); ++ continue; ++ } + scpi_pd->genpd.power_off = scpi_pd_power_off; + scpi_pd->genpd.power_on = scpi_pd_power_on; + +diff --git a/drivers/firmware/smccc/soc_id.c b/drivers/firmware/smccc/soc_id.c +index 581aa5e9b0778..dd7c3d5e8b0bb 100644 +--- a/drivers/firmware/smccc/soc_id.c ++++ b/drivers/firmware/smccc/soc_id.c +@@ -50,7 +50,7 @@ static int __init smccc_soc_init(void) + arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_SOC_ID, &res); + +- if (res.a0 == SMCCC_RET_NOT_SUPPORTED) { ++ if ((int)res.a0 == SMCCC_RET_NOT_SUPPORTED) { + pr_info("ARCH_SOC_ID not implemented, skipping ....\n"); + return 0; + } +diff --git a/drivers/firmware/sysfb_simplefb.c b/drivers/firmware/sysfb_simplefb.c +index b86761904949c..303a491e520d1 100644 +--- a/drivers/firmware/sysfb_simplefb.c ++++ b/drivers/firmware/sysfb_simplefb.c +@@ -113,12 +113,16 @@ __init int sysfb_create_simplefb(const struct screen_info *si, + sysfb_apply_efi_quirks(pd); + + ret = platform_device_add_resources(pd, &res, 1); +- if (ret) ++ if (ret) { ++ platform_device_put(pd); + return ret; ++ } + + ret = platform_device_add_data(pd, mode, sizeof(*mode)); +- if (ret) ++ if (ret) { ++ platform_device_put(pd); + return ret; ++ } + + return platform_device_add(pd); + } +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index fae5141251e5d..947474f6abb45 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -523,6 +523,7 @@ config GPIO_REG + config GPIO_ROCKCHIP + tristate "Rockchip GPIO support" + depends on ARCH_ROCKCHIP || COMPILE_TEST ++ select GENERIC_IRQ_CHIP + select GPIOLIB_IRQCHIP + default ARCH_ROCKCHIP + help +diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c +index 34e35b64dcdc0..23047dc84ef1b 100644 +--- a/drivers/gpio/gpio-aggregator.c ++++ b/drivers/gpio/gpio-aggregator.c +@@ -273,7 +273,8 @@ static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset) + { + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + +- return gpiod_get_value(fwd->descs[offset]); ++ return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset]) ++ : gpiod_get_value(fwd->descs[offset]); + } + + static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, +@@ -292,7 +293,10 @@ static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, + for_each_set_bit(i, mask, fwd->chip.ngpio) + descs[j++] = fwd->descs[i]; + +- error = gpiod_get_array_value(j, descs, NULL, values); ++ if (fwd->chip.can_sleep) ++ error = gpiod_get_array_value_cansleep(j, descs, NULL, values); ++ else ++ error = gpiod_get_array_value(j, descs, NULL, values); + if (error) + return error; + +@@ -327,7 +331,10 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) + { + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + +- gpiod_set_value(fwd->descs[offset], value); ++ if (chip->can_sleep) ++ gpiod_set_value_cansleep(fwd->descs[offset], value); ++ else ++ gpiod_set_value(fwd->descs[offset], value); + } + + static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, +@@ -346,7 +353,10 @@ static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, + descs[j++] = fwd->descs[i]; + } + +- gpiod_set_array_value(j, descs, NULL, values); ++ if (fwd->chip.can_sleep) ++ gpiod_set_array_value_cansleep(j, descs, NULL, values); ++ else ++ gpiod_set_array_value(j, descs, NULL, values); + } + + static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip, +diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c +index 3d6ef37a7702a..454cefbeecf0e 100644 +--- a/drivers/gpio/gpio-aspeed-sgpio.c ++++ b/drivers/gpio/gpio-aspeed-sgpio.c +@@ -31,7 +31,7 @@ struct aspeed_sgpio { + struct gpio_chip chip; + struct irq_chip intc; + struct clk *pclk; +- spinlock_t lock; ++ raw_spinlock_t lock; + void __iomem *base; + int irq; + }; +@@ -173,12 +173,12 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) + enum aspeed_sgpio_reg reg; + int rc = 0; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata; + rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset)); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; + } +@@ -215,11 +215,11 @@ static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + sgpio_set_value(gc, offset, val); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + } + + static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset) +@@ -236,9 +236,9 @@ static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int v + /* No special action is required for setting the direction; we'll + * error-out in sgpio_set_value if this isn't an output GPIO */ + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + rc = sgpio_set_value(gc, offset, val); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; + } +@@ -277,11 +277,11 @@ static void aspeed_sgpio_irq_ack(struct irq_data *d) + + status_addr = bank_reg(gpio, bank, reg_irq_status); + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + iowrite32(bit, status_addr); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + } + + static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) +@@ -296,7 +296,7 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + addr = bank_reg(gpio, bank, reg_irq_enable); + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + reg = ioread32(addr); + if (set) +@@ -306,7 +306,7 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) + + iowrite32(reg, addr); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + } + + static void aspeed_sgpio_irq_mask(struct irq_data *d) +@@ -355,7 +355,7 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type) + return -EINVAL; + } + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + addr = bank_reg(gpio, bank, reg_irq_type0); + reg = ioread32(addr); +@@ -372,7 +372,7 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type) + reg = (reg & ~bit) | type2; + iowrite32(reg, addr); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + irq_set_handler_locked(d, handler); + +@@ -395,7 +395,7 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc) + reg = ioread32(bank_reg(data, bank, reg_irq_status)); + + for_each_set_bit(p, ®, 32) +- generic_handle_domain_irq(gc->irq.domain, i * 32 + p * 2); ++ generic_handle_domain_irq(gc->irq.domain, (i * 32 + p) * 2); + } + + chained_irq_exit(ic, desc); +@@ -467,7 +467,7 @@ static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip, + + reg = bank_reg(gpio, to_bank(offset), reg_tolerance); + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + val = readl(reg); + +@@ -478,7 +478,7 @@ static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip, + + writel(val, reg); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; + } +@@ -575,7 +575,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) + iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval | + ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL); + +- spin_lock_init(&gpio->lock); ++ raw_spin_lock_init(&gpio->lock); + + gpio->chip.parent = &pdev->dev; + gpio->chip.ngpio = nr_gpios * 2; +diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c +index 3c8f20c57695f..318a7d95a1a8b 100644 +--- a/drivers/gpio/gpio-aspeed.c ++++ b/drivers/gpio/gpio-aspeed.c +@@ -53,7 +53,7 @@ struct aspeed_gpio_config { + struct aspeed_gpio { + struct gpio_chip chip; + struct irq_chip irqc; +- spinlock_t lock; ++ raw_spinlock_t lock; + void __iomem *base; + int irq; + const struct aspeed_gpio_config *config; +@@ -413,14 +413,14 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, + unsigned long flags; + bool copro; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + copro = aspeed_gpio_copro_request(gpio, offset); + + __aspeed_gpio_set(gc, offset, val); + + if (copro) + aspeed_gpio_copro_release(gpio, offset); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + } + + static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) +@@ -435,7 +435,7 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) + if (!have_input(gpio, offset)) + return -ENOTSUPP; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + reg = ioread32(addr); + reg &= ~GPIO_BIT(offset); +@@ -445,7 +445,7 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) + if (copro) + aspeed_gpio_copro_release(gpio, offset); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; + } +@@ -463,7 +463,7 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc, + if (!have_output(gpio, offset)) + return -ENOTSUPP; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + reg = ioread32(addr); + reg |= GPIO_BIT(offset); +@@ -474,7 +474,7 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc, + + if (copro) + aspeed_gpio_copro_release(gpio, offset); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; + } +@@ -492,11 +492,11 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) + if (!have_output(gpio, offset)) + return GPIO_LINE_DIRECTION_IN; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return val ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; + } +@@ -539,14 +539,14 @@ static void aspeed_gpio_irq_ack(struct irq_data *d) + + status_addr = bank_reg(gpio, bank, reg_irq_status); + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + copro = aspeed_gpio_copro_request(gpio, offset); + + iowrite32(bit, status_addr); + + if (copro) + aspeed_gpio_copro_release(gpio, offset); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + } + + static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set) +@@ -565,7 +565,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set) + + addr = bank_reg(gpio, bank, reg_irq_enable); + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + copro = aspeed_gpio_copro_request(gpio, offset); + + reg = ioread32(addr); +@@ -577,7 +577,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set) + + if (copro) + aspeed_gpio_copro_release(gpio, offset); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + } + + static void aspeed_gpio_irq_mask(struct irq_data *d) +@@ -629,7 +629,7 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type) + return -EINVAL; + } + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + copro = aspeed_gpio_copro_request(gpio, offset); + + addr = bank_reg(gpio, bank, reg_irq_type0); +@@ -649,7 +649,7 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type) + + if (copro) + aspeed_gpio_copro_release(gpio, offset); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + irq_set_handler_locked(d, handler); + +@@ -716,7 +716,7 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip, + + treg = bank_reg(gpio, to_bank(offset), reg_tolerance); + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + copro = aspeed_gpio_copro_request(gpio, offset); + + val = readl(treg); +@@ -730,7 +730,7 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip, + + if (copro) + aspeed_gpio_copro_release(gpio, offset); +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; + } +@@ -856,7 +856,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset, + return rc; + } + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + if (timer_allocation_registered(gpio, offset)) { + rc = unregister_allocated_timer(gpio, offset); +@@ -916,7 +916,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset, + configure_timer(gpio, offset, i); + + out: +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; + } +@@ -927,13 +927,13 @@ static int disable_debounce(struct gpio_chip *chip, unsigned int offset) + unsigned long flags; + int rc; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + rc = unregister_allocated_timer(gpio, offset); + if (!rc) + configure_timer(gpio, offset, 0); + +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; + } +@@ -1015,7 +1015,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc, + return -EINVAL; + bindex = offset >> 3; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + /* Sanity check, this shouldn't happen */ + if (gpio->cf_copro_bankmap[bindex] == 0xff) { +@@ -1036,7 +1036,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc, + if (bit) + *bit = GPIO_OFFSET(offset); + bail: +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + return rc; + } + EXPORT_SYMBOL_GPL(aspeed_gpio_copro_grab_gpio); +@@ -1060,7 +1060,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc) + return -EINVAL; + bindex = offset >> 3; + +- spin_lock_irqsave(&gpio->lock, flags); ++ raw_spin_lock_irqsave(&gpio->lock, flags); + + /* Sanity check, this shouldn't happen */ + if (gpio->cf_copro_bankmap[bindex] == 0) { +@@ -1074,7 +1074,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc) + aspeed_gpio_change_cmd_source(gpio, bank, bindex, + GPIO_CMDSRC_ARM); + bail: +- spin_unlock_irqrestore(&gpio->lock, flags); ++ raw_spin_unlock_irqrestore(&gpio->lock, flags); + return rc; + } + EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio); +@@ -1148,7 +1148,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); + +- spin_lock_init(&gpio->lock); ++ raw_spin_lock_init(&gpio->lock); + + gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node); + if (!gpio_id) +diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c +index 026903e3ef543..08b9e2cf4f2d6 100644 +--- a/drivers/gpio/gpio-dln2.c ++++ b/drivers/gpio/gpio-dln2.c +@@ -46,6 +46,7 @@ + struct dln2_gpio { + struct platform_device *pdev; + struct gpio_chip gpio; ++ struct irq_chip irqchip; + + /* + * Cache pin direction to save us one transfer, since the hardware has +@@ -383,15 +384,6 @@ static void dln2_irq_bus_unlock(struct irq_data *irqd) + mutex_unlock(&dln2->irq_lock); + } + +-static struct irq_chip dln2_gpio_irqchip = { +- .name = "dln2-irq", +- .irq_mask = dln2_irq_mask, +- .irq_unmask = dln2_irq_unmask, +- .irq_set_type = dln2_irq_set_type, +- .irq_bus_lock = dln2_irq_bus_lock, +- .irq_bus_sync_unlock = dln2_irq_bus_unlock, +-}; +- + static void dln2_gpio_event(struct platform_device *pdev, u16 echo, + const void *data, int len) + { +@@ -473,8 +465,15 @@ static int dln2_gpio_probe(struct platform_device *pdev) + dln2->gpio.direction_output = dln2_gpio_direction_output; + dln2->gpio.set_config = dln2_gpio_set_config; + ++ dln2->irqchip.name = "dln2-irq", ++ dln2->irqchip.irq_mask = dln2_irq_mask, ++ dln2->irqchip.irq_unmask = dln2_irq_unmask, ++ dln2->irqchip.irq_set_type = dln2_irq_set_type, ++ dln2->irqchip.irq_bus_lock = dln2_irq_bus_lock, ++ dln2->irqchip.irq_bus_sync_unlock = dln2_irq_bus_unlock, ++ + girq = &dln2->gpio.irq; +- girq->chip = &dln2_gpio_irqchip; ++ girq->chip = &dln2->irqchip; + /* The event comes from the outside so no parent handler */ + girq->parent_handler = NULL; + girq->num_parents = 0; +diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c +index 50003ad2e5898..52b8b72ded77f 100644 +--- a/drivers/gpio/gpio-idt3243x.c ++++ b/drivers/gpio/gpio-idt3243x.c +@@ -132,7 +132,7 @@ static int idt_gpio_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; + struct idt_gpio_ctrl *ctrl; +- unsigned int parent_irq; ++ int parent_irq; + int ngpios; + int ret; + +@@ -164,8 +164,8 @@ static int idt_gpio_probe(struct platform_device *pdev) + return PTR_ERR(ctrl->pic); + + parent_irq = platform_get_irq(pdev, 0); +- if (!parent_irq) +- return -EINVAL; ++ if (parent_irq < 0) ++ return parent_irq; + + girq = &ctrl->gc.irq; + girq->chip = &idt_gpio_irqchip; +diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c +index 70d6ae20b1da5..a964e25ea6206 100644 +--- a/drivers/gpio/gpio-mpc8xxx.c ++++ b/drivers/gpio/gpio-mpc8xxx.c +@@ -47,7 +47,7 @@ struct mpc8xxx_gpio_chip { + unsigned offset, int value); + + struct irq_domain *irq; +- unsigned int irqn; ++ int irqn; + }; + + /* +@@ -388,8 +388,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) + } + + mpc8xxx_gc->irqn = platform_get_irq(pdev, 0); +- if (!mpc8xxx_gc->irqn) +- return 0; ++ if (mpc8xxx_gc->irqn < 0) ++ return mpc8xxx_gc->irqn; + + mpc8xxx_gc->irq = irq_domain_create_linear(fwnode, + MPC8XXX_GPIO_PINS, +diff --git a/drivers/gpio/gpio-realtek-otto.c b/drivers/gpio/gpio-realtek-otto.c +index eeeb39bc171dc..bd75401b549d1 100644 +--- a/drivers/gpio/gpio-realtek-otto.c ++++ b/drivers/gpio/gpio-realtek-otto.c +@@ -205,7 +205,7 @@ static void realtek_gpio_irq_handler(struct irq_desc *desc) + status = realtek_gpio_read_isr(ctrl, lines_done / 8); + port_pin_count = min(gc->ngpio - lines_done, 8U); + for_each_set_bit(offset, &status, port_pin_count) +- generic_handle_domain_irq(gc->irq.domain, offset); ++ generic_handle_domain_irq(gc->irq.domain, offset + lines_done); + } + + chained_irq_exit(irq_chip, desc); +diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c +index ce63cbd14d69a..24155c038f6d0 100644 +--- a/drivers/gpio/gpio-rockchip.c ++++ b/drivers/gpio/gpio-rockchip.c +@@ -410,10 +410,8 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) + level = rockchip_gpio_readl(bank, bank->gpio_regs->int_type); + polarity = rockchip_gpio_readl(bank, bank->gpio_regs->int_polarity); + +- switch (type) { +- case IRQ_TYPE_EDGE_BOTH: ++ if (type == IRQ_TYPE_EDGE_BOTH) { + if (bank->gpio_type == GPIO_TYPE_V2) { +- bank->toggle_edge_mode &= ~mask; + rockchip_gpio_writel_bit(bank, d->hwirq, 1, + bank->gpio_regs->int_bothedge); + goto out; +@@ -431,30 +429,34 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) + else + polarity |= mask; + } +- break; +- case IRQ_TYPE_EDGE_RISING: +- bank->toggle_edge_mode &= ~mask; +- level |= mask; +- polarity |= mask; +- break; +- case IRQ_TYPE_EDGE_FALLING: +- bank->toggle_edge_mode &= ~mask; +- level |= mask; +- polarity &= ~mask; +- break; +- case IRQ_TYPE_LEVEL_HIGH: +- bank->toggle_edge_mode &= ~mask; +- level &= ~mask; +- polarity |= mask; +- break; +- case IRQ_TYPE_LEVEL_LOW: +- bank->toggle_edge_mode &= ~mask; +- level &= ~mask; +- polarity &= ~mask; +- break; +- default: +- ret = -EINVAL; +- goto out; ++ } else { ++ if (bank->gpio_type == GPIO_TYPE_V2) { ++ rockchip_gpio_writel_bit(bank, d->hwirq, 0, ++ bank->gpio_regs->int_bothedge); ++ } else { ++ bank->toggle_edge_mode &= ~mask; ++ } ++ switch (type) { ++ case IRQ_TYPE_EDGE_RISING: ++ level |= mask; ++ polarity |= mask; ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ level |= mask; ++ polarity &= ~mask; ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ level &= ~mask; ++ polarity |= mask; ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ level &= ~mask; ++ polarity &= ~mask; ++ break; ++ default: ++ ret = -EINVAL; ++ goto out; ++ } + } + + rockchip_gpio_writel(bank, level, bank->gpio_regs->int_type); +diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c +index 403f9e833d6a3..7d82388b4ab7c 100644 +--- a/drivers/gpio/gpio-sifive.c ++++ b/drivers/gpio/gpio-sifive.c +@@ -223,7 +223,7 @@ static int sifive_gpio_probe(struct platform_device *pdev) + NULL, + chip->base + SIFIVE_GPIO_OUTPUT_EN, + chip->base + SIFIVE_GPIO_INPUT_EN, +- 0); ++ BGPIOF_READ_OUTPUT_REG_SET); + if (ret) { + dev_err(dev, "unable to init generic GPIO\n"); + return ret; +diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c +index c99858f40a27e..00762de3d4096 100644 +--- a/drivers/gpio/gpio-tegra186.c ++++ b/drivers/gpio/gpio-tegra186.c +@@ -337,9 +337,12 @@ static int tegra186_gpio_of_xlate(struct gpio_chip *chip, + return offset + pin; + } + ++#define to_tegra_gpio(x) container_of((x), struct tegra_gpio, gpio) ++ + static void tegra186_irq_ack(struct irq_data *data) + { +- struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(data); ++ struct tegra_gpio *gpio = to_tegra_gpio(gc); + void __iomem *base; + + base = tegra186_gpio_get_base(gpio, data->hwirq); +@@ -351,7 +354,8 @@ static void tegra186_irq_ack(struct irq_data *data) + + static void tegra186_irq_mask(struct irq_data *data) + { +- struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(data); ++ struct tegra_gpio *gpio = to_tegra_gpio(gc); + void __iomem *base; + u32 value; + +@@ -366,7 +370,8 @@ static void tegra186_irq_mask(struct irq_data *data) + + static void tegra186_irq_unmask(struct irq_data *data) + { +- struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(data); ++ struct tegra_gpio *gpio = to_tegra_gpio(gc); + void __iomem *base; + u32 value; + +@@ -381,7 +386,8 @@ static void tegra186_irq_unmask(struct irq_data *data) + + static int tegra186_irq_set_type(struct irq_data *data, unsigned int type) + { +- struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data); ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(data); ++ struct tegra_gpio *gpio = to_tegra_gpio(gc); + void __iomem *base; + u32 value; + +diff --git a/drivers/gpio/gpio-virtio.c b/drivers/gpio/gpio-virtio.c +index d24f1c9264bc9..dd3b23c9580b1 100644 +--- a/drivers/gpio/gpio-virtio.c ++++ b/drivers/gpio/gpio-virtio.c +@@ -81,11 +81,7 @@ static int _virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio, + virtqueue_kick(vgpio->request_vq); + mutex_unlock(&vgpio->lock); + +- if (!wait_for_completion_timeout(&line->completion, HZ)) { +- dev_err(dev, "GPIO operation timed out\n"); +- ret = -ETIMEDOUT; +- goto out; +- } ++ wait_for_completion(&line->completion); + + if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) { + dev_err(dev, "GPIO request failed: %d\n", gpio); +diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c +index 47712b6903b51..d040c72fea582 100644 +--- a/drivers/gpio/gpiolib-acpi.c ++++ b/drivers/gpio/gpiolib-acpi.c +@@ -1059,10 +1059,17 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind + irq_flags = acpi_dev_get_irq_type(info.triggering, + info.polarity); + +- /* Set type if specified and different than the current one */ +- if (irq_flags != IRQ_TYPE_NONE && +- irq_flags != irq_get_trigger_type(irq)) +- irq_set_irq_type(irq, irq_flags); ++ /* ++ * If the IRQ is not already in use then set type ++ * if specified and different than the current one. ++ */ ++ if (can_request_irq(irq, irq_flags)) { ++ if (irq_flags != IRQ_TYPE_NONE && ++ irq_flags != irq_get_trigger_type(irq)) ++ irq_set_irq_type(irq, irq_flags); ++ } else { ++ dev_dbg(&adev->dev, "IRQ %d already in use\n", irq); ++ } + + return irq; + } +diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c +index c7b5446d01fd2..ffa0256cad5a0 100644 +--- a/drivers/gpio/gpiolib-cdev.c ++++ b/drivers/gpio/gpiolib-cdev.c +@@ -330,7 +330,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) + goto out_free_lh; + } + +- ret = gpiod_request(desc, lh->label); ++ ret = gpiod_request_user(desc, lh->label); + if (ret) + goto out_free_lh; + lh->descs[i] = desc; +@@ -1378,7 +1378,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) + goto out_free_linereq; + } + +- ret = gpiod_request(desc, lr->label); ++ ret = gpiod_request_user(desc, lr->label); + if (ret) + goto out_free_linereq; + +@@ -1764,7 +1764,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) + } + } + +- ret = gpiod_request(desc, le->label); ++ ret = gpiod_request_user(desc, le->label); + if (ret) + goto out_free_le; + le->desc = desc; +diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c +index 4098bc7f88b7e..44c1ad51b3fe9 100644 +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -475,12 +475,9 @@ static ssize_t export_store(struct class *class, + * they may be undone on its behalf too. + */ + +- status = gpiod_request(desc, "sysfs"); +- if (status) { +- if (status == -EPROBE_DEFER) +- status = -ENODEV; ++ status = gpiod_request_user(desc, "sysfs"); ++ if (status) + goto done; +- } + + status = gpiod_set_transitory(desc, false); + if (!status) { +diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h +index 30bc3f80f83e6..c31f4626915de 100644 +--- a/drivers/gpio/gpiolib.h ++++ b/drivers/gpio/gpiolib.h +@@ -135,6 +135,18 @@ struct gpio_desc { + + int gpiod_request(struct gpio_desc *desc, const char *label); + void gpiod_free(struct gpio_desc *desc); ++ ++static inline int gpiod_request_user(struct gpio_desc *desc, const char *label) ++{ ++ int ret; ++ ++ ret = gpiod_request(desc, label); ++ if (ret == -EPROBE_DEFER) ++ ret = -ENODEV; ++ ++ return ret; ++} ++ + int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, + unsigned long lflags, enum gpiod_flags dflags); + int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 269437b013280..7e73ac6fb21db 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1069,6 +1069,7 @@ struct amdgpu_device { + bool runpm; + bool in_runpm; + bool has_pr3; ++ bool is_fw_fb; + + bool pm_sysfs_en; + bool ucode_sysfs_en; +@@ -1078,8 +1079,6 @@ struct amdgpu_device { + char product_name[32]; + char serial[20]; + +- struct amdgpu_autodump autodump; +- + atomic_t throttling_logging_enabled; + struct ratelimit_state throttling_logging_rs; + uint32_t ras_hw_enabled; +@@ -1398,12 +1397,10 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta + int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); + + void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); +-bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); + void amdgpu_acpi_detect(void); + #else + static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } + static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } +-static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } + static inline void amdgpu_acpi_detect(void) { } + static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } + static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, +@@ -1412,6 +1409,14 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev, + enum amdgpu_ss ss_state) { return 0; } + #endif + ++#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) ++bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); ++bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); ++#else ++static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } ++static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } ++#endif ++ + int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, + uint64_t addr, struct amdgpu_bo **bo, + struct amdgpu_bo_va_mapping **mapping); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +index 4811b0faafd9a..0e12315fa0cb8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +@@ -1031,6 +1031,20 @@ void amdgpu_acpi_detect(void) + } + } + ++#if IS_ENABLED(CONFIG_SUSPEND) ++/** ++ * amdgpu_acpi_is_s3_active ++ * ++ * @adev: amdgpu_device_pointer ++ * ++ * returns true if supported, false if not. ++ */ ++bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) ++{ ++ return !(adev->flags & AMD_IS_APU) || ++ (pm_suspend_target_state == PM_SUSPEND_MEM); ++} ++ + /** + * amdgpu_acpi_is_s0ix_active + * +@@ -1040,11 +1054,24 @@ void amdgpu_acpi_detect(void) + */ + bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) + { +-#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) +- if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { +- if (adev->flags & AMD_IS_APU) +- return pm_suspend_target_state == PM_SUSPEND_TO_IDLE; ++ if (!(adev->flags & AMD_IS_APU) || ++ (pm_suspend_target_state != PM_SUSPEND_TO_IDLE)) ++ return false; ++ ++ if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { ++ dev_warn_once(adev->dev, ++ "Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n" ++ "To use suspend-to-idle change the sleep mode in BIOS setup.\n"); ++ return false; + } +-#endif ++ ++#if !IS_ENABLED(CONFIG_AMD_PMC) ++ dev_warn_once(adev->dev, ++ "Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n"); + return false; ++#else ++ return true; ++#endif /* CONFIG_AMD_PMC */ + } ++ ++#endif /* CONFIG_SUSPEND */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 054c1a224defb..ab36cce59d2e4 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1393,7 +1393,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( + struct sg_table *sg = NULL; + uint64_t user_addr = 0; + struct amdgpu_bo *bo; +- struct drm_gem_object *gobj; ++ struct drm_gem_object *gobj = NULL; + u32 domain, alloc_domain; + u64 alloc_flags; + int ret; +@@ -1503,14 +1503,16 @@ allocate_init_user_pages_failed: + remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info); + drm_vma_node_revoke(&gobj->vma_node, drm_priv); + err_node_allow: +- amdgpu_bo_unref(&bo); + /* Don't unreserve system mem limit twice */ + goto err_reserve_limit; + err_bo_create: + unreserve_mem_limit(adev, size, alloc_domain, !!sg); + err_reserve_limit: + mutex_destroy(&(*mem)->lock); +- kfree(*mem); ++ if (gobj) ++ drm_gem_object_put(gobj); ++ else ++ kfree(*mem); + err: + if (sg) { + sg_free_table(sg); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +index 15c45b2a39835..714178f1b6c6e 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +@@ -61,7 +61,7 @@ static void amdgpu_bo_list_free(struct kref *ref) + + int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, + struct drm_amdgpu_bo_list_entry *info, +- unsigned num_entries, struct amdgpu_bo_list **result) ++ size_t num_entries, struct amdgpu_bo_list **result) + { + unsigned last_entry = 0, first_userptr = num_entries; + struct amdgpu_bo_list_entry *array; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +index c905a4cfc173d..044b41f0bfd9c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +@@ -61,7 +61,7 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, + int amdgpu_bo_list_create(struct amdgpu_device *adev, + struct drm_file *filp, + struct drm_amdgpu_bo_list_entry *info, +- unsigned num_entries, ++ size_t num_entries, + struct amdgpu_bo_list **list); + + static inline struct amdgpu_bo_list_entry * +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +index b9c11c2b2885a..df1f9b88a53f9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +@@ -387,6 +387,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder) + native_mode->vdisplay != 0 && + native_mode->clock != 0) { + mode = drm_mode_duplicate(dev, native_mode); ++ if (!mode) ++ return NULL; ++ + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + drm_mode_set_name(mode); + +@@ -401,6 +404,9 @@ amdgpu_connector_lcd_native_mode(struct drm_encoder *encoder) + * simpler. + */ + mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false); ++ if (!mode) ++ return NULL; ++ + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name); + } +@@ -827,6 +833,7 @@ static int amdgpu_connector_vga_get_modes(struct drm_connector *connector) + + amdgpu_connector_get_edid(connector); + ret = amdgpu_connector_ddc_get_modes(connector); ++ amdgpu_get_native_mode(connector); + + return ret; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +index 463b9c0283f7e..ec30d81586a79 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +@@ -27,7 +27,6 @@ + #include <linux/pci.h> + #include <linux/uaccess.h> + #include <linux/pm_runtime.h> +-#include <linux/poll.h> + + #include "amdgpu.h" + #include "amdgpu_pm.h" +@@ -37,85 +36,7 @@ + #include "amdgpu_securedisplay.h" + #include "amdgpu_fw_attestation.h" + +-int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev) +-{ + #if defined(CONFIG_DEBUG_FS) +- unsigned long timeout = 600 * HZ; +- int ret; +- +- wake_up_interruptible(&adev->autodump.gpu_hang); +- +- ret = wait_for_completion_interruptible_timeout(&adev->autodump.dumping, timeout); +- if (ret == 0) { +- pr_err("autodump: timeout, move on to gpu recovery\n"); +- return -ETIMEDOUT; +- } +-#endif +- return 0; +-} +- +-#if defined(CONFIG_DEBUG_FS) +- +-static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) +-{ +- struct amdgpu_device *adev = inode->i_private; +- int ret; +- +- file->private_data = adev; +- +- ret = down_read_killable(&adev->reset_sem); +- if (ret) +- return ret; +- +- if (adev->autodump.dumping.done) { +- reinit_completion(&adev->autodump.dumping); +- ret = 0; +- } else { +- ret = -EBUSY; +- } +- +- up_read(&adev->reset_sem); +- +- return ret; +-} +- +-static int amdgpu_debugfs_autodump_release(struct inode *inode, struct file *file) +-{ +- struct amdgpu_device *adev = file->private_data; +- +- complete_all(&adev->autodump.dumping); +- return 0; +-} +- +-static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_table_struct *poll_table) +-{ +- struct amdgpu_device *adev = file->private_data; +- +- poll_wait(file, &adev->autodump.gpu_hang, poll_table); +- +- if (amdgpu_in_reset(adev)) +- return POLLIN | POLLRDNORM | POLLWRNORM; +- +- return 0; +-} +- +-static const struct file_operations autodump_debug_fops = { +- .owner = THIS_MODULE, +- .open = amdgpu_debugfs_autodump_open, +- .poll = amdgpu_debugfs_autodump_poll, +- .release = amdgpu_debugfs_autodump_release, +-}; +- +-static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev) +-{ +- init_completion(&adev->autodump.dumping); +- complete_all(&adev->autodump.dumping); +- init_waitqueue_head(&adev->autodump.gpu_hang); +- +- debugfs_create_file("amdgpu_autodump", 0600, +- adev_to_drm(adev)->primary->debugfs_root, +- adev, &autodump_debug_fops); +-} + + /** + * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes +@@ -1588,7 +1509,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) + } + + amdgpu_ras_debugfs_create_all(adev); +- amdgpu_debugfs_autodump_init(adev); + amdgpu_rap_debugfs_init(adev); + amdgpu_securedisplay_debugfs_init(adev); + amdgpu_fw_attestation_debugfs_init(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h +index 141a8474e24f2..8b641f40fdf66 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h +@@ -26,10 +26,6 @@ + /* + * Debugfs + */ +-struct amdgpu_autodump { +- struct completion dumping; +- struct wait_queue_head gpu_hang; +-}; + + int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); + int amdgpu_debugfs_init(struct amdgpu_device *adev); +@@ -37,4 +33,3 @@ void amdgpu_debugfs_fini(struct amdgpu_device *adev); + void amdgpu_debugfs_fence_init(struct amdgpu_device *adev); + void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev); + void amdgpu_debugfs_gem_init(struct amdgpu_device *adev); +-int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index af9bdf16eefd4..1545884dc703e 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -2394,6 +2394,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) + if (r) + goto init_failed; + ++ r = amdgpu_amdkfd_resume_iommu(adev); ++ if (r) ++ goto init_failed; ++ + r = amdgpu_device_ip_hw_init_phase1(adev); + if (r) + goto init_failed; +@@ -2432,10 +2436,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) + if (!adev->gmc.xgmi.pending_reset) + amdgpu_amdkfd_device_init(adev); + +- r = amdgpu_amdkfd_resume_iommu(adev); +- if (r) +- goto init_failed; +- + amdgpu_fru_get_product_info(adev); + + init_failed: +@@ -2745,6 +2745,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev) + adev->ip_blocks[i].status.hw = false; + } + ++ if (amdgpu_sriov_vf(adev)) { ++ if (amdgpu_virt_release_full_gpu(adev, false)) ++ DRM_ERROR("failed to release exclusive mode on fini\n"); ++ } ++ + return 0; + } + +@@ -2805,10 +2810,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) + + amdgpu_ras_fini(adev); + +- if (amdgpu_sriov_vf(adev)) +- if (amdgpu_virt_release_full_gpu(adev, false)) +- DRM_ERROR("failed to release exclusive mode on fini\n"); +- + return 0; + } + +@@ -3531,6 +3532,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, + adev->rmmio_size = pci_resource_len(adev->pdev, 2); + } + ++ for (i = 0; i < AMD_IP_BLOCK_TYPE_NUM; i++) ++ atomic_set(&adev->pm.pwr_state[i], POWER_STATE_UNKNOWN); ++ + adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size); + if (adev->rmmio == NULL) { + return -ENOMEM; +@@ -3850,7 +3854,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) + /* disable all interrupts */ + amdgpu_irq_disable_all(adev); + if (adev->mode_info.mode_config_initialized){ +- if (!amdgpu_device_has_dc_support(adev)) ++ if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev))) + drm_helper_force_disable_all(adev_to_drm(adev)); + else + drm_atomic_helper_shutdown(adev_to_drm(adev)); +@@ -3876,8 +3880,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) + + void amdgpu_device_fini_sw(struct amdgpu_device *adev) + { +- amdgpu_device_ip_fini(adev); + amdgpu_fence_driver_sw_fini(adev); ++ amdgpu_device_ip_fini(adev); + release_firmware(adev->firmware.gpu_info_fw); + adev->firmware.gpu_info_fw = NULL; + adev->accel_working = false; +@@ -4466,10 +4470,6 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, + if (reset_context->reset_req_dev == adev) + job = reset_context->job; + +- /* no need to dump if device is not in good state during probe period */ +- if (!adev->gmc.xgmi.pending_reset) +- amdgpu_debugfs_wait_dump(adev); +- + if (amdgpu_sriov_vf(adev)) { + /* stop the data exchange thread */ + amdgpu_virt_fini_data_exchange(adev); +@@ -5130,7 +5130,7 @@ skip_hw_reset: + drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); + } + +- if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { ++ if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { + drm_helper_resume_force_mode(adev_to_drm(tmp_adev)); + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +index ada7bc19118ac..a919f5daacd91 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +@@ -415,10 +415,15 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev) + } + } + ++union gc_info { ++ struct gc_info_v1_0 v1; ++ struct gc_info_v2_0 v2; ++}; ++ + int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev) + { + struct binary_header *bhdr; +- struct gc_info_v1_0 *gc_info; ++ union gc_info *gc_info; + + if (!adev->mman.discovery_bin) { + DRM_ERROR("ip discovery uninitialized\n"); +@@ -426,27 +431,54 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev) + } + + bhdr = (struct binary_header *)adev->mman.discovery_bin; +- gc_info = (struct gc_info_v1_0 *)(adev->mman.discovery_bin + ++ gc_info = (union gc_info *)(adev->mman.discovery_bin + + le16_to_cpu(bhdr->table_list[GC].offset)); +- +- adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->gc_num_se); +- adev->gfx.config.max_cu_per_sh = 2 * (le32_to_cpu(gc_info->gc_num_wgp0_per_sa) + +- le32_to_cpu(gc_info->gc_num_wgp1_per_sa)); +- adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->gc_num_sa_per_se); +- adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->gc_num_rb_per_se); +- adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->gc_num_gl2c); +- adev->gfx.config.max_gprs = le32_to_cpu(gc_info->gc_num_gprs); +- adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->gc_num_max_gs_thds); +- adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->gc_gs_table_depth); +- adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->gc_gsprim_buff_depth); +- adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->gc_double_offchip_lds_buffer); +- adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->gc_wave_size); +- adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->gc_max_waves_per_simd); +- adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->gc_max_scratch_slots_per_cu); +- adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->gc_lds_size); +- adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->gc_num_sc_per_se) / +- le32_to_cpu(gc_info->gc_num_sa_per_se); +- adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->gc_num_packer_per_sc); +- ++ switch (gc_info->v1.header.version_major) { ++ case 1: ++ adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v1.gc_num_se); ++ adev->gfx.config.max_cu_per_sh = 2 * (le32_to_cpu(gc_info->v1.gc_num_wgp0_per_sa) + ++ le32_to_cpu(gc_info->v1.gc_num_wgp1_per_sa)); ++ adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->v1.gc_num_sa_per_se); ++ adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->v1.gc_num_rb_per_se); ++ adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->v1.gc_num_gl2c); ++ adev->gfx.config.max_gprs = le32_to_cpu(gc_info->v1.gc_num_gprs); ++ adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->v1.gc_num_max_gs_thds); ++ adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->v1.gc_gs_table_depth); ++ adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->v1.gc_gsprim_buff_depth); ++ adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->v1.gc_double_offchip_lds_buffer); ++ adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->v1.gc_wave_size); ++ adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->v1.gc_max_waves_per_simd); ++ adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->v1.gc_max_scratch_slots_per_cu); ++ adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->v1.gc_lds_size); ++ adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->v1.gc_num_sc_per_se) / ++ le32_to_cpu(gc_info->v1.gc_num_sa_per_se); ++ adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->v1.gc_num_packer_per_sc); ++ break; ++ case 2: ++ adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->v2.gc_num_se); ++ adev->gfx.config.max_cu_per_sh = le32_to_cpu(gc_info->v2.gc_num_cu_per_sh); ++ adev->gfx.config.max_sh_per_se = le32_to_cpu(gc_info->v2.gc_num_sh_per_se); ++ adev->gfx.config.max_backends_per_se = le32_to_cpu(gc_info->v2.gc_num_rb_per_se); ++ adev->gfx.config.max_texture_channel_caches = le32_to_cpu(gc_info->v2.gc_num_tccs); ++ adev->gfx.config.max_gprs = le32_to_cpu(gc_info->v2.gc_num_gprs); ++ adev->gfx.config.max_gs_threads = le32_to_cpu(gc_info->v2.gc_num_max_gs_thds); ++ adev->gfx.config.gs_vgt_table_depth = le32_to_cpu(gc_info->v2.gc_gs_table_depth); ++ adev->gfx.config.gs_prim_buffer_depth = le32_to_cpu(gc_info->v2.gc_gsprim_buff_depth); ++ adev->gfx.config.double_offchip_lds_buf = le32_to_cpu(gc_info->v2.gc_double_offchip_lds_buffer); ++ adev->gfx.cu_info.wave_front_size = le32_to_cpu(gc_info->v2.gc_wave_size); ++ adev->gfx.cu_info.max_waves_per_simd = le32_to_cpu(gc_info->v2.gc_max_waves_per_simd); ++ adev->gfx.cu_info.max_scratch_slots_per_cu = le32_to_cpu(gc_info->v2.gc_max_scratch_slots_per_cu); ++ adev->gfx.cu_info.lds_size = le32_to_cpu(gc_info->v2.gc_lds_size); ++ adev->gfx.config.num_sc_per_sh = le32_to_cpu(gc_info->v2.gc_num_sc_per_se) / ++ le32_to_cpu(gc_info->v2.gc_num_sh_per_se); ++ adev->gfx.config.num_packer_per_sc = le32_to_cpu(gc_info->v2.gc_num_packer_per_sc); ++ break; ++ default: ++ dev_err(adev->dev, ++ "Unhandled GC info table %d.%d\n", ++ gc_info->v1.header.version_major, ++ gc_info->v1.header.version_minor); ++ return -EINVAL; ++ } + return 0; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +index ae6ab93c868b8..7444484a12bf8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +@@ -384,7 +384,7 @@ amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach) + struct amdgpu_vm_bo_base *bo_base; + int r; + +- if (bo->tbo.resource->mem_type == TTM_PL_SYSTEM) ++ if (!bo->tbo.resource || bo->tbo.resource->mem_type == TTM_PL_SYSTEM) + return; + + r = ttm_bo_validate(&bo->tbo, &placement, &ctx); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index f18240f873878..5a7fef324c820 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -38,6 +38,7 @@ + #include <drm/drm_probe_helper.h> + #include <linux/mmu_notifier.h> + #include <linux/suspend.h> ++#include <linux/fb.h> + + #include "amdgpu.h" + #include "amdgpu_irq.h" +@@ -890,6 +891,717 @@ MODULE_PARM_DESC(smu_pptable_id, + "specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)"); + module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444); + ++/* These devices are not supported by amdgpu. ++ * They are supported by the mach64, r128, radeon drivers ++ */ ++static const u16 amdgpu_unsupported_pciidlist[] = { ++ /* mach64 */ ++ 0x4354, ++ 0x4358, ++ 0x4554, ++ 0x4742, ++ 0x4744, ++ 0x4749, ++ 0x474C, ++ 0x474D, ++ 0x474E, ++ 0x474F, ++ 0x4750, ++ 0x4751, ++ 0x4752, ++ 0x4753, ++ 0x4754, ++ 0x4755, ++ 0x4756, ++ 0x4757, ++ 0x4758, ++ 0x4759, ++ 0x475A, ++ 0x4C42, ++ 0x4C44, ++ 0x4C47, ++ 0x4C49, ++ 0x4C4D, ++ 0x4C4E, ++ 0x4C50, ++ 0x4C51, ++ 0x4C52, ++ 0x4C53, ++ 0x5654, ++ 0x5655, ++ 0x5656, ++ /* r128 */ ++ 0x4c45, ++ 0x4c46, ++ 0x4d46, ++ 0x4d4c, ++ 0x5041, ++ 0x5042, ++ 0x5043, ++ 0x5044, ++ 0x5045, ++ 0x5046, ++ 0x5047, ++ 0x5048, ++ 0x5049, ++ 0x504A, ++ 0x504B, ++ 0x504C, ++ 0x504D, ++ 0x504E, ++ 0x504F, ++ 0x5050, ++ 0x5051, ++ 0x5052, ++ 0x5053, ++ 0x5054, ++ 0x5055, ++ 0x5056, ++ 0x5057, ++ 0x5058, ++ 0x5245, ++ 0x5246, ++ 0x5247, ++ 0x524b, ++ 0x524c, ++ 0x534d, ++ 0x5446, ++ 0x544C, ++ 0x5452, ++ /* radeon */ ++ 0x3150, ++ 0x3151, ++ 0x3152, ++ 0x3154, ++ 0x3155, ++ 0x3E50, ++ 0x3E54, ++ 0x4136, ++ 0x4137, ++ 0x4144, ++ 0x4145, ++ 0x4146, ++ 0x4147, ++ 0x4148, ++ 0x4149, ++ 0x414A, ++ 0x414B, ++ 0x4150, ++ 0x4151, ++ 0x4152, ++ 0x4153, ++ 0x4154, ++ 0x4155, ++ 0x4156, ++ 0x4237, ++ 0x4242, ++ 0x4336, ++ 0x4337, ++ 0x4437, ++ 0x4966, ++ 0x4967, ++ 0x4A48, ++ 0x4A49, ++ 0x4A4A, ++ 0x4A4B, ++ 0x4A4C, ++ 0x4A4D, ++ 0x4A4E, ++ 0x4A4F, ++ 0x4A50, ++ 0x4A54, ++ 0x4B48, ++ 0x4B49, ++ 0x4B4A, ++ 0x4B4B, ++ 0x4B4C, ++ 0x4C57, ++ 0x4C58, ++ 0x4C59, ++ 0x4C5A, ++ 0x4C64, ++ 0x4C66, ++ 0x4C67, ++ 0x4E44, ++ 0x4E45, ++ 0x4E46, ++ 0x4E47, ++ 0x4E48, ++ 0x4E49, ++ 0x4E4A, ++ 0x4E4B, ++ 0x4E50, ++ 0x4E51, ++ 0x4E52, ++ 0x4E53, ++ 0x4E54, ++ 0x4E56, ++ 0x5144, ++ 0x5145, ++ 0x5146, ++ 0x5147, ++ 0x5148, ++ 0x514C, ++ 0x514D, ++ 0x5157, ++ 0x5158, ++ 0x5159, ++ 0x515A, ++ 0x515E, ++ 0x5460, ++ 0x5462, ++ 0x5464, ++ 0x5548, ++ 0x5549, ++ 0x554A, ++ 0x554B, ++ 0x554C, ++ 0x554D, ++ 0x554E, ++ 0x554F, ++ 0x5550, ++ 0x5551, ++ 0x5552, ++ 0x5554, ++ 0x564A, ++ 0x564B, ++ 0x564F, ++ 0x5652, ++ 0x5653, ++ 0x5657, ++ 0x5834, ++ 0x5835, ++ 0x5954, ++ 0x5955, ++ 0x5974, ++ 0x5975, ++ 0x5960, ++ 0x5961, ++ 0x5962, ++ 0x5964, ++ 0x5965, ++ 0x5969, ++ 0x5a41, ++ 0x5a42, ++ 0x5a61, ++ 0x5a62, ++ 0x5b60, ++ 0x5b62, ++ 0x5b63, ++ 0x5b64, ++ 0x5b65, ++ 0x5c61, ++ 0x5c63, ++ 0x5d48, ++ 0x5d49, ++ 0x5d4a, ++ 0x5d4c, ++ 0x5d4d, ++ 0x5d4e, ++ 0x5d4f, ++ 0x5d50, ++ 0x5d52, ++ 0x5d57, ++ 0x5e48, ++ 0x5e4a, ++ 0x5e4b, ++ 0x5e4c, ++ 0x5e4d, ++ 0x5e4f, ++ 0x6700, ++ 0x6701, ++ 0x6702, ++ 0x6703, ++ 0x6704, ++ 0x6705, ++ 0x6706, ++ 0x6707, ++ 0x6708, ++ 0x6709, ++ 0x6718, ++ 0x6719, ++ 0x671c, ++ 0x671d, ++ 0x671f, ++ 0x6720, ++ 0x6721, ++ 0x6722, ++ 0x6723, ++ 0x6724, ++ 0x6725, ++ 0x6726, ++ 0x6727, ++ 0x6728, ++ 0x6729, ++ 0x6738, ++ 0x6739, ++ 0x673e, ++ 0x6740, ++ 0x6741, ++ 0x6742, ++ 0x6743, ++ 0x6744, ++ 0x6745, ++ 0x6746, ++ 0x6747, ++ 0x6748, ++ 0x6749, ++ 0x674A, ++ 0x6750, ++ 0x6751, ++ 0x6758, ++ 0x6759, ++ 0x675B, ++ 0x675D, ++ 0x675F, ++ 0x6760, ++ 0x6761, ++ 0x6762, ++ 0x6763, ++ 0x6764, ++ 0x6765, ++ 0x6766, ++ 0x6767, ++ 0x6768, ++ 0x6770, ++ 0x6771, ++ 0x6772, ++ 0x6778, ++ 0x6779, ++ 0x677B, ++ 0x6840, ++ 0x6841, ++ 0x6842, ++ 0x6843, ++ 0x6849, ++ 0x684C, ++ 0x6850, ++ 0x6858, ++ 0x6859, ++ 0x6880, ++ 0x6888, ++ 0x6889, ++ 0x688A, ++ 0x688C, ++ 0x688D, ++ 0x6898, ++ 0x6899, ++ 0x689b, ++ 0x689c, ++ 0x689d, ++ 0x689e, ++ 0x68a0, ++ 0x68a1, ++ 0x68a8, ++ 0x68a9, ++ 0x68b0, ++ 0x68b8, ++ 0x68b9, ++ 0x68ba, ++ 0x68be, ++ 0x68bf, ++ 0x68c0, ++ 0x68c1, ++ 0x68c7, ++ 0x68c8, ++ 0x68c9, ++ 0x68d8, ++ 0x68d9, ++ 0x68da, ++ 0x68de, ++ 0x68e0, ++ 0x68e1, ++ 0x68e4, ++ 0x68e5, ++ 0x68e8, ++ 0x68e9, ++ 0x68f1, ++ 0x68f2, ++ 0x68f8, ++ 0x68f9, ++ 0x68fa, ++ 0x68fe, ++ 0x7100, ++ 0x7101, ++ 0x7102, ++ 0x7103, ++ 0x7104, ++ 0x7105, ++ 0x7106, ++ 0x7108, ++ 0x7109, ++ 0x710A, ++ 0x710B, ++ 0x710C, ++ 0x710E, ++ 0x710F, ++ 0x7140, ++ 0x7141, ++ 0x7142, ++ 0x7143, ++ 0x7144, ++ 0x7145, ++ 0x7146, ++ 0x7147, ++ 0x7149, ++ 0x714A, ++ 0x714B, ++ 0x714C, ++ 0x714D, ++ 0x714E, ++ 0x714F, ++ 0x7151, ++ 0x7152, ++ 0x7153, ++ 0x715E, ++ 0x715F, ++ 0x7180, ++ 0x7181, ++ 0x7183, ++ 0x7186, ++ 0x7187, ++ 0x7188, ++ 0x718A, ++ 0x718B, ++ 0x718C, ++ 0x718D, ++ 0x718F, ++ 0x7193, ++ 0x7196, ++ 0x719B, ++ 0x719F, ++ 0x71C0, ++ 0x71C1, ++ 0x71C2, ++ 0x71C3, ++ 0x71C4, ++ 0x71C5, ++ 0x71C6, ++ 0x71C7, ++ 0x71CD, ++ 0x71CE, ++ 0x71D2, ++ 0x71D4, ++ 0x71D5, ++ 0x71D6, ++ 0x71DA, ++ 0x71DE, ++ 0x7200, ++ 0x7210, ++ 0x7211, ++ 0x7240, ++ 0x7243, ++ 0x7244, ++ 0x7245, ++ 0x7246, ++ 0x7247, ++ 0x7248, ++ 0x7249, ++ 0x724A, ++ 0x724B, ++ 0x724C, ++ 0x724D, ++ 0x724E, ++ 0x724F, ++ 0x7280, ++ 0x7281, ++ 0x7283, ++ 0x7284, ++ 0x7287, ++ 0x7288, ++ 0x7289, ++ 0x728B, ++ 0x728C, ++ 0x7290, ++ 0x7291, ++ 0x7293, ++ 0x7297, ++ 0x7834, ++ 0x7835, ++ 0x791e, ++ 0x791f, ++ 0x793f, ++ 0x7941, ++ 0x7942, ++ 0x796c, ++ 0x796d, ++ 0x796e, ++ 0x796f, ++ 0x9400, ++ 0x9401, ++ 0x9402, ++ 0x9403, ++ 0x9405, ++ 0x940A, ++ 0x940B, ++ 0x940F, ++ 0x94A0, ++ 0x94A1, ++ 0x94A3, ++ 0x94B1, ++ 0x94B3, ++ 0x94B4, ++ 0x94B5, ++ 0x94B9, ++ 0x9440, ++ 0x9441, ++ 0x9442, ++ 0x9443, ++ 0x9444, ++ 0x9446, ++ 0x944A, ++ 0x944B, ++ 0x944C, ++ 0x944E, ++ 0x9450, ++ 0x9452, ++ 0x9456, ++ 0x945A, ++ 0x945B, ++ 0x945E, ++ 0x9460, ++ 0x9462, ++ 0x946A, ++ 0x946B, ++ 0x947A, ++ 0x947B, ++ 0x9480, ++ 0x9487, ++ 0x9488, ++ 0x9489, ++ 0x948A, ++ 0x948F, ++ 0x9490, ++ 0x9491, ++ 0x9495, ++ 0x9498, ++ 0x949C, ++ 0x949E, ++ 0x949F, ++ 0x94C0, ++ 0x94C1, ++ 0x94C3, ++ 0x94C4, ++ 0x94C5, ++ 0x94C6, ++ 0x94C7, ++ 0x94C8, ++ 0x94C9, ++ 0x94CB, ++ 0x94CC, ++ 0x94CD, ++ 0x9500, ++ 0x9501, ++ 0x9504, ++ 0x9505, ++ 0x9506, ++ 0x9507, ++ 0x9508, ++ 0x9509, ++ 0x950F, ++ 0x9511, ++ 0x9515, ++ 0x9517, ++ 0x9519, ++ 0x9540, ++ 0x9541, ++ 0x9542, ++ 0x954E, ++ 0x954F, ++ 0x9552, ++ 0x9553, ++ 0x9555, ++ 0x9557, ++ 0x955f, ++ 0x9580, ++ 0x9581, ++ 0x9583, ++ 0x9586, ++ 0x9587, ++ 0x9588, ++ 0x9589, ++ 0x958A, ++ 0x958B, ++ 0x958C, ++ 0x958D, ++ 0x958E, ++ 0x958F, ++ 0x9590, ++ 0x9591, ++ 0x9593, ++ 0x9595, ++ 0x9596, ++ 0x9597, ++ 0x9598, ++ 0x9599, ++ 0x959B, ++ 0x95C0, ++ 0x95C2, ++ 0x95C4, ++ 0x95C5, ++ 0x95C6, ++ 0x95C7, ++ 0x95C9, ++ 0x95CC, ++ 0x95CD, ++ 0x95CE, ++ 0x95CF, ++ 0x9610, ++ 0x9611, ++ 0x9612, ++ 0x9613, ++ 0x9614, ++ 0x9615, ++ 0x9616, ++ 0x9640, ++ 0x9641, ++ 0x9642, ++ 0x9643, ++ 0x9644, ++ 0x9645, ++ 0x9647, ++ 0x9648, ++ 0x9649, ++ 0x964a, ++ 0x964b, ++ 0x964c, ++ 0x964e, ++ 0x964f, ++ 0x9710, ++ 0x9711, ++ 0x9712, ++ 0x9713, ++ 0x9714, ++ 0x9715, ++ 0x9802, ++ 0x9803, ++ 0x9804, ++ 0x9805, ++ 0x9806, ++ 0x9807, ++ 0x9808, ++ 0x9809, ++ 0x980A, ++ 0x9900, ++ 0x9901, ++ 0x9903, ++ 0x9904, ++ 0x9905, ++ 0x9906, ++ 0x9907, ++ 0x9908, ++ 0x9909, ++ 0x990A, ++ 0x990B, ++ 0x990C, ++ 0x990D, ++ 0x990E, ++ 0x990F, ++ 0x9910, ++ 0x9913, ++ 0x9917, ++ 0x9918, ++ 0x9919, ++ 0x9990, ++ 0x9991, ++ 0x9992, ++ 0x9993, ++ 0x9994, ++ 0x9995, ++ 0x9996, ++ 0x9997, ++ 0x9998, ++ 0x9999, ++ 0x999A, ++ 0x999B, ++ 0x999C, ++ 0x999D, ++ 0x99A0, ++ 0x99A2, ++ 0x99A4, ++ /* radeon secondary ids */ ++ 0x3171, ++ 0x3e70, ++ 0x4164, ++ 0x4165, ++ 0x4166, ++ 0x4168, ++ 0x4170, ++ 0x4171, ++ 0x4172, ++ 0x4173, ++ 0x496e, ++ 0x4a69, ++ 0x4a6a, ++ 0x4a6b, ++ 0x4a70, ++ 0x4a74, ++ 0x4b69, ++ 0x4b6b, ++ 0x4b6c, ++ 0x4c6e, ++ 0x4e64, ++ 0x4e65, ++ 0x4e66, ++ 0x4e67, ++ 0x4e68, ++ 0x4e69, ++ 0x4e6a, ++ 0x4e71, ++ 0x4f73, ++ 0x5569, ++ 0x556b, ++ 0x556d, ++ 0x556f, ++ 0x5571, ++ 0x5854, ++ 0x5874, ++ 0x5940, ++ 0x5941, ++ 0x5b72, ++ 0x5b73, ++ 0x5b74, ++ 0x5b75, ++ 0x5d44, ++ 0x5d45, ++ 0x5d6d, ++ 0x5d6f, ++ 0x5d72, ++ 0x5d77, ++ 0x5e6b, ++ 0x5e6d, ++ 0x7120, ++ 0x7124, ++ 0x7129, ++ 0x712e, ++ 0x712f, ++ 0x7162, ++ 0x7163, ++ 0x7166, ++ 0x7167, ++ 0x7172, ++ 0x7173, ++ 0x71a0, ++ 0x71a1, ++ 0x71a3, ++ 0x71a7, ++ 0x71bb, ++ 0x71e0, ++ 0x71e1, ++ 0x71e2, ++ 0x71e6, ++ 0x71e7, ++ 0x71f2, ++ 0x7269, ++ 0x726b, ++ 0x726e, ++ 0x72a0, ++ 0x72a8, ++ 0x72b1, ++ 0x72b3, ++ 0x793f, ++}; ++ + static const struct pci_device_id pciidlist[] = { + #ifdef CONFIG_DRM_AMDGPU_SI + {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, +@@ -1246,14 +1958,45 @@ MODULE_DEVICE_TABLE(pci, pciidlist); + + static const struct drm_driver amdgpu_kms_driver; + ++static bool amdgpu_is_fw_framebuffer(resource_size_t base, ++ resource_size_t size) ++{ ++ bool found = false; ++#if IS_REACHABLE(CONFIG_FB) ++ struct apertures_struct *a; ++ ++ a = alloc_apertures(1); ++ if (!a) ++ return false; ++ ++ a->ranges[0].base = base; ++ a->ranges[0].size = size; ++ ++ found = is_firmware_framebuffer(a); ++ kfree(a); ++#endif ++ return found; ++} ++ + static int amdgpu_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { + struct drm_device *ddev; + struct amdgpu_device *adev; + unsigned long flags = ent->driver_data; +- int ret, retry = 0; ++ int ret, retry = 0, i; + bool supports_atomic = false; ++ bool is_fw_fb; ++ resource_size_t base, size; ++ ++ if (amdgpu_aspm == -1 && !pcie_aspm_enabled(pdev)) ++ amdgpu_aspm = 0; ++ ++ /* skip devices which are owned by radeon */ ++ for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) { ++ if (amdgpu_unsupported_pciidlist[i] == pdev->device) ++ return -ENODEV; ++ } + + if (amdgpu_virtual_display || + amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK)) +@@ -1310,6 +2053,10 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, + } + #endif + ++ base = pci_resource_start(pdev, 0); ++ size = pci_resource_len(pdev, 0); ++ is_fw_fb = amdgpu_is_fw_framebuffer(base, size); ++ + /* Get rid of things like offb */ + ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver); + if (ret) +@@ -1322,6 +2069,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, + adev->dev = &pdev->dev; + adev->pdev = pdev; + ddev = adev_to_drm(adev); ++ adev->is_fw_fb = is_fw_fb; + + if (!supports_atomic) + ddev->driver_features &= ~DRIVER_ATOMIC; +@@ -1471,13 +2219,20 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work) + static int amdgpu_pmops_prepare(struct device *dev) + { + struct drm_device *drm_dev = dev_get_drvdata(dev); ++ struct amdgpu_device *adev = drm_to_adev(drm_dev); + + /* Return a positive number here so + * DPM_FLAG_SMART_SUSPEND works properly + */ + if (amdgpu_device_supports_boco(drm_dev)) +- return pm_runtime_suspended(dev) && +- pm_suspend_via_firmware(); ++ return pm_runtime_suspended(dev); ++ ++ /* if we will not support s3 or s2i for the device ++ * then skip suspend ++ */ ++ if (!amdgpu_acpi_is_s0ix_active(adev) && ++ !amdgpu_acpi_is_s3_active(adev)) ++ return 1; + + return 0; + } +@@ -1498,7 +2253,10 @@ static int amdgpu_pmops_suspend(struct device *dev) + adev->in_s3 = true; + r = amdgpu_device_suspend(drm_dev, true); + adev->in_s3 = false; +- ++ if (r) ++ return r; ++ if (!adev->in_s0ix) ++ r = amdgpu_asic_reset(adev); + return r; + } + +@@ -1575,12 +2333,27 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) + if (amdgpu_device_supports_px(drm_dev)) + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + ++ /* ++ * By setting mp1_state as PP_MP1_STATE_UNLOAD, MP1 will do some ++ * proper cleanups and put itself into a state ready for PNP. That ++ * can address some random resuming failure observed on BOCO capable ++ * platforms. ++ * TODO: this may be also needed for PX capable platform. ++ */ ++ if (amdgpu_device_supports_boco(drm_dev)) ++ adev->mp1_state = PP_MP1_STATE_UNLOAD; ++ + ret = amdgpu_device_suspend(drm_dev, false); + if (ret) { + adev->in_runpm = false; ++ if (amdgpu_device_supports_boco(drm_dev)) ++ adev->mp1_state = PP_MP1_STATE_NONE; + return ret; + } + ++ if (amdgpu_device_supports_boco(drm_dev)) ++ adev->mp1_state = PP_MP1_STATE_NONE; ++ + if (amdgpu_device_supports_px(drm_dev)) { + /* Only need to handle PCI state in the driver for ATPX + * PCI core handles it for _PR3. +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +index 8d682befe0d68..14499f0de32dc 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +@@ -552,9 +552,6 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev) + if (!ring || !ring->fence_drv.initialized) + continue; + +- if (!ring->no_scheduler) +- drm_sched_stop(&ring->sched, NULL); +- + /* You can't wait for HW to signal if it's gone */ + if (!drm_dev_is_unplugged(&adev->ddev)) + r = amdgpu_fence_wait_empty(ring); +@@ -614,11 +611,6 @@ void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev) + if (!ring || !ring->fence_drv.initialized) + continue; + +- if (!ring->no_scheduler) { +- drm_sched_resubmit_jobs(&ring->sched); +- drm_sched_start(&ring->sched, true); +- } +- + /* enable the interrupt */ + if (ring->fence_drv.irq_src) + amdgpu_irq_get(adev, ring->fence_drv.irq_src, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +index d6aa032890ee8..a1e63ba4c54a5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +@@ -61,7 +61,7 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf) + } + + ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, +- TTM_BO_VM_NUM_PREFAULT, 1); ++ TTM_BO_VM_NUM_PREFAULT); + + drm_dev_exit(idx); + } else { +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c +index f3d62e196901a..0c7963dfacad1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c +@@ -223,7 +223,7 @@ int amdgpu_ih_wait_on_checkpoint_process(struct amdgpu_device *adev, + */ + int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih) + { +- unsigned int count = AMDGPU_IH_MAX_NUM_IVS; ++ unsigned int count; + u32 wptr; + + if (!ih->enabled || adev->shutdown) +@@ -232,6 +232,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih) + wptr = amdgpu_ih_get_wptr(adev, ih); + + restart_ih: ++ count = AMDGPU_IH_MAX_NUM_IVS; + DRM_DEBUG("%s: rptr %d, wptr %d\n", __func__, ih->rptr, wptr); + + /* Order reading of wptr vs. reading of IH ring data */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +index cc2e0c9cfe0a1..4f3c62adccbde 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +@@ -333,7 +333,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev) + if (!amdgpu_device_has_dc_support(adev)) { + if (!adev->enable_virtual_display) + /* Disable vblank IRQs aggressively for power-saving */ +- /* XXX: can this be enabled for DC? */ + adev_to_drm(adev)->vblank_disable_immediate = true; + + r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +index 7e45640fbee02..09a2fe8390591 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +@@ -206,6 +206,12 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) + adev->runpm = true; + break; + } ++ /* XXX: disable runtime pm if we are the primary adapter ++ * to avoid displays being re-enabled after DPMS. ++ * This needs to be sorted out and fixed properly. ++ */ ++ if (adev->is_fw_fb) ++ adev->runpm = false; + if (adev->runpm) + dev_info(adev->dev, "Using BACO for runtime pm\n"); + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +index 9b41cb8c3de54..86e2090bbd6e0 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +@@ -2207,12 +2207,16 @@ static int psp_hw_start(struct psp_context *psp) + return ret; + } + ++ if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) ++ goto skip_pin_bo; ++ + ret = psp_tmr_init(psp); + if (ret) { + DRM_ERROR("PSP tmr init failed!\n"); + return ret; + } + ++skip_pin_bo: + /* + * For ASICs with DF Cstate management centralized + * to PMFW, TMR setup should be performed after PMFW +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +index 94126dc396888..8132f66177c27 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -1892,7 +1892,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, + unsigned i; + int r; + +- if (direct_submit && !ring->sched.ready) { ++ if (!direct_submit && !ring->sched.ready) { + DRM_ERROR("Trying to move memory with ring turned off.\n"); + return -EINVAL; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +index ce982afeff913..7d58bf410be05 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +@@ -142,15 +142,16 @@ static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc, + static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) + { ++ unsigned long flags; + if (crtc->state->event) { +- spin_lock(&crtc->dev->event_lock); ++ spin_lock_irqsave(&crtc->dev->event_lock, flags); + + if (drm_crtc_vblank_get(crtc) != 0) + drm_crtc_send_vblank_event(crtc, crtc->state->event); + else + drm_crtc_arm_vblank_event(crtc, crtc->state->event); + +- spin_unlock(&crtc->dev->event_lock); ++ spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + crtc->state->event = NULL; + } +@@ -504,8 +505,8 @@ static int amdgpu_vkms_sw_fini(void *handle) + int i = 0; + + for (i = 0; i < adev->mode_info.num_crtc; i++) +- if (adev->mode_info.crtcs[i]) +- hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); ++ if (adev->amdgpu_vkms_output[i].vblank_hrtimer.function) ++ hrtimer_cancel(&adev->amdgpu_vkms_output[i].vblank_hrtimer); + + kfree(adev->mode_info.bios_hardcoded_edid); + kfree(adev->amdgpu_vkms_output); +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +index 6b15cad78de9d..fd37bb39774c8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -768,11 +768,17 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, + * Check if all VM PDs/PTs are ready for updates + * + * Returns: +- * True if eviction list is empty. ++ * True if VM is not evicting. + */ + bool amdgpu_vm_ready(struct amdgpu_vm *vm) + { +- return list_empty(&vm->evicted); ++ bool ret; ++ ++ amdgpu_vm_eviction_lock(vm); ++ ret = !vm->evicting; ++ amdgpu_vm_eviction_unlock(vm); ++ ++ return ret && list_empty(&vm->evicted); + } + + /** +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +index 978ac927ac11d..a799e0b1ff736 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +@@ -386,6 +386,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) + "%s", "xgmi_hive_info"); + if (ret) { + dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi hive\n"); ++ kobject_put(&hive->kobj); + kfree(hive); + hive = NULL; + goto pro_end; +diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c +index 54f28c075f214..f10ce740a29cc 100644 +--- a/drivers/gpu/drm/amd/amdgpu/cik.c ++++ b/drivers/gpu/drm/amd/amdgpu/cik.c +@@ -1428,6 +1428,10 @@ static int cik_asic_reset(struct amdgpu_device *adev) + { + int r; + ++ /* APUs don't have full asic reset */ ++ if (adev->flags & AMD_IS_APU) ++ return 0; ++ + if (cik_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { + dev_info(adev->dev, "BACO reset\n"); + r = amdgpu_dpm_baco_reset(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +index 16dbe593cba2e..970d59a21005a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +@@ -7729,8 +7729,19 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev) + switch (adev->asic_type) { + case CHIP_VANGOGH: + case CHIP_YELLOW_CARP: +- clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh) | +- ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL); ++ preempt_disable(); ++ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh); ++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh); ++ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh); ++ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over ++ * roughly every 42 seconds. ++ */ ++ if (hi_check != clock_hi) { ++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh); ++ clock_hi = hi_check; ++ } ++ preempt_enable(); ++ clock = clock_lo | (clock_hi << 32ULL); + break; + default: + preempt_disable(); +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +index 025184a556ee6..c39e53a41f13a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +@@ -140,6 +140,11 @@ MODULE_FIRMWARE("amdgpu/aldebaran_rlc.bin"); + #define mmTCP_CHAN_STEER_5_ARCT 0x0b0c + #define mmTCP_CHAN_STEER_5_ARCT_BASE_IDX 0 + ++#define mmGOLDEN_TSC_COUNT_UPPER_Renoir 0x0025 ++#define mmGOLDEN_TSC_COUNT_UPPER_Renoir_BASE_IDX 1 ++#define mmGOLDEN_TSC_COUNT_LOWER_Renoir 0x0026 ++#define mmGOLDEN_TSC_COUNT_LOWER_Renoir_BASE_IDX 1 ++ + enum ta_ras_gfx_subblock { + /*CPC*/ + TA_RAS_BLOCK__GFX_CPC_INDEX_START = 0, +@@ -3056,8 +3061,8 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev) + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GDS | + AMD_PG_SUPPORT_RLC_SMU_HS)) { +- WREG32(mmRLC_JUMP_TABLE_RESTORE, +- adev->gfx.rlc.cp_table_gpu_addr >> 8); ++ WREG32_SOC15(GC, 0, mmRLC_JUMP_TABLE_RESTORE, ++ adev->gfx.rlc.cp_table_gpu_addr >> 8); + gfx_v9_0_init_gfx_power_gating(adev); + } + } +@@ -4228,19 +4233,38 @@ failed_kiq_read: + + static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev) + { +- uint64_t clock; ++ uint64_t clock, clock_lo, clock_hi, hi_check; + +- amdgpu_gfx_off_ctrl(adev, false); +- mutex_lock(&adev->gfx.gpu_clock_mutex); +- if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) { +- clock = gfx_v9_0_kiq_read_clock(adev); +- } else { +- WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1); +- clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) | +- ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL); ++ switch (adev->asic_type) { ++ case CHIP_RENOIR: ++ preempt_disable(); ++ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir); ++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Renoir); ++ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir); ++ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over ++ * roughly every 42 seconds. ++ */ ++ if (hi_check != clock_hi) { ++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Renoir); ++ clock_hi = hi_check; ++ } ++ preempt_enable(); ++ clock = clock_lo | (clock_hi << 32ULL); ++ break; ++ default: ++ amdgpu_gfx_off_ctrl(adev, false); ++ mutex_lock(&adev->gfx.gpu_clock_mutex); ++ if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) { ++ clock = gfx_v9_0_kiq_read_clock(adev); ++ } else { ++ WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1); ++ clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) | ++ ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL); ++ } ++ mutex_unlock(&adev->gfx.gpu_clock_mutex); ++ amdgpu_gfx_off_ctrl(adev, true); ++ break; + } +- mutex_unlock(&adev->gfx.gpu_clock_mutex); +- amdgpu_gfx_off_ctrl(adev, true); + return clock; + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +index bda1542ef1ddf..f51fd0688eca7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +@@ -162,7 +162,6 @@ static void gfxhub_v1_0_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC);/* XXX for emulation. */ + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1); +diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +index 14c1c1a297dd3..6e0ace2fbfab1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +@@ -196,7 +196,6 @@ static void gfxhub_v2_0_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC); /* UC, uncached */ + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +index 1a374ec0514a5..9328991e8807f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +@@ -197,7 +197,6 @@ static void gfxhub_v2_1_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC); /* UC, uncached */ + +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +index e47104a1f5596..3c01be6610144 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +@@ -1021,10 +1021,14 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) + return -EINVAL; + } + ++ if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) ++ goto skip_pin_bo; ++ + r = amdgpu_gart_table_vram_pin(adev); + if (r) + return r; + ++skip_pin_bo: + r = adev->gfxhub.funcs->gart_enable(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +index 0e81e03e9b498..0fe714f54cca9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +@@ -841,12 +841,12 @@ static int gmc_v6_0_sw_init(void *handle) + + adev->gmc.mc_mask = 0xffffffffffULL; + +- r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44)); ++ r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40)); + if (r) { + dev_warn(adev->dev, "No suitable DMA available.\n"); + return r; + } +- adev->need_swiotlb = drm_need_swiotlb(44); ++ adev->need_swiotlb = drm_need_swiotlb(40); + + r = gmc_v6_0_init_microcode(adev); + if (r) { +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +index 492ebed2915be..63b890f1e8afb 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +@@ -515,10 +515,10 @@ static void gmc_v8_0_mc_program(struct amdgpu_device *adev) + static int gmc_v8_0_mc_init(struct amdgpu_device *adev) + { + int r; ++ u32 tmp; + + adev->gmc.vram_width = amdgpu_atombios_get_vram_width(adev); + if (!adev->gmc.vram_width) { +- u32 tmp; + int chansize, numchan; + + /* Get VRAM informations */ +@@ -562,8 +562,15 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev) + adev->gmc.vram_width = numchan * chansize; + } + /* size in MB on si */ +- adev->gmc.mc_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL; +- adev->gmc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL; ++ tmp = RREG32(mmCONFIG_MEMSIZE); ++ /* some boards may have garbage in the upper 16 bits */ ++ if (tmp & 0xffff0000) { ++ DRM_INFO("Probable bad vram size: 0x%08x\n", tmp); ++ if (tmp & 0xffff) ++ tmp &= 0xffff; ++ } ++ adev->gmc.mc_vram_size = tmp * 1024ULL * 1024ULL; ++ adev->gmc.real_vram_size = adev->gmc.mc_vram_size; + + if (!(adev->flags & AMD_IS_APU)) { + r = amdgpu_device_resize_fb_bar(adev); +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +index 5551359d5dfdc..c67e212443429 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +@@ -72,6 +72,9 @@ + #define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x049d + #define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 + ++#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2 0x05ea ++#define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2_BASE_IDX 2 ++ + + static const char *gfxhub_client_ids[] = { + "CB", +@@ -1103,6 +1106,8 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) + u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); + unsigned size; + ++ /* TODO move to DC so GMC doesn't need to hard-code DCN registers */ ++ + if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { + size = AMDGPU_VBIOS_VGA_ALLOCATION; + } else { +@@ -1110,7 +1115,6 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) + + switch (adev->asic_type) { + case CHIP_RAVEN: +- case CHIP_RENOIR: + viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); + size = (REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * +@@ -1118,6 +1122,14 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) * + 4); + break; ++ case CHIP_RENOIR: ++ viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2); ++ size = (REG_GET_FIELD(viewport, ++ HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * ++ REG_GET_FIELD(viewport, ++ HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) * ++ 4); ++ break; + case CHIP_VEGA10: + case CHIP_VEGA12: + case CHIP_VEGA20: +@@ -1708,10 +1720,14 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) + return -EINVAL; + } + ++ if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) ++ goto skip_pin_bo; ++ + r = amdgpu_gart_table_vram_pin(adev); + if (r) + return r; + ++skip_pin_bo: + r = adev->gfxhub.funcs->gart_enable(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +index a99953833820e..b3bede1dc41da 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +@@ -145,7 +145,6 @@ static void mmhub_v1_0_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC);/* XXX for emulation. */ + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1); +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +index f80a14a1b82dc..f5f7181f9af5f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +@@ -165,7 +165,6 @@ static void mmhub_v1_7_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC);/* XXX for emulation. */ + tmp = REG_SET_FIELD(tmp, MC_VM_MX_L1_TLB_CNTL, ATC_EN, 1); +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +index 7ded6b2f058ef..2e58ed2caa485 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +@@ -269,7 +269,6 @@ static void mmhub_v2_0_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC); /* UC, uncached */ + +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c +index 88e457a150e02..c63b6b9349350 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c +@@ -194,7 +194,6 @@ static void mmhub_v2_3_init_tlb_regs(struct amdgpu_device *adev) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, MMMC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC); /* UC, uncached */ + +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +index c4ef822bbe8c5..ff49eeaf78824 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +@@ -189,8 +189,6 @@ static void mmhub_v9_4_init_tlb_regs(struct amdgpu_device *adev, int hubid) + ENABLE_ADVANCED_DRIVER_MODEL, 1); + tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, + SYSTEM_APERTURE_UNMAPPED_ACCESS, 0); +- tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, +- ECO_BITS, 0); + tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, + MTYPE, MTYPE_UC);/* XXX for emulation. */ + tmp = REG_SET_FIELD(tmp, VMSHAREDVC0_MC_VM_MX_L1_TLB_CNTL, +diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +index 8931000dcd418..e37948c157692 100644 +--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +@@ -2062,6 +2062,10 @@ static int sdma_v4_0_suspend(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ /* SMU saves SDMA state for us */ ++ if (adev->in_s0ix) ++ return 0; ++ + return sdma_v4_0_hw_fini(adev); + } + +@@ -2069,6 +2073,10 @@ static int sdma_v4_0_resume(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ /* SMU restores SDMA state for us */ ++ if (adev->in_s0ix) ++ return 0; ++ + return sdma_v4_0_hw_init(adev); + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c +index 0fc97c364fd76..6439d5c3d8d8b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc15.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc15.c +@@ -607,8 +607,8 @@ soc15_asic_reset_method(struct amdgpu_device *adev) + static int soc15_asic_reset(struct amdgpu_device *adev) + { + /* original raven doesn't have full asic reset */ +- if ((adev->apu_flags & AMD_APU_IS_RAVEN) && +- !(adev->apu_flags & AMD_APU_IS_RAVEN2)) ++ if ((adev->apu_flags & AMD_APU_IS_RAVEN) || ++ (adev->apu_flags & AMD_APU_IS_RAVEN2)) + return 0; + + switch (soc15_asic_reset_method(adev)) { +@@ -1273,8 +1273,11 @@ static int soc15_common_early_init(void *handle) + AMD_CG_SUPPORT_SDMA_LS | + AMD_CG_SUPPORT_VCN_MGCG; + ++ /* ++ * MMHUB PG needs to be disabled for Picasso for ++ * stability reasons. ++ */ + adev->pg_flags = AMD_PG_SUPPORT_SDMA | +- AMD_PG_SUPPORT_MMHUB | + AMD_PG_SUPPORT_VCN; + } else { + adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | +diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +index 7232241e3bfb2..0fef925b66024 100644 +--- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c ++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +@@ -698,6 +698,19 @@ static int uvd_v3_1_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->uvd.idle_work); ++ ++ if (RREG32(mmUVD_STATUS) != 0) ++ uvd_v3_1_stop(adev); ++ ++ return 0; ++} ++ ++static int uvd_v3_1_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -722,17 +735,6 @@ static int uvd_v3_1_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- if (RREG32(mmUVD_STATUS) != 0) +- uvd_v3_1_stop(adev); +- +- return 0; +-} +- +-static int uvd_v3_1_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = uvd_v3_1_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +index 52d6de969f462..c108b83817951 100644 +--- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c ++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +@@ -212,6 +212,19 @@ static int uvd_v4_2_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->uvd.idle_work); ++ ++ if (RREG32(mmUVD_STATUS) != 0) ++ uvd_v4_2_stop(adev); ++ ++ return 0; ++} ++ ++static int uvd_v4_2_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -236,17 +249,6 @@ static int uvd_v4_2_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- if (RREG32(mmUVD_STATUS) != 0) +- uvd_v4_2_stop(adev); +- +- return 0; +-} +- +-static int uvd_v4_2_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = uvd_v4_2_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +index db6d06758e4d4..563493d1f8306 100644 +--- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +@@ -210,6 +210,19 @@ static int uvd_v5_0_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->uvd.idle_work); ++ ++ if (RREG32(mmUVD_STATUS) != 0) ++ uvd_v5_0_stop(adev); ++ ++ return 0; ++} ++ ++static int uvd_v5_0_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -234,17 +247,6 @@ static int uvd_v5_0_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- if (RREG32(mmUVD_STATUS) != 0) +- uvd_v5_0_stop(adev); +- +- return 0; +-} +- +-static int uvd_v5_0_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = uvd_v5_0_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +index bc571833632ea..72f8762907681 100644 +--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +@@ -543,6 +543,19 @@ static int uvd_v6_0_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->uvd.idle_work); ++ ++ if (RREG32(mmUVD_STATUS) != 0) ++ uvd_v6_0_stop(adev); ++ ++ return 0; ++} ++ ++static int uvd_v6_0_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -567,17 +580,6 @@ static int uvd_v6_0_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- if (RREG32(mmUVD_STATUS) != 0) +- uvd_v6_0_stop(adev); +- +- return 0; +-} +- +-static int uvd_v6_0_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = uvd_v6_0_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +index b6e82d75561f6..1fd9ca21a091b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +@@ -606,6 +606,23 @@ static int uvd_v7_0_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->uvd.idle_work); ++ ++ if (!amdgpu_sriov_vf(adev)) ++ uvd_v7_0_stop(adev); ++ else { ++ /* full access mode, so don't touch any UVD register */ ++ DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); ++ } ++ ++ return 0; ++} ++ ++static int uvd_v7_0_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -630,21 +647,6 @@ static int uvd_v7_0_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- if (!amdgpu_sriov_vf(adev)) +- uvd_v7_0_stop(adev); +- else { +- /* full access mode, so don't touch any UVD register */ +- DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); +- } +- +- return 0; +-} +- +-static int uvd_v7_0_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = uvd_v7_0_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +index b70c17f0c52e8..98952fd387e73 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +@@ -479,6 +479,17 @@ static int vce_v2_0_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->vce.idle_work); ++ ++ return 0; ++} ++ ++static int vce_v2_0_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -502,14 +513,6 @@ static int vce_v2_0_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- return 0; +-} +- +-static int vce_v2_0_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = vce_v2_0_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +index 9de66893ccd6d..8fb5df7181e09 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +@@ -490,6 +490,21 @@ static int vce_v3_0_hw_fini(void *handle) + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + ++ cancel_delayed_work_sync(&adev->vce.idle_work); ++ ++ r = vce_v3_0_wait_for_idle(handle); ++ if (r) ++ return r; ++ ++ vce_v3_0_stop(adev); ++ return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); ++} ++ ++static int vce_v3_0_suspend(void *handle) ++{ ++ int r; ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work +@@ -513,19 +528,6 @@ static int vce_v3_0_hw_fini(void *handle) + AMD_CG_STATE_GATE); + } + +- r = vce_v3_0_wait_for_idle(handle); +- if (r) +- return r; +- +- vce_v3_0_stop(adev); +- return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); +-} +- +-static int vce_v3_0_suspend(void *handle) +-{ +- int r; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- + r = vce_v3_0_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +index fec902b800c28..70b8c88d30513 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +@@ -542,29 +542,8 @@ static int vce_v4_0_hw_fini(void *handle) + { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +- /* +- * Proper cleanups before halting the HW engine: +- * - cancel the delayed idle work +- * - enable powergating +- * - enable clockgating +- * - disable dpm +- * +- * TODO: to align with the VCN implementation, move the +- * jobs for clockgating/powergating/dpm setting to +- * ->set_powergating_state(). +- */ + cancel_delayed_work_sync(&adev->vce.idle_work); + +- if (adev->pm.dpm_enabled) { +- amdgpu_dpm_enable_vce(adev, false); +- } else { +- amdgpu_asic_set_vce_clocks(adev, 0, 0); +- amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, +- AMD_PG_STATE_GATE); +- amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, +- AMD_CG_STATE_GATE); +- } +- + if (!amdgpu_sriov_vf(adev)) { + /* vce_v4_0_wait_for_idle(handle); */ + vce_v4_0_stop(adev); +@@ -594,6 +573,29 @@ static int vce_v4_0_suspend(void *handle) + drm_dev_exit(idx); + } + ++ /* ++ * Proper cleanups before halting the HW engine: ++ * - cancel the delayed idle work ++ * - enable powergating ++ * - enable clockgating ++ * - disable dpm ++ * ++ * TODO: to align with the VCN implementation, move the ++ * jobs for clockgating/powergating/dpm setting to ++ * ->set_powergating_state(). ++ */ ++ cancel_delayed_work_sync(&adev->vce.idle_work); ++ ++ if (adev->pm.dpm_enabled) { ++ amdgpu_dpm_enable_vce(adev, false); ++ } else { ++ amdgpu_asic_set_vce_clocks(adev, 0, 0); ++ amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, ++ AMD_PG_STATE_GATE); ++ amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, ++ AMD_CG_STATE_GATE); ++ } ++ + r = vce_v4_0_hw_fini(adev); + if (r) + return r; +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +index 121ee9f2b8d16..462008d506904 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +@@ -253,6 +253,13 @@ static int vcn_v1_0_suspend(void *handle) + { + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ bool idle_work_unexecuted; ++ ++ idle_work_unexecuted = cancel_delayed_work_sync(&adev->vcn.idle_work); ++ if (idle_work_unexecuted) { ++ if (adev->pm.dpm_enabled) ++ amdgpu_dpm_enable_uvd(adev, false); ++ } + + r = vcn_v1_0_hw_fini(adev); + if (r) +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +index f4686e918e0d1..c405075a572c1 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +@@ -22,6 +22,7 @@ + */ + + #include <linux/firmware.h> ++#include <drm/drm_drv.h> + + #include "amdgpu.h" + #include "amdgpu_vcn.h" +@@ -192,11 +193,14 @@ static int vcn_v2_0_sw_init(void *handle) + */ + static int vcn_v2_0_sw_fini(void *handle) + { +- int r; ++ int r, idx; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared_cpu_addr; + +- fw_shared->present_flag_0 = 0; ++ if (drm_dev_enter(&adev->ddev, &idx)) { ++ fw_shared->present_flag_0 = 0; ++ drm_dev_exit(idx); ++ } + + amdgpu_virt_free_mm_table(adev); + +diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +index e0c0c3734432e..a0956d8623770 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c ++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +@@ -22,6 +22,7 @@ + */ + + #include <linux/firmware.h> ++#include <drm/drm_drv.h> + + #include "amdgpu.h" + #include "amdgpu_vcn.h" +@@ -233,17 +234,21 @@ static int vcn_v2_5_sw_init(void *handle) + */ + static int vcn_v2_5_sw_fini(void *handle) + { +- int i, r; ++ int i, r, idx; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + volatile struct amdgpu_fw_shared *fw_shared; + +- for (i = 0; i < adev->vcn.num_vcn_inst; i++) { +- if (adev->vcn.harvest_config & (1 << i)) +- continue; +- fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr; +- fw_shared->present_flag_0 = 0; ++ if (drm_dev_enter(&adev->ddev, &idx)) { ++ for (i = 0; i < adev->vcn.num_vcn_inst; i++) { ++ if (adev->vcn.harvest_config & (1 << i)) ++ continue; ++ fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr; ++ fw_shared->present_flag_0 = 0; ++ } ++ drm_dev_exit(idx); + } + ++ + if (amdgpu_sriov_vf(adev)) + amdgpu_virt_free_mm_table(adev); + +diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c +index fe9a7cc8d9eb0..6645ebbd2696c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vi.c ++++ b/drivers/gpu/drm/amd/amdgpu/vi.c +@@ -956,6 +956,10 @@ static int vi_asic_reset(struct amdgpu_device *adev) + { + int r; + ++ /* APUs don't have full asic reset */ ++ if (adev->flags & AMD_IS_APU) ++ return 0; ++ + if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { + dev_info(adev->dev, "BACO reset\n"); + r = amdgpu_dpm_baco_reset(adev); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +index cfedfb1e8596c..c33d689f29e8e 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +@@ -1060,6 +1060,9 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink, + return -ENODEV; + /* same everything but the other direction */ + props2 = kmemdup(props, sizeof(*props2), GFP_KERNEL); ++ if (!props2) ++ return -ENOMEM; ++ + props2->node_from = id_to; + props2->node_to = id_from; + props2->kobj = NULL; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +index 4a416231b24c8..88c483f699894 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c +@@ -916,6 +916,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, + kfd_double_confirm_iommu_support(kfd); + + if (kfd_iommu_device_init(kfd)) { ++ kfd->use_iommu_v2 = false; + dev_err(kfd_device, "Error initializing iommuv2\n"); + goto device_iommu_error; + } +@@ -924,6 +925,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, + + svm_migrate_init((struct amdgpu_device *)kfd->kgd); + ++ if(kgd2kfd_resume_iommu(kfd)) ++ goto device_iommu_error; ++ + if (kfd_resume(kfd)) + goto kfd_resume_error; + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index f8fce9d05f50c..4f2e0cc8a51a8 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -1225,6 +1225,11 @@ static int stop_cpsch(struct device_queue_manager *dqm) + bool hanging; + + dqm_lock(dqm); ++ if (!dqm->sched_running) { ++ dqm_unlock(dqm); ++ return 0; ++ } ++ + if (!dqm->is_hws_hang) + unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); + hanging = dqm->is_hws_hang || dqm->is_resetting; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +index 9d0f65a90002d..830809b694dd9 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +@@ -936,7 +936,7 @@ svm_range_split(struct svm_range *prange, uint64_t start, uint64_t last, + } + + static int +-svm_range_split_tail(struct svm_range *prange, struct svm_range *new, ++svm_range_split_tail(struct svm_range *prange, + uint64_t new_last, struct list_head *insert_list) + { + struct svm_range *tail; +@@ -948,7 +948,7 @@ svm_range_split_tail(struct svm_range *prange, struct svm_range *new, + } + + static int +-svm_range_split_head(struct svm_range *prange, struct svm_range *new, ++svm_range_split_head(struct svm_range *prange, + uint64_t new_start, struct list_head *insert_list) + { + struct svm_range *head; +@@ -1307,7 +1307,7 @@ struct svm_validate_context { + struct svm_range *prange; + bool intr; + unsigned long bitmap[MAX_GPU_INSTANCE]; +- struct ttm_validate_buffer tv[MAX_GPU_INSTANCE+1]; ++ struct ttm_validate_buffer tv[MAX_GPU_INSTANCE]; + struct list_head validate_list; + struct ww_acquire_ctx ticket; + }; +@@ -1334,11 +1334,6 @@ static int svm_range_reserve_bos(struct svm_validate_context *ctx) + ctx->tv[gpuidx].num_shared = 4; + list_add(&ctx->tv[gpuidx].head, &ctx->validate_list); + } +- if (ctx->prange->svm_bo && ctx->prange->ttm_res) { +- ctx->tv[MAX_GPU_INSTANCE].bo = &ctx->prange->svm_bo->bo->tbo; +- ctx->tv[MAX_GPU_INSTANCE].num_shared = 1; +- list_add(&ctx->tv[MAX_GPU_INSTANCE].head, &ctx->validate_list); +- } + + r = ttm_eu_reserve_buffers(&ctx->ticket, &ctx->validate_list, + ctx->intr, NULL); +@@ -1570,7 +1565,6 @@ retry_flush_work: + static void svm_range_restore_work(struct work_struct *work) + { + struct delayed_work *dwork = to_delayed_work(work); +- struct amdkfd_process_info *process_info; + struct svm_range_list *svms; + struct svm_range *prange; + struct kfd_process *p; +@@ -1590,12 +1584,10 @@ static void svm_range_restore_work(struct work_struct *work) + * the lifetime of this thread, kfd_process and mm will be valid. + */ + p = container_of(svms, struct kfd_process, svms); +- process_info = p->kgd_process_info; + mm = p->mm; + if (!mm) + return; + +- mutex_lock(&process_info->lock); + svm_range_list_lock_and_flush_work(svms, mm); + mutex_lock(&svms->lock); + +@@ -1648,7 +1640,6 @@ static void svm_range_restore_work(struct work_struct *work) + out_reschedule: + mutex_unlock(&svms->lock); + mmap_write_unlock(mm); +- mutex_unlock(&process_info->lock); + + /* If validation failed, reschedule another attempt */ + if (evicted_ranges) { +@@ -1764,49 +1755,54 @@ static struct svm_range *svm_range_clone(struct svm_range *old) + } + + /** +- * svm_range_handle_overlap - split overlap ranges +- * @svms: svm range list header +- * @new: range added with this attributes +- * @start: range added start address, in pages +- * @last: range last address, in pages +- * @update_list: output, the ranges attributes are updated. For set_attr, this +- * will do validation and map to GPUs. For unmap, this will be +- * removed and unmap from GPUs +- * @insert_list: output, the ranges will be inserted into svms, attributes are +- * not changes. For set_attr, this will add into svms. +- * @remove_list:output, the ranges will be removed from svms +- * @left: the remaining range after overlap, For set_attr, this will be added +- * as new range. ++ * svm_range_add - add svm range and handle overlap ++ * @p: the range add to this process svms ++ * @start: page size aligned ++ * @size: page size aligned ++ * @nattr: number of attributes ++ * @attrs: array of attributes ++ * @update_list: output, the ranges need validate and update GPU mapping ++ * @insert_list: output, the ranges need insert to svms ++ * @remove_list: output, the ranges are replaced and need remove from svms + * +- * Total have 5 overlap cases. ++ * Check if the virtual address range has overlap with any existing ranges, ++ * split partly overlapping ranges and add new ranges in the gaps. All changes ++ * should be applied to the range_list and interval tree transactionally. If ++ * any range split or allocation fails, the entire update fails. Therefore any ++ * existing overlapping svm_ranges are cloned and the original svm_ranges left ++ * unchanged. + * +- * This function handles overlap of an address interval with existing +- * struct svm_ranges for applying new attributes. This may require +- * splitting existing struct svm_ranges. All changes should be applied to +- * the range_list and interval tree transactionally. If any split operation +- * fails, the entire update fails. Therefore the existing overlapping +- * svm_ranges are cloned and the original svm_ranges left unchanged. If the +- * transaction succeeds, the modified clones are added and the originals +- * freed. Otherwise the clones are removed and the old svm_ranges remain. ++ * If the transaction succeeds, the caller can update and insert clones and ++ * new ranges, then free the originals. + * +- * Context: The caller must hold svms->lock ++ * Otherwise the caller can free the clones and new ranges, while the old ++ * svm_ranges remain unchanged. ++ * ++ * Context: Process context, caller must hold svms->lock ++ * ++ * Return: ++ * 0 - OK, otherwise error code + */ + static int +-svm_range_handle_overlap(struct svm_range_list *svms, struct svm_range *new, +- unsigned long start, unsigned long last, +- struct list_head *update_list, +- struct list_head *insert_list, +- struct list_head *remove_list, +- unsigned long *left) ++svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size, ++ uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs, ++ struct list_head *update_list, struct list_head *insert_list, ++ struct list_head *remove_list) + { ++ unsigned long last = start + size - 1UL; ++ struct svm_range_list *svms = &p->svms; + struct interval_tree_node *node; ++ struct svm_range new = {0}; + struct svm_range *prange; + struct svm_range *tmp; + int r = 0; + ++ pr_debug("svms 0x%p [0x%llx 0x%lx]\n", &p->svms, start, last); ++ + INIT_LIST_HEAD(update_list); + INIT_LIST_HEAD(insert_list); + INIT_LIST_HEAD(remove_list); ++ svm_range_apply_attrs(p, &new, nattr, attrs); + + node = interval_tree_iter_first(&svms->objects, start, last); + while (node) { +@@ -1834,14 +1830,14 @@ svm_range_handle_overlap(struct svm_range_list *svms, struct svm_range *new, + + if (node->start < start) { + pr_debug("change old range start\n"); +- r = svm_range_split_head(prange, new, start, ++ r = svm_range_split_head(prange, start, + insert_list); + if (r) + goto out; + } + if (node->last > last) { + pr_debug("change old range last\n"); +- r = svm_range_split_tail(prange, new, last, ++ r = svm_range_split_tail(prange, last, + insert_list); + if (r) + goto out; +@@ -1853,7 +1849,7 @@ svm_range_handle_overlap(struct svm_range_list *svms, struct svm_range *new, + prange = old; + } + +- if (!svm_range_is_same_attrs(prange, new)) ++ if (!svm_range_is_same_attrs(prange, &new)) + list_add(&prange->update_list, update_list); + + /* insert a new node if needed */ +@@ -1873,8 +1869,16 @@ svm_range_handle_overlap(struct svm_range_list *svms, struct svm_range *new, + start = next_start; + } + +- if (left && start <= last) +- *left = last - start + 1; ++ /* add a final range at the end if needed */ ++ if (start <= last) { ++ prange = svm_range_new(svms, start, last); ++ if (!prange) { ++ r = -ENOMEM; ++ goto out; ++ } ++ list_add(&prange->insert_list, insert_list); ++ list_add(&prange->update_list, update_list); ++ } + + out: + if (r) +@@ -2702,59 +2706,6 @@ svm_range_is_valid(struct mm_struct *mm, uint64_t start, uint64_t size) + return true; + } + +-/** +- * svm_range_add - add svm range and handle overlap +- * @p: the range add to this process svms +- * @start: page size aligned +- * @size: page size aligned +- * @nattr: number of attributes +- * @attrs: array of attributes +- * @update_list: output, the ranges need validate and update GPU mapping +- * @insert_list: output, the ranges need insert to svms +- * @remove_list: output, the ranges are replaced and need remove from svms +- * +- * Check if the virtual address range has overlap with the registered ranges, +- * split the overlapped range, copy and adjust pages address and vram nodes in +- * old and new ranges. +- * +- * Context: Process context, caller must hold svms->lock +- * +- * Return: +- * 0 - OK, otherwise error code +- */ +-static int +-svm_range_add(struct kfd_process *p, uint64_t start, uint64_t size, +- uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs, +- struct list_head *update_list, struct list_head *insert_list, +- struct list_head *remove_list) +-{ +- uint64_t last = start + size - 1UL; +- struct svm_range_list *svms; +- struct svm_range new = {0}; +- struct svm_range *prange; +- unsigned long left = 0; +- int r = 0; +- +- pr_debug("svms 0x%p [0x%llx 0x%llx]\n", &p->svms, start, last); +- +- svm_range_apply_attrs(p, &new, nattr, attrs); +- +- svms = &p->svms; +- +- r = svm_range_handle_overlap(svms, &new, start, last, update_list, +- insert_list, remove_list, &left); +- if (r) +- return r; +- +- if (left) { +- prange = svm_range_new(svms, last - left + 1, last); +- list_add(&prange->insert_list, insert_list); +- list_add(&prange->update_list, update_list); +- } +- +- return 0; +-} +- + /** + * svm_range_best_prefetch_location - decide the best prefetch location + * @prange: svm range structure +@@ -2979,7 +2930,6 @@ static int + svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, + uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) + { +- struct amdkfd_process_info *process_info = p->kgd_process_info; + struct mm_struct *mm = current->mm; + struct list_head update_list; + struct list_head insert_list; +@@ -2998,8 +2948,6 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, + + svms = &p->svms; + +- mutex_lock(&process_info->lock); +- + svm_range_list_lock_and_flush_work(svms, mm); + + if (!svm_range_is_valid(mm, start, size)) { +@@ -3075,8 +3023,6 @@ out_unlock_range: + mutex_unlock(&svms->lock); + mmap_read_unlock(mm); + out: +- mutex_unlock(&process_info->lock); +- + pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] done, r=%d\n", p->pasid, + &p->svms, start, start + size - 1, r); + +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 1ea31dcc7a8b0..cd611444ad177 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1141,8 +1141,15 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) + case CHIP_RAVEN: + case CHIP_RENOIR: + init_data.flags.gpu_vm_support = true; +- if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id)) ++ switch (adev->dm.dmcub_fw_version) { ++ case 0: /* development */ ++ case 0x1: /* linux-firmware.git hash 6d9f399 */ ++ case 0x01000000: /* linux-firmware.git hash 9a0b0f4 */ ++ init_data.flags.disable_dmcu = false; ++ break; ++ default: + init_data.flags.disable_dmcu = true; ++ } + break; + case CHIP_VANGOGH: + case CHIP_YELLOW_CARP: +@@ -2206,6 +2213,9 @@ static int dm_resume(void *handle) + if (amdgpu_in_reset(adev)) { + dc_state = dm->cached_dc_state; + ++ if (dc_enable_dmub_notifications(adev->dm.dc)) ++ amdgpu_dm_outbox_init(adev); ++ + r = dm_dmub_hw_init(adev); + if (r) + DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); +@@ -2217,8 +2227,8 @@ static int dm_resume(void *handle) + + for (i = 0; i < dc_state->stream_count; i++) { + dc_state->streams[i]->mode_changed = true; +- for (j = 0; j < dc_state->stream_status->plane_count; j++) { +- dc_state->stream_status->plane_states[j]->update_flags.raw ++ for (j = 0; j < dc_state->stream_status[i].plane_count; j++) { ++ dc_state->stream_status[i].plane_states[j]->update_flags.raw + = 0xffffffff; + } + } +@@ -2253,6 +2263,10 @@ static int dm_resume(void *handle) + /* TODO: Remove dc_state->dccg, use dc->dccg directly. */ + dc_resource_state_construct(dm->dc, dm_state->context); + ++ /* Re-enable outbox interrupts for DPIA. */ ++ if (dc_enable_dmub_notifications(adev->dm.dc)) ++ amdgpu_dm_outbox_init(adev); ++ + /* Before powering on DC we need to re-initialize DMUB. */ + r = dm_dmub_hw_init(adev); + if (r) +@@ -3213,7 +3227,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev) + + /* Use GRPH_PFLIP interrupt */ + for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT; +- i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + adev->mode_info.num_crtc - 1; ++ i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + dc->caps.max_otg_num - 1; + i++) { + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->pageflip_irq); + if (r) { +@@ -3798,6 +3812,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) + } + #endif + ++ /* Disable vblank IRQs aggressively for power-saving. */ ++ adev_to_drm(adev)->vblank_disable_immediate = true; ++ + /* loops over all connectors on the board */ + for (i = 0; i < link_cnt; i++) { + struct dc_link *link = NULL; +@@ -3839,8 +3856,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) + } else if (dc_link_detect(link, DETECT_REASON_BOOT)) { + amdgpu_dm_update_connector_after_detect(aconnector); + register_backlight_device(dm, link); ++ ++ if (dm->num_of_edps) ++ update_connector_ext_caps(aconnector); + if (amdgpu_dc_feature_mask & DC_PSR_MASK) + amdgpu_dm_set_psr_caps(link); ++ ++ /* TODO: Fix vblank control helpers to delay PSR entry to allow this when ++ * PSR is also supported. ++ */ ++ if (link->psr_settings.psr_feature_enabled) ++ adev_to_drm(adev)->vblank_disable_immediate = false; + } + + +@@ -5587,6 +5613,7 @@ static void update_dsc_caps(struct amdgpu_dm_connector *aconnector, + struct dsc_dec_dpcd_caps *dsc_caps) + { + stream->timing.flags.DSC = 0; ++ dsc_caps->is_dsc_supported = false; + + if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) { + dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc, +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +index cce062adc4391..8a441a22c46ec 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +@@ -314,6 +314,14 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) + ret = -EINVAL; + goto cleanup; + } ++ ++ if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) && ++ (aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) { ++ DRM_DEBUG_DRIVER("No DP connector available for CRC source\n"); ++ ret = -EINVAL; ++ goto cleanup; ++ } ++ + } + + #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +index 8080bba5b7a76..e94ddd5e7b638 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +@@ -247,6 +247,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, + { + struct amdgpu_dm_connector *connector = file_inode(f)->i_private; + struct dc_link *link = connector->dc_link; ++ struct dc *dc = (struct dc *)link->dc; + struct dc_link_settings prefer_link_settings; + char *wr_buf = NULL; + const uint32_t wr_buf_size = 40; +@@ -313,7 +314,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, + prefer_link_settings.lane_count = param[0]; + prefer_link_settings.link_rate = param[1]; + +- dp_retrain_link_dp_test(link, &prefer_link_settings, false); ++ dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true); + + kfree(wr_buf); + return size; +@@ -2907,10 +2908,13 @@ static int crc_win_update_set(void *data, u64 val) + struct amdgpu_device *adev = drm_to_adev(new_crtc->dev); + struct crc_rd_work *crc_rd_wrk = adev->dm.crc_rd_wrk; + ++ if (!crc_rd_wrk) ++ return 0; ++ + if (val) { + spin_lock_irq(&adev_to_drm(adev)->event_lock); + spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock); +- if (crc_rd_wrk && crc_rd_wrk->crtc) { ++ if (crc_rd_wrk->crtc) { + old_crtc = crc_rd_wrk->crtc; + old_acrtc = to_amdgpu_crtc(old_crtc); + } +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index 6fee12c91ef59..d793eec69d61e 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -40,6 +40,39 @@ + + #include "dm_helpers.h" + ++struct monitor_patch_info { ++ unsigned int manufacturer_id; ++ unsigned int product_id; ++ void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param); ++ unsigned int patch_param; ++}; ++static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param); ++ ++static const struct monitor_patch_info monitor_patch_table[] = { ++{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15}, ++{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15}, ++}; ++ ++static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param) ++{ ++ if (edid_caps) ++ edid_caps->panel_patch.max_dsc_target_bpp_limit = param; ++} ++ ++static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps) ++{ ++ int i, ret = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++) ++ if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id) ++ && (edid_caps->product_id == monitor_patch_table[i].product_id)) { ++ monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param); ++ ret++; ++ } ++ ++ return ret; ++} ++ + /* dm_helpers_parse_edid_caps + * + * Parse edid caps +@@ -125,6 +158,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps( + kfree(sads); + kfree(sadb); + ++ amdgpu_dm_patch_edid_caps(edid_caps); ++ + return result; + } + +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 7af0d58c231b6..74885ff77f96a 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 +@@ -36,6 +36,8 @@ + #include "dm_helpers.h" + + #include "dc_link_ddc.h" ++#include "ddc_service_types.h" ++#include "dpcd_defs.h" + + #include "i2caux_interface.h" + #include "dmub_cmd.h" +@@ -155,6 +157,16 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { + }; + + #if defined(CONFIG_DRM_AMD_DC_DCN) ++static bool needs_dsc_aux_workaround(struct dc_link *link) ++{ ++ if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && ++ (link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) && ++ link->dpcd_caps.sink_count.bits.SINK_COUNT >= 2) ++ return true; ++ ++ return false; ++} ++ + static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector) + { + struct dc_sink *dc_sink = aconnector->dc_sink; +@@ -164,7 +176,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto + u8 *dsc_branch_dec_caps = NULL; + + aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port); +-#if defined(CONFIG_HP_HOOK_WORKAROUND) ++ + /* + * drm_dp_mst_dsc_aux_for_port() will return NULL for certain configs + * because it only check the dsc/fec caps of the "port variable" and not the dock +@@ -174,10 +186,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto + * Workaround: explicitly check the use case above and use the mst dock's aux as dsc_aux + * + */ +- +- if (!aconnector->dsc_aux && !port->parent->port_parent) ++ if (!aconnector->dsc_aux && !port->parent->port_parent && ++ needs_dsc_aux_workaround(aconnector->dc_link)) + aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; +-#endif ++ + if (!aconnector->dsc_aux) + return false; + +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +index bb31541f80723..6420527fe476c 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +@@ -306,8 +306,7 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) + case FAMILY_NV: + if (ASICREV_IS_SIENNA_CICHLID_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { + dcn3_clk_mgr_destroy(clk_mgr); +- } +- if (ASICREV_IS_DIMGREY_CAVEFISH_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { ++ } else if (ASICREV_IS_DIMGREY_CAVEFISH_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { + dcn3_clk_mgr_destroy(clk_mgr); + } + if (ASICREV_IS_BEIGE_GOBY_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +index 1861a147a7fa1..5c5cbeb59c4d9 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +@@ -437,8 +437,10 @@ static void dcn3_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) + clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1; + + /* Refresh bounding box */ ++ DC_FP_START(); + clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box( + clk_mgr->base.ctx->dc, clk_mgr_base->bw_params); ++ DC_FP_END(); + } + + static bool dcn3_is_smu_present(struct clk_mgr *clk_mgr_base) +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +index 7046da14bb2a5..329ce4e84b83c 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +@@ -582,32 +582,32 @@ static struct wm_table lpddr5_wm_table = { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, +- .sr_exit_time_us = 5.32, +- .sr_enter_plus_exit_time_us = 6.38, ++ .sr_exit_time_us = 13.5, ++ .sr_enter_plus_exit_time_us = 16.5, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, +- .sr_exit_time_us = 9.82, +- .sr_enter_plus_exit_time_us = 11.196, ++ .sr_exit_time_us = 13.5, ++ .sr_enter_plus_exit_time_us = 16.5, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, +- .sr_exit_time_us = 9.89, +- .sr_enter_plus_exit_time_us = 11.24, ++ .sr_exit_time_us = 13.5, ++ .sr_enter_plus_exit_time_us = 16.5, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, +- .sr_exit_time_us = 9.748, +- .sr_enter_plus_exit_time_us = 11.102, ++ .sr_exit_time_us = 13.5, ++ .sr_enter_plus_exit_time_us = 16.5, + .valid = true, + }, + } +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +index 377c4e53a2b37..8f6e6496ea787 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +@@ -157,6 +157,7 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, + union display_idle_optimization_u idle_info = { 0 }; + idle_info.idle_info.df_request_disabled = 1; + idle_info.idle_info.phy_ref_clk_off = 1; ++ idle_info.idle_info.s0i2_rdy = 1; + dcn31_smu_set_display_idle_optimization(clk_mgr, idle_info.data); + /* update power state */ + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; +@@ -323,38 +324,38 @@ static struct clk_bw_params dcn31_bw_params = { + + }; + +-static struct wm_table ddr4_wm_table = { ++static struct wm_table ddr5_wm_table = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, +- .sr_exit_time_us = 6.09, +- .sr_enter_plus_exit_time_us = 7.14, ++ .sr_exit_time_us = 9, ++ .sr_enter_plus_exit_time_us = 11, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, +- .sr_exit_time_us = 10.12, +- .sr_enter_plus_exit_time_us = 11.48, ++ .sr_exit_time_us = 9, ++ .sr_enter_plus_exit_time_us = 11, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, +- .sr_exit_time_us = 10.12, +- .sr_enter_plus_exit_time_us = 11.48, ++ .sr_exit_time_us = 9, ++ .sr_enter_plus_exit_time_us = 11, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, +- .sr_exit_time_us = 10.12, +- .sr_enter_plus_exit_time_us = 11.48, ++ .sr_exit_time_us = 9, ++ .sr_enter_plus_exit_time_us = 11, + .valid = true, + }, + } +@@ -682,7 +683,7 @@ void dcn31_clk_mgr_construct( + if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { + dcn31_bw_params.wm_table = lpddr5_wm_table; + } else { +- dcn31_bw_params.wm_table = ddr4_wm_table; ++ dcn31_bw_params.wm_table = ddr5_wm_table; + } + /* Saved clocks configured at boot for debug purposes */ + dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c +index 8c2b77eb94593..21d2cbc3cbb20 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c +@@ -119,6 +119,16 @@ int dcn31_smu_send_msg_with_param( + + result = dcn31_smu_wait_for_response(clk_mgr, 10, 200000); + ++ if (result == VBIOSSMC_Result_Failed) { ++ if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu && ++ param == TABLE_WATERMARKS) ++ DC_LOG_WARNING("Watermarks table not configured properly by SMU"); ++ else ++ ASSERT(0); ++ REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Result_OK); ++ return -1; ++ } ++ + if (IS_SMU_TIMEOUT(result)) { + ASSERT(0); + dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000); +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index c798c65d42765..b37c4d2e7a1e0 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -891,10 +891,13 @@ static bool dc_construct(struct dc *dc, + goto fail; + #ifdef CONFIG_DRM_AMD_DC_DCN + dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present; +-#endif + +- if (dc->res_pool->funcs->update_bw_bounding_box) ++ if (dc->res_pool->funcs->update_bw_bounding_box) { ++ DC_FP_START(); + dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); ++ DC_FP_END(); ++ } ++#endif + + /* Creation of current_state must occur after dc->dml + * is initialized in dc_create_resource_pool because +@@ -1118,6 +1121,8 @@ struct dc *dc_create(const struct dc_init_data *init_params) + + dc->caps.max_dp_protocol_version = DP_VERSION_1_4; + ++ dc->caps.max_otg_num = dc->res_pool->res_cap->num_timing_generator; ++ + if (dc->res_pool->dmcu != NULL) + dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version; + } +@@ -2703,7 +2708,8 @@ static void commit_planes_for_stream(struct dc *dc, + #endif + + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) +- if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { ++ if (top_pipe_to_program && ++ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { + if (should_use_dmub_lock(stream->link)) { + union dmub_hw_lock_flags hw_locks = { 0 }; + struct dmub_hw_lock_inst_flags inst_flags = { 0 }; +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +index 1e44b13c1c7de..3c4205248efc2 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +@@ -1696,6 +1696,8 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx) + union down_spread_ctrl old_downspread; + union down_spread_ctrl new_downspread; + ++ memset(&old_downspread, 0, sizeof(old_downspread)); ++ + core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, + &old_downspread.raw, sizeof(old_downspread)); + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +index 6d655e158267a..605b96873d8cd 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +@@ -3650,7 +3650,9 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) + lttpr_dpcd_data, + sizeof(lttpr_dpcd_data)); + if (status != DC_OK) { +- dm_error("%s: Read LTTPR caps data failed.\n", __func__); ++#if defined(CONFIG_DRM_AMD_DC_DCN) ++ DC_LOG_DP2("%s: Read LTTPR caps data failed.\n", __func__); ++#endif + return false; + } + +@@ -3913,6 +3915,26 @@ static bool retrieve_link_cap(struct dc_link *link) + dp_hw_fw_revision.ieee_fw_rev, + sizeof(dp_hw_fw_revision.ieee_fw_rev)); + ++ /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */ ++ { ++ uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 }; ++ uint8_t fwrev_mbp_2018[] = { 7, 4 }; ++ uint8_t fwrev_mbp_2018_vega[] = { 8, 4 }; ++ ++ /* We also check for the firmware revision as 16,1 models have an ++ * identical device id and are incorrectly quirked otherwise. ++ */ ++ if ((link->dpcd_caps.sink_dev_id == 0x0010fa) && ++ !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018, ++ sizeof(str_mbp_2018)) && ++ (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018, ++ sizeof(fwrev_mbp_2018)) || ++ !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega, ++ sizeof(fwrev_mbp_2018_vega)))) { ++ link->reported_link_cap.link_rate = LINK_RATE_RBR2; ++ } ++ } ++ + memset(&link->dpcd_caps.dsc_caps, '\0', + sizeof(link->dpcd_caps.dsc_caps)); + memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); +@@ -4690,7 +4712,7 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready) + link_enc->funcs->fec_set_ready(link_enc, true); + link->fec_state = dc_link_fec_ready; + } else { +- link_enc->funcs->fec_set_ready(link->link_enc, false); ++ link_enc->funcs->fec_set_ready(link_enc, false); + link->fec_state = dc_link_fec_not_ready; + dm_error("dpcd write failed to set fec_ready"); + } +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +index a60396d5be445..7ae409f7dcf8d 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -1623,6 +1623,10 @@ bool dc_is_stream_unchanged( + if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) + return false; + ++ // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks ++ if (old_stream->audio_info.mode_count != stream->audio_info.mode_count) ++ return false; ++ + return true; + } + +@@ -1795,9 +1799,6 @@ enum dc_status dc_remove_stream_from_ctx( + dc->res_pool, + del_pipe->stream_res.stream_enc, + false); +- /* Release link encoder from stream in new dc_state. */ +- if (dc->res_pool->funcs->link_enc_unassign) +- dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); + + if (del_pipe->stream_res.audio) + update_audio_usage( +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 3ab52d9a82cf6..e0f58fab5e8ed 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -185,6 +185,7 @@ struct dc_caps { + struct dc_color_caps color; + bool vbios_lttpr_aware; + bool vbios_lttpr_enable; ++ uint32_t max_otg_num; + }; + + struct dc_bug_wa { +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index df8a7718a85fc..3af49cdf89ebd 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -1522,7 +1522,7 @@ void dcn10_power_down_on_boot(struct dc *dc) + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + +- if (link->link_enc->funcs->is_dig_enabled && ++ if (link->link_enc && link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + dc->hwss.power_down) { + dc->hwss.power_down(dc); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +index 34001a30d449a..10e613ec7d24f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +@@ -78,6 +78,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { + .get_clock = dcn10_get_clock, + .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, + .calc_vupdate_position = dcn10_calc_vupdate_position, ++ .power_down = dce110_power_down, + .set_backlight_level = dce110_set_backlight_level, + .set_abm_immediate_disable = dce110_set_abm_immediate_disable, + .set_pipe = dce110_set_pipe, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +index e3e01b17c164e..ede11eb120d4f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +@@ -1854,7 +1854,9 @@ static void swizzle_to_dml_params( + case DC_SW_VAR_D_X: + *sw_mode = dm_sw_var_d_x; + break; +- ++ case DC_SW_VAR_R_X: ++ *sw_mode = dm_sw_var_r_x; ++ break; + default: + ASSERT(0); /* Not supported */ + break; +@@ -3152,7 +3154,7 @@ void dcn20_calculate_dlg_params( + + context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml, + &context->res_ctx.pipe_ctx[i].rq_regs, +- pipes[pipe_idx].pipe); ++ &pipes[pipe_idx].pipe); + pipe_idx++; + } + } +@@ -3668,16 +3670,22 @@ static bool init_soc_bounding_box(struct dc *dc, + clock_limits_available = (status == PP_SMU_RESULT_OK); + } + +- if (clock_limits_available && uclk_states_available && num_states) ++ if (clock_limits_available && uclk_states_available && num_states) { ++ DC_FP_START(); + dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states); +- else if (clock_limits_available) ++ DC_FP_END(); ++ } else if (clock_limits_available) { ++ DC_FP_START(); + dcn20_cap_soc_clocks(loaded_bb, max_clocks); ++ DC_FP_END(); ++ } + } + + loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator; + loaded_ip->max_num_dpp = pool->base.pipe_count; ++ DC_FP_START(); + dcn20_patch_bounding_box(dc, loaded_bb); +- ++ DC_FP_END(); + return true; + } + +@@ -3697,8 +3705,6 @@ static bool dcn20_resource_construct( + enum dml_project dml_project_version = + get_dml_project_version(ctx->asic_id.hw_internal_rev); + +- DC_FP_START(); +- + ctx->dc_bios->regs = &bios_regs; + pool->base.funcs = &dcn20_res_pool_funcs; + +@@ -4047,12 +4053,10 @@ static bool dcn20_resource_construct( + pool->base.oem_device = NULL; + } + +- DC_FP_END(); + return true; + + create_fail: + +- DC_FP_END(); + dcn20_resource_destruct(pool); + + return false; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +index fbbdf99761838..92a308ad1213c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +@@ -874,7 +874,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .clock_trace = true, + .disable_pplib_clock_request = true, + .min_disp_clk_khz = 100000, +- .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, ++ .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +index fafed1e4a998d..0950784bafa49 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +@@ -1002,7 +1002,8 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc, + /* turning off DPG */ + pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false); + for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) +- mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false); ++ if (mpcc_pipe->plane_res.hubp) ++ mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false); + + stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space, + color_depth, solid_color, width, height, offset); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +index a0de309475a97..0294d0cc47595 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +@@ -840,7 +840,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, +- .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, ++ .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, +@@ -1879,7 +1879,6 @@ static noinline bool dcn30_internal_validate_bw( + dc->res_pool->funcs->update_soc_for_wm_a(dc, context); + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + +- DC_FP_START(); + if (!pipe_cnt) { + out = true; + goto validate_out; +@@ -2103,7 +2102,6 @@ validate_fail: + out = false; + + validate_out: +- DC_FP_END(); + return out; + } + +@@ -2304,7 +2302,9 @@ bool dcn30_validate_bandwidth(struct dc *dc, + + BW_VAL_TRACE_COUNT(); + ++ DC_FP_START(); + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); ++ DC_FP_END(); + + if (pipe_cnt == 0) + goto validate_out; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +index 912285fdce18e..dea358b01791c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +@@ -863,7 +863,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .disable_clock_gate = true, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, +- .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, ++ .pipe_split_policy = MPC_SPLIT_AVOID, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, +@@ -1622,12 +1622,106 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b + dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); + } + ++static void calculate_wm_set_for_vlevel( ++ int vlevel, ++ struct wm_range_table_entry *table_entry, ++ struct dcn_watermarks *wm_set, ++ struct display_mode_lib *dml, ++ display_e2e_pipe_params_st *pipes, ++ int pipe_cnt) ++{ ++ double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us; ++ ++ ASSERT(vlevel < dml->soc.num_states); ++ /* only pipe 0 is read for voltage and dcf/soc clocks */ ++ pipes[0].clks_cfg.voltage = vlevel; ++ pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz; ++ pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz; ++ ++ dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us; ++ dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us; ++ dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us; ++ ++ wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000; ++ wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000; ++ wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000; ++ wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000; ++ wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000; ++ wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000; ++ wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000; ++ wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000; ++ dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached; ++ ++} ++ ++static void dcn301_calculate_wm_and_dlg( ++ struct dc *dc, struct dc_state *context, ++ display_e2e_pipe_params_st *pipes, ++ int pipe_cnt, ++ int vlevel_req) ++{ ++ int i, pipe_idx; ++ int vlevel, vlevel_max; ++ struct wm_range_table_entry *table_entry; ++ struct clk_bw_params *bw_params = dc->clk_mgr->bw_params; ++ ++ ASSERT(bw_params); ++ ++ vlevel_max = bw_params->clk_table.num_entries - 1; ++ ++ /* WM Set D */ ++ table_entry = &bw_params->wm_table.entries[WM_D]; ++ if (table_entry->wm_type == WM_TYPE_RETRAINING) ++ vlevel = 0; ++ else ++ vlevel = vlevel_max; ++ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d, ++ &context->bw_ctx.dml, pipes, pipe_cnt); ++ /* WM Set C */ ++ table_entry = &bw_params->wm_table.entries[WM_C]; ++ vlevel = min(max(vlevel_req, 2), vlevel_max); ++ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c, ++ &context->bw_ctx.dml, pipes, pipe_cnt); ++ /* WM Set B */ ++ table_entry = &bw_params->wm_table.entries[WM_B]; ++ vlevel = min(max(vlevel_req, 1), vlevel_max); ++ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b, ++ &context->bw_ctx.dml, pipes, pipe_cnt); ++ ++ /* WM Set A */ ++ table_entry = &bw_params->wm_table.entries[WM_A]; ++ vlevel = min(vlevel_req, vlevel_max); ++ calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a, ++ &context->bw_ctx.dml, pipes, pipe_cnt); ++ ++ for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { ++ if (!context->res_ctx.pipe_ctx[i].stream) ++ continue; ++ ++ pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); ++ pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); ++ ++ if (dc->config.forced_clocks) { ++ pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; ++ pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; ++ } ++ if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000) ++ pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; ++ if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) ++ pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; ++ ++ pipe_idx++; ++ } ++ ++ dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); ++} ++ + static struct resource_funcs dcn301_res_pool_funcs = { + .destroy = dcn301_destroy_resource_pool, + .link_enc_create = dcn301_link_encoder_create, + .panel_cntl_create = dcn301_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, +- .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, ++ .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +index 7d3ff5d444023..2292bb82026e2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +@@ -211,7 +211,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, +- .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, ++ .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +index dd38796ba30ad..589ddab61c2a9 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +@@ -193,7 +193,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, +- .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, ++ .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +index 90c73a1cb9861..5e3bcaf12cac4 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +@@ -138,8 +138,11 @@ static uint32_t convert_and_clamp( + ret_val = wm_ns * refclk_mhz; + ret_val /= 1000; + +- if (ret_val > clamp_value) ++ if (ret_val > clamp_value) { ++ /* clamping WMs is abnormal, unexpected and may lead to underflow*/ ++ ASSERT(0); + ret_val = clamp_value; ++ } + + return ret_val; + } +@@ -159,7 +162,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) { + hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); + +@@ -193,7 +196,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) { + hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns; + prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value); + } else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns) +@@ -203,7 +206,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) { + hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); + +@@ -237,7 +240,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) { + hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns; + prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value); + } else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns) +@@ -247,7 +250,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) { + hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); + +@@ -281,7 +284,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) { + hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns; + prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value); + } else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns) +@@ -291,7 +294,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) { + hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns; + prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, + DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); + +@@ -325,7 +328,7 @@ static bool hubbub31_program_urgent_watermarks( + if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) { + hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns; + prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0x3fff); + REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0, + DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value); + } else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns) +@@ -351,7 +354,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" +@@ -367,7 +370,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->a.cstate_pstate.cstate_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n" +@@ -383,7 +386,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n" +@@ -399,7 +402,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->a.cstate_pstate.cstate_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.cstate_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n" +@@ -416,7 +419,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n" +@@ -432,7 +435,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->b.cstate_pstate.cstate_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n" +@@ -448,7 +451,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n" +@@ -464,7 +467,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->b.cstate_pstate.cstate_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.cstate_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n" +@@ -481,7 +484,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n" +@@ -497,7 +500,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->c.cstate_pstate.cstate_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n" +@@ -513,7 +516,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n" +@@ -529,7 +532,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->c.cstate_pstate.cstate_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.cstate_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n" +@@ -546,7 +549,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n" +@@ -562,7 +565,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->d.cstate_pstate.cstate_exit_ns; + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n" +@@ -578,7 +581,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0, + DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n" +@@ -594,7 +597,7 @@ static bool hubbub31_program_stutter_watermarks( + watermarks->d.cstate_pstate.cstate_exit_z8_ns; + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.cstate_exit_z8_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0, + DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n" +@@ -625,7 +628,7 @@ static bool hubbub31_program_pstate_watermarks( + watermarks->a.cstate_pstate.pstate_change_ns; + prog_wm_value = convert_and_clamp( + watermarks->a.cstate_pstate.pstate_change_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0, + DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" +@@ -642,7 +645,7 @@ static bool hubbub31_program_pstate_watermarks( + watermarks->b.cstate_pstate.pstate_change_ns; + prog_wm_value = convert_and_clamp( + watermarks->b.cstate_pstate.pstate_change_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0, + DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n" +@@ -659,7 +662,7 @@ static bool hubbub31_program_pstate_watermarks( + watermarks->c.cstate_pstate.pstate_change_ns; + prog_wm_value = convert_and_clamp( + watermarks->c.cstate_pstate.pstate_change_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0, + DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n" +@@ -676,7 +679,7 @@ static bool hubbub31_program_pstate_watermarks( + watermarks->d.cstate_pstate.pstate_change_ns; + prog_wm_value = convert_and_clamp( + watermarks->d.cstate_pstate.pstate_change_ns, +- refclk_mhz, 0x1fffff); ++ refclk_mhz, 0xffff); + REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0, + DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); + DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c +index 40011cd3c8ef0..4e9fe090b770a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c +@@ -100,6 +100,8 @@ static const struct hw_sequencer_funcs dcn31_funcs = { + .z10_save_init = dcn31_z10_save_init, + .is_abm_supported = dcn31_is_abm_supported, + .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, ++ .optimize_pwr_state = dcn21_optimize_pwr_state, ++ .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, + .update_visual_confirm_color = dcn20_update_visual_confirm_color, + }; + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +index 79e92ecca96c1..d4fe5352421fc 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +@@ -352,6 +352,14 @@ static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(3, D), + clk_src_regs(4, E) + }; ++/*pll_id being rempped in dmub, in driver it is logical instance*/ ++static const struct dce110_clk_src_regs clk_src_regs_b0[] = { ++ clk_src_regs(0, A), ++ clk_src_regs(1, B), ++ clk_src_regs(2, F), ++ clk_src_regs(3, G), ++ clk_src_regs(4, E) ++}; + + static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +@@ -462,7 +470,8 @@ static const struct dcn30_afmt_mask afmt_mask = { + SE_DCN3_REG_LIST(id)\ + } + +-static const struct dcn10_stream_enc_registers stream_enc_regs[] = { ++/* Some encoders won't be initialized here - but they're logical, not physical. */ ++static const struct dcn10_stream_enc_registers stream_enc_regs[ENGINE_ID_COUNT] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), +@@ -923,7 +932,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = false, +- .pipe_split_policy = MPC_SPLIT_AVOID, ++ .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, +@@ -2019,14 +2028,27 @@ static bool dcn31_resource_construct( + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); +- pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = ++ /*move phypllx_pixclk_resync to dmub next*/ ++ if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) { ++ pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = ++ dcn30_clock_source_create(ctx, ctx->dc_bios, ++ CLOCK_SOURCE_COMBO_PHY_PLL2, ++ &clk_src_regs_b0[2], false); ++ pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = ++ dcn30_clock_source_create(ctx, ctx->dc_bios, ++ CLOCK_SOURCE_COMBO_PHY_PLL3, ++ &clk_src_regs_b0[3], false); ++ } else { ++ pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL2, + &clk_src_regs[2], false); +- pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = ++ pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL3, + &clk_src_regs[3], false); ++ } ++ + pool->base.clock_sources[DCN31_CLK_SRC_PLL4] = + dcn30_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL4, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h +index 93571c9769967..cc4bed675588c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h +@@ -39,4 +39,35 @@ struct resource_pool *dcn31_create_resource_pool( + const struct dc_init_data *init_data, + struct dc *dc); + ++/*temp: B0 specific before switch to dcn313 headers*/ ++#ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL ++#define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e ++#define regPHYPLLF_PIXCLK_RESYNC_CNTL_BASE_IDX 1 ++#define regPHYPLLG_PIXCLK_RESYNC_CNTL 0x005f ++#define regPHYPLLG_PIXCLK_RESYNC_CNTL_BASE_IDX 1 ++ ++//PHYPLLF_PIXCLK_RESYNC_CNTL ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE__SHIFT 0x8 ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE_MASK 0x00000100L ++#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L ++ ++//PHYPLLG_PIXCLK_RESYNC_CNTL ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE__SHIFT 0x8 ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE_MASK 0x00000100L ++#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L ++#endif + #endif /* _DCN31_RESOURCE_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile +index 56055df2e8d2e..9009b92490f34 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile ++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile +@@ -70,6 +70,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram + CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) + CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag) + CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags) ++CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags) + CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) + CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) + CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags) +@@ -84,6 +85,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_rcfla + CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_rcflags) + CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_rcflags) + CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags) ++CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_rcflags) + endif + CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags) + CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags) +@@ -99,6 +101,7 @@ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o + DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o + DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o + DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o ++DML += dsc/rc_calc_fpu.o + endif + + AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +index 2091dd8c252da..8c168f348a27f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +@@ -768,12 +768,12 @@ static void dml20_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + + void dml20_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param) ++ const display_pipe_params_st *pipe_param) + { + display_rq_params_st rq_param = {0}; + + memset(rq_regs, 0, sizeof(*rq_regs)); +- dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param.src); ++ dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); + extract_rq_regs(mode_lib, rq_regs, rq_param); + + print__rq_regs_st(mode_lib, *rq_regs); +@@ -1549,7 +1549,7 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h +index d0b90947f5409..8b23867e97c18 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h +@@ -43,7 +43,7 @@ struct display_mode_lib; + void dml20_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param); ++ const display_pipe_params_st *pipe_param); + + + // Function: dml_rq_dlg_get_dlg_reg +@@ -61,7 +61,7 @@ void dml20_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +index 1a0c14e465faa..26ececfd40cdc 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +@@ -768,12 +768,12 @@ static void dml20v2_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + + void dml20v2_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param) ++ const display_pipe_params_st *pipe_param) + { + display_rq_params_st rq_param = {0}; + + memset(rq_regs, 0, sizeof(*rq_regs)); +- dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param.src); ++ dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); + extract_rq_regs(mode_lib, rq_regs, rq_param); + + print__rq_regs_st(mode_lib, *rq_regs); +@@ -1550,7 +1550,7 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h +index 27cf8bed9376f..2b4e46ea1c3df 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h +@@ -43,7 +43,7 @@ struct display_mode_lib; + void dml20v2_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param); ++ const display_pipe_params_st *pipe_param); + + + // Function: dml_rq_dlg_get_dlg_reg +@@ -61,7 +61,7 @@ void dml20v2_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +index 287e31052b307..736978c4d40a1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +@@ -694,7 +694,7 @@ static void get_surf_rq_param( + display_data_rq_sizing_params_st *rq_sizing_param, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, +- const display_pipe_params_st pipe_param, ++ const display_pipe_params_st *pipe_param, + bool is_chroma) + { + bool mode_422 = false; +@@ -706,30 +706,30 @@ static void get_surf_rq_param( + + // FIXME check if ppe apply for both luma and chroma in 422 case + if (is_chroma) { +- vp_width = pipe_param.src.viewport_width_c / ppe; +- vp_height = pipe_param.src.viewport_height_c; +- data_pitch = pipe_param.src.data_pitch_c; +- meta_pitch = pipe_param.src.meta_pitch_c; ++ vp_width = pipe_param->src.viewport_width_c / ppe; ++ vp_height = pipe_param->src.viewport_height_c; ++ data_pitch = pipe_param->src.data_pitch_c; ++ meta_pitch = pipe_param->src.meta_pitch_c; + } else { +- vp_width = pipe_param.src.viewport_width / ppe; +- vp_height = pipe_param.src.viewport_height; +- data_pitch = pipe_param.src.data_pitch; +- meta_pitch = pipe_param.src.meta_pitch; ++ vp_width = pipe_param->src.viewport_width / ppe; ++ vp_height = pipe_param->src.viewport_height; ++ data_pitch = pipe_param->src.data_pitch; ++ meta_pitch = pipe_param->src.meta_pitch; + } + +- if (pipe_param.dest.odm_combine) { ++ if (pipe_param->dest.odm_combine) { + unsigned int access_dir; + unsigned int full_src_vp_width; + unsigned int hactive_half; + unsigned int src_hactive_half; +- access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed +- hactive_half = pipe_param.dest.hactive / 2; ++ access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed ++ hactive_half = pipe_param->dest.hactive / 2; + if (is_chroma) { +- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; +- src_hactive_half = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_half; ++ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; ++ src_hactive_half = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_half; + } else { +- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; +- src_hactive_half = pipe_param.scale_ratio_depth.hscl_ratio * hactive_half; ++ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; ++ src_hactive_half = pipe_param->scale_ratio_depth.hscl_ratio * hactive_half; + } + + if (access_dir == 0) { +@@ -754,7 +754,7 @@ static void get_surf_rq_param( + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + +- if (pipe_param.src.hostvm) ++ if (pipe_param->src.hostvm) + rq_sizing_param->mpte_group_bytes = 512; + else + rq_sizing_param->mpte_group_bytes = 2048; +@@ -768,23 +768,23 @@ static void get_surf_rq_param( + vp_height, + data_pitch, + meta_pitch, +- pipe_param.src.source_format, +- pipe_param.src.sw_mode, +- pipe_param.src.macro_tile_size, +- pipe_param.src.source_scan, +- pipe_param.src.hostvm, ++ pipe_param->src.source_format, ++ pipe_param->src.sw_mode, ++ pipe_param->src.macro_tile_size, ++ pipe_param->src.source_scan, ++ pipe_param->src.hostvm, + is_chroma); + } + + static void dml_rq_dlg_get_rq_params( + struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, +- const display_pipe_params_st pipe_param) ++ const display_pipe_params_st *pipe_param) + { + // get param for luma surface +- rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 +- || pipe_param.src.source_format == dm_420_10; +- rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; ++ rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 ++ || pipe_param->src.source_format == dm_420_10; ++ rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; + + get_surf_rq_param( + mode_lib, +@@ -794,7 +794,7 @@ static void dml_rq_dlg_get_rq_params( + pipe_param, + 0); + +- if (is_dual_plane((enum source_format_class) (pipe_param.src.source_format))) { ++ if (is_dual_plane((enum source_format_class) (pipe_param->src.source_format))) { + // get param for chroma surface + get_surf_rq_param( + mode_lib, +@@ -806,14 +806,14 @@ static void dml_rq_dlg_get_rq_params( + } + + // calculate how to split the det buffer space between luma and chroma +- handle_det_buf_split(mode_lib, rq_param, pipe_param.src); ++ handle_det_buf_split(mode_lib, rq_param, pipe_param->src); + print__rq_params_st(mode_lib, *rq_param); + } + + void dml21_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param) ++ const display_pipe_params_st *pipe_param) + { + display_rq_params_st rq_param = {0}; + +@@ -1658,7 +1658,7 @@ void dml21_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +@@ -1696,7 +1696,7 @@ void dml21_rq_dlg_get_dlg_reg( + // system parameter calculation done + + dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); +- dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); ++ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); + dml_rq_dlg_get_dlg_params( + mode_lib, + e2e_pipe_param, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h +index e8f7785e3fc63..af6ad0ca9cf8a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h +@@ -44,7 +44,7 @@ struct display_mode_lib; + void dml21_rq_dlg_get_rq_reg( + struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param); ++ const display_pipe_params_st *pipe_param); + + // Function: dml_rq_dlg_get_dlg_reg + // Calculate and return DLG and TTU register struct given the system setting +@@ -61,7 +61,7 @@ void dml21_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +index 0d934fae1c3a6..2120e0941a095 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +@@ -747,7 +747,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, + display_data_rq_sizing_params_st *rq_sizing_param, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, +- const display_pipe_params_st pipe_param, ++ const display_pipe_params_st *pipe_param, + bool is_chroma, + bool is_alpha) + { +@@ -761,32 +761,32 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, + + // FIXME check if ppe apply for both luma and chroma in 422 case + if (is_chroma | is_alpha) { +- vp_width = pipe_param.src.viewport_width_c / ppe; +- vp_height = pipe_param.src.viewport_height_c; +- data_pitch = pipe_param.src.data_pitch_c; +- meta_pitch = pipe_param.src.meta_pitch_c; +- surface_height = pipe_param.src.surface_height_y / 2.0; ++ vp_width = pipe_param->src.viewport_width_c / ppe; ++ vp_height = pipe_param->src.viewport_height_c; ++ data_pitch = pipe_param->src.data_pitch_c; ++ meta_pitch = pipe_param->src.meta_pitch_c; ++ surface_height = pipe_param->src.surface_height_y / 2.0; + } else { +- vp_width = pipe_param.src.viewport_width / ppe; +- vp_height = pipe_param.src.viewport_height; +- data_pitch = pipe_param.src.data_pitch; +- meta_pitch = pipe_param.src.meta_pitch; +- surface_height = pipe_param.src.surface_height_y; ++ vp_width = pipe_param->src.viewport_width / ppe; ++ vp_height = pipe_param->src.viewport_height; ++ data_pitch = pipe_param->src.data_pitch; ++ meta_pitch = pipe_param->src.meta_pitch; ++ surface_height = pipe_param->src.surface_height_y; + } + +- if (pipe_param.dest.odm_combine) { ++ if (pipe_param->dest.odm_combine) { + unsigned int access_dir = 0; + unsigned int full_src_vp_width = 0; + unsigned int hactive_odm = 0; + unsigned int src_hactive_odm = 0; +- access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed +- hactive_odm = pipe_param.dest.hactive / ((unsigned int)pipe_param.dest.odm_combine*2); ++ access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed ++ hactive_odm = pipe_param->dest.hactive / ((unsigned int) pipe_param->dest.odm_combine*2); + if (is_chroma) { +- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; +- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_odm; ++ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; ++ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_odm; + } else { +- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; +- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio * hactive_odm; ++ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; ++ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio * hactive_odm; + } + + if (access_dir == 0) { +@@ -815,7 +815,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + +- if (pipe_param.src.hostvm) ++ if (pipe_param->src.hostvm) + rq_sizing_param->mpte_group_bytes = 512; + else + rq_sizing_param->mpte_group_bytes = 2048; +@@ -828,28 +828,28 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, + vp_height, + data_pitch, + meta_pitch, +- pipe_param.src.source_format, +- pipe_param.src.sw_mode, +- pipe_param.src.macro_tile_size, +- pipe_param.src.source_scan, +- pipe_param.src.hostvm, ++ pipe_param->src.source_format, ++ pipe_param->src.sw_mode, ++ pipe_param->src.macro_tile_size, ++ pipe_param->src.source_scan, ++ pipe_param->src.hostvm, + is_chroma, + surface_height); + } + + static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + display_rq_params_st *rq_param, +- const display_pipe_params_st pipe_param) ++ const display_pipe_params_st *pipe_param) + { + // get param for luma surface +- rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 +- || pipe_param.src.source_format == dm_420_10 +- || pipe_param.src.source_format == dm_rgbe_alpha +- || pipe_param.src.source_format == dm_420_12; ++ rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 ++ || pipe_param->src.source_format == dm_420_10 ++ || pipe_param->src.source_format == dm_rgbe_alpha ++ || pipe_param->src.source_format == dm_420_12; + +- rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; ++ rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; + +- rq_param->rgbe_alpha = (pipe_param.src.source_format == dm_rgbe_alpha)?1:0; ++ rq_param->rgbe_alpha = (pipe_param->src.source_format == dm_rgbe_alpha)?1:0; + + get_surf_rq_param(mode_lib, + &(rq_param->sizing.rq_l), +@@ -859,7 +859,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + 0, + 0); + +- if (is_dual_plane((enum source_format_class)(pipe_param.src.source_format))) { ++ if (is_dual_plane((enum source_format_class)(pipe_param->src.source_format))) { + // get param for chroma surface + get_surf_rq_param(mode_lib, + &(rq_param->sizing.rq_c), +@@ -871,13 +871,13 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, + } + + // calculate how to split the det buffer space between luma and chroma +- handle_det_buf_split(mode_lib, rq_param, pipe_param.src); ++ handle_det_buf_split(mode_lib, rq_param, pipe_param->src); + print__rq_params_st(mode_lib, *rq_param); + } + + void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param) ++ const display_pipe_params_st *pipe_param) + { + display_rq_params_st rq_param = { 0 }; + +@@ -1831,7 +1831,7 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, + void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +@@ -1866,7 +1866,7 @@ void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + // system parameter calculation done + + dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); +- dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); ++ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); + dml_rq_dlg_get_dlg_params(mode_lib, + e2e_pipe_param, + num_pipes, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h +index c04965cceff35..625e41f8d5751 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h +@@ -41,7 +41,7 @@ struct display_mode_lib; + // See also: <display_rq_regs_st> + void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param); ++ const display_pipe_params_st *pipe_param); + + // Function: dml_rq_dlg_get_dlg_reg + // Calculate and return DLG and TTU register struct given the system setting +@@ -57,7 +57,7 @@ void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +index c23905bc733ae..57bd4e3f8a823 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +@@ -738,7 +738,7 @@ static void get_surf_rq_param( + display_data_rq_sizing_params_st *rq_sizing_param, + display_data_rq_dlg_params_st *rq_dlg_param, + display_data_rq_misc_params_st *rq_misc_param, +- const display_pipe_params_st pipe_param, ++ const display_pipe_params_st *pipe_param, + bool is_chroma, + bool is_alpha) + { +@@ -752,33 +752,33 @@ static void get_surf_rq_param( + + // FIXME check if ppe apply for both luma and chroma in 422 case + if (is_chroma | is_alpha) { +- vp_width = pipe_param.src.viewport_width_c / ppe; +- vp_height = pipe_param.src.viewport_height_c; +- data_pitch = pipe_param.src.data_pitch_c; +- meta_pitch = pipe_param.src.meta_pitch_c; +- surface_height = pipe_param.src.surface_height_y / 2.0; ++ vp_width = pipe_param->src.viewport_width_c / ppe; ++ vp_height = pipe_param->src.viewport_height_c; ++ data_pitch = pipe_param->src.data_pitch_c; ++ meta_pitch = pipe_param->src.meta_pitch_c; ++ surface_height = pipe_param->src.surface_height_y / 2.0; + } else { +- vp_width = pipe_param.src.viewport_width / ppe; +- vp_height = pipe_param.src.viewport_height; +- data_pitch = pipe_param.src.data_pitch; +- meta_pitch = pipe_param.src.meta_pitch; +- surface_height = pipe_param.src.surface_height_y; ++ vp_width = pipe_param->src.viewport_width / ppe; ++ vp_height = pipe_param->src.viewport_height; ++ data_pitch = pipe_param->src.data_pitch; ++ meta_pitch = pipe_param->src.meta_pitch; ++ surface_height = pipe_param->src.surface_height_y; + } + +- if (pipe_param.dest.odm_combine) { ++ if (pipe_param->dest.odm_combine) { + unsigned int access_dir; + unsigned int full_src_vp_width; + unsigned int hactive_odm; + unsigned int src_hactive_odm; + +- access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed +- hactive_odm = pipe_param.dest.hactive / ((unsigned int) pipe_param.dest.odm_combine * 2); ++ access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed ++ hactive_odm = pipe_param->dest.hactive / ((unsigned int) pipe_param->dest.odm_combine * 2); + if (is_chroma) { +- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; +- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_odm; ++ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; ++ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_odm; + } else { +- full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; +- src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio * hactive_odm; ++ full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; ++ src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio * hactive_odm; + } + + if (access_dir == 0) { +@@ -808,7 +808,7 @@ static void get_surf_rq_param( + rq_sizing_param->meta_chunk_bytes = 2048; + rq_sizing_param->min_meta_chunk_bytes = 256; + +- if (pipe_param.src.hostvm) ++ if (pipe_param->src.hostvm) + rq_sizing_param->mpte_group_bytes = 512; + else + rq_sizing_param->mpte_group_bytes = 2048; +@@ -822,38 +822,38 @@ static void get_surf_rq_param( + vp_height, + data_pitch, + meta_pitch, +- pipe_param.src.source_format, +- pipe_param.src.sw_mode, +- pipe_param.src.macro_tile_size, +- pipe_param.src.source_scan, +- pipe_param.src.hostvm, ++ pipe_param->src.source_format, ++ pipe_param->src.sw_mode, ++ pipe_param->src.macro_tile_size, ++ pipe_param->src.source_scan, ++ pipe_param->src.hostvm, + is_chroma, + surface_height); + } + +-static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_params_st pipe_param) ++static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_params_st *pipe_param) + { + // get param for luma surface +- rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 || pipe_param.src.source_format == dm_420_10 || pipe_param.src.source_format == dm_rgbe_alpha +- || pipe_param.src.source_format == dm_420_12; ++ rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 || pipe_param->src.source_format == dm_420_10 || pipe_param->src.source_format == dm_rgbe_alpha ++ || pipe_param->src.source_format == dm_420_12; + +- rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; ++ rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; + +- rq_param->rgbe_alpha = (pipe_param.src.source_format == dm_rgbe_alpha) ? 1 : 0; ++ rq_param->rgbe_alpha = (pipe_param->src.source_format == dm_rgbe_alpha) ? 1 : 0; + + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), &(rq_param->dlg.rq_l), &(rq_param->misc.rq_l), pipe_param, 0, 0); + +- if (is_dual_plane((enum source_format_class) (pipe_param.src.source_format))) { ++ if (is_dual_plane((enum source_format_class) (pipe_param->src.source_format))) { + // get param for chroma surface + get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), &(rq_param->dlg.rq_c), &(rq_param->misc.rq_c), pipe_param, 1, rq_param->rgbe_alpha); + } + + // calculate how to split the det buffer space between luma and chroma +- handle_det_buf_split(mode_lib, rq_param, pipe_param.src); ++ handle_det_buf_split(mode_lib, rq_param, pipe_param->src); + print__rq_params_st(mode_lib, *rq_param); + } + +-void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st pipe_param) ++void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st *pipe_param) + { + display_rq_params_st rq_param = {0}; + +@@ -1677,7 +1677,7 @@ void dml31_rq_dlg_get_dlg_reg( + struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +@@ -1704,7 +1704,7 @@ void dml31_rq_dlg_get_dlg_reg( + // system parameter calculation done + + dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); +- dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); ++ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); + dml_rq_dlg_get_dlg_params( + mode_lib, + e2e_pipe_param, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h +index adf8518f761f9..8ee991351699d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h +@@ -41,7 +41,7 @@ struct display_mode_lib; + // See also: <display_rq_regs_st> + void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param); ++ const display_pipe_params_st *pipe_param); + + // Function: dml_rq_dlg_get_dlg_reg + // Calculate and return DLG and TTU register struct given the system setting +@@ -57,7 +57,7 @@ void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, + void dml31_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +index 1051ca1a23b8a..edb9f7567d6d9 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +@@ -80,11 +80,11 @@ enum dm_swizzle_mode { + dm_sw_SPARE_13 = 24, + dm_sw_64kb_s_x = 25, + dm_sw_64kb_d_x = 26, +- dm_sw_SPARE_14 = 27, ++ dm_sw_64kb_r_x = 27, + dm_sw_SPARE_15 = 28, + dm_sw_var_s_x = 29, + dm_sw_var_d_x = 30, +- dm_sw_64kb_r_x, ++ dm_sw_var_r_x = 31, + dm_sw_gfx7_2d_thin_l_vp, + dm_sw_gfx7_2d_thin_gl, + }; +diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +index d42a0aeca6be2..72b1957022aa2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +@@ -49,7 +49,7 @@ struct dml_funcs { + struct display_mode_lib *mode_lib, + display_dlg_regs_st *dlg_regs, + display_ttu_regs_st *ttu_regs, +- display_e2e_pipe_params_st *e2e_pipe_param, ++ const display_e2e_pipe_params_st *e2e_pipe_param, + const unsigned int num_pipes, + const unsigned int pipe_idx, + const bool cstate_en, +@@ -60,7 +60,7 @@ struct dml_funcs { + void (*rq_dlg_get_rq_reg)( + struct display_mode_lib *mode_lib, + display_rq_regs_st *rq_regs, +- const display_pipe_params_st pipe_param); ++ const display_pipe_params_st *pipe_param); + void (*recalculate)(struct display_mode_lib *mode_lib); + void (*validate)(struct display_mode_lib *mode_lib); + }; +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h +new file mode 100644 +index 0000000000000..e5fac9f4181d8 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h +@@ -0,0 +1,704 @@ ++ ++/* ++ * Copyright 2017 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++ ++const qp_table qp_table_422_10bpc_min = { ++ { 6, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} }, ++ { 6.5, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} }, ++ { 7, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 7, 9, 9, 9, 11, 15} }, ++ { 7.5, { 0, 2, 4, 6, 6, 6, 6, 7, 7, 7, 8, 9, 9, 11, 15} }, ++ { 8, { 0, 2, 3, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 11, 14} }, ++ { 8.5, { 0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 14} }, ++ { 9, { 0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 13} }, ++ { 9.5, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 13} }, ++ { 10, { 0, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12} }, ++ {10.5, { 0, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 11, 12} }, ++ { 11, { 0, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11} }, ++ {11.5, { 0, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 10, 11} }, ++ { 12, { 0, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10} }, ++ {12.5, { 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} }, ++ { 13, { 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 9} }, ++ {13.5, { 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 9} }, ++ { 14, { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8} }, ++ {14.5, { 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8} }, ++ { 15, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 6, 8} }, ++ {15.5, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, ++ { 16, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 7} }, ++ {16.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6} }, ++ { 17, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 6} }, ++ {17.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, ++ { 18, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 5} }, ++ {18.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 5} }, ++ { 19, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 4} }, ++ {19.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 4} }, ++ { 20, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 3} } ++}; ++ ++ ++const qp_table qp_table_444_8bpc_max = { ++ { 6, { 4, 6, 8, 8, 9, 9, 9, 10, 11, 12, 12, 12, 12, 13, 15} }, ++ { 6.5, { 4, 6, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 12, 13, 15} }, ++ { 7, { 4, 5, 7, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 13, 14} }, ++ { 7.5, { 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, ++ { 8, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, ++ { 8.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, ++ { 9, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} }, ++ { 9.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} }, ++ { 10, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, ++ {10.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 11, 12} }, ++ { 11, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11} }, ++ {11.5, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, ++ { 12, { 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, ++ {12.5, { 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, ++ { 13, { 1, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 10} }, ++ {13.5, { 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10} }, ++ { 14, { 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} }, ++ {14.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9} }, ++ { 15, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, ++ {15.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, ++ { 16, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8} }, ++ {16.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8} }, ++ { 17, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 8} }, ++ {17.5, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 8} }, ++ { 18, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7} }, ++ {18.5, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7} }, ++ { 19, { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6} }, ++ {19.5, { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6} }, ++ { 20, { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 6} }, ++ {20.5, { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 6} }, ++ { 21, { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, ++ {21.5, { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, ++ { 22, { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} }, ++ {22.5, { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} }, ++ { 23, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4} }, ++ {23.5, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4} }, ++ { 24, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_420_12bpc_max = { ++ { 4, {11, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 21, 22} }, ++ { 4.5, {10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, ++ { 5, { 9, 11, 12, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 20, 21} }, ++ { 5.5, { 8, 10, 11, 12, 13, 14, 15, 16, 16, 17, 17, 18, 18, 19, 20} }, ++ { 6, { 6, 9, 11, 12, 13, 14, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, ++ { 6.5, { 6, 8, 10, 11, 11, 13, 14, 15, 15, 16, 16, 17, 17, 18, 19} }, ++ { 7, { 5, 7, 9, 10, 10, 12, 13, 14, 14, 15, 16, 16, 17, 17, 18} }, ++ { 7.5, { 5, 7, 8, 9, 9, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17} }, ++ { 8, { 4, 6, 7, 8, 8, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, ++ { 8.5, { 3, 6, 6, 7, 7, 10, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, ++ { 9, { 3, 5, 6, 7, 7, 10, 11, 12, 12, 13, 13, 14, 14, 14, 15} }, ++ { 9.5, { 2, 5, 6, 6, 7, 9, 10, 11, 12, 12, 13, 13, 13, 14, 15} }, ++ { 10, { 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 13, 15} }, ++ {10.5, { 2, 3, 5, 5, 6, 7, 8, 9, 11, 11, 12, 12, 12, 12, 14} }, ++ { 11, { 1, 3, 4, 5, 6, 6, 7, 9, 10, 11, 11, 11, 12, 12, 13} }, ++ {11.5, { 1, 2, 3, 4, 5, 6, 6, 8, 9, 10, 10, 11, 11, 11, 13} }, ++ { 12, { 1, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 12} }, ++ {12.5, { 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 11} }, ++ { 13, { 1, 1, 1, 2, 4, 4, 6, 6, 7, 8, 8, 9, 9, 9, 11} }, ++ {13.5, { 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9, 11} }, ++ { 14, { 1, 1, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} }, ++ {14.5, { 0, 1, 1, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, ++ { 15, { 0, 1, 1, 1, 1, 2, 3, 3, 5, 5, 5, 6, 6, 7, 9} }, ++ {15.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8} }, ++ { 16, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 7} }, ++ {16.5, { 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 7} }, ++ { 17, { 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 6} }, ++ {17.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 6} }, ++ { 18, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 5} } ++}; ++ ++ ++const qp_table qp_table_444_10bpc_min = { ++ { 6, { 0, 4, 7, 7, 9, 9, 9, 9, 9, 10, 10, 10, 10, 12, 18} }, ++ { 6.5, { 0, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 12, 18} }, ++ { 7, { 0, 4, 6, 6, 8, 8, 8, 8, 8, 9, 9, 10, 10, 12, 17} }, ++ { 7.5, { 0, 4, 6, 6, 7, 8, 8, 8, 8, 8, 9, 9, 10, 12, 17} }, ++ { 8, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16} }, ++ { 8.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16} }, ++ { 9, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, ++ { 9.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, ++ { 10, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 15} }, ++ {10.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 15} }, ++ { 11, { 0, 3, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, ++ {11.5, { 0, 3, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, ++ { 12, { 0, 2, 4, 4, 6, 6, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, ++ {12.5, { 0, 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 9, 9, 11, 14} }, ++ { 13, { 0, 2, 4, 4, 5, 6, 7, 7, 7, 7, 8, 9, 9, 11, 13} }, ++ {13.5, { 0, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 11, 13} }, ++ { 14, { 0, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 11, 13} }, ++ {14.5, { 0, 2, 3, 4, 5, 5, 6, 6, 6, 7, 7, 8, 9, 11, 12} }, ++ { 15, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 11, 12} }, ++ {15.5, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 11, 12} }, ++ { 16, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 10, 11} }, ++ {16.5, { 0, 1, 2, 3, 4, 5, 5, 6, 6, 6, 7, 8, 8, 10, 11} }, ++ { 17, { 0, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8, 9, 11} }, ++ {17.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 11} }, ++ { 18, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} }, ++ {18.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} }, ++ { 19, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9} }, ++ {19.5, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9} }, ++ { 20, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 9} }, ++ {20.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 9} }, ++ { 21, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 9} }, ++ {21.5, { 0, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8} }, ++ { 22, { 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 8} }, ++ {22.5, { 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, ++ { 23, { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 7} }, ++ {23.5, { 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 7} }, ++ { 24, { 0, 0, 0, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 7} }, ++ {24.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 7} }, ++ { 25, { 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} }, ++ {25.5, { 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, ++ { 26, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 5} }, ++ {26.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 5} }, ++ { 27, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} }, ++ {27.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} }, ++ { 28, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4} }, ++ {28.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 4} }, ++ { 29, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3} }, ++ {29.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3} }, ++ { 30, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} } ++}; ++ ++ ++const qp_table qp_table_420_8bpc_max = { ++ { 4, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 13, 14} }, ++ { 4.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, ++ { 5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 12, 13} }, ++ { 5.5, { 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12} }, ++ { 6, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, ++ { 6.5, { 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, ++ { 7, { 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 9, 10} }, ++ { 7.5, { 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9} }, ++ { 8, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, ++ { 8.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8} }, ++ { 9, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7} }, ++ { 9.5, { 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, ++ { 10, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6} }, ++ {10.5, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} }, ++ { 11, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5} }, ++ {11.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, ++ { 12, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4} } ++}; ++ ++ ++const qp_table qp_table_444_8bpc_min = { ++ { 6, { 0, 1, 3, 3, 5, 5, 5, 5, 5, 6, 6, 6, 6, 9, 14} }, ++ { 6.5, { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 9, 14} }, ++ { 7, { 0, 0, 2, 2, 4, 4, 4, 4, 4, 5, 5, 6, 6, 9, 13} }, ++ { 7.5, { 0, 0, 2, 2, 3, 4, 4, 4, 4, 4, 5, 5, 6, 9, 13} }, ++ { 8, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} }, ++ { 8.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} }, ++ { 9, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} }, ++ { 9.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} }, ++ { 10, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, ++ {10.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, ++ { 11, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, ++ {11.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, ++ { 12, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, ++ {12.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 4, 5, 5, 7, 10} }, ++ { 13, { 0, 0, 1, 1, 2, 3, 3, 3, 3, 3, 4, 5, 5, 7, 9} }, ++ {13.5, { 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, ++ { 14, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, ++ {14.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ { 15, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ {15.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ { 16, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, ++ {16.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, ++ { 17, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, ++ {17.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, ++ { 18, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, ++ {18.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, ++ { 19, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5} }, ++ {19.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5} }, ++ { 20, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5} }, ++ {20.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5} }, ++ { 21, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} }, ++ {21.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} }, ++ { 22, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} }, ++ {22.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} }, ++ { 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} }, ++ {23.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} }, ++ { 24, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3} } ++}; ++ ++ ++const qp_table qp_table_444_12bpc_min = { ++ { 6, { 0, 5, 11, 11, 13, 13, 13, 13, 13, 14, 14, 14, 14, 17, 22} }, ++ { 6.5, { 0, 5, 10, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 17, 22} }, ++ { 7, { 0, 5, 10, 10, 12, 12, 12, 12, 12, 13, 13, 14, 14, 17, 21} }, ++ { 7.5, { 0, 5, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 14, 17, 21} }, ++ { 8, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 12, 13, 13, 13, 16, 20} }, ++ { 8.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 12, 13, 13, 13, 16, 20} }, ++ { 9, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, ++ { 9.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, ++ { 10, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, ++ {10.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, ++ { 11, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ {11.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ { 12, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ {12.5, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ { 13, { 0, 4, 7, 8, 9, 11, 11, 11, 11, 11, 13, 13, 13, 15, 17} }, ++ {13.5, { 0, 3, 6, 7, 9, 10, 10, 11, 11, 11, 12, 13, 13, 15, 17} }, ++ { 14, { 0, 3, 5, 6, 9, 9, 9, 10, 11, 11, 12, 13, 13, 15, 17} }, ++ {14.5, { 0, 2, 5, 6, 8, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ { 15, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ {15.5, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ { 16, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 11, 12, 12, 14, 15} }, ++ {16.5, { 0, 2, 3, 5, 7, 8, 9, 10, 11, 11, 11, 12, 12, 14, 15} }, ++ { 17, { 0, 2, 3, 5, 5, 6, 9, 9, 10, 10, 11, 11, 12, 13, 15} }, ++ {17.5, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 15} }, ++ { 18, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, ++ {18.5, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, ++ { 19, { 0, 1, 2, 4, 5, 5, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ {19.5, { 0, 1, 2, 4, 5, 5, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ { 20, { 0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 9, 10, 10, 11, 13} }, ++ {20.5, { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, 13} }, ++ { 21, { 0, 1, 2, 3, 4, 5, 5, 7, 7, 8, 9, 10, 10, 11, 13} }, ++ {21.5, { 0, 1, 2, 3, 3, 4, 5, 7, 7, 8, 9, 10, 10, 11, 12} }, ++ { 22, { 0, 0, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 12} }, ++ {22.5, { 0, 0, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 11} }, ++ { 23, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 7, 9, 9, 9, 9, 11} }, ++ {23.5, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 7, 9, 9, 9, 9, 11} }, ++ { 24, { 0, 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 8, 9, 11} }, ++ {24.5, { 0, 0, 1, 2, 3, 4, 4, 6, 6, 7, 8, 8, 8, 9, 11} }, ++ { 25, { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 8, 8, 10} }, ++ {25.5, { 0, 0, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} }, ++ { 26, { 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 7, 7, 9} }, ++ {26.5, { 0, 0, 1, 2, 2, 3, 4, 5, 5, 5, 7, 7, 7, 7, 9} }, ++ { 27, { 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, ++ {27.5, { 0, 0, 1, 1, 2, 2, 4, 4, 4, 5, 6, 7, 7, 7, 9} }, ++ { 28, { 0, 0, 0, 1, 1, 2, 3, 4, 4, 4, 6, 6, 6, 7, 9} }, ++ {28.5, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 8} }, ++ { 29, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8} }, ++ {29.5, { 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7} }, ++ { 30, { 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 5, 5, 5, 5, 7} }, ++ {30.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 7} }, ++ { 31, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 7} }, ++ {31.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, ++ { 32, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6} }, ++ {32.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 6} }, ++ { 33, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} }, ++ {33.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} }, ++ { 34, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 5} }, ++ {34.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 5} }, ++ { 35, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} }, ++ {35.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 4} }, ++ { 36, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} } ++}; ++ ++ ++const qp_table qp_table_420_12bpc_min = { ++ { 4, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21} }, ++ { 4.5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, ++ { 5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, ++ { 5.5, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, ++ { 6, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ { 6.5, { 0, 4, 6, 8, 9, 10, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ { 7, { 0, 3, 5, 7, 9, 10, 10, 11, 11, 11, 13, 13, 13, 15, 17} }, ++ { 7.5, { 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ { 8, { 0, 2, 4, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ { 8.5, { 0, 2, 4, 6, 6, 9, 9, 10, 11, 11, 12, 12, 13, 14, 15} }, ++ { 9, { 0, 2, 4, 6, 6, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14} }, ++ { 9.5, { 0, 2, 4, 5, 6, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14} }, ++ { 10, { 0, 2, 3, 5, 6, 7, 8, 8, 9, 10, 10, 12, 12, 12, 14} }, ++ {10.5, { 0, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 11, 11, 13} }, ++ { 11, { 0, 2, 3, 4, 5, 5, 6, 8, 8, 9, 9, 10, 11, 11, 12} }, ++ {11.5, { 0, 1, 2, 3, 4, 5, 5, 7, 8, 8, 9, 10, 10, 10, 12} }, ++ { 12, { 0, 0, 2, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 11} }, ++ {12.5, { 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 10} }, ++ { 13, { 0, 0, 0, 1, 3, 3, 5, 5, 6, 7, 7, 8, 8, 8, 10} }, ++ {13.5, { 0, 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 7, 8, 10} }, ++ { 14, { 0, 0, 0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 7, 9} }, ++ {14.5, { 0, 0, 0, 0, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 8} }, ++ { 15, { 0, 0, 0, 0, 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 8} }, ++ {15.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, ++ { 16, { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 6} }, ++ {16.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 6} }, ++ { 17, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 5} }, ++ {17.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 5} }, ++ { 18, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_422_12bpc_min = { ++ { 6, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} }, ++ { 6.5, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} }, ++ { 7, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, ++ { 7.5, { 0, 4, 8, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, ++ { 8, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, ++ { 8.5, { 0, 3, 6, 8, 9, 10, 10, 11, 11, 11, 12, 13, 13, 15, 18} }, ++ { 9, { 0, 3, 5, 8, 9, 10, 10, 10, 11, 11, 12, 13, 13, 15, 17} }, ++ { 9.5, { 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 13, 13, 15, 17} }, ++ { 10, { 0, 2, 4, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ {10.5, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, ++ { 11, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, 15} }, ++ {11.5, { 0, 2, 4, 6, 7, 7, 9, 9, 10, 11, 11, 12, 12, 14, 15} }, ++ { 12, { 0, 2, 4, 6, 6, 6, 8, 8, 9, 9, 11, 11, 12, 13, 14} }, ++ {12.5, { 0, 1, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 13, 14} }, ++ { 13, { 0, 1, 3, 4, 5, 5, 7, 8, 8, 9, 10, 10, 11, 12, 13} }, ++ {13.5, { 0, 1, 3, 3, 4, 5, 7, 7, 8, 8, 10, 10, 10, 12, 13} }, ++ { 14, { 0, 0, 2, 3, 4, 5, 6, 6, 7, 7, 9, 10, 10, 11, 12} }, ++ {14.5, { 0, 0, 1, 3, 4, 4, 6, 6, 6, 7, 9, 9, 9, 11, 12} }, ++ { 15, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 6, 8, 9, 9, 10, 12} }, ++ {15.5, { 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 8, 8, 8, 10, 11} }, ++ { 16, { 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 8, 8, 8, 9, 11} }, ++ {16.5, { 0, 0, 0, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 9, 10} }, ++ { 17, { 0, 0, 0, 1, 2, 2, 4, 4, 4, 5, 6, 6, 6, 8, 10} }, ++ {17.5, { 0, 0, 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 8, 9} }, ++ { 18, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 5, 5, 6, 7, 9} }, ++ {18.5, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 5, 5, 5, 7, 9} }, ++ { 19, { 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 8} }, ++ {19.5, { 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 6, 8} }, ++ { 20, { 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 7} }, ++ {20.5, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 7} }, ++ { 21, { 0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, ++ {21.5, { 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 6} }, ++ { 22, { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 6} }, ++ {22.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 5} }, ++ { 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5} }, ++ {23.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 4} }, ++ { 24, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_422_12bpc_max = { ++ { 6, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, ++ { 6.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, ++ { 7, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} }, ++ { 7.5, { 9, 10, 12, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20} }, ++ { 8, { 6, 9, 10, 12, 14, 15, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, ++ { 8.5, { 6, 8, 9, 11, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19} }, ++ { 9, { 5, 7, 8, 10, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18} }, ++ { 9.5, { 5, 7, 7, 9, 10, 12, 12, 13, 14, 14, 15, 15, 16, 17, 18} }, ++ { 10, { 4, 6, 6, 8, 9, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, ++ {10.5, { 4, 6, 6, 8, 9, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, ++ { 11, { 4, 5, 6, 8, 9, 10, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, ++ {11.5, { 3, 5, 6, 8, 9, 9, 11, 11, 12, 13, 13, 14, 14, 15, 16} }, ++ { 12, { 3, 5, 6, 8, 8, 8, 10, 10, 11, 11, 13, 13, 14, 14, 15} }, ++ {12.5, { 3, 4, 6, 7, 8, 8, 9, 10, 10, 11, 12, 13, 13, 14, 15} }, ++ { 13, { 2, 4, 5, 6, 7, 7, 9, 10, 10, 11, 12, 12, 13, 13, 14} }, ++ {13.5, { 2, 4, 5, 5, 6, 7, 9, 9, 10, 10, 12, 12, 12, 13, 14} }, ++ { 14, { 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 11, 12, 12, 12, 13} }, ++ {14.5, { 2, 3, 3, 5, 6, 6, 8, 8, 8, 9, 11, 11, 11, 12, 13} }, ++ { 15, { 2, 3, 3, 5, 5, 6, 7, 8, 8, 8, 10, 11, 11, 11, 13} }, ++ {15.5, { 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 10, 10, 10, 11, 12} }, ++ { 16, { 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 10, 10, 10, 10, 12} }, ++ {16.5, { 1, 2, 2, 4, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 11} }, ++ { 17, { 1, 1, 2, 3, 4, 4, 6, 6, 6, 7, 8, 8, 8, 9, 11} }, ++ {17.5, { 1, 1, 2, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 10} }, ++ { 18, { 1, 1, 1, 2, 3, 3, 5, 5, 5, 6, 7, 7, 8, 8, 10} }, ++ {18.5, { 1, 1, 1, 2, 3, 3, 5, 5, 5, 5, 7, 7, 7, 8, 10} }, ++ { 19, { 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 7, 9} }, ++ {19.5, { 1, 1, 1, 2, 2, 2, 4, 5, 5, 5, 6, 6, 6, 7, 9} }, ++ { 20, { 1, 1, 1, 2, 2, 2, 4, 5, 5, 5, 6, 6, 6, 6, 8} }, ++ {20.5, { 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 8} }, ++ { 21, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 7} }, ++ {21.5, { 0, 0, 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 7} }, ++ { 22, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 7} }, ++ {22.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 6} }, ++ { 23, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6} }, ++ {23.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5} }, ++ { 24, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5} } ++}; ++ ++ ++const qp_table qp_table_444_12bpc_max = { ++ { 6, {12, 14, 16, 16, 17, 17, 17, 18, 19, 20, 20, 20, 20, 21, 23} }, ++ { 6.5, {12, 14, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 20, 21, 23} }, ++ { 7, {12, 13, 15, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 21, 22} }, ++ { 7.5, {12, 13, 14, 15, 15, 16, 16, 17, 18, 18, 19, 19, 20, 21, 22} }, ++ { 8, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, ++ { 8.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, ++ { 9, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 21} }, ++ { 9.5, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 21} }, ++ { 10, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} }, ++ {10.5, {10, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 18, 19, 20} }, ++ { 11, { 9, 11, 13, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19} }, ++ {11.5, { 9, 11, 13, 14, 15, 15, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, ++ { 12, { 6, 9, 12, 13, 14, 14, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, ++ {12.5, { 6, 9, 12, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19} }, ++ { 13, { 5, 9, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 17, 18} }, ++ {13.5, { 5, 8, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18} }, ++ { 14, { 5, 8, 10, 11, 12, 12, 12, 13, 14, 14, 15, 16, 16, 16, 18} }, ++ {14.5, { 4, 7, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17} }, ++ { 15, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, ++ {15.5, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, ++ { 16, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 13, 14, 14, 15, 16} }, ++ {16.5, { 4, 5, 7, 8, 10, 11, 11, 12, 13, 13, 13, 14, 14, 15, 16} }, ++ { 17, { 4, 5, 7, 8, 8, 9, 11, 11, 12, 12, 12, 13, 13, 14, 16} }, ++ {17.5, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 16} }, ++ { 18, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 15} }, ++ {18.5, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 15} }, ++ { 19, { 3, 4, 6, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 14} }, ++ {19.5, { 3, 4, 6, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 14} }, ++ { 20, { 2, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11, 11, 12, 14} }, ++ {20.5, { 2, 3, 5, 5, 7, 8, 8, 8, 9, 10, 10, 11, 11, 12, 14} }, ++ { 21, { 2, 3, 5, 5, 7, 7, 7, 8, 8, 9, 10, 11, 11, 12, 14} }, ++ {21.5, { 2, 3, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13} }, ++ { 22, { 2, 2, 4, 5, 6, 6, 7, 7, 8, 9, 10, 10, 10, 11, 13} }, ++ {22.5, { 2, 2, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 10, 11, 12} }, ++ { 23, { 2, 2, 4, 5, 5, 6, 7, 7, 7, 8, 10, 10, 10, 10, 12} }, ++ {23.5, { 2, 2, 3, 5, 5, 6, 7, 7, 7, 8, 10, 10, 10, 10, 12} }, ++ { 24, { 2, 2, 3, 4, 4, 5, 7, 7, 7, 8, 9, 9, 9, 10, 12} }, ++ {24.5, { 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 9, 9, 10, 12} }, ++ { 25, { 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 9, 9, 11} }, ++ {25.5, { 1, 1, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9, 9, 9, 11} }, ++ { 26, { 1, 1, 3, 3, 3, 4, 5, 6, 6, 7, 8, 8, 8, 8, 10} }, ++ {26.5, { 1, 1, 2, 3, 3, 4, 5, 6, 6, 6, 8, 8, 8, 8, 10} }, ++ { 27, { 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 10} }, ++ {27.5, { 1, 1, 2, 2, 3, 3, 5, 5, 5, 6, 7, 8, 8, 8, 10} }, ++ { 28, { 0, 1, 1, 2, 2, 3, 4, 5, 5, 5, 7, 7, 7, 8, 10} }, ++ {28.5, { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, ++ { 29, { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 9} }, ++ {29.5, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8} }, ++ { 30, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 8} }, ++ {30.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 8} }, ++ { 31, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 8} }, ++ {31.5, { 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8} }, ++ { 32, { 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 7} }, ++ {32.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 7} }, ++ { 33, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, ++ {33.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, ++ { 34, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6} }, ++ {34.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 3, 3, 3, 3, 4, 6} }, ++ { 35, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} }, ++ {35.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 5} }, ++ { 36, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_420_8bpc_min = { ++ { 4, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 13} }, ++ { 4.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, ++ { 5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, ++ { 5.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, ++ { 6, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, ++ { 6.5, { 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 7, 10} }, ++ { 7, { 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, ++ { 7.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ { 8, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ { 8.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, ++ { 9, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6} }, ++ { 9.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, ++ { 10, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5} }, ++ {10.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 5} }, ++ { 11, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4} }, ++ {11.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} }, ++ { 12, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 3} } ++}; ++ ++ ++const qp_table qp_table_422_8bpc_min = { ++ { 6, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, ++ { 6.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, ++ { 7, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, ++ { 7.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, ++ { 8, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, ++ { 8.5, { 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 7, 10} }, ++ { 9, { 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, ++ { 9.5, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 9} }, ++ { 10, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ {10.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, ++ { 11, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, ++ {11.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, ++ { 12, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6} }, ++ {12.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, ++ { 13, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5} }, ++ {13.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 5} }, ++ { 14, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4} }, ++ {14.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4} }, ++ { 15, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 4} }, ++ {15.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} }, ++ { 16, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} } ++}; ++ ++ ++const qp_table qp_table_422_10bpc_max = { ++ { 6, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, ++ { 6.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, ++ { 7, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, ++ { 7.5, { 5, 6, 8, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16} }, ++ { 8, { 4, 6, 7, 9, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, ++ { 8.5, { 4, 5, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15} }, ++ { 9, { 3, 4, 5, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14} }, ++ { 9.5, { 3, 4, 4, 6, 6, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, ++ { 10, { 2, 3, 3, 5, 5, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ {10.5, { 2, 3, 3, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ { 11, { 2, 3, 3, 5, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, ++ {11.5, { 2, 3, 3, 5, 5, 5, 7, 7, 8, 9, 9, 10, 10, 11, 12} }, ++ { 12, { 2, 3, 3, 5, 5, 5, 7, 7, 8, 8, 9, 9, 10, 10, 11} }, ++ {12.5, { 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, ++ { 13, { 1, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10} }, ++ {13.5, { 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 10} }, ++ { 14, { 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 8, 9} }, ++ {14.5, { 1, 2, 2, 3, 4, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9} }, ++ { 15, { 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7, 7, 7, 9} }, ++ {15.5, { 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 8} }, ++ { 16, { 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 8} }, ++ {16.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7} }, ++ { 17, { 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 7} }, ++ {17.5, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6} }, ++ { 18, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 6} }, ++ {18.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 6} }, ++ { 19, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 5} }, ++ {19.5, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 5} }, ++ { 20, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_420_10bpc_max = { ++ { 4, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 17, 18} }, ++ { 4.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, ++ { 5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 16, 17} }, ++ { 5.5, { 6, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14, 14, 15, 16} }, ++ { 6, { 4, 6, 8, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, ++ { 6.5, { 4, 5, 7, 8, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 15} }, ++ { 7, { 3, 4, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14} }, ++ { 7.5, { 3, 4, 5, 6, 6, 7, 8, 9, 10, 10, 11, 11, 12, 12, 13} }, ++ { 8, { 2, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ { 8.5, { 1, 3, 3, 4, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, ++ { 9, { 1, 3, 3, 4, 4, 6, 7, 8, 8, 9, 9, 10, 10, 10, 11} }, ++ { 9.5, { 1, 3, 3, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 11} }, ++ { 10, { 1, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 11} }, ++ {10.5, { 1, 1, 3, 3, 3, 4, 5, 5, 7, 7, 8, 8, 8, 8, 10} }, ++ { 11, { 0, 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 8, 9} }, ++ {11.5, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 7, 9} }, ++ { 12, { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 6, 8} }, ++ {12.5, { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, ++ { 13, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 7} }, ++ {13.5, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} }, ++ { 14, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, ++ {14.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 5} }, ++ { 15, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} } ++}; ++ ++ ++const qp_table qp_table_420_10bpc_min = { ++ { 4, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 17} }, ++ { 4.5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, ++ { 5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, ++ { 5.5, { 0, 3, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15} }, ++ { 6, { 0, 2, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, ++ { 6.5, { 0, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 11, 14} }, ++ { 7, { 0, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 11, 13} }, ++ { 7.5, { 0, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 11, 12} }, ++ { 8, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12} }, ++ { 8.5, { 0, 2, 2, 3, 3, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11} }, ++ { 9, { 0, 2, 2, 3, 3, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10} }, ++ { 9.5, { 0, 2, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10} }, ++ { 10, { 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 8, 8, 8, 10} }, ++ {10.5, { 0, 0, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, ++ { 11, { 0, 0, 1, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8} }, ++ {11.5, { 0, 0, 0, 1, 2, 2, 2, 3, 4, 4, 5, 6, 6, 6, 8} }, ++ { 12, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 7} }, ++ {12.5, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6} }, ++ { 13, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, ++ {13.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 5} }, ++ { 14, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} }, ++ {14.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4} }, ++ { 15, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_444_10bpc_max = { ++ { 6, { 8, 10, 12, 12, 13, 13, 13, 14, 15, 16, 16, 16, 16, 17, 19} }, ++ { 6.5, { 8, 10, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 16, 17, 19} }, ++ { 7, { 8, 9, 11, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 17, 18} }, ++ { 7.5, { 8, 9, 10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16, 17, 18} }, ++ { 8, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, ++ { 8.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, ++ { 9, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 17} }, ++ { 9.5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 17} }, ++ { 10, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, ++ {10.5, { 6, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 14, 15, 16} }, ++ { 11, { 5, 7, 9, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15} }, ++ {11.5, { 5, 7, 9, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, ++ { 12, { 4, 6, 8, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, ++ {12.5, { 4, 6, 8, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15} }, ++ { 13, { 3, 6, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 14} }, ++ {13.5, { 3, 5, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14} }, ++ { 14, { 3, 5, 6, 7, 8, 8, 8, 9, 10, 10, 11, 12, 12, 12, 14} }, ++ {14.5, { 2, 4, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13} }, ++ { 15, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ {15.5, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, ++ { 16, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 11, 12} }, ++ {16.5, { 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 9, 10, 10, 11, 12} }, ++ { 17, { 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 12} }, ++ {17.5, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 12} }, ++ { 18, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 11} }, ++ {18.5, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 11} }, ++ { 19, { 1, 2, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 10} }, ++ {19.5, { 1, 2, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 10} }, ++ { 20, { 1, 2, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 10} }, ++ {20.5, { 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 7, 7, 8, 10} }, ++ { 21, { 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 7, 7, 8, 10} }, ++ {21.5, { 1, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9} }, ++ { 22, { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 9} }, ++ {22.5, { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8} }, ++ { 23, { 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8} }, ++ {23.5, { 1, 1, 1, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8} }, ++ { 24, { 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 8} }, ++ {24.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 8} }, ++ { 25, { 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 7} }, ++ {25.5, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 7} }, ++ { 26, { 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 6} }, ++ {26.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 6} }, ++ { 27, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, ++ {27.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, ++ { 28, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 5} }, ++ {28.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} }, ++ { 29, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4} }, ++ {29.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4} }, ++ { 30, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4} } ++}; ++ ++ ++const qp_table qp_table_422_8bpc_max = { ++ { 6, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, ++ { 6.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, ++ { 7, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, ++ { 7.5, { 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12} }, ++ { 8, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, ++ { 8.5, { 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, ++ { 9, { 1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10} }, ++ { 9.5, { 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 10} }, ++ { 10, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, ++ {10.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, ++ { 11, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8} }, ++ {11.5, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8} }, ++ { 12, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7} }, ++ {12.5, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7} }, ++ { 13, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6} }, ++ {13.5, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 6} }, ++ { 14, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5} }, ++ {14.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5} }, ++ { 15, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 5} }, ++ {15.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} }, ++ { 16, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} } ++}; ++ +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c +new file mode 100644 +index 0000000000000..3ee858f311d12 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c +@@ -0,0 +1,291 @@ ++/* ++ * Copyright 2021 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#include "rc_calc_fpu.h" ++ ++#include "qp_tables.h" ++#include "amdgpu_dm/dc_fpu.h" ++ ++#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min) ++ ++#define MODE_SELECT(val444, val422, val420) \ ++ (cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420)) ++ ++ ++#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \ ++ table = qp_table_##mode##_##bpc##bpc_##max; \ ++ table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \ ++ break ++ ++static int median3(int a, int b, int c) ++{ ++ if (a > b) ++ swap(a, b); ++ if (b > c) ++ swap(b, c); ++ if (a > b) ++ swap(b, c); ++ ++ return b; ++} ++ ++static double dsc_roundf(double num) ++{ ++ if (num < 0.0) ++ num = num - 0.5; ++ else ++ num = num + 0.5; ++ ++ return (int)(num); ++} ++ ++static double dsc_ceil(double num) ++{ ++ double retval = (int)num; ++ ++ if (retval != num && num > 0) ++ retval = num + 1; ++ ++ return (int)retval; ++} ++ ++static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, ++ enum max_min max_min, float bpp) ++{ ++ int mode = MODE_SELECT(444, 422, 420); ++ int sel = table_hash(mode, bpc, max_min); ++ int table_size = 0; ++ int index; ++ const struct qp_entry *table = 0L; ++ ++ // alias enum ++ enum { min = DAL_MM_MIN, max = DAL_MM_MAX }; ++ switch (sel) { ++ TABLE_CASE(444, 8, max); ++ TABLE_CASE(444, 8, min); ++ TABLE_CASE(444, 10, max); ++ TABLE_CASE(444, 10, min); ++ TABLE_CASE(444, 12, max); ++ TABLE_CASE(444, 12, min); ++ TABLE_CASE(422, 8, max); ++ TABLE_CASE(422, 8, min); ++ TABLE_CASE(422, 10, max); ++ TABLE_CASE(422, 10, min); ++ TABLE_CASE(422, 12, max); ++ TABLE_CASE(422, 12, min); ++ TABLE_CASE(420, 8, max); ++ TABLE_CASE(420, 8, min); ++ TABLE_CASE(420, 10, max); ++ TABLE_CASE(420, 10, min); ++ TABLE_CASE(420, 12, max); ++ TABLE_CASE(420, 12, min); ++ } ++ ++ if (table == 0) ++ return; ++ ++ index = (bpp - table[0].bpp) * 2; ++ ++ /* requested size is bigger than the table */ ++ if (index >= table_size) { ++ dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n"); ++ return; ++ } ++ ++ memcpy(qps, table[index].qps, sizeof(qp_set)); ++} ++ ++static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp) ++{ ++ int *p = ofs; ++ ++ if (mode == CM_444 || mode == CM_RGB) { ++ *p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0)))))); ++ *p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0)))))); ++ *p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0)))))); ++ *p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0)))))); ++ *p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0)))))); ++ *p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0)))); ++ *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0)))); ++ *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0)))); ++ *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0)))); ++ *p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0)))); ++ *p++ = -10; ++ *p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0)))); ++ *p++ = -12; ++ *p++ = -12; ++ *p++ = -12; ++ } else if (mode == CM_422) { ++ *p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0)))); ++ *p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0)))); ++ *p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0)))); ++ *p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0)))); ++ *p++ = -10; ++ *p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1)))); ++ *p++ = -12; ++ *p++ = -12; ++ *p++ = -12; ++ } else { ++ *p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0)))); ++ *p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0)))); ++ *p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0)))); ++ *p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0)))); ++ *p++ = -10; ++ *p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0)))); ++ *p++ = -12; ++ *p++ = -12; ++ *p++ = -12; ++ } ++} ++ ++void _do_calc_rc_params(struct rc_params *rc, ++ enum colour_mode cm, ++ enum bits_per_comp bpc, ++ u16 drm_bpp, ++ bool is_navite_422_or_420, ++ int slice_width, ++ int slice_height, ++ int minor_version) ++{ ++ float bpp; ++ float bpp_group; ++ float initial_xmit_delay_factor; ++ int padding_pixels; ++ int i; ++ ++ dc_assert_fp_enabled(); ++ ++ bpp = ((float)drm_bpp / 16.0); ++ /* in native_422 or native_420 modes, the bits_per_pixel is double the ++ * target bpp (the latter is what calc_rc_params expects) ++ */ ++ if (is_navite_422_or_420) ++ bpp /= 2.0; ++ ++ rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); ++ rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); ++ ++ bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0); ++ ++ switch (cm) { ++ case CM_420: ++ rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584))))); ++ rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group))); ++ rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group))); ++ break; ++ case CM_422: ++ rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584)))); ++ rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group))); ++ rc->second_line_bpg_offset = 0; ++ break; ++ case CM_444: ++ case CM_RGB: ++ rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2))))); ++ rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group))); ++ rc->second_line_bpg_offset = 0; ++ break; ++ } ++ ++ initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0; ++ rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor); ++ ++ if (cm == CM_422 || cm == CM_420) ++ slice_width /= 2; ++ ++ padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0; ++ if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) { ++ if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1) ++ rc->initial_xmit_delay++; ++ } ++ ++ rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); ++ rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); ++ rc->flatness_det_thresh = 2 << (bpc - 8); ++ ++ get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp); ++ get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp); ++ if (cm == CM_444 && minor_version == 1) { ++ for (i = 0; i < QP_SET_SIZE; ++i) { ++ rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0; ++ rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0; ++ } ++ } ++ get_ofs_set(rc->ofs, cm, bpp); ++ ++ /* fixed parameters */ ++ rc->rc_model_size = 8192; ++ rc->rc_edge_factor = 6; ++ rc->rc_tgt_offset_hi = 3; ++ rc->rc_tgt_offset_lo = 3; ++ ++ rc->rc_buf_thresh[0] = 896; ++ rc->rc_buf_thresh[1] = 1792; ++ rc->rc_buf_thresh[2] = 2688; ++ rc->rc_buf_thresh[3] = 3584; ++ rc->rc_buf_thresh[4] = 4480; ++ rc->rc_buf_thresh[5] = 5376; ++ rc->rc_buf_thresh[6] = 6272; ++ rc->rc_buf_thresh[7] = 6720; ++ rc->rc_buf_thresh[8] = 7168; ++ rc->rc_buf_thresh[9] = 7616; ++ rc->rc_buf_thresh[10] = 7744; ++ rc->rc_buf_thresh[11] = 7872; ++ rc->rc_buf_thresh[12] = 8000; ++ rc->rc_buf_thresh[13] = 8064; ++} ++ ++u32 _do_bytes_per_pixel_calc(int slice_width, ++ u16 drm_bpp, ++ bool is_navite_422_or_420) ++{ ++ float bpp; ++ u32 bytes_per_pixel; ++ double d_bytes_per_pixel; ++ ++ dc_assert_fp_enabled(); ++ ++ bpp = ((float)drm_bpp / 16.0); ++ d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width; ++ // TODO: Make sure the formula for calculating this is precise (ceiling ++ // vs. floor, and at what point they should be applied) ++ if (is_navite_422_or_420) ++ d_bytes_per_pixel /= 2; ++ ++ bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000); ++ ++ return bytes_per_pixel; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h +new file mode 100644 +index 0000000000000..b93b95409fbe2 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h +@@ -0,0 +1,94 @@ ++/* ++ * Copyright 2021 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#ifndef __RC_CALC_FPU_H__ ++#define __RC_CALC_FPU_H__ ++ ++#include "os_types.h" ++#include <drm/drm_dsc.h> ++ ++#define QP_SET_SIZE 15 ++ ++typedef int qp_set[QP_SET_SIZE]; ++ ++struct rc_params { ++ int rc_quant_incr_limit0; ++ int rc_quant_incr_limit1; ++ int initial_fullness_offset; ++ int initial_xmit_delay; ++ int first_line_bpg_offset; ++ int second_line_bpg_offset; ++ int flatness_min_qp; ++ int flatness_max_qp; ++ int flatness_det_thresh; ++ qp_set qp_min; ++ qp_set qp_max; ++ qp_set ofs; ++ int rc_model_size; ++ int rc_edge_factor; ++ int rc_tgt_offset_hi; ++ int rc_tgt_offset_lo; ++ int rc_buf_thresh[QP_SET_SIZE - 1]; ++}; ++ ++enum colour_mode { ++ CM_RGB, /* 444 RGB */ ++ CM_444, /* 444 YUV or simple 422 */ ++ CM_422, /* native 422 */ ++ CM_420 /* native 420 */ ++}; ++ ++enum bits_per_comp { ++ BPC_8 = 8, ++ BPC_10 = 10, ++ BPC_12 = 12 ++}; ++ ++enum max_min { ++ DAL_MM_MIN = 0, ++ DAL_MM_MAX = 1 ++}; ++ ++struct qp_entry { ++ float bpp; ++ const qp_set qps; ++}; ++ ++typedef struct qp_entry qp_table[]; ++ ++u32 _do_bytes_per_pixel_calc(int slice_width, ++ u16 drm_bpp, ++ bool is_navite_422_or_420); ++ ++void _do_calc_rc_params(struct rc_params *rc, ++ enum colour_mode cm, ++ enum bits_per_comp bpc, ++ u16 drm_bpp, ++ bool is_navite_422_or_420, ++ int slice_width, ++ int slice_height, ++ int minor_version); ++ ++#endif +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile +index 8d31eb75c6a6e..a2537229ee88b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile ++++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile +@@ -1,35 +1,6 @@ + # SPDX-License-Identifier: MIT + # + # Makefile for the 'dsc' sub-component of DAL. +- +-ifdef CONFIG_X86 +-dsc_ccflags := -mhard-float -msse +-endif +- +-ifdef CONFIG_PPC64 +-dsc_ccflags := -mhard-float -maltivec +-endif +- +-ifdef CONFIG_CC_IS_GCC +-ifeq ($(call cc-ifversion, -lt, 0701, y), y) +-IS_OLD_GCC = 1 +-endif +-endif +- +-ifdef CONFIG_X86 +-ifdef IS_OLD_GCC +-# Stack alignment mismatch, proceed with caution. +-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +-# (8B stack alignment). +-dsc_ccflags += -mpreferred-stack-boundary=4 +-else +-dsc_ccflags += -msse2 +-endif +-endif +- +-CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags) +-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_rcflags) +- + DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o + + AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC)) +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h b/drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h +deleted file mode 100644 +index e5fac9f4181d8..0000000000000 +--- a/drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h ++++ /dev/null +@@ -1,704 +0,0 @@ +- +-/* +- * Copyright 2017 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: AMD +- * +- */ +- +- +-const qp_table qp_table_422_10bpc_min = { +- { 6, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} }, +- { 6.5, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} }, +- { 7, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 7, 9, 9, 9, 11, 15} }, +- { 7.5, { 0, 2, 4, 6, 6, 6, 6, 7, 7, 7, 8, 9, 9, 11, 15} }, +- { 8, { 0, 2, 3, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 11, 14} }, +- { 8.5, { 0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 14} }, +- { 9, { 0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 13} }, +- { 9.5, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 13} }, +- { 10, { 0, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12} }, +- {10.5, { 0, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 11, 12} }, +- { 11, { 0, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11} }, +- {11.5, { 0, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 10, 11} }, +- { 12, { 0, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10} }, +- {12.5, { 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} }, +- { 13, { 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 9} }, +- {13.5, { 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 9} }, +- { 14, { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8} }, +- {14.5, { 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8} }, +- { 15, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 6, 8} }, +- {15.5, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, +- { 16, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 7} }, +- {16.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6} }, +- { 17, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 6} }, +- {17.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, +- { 18, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 5} }, +- {18.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 5} }, +- { 19, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 4} }, +- {19.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 4} }, +- { 20, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 3} } +-}; +- +- +-const qp_table qp_table_444_8bpc_max = { +- { 6, { 4, 6, 8, 8, 9, 9, 9, 10, 11, 12, 12, 12, 12, 13, 15} }, +- { 6.5, { 4, 6, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 12, 13, 15} }, +- { 7, { 4, 5, 7, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 13, 14} }, +- { 7.5, { 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, +- { 8, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, +- { 8.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, +- { 9, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} }, +- { 9.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 13} }, +- { 10, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, +- {10.5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 11, 12} }, +- { 11, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11} }, +- {11.5, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, +- { 12, { 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, +- {12.5, { 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, +- { 13, { 1, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 10} }, +- {13.5, { 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10} }, +- { 14, { 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} }, +- {14.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9} }, +- { 15, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, +- {15.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, +- { 16, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8} }, +- {16.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8} }, +- { 17, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 8} }, +- {17.5, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 8} }, +- { 18, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7} }, +- {18.5, { 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 7} }, +- { 19, { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6} }, +- {19.5, { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6} }, +- { 20, { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 6} }, +- {20.5, { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 6} }, +- { 21, { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, +- {21.5, { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, +- { 22, { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} }, +- {22.5, { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} }, +- { 23, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4} }, +- {23.5, { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4} }, +- { 24, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4} } +-}; +- +- +-const qp_table qp_table_420_12bpc_max = { +- { 4, {11, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 21, 22} }, +- { 4.5, {10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, +- { 5, { 9, 11, 12, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 20, 21} }, +- { 5.5, { 8, 10, 11, 12, 13, 14, 15, 16, 16, 17, 17, 18, 18, 19, 20} }, +- { 6, { 6, 9, 11, 12, 13, 14, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, +- { 6.5, { 6, 8, 10, 11, 11, 13, 14, 15, 15, 16, 16, 17, 17, 18, 19} }, +- { 7, { 5, 7, 9, 10, 10, 12, 13, 14, 14, 15, 16, 16, 17, 17, 18} }, +- { 7.5, { 5, 7, 8, 9, 9, 11, 12, 13, 14, 14, 15, 15, 16, 16, 17} }, +- { 8, { 4, 6, 7, 8, 8, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, +- { 8.5, { 3, 6, 6, 7, 7, 10, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, +- { 9, { 3, 5, 6, 7, 7, 10, 11, 12, 12, 13, 13, 14, 14, 14, 15} }, +- { 9.5, { 2, 5, 6, 6, 7, 9, 10, 11, 12, 12, 13, 13, 13, 14, 15} }, +- { 10, { 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 13, 15} }, +- {10.5, { 2, 3, 5, 5, 6, 7, 8, 9, 11, 11, 12, 12, 12, 12, 14} }, +- { 11, { 1, 3, 4, 5, 6, 6, 7, 9, 10, 11, 11, 11, 12, 12, 13} }, +- {11.5, { 1, 2, 3, 4, 5, 6, 6, 8, 9, 10, 10, 11, 11, 11, 13} }, +- { 12, { 1, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 12} }, +- {12.5, { 1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 11} }, +- { 13, { 1, 1, 1, 2, 4, 4, 6, 6, 7, 8, 8, 9, 9, 9, 11} }, +- {13.5, { 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 8, 9, 11} }, +- { 14, { 1, 1, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} }, +- {14.5, { 0, 1, 1, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, +- { 15, { 0, 1, 1, 1, 1, 2, 3, 3, 5, 5, 5, 6, 6, 7, 9} }, +- {15.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8} }, +- { 16, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 7} }, +- {16.5, { 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 7} }, +- { 17, { 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 6} }, +- {17.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 6} }, +- { 18, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 5} } +-}; +- +- +-const qp_table qp_table_444_10bpc_min = { +- { 6, { 0, 4, 7, 7, 9, 9, 9, 9, 9, 10, 10, 10, 10, 12, 18} }, +- { 6.5, { 0, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 12, 18} }, +- { 7, { 0, 4, 6, 6, 8, 8, 8, 8, 8, 9, 9, 10, 10, 12, 17} }, +- { 7.5, { 0, 4, 6, 6, 7, 8, 8, 8, 8, 8, 9, 9, 10, 12, 17} }, +- { 8, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16} }, +- { 8.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 8, 9, 9, 9, 12, 16} }, +- { 9, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, +- { 9.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, +- { 10, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 15} }, +- {10.5, { 0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 15} }, +- { 11, { 0, 3, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, +- {11.5, { 0, 3, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, +- { 12, { 0, 2, 4, 4, 6, 6, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, +- {12.5, { 0, 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 9, 9, 11, 14} }, +- { 13, { 0, 2, 4, 4, 5, 6, 7, 7, 7, 7, 8, 9, 9, 11, 13} }, +- {13.5, { 0, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 11, 13} }, +- { 14, { 0, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 11, 13} }, +- {14.5, { 0, 2, 3, 4, 5, 5, 6, 6, 6, 7, 7, 8, 9, 11, 12} }, +- { 15, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 11, 12} }, +- {15.5, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 11, 12} }, +- { 16, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 10, 11} }, +- {16.5, { 0, 1, 2, 3, 4, 5, 5, 6, 6, 6, 7, 8, 8, 10, 11} }, +- { 17, { 0, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8, 9, 11} }, +- {17.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 11} }, +- { 18, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} }, +- {18.5, { 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10} }, +- { 19, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9} }, +- {19.5, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9} }, +- { 20, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 9} }, +- {20.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 9} }, +- { 21, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 9} }, +- {21.5, { 0, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8} }, +- { 22, { 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 8} }, +- {22.5, { 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, +- { 23, { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 7} }, +- {23.5, { 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 7} }, +- { 24, { 0, 0, 0, 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 7} }, +- {24.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 7} }, +- { 25, { 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} }, +- {25.5, { 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, +- { 26, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 5} }, +- {26.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 5} }, +- { 27, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} }, +- {27.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} }, +- { 28, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4} }, +- {28.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 4} }, +- { 29, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3} }, +- {29.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3} }, +- { 30, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} } +-}; +- +- +-const qp_table qp_table_420_8bpc_max = { +- { 4, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 13, 14} }, +- { 4.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, +- { 5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 12, 13} }, +- { 5.5, { 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12} }, +- { 6, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, +- { 6.5, { 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, +- { 7, { 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 9, 10} }, +- { 7.5, { 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9} }, +- { 8, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, +- { 8.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8} }, +- { 9, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7} }, +- { 9.5, { 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, +- { 10, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6} }, +- {10.5, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} }, +- { 11, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5} }, +- {11.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5} }, +- { 12, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4} } +-}; +- +- +-const qp_table qp_table_444_8bpc_min = { +- { 6, { 0, 1, 3, 3, 5, 5, 5, 5, 5, 6, 6, 6, 6, 9, 14} }, +- { 6.5, { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 9, 14} }, +- { 7, { 0, 0, 2, 2, 4, 4, 4, 4, 4, 5, 5, 6, 6, 9, 13} }, +- { 7.5, { 0, 0, 2, 2, 3, 4, 4, 4, 4, 4, 5, 5, 6, 9, 13} }, +- { 8, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} }, +- { 8.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 4, 5, 5, 5, 8, 12} }, +- { 9, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} }, +- { 9.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 12} }, +- { 10, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, +- {10.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, +- { 11, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, +- {11.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, +- { 12, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, +- {12.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 4, 5, 5, 7, 10} }, +- { 13, { 0, 0, 1, 1, 2, 3, 3, 3, 3, 3, 4, 5, 5, 7, 9} }, +- {13.5, { 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, +- { 14, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, +- {14.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 5, 7, 8} }, +- { 15, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, +- {15.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, +- { 16, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, +- {16.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, +- { 17, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, +- {17.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, +- { 18, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, +- {18.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, +- { 19, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5} }, +- {19.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5} }, +- { 20, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5} }, +- {20.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5} }, +- { 21, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} }, +- {21.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} }, +- { 22, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} }, +- {22.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} }, +- { 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} }, +- {23.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} }, +- { 24, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3} } +-}; +- +- +-const qp_table qp_table_444_12bpc_min = { +- { 6, { 0, 5, 11, 11, 13, 13, 13, 13, 13, 14, 14, 14, 14, 17, 22} }, +- { 6.5, { 0, 5, 10, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 17, 22} }, +- { 7, { 0, 5, 10, 10, 12, 12, 12, 12, 12, 13, 13, 14, 14, 17, 21} }, +- { 7.5, { 0, 5, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 14, 17, 21} }, +- { 8, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 12, 13, 13, 13, 16, 20} }, +- { 8.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 12, 13, 13, 13, 16, 20} }, +- { 9, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, +- { 9.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, +- { 10, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, +- {10.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, +- { 11, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- {11.5, { 0, 4, 8, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- { 12, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- {12.5, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- { 13, { 0, 4, 7, 8, 9, 11, 11, 11, 11, 11, 13, 13, 13, 15, 17} }, +- {13.5, { 0, 3, 6, 7, 9, 10, 10, 11, 11, 11, 12, 13, 13, 15, 17} }, +- { 14, { 0, 3, 5, 6, 9, 9, 9, 10, 11, 11, 12, 13, 13, 15, 17} }, +- {14.5, { 0, 2, 5, 6, 8, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, +- { 15, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, +- {15.5, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, +- { 16, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 11, 12, 12, 14, 15} }, +- {16.5, { 0, 2, 3, 5, 7, 8, 9, 10, 11, 11, 11, 12, 12, 14, 15} }, +- { 17, { 0, 2, 3, 5, 5, 6, 9, 9, 10, 10, 11, 11, 12, 13, 15} }, +- {17.5, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 15} }, +- { 18, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, +- {18.5, { 0, 2, 3, 5, 5, 6, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, +- { 19, { 0, 1, 2, 4, 5, 5, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- {19.5, { 0, 1, 2, 4, 5, 5, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- { 20, { 0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 9, 10, 10, 11, 13} }, +- {20.5, { 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, 13} }, +- { 21, { 0, 1, 2, 3, 4, 5, 5, 7, 7, 8, 9, 10, 10, 11, 13} }, +- {21.5, { 0, 1, 2, 3, 3, 4, 5, 7, 7, 8, 9, 10, 10, 11, 12} }, +- { 22, { 0, 0, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 12} }, +- {22.5, { 0, 0, 1, 3, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10, 11} }, +- { 23, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 7, 9, 9, 9, 9, 11} }, +- {23.5, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 7, 9, 9, 9, 9, 11} }, +- { 24, { 0, 0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 8, 8, 9, 11} }, +- {24.5, { 0, 0, 1, 2, 3, 4, 4, 6, 6, 7, 8, 8, 8, 9, 11} }, +- { 25, { 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 8, 8, 10} }, +- {25.5, { 0, 0, 1, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 8, 10} }, +- { 26, { 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 7, 7, 9} }, +- {26.5, { 0, 0, 1, 2, 2, 3, 4, 5, 5, 5, 7, 7, 7, 7, 9} }, +- { 27, { 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, +- {27.5, { 0, 0, 1, 1, 2, 2, 4, 4, 4, 5, 6, 7, 7, 7, 9} }, +- { 28, { 0, 0, 0, 1, 1, 2, 3, 4, 4, 4, 6, 6, 6, 7, 9} }, +- {28.5, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 8} }, +- { 29, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 8} }, +- {29.5, { 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7} }, +- { 30, { 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 5, 5, 5, 5, 7} }, +- {30.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 7} }, +- { 31, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 7} }, +- {31.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, +- { 32, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6} }, +- {32.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 6} }, +- { 33, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} }, +- {33.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 5} }, +- { 34, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 5} }, +- {34.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 5} }, +- { 35, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} }, +- {35.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 4} }, +- { 36, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3} } +-}; +- +- +-const qp_table qp_table_420_12bpc_min = { +- { 4, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21} }, +- { 4.5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, +- { 5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} }, +- { 5.5, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, +- { 6, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- { 6.5, { 0, 4, 6, 8, 9, 10, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- { 7, { 0, 3, 5, 7, 9, 10, 10, 11, 11, 11, 13, 13, 13, 15, 17} }, +- { 7.5, { 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 13, 13, 15, 16} }, +- { 8, { 0, 2, 4, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, +- { 8.5, { 0, 2, 4, 6, 6, 9, 9, 10, 11, 11, 12, 12, 13, 14, 15} }, +- { 9, { 0, 2, 4, 6, 6, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14} }, +- { 9.5, { 0, 2, 4, 5, 6, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14} }, +- { 10, { 0, 2, 3, 5, 6, 7, 8, 8, 9, 10, 10, 12, 12, 12, 14} }, +- {10.5, { 0, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 11, 11, 13} }, +- { 11, { 0, 2, 3, 4, 5, 5, 6, 8, 8, 9, 9, 10, 11, 11, 12} }, +- {11.5, { 0, 1, 2, 3, 4, 5, 5, 7, 8, 8, 9, 10, 10, 10, 12} }, +- { 12, { 0, 0, 2, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 11} }, +- {12.5, { 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 10} }, +- { 13, { 0, 0, 0, 1, 3, 3, 5, 5, 6, 7, 7, 8, 8, 8, 10} }, +- {13.5, { 0, 0, 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 7, 8, 10} }, +- { 14, { 0, 0, 0, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 7, 9} }, +- {14.5, { 0, 0, 0, 0, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 8} }, +- { 15, { 0, 0, 0, 0, 0, 1, 2, 2, 4, 4, 4, 5, 5, 6, 8} }, +- {15.5, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7} }, +- { 16, { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 6} }, +- {16.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 6} }, +- { 17, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 5} }, +- {17.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 5} }, +- { 18, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 4} } +-}; +- +- +-const qp_table qp_table_422_12bpc_min = { +- { 6, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} }, +- { 6.5, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} }, +- { 7, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, +- { 7.5, { 0, 4, 8, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} }, +- { 8, { 0, 4, 7, 8, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 18} }, +- { 8.5, { 0, 3, 6, 8, 9, 10, 10, 11, 11, 11, 12, 13, 13, 15, 18} }, +- { 9, { 0, 3, 5, 8, 9, 10, 10, 10, 11, 11, 12, 13, 13, 15, 17} }, +- { 9.5, { 0, 3, 5, 7, 8, 9, 10, 10, 11, 11, 12, 13, 13, 15, 17} }, +- { 10, { 0, 2, 4, 6, 7, 9, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, +- {10.5, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 15, 16} }, +- { 11, { 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, 15} }, +- {11.5, { 0, 2, 4, 6, 7, 7, 9, 9, 10, 11, 11, 12, 12, 14, 15} }, +- { 12, { 0, 2, 4, 6, 6, 6, 8, 8, 9, 9, 11, 11, 12, 13, 14} }, +- {12.5, { 0, 1, 4, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 13, 14} }, +- { 13, { 0, 1, 3, 4, 5, 5, 7, 8, 8, 9, 10, 10, 11, 12, 13} }, +- {13.5, { 0, 1, 3, 3, 4, 5, 7, 7, 8, 8, 10, 10, 10, 12, 13} }, +- { 14, { 0, 0, 2, 3, 4, 5, 6, 6, 7, 7, 9, 10, 10, 11, 12} }, +- {14.5, { 0, 0, 1, 3, 4, 4, 6, 6, 6, 7, 9, 9, 9, 11, 12} }, +- { 15, { 0, 0, 1, 3, 3, 4, 5, 6, 6, 6, 8, 9, 9, 10, 12} }, +- {15.5, { 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 8, 8, 8, 10, 11} }, +- { 16, { 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 8, 8, 8, 9, 11} }, +- {16.5, { 0, 0, 0, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 9, 10} }, +- { 17, { 0, 0, 0, 1, 2, 2, 4, 4, 4, 5, 6, 6, 6, 8, 10} }, +- {17.5, { 0, 0, 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 8, 9} }, +- { 18, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 5, 5, 6, 7, 9} }, +- {18.5, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 3, 5, 5, 5, 7, 9} }, +- { 19, { 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 8} }, +- {19.5, { 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 6, 8} }, +- { 20, { 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 7} }, +- {20.5, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 7} }, +- { 21, { 0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, +- {21.5, { 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 6} }, +- { 22, { 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 6} }, +- {22.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 5} }, +- { 23, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5} }, +- {23.5, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 4} }, +- { 24, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 4} } +-}; +- +- +-const qp_table qp_table_422_12bpc_max = { +- { 6, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, +- { 6.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, +- { 7, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} }, +- { 7.5, { 9, 10, 12, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20} }, +- { 8, { 6, 9, 10, 12, 14, 15, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, +- { 8.5, { 6, 8, 9, 11, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19} }, +- { 9, { 5, 7, 8, 10, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18} }, +- { 9.5, { 5, 7, 7, 9, 10, 12, 12, 13, 14, 14, 15, 15, 16, 17, 18} }, +- { 10, { 4, 6, 6, 8, 9, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, +- {10.5, { 4, 6, 6, 8, 9, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, +- { 11, { 4, 5, 6, 8, 9, 10, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, +- {11.5, { 3, 5, 6, 8, 9, 9, 11, 11, 12, 13, 13, 14, 14, 15, 16} }, +- { 12, { 3, 5, 6, 8, 8, 8, 10, 10, 11, 11, 13, 13, 14, 14, 15} }, +- {12.5, { 3, 4, 6, 7, 8, 8, 9, 10, 10, 11, 12, 13, 13, 14, 15} }, +- { 13, { 2, 4, 5, 6, 7, 7, 9, 10, 10, 11, 12, 12, 13, 13, 14} }, +- {13.5, { 2, 4, 5, 5, 6, 7, 9, 9, 10, 10, 12, 12, 12, 13, 14} }, +- { 14, { 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 11, 12, 12, 12, 13} }, +- {14.5, { 2, 3, 3, 5, 6, 6, 8, 8, 8, 9, 11, 11, 11, 12, 13} }, +- { 15, { 2, 3, 3, 5, 5, 6, 7, 8, 8, 8, 10, 11, 11, 11, 13} }, +- {15.5, { 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 10, 10, 10, 11, 12} }, +- { 16, { 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 10, 10, 10, 10, 12} }, +- {16.5, { 1, 2, 2, 4, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 11} }, +- { 17, { 1, 1, 2, 3, 4, 4, 6, 6, 6, 7, 8, 8, 8, 9, 11} }, +- {17.5, { 1, 1, 2, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 10} }, +- { 18, { 1, 1, 1, 2, 3, 3, 5, 5, 5, 6, 7, 7, 8, 8, 10} }, +- {18.5, { 1, 1, 1, 2, 3, 3, 5, 5, 5, 5, 7, 7, 7, 8, 10} }, +- { 19, { 1, 1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 7, 9} }, +- {19.5, { 1, 1, 1, 2, 2, 2, 4, 5, 5, 5, 6, 6, 6, 7, 9} }, +- { 20, { 1, 1, 1, 2, 2, 2, 4, 5, 5, 5, 6, 6, 6, 6, 8} }, +- {20.5, { 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 8} }, +- { 21, { 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 7} }, +- {21.5, { 0, 0, 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 7} }, +- { 22, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 7} }, +- {22.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 6} }, +- { 23, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6} }, +- {23.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5} }, +- { 24, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5} } +-}; +- +- +-const qp_table qp_table_444_12bpc_max = { +- { 6, {12, 14, 16, 16, 17, 17, 17, 18, 19, 20, 20, 20, 20, 21, 23} }, +- { 6.5, {12, 14, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 20, 21, 23} }, +- { 7, {12, 13, 15, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 21, 22} }, +- { 7.5, {12, 13, 14, 15, 15, 16, 16, 17, 18, 18, 19, 19, 20, 21, 22} }, +- { 8, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, +- { 8.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} }, +- { 9, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 21} }, +- { 9.5, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 21} }, +- { 10, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} }, +- {10.5, {10, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 18, 19, 20} }, +- { 11, { 9, 11, 13, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19} }, +- {11.5, { 9, 11, 13, 14, 15, 15, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, +- { 12, { 6, 9, 12, 13, 14, 14, 15, 16, 16, 17, 17, 17, 17, 18, 19} }, +- {12.5, { 6, 9, 12, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 19} }, +- { 13, { 5, 9, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 17, 18} }, +- {13.5, { 5, 8, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18} }, +- { 14, { 5, 8, 10, 11, 12, 12, 12, 13, 14, 14, 15, 16, 16, 16, 18} }, +- {14.5, { 4, 7, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 17} }, +- { 15, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, +- {15.5, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17} }, +- { 16, { 4, 7, 9, 10, 10, 11, 11, 12, 13, 13, 13, 14, 14, 15, 16} }, +- {16.5, { 4, 5, 7, 8, 10, 11, 11, 12, 13, 13, 13, 14, 14, 15, 16} }, +- { 17, { 4, 5, 7, 8, 8, 9, 11, 11, 12, 12, 12, 13, 13, 14, 16} }, +- {17.5, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 16} }, +- { 18, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 15} }, +- {18.5, { 3, 5, 7, 8, 8, 9, 10, 11, 12, 12, 12, 13, 13, 14, 15} }, +- { 19, { 3, 4, 6, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 14} }, +- {19.5, { 3, 4, 6, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 14} }, +- { 20, { 2, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11, 11, 12, 14} }, +- {20.5, { 2, 3, 5, 5, 7, 8, 8, 8, 9, 10, 10, 11, 11, 12, 14} }, +- { 21, { 2, 3, 5, 5, 7, 7, 7, 8, 8, 9, 10, 11, 11, 12, 14} }, +- {21.5, { 2, 3, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11, 11, 12, 13} }, +- { 22, { 2, 2, 4, 5, 6, 6, 7, 7, 8, 9, 10, 10, 10, 11, 13} }, +- {22.5, { 2, 2, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 10, 11, 12} }, +- { 23, { 2, 2, 4, 5, 5, 6, 7, 7, 7, 8, 10, 10, 10, 10, 12} }, +- {23.5, { 2, 2, 3, 5, 5, 6, 7, 7, 7, 8, 10, 10, 10, 10, 12} }, +- { 24, { 2, 2, 3, 4, 4, 5, 7, 7, 7, 8, 9, 9, 9, 10, 12} }, +- {24.5, { 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 9, 9, 10, 12} }, +- { 25, { 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 9, 9, 11} }, +- {25.5, { 1, 1, 3, 3, 4, 5, 6, 6, 7, 7, 8, 9, 9, 9, 11} }, +- { 26, { 1, 1, 3, 3, 3, 4, 5, 6, 6, 7, 8, 8, 8, 8, 10} }, +- {26.5, { 1, 1, 2, 3, 3, 4, 5, 6, 6, 6, 8, 8, 8, 8, 10} }, +- { 27, { 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 10} }, +- {27.5, { 1, 1, 2, 2, 3, 3, 5, 5, 5, 6, 7, 8, 8, 8, 10} }, +- { 28, { 0, 1, 1, 2, 2, 3, 4, 5, 5, 5, 7, 7, 7, 8, 10} }, +- {28.5, { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, +- { 29, { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 9} }, +- {29.5, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8} }, +- { 30, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 8} }, +- {30.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 8} }, +- { 31, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6, 8} }, +- {31.5, { 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8} }, +- { 32, { 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 7} }, +- {32.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 7} }, +- { 33, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, +- {33.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, +- { 34, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 6} }, +- {34.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 3, 3, 3, 3, 4, 6} }, +- { 35, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} }, +- {35.5, { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 5} }, +- { 36, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4} } +-}; +- +- +-const qp_table qp_table_420_8bpc_min = { +- { 4, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 13} }, +- { 4.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, +- { 5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, +- { 5.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, +- { 6, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, +- { 6.5, { 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 7, 10} }, +- { 7, { 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, +- { 7.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 7, 8} }, +- { 8, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, +- { 8.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, +- { 9, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6} }, +- { 9.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, +- { 10, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5} }, +- {10.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 5} }, +- { 11, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4} }, +- {11.5, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4} }, +- { 12, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 3} } +-}; +- +- +-const qp_table qp_table_422_8bpc_min = { +- { 6, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, +- { 6.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} }, +- { 7, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, +- { 7.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} }, +- { 8, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10} }, +- { 8.5, { 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 5, 7, 10} }, +- { 9, { 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 4, 5, 5, 7, 9} }, +- { 9.5, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 9} }, +- { 10, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, +- {10.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 7, 8} }, +- { 11, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, +- {11.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7} }, +- { 12, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6} }, +- {12.5, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6} }, +- { 13, { 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5} }, +- {13.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 5} }, +- { 14, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4} }, +- {14.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 4} }, +- { 15, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 4} }, +- {15.5, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} }, +- { 16, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3} } +-}; +- +- +-const qp_table qp_table_422_10bpc_max = { +- { 6, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, +- { 6.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, +- { 7, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, +- { 7.5, { 5, 6, 8, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16} }, +- { 8, { 4, 6, 7, 9, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, +- { 8.5, { 4, 5, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15} }, +- { 9, { 3, 4, 5, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14} }, +- { 9.5, { 3, 4, 4, 6, 6, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14} }, +- { 10, { 2, 3, 3, 5, 5, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- {10.5, { 2, 3, 3, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- { 11, { 2, 3, 3, 5, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, +- {11.5, { 2, 3, 3, 5, 5, 5, 7, 7, 8, 9, 9, 10, 10, 11, 12} }, +- { 12, { 2, 3, 3, 5, 5, 5, 7, 7, 8, 8, 9, 9, 10, 10, 11} }, +- {12.5, { 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, +- { 13, { 1, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10} }, +- {13.5, { 1, 2, 3, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 10} }, +- { 14, { 1, 2, 3, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 8, 9} }, +- {14.5, { 1, 2, 2, 3, 4, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9} }, +- { 15, { 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7, 7, 7, 9} }, +- {15.5, { 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 8} }, +- { 16, { 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 8} }, +- {16.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7} }, +- { 17, { 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 7} }, +- {17.5, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6} }, +- { 18, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 6} }, +- {18.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 6} }, +- { 19, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 5} }, +- {19.5, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 5} }, +- { 20, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 4} } +-}; +- +- +-const qp_table qp_table_420_10bpc_max = { +- { 4, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 17, 18} }, +- { 4.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, +- { 5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 16, 17} }, +- { 5.5, { 6, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14, 14, 15, 16} }, +- { 6, { 4, 6, 8, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, +- { 6.5, { 4, 5, 7, 8, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 15} }, +- { 7, { 3, 4, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14} }, +- { 7.5, { 3, 4, 5, 6, 6, 7, 8, 9, 10, 10, 11, 11, 12, 12, 13} }, +- { 8, { 2, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- { 8.5, { 1, 3, 3, 4, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, +- { 9, { 1, 3, 3, 4, 4, 6, 7, 8, 8, 9, 9, 10, 10, 10, 11} }, +- { 9.5, { 1, 3, 3, 3, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 11} }, +- { 10, { 1, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 11} }, +- {10.5, { 1, 1, 3, 3, 3, 4, 5, 5, 7, 7, 8, 8, 8, 8, 10} }, +- { 11, { 0, 1, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 8, 8, 9} }, +- {11.5, { 0, 1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 7, 7, 7, 9} }, +- { 12, { 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 6, 8} }, +- {12.5, { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7} }, +- { 13, { 0, 0, 0, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 7} }, +- {13.5, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 6} }, +- { 14, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, +- {14.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 5} }, +- { 15, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 5} } +-}; +- +- +-const qp_table qp_table_420_10bpc_min = { +- { 4, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 17} }, +- { 4.5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, +- { 5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} }, +- { 5.5, { 0, 3, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15} }, +- { 6, { 0, 2, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14} }, +- { 6.5, { 0, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9, 9, 11, 14} }, +- { 7, { 0, 2, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 11, 13} }, +- { 7.5, { 0, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 11, 12} }, +- { 8, { 0, 2, 3, 4, 4, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12} }, +- { 8.5, { 0, 2, 2, 3, 3, 5, 5, 6, 6, 7, 8, 8, 9, 10, 11} }, +- { 9, { 0, 2, 2, 3, 3, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10} }, +- { 9.5, { 0, 2, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10} }, +- { 10, { 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 8, 8, 8, 10} }, +- {10.5, { 0, 0, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 9} }, +- { 11, { 0, 0, 1, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8} }, +- {11.5, { 0, 0, 0, 1, 2, 2, 2, 3, 4, 4, 5, 6, 6, 6, 8} }, +- { 12, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 7} }, +- {12.5, { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6} }, +- { 13, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, +- {13.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 5} }, +- { 14, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} }, +- {14.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4} }, +- { 15, { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 4} } +-}; +- +- +-const qp_table qp_table_444_10bpc_max = { +- { 6, { 8, 10, 12, 12, 13, 13, 13, 14, 15, 16, 16, 16, 16, 17, 19} }, +- { 6.5, { 8, 10, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 16, 17, 19} }, +- { 7, { 8, 9, 11, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 17, 18} }, +- { 7.5, { 8, 9, 10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16, 17, 18} }, +- { 8, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, +- { 8.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} }, +- { 9, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 17} }, +- { 9.5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 17} }, +- { 10, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} }, +- {10.5, { 6, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 14, 15, 16} }, +- { 11, { 5, 7, 9, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15} }, +- {11.5, { 5, 7, 9, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, +- { 12, { 4, 6, 8, 9, 10, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15} }, +- {12.5, { 4, 6, 8, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 14, 15} }, +- { 13, { 3, 6, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 14} }, +- {13.5, { 3, 5, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14} }, +- { 14, { 3, 5, 6, 7, 8, 8, 8, 9, 10, 10, 11, 12, 12, 12, 14} }, +- {14.5, { 2, 4, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13} }, +- { 15, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- {15.5, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13} }, +- { 16, { 2, 4, 5, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 11, 12} }, +- {16.5, { 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 9, 10, 10, 11, 12} }, +- { 17, { 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 12} }, +- {17.5, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 12} }, +- { 18, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 11} }, +- {18.5, { 1, 3, 4, 5, 5, 6, 6, 7, 8, 8, 8, 9, 9, 10, 11} }, +- { 19, { 1, 2, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 10} }, +- {19.5, { 1, 2, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 8, 9, 10} }, +- { 20, { 1, 2, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 10} }, +- {20.5, { 1, 2, 3, 3, 4, 5, 5, 5, 5, 6, 6, 7, 7, 8, 10} }, +- { 21, { 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 7, 7, 8, 10} }, +- {21.5, { 1, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9} }, +- { 22, { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 9} }, +- {22.5, { 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8} }, +- { 23, { 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8} }, +- {23.5, { 1, 1, 1, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8} }, +- { 24, { 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, 6, 8} }, +- {24.5, { 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 8} }, +- { 25, { 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 7} }, +- {25.5, { 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 7} }, +- { 26, { 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 6} }, +- {26.5, { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 6} }, +- { 27, { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 6} }, +- {27.5, { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 6} }, +- { 28, { 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 5} }, +- {28.5, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 5} }, +- { 29, { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4} }, +- {29.5, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4} }, +- { 30, { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4} } +-}; +- +- +-const qp_table qp_table_422_8bpc_max = { +- { 6, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, +- { 6.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} }, +- { 7, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} }, +- { 7.5, { 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12} }, +- { 8, { 2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11} }, +- { 8.5, { 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11} }, +- { 9, { 1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10} }, +- { 9.5, { 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 10} }, +- { 10, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, +- {10.5, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9} }, +- { 11, { 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8} }, +- {11.5, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8} }, +- { 12, { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7} }, +- {12.5, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7} }, +- { 13, { 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6} }, +- {13.5, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 6} }, +- { 14, { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5} }, +- {14.5, { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5} }, +- { 15, { 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 5} }, +- {15.5, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} }, +- { 16, { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 4} } +-}; +- +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c +index 7b294f637881a..b19d3aeb5962c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c ++++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c +@@ -23,266 +23,7 @@ + * Authors: AMD + * + */ +-#include <drm/drm_dsc.h> +- +-#include "os_types.h" + #include "rc_calc.h" +-#include "qp_tables.h" +- +-#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min) +- +-#define MODE_SELECT(val444, val422, val420) \ +- (cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420)) +- +- +-#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \ +- table = qp_table_##mode##_##bpc##bpc_##max; \ +- table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \ +- break +- +- +-static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, +- enum max_min max_min, float bpp) +-{ +- int mode = MODE_SELECT(444, 422, 420); +- int sel = table_hash(mode, bpc, max_min); +- int table_size = 0; +- int index; +- const struct qp_entry *table = 0L; +- +- // alias enum +- enum { min = DAL_MM_MIN, max = DAL_MM_MAX }; +- switch (sel) { +- TABLE_CASE(444, 8, max); +- TABLE_CASE(444, 8, min); +- TABLE_CASE(444, 10, max); +- TABLE_CASE(444, 10, min); +- TABLE_CASE(444, 12, max); +- TABLE_CASE(444, 12, min); +- TABLE_CASE(422, 8, max); +- TABLE_CASE(422, 8, min); +- TABLE_CASE(422, 10, max); +- TABLE_CASE(422, 10, min); +- TABLE_CASE(422, 12, max); +- TABLE_CASE(422, 12, min); +- TABLE_CASE(420, 8, max); +- TABLE_CASE(420, 8, min); +- TABLE_CASE(420, 10, max); +- TABLE_CASE(420, 10, min); +- TABLE_CASE(420, 12, max); +- TABLE_CASE(420, 12, min); +- } +- +- if (table == 0) +- return; +- +- index = (bpp - table[0].bpp) * 2; +- +- /* requested size is bigger than the table */ +- if (index >= table_size) { +- dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n"); +- return; +- } +- +- memcpy(qps, table[index].qps, sizeof(qp_set)); +-} +- +-static double dsc_roundf(double num) +-{ +- if (num < 0.0) +- num = num - 0.5; +- else +- num = num + 0.5; +- +- return (int)(num); +-} +- +-static double dsc_ceil(double num) +-{ +- double retval = (int)num; +- +- if (retval != num && num > 0) +- retval = num + 1; +- +- return (int)retval; +-} +- +-static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp) +-{ +- int *p = ofs; +- +- if (mode == CM_444 || mode == CM_RGB) { +- *p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0)))))); +- *p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0)))))); +- *p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0)))))); +- *p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0)))))); +- *p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0)))))); +- *p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0)))); +- *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0)))); +- *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0)))); +- *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0)))); +- *p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0)))); +- *p++ = -10; +- *p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0)))); +- *p++ = -12; +- *p++ = -12; +- *p++ = -12; +- } else if (mode == CM_422) { +- *p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0)))); +- *p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0)))); +- *p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0)))); +- *p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0)))); +- *p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0)))); +- *p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0)))); +- *p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0)))); +- *p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0)))); +- *p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0)))); +- *p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0)))); +- *p++ = -10; +- *p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1)))); +- *p++ = -12; +- *p++ = -12; +- *p++ = -12; +- } else { +- *p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0)))); +- *p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0)))); +- *p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0)))); +- *p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0)))); +- *p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0)))); +- *p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0)))); +- *p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0)))); +- *p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0)))); +- *p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0)))); +- *p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0)))); +- *p++ = -10; +- *p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0)))); +- *p++ = -12; +- *p++ = -12; +- *p++ = -12; +- } +-} +- +-static int median3(int a, int b, int c) +-{ +- if (a > b) +- swap(a, b); +- if (b > c) +- swap(b, c); +- if (a > b) +- swap(b, c); +- +- return b; +-} +- +-static void _do_calc_rc_params(struct rc_params *rc, enum colour_mode cm, +- enum bits_per_comp bpc, u16 drm_bpp, +- bool is_navite_422_or_420, +- int slice_width, int slice_height, +- int minor_version) +-{ +- float bpp; +- float bpp_group; +- float initial_xmit_delay_factor; +- int padding_pixels; +- int i; +- +- bpp = ((float)drm_bpp / 16.0); +- /* in native_422 or native_420 modes, the bits_per_pixel is double the +- * target bpp (the latter is what calc_rc_params expects) +- */ +- if (is_navite_422_or_420) +- bpp /= 2.0; +- +- rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); +- rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); +- +- bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0); +- +- switch (cm) { +- case CM_420: +- rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584))))); +- rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group))); +- rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group))); +- break; +- case CM_422: +- rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584)))); +- rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group))); +- rc->second_line_bpg_offset = 0; +- break; +- case CM_444: +- case CM_RGB: +- rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2))))); +- rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group))); +- rc->second_line_bpg_offset = 0; +- break; +- } +- +- initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0; +- rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor); +- +- if (cm == CM_422 || cm == CM_420) +- slice_width /= 2; +- +- padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0; +- if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) { +- if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1) +- rc->initial_xmit_delay++; +- } +- +- rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); +- rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0); +- rc->flatness_det_thresh = 2 << (bpc - 8); +- +- get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp); +- get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp); +- if (cm == CM_444 && minor_version == 1) { +- for (i = 0; i < QP_SET_SIZE; ++i) { +- rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0; +- rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0; +- } +- } +- get_ofs_set(rc->ofs, cm, bpp); +- +- /* fixed parameters */ +- rc->rc_model_size = 8192; +- rc->rc_edge_factor = 6; +- rc->rc_tgt_offset_hi = 3; +- rc->rc_tgt_offset_lo = 3; +- +- rc->rc_buf_thresh[0] = 896; +- rc->rc_buf_thresh[1] = 1792; +- rc->rc_buf_thresh[2] = 2688; +- rc->rc_buf_thresh[3] = 3584; +- rc->rc_buf_thresh[4] = 4480; +- rc->rc_buf_thresh[5] = 5376; +- rc->rc_buf_thresh[6] = 6272; +- rc->rc_buf_thresh[7] = 6720; +- rc->rc_buf_thresh[8] = 7168; +- rc->rc_buf_thresh[9] = 7616; +- rc->rc_buf_thresh[10] = 7744; +- rc->rc_buf_thresh[11] = 7872; +- rc->rc_buf_thresh[12] = 8000; +- rc->rc_buf_thresh[13] = 8064; +-} +- +-static u32 _do_bytes_per_pixel_calc(int slice_width, u16 drm_bpp, +- bool is_navite_422_or_420) +-{ +- float bpp; +- u32 bytes_per_pixel; +- double d_bytes_per_pixel; +- +- bpp = ((float)drm_bpp / 16.0); +- d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width; +- // TODO: Make sure the formula for calculating this is precise (ceiling +- // vs. floor, and at what point they should be applied) +- if (is_navite_422_or_420) +- d_bytes_per_pixel /= 2; +- +- bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000); +- +- return bytes_per_pixel; +-} + + /** + * calc_rc_params - reads the user's cmdline mode +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h +index 262f06afcbf95..c2340e001b578 100644 +--- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h ++++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h +@@ -27,55 +27,7 @@ + #ifndef __RC_CALC_H__ + #define __RC_CALC_H__ + +- +-#define QP_SET_SIZE 15 +- +-typedef int qp_set[QP_SET_SIZE]; +- +-struct rc_params { +- int rc_quant_incr_limit0; +- int rc_quant_incr_limit1; +- int initial_fullness_offset; +- int initial_xmit_delay; +- int first_line_bpg_offset; +- int second_line_bpg_offset; +- int flatness_min_qp; +- int flatness_max_qp; +- int flatness_det_thresh; +- qp_set qp_min; +- qp_set qp_max; +- qp_set ofs; +- int rc_model_size; +- int rc_edge_factor; +- int rc_tgt_offset_hi; +- int rc_tgt_offset_lo; +- int rc_buf_thresh[QP_SET_SIZE - 1]; +-}; +- +-enum colour_mode { +- CM_RGB, /* 444 RGB */ +- CM_444, /* 444 YUV or simple 422 */ +- CM_422, /* native 422 */ +- CM_420 /* native 420 */ +-}; +- +-enum bits_per_comp { +- BPC_8 = 8, +- BPC_10 = 10, +- BPC_12 = 12 +-}; +- +-enum max_min { +- DAL_MM_MIN = 0, +- DAL_MM_MAX = 1 +-}; +- +-struct qp_entry { +- float bpp; +- const qp_set qps; +-}; +- +-typedef struct qp_entry qp_table[]; ++#include "dml/dsc/rc_calc_fpu.h" + + void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps); + u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps); +diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c +index ef830aded5b1c..1e19dd674e5a2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c ++++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c +@@ -22,7 +22,6 @@ + * Authors: AMD + * + */ +-#include "os_types.h" + #include <drm/drm_dsc.h> + #include "dscc_types.h" + #include "rc_calc.h" +diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h +index 571fcf23cea92..a3a9ea077f505 100644 +--- a/drivers/gpu/drm/amd/display/include/logger_types.h ++++ b/drivers/gpu/drm/amd/display/include/logger_types.h +@@ -72,6 +72,9 @@ + #define DC_LOG_DSC(...) DRM_DEBUG_KMS(__VA_ARGS__) + #define DC_LOG_SMU(...) pr_debug("[SMU_MSG]:"__VA_ARGS__) + #define DC_LOG_DWB(...) DRM_DEBUG_KMS(__VA_ARGS__) ++#if defined(CONFIG_DRM_AMD_DC_DCN) ++#define DC_LOG_DP2(...) DRM_DEBUG_KMS(__VA_ARGS__) ++#endif + + struct dal_logger; + +diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h +index 257f280d3d53f..bd077ea224a40 100644 +--- a/drivers/gpu/drm/amd/include/amd_shared.h ++++ b/drivers/gpu/drm/amd/include/amd_shared.h +@@ -98,7 +98,8 @@ enum amd_ip_block_type { + AMD_IP_BLOCK_TYPE_ACP, + AMD_IP_BLOCK_TYPE_VCN, + AMD_IP_BLOCK_TYPE_MES, +- AMD_IP_BLOCK_TYPE_JPEG ++ AMD_IP_BLOCK_TYPE_JPEG, ++ AMD_IP_BLOCK_TYPE_NUM, + }; + + enum amd_clockgating_state { +diff --git a/drivers/gpu/drm/amd/include/discovery.h b/drivers/gpu/drm/amd/include/discovery.h +index 7ec4331e67f26..a486769b66c6a 100644 +--- a/drivers/gpu/drm/amd/include/discovery.h ++++ b/drivers/gpu/drm/amd/include/discovery.h +@@ -143,6 +143,55 @@ struct gc_info_v1_0 { + uint32_t gc_num_gl2a; + }; + ++struct gc_info_v1_1 { ++ struct gpu_info_header header; ++ ++ uint32_t gc_num_se; ++ uint32_t gc_num_wgp0_per_sa; ++ uint32_t gc_num_wgp1_per_sa; ++ uint32_t gc_num_rb_per_se; ++ uint32_t gc_num_gl2c; ++ uint32_t gc_num_gprs; ++ uint32_t gc_num_max_gs_thds; ++ uint32_t gc_gs_table_depth; ++ uint32_t gc_gsprim_buff_depth; ++ uint32_t gc_parameter_cache_depth; ++ uint32_t gc_double_offchip_lds_buffer; ++ uint32_t gc_wave_size; ++ uint32_t gc_max_waves_per_simd; ++ uint32_t gc_max_scratch_slots_per_cu; ++ uint32_t gc_lds_size; ++ uint32_t gc_num_sc_per_se; ++ uint32_t gc_num_sa_per_se; ++ uint32_t gc_num_packer_per_sc; ++ uint32_t gc_num_gl2a; ++ uint32_t gc_num_tcp_per_sa; ++ uint32_t gc_num_sdp_interface; ++ uint32_t gc_num_tcps; ++}; ++ ++struct gc_info_v2_0 { ++ struct gpu_info_header header; ++ ++ uint32_t gc_num_se; ++ uint32_t gc_num_cu_per_sh; ++ uint32_t gc_num_sh_per_se; ++ uint32_t gc_num_rb_per_se; ++ uint32_t gc_num_tccs; ++ uint32_t gc_num_gprs; ++ uint32_t gc_num_max_gs_thds; ++ uint32_t gc_gs_table_depth; ++ uint32_t gc_gsprim_buff_depth; ++ uint32_t gc_parameter_cache_depth; ++ uint32_t gc_double_offchip_lds_buffer; ++ uint32_t gc_wave_size; ++ uint32_t gc_max_waves_per_simd; ++ uint32_t gc_max_scratch_slots_per_cu; ++ uint32_t gc_lds_size; ++ uint32_t gc_num_sc_per_se; ++ uint32_t gc_num_packer_per_sc; ++}; ++ + typedef struct harvest_info_header { + uint32_t signature; /* Table Signature */ + uint32_t version; /* Table Version */ +diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +index 03581d5b18360..08362d506534b 100644 +--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c ++++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block + { + int ret = 0; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; ++ enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; ++ ++ if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) { ++ dev_dbg(adev->dev, "IP block%d already in the target %s state!", ++ block_type, gate ? "gate" : "ungate"); ++ return 0; ++ } + + switch (block_type) { + case AMD_IP_BLOCK_TYPE_UVD: +@@ -979,6 +986,9 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block + break; + } + ++ if (!ret) ++ atomic_set(&adev->pm.pwr_state[block_type], pwr_state); ++ + return ret; + } + +diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c +index 249cb0aeb5ae4..640db5020ccc3 100644 +--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c ++++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c +@@ -2117,6 +2117,12 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ + } + } + ++ /* setting should not be allowed from VF */ ++ if (amdgpu_sriov_vf(adev)) { ++ dev_attr->attr.mode &= ~S_IWUGO; ++ dev_attr->store = NULL; ++ } ++ + #undef DEVICE_ATTR_IS + + return 0; +@@ -3439,8 +3445,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, + attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr || + attr == &sensor_dev_attr_power2_cap.dev_attr.attr || + attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || +- attr == &sensor_dev_attr_power2_label.dev_attr.attr || +- attr == &sensor_dev_attr_power1_label.dev_attr.attr)) ++ attr == &sensor_dev_attr_power2_label.dev_attr.attr)) + return 0; + + return effective_mode; +diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +index 98f1b3d8c1d59..16e3f72d31b9f 100644 +--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h ++++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +@@ -417,6 +417,12 @@ struct amdgpu_dpm { + enum amd_dpm_forced_level forced_level; + }; + ++enum ip_power_state { ++ POWER_STATE_UNKNOWN, ++ POWER_STATE_ON, ++ POWER_STATE_OFF, ++}; ++ + struct amdgpu_pm { + struct mutex mutex; + u32 current_sclk; +@@ -452,6 +458,8 @@ struct amdgpu_pm { + struct i2c_adapter smu_i2c; + struct mutex smu_i2c_mutex; + struct list_head pm_attr_list; ++ ++ atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM]; + }; + + #define R600_SSTU_DFLT 0 +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +index 1de3ae77e03ed..1f406f21b452f 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +@@ -1036,13 +1036,13 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, + else + i = 1; + +- size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", ++ size += sprintf(buf + size, "0: %uMhz %s\n", + data->gfx_min_freq_limit/100, + i == 0 ? "*" : ""); +- size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", ++ size += sprintf(buf + size, "1: %uMhz %s\n", + i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK, + i == 1 ? "*" : ""); +- size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", ++ size += sprintf(buf + size, "2: %uMhz %s\n", + data->gfx_max_freq_limit/100, + i == 2 ? "*" : ""); + break; +@@ -1050,7 +1050,7 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now); + + for (i = 0; i < mclk_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, + mclk_table->entries[i].clk / 100, + ((mclk_table->entries[i].clk / 100) +@@ -1065,10 +1065,10 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, + if (ret) + return ret; + +- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); +- size += sysfs_emit_at(buf, size, "0: %10uMhz\n", ++ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); ++ size += sprintf(buf + size, "0: %10uMhz\n", + (data->gfx_actual_soft_min_freq > 0) ? data->gfx_actual_soft_min_freq : min_freq); +- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", ++ size += sprintf(buf + size, "1: %10uMhz\n", + (data->gfx_actual_soft_max_freq > 0) ? data->gfx_actual_soft_max_freq : max_freq); + } + break; +@@ -1081,8 +1081,8 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, + if (ret) + return ret; + +- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +- size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n", ++ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); ++ size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + min_freq, max_freq); + } + break; +@@ -1456,6 +1456,8 @@ static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) + if (!buf) + return -EINVAL; + ++ phm_get_sysfs_buf(&buf, &size); ++ + size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n",title[0], + title[1], title[2], title[3], title[4], title[5]); + +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +index e7803ce8f67aa..611969bf45207 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +@@ -4926,7 +4926,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, + now = i; + + for (i = 0; i < sclk_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, sclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; +@@ -4941,7 +4941,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, + now = i; + + for (i = 0; i < mclk_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, mclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; +@@ -4955,7 +4955,7 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, + now = i; + + for (i = 0; i < pcie_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %s %s\n", i, ++ size += sprintf(buf + size, "%d: %s %s\n", i, + (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" : + (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" : + (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "", +@@ -4963,32 +4963,32 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, + break; + case OD_SCLK: + if (hwmgr->od_enabled) { +- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); ++ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); + for (i = 0; i < odn_sclk_table->num_of_pl; i++) +- size += sysfs_emit_at(buf, size, "%d: %10uMHz %10umV\n", ++ size += sprintf(buf + size, "%d: %10uMHz %10umV\n", + i, odn_sclk_table->entries[i].clock/100, + odn_sclk_table->entries[i].vddc); + } + break; + case OD_MCLK: + if (hwmgr->od_enabled) { +- size = sysfs_emit(buf, "%s:\n", "OD_MCLK"); ++ size += sprintf(buf + size, "%s:\n", "OD_MCLK"); + for (i = 0; i < odn_mclk_table->num_of_pl; i++) +- size += sysfs_emit_at(buf, size, "%d: %10uMHz %10umV\n", ++ size += sprintf(buf + size, "%d: %10uMHz %10umV\n", + i, odn_mclk_table->entries[i].clock/100, + odn_mclk_table->entries[i].vddc); + } + break; + case OD_RANGE: + if (hwmgr->od_enabled) { +- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +- size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n", ++ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); ++ size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); +- size += sysfs_emit_at(buf, size, "MCLK: %7uMHz %10uMHz\n", ++ size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); +- size += sysfs_emit_at(buf, size, "VDDC: %7umV %11umV\n", ++ size += sprintf(buf + size, "VDDC: %7umV %11umV\n", + data->odn_dpm_table.min_vddc, + data->odn_dpm_table.max_vddc); + } +@@ -5518,6 +5518,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) + if (!buf) + return -EINVAL; + ++ phm_get_sysfs_buf(&buf, &size); ++ + size += sysfs_emit_at(buf, size, "%s %16s %16s %16s %16s %16s %16s %16s\n", + title[0], title[1], title[2], title[3], + title[4], title[5], title[6], title[7]); +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +index b94a77e4e7147..03bf8f0692228 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +@@ -1559,7 +1559,7 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, + CURR_SCLK_INDEX); + + for (i = 0; i < sclk_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, sclk_table->entries[i].clk / 100, + (i == now) ? "*" : ""); + break; +@@ -1571,7 +1571,7 @@ static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, + CURR_MCLK_INDEX); + + for (i = SMU8_NUM_NBPMEMORYCLOCK; i > 0; i--) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + SMU8_NUM_NBPMEMORYCLOCK-i, data->sys_info.nbp_memory_clock[i-1] / 100, + (SMU8_NUM_NBPMEMORYCLOCK-i == now) ? "*" : ""); + break; +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h +index ad33983a8064e..2a75da1e9f035 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h +@@ -109,6 +109,19 @@ int phm_irq_process(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); + ++/* ++ * Helper function to make sysfs_emit_at() happy. Align buf to ++ * the current page boundary and record the offset. ++ */ ++static inline void phm_get_sysfs_buf(char **buf, int *offset) ++{ ++ if (!*buf || !offset) ++ return; ++ ++ *offset = offset_in_page(*buf); ++ *buf -= *offset; ++} ++ + int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr); + + void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size, +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +index c152a61ddd2c9..e6336654c5655 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +@@ -4548,6 +4548,8 @@ static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) + int ret = 0; + int size = 0; + ++ phm_get_sysfs_buf(&buf, &size); ++ + ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", +@@ -4650,7 +4652,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + else + count = sclk_table->count; + for (i = 0; i < count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, sclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; +@@ -4661,7 +4663,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); + + for (i = 0; i < mclk_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, mclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; +@@ -4672,7 +4674,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); + + for (i = 0; i < soc_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, soc_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; +@@ -4684,7 +4686,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now); + + for (i = 0; i < dcef_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, dcef_table->dpm_levels[i].value / 100, + (dcef_table->dpm_levels[i].value / 100 == now) ? + "*" : ""); +@@ -4698,7 +4700,7 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + gen_speed = pptable->PcieGenSpeed[i]; + lane_width = pptable->PcieLaneCount[i]; + +- size += sysfs_emit_at(buf, size, "%d: %s %s %s\n", i, ++ size += sprintf(buf + size, "%d: %s %s %s\n", i, + (gen_speed == 0) ? "2.5GT/s," : + (gen_speed == 1) ? "5.0GT/s," : + (gen_speed == 2) ? "8.0GT/s," : +@@ -4717,34 +4719,34 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + + case OD_SCLK: + if (hwmgr->od_enabled) { +- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); ++ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; + for (i = 0; i < podn_vdd_dep->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %10uMhz %10umV\n", ++ size += sprintf(buf + size, "%d: %10uMhz %10umV\n", + i, podn_vdd_dep->entries[i].clk / 100, + podn_vdd_dep->entries[i].vddc); + } + break; + case OD_MCLK: + if (hwmgr->od_enabled) { +- size = sysfs_emit(buf, "%s:\n", "OD_MCLK"); ++ size += sprintf(buf + size, "%s:\n", "OD_MCLK"); + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; + for (i = 0; i < podn_vdd_dep->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %10uMhz %10umV\n", ++ size += sprintf(buf + size, "%d: %10uMhz %10umV\n", + i, podn_vdd_dep->entries[i].clk/100, + podn_vdd_dep->entries[i].vddc); + } + break; + case OD_RANGE: + if (hwmgr->od_enabled) { +- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +- size += sysfs_emit_at(buf, size, "SCLK: %7uMHz %10uMHz\n", ++ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); ++ size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); +- size += sysfs_emit_at(buf, size, "MCLK: %7uMHz %10uMHz\n", ++ size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.mem_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); +- size += sysfs_emit_at(buf, size, "VDDC: %7umV %11umV\n", ++ size += sprintf(buf + size, "VDDC: %7umV %11umV\n", + data->odn_dpm_table.min_vddc, + data->odn_dpm_table.max_vddc); + } +@@ -5112,6 +5114,8 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) + if (!buf) + return -EINVAL; + ++ phm_get_sysfs_buf(&buf, &size); ++ + size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n",title[0], + title[1], title[2], title[3], title[4], title[5]); + +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c +index 8558718e15a8f..a2f4d6773d458 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c +@@ -2141,6 +2141,8 @@ static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) + int ret = 0; + int size = 0; + ++ phm_get_sysfs_buf(&buf, &size); ++ + ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", +@@ -2256,7 +2258,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, + "Attempt to get gfx clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); + break; +@@ -2272,7 +2274,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, + "Attempt to get memory clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); + break; +@@ -2290,7 +2292,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, + "Attempt to get soc clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); + break; +@@ -2308,7 +2310,7 @@ static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, + "Attempt to get dcef clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); + break; +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +index 0cf39c1244b1c..85d55ab4e369f 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +@@ -3238,6 +3238,8 @@ static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) + int ret = 0; + int size = 0; + ++ phm_get_sysfs_buf(&buf, &size); ++ + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", +@@ -3372,13 +3374,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + return ret); + + if (vega20_get_sclks(hwmgr, &clocks)) { +- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", ++ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; +@@ -3390,13 +3392,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + return ret); + + if (vega20_get_memclocks(hwmgr, &clocks)) { +- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", ++ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; +@@ -3408,13 +3410,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + return ret); + + if (vega20_get_socclocks(hwmgr, &clocks)) { +- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", ++ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; +@@ -3426,7 +3428,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + return ret); + + for (i = 0; i < fclk_dpm_table->count; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, fclk_dpm_table->dpm_levels[i].value, + fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : ""); + break; +@@ -3438,13 +3440,13 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + return ret); + + if (vega20_get_dcefclocks(hwmgr, &clocks)) { +- size += sysfs_emit_at(buf, size, "0: %uMhz * (DPM disabled)\n", ++ size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) +- size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", ++ size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; +@@ -3458,7 +3460,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + gen_speed = pptable->PcieGenSpeed[i]; + lane_width = pptable->PcieLaneCount[i]; + +- size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i, ++ size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, + (gen_speed == 0) ? "2.5GT/s," : + (gen_speed == 1) ? "5.0GT/s," : + (gen_speed == 2) ? "8.0GT/s," : +@@ -3479,18 +3481,18 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + case OD_SCLK: + if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { +- size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); +- size += sysfs_emit_at(buf, size, "0: %10uMhz\n", ++ size += sprintf(buf + size, "%s:\n", "OD_SCLK"); ++ size += sprintf(buf + size, "0: %10uMhz\n", + od_table->GfxclkFmin); +- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", ++ size += sprintf(buf + size, "1: %10uMhz\n", + od_table->GfxclkFmax); + } + break; + + case OD_MCLK: + if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { +- size = sysfs_emit(buf, "%s:\n", "OD_MCLK"); +- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", ++ size += sprintf(buf + size, "%s:\n", "OD_MCLK"); ++ size += sprintf(buf + size, "1: %10uMhz\n", + od_table->UclkFmax); + } + +@@ -3503,14 +3505,14 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { +- size = sysfs_emit(buf, "%s:\n", "OD_VDDC_CURVE"); +- size += sysfs_emit_at(buf, size, "0: %10uMhz %10dmV\n", ++ size += sprintf(buf + size, "%s:\n", "OD_VDDC_CURVE"); ++ size += sprintf(buf + size, "0: %10uMhz %10dmV\n", + od_table->GfxclkFreq1, + od_table->GfxclkVolt1 / VOLTAGE_SCALE); +- size += sysfs_emit_at(buf, size, "1: %10uMhz %10dmV\n", ++ size += sprintf(buf + size, "1: %10uMhz %10dmV\n", + od_table->GfxclkFreq2, + od_table->GfxclkVolt2 / VOLTAGE_SCALE); +- size += sysfs_emit_at(buf, size, "2: %10uMhz %10dmV\n", ++ size += sprintf(buf + size, "2: %10uMhz %10dmV\n", + od_table->GfxclkFreq3, + od_table->GfxclkVolt3 / VOLTAGE_SCALE); + } +@@ -3518,17 +3520,17 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + break; + + case OD_RANGE: +- size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); ++ size += sprintf(buf + size, "%s:\n", "OD_RANGE"); + + if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { +- size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", ++ size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, + od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); + } + + if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { +- size += sysfs_emit_at(buf, size, "MCLK: %7uMhz %10uMhz\n", ++ size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_UCLK_FMAX].min_value, + od8_settings[OD8_SETTING_UCLK_FMAX].max_value); + } +@@ -3539,22 +3541,22 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { +- size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", ++ size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, + od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value); +- size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", ++ size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); +- size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", ++ size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, + od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value); +- size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", ++ size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); +- size += sysfs_emit_at(buf, size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", ++ size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, + od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value); +- size += sysfs_emit_at(buf, size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", ++ size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); + } +@@ -4003,6 +4005,8 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) + if (!buf) + return -EINVAL; + ++ phm_get_sysfs_buf(&buf, &size); ++ + size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n", + title[0], title[1], title[2], title[3], title[4], title[5], + title[6], title[7], title[8], title[9], title[10]); +diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +index 04863a7971155..6dc83cfad9d84 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +@@ -1386,8 +1386,14 @@ static int smu_disable_dpms(struct smu_context *smu) + { + struct amdgpu_device *adev = smu->adev; + int ret = 0; ++ /* ++ * TODO: (adev->in_suspend && !adev->in_s0ix) is added to pair ++ * the workaround which always reset the asic in suspend. ++ * It's likely that workaround will be dropped in the future. ++ * Then the change here should be dropped together. ++ */ + bool use_baco = !smu->is_apu && +- ((amdgpu_in_reset(adev) && ++ (((amdgpu_in_reset(adev) || (adev->in_suspend && !adev->in_s0ix)) && + (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || + ((adev->in_runpm || adev->in_s4) && amdgpu_asic_supports_baco(adev))); + +@@ -1536,9 +1542,7 @@ static int smu_suspend(void *handle) + + smu->watermarks_bitmap &= ~(WATERMARKS_LOADED); + +- /* skip CGPG when in S0ix */ +- if (smu->is_apu && !adev->in_s0ix) +- smu_set_gfx_cgpg(&adev->smu, false); ++ smu_set_gfx_cgpg(&adev->smu, false); + + return 0; + } +@@ -1569,8 +1573,7 @@ static int smu_resume(void *handle) + return ret; + } + +- if (smu->is_apu) +- smu_set_gfx_cgpg(&adev->smu, true); ++ smu_set_gfx_cgpg(&adev->smu, true); + + smu->disable_uclk_switch = 0; + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +index b1ad451af06bd..dfba0bc732073 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +@@ -1265,7 +1265,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, char *buf) + { + uint16_t *curve_settings; +- int i, size = 0, ret = 0; ++ int i, levels, size = 0, ret = 0; + uint32_t cur_value = 0, value = 0, count = 0; + uint32_t freq_values[3] = {0}; + uint32_t mark_index = 0; +@@ -1319,14 +1319,17 @@ static int navi10_print_clk_levels(struct smu_context *smu, + freq_values[1] = cur_value; + mark_index = cur_value == freq_values[0] ? 0 : + cur_value == freq_values[2] ? 2 : 1; +- if (mark_index != 1) +- freq_values[1] = (freq_values[0] + freq_values[2]) / 2; + +- for (i = 0; i < 3; i++) { ++ levels = 3; ++ if (mark_index != 1) { ++ levels = 2; ++ freq_values[1] = freq_values[2]; ++ } ++ ++ for (i = 0; i < levels; i++) { + size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, freq_values[i], + i == mark_index ? "*" : ""); + } +- + } + break; + case SMU_PCIE: +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +index ca57221e39629..574a9d7f7a5e7 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +@@ -418,6 +418,36 @@ static int sienna_cichlid_store_powerplay_table(struct smu_context *smu) + return 0; + } + ++static int sienna_cichlid_patch_pptable_quirk(struct smu_context *smu) ++{ ++ struct amdgpu_device *adev = smu->adev; ++ uint32_t *board_reserved; ++ uint16_t *freq_table_gfx; ++ uint32_t i; ++ ++ /* Fix some OEM SKU specific stability issues */ ++ GET_PPTABLE_MEMBER(BoardReserved, &board_reserved); ++ if ((adev->pdev->device == 0x73DF) && ++ (adev->pdev->revision == 0XC3) && ++ (adev->pdev->subsystem_device == 0x16C2) && ++ (adev->pdev->subsystem_vendor == 0x1043)) ++ board_reserved[0] = 1387; ++ ++ GET_PPTABLE_MEMBER(FreqTableGfx, &freq_table_gfx); ++ if ((adev->pdev->device == 0x73DF) && ++ (adev->pdev->revision == 0XC3) && ++ ((adev->pdev->subsystem_device == 0x16C2) || ++ (adev->pdev->subsystem_device == 0x133C)) && ++ (adev->pdev->subsystem_vendor == 0x1043)) { ++ for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) { ++ if (freq_table_gfx[i] > 2500) ++ freq_table_gfx[i] = 2500; ++ } ++ } ++ ++ return 0; ++} ++ + static int sienna_cichlid_setup_pptable(struct smu_context *smu) + { + int ret = 0; +@@ -438,7 +468,7 @@ static int sienna_cichlid_setup_pptable(struct smu_context *smu) + if (ret) + return ret; + +- return ret; ++ return sienna_cichlid_patch_pptable_quirk(smu); + } + + static int sienna_cichlid_tables_init(struct smu_context *smu) +@@ -1278,21 +1308,37 @@ static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu) + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; ++ struct amdgpu_device *adev = smu->adev; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.peak = gfx_table->max; +- if (gfx_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK) +- pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; +- if (mem_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK) +- pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; +- if (soc_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK) ++ ++ switch (adev->asic_type) { ++ case CHIP_SIENNA_CICHLID: ++ case CHIP_NAVY_FLOUNDER: ++ pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK; ++ pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK; + pstate_table->socclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK; ++ break; ++ case CHIP_DIMGREY_CAVEFISH: ++ pstate_table->gfxclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_GFXCLK; ++ pstate_table->uclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_MEMCLK; ++ pstate_table->socclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_SOCCLK; ++ break; ++ case CHIP_BEIGE_GOBY: ++ pstate_table->gfxclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_GFXCLK; ++ pstate_table->uclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_MEMCLK; ++ pstate_table->socclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_SOCCLK; ++ break; ++ default: ++ break; ++ } + + return 0; + } +@@ -3728,14 +3774,14 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, + + static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) + { +- struct smu_table_context *table_context = &smu->smu_table; +- PPTable_t *smc_pptable = table_context->driver_pptable; ++ uint16_t *mgpu_fan_boost_limit_rpm; + ++ GET_PPTABLE_MEMBER(MGpuFanBoostLimitRpm, &mgpu_fan_boost_limit_rpm); + /* + * Skip the MGpuFanBoost setting for those ASICs + * which do not support it + */ +- if (!smc_pptable->MGpuFanBoostLimitRpm) ++ if (*mgpu_fan_boost_limit_rpm == 0) + return 0; + + return smu_cmn_send_smc_msg_with_param(smu, +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h +index 38cd0ece24f6b..42f705c7a36f8 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h +@@ -33,6 +33,14 @@ typedef enum { + #define SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK 960 + #define SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK 1000 + ++#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_GFXCLK 1950 ++#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_SOCCLK 960 ++#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_MEMCLK 676 ++ ++#define BEIGE_GOBY_UMD_PSTATE_PROFILING_GFXCLK 2200 ++#define BEIGE_GOBY_UMD_PSTATE_PROFILING_SOCCLK 960 ++#define BEIGE_GOBY_UMD_PSTATE_PROFILING_MEMCLK 1000 ++ + extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu); + + #endif +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +index f6ef0ce6e9e2c..a9dceef4a7011 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +@@ -1386,52 +1386,38 @@ static int vangogh_set_performance_level(struct smu_context *smu, + uint32_t soc_mask, mclk_mask, fclk_mask; + uint32_t vclk_mask = 0, dclk_mask = 0; + ++ smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; ++ smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; ++ + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: +- smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; ++ smu->gfx_actual_hard_min_freq = smu->gfx_default_soft_max_freq; + smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; + +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; + + ret = vangogh_force_dpm_limit_value(smu, true); ++ if (ret) ++ return ret; + break; + case AMD_DPM_FORCED_LEVEL_LOW: + smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; +- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; +- +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; ++ smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq; + + ret = vangogh_force_dpm_limit_value(smu, false); ++ if (ret) ++ return ret; + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; + smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; + +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; +- + ret = vangogh_unforce_dpm_levels(smu); +- break; +- case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: +- smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; +- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; +- +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; +- +- ret = smu_cmn_send_smc_msg_with_param(smu, +- SMU_MSG_SetHardMinGfxClk, +- VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL); +- if (ret) +- return ret; +- +- ret = smu_cmn_send_smc_msg_with_param(smu, +- SMU_MSG_SetSoftMaxGfxClk, +- VANGOGH_UMD_PSTATE_STANDARD_GFXCLK, NULL); + if (ret) + return ret; ++ break; ++ case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: ++ smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK; ++ smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_STANDARD_GFXCLK; + + ret = vangogh_get_profiling_clk_mask(smu, level, + &vclk_mask, +@@ -1446,32 +1432,15 @@ static int vangogh_set_performance_level(struct smu_context *smu, + vangogh_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); + vangogh_force_clk_levels(smu, SMU_VCLK, 1 << vclk_mask); + vangogh_force_clk_levels(smu, SMU_DCLK, 1 << dclk_mask); +- + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; +- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; +- +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; +- +- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, +- VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL); +- if (ret) +- return ret; +- +- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, +- VANGOGH_UMD_PSTATE_PEAK_DCLK, NULL); +- if (ret) +- return ret; ++ smu->gfx_actual_soft_max_freq = smu->gfx_default_hard_min_freq; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; + smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; + +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; +- + ret = vangogh_get_profiling_clk_mask(smu, level, + NULL, + NULL, +@@ -1484,29 +1453,29 @@ static int vangogh_set_performance_level(struct smu_context *smu, + vangogh_force_clk_levels(smu, SMU_FCLK, 1 << fclk_mask); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: +- smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; +- smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; +- +- smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; +- smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; +- +- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, +- VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL); +- if (ret) +- return ret; ++ smu->gfx_actual_hard_min_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK; ++ smu->gfx_actual_soft_max_freq = VANGOGH_UMD_PSTATE_PEAK_GFXCLK; + +- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, +- VANGOGH_UMD_PSTATE_PEAK_GFXCLK, NULL); ++ ret = vangogh_set_peak_clock_by_device(smu); + if (ret) + return ret; +- +- ret = vangogh_set_peak_clock_by_device(smu); + break; + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: +- break; ++ return 0; + } ++ ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, ++ smu->gfx_actual_hard_min_freq, NULL); ++ if (ret) ++ return ret; ++ ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, ++ smu->gfx_actual_soft_max_freq, NULL); ++ if (ret) ++ return ret; ++ + return ret; + } + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c +index d60b8c5e87157..9c91e79c955fb 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c +@@ -120,7 +120,8 @@ int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate) + + int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable) + { +- if (!(smu->adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) ++ /* Until now the SMU12 only implemented for Renoir series so here neen't do APU check. */ ++ if (!(smu->adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) || smu->adev->in_s0ix) + return 0; + + return smu_cmn_send_smc_msg_with_param(smu, +@@ -191,6 +192,9 @@ int smu_v12_0_fini_smc_tables(struct smu_context *smu) + kfree(smu_table->watermarks_table); + smu_table->watermarks_table = NULL; + ++ kfree(smu_table->gpu_metrics_table); ++ smu_table->gpu_metrics_table = NULL; ++ + return 0; + } + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +index 5019903db492a..c9cfeb094750d 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +@@ -1619,7 +1619,7 @@ static int aldebaran_allow_xgmi_power_down(struct smu_context *smu, bool en) + { + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GmiPwrDnControl, +- en ? 1 : 0, ++ en ? 0 : 1, + NULL); + } + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +index a0e50f23b1dd7..8d4aa16b2ae7c 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +@@ -197,6 +197,7 @@ int smu_v13_0_check_fw_status(struct smu_context *smu) + + int smu_v13_0_check_fw_version(struct smu_context *smu) + { ++ struct amdgpu_device *adev = smu->adev; + uint32_t if_version = 0xff, smu_version = 0xff; + uint16_t smu_major; + uint8_t smu_minor, smu_debug; +@@ -209,6 +210,8 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) + smu_major = (smu_version >> 16) & 0xffff; + smu_minor = (smu_version >> 8) & 0xff; + smu_debug = (smu_version >> 0) & 0xff; ++ if (smu->is_apu) ++ adev->pm.fw_version = smu_version; + + switch (smu->adev->asic_type) { + case CHIP_ALDEBARAN: +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +index a403657151ba1..0e1a843608e43 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +@@ -291,14 +291,9 @@ static int yellow_carp_post_smu_init(struct smu_context *smu) + + static int yellow_carp_mode_reset(struct smu_context *smu, int type) + { +- int ret = 0, index = 0; +- +- index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, +- SMU_MSG_GfxDeviceDriverReset); +- if (index < 0) +- return index == -EACCES ? 0 : index; ++ int ret = 0; + +- ret = smu_cmn_send_smc_msg_with_param(smu, (uint16_t)index, type, NULL); ++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, type, NULL); + if (ret) + dev_err(smu->adev->dev, "Failed to mode reset!\n"); + +diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +index b53fee6f1c170..65f172807a0d5 100644 +--- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c ++++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +@@ -291,7 +291,7 @@ vga_pw_show(struct device *dev, struct device_attribute *attr, char *buf) + if (rc) + return rc; + +- return sprintf(buf, "%u\n", reg & 1); ++ return sprintf(buf, "%u\n", reg); + } + static DEVICE_ATTR_RO(vga_pw); + +diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c +index 1e30eaeb0e1b3..d5c98f79d58d3 100644 +--- a/drivers/gpu/drm/ast/ast_mode.c ++++ b/drivers/gpu/drm/ast/ast_mode.c +@@ -1121,7 +1121,10 @@ static void ast_crtc_reset(struct drm_crtc *crtc) + if (crtc->state) + crtc->funcs->atomic_destroy_state(crtc, crtc->state); + +- __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); ++ if (ast_state) ++ __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); ++ else ++ __drm_atomic_helper_crtc_reset(crtc, NULL); + } + + static struct drm_crtc_state * +diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h +index d9eb353a4bf09..dbe1cc620f6e6 100644 +--- a/drivers/gpu/drm/ast/ast_tables.h ++++ b/drivers/gpu/drm/ast/ast_tables.h +@@ -282,8 +282,6 @@ static const struct ast_vbios_enhtable res_1360x768[] = { + }; + + static const struct ast_vbios_enhtable res_1600x900[] = { +- {1800, 1600, 24, 80, 1000, 900, 1, 3, VCLK108, /* 60Hz */ +- (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 3, 0x3A }, + {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75, /* 60Hz CVT RB */ + (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | + AST2500PreCatchCRT), 60, 1, 0x3A }, +diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +index cab6c8b92efd4..6a4f20fccf841 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +@@ -998,11 +998,21 @@ int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, + if (!blocking) + return 0; + ++ /* ++ * db[1]!=0: entering PSR, wait for fully active remote frame buffer. ++ * db[1]==0: exiting PSR, wait for either ++ * (a) ACTIVE_RESYNC - the sink "must display the ++ * incoming active frames from the Source device with no visible ++ * glitches and/or artifacts", even though timings may still be ++ * re-synchronizing; or ++ * (b) INACTIVE - the transition is fully complete. ++ */ + ret = readx_poll_timeout(analogix_dp_get_psr_status, dp, psr_status, + psr_status >= 0 && + ((vsc->db[1] && psr_status == DP_PSR_SINK_ACTIVE_RFB) || +- (!vsc->db[1] && psr_status == DP_PSR_SINK_INACTIVE)), 1500, +- DP_TIMEOUT_PSR_LOOP_MS * 1000); ++ (!vsc->db[1] && (psr_status == DP_PSR_SINK_ACTIVE_RESYNC || ++ psr_status == DP_PSR_SINK_INACTIVE))), ++ 1500, DP_TIMEOUT_PSR_LOOP_MS * 1000); + if (ret) { + dev_warn(dp->dev, "Failed to apply PSR %d\n", ret); + return ret; +diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c +index 14d73fb1dd15b..ea414cd349b5c 100644 +--- a/drivers/gpu/drm/bridge/analogix/anx7625.c ++++ b/drivers/gpu/drm/bridge/analogix/anx7625.c +@@ -720,7 +720,7 @@ static int edid_read(struct anx7625_data *ctx, + ret = sp_tx_aux_rd(ctx, 0xf1); + + if (ret) { +- sp_tx_rst_aux(ctx); ++ ret = sp_tx_rst_aux(ctx); + DRM_DEV_DEBUG_DRIVER(dev, "edid read fail, reset!\n"); + } else { + ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client, +@@ -735,7 +735,7 @@ static int edid_read(struct anx7625_data *ctx, + if (cnt > EDID_TRY_CNT) + return -EIO; + +- return 0; ++ return ret; + } + + static int segments_edid_read(struct anx7625_data *ctx, +@@ -785,7 +785,7 @@ static int segments_edid_read(struct anx7625_data *ctx, + if (cnt > EDID_TRY_CNT) + return -EIO; + +- return 0; ++ return ret; + } + + static int sp_tx_edid_read(struct anx7625_data *ctx, +@@ -887,7 +887,11 @@ static int sp_tx_edid_read(struct anx7625_data *ctx, + } + + /* Reset aux channel */ +- sp_tx_rst_aux(ctx); ++ ret = sp_tx_rst_aux(ctx); ++ if (ret < 0) { ++ DRM_DEV_ERROR(dev, "Failed to reset aux channel!\n"); ++ return ret; ++ } + + return (blocks_num + 1); + } +diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c +index 05eb759da6fc6..847a0dce7f1d3 100644 +--- a/drivers/gpu/drm/bridge/display-connector.c ++++ b/drivers/gpu/drm/bridge/display-connector.c +@@ -107,7 +107,7 @@ static int display_connector_probe(struct platform_device *pdev) + { + struct display_connector *conn; + unsigned int type; +- const char *label; ++ const char *label = NULL; + int ret; + + conn = devm_kzalloc(&pdev->dev, sizeof(*conn), GFP_KERNEL); +diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c +index 2f2a09adb4bc8..06b59b422c696 100644 +--- a/drivers/gpu/drm/bridge/ite-it66121.c ++++ b/drivers/gpu/drm/bridge/ite-it66121.c +@@ -889,7 +889,7 @@ unlock: + static int it66121_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +- u32 vendor_ids[2], device_ids[2], revision_id; ++ u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; + struct device_node *ep; + int ret; + struct it66121_ctx *ctx; +@@ -918,11 +918,26 @@ static int it66121_probe(struct i2c_client *client, + return -EINVAL; + + ep = of_graph_get_remote_node(dev->of_node, 1, -1); +- if (!ep) +- return -EPROBE_DEFER; ++ if (!ep) { ++ dev_err(ctx->dev, "The endpoint is unconnected\n"); ++ return -EINVAL; ++ } ++ ++ if (!of_device_is_available(ep)) { ++ of_node_put(ep); ++ dev_err(ctx->dev, "The remote device is disabled\n"); ++ return -ENODEV; ++ } + + ctx->next_bridge = of_drm_find_bridge(ep); + of_node_put(ep); ++ if (!ctx->next_bridge) { ++ dev_dbg(ctx->dev, "Next bridge not found, deferring probe\n"); ++ return -EPROBE_DEFER; ++ } ++ ++ if (!ctx->next_bridge) ++ return -EPROBE_DEFER; + + i2c_set_clientdata(client, ctx); + mutex_init(&ctx->lock); +diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +index 3cac16db970f0..010657ea7af78 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c ++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +@@ -167,9 +167,10 @@ static void lt9611uxc_hpd_work(struct work_struct *work) + struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work); + bool connected; + +- if (lt9611uxc->connector.dev) +- drm_kms_helper_hotplug_event(lt9611uxc->connector.dev); +- else { ++ if (lt9611uxc->connector.dev) { ++ if (lt9611uxc->connector.dev->mode_config.funcs) ++ drm_kms_helper_hotplug_event(lt9611uxc->connector.dev); ++ } else { + + mutex_lock(<9611uxc->ocm_lock); + connected = lt9611uxc->hdmi_connected; +@@ -339,6 +340,8 @@ static int lt9611uxc_connector_init(struct drm_bridge *bridge, struct lt9611uxc + return -ENODEV; + } + ++ lt9611uxc->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ + drm_connector_helper_add(<9611uxc->connector, + <9611uxc_bridge_connector_helper_funcs); + ret = drm_connector_init(bridge->dev, <9611uxc->connector, +diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +index d2808c4a6fb1c..cce98bf2a4e73 100644 +--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c ++++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +@@ -306,19 +306,10 @@ out: + mutex_unlock(&ge_b850v3_lvds_dev_mutex); + } + +-static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, +- const struct i2c_device_id *id) ++static int ge_b850v3_register(void) + { ++ struct i2c_client *stdp4028_i2c = ge_b850v3_lvds_ptr->stdp4028_i2c; + struct device *dev = &stdp4028_i2c->dev; +- int ret; +- +- ret = ge_b850v3_lvds_init(dev); +- +- if (ret) +- return ret; +- +- ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c; +- i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr); + + /* drm bridge initialization */ + ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; +@@ -343,6 +334,27 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, + "ge-b850v3-lvds-dp", ge_b850v3_lvds_ptr); + } + ++static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &stdp4028_i2c->dev; ++ int ret; ++ ++ ret = ge_b850v3_lvds_init(dev); ++ ++ if (ret) ++ return ret; ++ ++ ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c; ++ i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr); ++ ++ /* Only register after both bridges are probed */ ++ if (!ge_b850v3_lvds_ptr->stdp2690_i2c) ++ return 0; ++ ++ return ge_b850v3_register(); ++} ++ + static int stdp4028_ge_b850v3_fw_remove(struct i2c_client *stdp4028_i2c) + { + ge_b850v3_lvds_remove(); +@@ -386,7 +398,11 @@ static int stdp2690_ge_b850v3_fw_probe(struct i2c_client *stdp2690_i2c, + ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c; + i2c_set_clientdata(stdp2690_i2c, ge_b850v3_lvds_ptr); + +- return 0; ++ /* Only register after both bridges are probed */ ++ if (!ge_b850v3_lvds_ptr->stdp4028_i2c) ++ return 0; ++ ++ return ge_b850v3_register(); + } + + static int stdp2690_ge_b850v3_fw_remove(struct i2c_client *stdp2690_i2c) +diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c +index ed8ac5059cd26..af07eeb47ca02 100644 +--- a/drivers/gpu/drm/bridge/nwl-dsi.c ++++ b/drivers/gpu/drm/bridge/nwl-dsi.c +@@ -7,6 +7,7 @@ + */ + + #include <linux/bitfield.h> ++#include <linux/bits.h> + #include <linux/clk.h> + #include <linux/irq.h> + #include <linux/math64.h> +@@ -196,12 +197,9 @@ static u32 ps2bc(struct nwl_dsi *dsi, unsigned long long ps) + /* + * ui2bc - UI time periods to byte clock cycles + */ +-static u32 ui2bc(struct nwl_dsi *dsi, unsigned long long ui) ++static u32 ui2bc(unsigned int ui) + { +- u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); +- +- return DIV64_U64_ROUND_UP(ui * dsi->lanes, +- dsi->mode.clock * 1000 * bpp); ++ return DIV_ROUND_UP(ui, BITS_PER_BYTE); + } + + /* +@@ -232,12 +230,12 @@ static int nwl_dsi_config_host(struct nwl_dsi *dsi) + } + + /* values in byte clock cycles */ +- cycles = ui2bc(dsi, cfg->clk_pre); ++ cycles = ui2bc(cfg->clk_pre); + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_t_pre: 0x%x\n", cycles); + nwl_dsi_write(dsi, NWL_DSI_CFG_T_PRE, cycles); + cycles = ps2bc(dsi, cfg->lpx + cfg->clk_prepare + cfg->clk_zero); + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_tx_gap (pre): 0x%x\n", cycles); +- cycles += ui2bc(dsi, cfg->clk_pre); ++ cycles += ui2bc(cfg->clk_pre); + DRM_DEV_DEBUG_DRIVER(dsi->dev, "cfg_t_post: 0x%x\n", cycles); + nwl_dsi_write(dsi, NWL_DSI_CFG_T_POST, cycles); + cycles = ps2bc(dsi, cfg->hs_exit); +@@ -939,6 +937,40 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge) + drm_of_panel_bridge_remove(dsi->dev->of_node, 1, 0); + } + ++static u32 *nwl_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, ++ struct drm_bridge_state *bridge_state, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state, ++ u32 output_fmt, ++ unsigned int *num_input_fmts) ++{ ++ u32 *input_fmts, input_fmt; ++ ++ *num_input_fmts = 0; ++ ++ switch (output_fmt) { ++ /* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */ ++ case MEDIA_BUS_FMT_FIXED: ++ input_fmt = MEDIA_BUS_FMT_RGB888_1X24; ++ break; ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_RGB666_1X18: ++ case MEDIA_BUS_FMT_RGB565_1X16: ++ input_fmt = output_fmt; ++ break; ++ default: ++ return NULL; ++ } ++ ++ input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL); ++ if (!input_fmts) ++ return NULL; ++ input_fmts[0] = input_fmt; ++ *num_input_fmts = 1; ++ ++ return input_fmts; ++} ++ + static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, +@@ -946,6 +978,7 @@ static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { + .atomic_check = nwl_dsi_bridge_atomic_check, + .atomic_enable = nwl_dsi_bridge_atomic_enable, + .atomic_disable = nwl_dsi_bridge_atomic_disable, ++ .atomic_get_input_bus_fmts = nwl_bridge_atomic_get_input_bus_fmts, + .mode_set = nwl_dsi_bridge_mode_set, + .mode_valid = nwl_dsi_bridge_mode_valid, + .attach = nwl_dsi_bridge_attach, +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c +index d0db1acf11d73..7d2ed0ed2fe26 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c +@@ -320,13 +320,17 @@ static int dw_hdmi_open(struct snd_pcm_substream *substream) + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dw_hdmi *dw = substream->private_data; + void __iomem *base = dw->data.base; ++ u8 *eld; + int ret; + + runtime->hw = dw_hdmi_hw; + +- ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld); +- if (ret < 0) +- return ret; ++ eld = dw->data.get_eld(dw->data.hdmi); ++ if (eld) { ++ ret = snd_pcm_hw_constraint_eld(runtime, eld); ++ if (ret < 0) ++ return ret; ++ } + + ret = snd_pcm_limit_hw_rates(runtime); + if (ret < 0) +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +index cb07dc0da5a70..f72d27208ebef 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +@@ -9,15 +9,15 @@ struct dw_hdmi_audio_data { + void __iomem *base; + int irq; + struct dw_hdmi *hdmi; +- u8 *eld; ++ u8 *(*get_eld)(struct dw_hdmi *hdmi); + }; + + struct dw_hdmi_i2s_audio_data { + struct dw_hdmi *hdmi; +- u8 *eld; + + void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); + u8 (*read)(struct dw_hdmi *hdmi, int offset); ++ u8 *(*get_eld)(struct dw_hdmi *hdmi); + }; + + #endif +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +index feb04f127b550..f50b47ac11a82 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +@@ -135,8 +135,15 @@ static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, uint8_t *buf, + size_t len) + { + struct dw_hdmi_i2s_audio_data *audio = data; ++ u8 *eld; ++ ++ eld = audio->get_eld(audio->hdmi); ++ if (eld) ++ memcpy(buf, eld, min_t(size_t, MAX_ELD_BYTES, len)); ++ else ++ /* Pass en empty ELD if connector not available */ ++ memset(buf, 0, len); + +- memcpy(buf, audio->eld, min_t(size_t, MAX_ELD_BYTES, len)); + return 0; + } + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index f08d0fded61f7..e1211a5b334ba 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -757,6 +757,14 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) + hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); + } + ++static u8 *hdmi_audio_get_eld(struct dw_hdmi *hdmi) ++{ ++ if (!hdmi->curr_conn) ++ return NULL; ++ ++ return hdmi->curr_conn->eld; ++} ++ + static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi) + { + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); +@@ -3431,7 +3439,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + audio.base = hdmi->regs; + audio.irq = irq; + audio.hdmi = hdmi; +- audio.eld = hdmi->connector.eld; ++ audio.get_eld = hdmi_audio_get_eld; + hdmi->enable_audio = dw_hdmi_ahb_audio_enable; + hdmi->disable_audio = dw_hdmi_ahb_audio_disable; + +@@ -3444,7 +3452,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, + struct dw_hdmi_i2s_audio_data audio; + + audio.hdmi = hdmi; +- audio.eld = hdmi->connector.eld; ++ audio.get_eld = hdmi_audio_get_eld; + audio.write = hdmi_writeb; + audio.read = hdmi_readb; + hdmi->enable_audio = dw_hdmi_i2s_audio_enable; +diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +index 41d48a393e7f5..45a5f1e48f0ef 100644 +--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c ++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c +@@ -188,6 +188,7 @@ static const struct regmap_config ti_sn65dsi86_regmap_config = { + .val_bits = 8, + .volatile_table = &ti_sn_bridge_volatile_table, + .cache_type = REGCACHE_NONE, ++ .max_register = 0xFF, + }; + + static void ti_sn65dsi86_write_u16(struct ti_sn65dsi86 *pdata, +@@ -1472,6 +1473,7 @@ static inline void ti_sn_gpio_unregister(void) {} + + static void ti_sn65dsi86_runtime_disable(void *data) + { ++ pm_runtime_dont_use_autosuspend(data); + pm_runtime_disable(data); + } + +@@ -1531,11 +1533,11 @@ static int ti_sn65dsi86_probe(struct i2c_client *client, + "failed to get reference clock\n"); + + pm_runtime_enable(dev); ++ pm_runtime_set_autosuspend_delay(pdata->dev, 500); ++ pm_runtime_use_autosuspend(pdata->dev); + ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev); + if (ret) + return ret; +- pm_runtime_set_autosuspend_delay(pdata->dev, 500); +- pm_runtime_use_autosuspend(pdata->dev); + + ti_sn65dsi86_debugfs_init(pdata); + +diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c +index ff1416cd609a5..a1e4c7905ebbe 100644 +--- a/drivers/gpu/drm/drm_atomic.c ++++ b/drivers/gpu/drm/drm_atomic.c +@@ -1310,8 +1310,10 @@ int drm_atomic_check_only(struct drm_atomic_state *state) + + DRM_DEBUG_ATOMIC("checking %p\n", state); + +- for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) +- requested_crtc |= drm_crtc_mask(crtc); ++ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { ++ if (new_crtc_state->enable) ++ requested_crtc |= drm_crtc_mask(crtc); ++ } + + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { + ret = drm_atomic_plane_check(old_plane_state, new_plane_state); +@@ -1360,8 +1362,10 @@ int drm_atomic_check_only(struct drm_atomic_state *state) + } + } + +- for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) +- affected_crtc |= drm_crtc_mask(crtc); ++ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { ++ if (new_crtc_state->enable) ++ affected_crtc |= drm_crtc_mask(crtc); ++ } + + /* + * For commits that allow modesets drivers can add other CRTCs to the +diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c +index 2c0c6ec928200..ff2bc9a118011 100644 +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -1001,7 +1001,7 @@ crtc_needs_disable(struct drm_crtc_state *old_state, + * it's in self refresh mode and needs to be fully disabled. + */ + return old_state->active || +- (old_state->self_refresh_active && !new_state->enable) || ++ (old_state->self_refresh_active && !new_state->active) || + new_state->self_refresh_active; + } + +diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c +index 909f318331816..f195c70131373 100644 +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -76,15 +76,17 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, + state->mode_blob = NULL; + + if (mode) { ++ struct drm_property_blob *blob; ++ + drm_mode_convert_to_umode(&umode, mode); +- state->mode_blob = +- drm_property_create_blob(state->crtc->dev, +- sizeof(umode), +- &umode); +- if (IS_ERR(state->mode_blob)) +- return PTR_ERR(state->mode_blob); ++ blob = drm_property_create_blob(crtc->dev, ++ sizeof(umode), &umode); ++ if (IS_ERR(blob)) ++ return PTR_ERR(blob); + + drm_mode_copy(&state->mode, mode); ++ ++ state->mode_blob = blob; + state->enable = true; + drm_dbg_atomic(crtc->dev, + "Set [MODE:%s] for [CRTC:%d:%s] state %p\n", +diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c +index 6d0f2c447f3b9..7bb24523a7493 100644 +--- a/drivers/gpu/drm/drm_dp_helper.c ++++ b/drivers/gpu/drm/drm_dp_helper.c +@@ -3214,27 +3214,13 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli + const u16 level) + { + int ret; +- u8 dpcd_buf, new_dpcd_buf; ++ u8 dpcd_buf = DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; + +- ret = drm_dp_dpcd_readb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf); +- if (ret != 1) { +- drm_dbg_kms(aux->drm_dev, +- "%s: Failed to read backlight mode: %d\n", aux->name, ret); +- return ret < 0 ? ret : -EIO; +- } +- +- new_dpcd_buf = dpcd_buf; +- +- if ((dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) != DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { +- new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; +- new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; +- +- if (bl->pwmgen_bit_count) { +- ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); +- if (ret != 1) +- drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n", +- aux->name, ret); +- } ++ if (bl->pwmgen_bit_count) { ++ ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); ++ if (ret != 1) ++ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n", ++ aux->name, ret); + } + + if (bl->pwm_freq_pre_divider) { +@@ -3244,16 +3230,14 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli + "%s: Failed to write aux backlight frequency: %d\n", + aux->name, ret); + else +- new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; ++ dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; + } + +- if (new_dpcd_buf != dpcd_buf) { +- ret = drm_dp_dpcd_writeb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf); +- if (ret != 1) { +- drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux backlight mode: %d\n", +- aux->name, ret); +- return ret < 0 ? ret : -EIO; +- } ++ ret = drm_dp_dpcd_writeb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, dpcd_buf); ++ if (ret != 1) { ++ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux backlight mode: %d\n", ++ aux->name, ret); ++ return ret < 0 ? ret : -EIO; + } + + ret = drm_edp_backlight_set_level(aux, bl, level); +diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c +index 7a5097467ba5c..b3a1636d1b984 100644 +--- a/drivers/gpu/drm/drm_drv.c ++++ b/drivers/gpu/drm/drm_drv.c +@@ -581,6 +581,7 @@ static int drm_dev_init(struct drm_device *dev, + const struct drm_driver *driver, + struct device *parent) + { ++ struct inode *inode; + int ret; + + if (!drm_core_init_complete) { +@@ -617,13 +618,15 @@ static int drm_dev_init(struct drm_device *dev, + if (ret) + return ret; + +- dev->anon_inode = drm_fs_inode_new(); +- if (IS_ERR(dev->anon_inode)) { +- ret = PTR_ERR(dev->anon_inode); ++ inode = drm_fs_inode_new(); ++ if (IS_ERR(inode)) { ++ ret = PTR_ERR(inode); + DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret); + goto err; + } + ++ dev->anon_inode = inode; ++ + if (drm_core_check_feature(dev, DRIVER_RENDER)) { + ret = drm_minor_alloc(dev, DRM_MINOR_RENDER); + if (ret) +diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c +index ea9a79bc95839..6ad4361a5cbc7 100644 +--- a/drivers/gpu/drm/drm_edid.c ++++ b/drivers/gpu/drm/drm_edid.c +@@ -5205,6 +5205,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi + if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) + return quirks; + ++ info->color_formats |= DRM_COLOR_FORMAT_RGB444; + drm_parse_cea_ext(connector, edid); + + /* +@@ -5253,7 +5254,6 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi + DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n", + connector->name, info->bpc); + +- info->color_formats |= DRM_COLOR_FORMAT_RGB444; + if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) + info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; + if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) +diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c +index 8e7a124d6c5a3..22bf690910b25 100644 +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -1743,7 +1743,13 @@ void drm_fb_helper_fill_info(struct fb_info *info, + sizes->fb_width, sizes->fb_height); + + info->par = fb_helper; +- snprintf(info->fix.id, sizeof(info->fix.id), "%s", ++ /* ++ * The DRM drivers fbdev emulation device name can be confusing if the ++ * driver name also has a "drm" suffix on it. Leading to names such as ++ * "simpledrmdrmfb" in /proc/fb. Unfortunately, it's an uAPI and can't ++ * be changed due user-space tools (e.g: pm-utils) matching against it. ++ */ ++ snprintf(info->fix.id, sizeof(info->fix.id), "%sdrmfb", + fb_helper->dev->driver->name); + + } +diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c +index d53388199f34c..6533efa840204 100644 +--- a/drivers/gpu/drm/drm_gem_cma_helper.c ++++ b/drivers/gpu/drm/drm_gem_cma_helper.c +@@ -210,8 +210,13 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) + dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map); + drm_prime_gem_destroy(gem_obj, cma_obj->sgt); + } else if (cma_obj->vaddr) { +- dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, +- cma_obj->vaddr, cma_obj->paddr); ++ if (cma_obj->map_noncoherent) ++ dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size, ++ cma_obj->vaddr, cma_obj->paddr, ++ DMA_TO_DEVICE); ++ else ++ dma_free_wc(gem_obj->dev->dev, cma_obj->base.size, ++ cma_obj->vaddr, cma_obj->paddr); + } + + drm_gem_object_release(gem_obj); +@@ -510,6 +515,7 @@ int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) + */ + vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node); + vma->vm_flags &= ~VM_PFNMAP; ++ vma->vm_flags |= VM_DONTEXPAND; + + cma_obj = to_drm_gem_cma_obj(obj); + +diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c +index e1b2ce4921ae7..448c2f2d803a6 100644 +--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c ++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c +@@ -109,6 +109,18 @@ static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { + .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, + }; + ++static const struct drm_dmi_panel_orientation_data lcd1280x1920_rightside_up = { ++ .width = 1280, ++ .height = 1920, ++ .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, ++}; ++ ++static const struct drm_dmi_panel_orientation_data lcd1600x2560_leftside_up = { ++ .width = 1600, ++ .height = 2560, ++ .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, ++}; ++ + static const struct dmi_system_id orientation_data[] = { + { /* Acer One 10 (S1003) */ + .matches = { +@@ -205,6 +217,13 @@ static const struct dmi_system_id orientation_data[] = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"), + }, + .driver_data = (void *)&itworks_tw891, ++ }, { /* KD Kurio Smart C15200 2-in-1 */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "KD Interactive"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Kurio Smart"), ++ DMI_EXACT_MATCH(DMI_BOARD_NAME, "KDM960BCP"), ++ }, ++ .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* + * Lenovo Ideapad Miix 310 laptop, only some production batches + * have a portrait screen, the resolution checks makes the quirk +@@ -223,12 +242,23 @@ static const struct dmi_system_id orientation_data[] = { + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, +- }, { /* Lenovo Ideapad D330 */ ++ }, { /* Lenovo Ideapad D330-10IGM (HD) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), +- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81H3"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"), + }, ++ .driver_data = (void *)&lcd800x1280_rightside_up, ++ }, { /* Lenovo Ideapad D330-10IGM (FHD) */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"), ++ }, ++ .driver_data = (void *)&lcd1200x1920_rightside_up, ++ }, { /* Lenovo Yoga Book X90F / X91F / X91L */ ++ .matches = { ++ /* Non exact match to match all versions */ ++ DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"), ++ }, + .driver_data = (void *)&lcd1200x1920_rightside_up, + }, { /* OneGX1 Pro */ + .matches = { +@@ -237,6 +267,25 @@ static const struct dmi_system_id orientation_data[] = { + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"), + }, + .driver_data = (void *)&onegx1_pro, ++ }, { /* OneXPlayer */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"), ++ }, ++ .driver_data = (void *)&lcd1600x2560_leftside_up, ++ }, { /* Samsung GalaxyBook 10.6 */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"), ++ }, ++ .driver_data = (void *)&lcd1280x1920_rightside_up, ++ }, { /* Valve Steam Deck */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"), ++ }, ++ .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* VIOS LTH17 */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"), +diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c +index 5b2d0ca03705c..838b32b70bce6 100644 +--- a/drivers/gpu/drm/drm_plane_helper.c ++++ b/drivers/gpu/drm/drm_plane_helper.c +@@ -123,7 +123,6 @@ static int drm_plane_helper_check_update(struct drm_plane *plane, + .crtc_w = drm_rect_width(dst), + .crtc_h = drm_rect_height(dst), + .rotation = rotation, +- .visible = *visible, + }; + struct drm_crtc_state crtc_state = { + .crtc = crtc, +diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c +index deb23dbec8b52..d6c7f4f9a7a29 100644 +--- a/drivers/gpu/drm/drm_prime.c ++++ b/drivers/gpu/drm/drm_prime.c +@@ -719,11 +719,13 @@ int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) + if (obj->funcs && obj->funcs->mmap) { + vma->vm_ops = obj->funcs->vm_ops; + ++ drm_gem_object_get(obj); + ret = obj->funcs->mmap(obj, vma); +- if (ret) ++ if (ret) { ++ drm_gem_object_put(obj); + return ret; ++ } + vma->vm_private_data = obj; +- drm_gem_object_get(obj); + return 0; + } + +diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c +index c9a9d74f338c1..c313a5b4549c4 100644 +--- a/drivers/gpu/drm/drm_syncobj.c ++++ b/drivers/gpu/drm/drm_syncobj.c +@@ -404,8 +404,17 @@ int drm_syncobj_find_fence(struct drm_file *file_private, + + if (*fence) { + ret = dma_fence_chain_find_seqno(fence, point); +- if (!ret) ++ if (!ret) { ++ /* If the requested seqno is already signaled ++ * drm_syncobj_find_fence may return a NULL ++ * fence. To make sure the recipient gets ++ * signalled, use a new fence instead. ++ */ ++ if (!*fence) ++ *fence = dma_fence_get_stub(); ++ + goto out; ++ } + dma_fence_put(*fence); + } else { + ret = -EINVAL; +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +index 486259e154aff..90488ab8c6d8e 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +@@ -469,6 +469,12 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, + return -EINVAL; + } + ++ if (args->stream_size > SZ_128K || args->nr_relocs > SZ_128K || ++ args->nr_bos > SZ_128K || args->nr_pmrs > 128) { ++ DRM_ERROR("submit arguments out of size limits\n"); ++ return -EINVAL; ++ } ++ + /* + * Copy the command submission and bo array to kernel space in + * one go, and do this outside of any locks. +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +index 1c75c8ed5bcea..85eddd492774d 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +@@ -130,6 +130,7 @@ struct etnaviv_gpu { + + /* hang detection */ + u32 hangcheck_dma_addr; ++ u32 hangcheck_fence; + + void __iomem *mmio; + int irq; +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c +index feb6da1b6cebc..bbf391f48f949 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c +@@ -107,8 +107,10 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job + */ + dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS); + change = dma_addr - gpu->hangcheck_dma_addr; +- if (change < 0 || change > 16) { ++ if (gpu->completed_fence != gpu->hangcheck_fence || ++ change < 0 || change > 16) { + gpu->hangcheck_dma_addr = dma_addr; ++ gpu->hangcheck_fence = gpu->completed_fence; + goto out_no_timeout; + } + +diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c +index cd818a6291835..00e53de4812bb 100644 +--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c ++++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c +@@ -225,12 +225,29 @@ static int hyperv_vmbus_remove(struct hv_device *hdev) + { + struct drm_device *dev = hv_get_drvdata(hdev); + struct hyperv_drm_device *hv = to_hv(dev); ++ struct pci_dev *pdev; + + drm_dev_unplug(dev); + drm_atomic_helper_shutdown(dev); + vmbus_close(hdev->channel); + hv_set_drvdata(hdev, NULL); +- vmbus_free_mmio(hv->mem->start, hv->fb_size); ++ ++ /* ++ * Free allocated MMIO memory only on Gen2 VMs. ++ * On Gen1 VMs, release the PCI device ++ */ ++ if (efi_enabled(EFI_BOOT)) { ++ vmbus_free_mmio(hv->mem->start, hv->fb_size); ++ } else { ++ pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT, ++ PCI_DEVICE_ID_HYPERV_VIDEO, NULL); ++ if (!pdev) { ++ drm_err(dev, "Unable to find PCI Hyper-V video\n"); ++ return -ENODEV; ++ } ++ pci_release_region(pdev, 0); ++ pci_dev_put(pdev); ++ } + + return 0; + } +diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig +index f960f5d7664e6..fe6b34774483f 100644 +--- a/drivers/gpu/drm/i915/Kconfig ++++ b/drivers/gpu/drm/i915/Kconfig +@@ -101,6 +101,7 @@ config DRM_I915_USERPTR + config DRM_I915_GVT + bool "Enable Intel GVT-g graphics virtualization host support" + depends on DRM_I915 ++ depends on X86 + depends on 64BIT + default n + help +diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile +index 335ba9f43d8f7..26cf754229451 100644 +--- a/drivers/gpu/drm/i915/Makefile ++++ b/drivers/gpu/drm/i915/Makefile +@@ -211,6 +211,8 @@ i915-y += \ + display/intel_dpio_phy.o \ + display/intel_dpll.o \ + display/intel_dpll_mgr.o \ ++ display/intel_dpt.o \ ++ display/intel_drrs.o \ + display/intel_dsb.o \ + display/intel_fb.o \ + display/intel_fbc.o \ +diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c +index be352e9f0afc1..63baaf6988ade 100644 +--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c ++++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c +@@ -584,6 +584,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv, + else + intel_encoder->enable = g4x_enable_hdmi; + } ++ intel_encoder->shutdown = intel_hdmi_encoder_shutdown; + + intel_encoder->type = INTEL_OUTPUT_HDMI; + intel_encoder->power_domain = intel_port_to_power_domain(port); +diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c +index a3eae3f3eadce..638a00b2dc2d2 100644 +--- a/drivers/gpu/drm/i915/display/icl_dsi.c ++++ b/drivers/gpu/drm/i915/display/icl_dsi.c +@@ -711,10 +711,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder, + intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); + + for_each_dsi_phy(phy, intel_dsi->phys) { +- if (DISPLAY_VER(dev_priv) >= 12) +- val |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); +- else +- val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); ++ val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + } + intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); + +@@ -1150,8 +1147,6 @@ static void + gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) + { +- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); +- + /* step 4a: power up all lanes of the DDI used by DSI */ + gen11_dsi_power_up_lanes(encoder); + +@@ -1177,8 +1172,7 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, + gen11_dsi_configure_transcoder(encoder, crtc_state); + + /* Step 4l: Gate DDI clocks */ +- if (DISPLAY_VER(dev_priv) == 11) +- gen11_dsi_gate_clocks(encoder); ++ gen11_dsi_gate_clocks(encoder); + } + + static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) +diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c +index fd71346aac7bc..32d5a556b7eac 100644 +--- a/drivers/gpu/drm/i915/display/intel_bios.c ++++ b/drivers/gpu/drm/i915/display/intel_bios.c +@@ -1692,6 +1692,39 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin) + return 0; + } + ++static u8 dvo_port_type(u8 dvo_port) ++{ ++ switch (dvo_port) { ++ case DVO_PORT_HDMIA: ++ case DVO_PORT_HDMIB: ++ case DVO_PORT_HDMIC: ++ case DVO_PORT_HDMID: ++ case DVO_PORT_HDMIE: ++ case DVO_PORT_HDMIF: ++ case DVO_PORT_HDMIG: ++ case DVO_PORT_HDMIH: ++ case DVO_PORT_HDMII: ++ return DVO_PORT_HDMIA; ++ case DVO_PORT_DPA: ++ case DVO_PORT_DPB: ++ case DVO_PORT_DPC: ++ case DVO_PORT_DPD: ++ case DVO_PORT_DPE: ++ case DVO_PORT_DPF: ++ case DVO_PORT_DPG: ++ case DVO_PORT_DPH: ++ case DVO_PORT_DPI: ++ return DVO_PORT_DPA; ++ case DVO_PORT_MIPIA: ++ case DVO_PORT_MIPIB: ++ case DVO_PORT_MIPIC: ++ case DVO_PORT_MIPID: ++ return DVO_PORT_MIPIA; ++ default: ++ return dvo_port; ++ } ++} ++ + static enum port __dvo_port_to_port(int n_ports, int n_dvo, + const int port_mapping[][3], u8 dvo_port) + { +@@ -2622,35 +2655,17 @@ bool intel_bios_is_port_edp(struct drm_i915_private *i915, enum port port) + return false; + } + +-static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, +- enum port port) ++static bool child_dev_is_dp_dual_mode(const struct child_device_config *child) + { +- static const struct { +- u16 dp, hdmi; +- } port_mapping[] = { +- /* +- * Buggy VBTs may declare DP ports as having +- * HDMI type dvo_port :( So let's check both. +- */ +- [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, }, +- [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, }, +- [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, +- [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, +- [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, +- }; +- +- if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) +- return false; +- + if ((child->device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) != + (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS)) + return false; + +- if (child->dvo_port == port_mapping[port].dp) ++ if (dvo_port_type(child->dvo_port) == DVO_PORT_DPA) + return true; + + /* Only accept a HDMI dvo_port as DP++ if it has an AUX channel */ +- if (child->dvo_port == port_mapping[port].hdmi && ++ if (dvo_port_type(child->dvo_port) == DVO_PORT_HDMIA && + child->aux_channel != 0) + return true; + +@@ -2660,10 +2675,36 @@ static bool child_dev_is_dp_dual_mode(const struct child_device_config *child, + bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *i915, + enum port port) + { ++ static const struct { ++ u16 dp, hdmi; ++ } port_mapping[] = { ++ /* ++ * Buggy VBTs may declare DP ports as having ++ * HDMI type dvo_port :( So let's check both. ++ */ ++ [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, }, ++ [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, }, ++ [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, }, ++ [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, }, ++ [PORT_F] = { DVO_PORT_DPF, DVO_PORT_HDMIF, }, ++ }; + const struct intel_bios_encoder_data *devdata; + ++ if (HAS_DDI(i915)) { ++ const struct intel_bios_encoder_data *devdata; ++ ++ devdata = intel_bios_encoder_data_lookup(i915, port); ++ ++ return devdata && child_dev_is_dp_dual_mode(&devdata->child); ++ } ++ ++ if (port == PORT_A || port >= ARRAY_SIZE(port_mapping)) ++ return false; ++ + list_for_each_entry(devdata, &i915->vbt.display_devices, node) { +- if (child_dev_is_dp_dual_mode(&devdata->child, port)) ++ if ((devdata->child.dvo_port == port_mapping[port].dp || ++ devdata->child.dvo_port == port_mapping[port].hdmi) && ++ child_dev_is_dp_dual_mode(&devdata->child)) + return true; + } + +diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c +index 4b94256d73197..7144c76ac9701 100644 +--- a/drivers/gpu/drm/i915/display/intel_bw.c ++++ b/drivers/gpu/drm/i915/display/intel_bw.c +@@ -681,6 +681,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) + unsigned int max_bw_point = 0, max_bw = 0; + unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points; + unsigned int num_psf_gv_points = dev_priv->max_bw[0].num_psf_gv_points; ++ bool changed = false; + u32 mask = 0; + + /* FIXME earlier gens need some checks too */ +@@ -724,6 +725,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) + new_bw_state->data_rate[crtc->pipe] = new_data_rate; + new_bw_state->num_active_planes[crtc->pipe] = new_active_planes; + ++ changed = true; ++ + drm_dbg_kms(&dev_priv->drm, + "pipe %c data rate %u num active planes %u\n", + pipe_name(crtc->pipe), +@@ -731,7 +734,19 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) + new_bw_state->num_active_planes[crtc->pipe]); + } + +- if (!new_bw_state) ++ old_bw_state = intel_atomic_get_old_bw_state(state); ++ new_bw_state = intel_atomic_get_new_bw_state(state); ++ ++ if (new_bw_state && ++ intel_can_enable_sagv(dev_priv, old_bw_state) != ++ intel_can_enable_sagv(dev_priv, new_bw_state)) ++ changed = true; ++ ++ /* ++ * If none of our inputs (data rates, number of active ++ * planes, SAGV yes/no) changed then nothing to do here. ++ */ ++ if (!changed) + return 0; + + ret = intel_atomic_lock_global_state(&new_bw_state->base); +@@ -814,7 +829,6 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) + */ + new_bw_state->qgv_points_mask = ~allowed_points & mask; + +- old_bw_state = intel_atomic_get_old_bw_state(state); + /* + * If the actual mask had changed we need to make sure that + * the commits are serialized(in case this is a nomodeset, nonblocking) +diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h +index 46c6eecbd9175..0ceaed1c96562 100644 +--- a/drivers/gpu/drm/i915/display/intel_bw.h ++++ b/drivers/gpu/drm/i915/display/intel_bw.h +@@ -30,19 +30,19 @@ struct intel_bw_state { + */ + u8 pipe_sagv_reject; + ++ /* bitmask of active pipes */ ++ u8 active_pipes; ++ + /* + * Current QGV points mask, which restricts + * some particular SAGV states, not to confuse + * with pipe_sagv_mask. + */ +- u8 qgv_points_mask; ++ u16 qgv_points_mask; + + unsigned int data_rate[I915_MAX_PIPES]; + u8 num_active_planes[I915_MAX_PIPES]; + +- /* bitmask of active pipes */ +- u8 active_pipes; +- + int min_cdclk; + }; + +diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c +index bd184325d0c75..f61901e26409e 100644 +--- a/drivers/gpu/drm/i915/display/intel_ddi.c ++++ b/drivers/gpu/drm/i915/display/intel_ddi.c +@@ -40,6 +40,7 @@ + #include "intel_dp_link_training.h" + #include "intel_dp_mst.h" + #include "intel_dpio_phy.h" ++#include "intel_drrs.h" + #include "intel_dsi.h" + #include "intel_fdi.h" + #include "intel_fifo_underrun.h" +@@ -4432,6 +4433,7 @@ static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) + enum phy phy = intel_port_to_phy(i915, encoder->port); + + intel_dp_encoder_shutdown(encoder); ++ intel_hdmi_encoder_shutdown(encoder); + + if (!intel_phy_is_tc(i915, phy)) + return; +diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +index ba2c08f1a797c..876620455ed31 100644 +--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c ++++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +@@ -476,14 +476,14 @@ static const struct intel_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi = { + static const union intel_ddi_buf_trans_entry _ehl_combo_phy_ddi_translations_dp[] = { + /* NT mV Trans mV db */ + { .icl = { 0xA, 0x33, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */ +- { .icl = { 0xA, 0x47, 0x36, 0x00, 0x09 } }, /* 350 500 3.1 */ +- { .icl = { 0xC, 0x64, 0x34, 0x00, 0x0B } }, /* 350 700 6.0 */ +- { .icl = { 0x6, 0x7F, 0x30, 0x00, 0x0F } }, /* 350 900 8.2 */ ++ { .icl = { 0xA, 0x47, 0x38, 0x00, 0x07 } }, /* 350 500 3.1 */ ++ { .icl = { 0xC, 0x64, 0x33, 0x00, 0x0C } }, /* 350 700 6.0 */ ++ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 350 900 8.2 */ + { .icl = { 0xA, 0x46, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */ +- { .icl = { 0xC, 0x64, 0x38, 0x00, 0x07 } }, /* 500 700 2.9 */ ++ { .icl = { 0xC, 0x64, 0x37, 0x00, 0x08 } }, /* 500 700 2.9 */ + { .icl = { 0x6, 0x7F, 0x32, 0x00, 0x0D } }, /* 500 900 5.1 */ + { .icl = { 0xC, 0x61, 0x3F, 0x00, 0x00 } }, /* 650 700 0.6 */ +- { .icl = { 0x6, 0x7F, 0x38, 0x00, 0x07 } }, /* 600 900 3.5 */ ++ { .icl = { 0x6, 0x7F, 0x37, 0x00, 0x08 } }, /* 600 900 3.5 */ + { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */ + }; + +diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c +index 17f44ffea5866..625ce6975eeba 100644 +--- a/drivers/gpu/drm/i915/display/intel_display.c ++++ b/drivers/gpu/drm/i915/display/intel_display.c +@@ -84,6 +84,7 @@ + #include "intel_display_types.h" + #include "intel_dmc.h" + #include "intel_dp_link_training.h" ++#include "intel_dpt.h" + #include "intel_fbc.h" + #include "intel_fdi.h" + #include "intel_fbdev.h" +@@ -126,182 +127,6 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state); + static void intel_modeset_setup_hw_state(struct drm_device *dev, + struct drm_modeset_acquire_ctx *ctx); + +-struct i915_dpt { +- struct i915_address_space vm; +- +- struct drm_i915_gem_object *obj; +- struct i915_vma *vma; +- void __iomem *iomem; +-}; +- +-#define i915_is_dpt(vm) ((vm)->is_dpt) +- +-static inline struct i915_dpt * +-i915_vm_to_dpt(struct i915_address_space *vm) +-{ +- BUILD_BUG_ON(offsetof(struct i915_dpt, vm)); +- GEM_BUG_ON(!i915_is_dpt(vm)); +- return container_of(vm, struct i915_dpt, vm); +-} +- +-#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT) +- +-static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) +-{ +- writeq(pte, addr); +-} +- +-static void dpt_insert_page(struct i915_address_space *vm, +- dma_addr_t addr, +- u64 offset, +- enum i915_cache_level level, +- u32 flags) +-{ +- struct i915_dpt *dpt = i915_vm_to_dpt(vm); +- gen8_pte_t __iomem *base = dpt->iomem; +- +- gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE, +- vm->pte_encode(addr, level, flags)); +-} +- +-static void dpt_insert_entries(struct i915_address_space *vm, +- struct i915_vma *vma, +- enum i915_cache_level level, +- u32 flags) +-{ +- struct i915_dpt *dpt = i915_vm_to_dpt(vm); +- gen8_pte_t __iomem *base = dpt->iomem; +- const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags); +- struct sgt_iter sgt_iter; +- dma_addr_t addr; +- int i; +- +- /* +- * Note that we ignore PTE_READ_ONLY here. The caller must be careful +- * not to allow the user to override access to a read only page. +- */ +- +- i = vma->node.start / I915_GTT_PAGE_SIZE; +- for_each_sgt_daddr(addr, sgt_iter, vma->pages) +- gen8_set_pte(&base[i++], pte_encode | addr); +-} +- +-static void dpt_clear_range(struct i915_address_space *vm, +- u64 start, u64 length) +-{ +-} +- +-static void dpt_bind_vma(struct i915_address_space *vm, +- struct i915_vm_pt_stash *stash, +- struct i915_vma *vma, +- enum i915_cache_level cache_level, +- u32 flags) +-{ +- struct drm_i915_gem_object *obj = vma->obj; +- u32 pte_flags; +- +- /* Applicable to VLV (gen8+ do not support RO in the GGTT) */ +- pte_flags = 0; +- if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj)) +- pte_flags |= PTE_READ_ONLY; +- if (i915_gem_object_is_lmem(obj)) +- pte_flags |= PTE_LM; +- +- vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); +- +- vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; +- +- /* +- * Without aliasing PPGTT there's no difference between +- * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally +- * upgrade to both bound if we bind either to avoid double-binding. +- */ +- atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags); +-} +- +-static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) +-{ +- vm->clear_range(vm, vma->node.start, vma->size); +-} +- +-static void dpt_cleanup(struct i915_address_space *vm) +-{ +- struct i915_dpt *dpt = i915_vm_to_dpt(vm); +- +- i915_gem_object_put(dpt->obj); +-} +- +-static struct i915_address_space * +-intel_dpt_create(struct intel_framebuffer *fb) +-{ +- struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base; +- struct drm_i915_private *i915 = to_i915(obj->dev); +- struct drm_i915_gem_object *dpt_obj; +- struct i915_address_space *vm; +- struct i915_dpt *dpt; +- size_t size; +- int ret; +- +- if (intel_fb_needs_pot_stride_remap(fb)) +- size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped); +- else +- size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE); +- +- size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE); +- +- if (HAS_LMEM(i915)) +- dpt_obj = i915_gem_object_create_lmem(i915, size, 0); +- else +- dpt_obj = i915_gem_object_create_stolen(i915, size); +- if (IS_ERR(dpt_obj)) +- return ERR_CAST(dpt_obj); +- +- ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE); +- if (ret) { +- i915_gem_object_put(dpt_obj); +- return ERR_PTR(ret); +- } +- +- dpt = kzalloc(sizeof(*dpt), GFP_KERNEL); +- if (!dpt) { +- i915_gem_object_put(dpt_obj); +- return ERR_PTR(-ENOMEM); +- } +- +- vm = &dpt->vm; +- +- vm->gt = &i915->gt; +- vm->i915 = i915; +- vm->dma = i915->drm.dev; +- vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE; +- vm->is_dpt = true; +- +- i915_address_space_init(vm, VM_CLASS_DPT); +- +- vm->insert_page = dpt_insert_page; +- vm->clear_range = dpt_clear_range; +- vm->insert_entries = dpt_insert_entries; +- vm->cleanup = dpt_cleanup; +- +- vm->vma_ops.bind_vma = dpt_bind_vma; +- vm->vma_ops.unbind_vma = dpt_unbind_vma; +- vm->vma_ops.set_pages = ggtt_set_pages; +- vm->vma_ops.clear_pages = clear_pages; +- +- vm->pte_encode = gen8_ggtt_pte_encode; +- +- dpt->obj = dpt_obj; +- +- return &dpt->vm; +-} +- +-static void intel_dpt_destroy(struct i915_address_space *vm) +-{ +- struct i915_dpt *dpt = i915_vm_to_dpt(vm); +- +- i915_vm_close(&dpt->vm); +-} +- + /* returns HPLL frequency in kHz */ + int vlv_get_hpll_vco(struct drm_i915_private *dev_priv) + { +@@ -1879,49 +1704,6 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc, + intel_wait_for_vblank(dev_priv, crtc->pipe); + } + +-static struct i915_vma *intel_dpt_pin(struct i915_address_space *vm) +-{ +- struct drm_i915_private *i915 = vm->i915; +- struct i915_dpt *dpt = i915_vm_to_dpt(vm); +- intel_wakeref_t wakeref; +- struct i915_vma *vma; +- void __iomem *iomem; +- +- wakeref = intel_runtime_pm_get(&i915->runtime_pm); +- atomic_inc(&i915->gpu_error.pending_fb_pin); +- +- vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096, +- HAS_LMEM(i915) ? 0 : PIN_MAPPABLE); +- if (IS_ERR(vma)) +- goto err; +- +- iomem = i915_vma_pin_iomap(vma); +- i915_vma_unpin(vma); +- if (IS_ERR(iomem)) { +- vma = iomem; +- goto err; +- } +- +- dpt->vma = vma; +- dpt->iomem = iomem; +- +- i915_vma_get(vma); +- +-err: +- atomic_dec(&i915->gpu_error.pending_fb_pin); +- intel_runtime_pm_put(&i915->runtime_pm, wakeref); +- +- return vma; +-} +- +-static void intel_dpt_unpin(struct i915_address_space *vm) +-{ +- struct i915_dpt *dpt = i915_vm_to_dpt(vm); +- +- i915_vma_unpin_iomap(dpt->vma); +- i915_vma_put(dpt->vma); +-} +- + static bool + intel_reuse_initial_plane_obj(struct drm_i915_private *i915, + const struct intel_initial_plane_config *plane_config, +diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c +index 8fdacb252bb19..b136a0fc0963b 100644 +--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c ++++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c +@@ -13,6 +13,7 @@ + #include "intel_display_types.h" + #include "intel_dmc.h" + #include "intel_dp.h" ++#include "intel_drrs.h" + #include "intel_fbc.h" + #include "intel_hdcp.h" + #include "intel_hdmi.h" +diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h +index 6beeeeba1bed2..b56850d964919 100644 +--- a/drivers/gpu/drm/i915/display/intel_display_types.h ++++ b/drivers/gpu/drm/i915/display/intel_display_types.h +@@ -1639,6 +1639,9 @@ struct intel_dp { + struct intel_dp_pcon_frl frl; + + struct intel_psr psr; ++ ++ /* When we last wrote the OUI for eDP */ ++ unsigned long last_oui_write; + }; + + enum lspcon_vendor { +diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c +index b3c8e1c450efb..73076737add75 100644 +--- a/drivers/gpu/drm/i915/display/intel_dmc.c ++++ b/drivers/gpu/drm/i915/display/intel_dmc.c +@@ -606,7 +606,7 @@ static void parse_dmc_fw(struct drm_i915_private *dev_priv, + continue; + + offset = readcount + dmc->dmc_info[id].dmc_offset * 4; +- if (fw->size - offset < 0) { ++ if (offset > fw->size) { + drm_err(&dev_priv->drm, "Reading beyond the fw_size\n"); + continue; + } +diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c +index 5cf152be44877..dbff4b6aa22bf 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp.c ++++ b/drivers/gpu/drm/i915/display/intel_dp.c +@@ -29,6 +29,7 @@ + #include <linux/i2c.h> + #include <linux/notifier.h> + #include <linux/slab.h> ++#include <linux/timekeeping.h> + #include <linux/types.h> + + #include <asm/byteorder.h> +@@ -55,6 +56,7 @@ + #include "intel_dp_mst.h" + #include "intel_dpio_phy.h" + #include "intel_dpll.h" ++#include "intel_drrs.h" + #include "intel_fifo_underrun.h" + #include "intel_hdcp.h" + #include "intel_hdmi.h" +@@ -111,6 +113,12 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) + static void intel_dp_unset_edid(struct intel_dp *intel_dp); + static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc); + ++static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp) ++{ ++ intel_dp->sink_rates[0] = 162000; ++ intel_dp->num_sink_rates = 1; ++} ++ + /* update sink rates from dpcd */ + static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) + { +@@ -1603,46 +1611,6 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); + } + +-static void +-intel_dp_drrs_compute_config(struct intel_dp *intel_dp, +- struct intel_crtc_state *pipe_config, +- int output_bpp, bool constant_n) +-{ +- struct intel_connector *intel_connector = intel_dp->attached_connector; +- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +- int pixel_clock; +- +- if (pipe_config->vrr.enable) +- return; +- +- /* +- * DRRS and PSR can't be enable together, so giving preference to PSR +- * as it allows more power-savings by complete shutting down display, +- * so to guarantee this, intel_dp_drrs_compute_config() must be called +- * after intel_psr_compute_config(). +- */ +- if (pipe_config->has_psr) +- return; +- +- if (!intel_connector->panel.downclock_mode || +- dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) +- return; +- +- pipe_config->has_drrs = true; +- +- pixel_clock = intel_connector->panel.downclock_mode->clock; +- if (pipe_config->splitter.enable) +- pixel_clock /= pipe_config->splitter.link_count; +- +- intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock, +- pipe_config->port_clock, &pipe_config->dp_m2_n2, +- constant_n, pipe_config->fec_enable); +- +- /* FIXME: abstract this better */ +- if (pipe_config->splitter.enable) +- pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count; +-} +- + int + intel_dp_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, +@@ -1767,6 +1735,12 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, + intel_dp->lane_count = lane_count; + } + ++static void intel_dp_reset_max_link_params(struct intel_dp *intel_dp) ++{ ++ intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); ++ intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); ++} ++ + /* Enable backlight PWM and backlight PP control. */ + void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +@@ -1852,6 +1826,16 @@ intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful) + + if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) + drm_err(&i915->drm, "Failed to write source OUI\n"); ++ ++ intel_dp->last_oui_write = jiffies; ++} ++ ++void intel_dp_wait_source_oui(struct intel_dp *intel_dp) ++{ ++ struct drm_i915_private *i915 = dp_to_i915(intel_dp); ++ ++ drm_dbg_kms(&i915->drm, "Performing OUI wait\n"); ++ wait_remaining_ms_from_jiffies(intel_dp->last_oui_write, 30); + } + + /* If the device supports it, try to set the power state appropriately */ +@@ -1926,8 +1910,7 @@ void intel_dp_sync_state(struct intel_encoder *encoder, + if (intel_dp->dpcd[DP_DPCD_REV] == 0) + intel_dp_get_dpcd(intel_dp); + +- intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); +- intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); ++ intel_dp_reset_max_link_params(intel_dp); + } + + bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, +@@ -2462,6 +2445,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) + */ + intel_psr_init_dpcd(intel_dp); + ++ /* Clear the default sink rates */ ++ intel_dp->num_sink_rates = 0; ++ + /* Read the eDP 1.4+ supported link rates. */ + if (intel_dp->edp_dpcd[0] >= DP_EDP_14) { + __le16 sink_rates[DP_MAX_SUPPORTED_RATES]; +@@ -2497,6 +2483,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) + intel_dp_set_sink_rates(intel_dp); + + intel_dp_set_common_rates(intel_dp); ++ intel_dp_reset_max_link_params(intel_dp); + + /* Read the eDP DSC DPCD registers */ + if (DISPLAY_VER(dev_priv) >= 10) +@@ -4240,12 +4227,7 @@ intel_dp_detect(struct drm_connector *connector, + * supports link training fallback params. + */ + if (intel_dp->reset_link_params || intel_dp->is_mst) { +- /* Initial max link lane count */ +- intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); +- +- /* Initial max link rate */ +- intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp); +- ++ intel_dp_reset_max_link_params(intel_dp); + intel_dp->reset_link_params = false; + } + +@@ -4716,432 +4698,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect + drm_connector_attach_vrr_capable_property(connector); + } + +-/** +- * intel_dp_set_drrs_state - program registers for RR switch to take effect +- * @dev_priv: i915 device +- * @crtc_state: a pointer to the active intel_crtc_state +- * @refresh_rate: RR to be programmed +- * +- * This function gets called when refresh rate (RR) has to be changed from +- * one frequency to another. Switches can be between high and low RR +- * supported by the panel or to any other RR based on media playback (in +- * this case, RR value needs to be passed from user space). +- * +- * The caller of this function needs to take a lock on dev_priv->drrs. +- */ +-static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, +- const struct intel_crtc_state *crtc_state, +- int refresh_rate) +-{ +- struct intel_dp *intel_dp = dev_priv->drrs.dp; +- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +- enum drrs_refresh_rate_type index = DRRS_HIGH_RR; +- +- if (refresh_rate <= 0) { +- drm_dbg_kms(&dev_priv->drm, +- "Refresh rate should be positive non-zero.\n"); +- return; +- } +- +- if (intel_dp == NULL) { +- drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n"); +- return; +- } +- +- if (!crtc) { +- drm_dbg_kms(&dev_priv->drm, +- "DRRS: intel_crtc not initialized\n"); +- return; +- } +- +- if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) { +- drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); +- return; +- } +- +- if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) == +- refresh_rate) +- index = DRRS_LOW_RR; +- +- if (index == dev_priv->drrs.refresh_rate_type) { +- drm_dbg_kms(&dev_priv->drm, +- "DRRS requested for previously set RR...ignoring\n"); +- return; +- } +- +- if (!crtc_state->hw.active) { +- drm_dbg_kms(&dev_priv->drm, +- "eDP encoder disabled. CRTC not Active\n"); +- return; +- } +- +- if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) { +- switch (index) { +- case DRRS_HIGH_RR: +- intel_dp_set_m_n(crtc_state, M1_N1); +- break; +- case DRRS_LOW_RR: +- intel_dp_set_m_n(crtc_state, M2_N2); +- break; +- case DRRS_MAX_RR: +- default: +- drm_err(&dev_priv->drm, +- "Unsupported refreshrate type\n"); +- } +- } else if (DISPLAY_VER(dev_priv) > 6) { +- i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder); +- u32 val; +- +- val = intel_de_read(dev_priv, reg); +- if (index > DRRS_HIGH_RR) { +- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +- val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV; +- else +- val |= PIPECONF_EDP_RR_MODE_SWITCH; +- } else { +- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +- val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV; +- else +- val &= ~PIPECONF_EDP_RR_MODE_SWITCH; +- } +- intel_de_write(dev_priv, reg, val); +- } +- +- dev_priv->drrs.refresh_rate_type = index; +- +- drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n", +- refresh_rate); +-} +- +-static void +-intel_edp_drrs_enable_locked(struct intel_dp *intel_dp) +-{ +- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +- +- dev_priv->drrs.busy_frontbuffer_bits = 0; +- dev_priv->drrs.dp = intel_dp; +-} +- +-/** +- * intel_edp_drrs_enable - init drrs struct if supported +- * @intel_dp: DP struct +- * @crtc_state: A pointer to the active crtc state. +- * +- * Initializes frontbuffer_bits and drrs.dp +- */ +-void intel_edp_drrs_enable(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state) +-{ +- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +- +- if (!crtc_state->has_drrs) +- return; +- +- drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n"); +- +- mutex_lock(&dev_priv->drrs.mutex); +- +- if (dev_priv->drrs.dp) { +- drm_warn(&dev_priv->drm, "DRRS already enabled\n"); +- goto unlock; +- } +- +- intel_edp_drrs_enable_locked(intel_dp); +- +-unlock: +- mutex_unlock(&dev_priv->drrs.mutex); +-} +- +-static void +-intel_edp_drrs_disable_locked(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state) +-{ +- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +- +- if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) { +- int refresh; +- +- refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode); +- intel_dp_set_drrs_state(dev_priv, crtc_state, refresh); +- } +- +- dev_priv->drrs.dp = NULL; +-} +- +-/** +- * intel_edp_drrs_disable - Disable DRRS +- * @intel_dp: DP struct +- * @old_crtc_state: Pointer to old crtc_state. +- * +- */ +-void intel_edp_drrs_disable(struct intel_dp *intel_dp, +- const struct intel_crtc_state *old_crtc_state) +-{ +- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +- +- if (!old_crtc_state->has_drrs) +- return; +- +- mutex_lock(&dev_priv->drrs.mutex); +- if (!dev_priv->drrs.dp) { +- mutex_unlock(&dev_priv->drrs.mutex); +- return; +- } +- +- intel_edp_drrs_disable_locked(intel_dp, old_crtc_state); +- mutex_unlock(&dev_priv->drrs.mutex); +- +- cancel_delayed_work_sync(&dev_priv->drrs.work); +-} +- +-/** +- * intel_edp_drrs_update - Update DRRS state +- * @intel_dp: Intel DP +- * @crtc_state: new CRTC state +- * +- * This function will update DRRS states, disabling or enabling DRRS when +- * executing fastsets. For full modeset, intel_edp_drrs_disable() and +- * intel_edp_drrs_enable() should be called instead. +- */ +-void +-intel_edp_drrs_update(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state) +-{ +- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); +- +- if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) +- return; +- +- mutex_lock(&dev_priv->drrs.mutex); +- +- /* New state matches current one? */ +- if (crtc_state->has_drrs == !!dev_priv->drrs.dp) +- goto unlock; +- +- if (crtc_state->has_drrs) +- intel_edp_drrs_enable_locked(intel_dp); +- else +- intel_edp_drrs_disable_locked(intel_dp, crtc_state); +- +-unlock: +- mutex_unlock(&dev_priv->drrs.mutex); +-} +- +-static void intel_edp_drrs_downclock_work(struct work_struct *work) +-{ +- struct drm_i915_private *dev_priv = +- container_of(work, typeof(*dev_priv), drrs.work.work); +- struct intel_dp *intel_dp; +- +- mutex_lock(&dev_priv->drrs.mutex); +- +- intel_dp = dev_priv->drrs.dp; +- +- if (!intel_dp) +- goto unlock; +- +- /* +- * The delayed work can race with an invalidate hence we need to +- * recheck. +- */ +- +- if (dev_priv->drrs.busy_frontbuffer_bits) +- goto unlock; +- +- if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) { +- struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; +- +- intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, +- drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode)); +- } +- +-unlock: +- mutex_unlock(&dev_priv->drrs.mutex); +-} +- +-/** +- * intel_edp_drrs_invalidate - Disable Idleness DRRS +- * @dev_priv: i915 device +- * @frontbuffer_bits: frontbuffer plane tracking bits +- * +- * This function gets called everytime rendering on the given planes start. +- * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR). +- * +- * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits. +- */ +-void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, +- unsigned int frontbuffer_bits) +-{ +- struct intel_dp *intel_dp; +- struct drm_crtc *crtc; +- enum pipe pipe; +- +- if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED) +- return; +- +- cancel_delayed_work(&dev_priv->drrs.work); +- +- mutex_lock(&dev_priv->drrs.mutex); +- +- intel_dp = dev_priv->drrs.dp; +- if (!intel_dp) { +- mutex_unlock(&dev_priv->drrs.mutex); +- return; +- } +- +- crtc = dp_to_dig_port(intel_dp)->base.base.crtc; +- pipe = to_intel_crtc(crtc)->pipe; +- +- frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); +- dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits; +- +- /* invalidate means busy screen hence upclock */ +- if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) +- intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, +- drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode)); +- +- mutex_unlock(&dev_priv->drrs.mutex); +-} +- +-/** +- * intel_edp_drrs_flush - Restart Idleness DRRS +- * @dev_priv: i915 device +- * @frontbuffer_bits: frontbuffer plane tracking bits +- * +- * This function gets called every time rendering on the given planes has +- * completed or flip on a crtc is completed. So DRRS should be upclocked +- * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again, +- * if no other planes are dirty. +- * +- * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits. +- */ +-void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, +- unsigned int frontbuffer_bits) +-{ +- struct intel_dp *intel_dp; +- struct drm_crtc *crtc; +- enum pipe pipe; +- +- if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED) +- return; +- +- cancel_delayed_work(&dev_priv->drrs.work); +- +- mutex_lock(&dev_priv->drrs.mutex); +- +- intel_dp = dev_priv->drrs.dp; +- if (!intel_dp) { +- mutex_unlock(&dev_priv->drrs.mutex); +- return; +- } +- +- crtc = dp_to_dig_port(intel_dp)->base.base.crtc; +- pipe = to_intel_crtc(crtc)->pipe; +- +- frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); +- dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; +- +- /* flush means busy screen hence upclock */ +- if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) +- intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, +- drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode)); +- +- /* +- * flush also means no more activity hence schedule downclock, if all +- * other fbs are quiescent too +- */ +- if (!dev_priv->drrs.busy_frontbuffer_bits) +- schedule_delayed_work(&dev_priv->drrs.work, +- msecs_to_jiffies(1000)); +- mutex_unlock(&dev_priv->drrs.mutex); +-} +- +-/** +- * DOC: Display Refresh Rate Switching (DRRS) +- * +- * Display Refresh Rate Switching (DRRS) is a power conservation feature +- * which enables swtching between low and high refresh rates, +- * dynamically, based on the usage scenario. This feature is applicable +- * for internal panels. +- * +- * Indication that the panel supports DRRS is given by the panel EDID, which +- * would list multiple refresh rates for one resolution. +- * +- * DRRS is of 2 types - static and seamless. +- * Static DRRS involves changing refresh rate (RR) by doing a full modeset +- * (may appear as a blink on screen) and is used in dock-undock scenario. +- * Seamless DRRS involves changing RR without any visual effect to the user +- * and can be used during normal system usage. This is done by programming +- * certain registers. +- * +- * Support for static/seamless DRRS may be indicated in the VBT based on +- * inputs from the panel spec. +- * +- * DRRS saves power by switching to low RR based on usage scenarios. +- * +- * The implementation is based on frontbuffer tracking implementation. When +- * there is a disturbance on the screen triggered by user activity or a periodic +- * system activity, DRRS is disabled (RR is changed to high RR). When there is +- * no movement on screen, after a timeout of 1 second, a switch to low RR is +- * made. +- * +- * For integration with frontbuffer tracking code, intel_edp_drrs_invalidate() +- * and intel_edp_drrs_flush() are called. +- * +- * DRRS can be further extended to support other internal panels and also +- * the scenario of video playback wherein RR is set based on the rate +- * requested by userspace. +- */ +- +-/** +- * intel_dp_drrs_init - Init basic DRRS work and mutex. +- * @connector: eDP connector +- * @fixed_mode: preferred mode of panel +- * +- * This function is called only once at driver load to initialize basic +- * DRRS stuff. +- * +- * Returns: +- * Downclock mode if panel supports it, else return NULL. +- * DRRS support is determined by the presence of downclock mode (apart +- * from VBT setting). +- */ +-static struct drm_display_mode * +-intel_dp_drrs_init(struct intel_connector *connector, +- struct drm_display_mode *fixed_mode) +-{ +- struct drm_i915_private *dev_priv = to_i915(connector->base.dev); +- struct drm_display_mode *downclock_mode = NULL; +- +- INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work); +- mutex_init(&dev_priv->drrs.mutex); +- +- if (DISPLAY_VER(dev_priv) <= 6) { +- drm_dbg_kms(&dev_priv->drm, +- "DRRS supported for Gen7 and above\n"); +- return NULL; +- } +- +- if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { +- drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n"); +- return NULL; +- } +- +- downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode); +- if (!downclock_mode) { +- drm_dbg_kms(&dev_priv->drm, +- "Downclock mode is not found. DRRS not supported\n"); +- return NULL; +- } +- +- dev_priv->drrs.type = dev_priv->vbt.drrs_type; +- +- dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR; +- drm_dbg_kms(&dev_priv->drm, +- "seamless DRRS supported for eDP panel.\n"); +- return downclock_mode; +-} +- + static bool intel_edp_init_connector(struct intel_dp *intel_dp, + struct intel_connector *intel_connector) + { +@@ -5296,6 +4852,9 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, + return false; + + intel_dp_set_source_rates(intel_dp); ++ intel_dp_set_default_sink_rates(intel_dp); ++ intel_dp_set_common_rates(intel_dp); ++ intel_dp_reset_max_link_params(intel_dp); + + intel_dp->reset_link_params = true; + intel_dp->pps.pps_pipe = INVALID_PIPE; +diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h +index 680631b5b4378..3dd6ebc2f6b14 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp.h ++++ b/drivers/gpu/drm/i915/display/intel_dp.h +@@ -70,17 +70,6 @@ int intel_dp_max_link_rate(struct intel_dp *intel_dp); + int intel_dp_max_lane_count(struct intel_dp *intel_dp); + int intel_dp_rate_select(struct intel_dp *intel_dp, int rate); + +-void intel_edp_drrs_enable(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state); +-void intel_edp_drrs_disable(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state); +-void intel_edp_drrs_update(struct intel_dp *intel_dp, +- const struct intel_crtc_state *crtc_state); +-void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, +- unsigned int frontbuffer_bits); +-void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, +- unsigned int frontbuffer_bits); +- + void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, + u8 *link_bw, u8 *rate_select); + bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); +@@ -129,4 +118,6 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); + void intel_dp_phy_test(struct intel_encoder *encoder); + ++void intel_dp_wait_source_oui(struct intel_dp *intel_dp); ++ + #endif /* __INTEL_DP_H__ */ +diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +index 6ac568617ef37..c82f8febe7303 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c ++++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +@@ -35,6 +35,7 @@ + */ + + #include "intel_display_types.h" ++#include "intel_dp.h" + #include "intel_dp_aux_backlight.h" + #include "intel_panel.h" + +@@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) + int ret; + u8 tcon_cap[4]; + ++ intel_dp_wait_source_oui(intel_dp); ++ + ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); + if (ret != sizeof(tcon_cap)) + return false; +@@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, + int ret; + u8 old_ctrl, ctrl; + ++ intel_dp_wait_source_oui(intel_dp); ++ + ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); + if (ret != 1) { + drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret); +diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c +new file mode 100644 +index 0000000000000..22acd945a9e47 +--- /dev/null ++++ b/drivers/gpu/drm/i915/display/intel_dpt.c +@@ -0,0 +1,229 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * Copyright © 2021 Intel Corporation ++ */ ++ ++#include "i915_drv.h" ++#include "intel_display_types.h" ++#include "intel_dpt.h" ++#include "intel_fb.h" ++#include "gt/gen8_ppgtt.h" ++ ++struct i915_dpt { ++ struct i915_address_space vm; ++ ++ struct drm_i915_gem_object *obj; ++ struct i915_vma *vma; ++ void __iomem *iomem; ++}; ++ ++#define i915_is_dpt(vm) ((vm)->is_dpt) ++ ++static inline struct i915_dpt * ++i915_vm_to_dpt(struct i915_address_space *vm) ++{ ++ BUILD_BUG_ON(offsetof(struct i915_dpt, vm)); ++ GEM_BUG_ON(!i915_is_dpt(vm)); ++ return container_of(vm, struct i915_dpt, vm); ++} ++ ++#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT) ++ ++static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte) ++{ ++ writeq(pte, addr); ++} ++ ++static void dpt_insert_page(struct i915_address_space *vm, ++ dma_addr_t addr, ++ u64 offset, ++ enum i915_cache_level level, ++ u32 flags) ++{ ++ struct i915_dpt *dpt = i915_vm_to_dpt(vm); ++ gen8_pte_t __iomem *base = dpt->iomem; ++ ++ gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE, ++ vm->pte_encode(addr, level, flags)); ++} ++ ++static void dpt_insert_entries(struct i915_address_space *vm, ++ struct i915_vma *vma, ++ enum i915_cache_level level, ++ u32 flags) ++{ ++ struct i915_dpt *dpt = i915_vm_to_dpt(vm); ++ gen8_pte_t __iomem *base = dpt->iomem; ++ const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags); ++ struct sgt_iter sgt_iter; ++ dma_addr_t addr; ++ int i; ++ ++ /* ++ * Note that we ignore PTE_READ_ONLY here. The caller must be careful ++ * not to allow the user to override access to a read only page. ++ */ ++ ++ i = vma->node.start / I915_GTT_PAGE_SIZE; ++ for_each_sgt_daddr(addr, sgt_iter, vma->pages) ++ gen8_set_pte(&base[i++], pte_encode | addr); ++} ++ ++static void dpt_clear_range(struct i915_address_space *vm, ++ u64 start, u64 length) ++{ ++} ++ ++static void dpt_bind_vma(struct i915_address_space *vm, ++ struct i915_vm_pt_stash *stash, ++ struct i915_vma *vma, ++ enum i915_cache_level cache_level, ++ u32 flags) ++{ ++ struct drm_i915_gem_object *obj = vma->obj; ++ u32 pte_flags; ++ ++ /* Applicable to VLV (gen8+ do not support RO in the GGTT) */ ++ pte_flags = 0; ++ if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj)) ++ pte_flags |= PTE_READ_ONLY; ++ if (i915_gem_object_is_lmem(obj)) ++ pte_flags |= PTE_LM; ++ ++ vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); ++ ++ vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; ++ ++ /* ++ * Without aliasing PPGTT there's no difference between ++ * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally ++ * upgrade to both bound if we bind either to avoid double-binding. ++ */ ++ atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags); ++} ++ ++static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) ++{ ++ vm->clear_range(vm, vma->node.start, vma->size); ++} ++ ++static void dpt_cleanup(struct i915_address_space *vm) ++{ ++ struct i915_dpt *dpt = i915_vm_to_dpt(vm); ++ ++ i915_gem_object_put(dpt->obj); ++} ++ ++struct i915_vma *intel_dpt_pin(struct i915_address_space *vm) ++{ ++ struct drm_i915_private *i915 = vm->i915; ++ struct i915_dpt *dpt = i915_vm_to_dpt(vm); ++ intel_wakeref_t wakeref; ++ struct i915_vma *vma; ++ void __iomem *iomem; ++ ++ wakeref = intel_runtime_pm_get(&i915->runtime_pm); ++ atomic_inc(&i915->gpu_error.pending_fb_pin); ++ ++ vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096, ++ HAS_LMEM(i915) ? 0 : PIN_MAPPABLE); ++ if (IS_ERR(vma)) ++ goto err; ++ ++ iomem = i915_vma_pin_iomap(vma); ++ i915_vma_unpin(vma); ++ if (IS_ERR(iomem)) { ++ vma = iomem; ++ goto err; ++ } ++ ++ dpt->vma = vma; ++ dpt->iomem = iomem; ++ ++ i915_vma_get(vma); ++ ++err: ++ atomic_dec(&i915->gpu_error.pending_fb_pin); ++ intel_runtime_pm_put(&i915->runtime_pm, wakeref); ++ ++ return vma; ++} ++ ++void intel_dpt_unpin(struct i915_address_space *vm) ++{ ++ struct i915_dpt *dpt = i915_vm_to_dpt(vm); ++ ++ i915_vma_unpin_iomap(dpt->vma); ++ i915_vma_put(dpt->vma); ++} ++ ++struct i915_address_space * ++intel_dpt_create(struct intel_framebuffer *fb) ++{ ++ struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base; ++ struct drm_i915_private *i915 = to_i915(obj->dev); ++ struct drm_i915_gem_object *dpt_obj; ++ struct i915_address_space *vm; ++ struct i915_dpt *dpt; ++ size_t size; ++ int ret; ++ ++ if (intel_fb_needs_pot_stride_remap(fb)) ++ size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped); ++ else ++ size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE); ++ ++ size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE); ++ ++ if (HAS_LMEM(i915)) ++ dpt_obj = i915_gem_object_create_lmem(i915, size, 0); ++ else ++ dpt_obj = i915_gem_object_create_stolen(i915, size); ++ if (IS_ERR(dpt_obj)) ++ return ERR_CAST(dpt_obj); ++ ++ ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE); ++ if (ret) { ++ i915_gem_object_put(dpt_obj); ++ return ERR_PTR(ret); ++ } ++ ++ dpt = kzalloc(sizeof(*dpt), GFP_KERNEL); ++ if (!dpt) { ++ i915_gem_object_put(dpt_obj); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ vm = &dpt->vm; ++ ++ vm->gt = &i915->gt; ++ vm->i915 = i915; ++ vm->dma = i915->drm.dev; ++ vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE; ++ vm->is_dpt = true; ++ ++ i915_address_space_init(vm, VM_CLASS_DPT); ++ ++ vm->insert_page = dpt_insert_page; ++ vm->clear_range = dpt_clear_range; ++ vm->insert_entries = dpt_insert_entries; ++ vm->cleanup = dpt_cleanup; ++ ++ vm->vma_ops.bind_vma = dpt_bind_vma; ++ vm->vma_ops.unbind_vma = dpt_unbind_vma; ++ vm->vma_ops.set_pages = ggtt_set_pages; ++ vm->vma_ops.clear_pages = clear_pages; ++ ++ vm->pte_encode = gen8_ggtt_pte_encode; ++ ++ dpt->obj = dpt_obj; ++ ++ return &dpt->vm; ++} ++ ++void intel_dpt_destroy(struct i915_address_space *vm) ++{ ++ struct i915_dpt *dpt = i915_vm_to_dpt(vm); ++ ++ i915_vm_close(&dpt->vm); ++} +diff --git a/drivers/gpu/drm/i915/display/intel_dpt.h b/drivers/gpu/drm/i915/display/intel_dpt.h +new file mode 100644 +index 0000000000000..45142b8f849f6 +--- /dev/null ++++ b/drivers/gpu/drm/i915/display/intel_dpt.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Copyright © 2021 Intel Corporation ++ */ ++ ++#ifndef __INTEL_DPT_H__ ++#define __INTEL_DPT_H__ ++ ++struct i915_address_space; ++struct i915_vma; ++struct intel_framebuffer; ++ ++void intel_dpt_destroy(struct i915_address_space *vm); ++struct i915_vma *intel_dpt_pin(struct i915_address_space *vm); ++void intel_dpt_unpin(struct i915_address_space *vm); ++struct i915_address_space * ++intel_dpt_create(struct intel_framebuffer *fb); ++ ++#endif /* __INTEL_DPT_H__ */ +diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c +new file mode 100644 +index 0000000000000..3c7d6bf579484 +--- /dev/null ++++ b/drivers/gpu/drm/i915/display/intel_drrs.c +@@ -0,0 +1,485 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * Copyright © 2021 Intel Corporation ++ */ ++ ++#include "i915_drv.h" ++#include "intel_atomic.h" ++#include "intel_de.h" ++#include "intel_display_types.h" ++#include "intel_drrs.h" ++#include "intel_panel.h" ++ ++/** ++ * DOC: Display Refresh Rate Switching (DRRS) ++ * ++ * Display Refresh Rate Switching (DRRS) is a power conservation feature ++ * which enables swtching between low and high refresh rates, ++ * dynamically, based on the usage scenario. This feature is applicable ++ * for internal panels. ++ * ++ * Indication that the panel supports DRRS is given by the panel EDID, which ++ * would list multiple refresh rates for one resolution. ++ * ++ * DRRS is of 2 types - static and seamless. ++ * Static DRRS involves changing refresh rate (RR) by doing a full modeset ++ * (may appear as a blink on screen) and is used in dock-undock scenario. ++ * Seamless DRRS involves changing RR without any visual effect to the user ++ * and can be used during normal system usage. This is done by programming ++ * certain registers. ++ * ++ * Support for static/seamless DRRS may be indicated in the VBT based on ++ * inputs from the panel spec. ++ * ++ * DRRS saves power by switching to low RR based on usage scenarios. ++ * ++ * The implementation is based on frontbuffer tracking implementation. When ++ * there is a disturbance on the screen triggered by user activity or a periodic ++ * system activity, DRRS is disabled (RR is changed to high RR). When there is ++ * no movement on screen, after a timeout of 1 second, a switch to low RR is ++ * made. ++ * ++ * For integration with frontbuffer tracking code, intel_edp_drrs_invalidate() ++ * and intel_edp_drrs_flush() are called. ++ * ++ * DRRS can be further extended to support other internal panels and also ++ * the scenario of video playback wherein RR is set based on the rate ++ * requested by userspace. ++ */ ++ ++void ++intel_dp_drrs_compute_config(struct intel_dp *intel_dp, ++ struct intel_crtc_state *pipe_config, ++ int output_bpp, bool constant_n) ++{ ++ struct intel_connector *intel_connector = intel_dp->attached_connector; ++ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ int pixel_clock; ++ ++ if (pipe_config->vrr.enable) ++ return; ++ ++ /* ++ * DRRS and PSR can't be enable together, so giving preference to PSR ++ * as it allows more power-savings by complete shutting down display, ++ * so to guarantee this, intel_dp_drrs_compute_config() must be called ++ * after intel_psr_compute_config(). ++ */ ++ if (pipe_config->has_psr) ++ return; ++ ++ if (!intel_connector->panel.downclock_mode || ++ dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) ++ return; ++ ++ pipe_config->has_drrs = true; ++ ++ pixel_clock = intel_connector->panel.downclock_mode->clock; ++ if (pipe_config->splitter.enable) ++ pixel_clock /= pipe_config->splitter.link_count; ++ ++ intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock, ++ pipe_config->port_clock, &pipe_config->dp_m2_n2, ++ constant_n, pipe_config->fec_enable); ++ ++ /* FIXME: abstract this better */ ++ if (pipe_config->splitter.enable) ++ pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count; ++} ++ ++/** ++ * intel_dp_set_drrs_state - program registers for RR switch to take effect ++ * @dev_priv: i915 device ++ * @crtc_state: a pointer to the active intel_crtc_state ++ * @refresh_rate: RR to be programmed ++ * ++ * This function gets called when refresh rate (RR) has to be changed from ++ * one frequency to another. Switches can be between high and low RR ++ * supported by the panel or to any other RR based on media playback (in ++ * this case, RR value needs to be passed from user space). ++ * ++ * The caller of this function needs to take a lock on dev_priv->drrs. ++ */ ++static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, ++ const struct intel_crtc_state *crtc_state, ++ int refresh_rate) ++{ ++ struct intel_dp *intel_dp = dev_priv->drrs.dp; ++ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); ++ enum drrs_refresh_rate_type index = DRRS_HIGH_RR; ++ ++ if (refresh_rate <= 0) { ++ drm_dbg_kms(&dev_priv->drm, ++ "Refresh rate should be positive non-zero.\n"); ++ return; ++ } ++ ++ if (intel_dp == NULL) { ++ drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n"); ++ return; ++ } ++ ++ if (!crtc) { ++ drm_dbg_kms(&dev_priv->drm, ++ "DRRS: intel_crtc not initialized\n"); ++ return; ++ } ++ ++ if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) { ++ drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); ++ return; ++ } ++ ++ if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) == ++ refresh_rate) ++ index = DRRS_LOW_RR; ++ ++ if (index == dev_priv->drrs.refresh_rate_type) { ++ drm_dbg_kms(&dev_priv->drm, ++ "DRRS requested for previously set RR...ignoring\n"); ++ return; ++ } ++ ++ if (!crtc_state->hw.active) { ++ drm_dbg_kms(&dev_priv->drm, ++ "eDP encoder disabled. CRTC not Active\n"); ++ return; ++ } ++ ++ if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) { ++ switch (index) { ++ case DRRS_HIGH_RR: ++ intel_dp_set_m_n(crtc_state, M1_N1); ++ break; ++ case DRRS_LOW_RR: ++ intel_dp_set_m_n(crtc_state, M2_N2); ++ break; ++ case DRRS_MAX_RR: ++ default: ++ drm_err(&dev_priv->drm, ++ "Unsupported refreshrate type\n"); ++ } ++ } else if (DISPLAY_VER(dev_priv) > 6) { ++ i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder); ++ u32 val; ++ ++ val = intel_de_read(dev_priv, reg); ++ if (index > DRRS_HIGH_RR) { ++ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ++ val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV; ++ else ++ val |= PIPECONF_EDP_RR_MODE_SWITCH; ++ } else { ++ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) ++ val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV; ++ else ++ val &= ~PIPECONF_EDP_RR_MODE_SWITCH; ++ } ++ intel_de_write(dev_priv, reg, val); ++ } ++ ++ dev_priv->drrs.refresh_rate_type = index; ++ ++ drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n", ++ refresh_rate); ++} ++ ++static void ++intel_edp_drrs_enable_locked(struct intel_dp *intel_dp) ++{ ++ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ ++ dev_priv->drrs.busy_frontbuffer_bits = 0; ++ dev_priv->drrs.dp = intel_dp; ++} ++ ++/** ++ * intel_edp_drrs_enable - init drrs struct if supported ++ * @intel_dp: DP struct ++ * @crtc_state: A pointer to the active crtc state. ++ * ++ * Initializes frontbuffer_bits and drrs.dp ++ */ ++void intel_edp_drrs_enable(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state) ++{ ++ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ ++ if (!crtc_state->has_drrs) ++ return; ++ ++ drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n"); ++ ++ mutex_lock(&dev_priv->drrs.mutex); ++ ++ if (dev_priv->drrs.dp) { ++ drm_warn(&dev_priv->drm, "DRRS already enabled\n"); ++ goto unlock; ++ } ++ ++ intel_edp_drrs_enable_locked(intel_dp); ++ ++unlock: ++ mutex_unlock(&dev_priv->drrs.mutex); ++} ++ ++static void ++intel_edp_drrs_disable_locked(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state) ++{ ++ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ ++ if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) { ++ int refresh; ++ ++ refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode); ++ intel_dp_set_drrs_state(dev_priv, crtc_state, refresh); ++ } ++ ++ dev_priv->drrs.dp = NULL; ++} ++ ++/** ++ * intel_edp_drrs_disable - Disable DRRS ++ * @intel_dp: DP struct ++ * @old_crtc_state: Pointer to old crtc_state. ++ * ++ */ ++void intel_edp_drrs_disable(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *old_crtc_state) ++{ ++ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ ++ if (!old_crtc_state->has_drrs) ++ return; ++ ++ mutex_lock(&dev_priv->drrs.mutex); ++ if (!dev_priv->drrs.dp) { ++ mutex_unlock(&dev_priv->drrs.mutex); ++ return; ++ } ++ ++ intel_edp_drrs_disable_locked(intel_dp, old_crtc_state); ++ mutex_unlock(&dev_priv->drrs.mutex); ++ ++ cancel_delayed_work_sync(&dev_priv->drrs.work); ++} ++ ++/** ++ * intel_edp_drrs_update - Update DRRS state ++ * @intel_dp: Intel DP ++ * @crtc_state: new CRTC state ++ * ++ * This function will update DRRS states, disabling or enabling DRRS when ++ * executing fastsets. For full modeset, intel_edp_drrs_disable() and ++ * intel_edp_drrs_enable() should be called instead. ++ */ ++void ++intel_edp_drrs_update(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state) ++{ ++ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); ++ ++ if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) ++ return; ++ ++ mutex_lock(&dev_priv->drrs.mutex); ++ ++ /* New state matches current one? */ ++ if (crtc_state->has_drrs == !!dev_priv->drrs.dp) ++ goto unlock; ++ ++ if (crtc_state->has_drrs) ++ intel_edp_drrs_enable_locked(intel_dp); ++ else ++ intel_edp_drrs_disable_locked(intel_dp, crtc_state); ++ ++unlock: ++ mutex_unlock(&dev_priv->drrs.mutex); ++} ++ ++static void intel_edp_drrs_downclock_work(struct work_struct *work) ++{ ++ struct drm_i915_private *dev_priv = ++ container_of(work, typeof(*dev_priv), drrs.work.work); ++ struct intel_dp *intel_dp; ++ ++ mutex_lock(&dev_priv->drrs.mutex); ++ ++ intel_dp = dev_priv->drrs.dp; ++ ++ if (!intel_dp) ++ goto unlock; ++ ++ /* ++ * The delayed work can race with an invalidate hence we need to ++ * recheck. ++ */ ++ ++ if (dev_priv->drrs.busy_frontbuffer_bits) ++ goto unlock; ++ ++ if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) { ++ struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; ++ ++ intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, ++ drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode)); ++ } ++ ++unlock: ++ mutex_unlock(&dev_priv->drrs.mutex); ++} ++ ++/** ++ * intel_edp_drrs_invalidate - Disable Idleness DRRS ++ * @dev_priv: i915 device ++ * @frontbuffer_bits: frontbuffer plane tracking bits ++ * ++ * This function gets called everytime rendering on the given planes start. ++ * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR). ++ * ++ * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits. ++ */ ++void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, ++ unsigned int frontbuffer_bits) ++{ ++ struct intel_dp *intel_dp; ++ struct drm_crtc *crtc; ++ enum pipe pipe; ++ ++ if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED) ++ return; ++ ++ cancel_delayed_work(&dev_priv->drrs.work); ++ ++ mutex_lock(&dev_priv->drrs.mutex); ++ ++ intel_dp = dev_priv->drrs.dp; ++ if (!intel_dp) { ++ mutex_unlock(&dev_priv->drrs.mutex); ++ return; ++ } ++ ++ crtc = dp_to_dig_port(intel_dp)->base.base.crtc; ++ pipe = to_intel_crtc(crtc)->pipe; ++ ++ frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); ++ dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits; ++ ++ /* invalidate means busy screen hence upclock */ ++ if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) ++ intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, ++ drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode)); ++ ++ mutex_unlock(&dev_priv->drrs.mutex); ++} ++ ++/** ++ * intel_edp_drrs_flush - Restart Idleness DRRS ++ * @dev_priv: i915 device ++ * @frontbuffer_bits: frontbuffer plane tracking bits ++ * ++ * This function gets called every time rendering on the given planes has ++ * completed or flip on a crtc is completed. So DRRS should be upclocked ++ * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again, ++ * if no other planes are dirty. ++ * ++ * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits. ++ */ ++void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, ++ unsigned int frontbuffer_bits) ++{ ++ struct intel_dp *intel_dp; ++ struct drm_crtc *crtc; ++ enum pipe pipe; ++ ++ if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED) ++ return; ++ ++ cancel_delayed_work(&dev_priv->drrs.work); ++ ++ mutex_lock(&dev_priv->drrs.mutex); ++ ++ intel_dp = dev_priv->drrs.dp; ++ if (!intel_dp) { ++ mutex_unlock(&dev_priv->drrs.mutex); ++ return; ++ } ++ ++ crtc = dp_to_dig_port(intel_dp)->base.base.crtc; ++ pipe = to_intel_crtc(crtc)->pipe; ++ ++ frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); ++ dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; ++ ++ /* flush means busy screen hence upclock */ ++ if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) ++ intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config, ++ drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode)); ++ ++ /* ++ * flush also means no more activity hence schedule downclock, if all ++ * other fbs are quiescent too ++ */ ++ if (!dev_priv->drrs.busy_frontbuffer_bits) ++ schedule_delayed_work(&dev_priv->drrs.work, ++ msecs_to_jiffies(1000)); ++ mutex_unlock(&dev_priv->drrs.mutex); ++} ++ ++/** ++ * intel_dp_drrs_init - Init basic DRRS work and mutex. ++ * @connector: eDP connector ++ * @fixed_mode: preferred mode of panel ++ * ++ * This function is called only once at driver load to initialize basic ++ * DRRS stuff. ++ * ++ * Returns: ++ * Downclock mode if panel supports it, else return NULL. ++ * DRRS support is determined by the presence of downclock mode (apart ++ * from VBT setting). ++ */ ++struct drm_display_mode * ++intel_dp_drrs_init(struct intel_connector *connector, ++ struct drm_display_mode *fixed_mode) ++{ ++ struct drm_i915_private *dev_priv = to_i915(connector->base.dev); ++ struct intel_encoder *encoder = connector->encoder; ++ struct drm_display_mode *downclock_mode = NULL; ++ ++ INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work); ++ mutex_init(&dev_priv->drrs.mutex); ++ ++ if (DISPLAY_VER(dev_priv) <= 6) { ++ drm_dbg_kms(&dev_priv->drm, ++ "DRRS supported for Gen7 and above\n"); ++ return NULL; ++ } ++ ++ if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) && ++ encoder->port != PORT_A) { ++ drm_dbg_kms(&dev_priv->drm, ++ "DRRS only supported on eDP port A\n"); ++ return NULL; ++ } ++ ++ if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { ++ drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n"); ++ return NULL; ++ } ++ ++ downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode); ++ if (!downclock_mode) { ++ drm_dbg_kms(&dev_priv->drm, ++ "Downclock mode is not found. DRRS not supported\n"); ++ return NULL; ++ } ++ ++ dev_priv->drrs.type = dev_priv->vbt.drrs_type; ++ ++ dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR; ++ drm_dbg_kms(&dev_priv->drm, ++ "seamless DRRS supported for eDP panel.\n"); ++ return downclock_mode; ++} +diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h +new file mode 100644 +index 0000000000000..ffa175b4cf4f4 +--- /dev/null ++++ b/drivers/gpu/drm/i915/display/intel_drrs.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * Copyright © 2021 Intel Corporation ++ */ ++ ++#ifndef __INTEL_DRRS_H__ ++#define __INTEL_DRRS_H__ ++ ++#include <linux/types.h> ++ ++struct drm_i915_private; ++struct intel_crtc_state; ++struct intel_connector; ++struct intel_dp; ++ ++void intel_edp_drrs_enable(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state); ++void intel_edp_drrs_disable(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state); ++void intel_edp_drrs_update(struct intel_dp *intel_dp, ++ const struct intel_crtc_state *crtc_state); ++void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, ++ unsigned int frontbuffer_bits); ++void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, ++ unsigned int frontbuffer_bits); ++void intel_dp_drrs_compute_config(struct intel_dp *intel_dp, ++ struct intel_crtc_state *pipe_config, ++ int output_bpp, bool constant_n); ++struct drm_display_mode *intel_dp_drrs_init(struct intel_connector *connector, ++ struct drm_display_mode *fixed_mode); ++ ++#endif /* __INTEL_DRRS_H__ */ +diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c +index c60a81a81c09c..c6413c5409420 100644 +--- a/drivers/gpu/drm/i915/display/intel_fb.c ++++ b/drivers/gpu/drm/i915/display/intel_fb.c +@@ -172,8 +172,9 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl + + intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane); + intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane); +- *w = fb->base.width / main_hsub / hsub; +- *h = fb->base.height / main_vsub / vsub; ++ ++ *w = DIV_ROUND_UP(fb->base.width, main_hsub * hsub); ++ *h = DIV_ROUND_UP(fb->base.height, main_vsub * vsub); + } + + static u32 intel_adjust_tile_offset(int *x, int *y, +diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c +index 8e75debcce1a9..e4834d84ce5e3 100644 +--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c ++++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c +@@ -62,6 +62,7 @@ + #include "intel_display_types.h" + #include "intel_fbc.h" + #include "intel_frontbuffer.h" ++#include "intel_drrs.h" + #include "intel_psr.h" + + /** +diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c +index b04685bb6439c..c3787512295dd 100644 +--- a/drivers/gpu/drm/i915/display/intel_hdmi.c ++++ b/drivers/gpu/drm/i915/display/intel_hdmi.c +@@ -53,21 +53,20 @@ + #include "intel_panel.h" + #include "intel_snps_phy.h" + +-static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi) ++static struct drm_i915_private *intel_hdmi_to_i915(struct intel_hdmi *intel_hdmi) + { +- return hdmi_to_dig_port(intel_hdmi)->base.base.dev; ++ return to_i915(hdmi_to_dig_port(intel_hdmi)->base.base.dev); + } + + static void + assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) + { +- struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi); +- struct drm_i915_private *dev_priv = to_i915(dev); ++ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(intel_hdmi); + u32 enabled_bits; + + enabled_bits = HAS_DDI(dev_priv) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; + +- drm_WARN(dev, ++ drm_WARN(&dev_priv->drm, + intel_de_read(dev_priv, intel_hdmi->hdmi_reg) & enabled_bits, + "HDMI port enabled, expecting disabled\n"); + } +@@ -1246,13 +1245,14 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, + + void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) + { +- struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); +- struct i2c_adapter *adapter = +- intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); ++ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); ++ struct i2c_adapter *adapter; + + if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) + return; + ++ adapter = intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); ++ + drm_dbg_kms(&dev_priv->drm, "%s DP dual mode adaptor TMDS output\n", + enable ? "Enabling" : "Disabling"); + +@@ -1830,7 +1830,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, + int clock, bool respect_downstream_limits, + bool has_hdmi_sink) + { +- struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); ++ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); + + if (clock < 25000) + return MODE_CLOCK_LOW; +@@ -1946,8 +1946,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) + { + struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); +- struct drm_device *dev = intel_hdmi_to_dev(hdmi); +- struct drm_i915_private *dev_priv = to_i915(dev); ++ struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); + enum drm_mode_status status; + int clock = mode->clock; + int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; +@@ -2260,6 +2259,17 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, + return 0; + } + ++void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder) ++{ ++ struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); ++ ++ /* ++ * Give a hand to buggy BIOSen which forget to turn ++ * the TMDS output buffers back on after a reboot. ++ */ ++ intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); ++} ++ + static void + intel_hdmi_unset_edid(struct drm_connector *connector) + { +diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h +index b43a180d007e0..2bf440eb400ab 100644 +--- a/drivers/gpu/drm/i915/display/intel_hdmi.h ++++ b/drivers/gpu/drm/i915/display/intel_hdmi.h +@@ -28,6 +28,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, + int intel_hdmi_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state); ++void intel_hdmi_encoder_shutdown(struct intel_encoder *encoder); + bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, + struct drm_connector *connector, + bool high_tmds_clock_ratio, +diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c +index 3855fba709807..f7f49b69830fa 100644 +--- a/drivers/gpu/drm/i915/display/intel_opregion.c ++++ b/drivers/gpu/drm/i915/display/intel_opregion.c +@@ -361,6 +361,21 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, + port++; + } + ++ /* ++ * The port numbering and mapping here is bizarre. The now-obsolete ++ * swsci spec supports ports numbered [0..4]. Port E is handled as a ++ * special case, but port F and beyond are not. The functionality is ++ * supposed to be obsolete for new platforms. Just bail out if the port ++ * number is out of bounds after mapping. ++ */ ++ if (port > 4) { ++ drm_dbg_kms(&dev_priv->drm, ++ "[ENCODER:%d:%s] port %c (index %u) out of bounds for display power state notification\n", ++ intel_encoder->base.base.id, intel_encoder->base.name, ++ port_name(intel_encoder->port), port); ++ return -EINVAL; ++ } ++ + if (!enable) + parm |= 4 << 8; + +diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c +index 7e3f5c6ca4846..dfa5f18171e3b 100644 +--- a/drivers/gpu/drm/i915/display/intel_overlay.c ++++ b/drivers/gpu/drm/i915/display/intel_overlay.c +@@ -959,6 +959,9 @@ static int check_overlay_dst(struct intel_overlay *overlay, + const struct intel_crtc_state *pipe_config = + overlay->crtc->config; + ++ if (rec->dst_height == 0 || rec->dst_width == 0) ++ return -EINVAL; ++ + if (rec->dst_x < pipe_config->pipe_src_w && + rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w && + rec->dst_y < pipe_config->pipe_src_h && +diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c +index 18b52b64af955..536b319ffe5ba 100644 +--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c ++++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c +@@ -32,7 +32,7 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *dev_priv) + if (intel_de_wait_for_clear(dev_priv, ICL_PHY_MISC(phy), + DG2_PHY_DP_TX_ACK_MASK, 25)) + DRM_ERROR("SNPS PHY %c failed to calibrate after 25ms.\n", +- phy); ++ phy_name(phy)); + } + } + +diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c +index 3ffece568ed98..0e885440be242 100644 +--- a/drivers/gpu/drm/i915/display/intel_tc.c ++++ b/drivers/gpu/drm/i915/display/intel_tc.c +@@ -291,10 +291,11 @@ static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port) + static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) + { + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ++ enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); + struct intel_uncore *uncore = &i915->uncore; + u32 val; + +- val = intel_uncore_read(uncore, TCSS_DDI_STATUS(dig_port->tc_phy_fia_idx)); ++ val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); + if (val == 0xffffffff) { + drm_dbg_kms(&i915->drm, + "Port %s: PHY in TCCOLD, assuming not complete\n", +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +index 2471f36aaff38..3012cbe5b0b7c 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h ++++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +@@ -298,6 +298,7 @@ struct drm_i915_gem_object { + I915_BO_ALLOC_USER) + #define I915_BO_READONLY BIT(4) + #define I915_TILING_QUIRK_BIT 5 /* unknown swizzling; do not release! */ ++#define I915_BO_WAS_BOUND_BIT 6 + + /** + * @mem_flags - Mutable placement-related flags +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c +index 8eb1c3a6fc9cd..9053cea3395a6 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c +@@ -10,6 +10,8 @@ + #include "i915_gem_lmem.h" + #include "i915_gem_mman.h" + ++#include "gt/intel_gt.h" ++ + void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages, + unsigned int sg_page_sizes) +@@ -160,7 +162,6 @@ retry: + /* Immediately discard the backing storage */ + void i915_gem_object_truncate(struct drm_i915_gem_object *obj) + { +- drm_gem_free_mmap_offset(&obj->base); + if (obj->ops->truncate) + obj->ops->truncate(obj); + } +@@ -218,6 +219,14 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) + __i915_gem_object_reset_page_iter(obj); + obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0; + ++ if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) { ++ struct drm_i915_private *i915 = to_i915(obj->base.dev); ++ intel_wakeref_t wakeref; ++ ++ with_intel_runtime_pm_if_active(&i915->runtime_pm, wakeref) ++ intel_gt_invalidate_tlbs(&i915->gt); ++ } ++ + return pages; + } + +diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +index 6ea13159bffcc..4b823fbfe76a1 100644 +--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c ++++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +@@ -759,11 +759,9 @@ static void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj) + if (obj->mm.madv != I915_MADV_WILLNEED) { + bo->priority = I915_TTM_PRIO_PURGE; + } else if (!i915_gem_object_has_pages(obj)) { +- if (bo->priority < I915_TTM_PRIO_HAS_PAGES) +- bo->priority = I915_TTM_PRIO_HAS_PAGES; ++ bo->priority = I915_TTM_PRIO_NO_PAGES; + } else { +- if (bo->priority > I915_TTM_PRIO_NO_PAGES) +- bo->priority = I915_TTM_PRIO_NO_PAGES; ++ bo->priority = I915_TTM_PRIO_HAS_PAGES; + } + + ttm_bo_move_to_lru_tail(bo, bo->resource, NULL); +diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +index de5f9c86b9a44..cafb0608ffb46 100644 +--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c ++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +@@ -2140,10 +2140,6 @@ static void __execlists_unhold(struct i915_request *rq) + if (p->flags & I915_DEPENDENCY_WEAK) + continue; + +- /* Propagate any change in error status */ +- if (rq->fence.error) +- i915_request_set_error_once(w, rq->fence.error); +- + if (w->engine != rq->engine) + continue; + +diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c +index 62d40c9866427..e1e1d17d49fdd 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt.c ++++ b/drivers/gpu/drm/i915/gt/intel_gt.c +@@ -29,6 +29,8 @@ void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) + + spin_lock_init(>->irq_lock); + ++ mutex_init(>->tlb_invalidate_lock); ++ + INIT_LIST_HEAD(>->closed_vma); + spin_lock_init(>->closed_lock); + +@@ -895,3 +897,103 @@ void intel_gt_info_print(const struct intel_gt_info *info, + + intel_sseu_dump(&info->sseu, p); + } ++ ++struct reg_and_bit { ++ i915_reg_t reg; ++ u32 bit; ++}; ++ ++static struct reg_and_bit ++get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8, ++ const i915_reg_t *regs, const unsigned int num) ++{ ++ const unsigned int class = engine->class; ++ struct reg_and_bit rb = { }; ++ ++ if (drm_WARN_ON_ONCE(&engine->i915->drm, ++ class >= num || !regs[class].reg)) ++ return rb; ++ ++ rb.reg = regs[class]; ++ if (gen8 && class == VIDEO_DECODE_CLASS) ++ rb.reg.reg += 4 * engine->instance; /* GEN8_M2TCR */ ++ else ++ rb.bit = engine->instance; ++ ++ rb.bit = BIT(rb.bit); ++ ++ return rb; ++} ++ ++void intel_gt_invalidate_tlbs(struct intel_gt *gt) ++{ ++ static const i915_reg_t gen8_regs[] = { ++ [RENDER_CLASS] = GEN8_RTCR, ++ [VIDEO_DECODE_CLASS] = GEN8_M1TCR, /* , GEN8_M2TCR */ ++ [VIDEO_ENHANCEMENT_CLASS] = GEN8_VTCR, ++ [COPY_ENGINE_CLASS] = GEN8_BTCR, ++ }; ++ static const i915_reg_t gen12_regs[] = { ++ [RENDER_CLASS] = GEN12_GFX_TLB_INV_CR, ++ [VIDEO_DECODE_CLASS] = GEN12_VD_TLB_INV_CR, ++ [VIDEO_ENHANCEMENT_CLASS] = GEN12_VE_TLB_INV_CR, ++ [COPY_ENGINE_CLASS] = GEN12_BLT_TLB_INV_CR, ++ }; ++ struct drm_i915_private *i915 = gt->i915; ++ struct intel_uncore *uncore = gt->uncore; ++ struct intel_engine_cs *engine; ++ enum intel_engine_id id; ++ const i915_reg_t *regs; ++ unsigned int num = 0; ++ ++ if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) ++ return; ++ ++ if (GRAPHICS_VER(i915) == 12) { ++ regs = gen12_regs; ++ num = ARRAY_SIZE(gen12_regs); ++ } else if (GRAPHICS_VER(i915) >= 8 && GRAPHICS_VER(i915) <= 11) { ++ regs = gen8_regs; ++ num = ARRAY_SIZE(gen8_regs); ++ } else if (GRAPHICS_VER(i915) < 8) { ++ return; ++ } ++ ++ if (drm_WARN_ONCE(&i915->drm, !num, ++ "Platform does not implement TLB invalidation!")) ++ return; ++ ++ GEM_TRACE("\n"); ++ ++ assert_rpm_wakelock_held(&i915->runtime_pm); ++ ++ mutex_lock(>->tlb_invalidate_lock); ++ intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); ++ ++ for_each_engine(engine, gt, id) { ++ /* ++ * HW architecture suggest typical invalidation time at 40us, ++ * with pessimistic cases up to 100us and a recommendation to ++ * cap at 1ms. We go a bit higher just in case. ++ */ ++ const unsigned int timeout_us = 100; ++ const unsigned int timeout_ms = 4; ++ struct reg_and_bit rb; ++ ++ rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); ++ if (!i915_mmio_reg_offset(rb.reg)) ++ continue; ++ ++ intel_uncore_write_fw(uncore, rb.reg, rb.bit); ++ if (__intel_wait_for_register_fw(uncore, ++ rb.reg, rb.bit, 0, ++ timeout_us, timeout_ms, ++ NULL)) ++ drm_err_ratelimited(>->i915->drm, ++ "%s TLB invalidation did not complete in %ums!\n", ++ engine->name, timeout_ms); ++ } ++ ++ intel_uncore_forcewake_put_delayed(uncore, FORCEWAKE_ALL); ++ mutex_unlock(>->tlb_invalidate_lock); ++} +diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h +index 74e771871a9bd..c0169d6017c2d 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt.h ++++ b/drivers/gpu/drm/i915/gt/intel_gt.h +@@ -90,4 +90,6 @@ void intel_gt_info_print(const struct intel_gt_info *info, + + void intel_gt_watchdog_work(struct work_struct *work); + ++void intel_gt_invalidate_tlbs(struct intel_gt *gt); ++ + #endif /* __INTEL_GT_H__ */ +diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h +index a81e21bf1bd1a..9fbcbcc6c35db 100644 +--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h ++++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h +@@ -72,6 +72,8 @@ struct intel_gt { + + struct intel_uc uc; + ++ struct mutex tlb_invalidate_lock; ++ + struct intel_gt_timelines { + spinlock_t lock; /* protects active_list */ + struct list_head active_list; +diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c +index aae609d7d85dd..6b5ab19a2ada9 100644 +--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c ++++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c +@@ -621,13 +621,6 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, + FF_MODE2_GS_TIMER_MASK, + FF_MODE2_GS_TIMER_224, + 0, false); +- +- /* +- * Wa_14012131227:dg1 +- * Wa_1508744258:tgl,rkl,dg1,adl-s,adl-p +- */ +- wa_masked_en(wal, GEN7_COMMON_SLICE_CHICKEN1, +- GEN9_RHWO_OPTIMIZATION_DISABLE); + } + + static void dg1_ctx_workarounds_init(struct intel_engine_cs *engine, +diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +index 65a3e7fdb2b2c..95ff630157b9c 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +@@ -133,7 +133,7 @@ static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id) + { + u32 request[] = { + GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST, +- SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2), ++ SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1), + id, + }; + +diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +index 87d8dc8f51b96..93c9de8f43e8e 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +@@ -148,11 +148,12 @@ static inline void clr_context_registered(struct intel_context *ce) + #define SCHED_STATE_BLOCKED_SHIFT 4 + #define SCHED_STATE_BLOCKED BIT(SCHED_STATE_BLOCKED_SHIFT) + #define SCHED_STATE_BLOCKED_MASK (0xfff << SCHED_STATE_BLOCKED_SHIFT) ++ + static inline void init_sched_state(struct intel_context *ce) + { + /* Only should be called from guc_lrc_desc_pin() */ + atomic_set(&ce->guc_sched_state_no_lock, 0); +- ce->guc_state.sched_state = 0; ++ ce->guc_state.sched_state &= SCHED_STATE_BLOCKED_MASK; + } + + static inline bool +@@ -352,20 +353,29 @@ static inline void set_lrc_desc_registered(struct intel_guc *guc, u32 id, + xa_unlock_irqrestore(&guc->context_lookup, flags); + } + ++static void decr_outstanding_submission_g2h(struct intel_guc *guc) ++{ ++ if (atomic_dec_and_test(&guc->outstanding_submission_g2h)) ++ wake_up_all(&guc->ct.wq); ++} ++ + static int guc_submission_send_busy_loop(struct intel_guc *guc, + const u32 *action, + u32 len, + u32 g2h_len_dw, + bool loop) + { +- int err; +- +- err = intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); ++ /* ++ * We always loop when a send requires a reply (i.e. g2h_len_dw > 0), ++ * so we don't handle the case where we don't get a reply because we ++ * aborted the send due to the channel being busy. ++ */ ++ GEM_BUG_ON(g2h_len_dw && !loop); + +- if (!err && g2h_len_dw) ++ if (g2h_len_dw) + atomic_inc(&guc->outstanding_submission_g2h); + +- return err; ++ return intel_guc_send_busy_loop(guc, action, len, g2h_len_dw, loop); + } + + int intel_guc_wait_for_pending_msg(struct intel_guc *guc, +@@ -616,7 +626,7 @@ static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc) + init_sched_state(ce); + + if (pending_enable || destroyed || deregister) { +- atomic_dec(&guc->outstanding_submission_g2h); ++ decr_outstanding_submission_g2h(guc); + if (deregister) + guc_signal_context_fence(ce); + if (destroyed) { +@@ -635,7 +645,7 @@ static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc) + intel_engine_signal_breadcrumbs(ce->engine); + } + intel_context_sched_disable_unpin(ce); +- atomic_dec(&guc->outstanding_submission_g2h); ++ decr_outstanding_submission_g2h(guc); + spin_lock_irqsave(&ce->guc_state.lock, flags); + guc_blocked_fence_complete(ce); + spin_unlock_irqrestore(&ce->guc_state.lock, flags); +@@ -797,15 +807,13 @@ __unwind_incomplete_requests(struct intel_context *ce) + + spin_lock_irqsave(&sched_engine->lock, flags); + spin_lock(&ce->guc_active.lock); +- list_for_each_entry_safe(rq, rn, +- &ce->guc_active.requests, +- sched.link) { ++ list_for_each_entry_safe_reverse(rq, rn, ++ &ce->guc_active.requests, ++ sched.link) { + if (i915_request_completed(rq)) + continue; + + list_del_init(&rq->sched.link); +- spin_unlock(&ce->guc_active.lock); +- + __i915_request_unsubmit(rq); + + /* Push the request back into the queue for later resubmission. */ +@@ -816,10 +824,8 @@ __unwind_incomplete_requests(struct intel_context *ce) + } + GEM_BUG_ON(i915_sched_engine_is_empty(sched_engine)); + +- list_add_tail(&rq->sched.link, pl); ++ list_add(&rq->sched.link, pl); + set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags); +- +- spin_lock(&ce->guc_active.lock); + } + spin_unlock(&ce->guc_active.lock); + spin_unlock_irqrestore(&sched_engine->lock, flags); +@@ -828,17 +834,33 @@ __unwind_incomplete_requests(struct intel_context *ce) + static void __guc_reset_context(struct intel_context *ce, bool stalled) + { + struct i915_request *rq; ++ unsigned long flags; + u32 head; ++ bool skip = false; + + intel_context_get(ce); + + /* +- * GuC will implicitly mark the context as non-schedulable +- * when it sends the reset notification. Make sure our state +- * reflects this change. The context will be marked enabled +- * on resubmission. ++ * GuC will implicitly mark the context as non-schedulable when it sends ++ * the reset notification. Make sure our state reflects this change. The ++ * context will be marked enabled on resubmission. ++ * ++ * XXX: If the context is reset as a result of the request cancellation ++ * this G2H is received after the schedule disable complete G2H which is ++ * wrong as this creates a race between the request cancellation code ++ * re-submitting the context and this G2H handler. This is a bug in the ++ * GuC but can be worked around in the meantime but converting this to a ++ * NOP if a pending enable is in flight as this indicates that a request ++ * cancellation has occurred. + */ +- clr_context_enabled(ce); ++ spin_lock_irqsave(&ce->guc_state.lock, flags); ++ if (likely(!context_pending_enable(ce))) ++ clr_context_enabled(ce); ++ else ++ skip = true; ++ spin_unlock_irqrestore(&ce->guc_state.lock, flags); ++ if (unlikely(skip)) ++ goto out_put; + + rq = intel_context_find_active_request(ce); + if (!rq) { +@@ -857,6 +879,7 @@ static void __guc_reset_context(struct intel_context *ce, bool stalled) + out_replay: + guc_reset_state(ce, head, stalled); + __unwind_incomplete_requests(ce); ++out_put: + intel_context_put(ce); + } + +@@ -1233,8 +1256,7 @@ static int register_context(struct intel_context *ce, bool loop) + } + + static int __guc_action_deregister_context(struct intel_guc *guc, +- u32 guc_id, +- bool loop) ++ u32 guc_id) + { + u32 action[] = { + INTEL_GUC_ACTION_DEREGISTER_CONTEXT, +@@ -1243,16 +1265,16 @@ static int __guc_action_deregister_context(struct intel_guc *guc, + + return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), + G2H_LEN_DW_DEREGISTER_CONTEXT, +- loop); ++ true); + } + +-static int deregister_context(struct intel_context *ce, u32 guc_id, bool loop) ++static int deregister_context(struct intel_context *ce, u32 guc_id) + { + struct intel_guc *guc = ce_to_guc(ce); + + trace_intel_context_deregister(ce); + +- return __guc_action_deregister_context(guc, guc_id, loop); ++ return __guc_action_deregister_context(guc, guc_id); + } + + static intel_engine_mask_t adjust_engine_mask(u8 class, intel_engine_mask_t mask) +@@ -1340,26 +1362,23 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) + * registering this context. + */ + if (context_registered) { ++ bool disabled; ++ unsigned long flags; ++ + trace_intel_context_steal_guc_id(ce); +- if (!loop) { ++ GEM_BUG_ON(!loop); ++ ++ /* Seal race with Reset */ ++ spin_lock_irqsave(&ce->guc_state.lock, flags); ++ disabled = submission_disabled(guc); ++ if (likely(!disabled)) { + set_context_wait_for_deregister_to_register(ce); + intel_context_get(ce); +- } else { +- bool disabled; +- unsigned long flags; +- +- /* Seal race with Reset */ +- spin_lock_irqsave(&ce->guc_state.lock, flags); +- disabled = submission_disabled(guc); +- if (likely(!disabled)) { +- set_context_wait_for_deregister_to_register(ce); +- intel_context_get(ce); +- } +- spin_unlock_irqrestore(&ce->guc_state.lock, flags); +- if (unlikely(disabled)) { +- reset_lrc_desc(guc, desc_idx); +- return 0; /* Will get registered later */ +- } ++ } ++ spin_unlock_irqrestore(&ce->guc_state.lock, flags); ++ if (unlikely(disabled)) { ++ reset_lrc_desc(guc, desc_idx); ++ return 0; /* Will get registered later */ + } + + /* +@@ -1367,13 +1386,9 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) + * context whose guc_id was stolen. + */ + with_intel_runtime_pm(runtime_pm, wakeref) +- ret = deregister_context(ce, ce->guc_id, loop); +- if (unlikely(ret == -EBUSY)) { +- clr_context_wait_for_deregister_to_register(ce); +- intel_context_put(ce); +- } else if (unlikely(ret == -ENODEV)) { ++ ret = deregister_context(ce, ce->guc_id); ++ if (unlikely(ret == -ENODEV)) + ret = 0; /* Will get registered later */ +- } + } else { + with_intel_runtime_pm(runtime_pm, wakeref) + ret = register_context(ce, loop); +@@ -1548,6 +1563,23 @@ static struct i915_sw_fence *guc_context_block(struct intel_context *ce) + return &ce->guc_blocked; + } + ++#define SCHED_STATE_MULTI_BLOCKED_MASK \ ++ (SCHED_STATE_BLOCKED_MASK & ~SCHED_STATE_BLOCKED) ++#define SCHED_STATE_NO_UNBLOCK \ ++ (SCHED_STATE_MULTI_BLOCKED_MASK | \ ++ SCHED_STATE_PENDING_DISABLE | \ ++ SCHED_STATE_BANNED) ++ ++static bool context_cant_unblock(struct intel_context *ce) ++{ ++ lockdep_assert_held(&ce->guc_state.lock); ++ ++ return (ce->guc_state.sched_state & SCHED_STATE_NO_UNBLOCK) || ++ context_guc_id_invalid(ce) || ++ !lrc_desc_registered(ce_to_guc(ce), ce->guc_id) || ++ !intel_context_is_pinned(ce); ++} ++ + static void guc_context_unblock(struct intel_context *ce) + { + struct intel_guc *guc = ce_to_guc(ce); +@@ -1562,9 +1594,7 @@ static void guc_context_unblock(struct intel_context *ce) + spin_lock_irqsave(&ce->guc_state.lock, flags); + + if (unlikely(submission_disabled(guc) || +- !intel_context_is_pinned(ce) || +- context_pending_disable(ce) || +- context_blocked(ce) > 1)) { ++ context_cant_unblock(ce))) { + enable = false; + } else { + enable = true; +@@ -1601,6 +1631,13 @@ static void guc_context_cancel_request(struct intel_context *ce, + guc_reset_state(ce, intel_ring_wrap(ce->ring, rq->head), + true); + } ++ ++ /* ++ * XXX: Racey if context is reset, see comment in ++ * __guc_reset_context(). ++ */ ++ flush_work(&ce_to_guc(ce)->ct.requests.worker); ++ + guc_context_unblock(ce); + } + } +@@ -1730,7 +1767,7 @@ static inline void guc_lrc_desc_unpin(struct intel_context *ce) + GEM_BUG_ON(context_enabled(ce)); + + clr_context_registered(ce); +- deregister_context(ce, ce->guc_id, true); ++ deregister_context(ce, ce->guc_id); + } + + static void __guc_context_destroy(struct intel_context *ce) +@@ -2583,12 +2620,6 @@ g2h_context_lookup(struct intel_guc *guc, u32 desc_idx) + return ce; + } + +-static void decr_outstanding_submission_g2h(struct intel_guc *guc) +-{ +- if (atomic_dec_and_test(&guc->outstanding_submission_g2h)) +- wake_up_all(&guc->ct.wq); +-} +- + int intel_guc_deregister_done_process_msg(struct intel_guc *guc, + const u32 *msg, + u32 len) +@@ -2721,7 +2752,12 @@ static void guc_handle_context_reset(struct intel_guc *guc, + { + trace_intel_context_reset(ce); + +- if (likely(!intel_context_is_banned(ce))) { ++ /* ++ * XXX: Racey if request cancellation has occurred, see comment in ++ * __guc_reset_context(). ++ */ ++ if (likely(!intel_context_is_banned(ce) && ++ !context_blocked(ce))) { + capture_error_state(guc, ce); + guc_context_replay(ce); + } +diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c +index 1bbd09ad52873..1ad7259fb1f0c 100644 +--- a/drivers/gpu/drm/i915/i915_pci.c ++++ b/drivers/gpu/drm/i915/i915_pci.c +@@ -865,7 +865,7 @@ static const struct intel_device_info jsl_info = { + }, \ + TGL_CURSOR_OFFSETS, \ + .has_global_mocs = 1, \ +- .display.has_dsb = 1 ++ .display.has_dsb = 0 /* FIXME: LUT load is broken with DSB */ + + static const struct intel_device_info tgl_info = { + GEN12_FEATURES, +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 9023d4ecf3b37..c65473fc90935 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -2669,6 +2669,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) + #define GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING (1 << 28) + #define GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT (1 << 24) + ++#define GEN8_RTCR _MMIO(0x4260) ++#define GEN8_M1TCR _MMIO(0x4264) ++#define GEN8_M2TCR _MMIO(0x4268) ++#define GEN8_BTCR _MMIO(0x426c) ++#define GEN8_VTCR _MMIO(0x4270) ++ + #if 0 + #define PRB0_TAIL _MMIO(0x2030) + #define PRB0_HEAD _MMIO(0x2034) +@@ -2763,6 +2769,11 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) + #define FAULT_VA_HIGH_BITS (0xf << 0) + #define FAULT_GTT_SEL (1 << 4) + ++#define GEN12_GFX_TLB_INV_CR _MMIO(0xced8) ++#define GEN12_VD_TLB_INV_CR _MMIO(0xcedc) ++#define GEN12_VE_TLB_INV_CR _MMIO(0xcee0) ++#define GEN12_BLT_TLB_INV_CR _MMIO(0xcee4) ++ + #define GEN12_AUX_ERR_DBG _MMIO(0x43f4) + + #define FPGA_DBG _MMIO(0x42300) +diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c +index 4b7fc4647e460..dfd20060812bc 100644 +--- a/drivers/gpu/drm/i915/i915_vma.c ++++ b/drivers/gpu/drm/i915/i915_vma.c +@@ -434,6 +434,9 @@ int i915_vma_bind(struct i915_vma *vma, + vma->ops->bind_vma(vma->vm, NULL, vma, cache_level, bind_flags); + } + ++ if (vma->obj) ++ set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags); ++ + atomic_or(bind_flags, &vma->flags); + return 0; + } +diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c +index d1d4b97b86f59..287f5a3d0b354 100644 +--- a/drivers/gpu/drm/i915/intel_pch.c ++++ b/drivers/gpu/drm/i915/intel_pch.c +@@ -108,6 +108,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) + /* Comet Lake V PCH is based on KBP, which is SPT compatible */ + return PCH_SPT; + case INTEL_PCH_ICP_DEVICE_ID_TYPE: ++ case INTEL_PCH_ICP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); + return PCH_ICP; +@@ -123,7 +124,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) + !IS_GEN9_BC(dev_priv)); + return PCH_TGP; + case INTEL_PCH_JSP_DEVICE_ID_TYPE: +- case INTEL_PCH_JSP2_DEVICE_ID_TYPE: + drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); + drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); + return PCH_JSP; +diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h +index 7c0d83d292dcc..994c56fcb1991 100644 +--- a/drivers/gpu/drm/i915/intel_pch.h ++++ b/drivers/gpu/drm/i915/intel_pch.h +@@ -50,11 +50,11 @@ enum intel_pch { + #define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 + #define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 + #define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 ++#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880 + #define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 + #define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 + #define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 + #define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 +-#define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880 + #define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80 + #define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 + #define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index a725792d5248b..9c5e4758947b6 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -3063,9 +3063,9 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv) + * The BIOS provided WM memory latency values are often + * inadequate for high resolution displays. Adjust them. + */ +- changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) | +- ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12) | +- ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12); ++ changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12); ++ changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12); ++ changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12); + + if (!changed) + return; +@@ -4020,6 +4020,17 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state) + return ret; + } + ++ if (intel_can_enable_sagv(dev_priv, new_bw_state) != ++ intel_can_enable_sagv(dev_priv, old_bw_state)) { ++ ret = intel_atomic_serialize_global_state(&new_bw_state->base); ++ if (ret) ++ return ret; ++ } else if (new_bw_state->pipe_sagv_reject != old_bw_state->pipe_sagv_reject) { ++ ret = intel_atomic_lock_global_state(&new_bw_state->base); ++ if (ret) ++ return ret; ++ } ++ + for_each_new_intel_crtc_in_state(state, crtc, + new_crtc_state, i) { + struct skl_pipe_wm *pipe_wm = &new_crtc_state->wm.skl.optimal; +@@ -4035,17 +4046,6 @@ static int intel_compute_sagv_mask(struct intel_atomic_state *state) + intel_can_enable_sagv(dev_priv, new_bw_state); + } + +- if (intel_can_enable_sagv(dev_priv, new_bw_state) != +- intel_can_enable_sagv(dev_priv, old_bw_state)) { +- ret = intel_atomic_serialize_global_state(&new_bw_state->base); +- if (ret) +- return ret; +- } else if (new_bw_state->pipe_sagv_reject != old_bw_state->pipe_sagv_reject) { +- ret = intel_atomic_lock_global_state(&new_bw_state->base); +- if (ret) +- return ret; +- } +- + return 0; + } + +@@ -4708,6 +4708,10 @@ static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = { + }; + + static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = { ++ /* ++ * Keep the join_mbus cases first so check_mbus_joined() ++ * will prefer them over the !join_mbus cases. ++ */ + { + .active_pipes = BIT(PIPE_A), + .dbuf_mask = { +@@ -4722,6 +4726,20 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = { + }, + .join_mbus = true, + }, ++ { ++ .active_pipes = BIT(PIPE_A), ++ .dbuf_mask = { ++ [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), ++ }, ++ .join_mbus = false, ++ }, ++ { ++ .active_pipes = BIT(PIPE_B), ++ .dbuf_mask = { ++ [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), ++ }, ++ .join_mbus = false, ++ }, + { + .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), + .dbuf_mask = { +@@ -4826,7 +4844,7 @@ static bool check_mbus_joined(u8 active_pipes, + { + int i; + +- for (i = 0; i < dbuf_slices[i].active_pipes; i++) { ++ for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { + if (dbuf_slices[i].active_pipes == active_pipes) + return dbuf_slices[i].join_mbus; + } +@@ -4838,13 +4856,14 @@ static bool adlp_check_mbus_joined(u8 active_pipes) + return check_mbus_joined(active_pipes, adlp_allowed_dbufs); + } + +-static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, ++static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus, + const struct dbuf_slice_conf_entry *dbuf_slices) + { + int i; + +- for (i = 0; i < dbuf_slices[i].active_pipes; i++) { +- if (dbuf_slices[i].active_pipes == active_pipes) ++ for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { ++ if (dbuf_slices[i].active_pipes == active_pipes && ++ dbuf_slices[i].join_mbus == join_mbus) + return dbuf_slices[i].dbuf_mask[pipe]; + } + return 0; +@@ -4855,7 +4874,7 @@ static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, + * returns correspondent DBuf slice mask as stated in BSpec for particular + * platform. + */ +-static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes) ++static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) + { + /* + * FIXME: For ICL this is still a bit unclear as prev BSpec revision +@@ -4869,37 +4888,41 @@ static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes) + * still here - we will need it once those additional constraints + * pop up. + */ +- return compute_dbuf_slices(pipe, active_pipes, icl_allowed_dbufs); ++ return compute_dbuf_slices(pipe, active_pipes, join_mbus, ++ icl_allowed_dbufs); + } + +-static u8 tgl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes) ++static u8 tgl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) + { +- return compute_dbuf_slices(pipe, active_pipes, tgl_allowed_dbufs); ++ return compute_dbuf_slices(pipe, active_pipes, join_mbus, ++ tgl_allowed_dbufs); + } + +-static u32 adlp_compute_dbuf_slices(enum pipe pipe, u32 active_pipes) ++static u8 adlp_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) + { +- return compute_dbuf_slices(pipe, active_pipes, adlp_allowed_dbufs); ++ return compute_dbuf_slices(pipe, active_pipes, join_mbus, ++ adlp_allowed_dbufs); + } + +-static u32 dg2_compute_dbuf_slices(enum pipe pipe, u32 active_pipes) ++static u8 dg2_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) + { +- return compute_dbuf_slices(pipe, active_pipes, dg2_allowed_dbufs); ++ return compute_dbuf_slices(pipe, active_pipes, join_mbus, ++ dg2_allowed_dbufs); + } + +-static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes) ++static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool join_mbus) + { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + + if (IS_DG2(dev_priv)) +- return dg2_compute_dbuf_slices(pipe, active_pipes); ++ return dg2_compute_dbuf_slices(pipe, active_pipes, join_mbus); + else if (IS_ALDERLAKE_P(dev_priv)) +- return adlp_compute_dbuf_slices(pipe, active_pipes); ++ return adlp_compute_dbuf_slices(pipe, active_pipes, join_mbus); + else if (DISPLAY_VER(dev_priv) == 12) +- return tgl_compute_dbuf_slices(pipe, active_pipes); ++ return tgl_compute_dbuf_slices(pipe, active_pipes, join_mbus); + else if (DISPLAY_VER(dev_priv) == 11) +- return icl_compute_dbuf_slices(pipe, active_pipes); ++ return icl_compute_dbuf_slices(pipe, active_pipes, join_mbus); + /* + * For anything else just return one slice yet. + * Should be extended for other platforms. +@@ -6110,11 +6133,16 @@ skl_compute_ddb(struct intel_atomic_state *state) + return ret; + } + ++ if (IS_ALDERLAKE_P(dev_priv)) ++ new_dbuf_state->joined_mbus = ++ adlp_check_mbus_joined(new_dbuf_state->active_pipes); ++ + for_each_intel_crtc(&dev_priv->drm, crtc) { + enum pipe pipe = crtc->pipe; + + new_dbuf_state->slices[pipe] = +- skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes); ++ skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes, ++ new_dbuf_state->joined_mbus); + + if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe]) + continue; +@@ -6126,9 +6154,6 @@ skl_compute_ddb(struct intel_atomic_state *state) + + new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state); + +- if (IS_ALDERLAKE_P(dev_priv)) +- new_dbuf_state->joined_mbus = adlp_check_mbus_joined(new_dbuf_state->active_pipes); +- + if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices || + old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { + ret = intel_atomic_serialize_global_state(&new_dbuf_state->base); +@@ -6609,6 +6634,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) + enum pipe pipe = crtc->pipe; + unsigned int mbus_offset; + enum plane_id plane_id; ++ u8 slices; + + skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal); + crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal; +@@ -6628,19 +6654,22 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) + skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_uv); + } + +- dbuf_state->slices[pipe] = +- skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes); +- + dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state); + + /* + * Used for checking overlaps, so we need absolute + * offsets instead of MBUS relative offsets. + */ +- mbus_offset = mbus_ddb_offset(dev_priv, dbuf_state->slices[pipe]); ++ slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes, ++ dbuf_state->joined_mbus); ++ mbus_offset = mbus_ddb_offset(dev_priv, slices); + crtc_state->wm.skl.ddb.start = mbus_offset + dbuf_state->ddb[pipe].start; + crtc_state->wm.skl.ddb.end = mbus_offset + dbuf_state->ddb[pipe].end; + ++ /* The slices actually used by the planes on the pipe */ ++ dbuf_state->slices[pipe] = ++ skl_ddb_dbuf_slice_mask(dev_priv, &crtc_state->wm.skl.ddb); ++ + drm_dbg_kms(&dev_priv->drm, + "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n", + crtc->base.base.id, crtc->base.name, +diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c +index 6b38bc2811c1b..de8d0558389c4 100644 +--- a/drivers/gpu/drm/i915/intel_uncore.c ++++ b/drivers/gpu/drm/i915/intel_uncore.c +@@ -718,7 +718,8 @@ void intel_uncore_forcewake_get__locked(struct intel_uncore *uncore, + } + + static void __intel_uncore_forcewake_put(struct intel_uncore *uncore, +- enum forcewake_domains fw_domains) ++ enum forcewake_domains fw_domains, ++ bool delayed) + { + struct intel_uncore_forcewake_domain *domain; + unsigned int tmp; +@@ -733,7 +734,11 @@ static void __intel_uncore_forcewake_put(struct intel_uncore *uncore, + continue; + } + +- uncore->funcs.force_wake_put(uncore, domain->mask); ++ if (delayed && ++ !(domain->uncore->fw_domains_timer & domain->mask)) ++ fw_domain_arm_timer(domain); ++ else ++ uncore->funcs.force_wake_put(uncore, domain->mask); + } + } + +@@ -754,7 +759,20 @@ void intel_uncore_forcewake_put(struct intel_uncore *uncore, + return; + + spin_lock_irqsave(&uncore->lock, irqflags); +- __intel_uncore_forcewake_put(uncore, fw_domains); ++ __intel_uncore_forcewake_put(uncore, fw_domains, false); ++ spin_unlock_irqrestore(&uncore->lock, irqflags); ++} ++ ++void intel_uncore_forcewake_put_delayed(struct intel_uncore *uncore, ++ enum forcewake_domains fw_domains) ++{ ++ unsigned long irqflags; ++ ++ if (!uncore->funcs.force_wake_put) ++ return; ++ ++ spin_lock_irqsave(&uncore->lock, irqflags); ++ __intel_uncore_forcewake_put(uncore, fw_domains, true); + spin_unlock_irqrestore(&uncore->lock, irqflags); + } + +@@ -796,7 +814,7 @@ void intel_uncore_forcewake_put__locked(struct intel_uncore *uncore, + if (!uncore->funcs.force_wake_put) + return; + +- __intel_uncore_forcewake_put(uncore, fw_domains); ++ __intel_uncore_forcewake_put(uncore, fw_domains, false); + } + + void assert_forcewakes_inactive(struct intel_uncore *uncore) +diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h +index 3c0b0a8b5250d..4c63209dcf530 100644 +--- a/drivers/gpu/drm/i915/intel_uncore.h ++++ b/drivers/gpu/drm/i915/intel_uncore.h +@@ -229,6 +229,8 @@ void intel_uncore_forcewake_get(struct intel_uncore *uncore, + enum forcewake_domains domains); + void intel_uncore_forcewake_put(struct intel_uncore *uncore, + enum forcewake_domains domains); ++void intel_uncore_forcewake_put_delayed(struct intel_uncore *uncore, ++ enum forcewake_domains domains); + void intel_uncore_forcewake_flush(struct intel_uncore *uncore, + enum forcewake_domains fw_domains); + +diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c +index 9558e9e1b431b..cb685fe2039b4 100644 +--- a/drivers/gpu/drm/imx/imx-drm-core.c ++++ b/drivers/gpu/drm/imx/imx-drm-core.c +@@ -81,7 +81,6 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) + struct drm_plane_state *old_plane_state, *new_plane_state; + bool plane_disabling = false; + int i; +- bool fence_cookie = dma_fence_begin_signalling(); + + drm_atomic_helper_commit_modeset_disables(dev, state); + +@@ -112,7 +111,6 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) + } + + drm_atomic_helper_commit_hw_done(state); +- dma_fence_end_signalling(fence_cookie); + } + + static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { +diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c +index 00404ba4126dd..2735b8eb35376 100644 +--- a/drivers/gpu/drm/kmb/kmb_plane.c ++++ b/drivers/gpu/drm/kmb/kmb_plane.c +@@ -158,12 +158,6 @@ static void kmb_plane_atomic_disable(struct drm_plane *plane, + case LAYER_1: + kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL2_ENABLE; + break; +- case LAYER_2: +- kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL1_ENABLE; +- break; +- case LAYER_3: +- kmb->plane_status[plane_id].ctrl = LCD_CTRL_GL2_ENABLE; +- break; + } + + kmb->plane_status[plane_id].disable = true; +diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c +index 65fdca366e41f..36c9905894278 100644 +--- a/drivers/gpu/drm/lima/lima_device.c ++++ b/drivers/gpu/drm/lima/lima_device.c +@@ -357,6 +357,7 @@ int lima_device_init(struct lima_device *ldev) + int err, i; + + dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32)); ++ dma_set_max_seg_size(ldev->dev, UINT_MAX); + + err = lima_clk_init(ldev); + if (err) +diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c +index 93b40c245f007..5d90d2eb00193 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dsi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c +@@ -11,6 +11,7 @@ + #include <linux/of_platform.h> + #include <linux/phy/phy.h> + #include <linux/platform_device.h> ++#include <linux/reset.h> + + #include <video/mipi_display.h> + #include <video/videomode.h> +@@ -980,8 +981,10 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) + struct mtk_dsi *dsi = dev_get_drvdata(dev); + + ret = mtk_dsi_encoder_init(drm, dsi); ++ if (ret) ++ return ret; + +- return ret; ++ return device_reset_optional(dev); + } + + static void mtk_dsi_unbind(struct device *dev, struct device *master, +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 5838c44cbf6f0..3196189429bcf 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -1224,12 +1224,14 @@ static int mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, + return MODE_BAD; + } + +- if (hdmi->conf->cea_modes_only && !drm_match_cea_mode(mode)) +- return MODE_BAD; ++ if (hdmi->conf) { ++ if (hdmi->conf->cea_modes_only && !drm_match_cea_mode(mode)) ++ return MODE_BAD; + +- if (hdmi->conf->max_mode_clock && +- mode->clock > hdmi->conf->max_mode_clock) +- return MODE_CLOCK_HIGH; ++ if (hdmi->conf->max_mode_clock && ++ mode->clock > hdmi->conf->max_mode_clock) ++ return MODE_CLOCK_HIGH; ++ } + + if (mode->clock < 27000) + return MODE_CLOCK_LOW; +diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig +index 3ddf739a6f9b8..c49b239231190 100644 +--- a/drivers/gpu/drm/msm/Kconfig ++++ b/drivers/gpu/drm/msm/Kconfig +@@ -63,6 +63,7 @@ config DRM_MSM_HDMI_HDCP + config DRM_MSM_DP + bool "Enable DisplayPort support in MSM DRM driver" + depends on DRM_MSM ++ select RATIONAL + default y + help + Compile in support for DP driver in MSM DRM driver. DP external +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +index 8b73f70766a47..4347a104755a9 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +@@ -516,11 +516,11 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct platform_device *pdev = to_platform_device(gmu->dev); + void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc"); +- void __iomem *seqptr; ++ void __iomem *seqptr = NULL; + uint32_t pdc_address_offset; + bool pdc_in_aop = false; + +- if (!pdcptr) ++ if (IS_ERR(pdcptr)) + goto err; + + if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu)) +@@ -532,7 +532,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu) + + if (!pdc_in_aop) { + seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq"); +- if (!seqptr) ++ if (IS_ERR(seqptr)) + goto err; + } + +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +index 267a880811d65..b681c45520bbd 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +@@ -1424,17 +1424,24 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) + { + struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; +- u32 gpu_scid, cntl1_regval = 0; ++ u32 cntl1_regval = 0; + + if (IS_ERR(a6xx_gpu->llc_mmio)) + return; + + if (!llcc_slice_activate(a6xx_gpu->llc_slice)) { +- gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); ++ u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); + + gpu_scid &= 0x1f; + cntl1_regval = (gpu_scid << 0) | (gpu_scid << 5) | (gpu_scid << 10) | + (gpu_scid << 15) | (gpu_scid << 20); ++ ++ /* On A660, the SCID programming for UCHE traffic is done in ++ * A6XX_GBIF_SCACHE_CNTL0[14:10] ++ */ ++ if (adreno_is_a660_family(adreno_gpu)) ++ gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | ++ (1 << 8), (gpu_scid << 10) | (1 << 8)); + } + + /* +@@ -1471,13 +1478,6 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) + } + + gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval); +- +- /* On A660, the SCID programming for UCHE traffic is done in +- * A6XX_GBIF_SCACHE_CNTL0[14:10] +- */ +- if (adreno_is_a660_family(adreno_gpu)) +- gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | +- (1 << 8), (gpu_scid << 10) | (1 << 8)); + } + + static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) +@@ -1557,6 +1557,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) + for (i = 0; i < gpu->nr_rings; i++) + a6xx_gpu->shadow[i] = 0; + ++ gpu->suspend_count++; ++ + return 0; + } + +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +index e8f65cd8eca6e..bfac7e47cb396 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +@@ -777,12 +777,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + a6xx_state->gmu_registers = state_kcalloc(a6xx_state, +- 2, sizeof(*a6xx_state->gmu_registers)); ++ 3, sizeof(*a6xx_state->gmu_registers)); + + if (!a6xx_state->gmu_registers) + return; + +- a6xx_state->nr_gmu_registers = 2; ++ a6xx_state->nr_gmu_registers = 3; + + /* Get the CX GMU registers from AHB */ + _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +index a98e964c3b6fa..355894a3b48c3 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c +@@ -26,9 +26,16 @@ static void dpu_setup_dspp_pcc(struct dpu_hw_dspp *ctx, + struct dpu_hw_pcc_cfg *cfg) + { + +- u32 base = ctx->cap->sblk->pcc.base; ++ u32 base; + +- if (!ctx || !base) { ++ if (!ctx) { ++ DRM_ERROR("invalid ctx %pK\n", ctx); ++ return; ++ } ++ ++ base = ctx->cap->sblk->pcc.base; ++ ++ if (!base) { + DRM_ERROR("invalid ctx %pK pcc base 0x%x\n", ctx, base); + return; + } +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +index 69eed79324865..f9460672176aa 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +@@ -138,11 +138,13 @@ static int _sspp_subblk_offset(struct dpu_hw_pipe *ctx, + u32 *idx) + { + int rc = 0; +- const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk; ++ const struct dpu_sspp_sub_blks *sblk; + +- if (!ctx) ++ if (!ctx || !ctx->cap || !ctx->cap->sblk) + return -EINVAL; + ++ sblk = ctx->cap->sblk; ++ + switch (s_id) { + case DPU_SSPP_SRC: + *idx = sblk->src_blk.base; +@@ -419,7 +421,7 @@ static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_pipe *ctx, + + (void)pe; + if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp +- || !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk) ++ || !scaler3_cfg) + return; + + dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx, +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +index ae48f41821cfe..93d916858d5ad 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +@@ -73,8 +73,8 @@ static int _dpu_danger_signal_status(struct seq_file *s, + &status); + } else { + seq_puts(s, "\nSafe signal status:\n"); +- if (kms->hw_mdp->ops.get_danger_status) +- kms->hw_mdp->ops.get_danger_status(kms->hw_mdp, ++ if (kms->hw_mdp->ops.get_safe_status) ++ kms->hw_mdp->ops.get_safe_status(kms->hw_mdp, + &status); + } + pm_runtime_put_sync(&kms->pdev->dev); +@@ -908,6 +908,10 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms) + return 0; + + mmu = msm_iommu_new(dpu_kms->dev->dev, domain); ++ if (IS_ERR(mmu)) { ++ iommu_domain_free(domain); ++ return PTR_ERR(mmu); ++ } + aspace = msm_gem_address_space_create(mmu, "dpu1", + 0x1000, 0x100000000 - 0x1000); + +diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c +index eb40d8413bca9..6d36f63c33388 100644 +--- a/drivers/gpu/drm/msm/dp/dp_aux.c ++++ b/drivers/gpu/drm/msm/dp/dp_aux.c +@@ -33,6 +33,7 @@ struct dp_aux_private { + bool read; + bool no_send_addr; + bool no_send_stop; ++ bool initted; + u32 offset; + u32 segment; + +@@ -331,6 +332,10 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, + } + + mutex_lock(&aux->mutex); ++ if (!aux->initted) { ++ ret = -EIO; ++ goto exit; ++ } + + dp_aux_update_offset_and_segment(aux, msg); + dp_aux_transfer_helper(aux, msg, true); +@@ -380,6 +385,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, + } + + aux->cmd_busy = false; ++ ++exit: + mutex_unlock(&aux->mutex); + + return ret; +@@ -431,8 +438,13 @@ void dp_aux_init(struct drm_dp_aux *dp_aux) + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + ++ mutex_lock(&aux->mutex); ++ + dp_catalog_aux_enable(aux->catalog, true); + aux->retry_cnt = 0; ++ aux->initted = true; ++ ++ mutex_unlock(&aux->mutex); + } + + void dp_aux_deinit(struct drm_dp_aux *dp_aux) +@@ -441,7 +453,12 @@ void dp_aux_deinit(struct drm_dp_aux *dp_aux) + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + ++ mutex_lock(&aux->mutex); ++ ++ aux->initted = false; + dp_catalog_aux_enable(aux->catalog, false); ++ ++ mutex_unlock(&aux->mutex); + } + + int dp_aux_register(struct drm_dp_aux *dp_aux) +diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c +index 75ae3008b68f4..122fadcf7cc1e 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi.c ++++ b/drivers/gpu/drm/msm/dsi/dsi.c +@@ -40,7 +40,12 @@ static int dsi_get_phy(struct msm_dsi *msm_dsi) + + of_node_put(phy_node); + +- if (!phy_pdev || !msm_dsi->phy) { ++ if (!phy_pdev) { ++ DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__); ++ return -EPROBE_DEFER; ++ } ++ if (!msm_dsi->phy) { ++ put_device(&phy_pdev->dev); + DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__); + return -EPROBE_DEFER; + } +@@ -215,9 +220,13 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, + goto fail; + } + +- if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) { +- ret = -EINVAL; +- goto fail; ++ if (msm_dsi_is_bonded_dsi(msm_dsi) && ++ !msm_dsi_is_master_dsi(msm_dsi)) { ++ /* ++ * Do not return an eror here, ++ * Just skip creating encoder/connector for the slave-DSI. ++ */ ++ return 0; + } + + msm_dsi->encoder = encoder; +diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h +index b50db91cb8a7e..a63666e59d19e 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi.h ++++ b/drivers/gpu/drm/msm/dsi/dsi.h +@@ -82,7 +82,6 @@ int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg); + bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len); + int msm_dsi_manager_register(struct msm_dsi *msm_dsi); + void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); +-bool msm_dsi_manager_validate_current_config(u8 id); + void msm_dsi_manager_tpg_enable(void); + + /* msm dsi */ +@@ -107,6 +106,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, + u32 dma_base, u32 len); + int msm_dsi_host_enable(struct mipi_dsi_host *host); + int msm_dsi_host_disable(struct mipi_dsi_host *host); ++void msm_dsi_host_enable_irq(struct mipi_dsi_host *host); ++void msm_dsi_host_disable_irq(struct mipi_dsi_host *host); + int msm_dsi_host_power_on(struct mipi_dsi_host *host, + struct msm_dsi_phy_shared_timings *phy_shared_timings, + bool is_bonded_dsi, struct msm_dsi_phy *phy); +diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c +index c86b5090fae60..dc85974c78975 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_host.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_host.c +@@ -115,16 +115,16 @@ struct msm_dsi_host { + struct clk *pixel_clk_src; + struct clk *byte_intf_clk; + +- u32 byte_clk_rate; +- u32 pixel_clk_rate; +- u32 esc_clk_rate; ++ unsigned long byte_clk_rate; ++ unsigned long pixel_clk_rate; ++ unsigned long esc_clk_rate; + + /* DSI v2 specific clocks */ + struct clk *src_clk; + struct clk *esc_clk_src; + struct clk *dsi_clk_src; + +- u32 src_clk_rate; ++ unsigned long src_clk_rate; + + struct gpio_desc *disp_en_gpio; + struct gpio_desc *te_gpio; +@@ -498,10 +498,10 @@ int msm_dsi_runtime_resume(struct device *dev) + + int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) + { +- u32 byte_intf_rate; ++ unsigned long byte_intf_rate; + int ret; + +- DBG("Set clk rates: pclk=%d, byteclk=%d", ++ DBG("Set clk rates: pclk=%d, byteclk=%lu", + msm_host->mode->clock, msm_host->byte_clk_rate); + + ret = dev_pm_opp_set_rate(&msm_host->pdev->dev, +@@ -583,7 +583,7 @@ int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host) + { + int ret; + +- DBG("Set clk rates: pclk=%d, byteclk=%d, esc_clk=%d, dsi_src_clk=%d", ++ DBG("Set clk rates: pclk=%d, byteclk=%lu, esc_clk=%lu, dsi_src_clk=%lu", + msm_host->mode->clock, msm_host->byte_clk_rate, + msm_host->esc_clk_rate, msm_host->src_clk_rate); + +@@ -673,10 +673,10 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) + clk_disable_unprepare(msm_host->byte_clk); + } + +-static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bonded_dsi) ++static unsigned long dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + { + struct drm_display_mode *mode = msm_host->mode; +- u32 pclk_rate; ++ unsigned long pclk_rate; + + pclk_rate = mode->clock * 1000; + +@@ -696,7 +696,7 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + { + u8 lanes = msm_host->lanes; + u32 bpp = dsi_get_bpp(msm_host->format); +- u32 pclk_rate = dsi_get_pclk_rate(msm_host, is_bonded_dsi); ++ unsigned long pclk_rate = dsi_get_pclk_rate(msm_host, is_bonded_dsi); + u64 pclk_bpp = (u64)pclk_rate * bpp; + + if (lanes == 0) { +@@ -713,7 +713,7 @@ static void dsi_calc_pclk(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + msm_host->pixel_clk_rate = pclk_rate; + msm_host->byte_clk_rate = pclk_bpp; + +- DBG("pclk=%d, bclk=%d", msm_host->pixel_clk_rate, ++ DBG("pclk=%lu, bclk=%lu", msm_host->pixel_clk_rate, + msm_host->byte_clk_rate); + + } +@@ -772,7 +772,7 @@ int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi) + + msm_host->esc_clk_rate = msm_host->byte_clk_rate / esc_div; + +- DBG("esc=%d, src=%d", msm_host->esc_clk_rate, ++ DBG("esc=%lu, src=%lu", msm_host->esc_clk_rate, + msm_host->src_clk_rate); + + return 0; +@@ -1696,6 +1696,8 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, + if (!prop) { + DRM_DEV_DEBUG(dev, + "failed to find data lane mapping, using default\n"); ++ /* Set the number of date lanes to 4 by default. */ ++ msm_host->num_data_lanes = 4; + return 0; + } + +@@ -1898,6 +1900,23 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) + return ret; + } + ++ msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); ++ if (msm_host->irq < 0) { ++ ret = msm_host->irq; ++ dev_err(&pdev->dev, "failed to get irq: %d\n", ret); ++ return ret; ++ } ++ ++ /* do not autoenable, will be enabled later */ ++ ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, ++ IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, ++ "dsi_isr", msm_host); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", ++ msm_host->irq, ret); ++ return ret; ++ } ++ + init_completion(&msm_host->dma_comp); + init_completion(&msm_host->video_comp); + mutex_init(&msm_host->dev_mutex); +@@ -1941,25 +1960,8 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, + { + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; +- struct platform_device *pdev = msm_host->pdev; + int ret; + +- msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); +- if (msm_host->irq < 0) { +- ret = msm_host->irq; +- DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret); +- return ret; +- } +- +- ret = devm_request_irq(&pdev->dev, msm_host->irq, +- dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, +- "dsi_isr", msm_host); +- if (ret < 0) { +- DRM_DEV_ERROR(&pdev->dev, "failed to request IRQ%u: %d\n", +- msm_host->irq, ret); +- return ret; +- } +- + msm_host->dev = dev; + ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); + if (ret) { +@@ -2315,6 +2317,20 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, + clk_req->escclk_rate = msm_host->esc_clk_rate; + } + ++void msm_dsi_host_enable_irq(struct mipi_dsi_host *host) ++{ ++ struct msm_dsi_host *msm_host = to_msm_dsi_host(host); ++ ++ enable_irq(msm_host->irq); ++} ++ ++void msm_dsi_host_disable_irq(struct mipi_dsi_host *host) ++{ ++ struct msm_dsi_host *msm_host = to_msm_dsi_host(host); ++ ++ disable_irq(msm_host->irq); ++} ++ + int msm_dsi_host_enable(struct mipi_dsi_host *host) + { + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); +diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c +index c41d39f5b7cf4..fa4c396df6a92 100644 +--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c ++++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c +@@ -377,6 +377,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) + } + } + ++ /* ++ * Enable before preparing the panel, disable after unpreparing, so ++ * that the panel can communicate over the DSI link. ++ */ ++ msm_dsi_host_enable_irq(host); ++ if (is_bonded_dsi && msm_dsi1) ++ msm_dsi_host_enable_irq(msm_dsi1->host); ++ + /* Always call panel functions once, because even for dual panels, + * there is only one drm_panel instance. + */ +@@ -411,6 +419,10 @@ host_en_fail: + if (panel) + drm_panel_unprepare(panel); + panel_prep_fail: ++ msm_dsi_host_disable_irq(host); ++ if (is_bonded_dsi && msm_dsi1) ++ msm_dsi_host_disable_irq(msm_dsi1->host); ++ + if (is_bonded_dsi && msm_dsi1) + msm_dsi_host_power_off(msm_dsi1->host); + host1_on_fail: +@@ -523,6 +535,10 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) + id, ret); + } + ++ msm_dsi_host_disable_irq(host); ++ if (is_bonded_dsi && msm_dsi1) ++ msm_dsi_host_disable_irq(msm_dsi1->host); ++ + /* Save PHY status if it is a clock source */ + msm_dsi_phy_pll_save_state(msm_dsi->phy); + +@@ -631,23 +647,6 @@ fail: + return ERR_PTR(ret); + } + +-bool msm_dsi_manager_validate_current_config(u8 id) +-{ +- bool is_bonded_dsi = IS_BONDED_DSI(); +- +- /* +- * For bonded DSI, we only have one drm panel. For this +- * use case, we register only one bridge/connector. +- * Skip bridge/connector initialisation if it is +- * slave-DSI for bonded DSI configuration. +- */ +- if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) { +- DBG("Skip bridge registration for slave DSI->id: %d\n", id); +- return false; +- } +- return true; +-} +- + /* initialize bridge */ + struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) + { +diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +index 8c65ef6968caf..a878b8b079c64 100644 +--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c ++++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +@@ -806,12 +806,14 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, + struct msm_dsi_phy_clk_request *clk_req, + struct msm_dsi_phy_shared_timings *shared_timings) + { +- struct device *dev = &phy->pdev->dev; ++ struct device *dev; + int ret; + + if (!phy || !phy->cfg->ops.enable) + return -EINVAL; + ++ dev = &phy->pdev->dev; ++ + ret = dsi_phy_enable_resource(phy); + if (ret) { + DRM_DEV_ERROR(dev, "%s: resource enable failed, %d\n", +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c +index 737453b6e5966..94f948ef279d1 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c +@@ -97,10 +97,15 @@ static int msm_hdmi_get_phy(struct hdmi *hdmi) + + of_node_put(phy_node); + +- if (!phy_pdev || !hdmi->phy) { ++ if (!phy_pdev) { + DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n"); + return -EPROBE_DEFER; + } ++ if (!hdmi->phy) { ++ DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n"); ++ put_device(&phy_pdev->dev); ++ return -EPROBE_DEFER; ++ } + + hdmi->phy_dev = get_device(&phy_pdev->dev); + +diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c +index 09d2d279c30ae..dee13fedee3b5 100644 +--- a/drivers/gpu/drm/msm/msm_debugfs.c ++++ b/drivers/gpu/drm/msm/msm_debugfs.c +@@ -77,6 +77,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file) + goto free_priv; + + pm_runtime_get_sync(&gpu->pdev->dev); ++ msm_gpu_hw_init(gpu); + show_priv->state = gpu->funcs->gpu_state_get(gpu); + pm_runtime_put_sync(&gpu->pdev->dev); + +diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c +index d4e09703a87db..bbf999c665174 100644 +--- a/drivers/gpu/drm/msm/msm_drv.c ++++ b/drivers/gpu/drm/msm/msm_drv.c +@@ -437,7 +437,7 @@ static int msm_init_vram(struct drm_device *dev) + of_node_put(node); + if (ret) + return ret; +- size = r.end - r.start; ++ size = r.end - r.start + 1; + DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start); + + /* if we have no IOMMU, then we need to use carveout allocator. +@@ -938,29 +938,18 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, + return ret; + } + +-static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, +- struct drm_file *file) ++static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, ++ ktime_t timeout) + { +- struct msm_drm_private *priv = dev->dev_private; +- struct drm_msm_wait_fence *args = data; +- ktime_t timeout = to_ktime(args->timeout); +- struct msm_gpu_submitqueue *queue; +- struct msm_gpu *gpu = priv->gpu; + struct dma_fence *fence; + int ret; + +- if (args->pad) { +- DRM_ERROR("invalid pad: %08x\n", args->pad); ++ if (fence_id > queue->last_fence) { ++ DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n", ++ fence_id, queue->last_fence); + return -EINVAL; + } + +- if (!gpu) +- return 0; +- +- queue = msm_submitqueue_get(file->driver_priv, args->queueid); +- if (!queue) +- return -ENOENT; +- + /* + * Map submitqueue scoped "seqno" (which is actually an idr key) + * back to underlying dma-fence +@@ -972,7 +961,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, + ret = mutex_lock_interruptible(&queue->lock); + if (ret) + return ret; +- fence = idr_find(&queue->fence_idr, args->fence); ++ fence = idr_find(&queue->fence_idr, fence_id); + if (fence) + fence = dma_fence_get_rcu(fence); + mutex_unlock(&queue->lock); +@@ -988,6 +977,32 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, + } + + dma_fence_put(fence); ++ ++ return ret; ++} ++ ++static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, ++ struct drm_file *file) ++{ ++ struct msm_drm_private *priv = dev->dev_private; ++ struct drm_msm_wait_fence *args = data; ++ struct msm_gpu_submitqueue *queue; ++ int ret; ++ ++ if (args->pad) { ++ DRM_ERROR("invalid pad: %08x\n", args->pad); ++ return -EINVAL; ++ } ++ ++ if (!priv->gpu) ++ return 0; ++ ++ queue = msm_submitqueue_get(file->driver_priv, args->queueid); ++ if (!queue) ++ return -ENOENT; ++ ++ ret = wait_fence(queue, args->fence, to_ktime(args->timeout)); ++ + msm_submitqueue_put(queue); + + return ret; +diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c +index 22308a1b66fc3..cb52ac01e5122 100644 +--- a/drivers/gpu/drm/msm/msm_gem.c ++++ b/drivers/gpu/drm/msm/msm_gem.c +@@ -1055,8 +1055,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct + { + struct msm_gem_object *msm_obj = to_msm_bo(obj); + +- vma->vm_flags &= ~VM_PFNMAP; +- vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND; ++ vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags)); + + return 0; +@@ -1132,6 +1131,7 @@ static int msm_gem_new_impl(struct drm_device *dev, + msm_obj->flags = flags; + msm_obj->madv = MSM_MADV_WILLNEED; + ++ INIT_LIST_HEAD(&msm_obj->node); + INIT_LIST_HEAD(&msm_obj->vmas); + + *obj = &msm_obj->base; +@@ -1166,7 +1166,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32 + + ret = msm_gem_new_impl(dev, size, flags, &obj); + if (ret) +- goto fail; ++ return ERR_PTR(ret); + + msm_obj = to_msm_bo(obj); + +@@ -1250,7 +1250,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, + + ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj); + if (ret) +- goto fail; ++ return ERR_PTR(ret); + + drm_gem_private_object_init(dev, obj, size); + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index 151d19e4453cd..7fb7ff043bcd7 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -780,6 +780,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + args->nr_cmds); + if (IS_ERR(submit)) { + ret = PTR_ERR(submit); ++ submit = NULL; + goto out_unlock; + } + +@@ -886,7 +887,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + * to the underlying fence. + */ + submit->fence_id = idr_alloc_cyclic(&queue->fence_idr, +- submit->user_fence, 0, INT_MAX, GFP_KERNEL); ++ submit->user_fence, 1, INT_MAX, GFP_KERNEL); + if (submit->fence_id < 0) { + ret = submit->fence_id = 0; + submit->fence_id = 0; +@@ -911,6 +912,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + drm_sched_entity_push_job(&submit->base, queue->entity); + + args->fence = submit->fence_id; ++ queue->last_fence = submit->fence_id; + + msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs); + msm_process_post_deps(post_deps, args->nr_out_syncobjs, +diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c +index 8a3a592da3a4d..2c46cd968ac4c 100644 +--- a/drivers/gpu/drm/msm/msm_gpu.c ++++ b/drivers/gpu/drm/msm/msm_gpu.c +@@ -296,7 +296,7 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, + state->bos = kcalloc(nr, + sizeof(struct msm_gpu_state_bo), GFP_KERNEL); + +- for (i = 0; i < submit->nr_bos; i++) { ++ for (i = 0; state->bos && i < submit->nr_bos; i++) { + if (should_dump(submit, i)) { + msm_gpu_crashstate_get_bo(state, submit->bos[i].obj, + submit->bos[i].iova, submit->bos[i].flags); +diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h +index ee25d556c8a10..2e2424066e701 100644 +--- a/drivers/gpu/drm/msm/msm_gpu.h ++++ b/drivers/gpu/drm/msm/msm_gpu.h +@@ -352,6 +352,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, + * @ring_nr: the ringbuffer used by this submitqueue, which is determined + * by the submitqueue's priority + * @faults: the number of GPU hangs associated with this submitqueue ++ * @last_fence: the sequence number of the last allocated fence (for error ++ * checking) + * @ctx: the per-drm_file context associated with the submitqueue (ie. + * which set of pgtables do submits jobs associated with the + * submitqueue use) +@@ -367,6 +369,7 @@ struct msm_gpu_submitqueue { + u32 flags; + u32 ring_nr; + int faults; ++ uint32_t last_fence; + struct msm_file_private *ctx; + struct list_head node; + struct idr fence_idr; +diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c +index 20006d060b5b5..4ac2a4eb984d8 100644 +--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c ++++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c +@@ -20,6 +20,10 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, + struct msm_gpu *gpu = dev_to_gpu(dev); + struct dev_pm_opp *opp; + ++ /* ++ * Note that devfreq_recommended_opp() can modify the freq ++ * to something that actually is in the opp table: ++ */ + opp = devfreq_recommended_opp(dev, freq, flags); + + /* +@@ -28,6 +32,7 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, + */ + if (gpu->devfreq.idle_freq) { + gpu->devfreq.idle_freq = *freq; ++ dev_pm_opp_put(opp); + return 0; + } + +diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c +index b8621c6e05546..7cb158bcbcf67 100644 +--- a/drivers/gpu/drm/msm/msm_submitqueue.c ++++ b/drivers/gpu/drm/msm/msm_submitqueue.c +@@ -101,6 +101,7 @@ get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, + + ret = drm_sched_entity_init(entity, sched_prio, &sched, 1, NULL); + if (ret) { ++ mutex_unlock(&entity_lock); + kfree(entity); + return ERR_PTR(ret); + } +diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c +index 89dd618d78f31..988bc4fbd78df 100644 +--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c ++++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c +@@ -361,7 +361,17 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, + bridge_state = + drm_atomic_get_new_bridge_state(state, + mxsfb->bridge); +- bus_format = bridge_state->input_bus_cfg.format; ++ if (!bridge_state) ++ bus_format = MEDIA_BUS_FMT_FIXED; ++ else ++ bus_format = bridge_state->input_bus_cfg.format; ++ ++ if (bus_format == MEDIA_BUS_FMT_FIXED) { ++ dev_warn_once(drm->dev, ++ "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n" ++ "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n"); ++ bus_format = MEDIA_BUS_FMT_RGB888_1X24; ++ } + } + + /* If there is no bridge, use bus format from connector */ +diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c +index 7739f46470d3e..99fee4d8cd318 100644 +--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c ++++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c +@@ -205,7 +205,7 @@ nv04_display_destroy(struct drm_device *dev) + nvif_notify_dtor(&disp->flip); + + nouveau_display(dev)->priv = NULL; +- kfree(disp); ++ vfree(disp); + + nvif_object_unmap(&drm->client.device.object); + } +@@ -223,7 +223,7 @@ nv04_display_create(struct drm_device *dev) + struct nv04_display *disp; + int i, ret; + +- disp = kzalloc(sizeof(*disp), GFP_KERNEL); ++ disp = vzalloc(sizeof(*disp)); + if (!disp) + return -ENOMEM; + +diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c +index 6109cd9e33991..e7efd9ede8e4b 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_drm.c +@@ -562,6 +562,7 @@ nouveau_drm_device_init(struct drm_device *dev) + nvkm_dbgopt(nouveau_debug, "DRM"); + + INIT_LIST_HEAD(&drm->clients); ++ mutex_init(&drm->clients_lock); + spin_lock_init(&drm->tile.lock); + + /* workaround an odd issue on nvc1 by disabling the device's +@@ -632,6 +633,7 @@ fail_alloc: + static void + nouveau_drm_device_fini(struct drm_device *dev) + { ++ struct nouveau_cli *cli, *temp_cli; + struct nouveau_drm *drm = nouveau_drm(dev); + + if (nouveau_pmops_runtime()) { +@@ -656,9 +658,28 @@ nouveau_drm_device_fini(struct drm_device *dev) + nouveau_ttm_fini(drm); + nouveau_vga_fini(drm); + ++ /* ++ * There may be existing clients from as-yet unclosed files. For now, ++ * clean them up here rather than deferring until the file is closed, ++ * but this likely not correct if we want to support hot-unplugging ++ * properly. ++ */ ++ mutex_lock(&drm->clients_lock); ++ list_for_each_entry_safe(cli, temp_cli, &drm->clients, head) { ++ list_del(&cli->head); ++ mutex_lock(&cli->mutex); ++ if (cli->abi16) ++ nouveau_abi16_fini(cli->abi16); ++ mutex_unlock(&cli->mutex); ++ nouveau_cli_fini(cli); ++ kfree(cli); ++ } ++ mutex_unlock(&drm->clients_lock); ++ + nouveau_cli_fini(&drm->client); + nouveau_cli_fini(&drm->master); + nvif_parent_dtor(&drm->parent); ++ mutex_destroy(&drm->clients_lock); + kfree(drm); + } + +@@ -796,7 +817,7 @@ nouveau_drm_device_remove(struct drm_device *dev) + struct nvkm_client *client; + struct nvkm_device *device; + +- drm_dev_unregister(dev); ++ drm_dev_unplug(dev); + + client = nvxx_client(&drm->client.base); + device = nvkm_device_find(client->device); +@@ -1090,9 +1111,9 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) + + fpriv->driver_priv = cli; + +- mutex_lock(&drm->client.mutex); ++ mutex_lock(&drm->clients_lock); + list_add(&cli->head, &drm->clients); +- mutex_unlock(&drm->client.mutex); ++ mutex_unlock(&drm->clients_lock); + + done: + if (ret && cli) { +@@ -1110,6 +1131,16 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) + { + struct nouveau_cli *cli = nouveau_cli(fpriv); + struct nouveau_drm *drm = nouveau_drm(dev); ++ int dev_index; ++ ++ /* ++ * The device is gone, and as it currently stands all clients are ++ * cleaned up in the removal codepath. In the future this may change ++ * so that we can support hot-unplugging, but for now we immediately ++ * return to avoid a double-free situation. ++ */ ++ if (!drm_dev_enter(dev, &dev_index)) ++ return; + + pm_runtime_get_sync(dev->dev); + +@@ -1118,14 +1149,15 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) + nouveau_abi16_fini(cli->abi16); + mutex_unlock(&cli->mutex); + +- mutex_lock(&drm->client.mutex); ++ mutex_lock(&drm->clients_lock); + list_del(&cli->head); +- mutex_unlock(&drm->client.mutex); ++ mutex_unlock(&drm->clients_lock); + + nouveau_cli_fini(cli); + kfree(cli); + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); ++ drm_dev_exit(dev_index); + } + + static const struct drm_ioctl_desc +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index ba65f136cf481..b2a970aa9bf4b 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -139,6 +139,11 @@ struct nouveau_drm { + + struct list_head clients; + ++ /** ++ * @clients_lock: Protects access to the @clients list of &struct nouveau_cli. ++ */ ++ struct mutex clients_lock; ++ + u8 old_pm_cap; + + struct { +diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c +index 05d0b3eb36904..0ae416aa76dcb 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fence.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.c +@@ -353,15 +353,22 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e + + if (ret) + return ret; +- } + +- fobj = dma_resv_shared_list(resv); +- fence = dma_resv_excl_fence(resv); ++ fobj = NULL; ++ } else { ++ fobj = dma_resv_shared_list(resv); ++ } + +- if (fence) { ++ /* Waiting for the exclusive fence first causes performance regressions ++ * under some circumstances. So manually wait for the shared ones first. ++ */ ++ for (i = 0; i < (fobj ? fobj->shared_count : 0) && !ret; ++i) { + struct nouveau_channel *prev = NULL; + bool must_wait = true; + ++ fence = rcu_dereference_protected(fobj->shared[i], ++ dma_resv_held(resv)); ++ + f = nouveau_local_fence(fence, chan->drm); + if (f) { + rcu_read_lock(); +@@ -373,20 +380,13 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e + + if (must_wait) + ret = dma_fence_wait(fence, intr); +- +- return ret; + } + +- if (!exclusive || !fobj) +- return ret; +- +- for (i = 0; i < fobj->shared_count && !ret; ++i) { ++ fence = dma_resv_excl_fence(resv); ++ if (fence) { + struct nouveau_channel *prev = NULL; + bool must_wait = true; + +- fence = rcu_dereference_protected(fobj->shared[i], +- dma_resv_held(resv)); +- + f = nouveau_local_fence(fence, chan->drm); + if (f) { + rcu_read_lock(); +@@ -398,6 +398,8 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e + + if (must_wait) + ret = dma_fence_wait(fence, intr); ++ ++ return ret; + } + + return ret; +diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c +index 8c2ecc2827232..c89d5964148fd 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_gem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c +@@ -56,7 +56,7 @@ static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) + + nouveau_bo_del_io_reserve_lru(bo); + prot = vm_get_page_prot(vma->vm_flags); +- ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); ++ ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT); + nouveau_bo_add_io_reserve_lru(bo); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret; +diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c +index b0c3422cb01fa..9985bfde015a6 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_svm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_svm.c +@@ -162,10 +162,14 @@ nouveau_svmm_bind(struct drm_device *dev, void *data, + */ + + mm = get_task_mm(current); ++ if (!mm) { ++ return -EINVAL; ++ } + mmap_read_lock(mm); + + if (!cli->svm.svmm) { + mmap_read_unlock(mm); ++ mmput(mm); + return -EINVAL; + } + +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c +index 704df0f2d1f16..09a112af2f893 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c +@@ -78,6 +78,6 @@ int + gt215_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_engine **pengine) + { +- return nvkm_falcon_new_(>215_ce, device, type, inst, ++ return nvkm_falcon_new_(>215_ce, device, type, -1, + (device->chipset != 0xaf), 0x104000, pengine); + } +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +index ca75c5f6ecaf8..88d262ba648cf 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +@@ -2626,6 +2626,27 @@ nv174_chipset = { + .fifo = { 0x00000001, ga102_fifo_new }, + }; + ++static const struct nvkm_device_chip ++nv176_chipset = { ++ .name = "GA106", ++ .bar = { 0x00000001, tu102_bar_new }, ++ .bios = { 0x00000001, nvkm_bios_new }, ++ .devinit = { 0x00000001, ga100_devinit_new }, ++ .fb = { 0x00000001, ga102_fb_new }, ++ .gpio = { 0x00000001, ga102_gpio_new }, ++ .i2c = { 0x00000001, gm200_i2c_new }, ++ .imem = { 0x00000001, nv50_instmem_new }, ++ .mc = { 0x00000001, ga100_mc_new }, ++ .mmu = { 0x00000001, tu102_mmu_new }, ++ .pci = { 0x00000001, gp100_pci_new }, ++ .privring = { 0x00000001, gm200_privring_new }, ++ .timer = { 0x00000001, gk20a_timer_new }, ++ .top = { 0x00000001, ga100_top_new }, ++ .disp = { 0x00000001, ga102_disp_new }, ++ .dma = { 0x00000001, gv100_dma_new }, ++ .fifo = { 0x00000001, ga102_fifo_new }, ++}; ++ + static const struct nvkm_device_chip + nv177_chipset = { + .name = "GA107", +@@ -3072,6 +3093,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, + case 0x168: device->chip = &nv168_chipset; break; + case 0x172: device->chip = &nv172_chipset; break; + case 0x174: device->chip = &nv174_chipset; break; ++ case 0x176: device->chip = &nv176_chipset; break; + case 0x177: device->chip = &nv177_chipset; break; + default: + if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) { +@@ -3147,8 +3169,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, + WARN_ON(device->chip->ptr.inst & ~((1 << ARRAY_SIZE(device->ptr)) - 1)); \ + for (j = 0; device->chip->ptr.inst && j < ARRAY_SIZE(device->ptr); j++) { \ + if ((device->chip->ptr.inst & BIT(j)) && (subdev_mask & BIT_ULL(type))) { \ +- int inst = (device->chip->ptr.inst == 1) ? -1 : (j); \ +- ret = device->chip->ptr.ctor(device, (type), inst, &device->ptr[j]); \ ++ ret = device->chip->ptr.ctor(device, (type), (j), &device->ptr[j]); \ + subdev = nvkm_device_subdev(device, (type), (j)); \ + if (ret) { \ + nvkm_subdev_del(&subdev); \ +diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c +index 6e3c450eaacef..3ff49344abc77 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c ++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c +@@ -62,7 +62,6 @@ gv100_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); +- nvkm_wr32(device, 0x6f0110 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); +diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +index 262641a014b06..c91130a6be2a1 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +@@ -117,8 +117,12 @@ nvkm_falcon_disable(struct nvkm_falcon *falcon) + int + nvkm_falcon_reset(struct nvkm_falcon *falcon) + { +- nvkm_falcon_disable(falcon); +- return nvkm_falcon_enable(falcon); ++ if (!falcon->func->reset) { ++ nvkm_falcon_disable(falcon); ++ return nvkm_falcon_enable(falcon); ++ } ++ ++ return falcon->func->reset(falcon); + } + + int +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c +index cdb1ead26d84f..82b4c8e1457c2 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c +@@ -207,11 +207,13 @@ int + gm200_acr_wpr_parse(struct nvkm_acr *acr) + { + const struct wpr_header *hdr = (void *)acr->wpr_fw->data; ++ struct nvkm_acr_lsfw *lsfw; + + while (hdr->falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID) { + wpr_header_dump(&acr->subdev, hdr); +- if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) +- return -ENOMEM; ++ lsfw = nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id); ++ if (IS_ERR(lsfw)) ++ return PTR_ERR(lsfw); + } + + return 0; +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c +index fb9132a39bb1a..fd97a935a380e 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c +@@ -161,11 +161,13 @@ int + gp102_acr_wpr_parse(struct nvkm_acr *acr) + { + const struct wpr_header_v1 *hdr = (void *)acr->wpr_fw->data; ++ struct nvkm_acr_lsfw *lsfw; + + while (hdr->falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) { + wpr_header_v1_dump(&acr->subdev, hdr); +- if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) +- return -ENOMEM; ++ lsfw = nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id); ++ if (IS_ERR(lsfw)) ++ return PTR_ERR(lsfw); + } + + return 0; +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +index d0f52d59fc2f9..64e423dddd9e7 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c +@@ -38,7 +38,7 @@ nvbios_addr(struct nvkm_bios *bios, u32 *addr, u8 size) + *addr += bios->imaged_addr; + } + +- if (unlikely(*addr + size >= bios->size)) { ++ if (unlikely(*addr + size > bios->size)) { + nvkm_error(&bios->subdev, "OOB %d %08x %08x\n", size, p, *addr); + return false; + } +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +index 24382875fb4f3..455e95a89259f 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +@@ -94,20 +94,13 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) + return 0; + } + +-static int ++static void + nvkm_pmu_reset(struct nvkm_pmu *pmu) + { + struct nvkm_device *device = pmu->subdev.device; + + if (!pmu->func->enabled(pmu)) +- return 0; +- +- /* Inhibit interrupts, and wait for idle. */ +- nvkm_wr32(device, 0x10a014, 0x0000ffff); +- nvkm_msec(device, 2000, +- if (!nvkm_rd32(device, 0x10a04c)) +- break; +- ); ++ return; + + /* Reset. */ + if (pmu->func->reset) +@@ -118,25 +111,37 @@ nvkm_pmu_reset(struct nvkm_pmu *pmu) + if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006)) + break; + ); +- +- return 0; + } + + static int + nvkm_pmu_preinit(struct nvkm_subdev *subdev) + { + struct nvkm_pmu *pmu = nvkm_pmu(subdev); +- return nvkm_pmu_reset(pmu); ++ nvkm_pmu_reset(pmu); ++ return 0; + } + + static int + nvkm_pmu_init(struct nvkm_subdev *subdev) + { + struct nvkm_pmu *pmu = nvkm_pmu(subdev); +- int ret = nvkm_pmu_reset(pmu); +- if (ret == 0 && pmu->func->init) +- ret = pmu->func->init(pmu); +- return ret; ++ struct nvkm_device *device = pmu->subdev.device; ++ ++ if (!pmu->func->init) ++ return 0; ++ ++ if (pmu->func->enabled(pmu)) { ++ /* Inhibit interrupts, and wait for idle. */ ++ nvkm_wr32(device, 0x10a014, 0x0000ffff); ++ nvkm_msec(device, 2000, ++ if (!nvkm_rd32(device, 0x10a04c)) ++ break; ++ ); ++ ++ nvkm_pmu_reset(pmu); ++ } ++ ++ return pmu->func->init(pmu); + } + + static void * +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c +index 5968c7696596c..40439e329aa9f 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c +@@ -23,9 +23,38 @@ + */ + #include "priv.h" + ++static int ++gm200_pmu_flcn_reset(struct nvkm_falcon *falcon) ++{ ++ struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon); ++ ++ nvkm_falcon_wr32(falcon, 0x014, 0x0000ffff); ++ pmu->func->reset(pmu); ++ return nvkm_falcon_enable(falcon); ++} ++ ++const struct nvkm_falcon_func ++gm200_pmu_flcn = { ++ .debug = 0xc08, ++ .fbif = 0xe00, ++ .load_imem = nvkm_falcon_v1_load_imem, ++ .load_dmem = nvkm_falcon_v1_load_dmem, ++ .read_dmem = nvkm_falcon_v1_read_dmem, ++ .bind_context = nvkm_falcon_v1_bind_context, ++ .wait_for_halt = nvkm_falcon_v1_wait_for_halt, ++ .clear_interrupt = nvkm_falcon_v1_clear_interrupt, ++ .set_start_addr = nvkm_falcon_v1_set_start_addr, ++ .start = nvkm_falcon_v1_start, ++ .enable = nvkm_falcon_v1_enable, ++ .disable = nvkm_falcon_v1_disable, ++ .reset = gm200_pmu_flcn_reset, ++ .cmdq = { 0x4a0, 0x4b0, 4 }, ++ .msgq = { 0x4c8, 0x4cc, 0 }, ++}; ++ + static const struct nvkm_pmu_func + gm200_pmu = { +- .flcn = >215_pmu_flcn, ++ .flcn = &gm200_pmu_flcn, + .enabled = gf100_pmu_enabled, + .reset = gf100_pmu_reset, + }; +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +index 148706977eec7..e1772211b0a4b 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +@@ -211,7 +211,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) + + static const struct nvkm_pmu_func + gm20b_pmu = { +- .flcn = >215_pmu_flcn, ++ .flcn = &gm200_pmu_flcn, + .enabled = gf100_pmu_enabled, + .intr = gt215_pmu_intr, + .recv = gm20b_pmu_recv, +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +index 00da1b873ce81..6bf7fc1bd1e3b 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +@@ -39,7 +39,7 @@ gp102_pmu_enabled(struct nvkm_pmu *pmu) + + static const struct nvkm_pmu_func + gp102_pmu = { +- .flcn = >215_pmu_flcn, ++ .flcn = &gm200_pmu_flcn, + .enabled = gp102_pmu_enabled, + .reset = gp102_pmu_reset, + }; +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +index 461f722656e24..ba1583bb618b2 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +@@ -78,7 +78,7 @@ gp10b_pmu_acr = { + + static const struct nvkm_pmu_func + gp10b_pmu = { +- .flcn = >215_pmu_flcn, ++ .flcn = &gm200_pmu_flcn, + .enabled = gf100_pmu_enabled, + .intr = gt215_pmu_intr, + .recv = gm20b_pmu_recv, +diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +index e7860d1773539..bcaade758ff72 100644 +--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h ++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +@@ -44,6 +44,8 @@ void gf100_pmu_reset(struct nvkm_pmu *); + + void gk110_pmu_pgob(struct nvkm_pmu *, bool); + ++extern const struct nvkm_falcon_func gm200_pmu_flcn; ++ + void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64); + void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); + int gm20b_pmu_acr_boot(struct nvkm_falcon *); +diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +index 581661b506f81..f9c1f7bc8218c 100644 +--- a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c ++++ b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +@@ -227,7 +227,13 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi) + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->lanes = 4; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ drm_panel_remove(&ctx->panel); ++ return ret; ++ } ++ ++ return 0; + } + + static int feiyang_dsi_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c +index aea3162253914..f194b62e290ca 100644 +--- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c ++++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c +@@ -484,6 +484,7 @@ static void innolux_panel_del(struct innolux_panel *innolux) + static int innolux_panel_probe(struct mipi_dsi_device *dsi) + { + const struct panel_desc *desc; ++ struct innolux_panel *innolux; + int err; + + desc = of_device_get_match_data(&dsi->dev); +@@ -495,7 +496,14 @@ static int innolux_panel_probe(struct mipi_dsi_device *dsi) + if (err < 0) + return err; + +- return mipi_dsi_attach(dsi); ++ err = mipi_dsi_attach(dsi); ++ if (err < 0) { ++ innolux = mipi_dsi_get_drvdata(dsi); ++ innolux_panel_del(innolux); ++ return err; ++ } ++ ++ return 0; + } + + static int innolux_panel_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +index 733010b5e4f53..3c86ad262d5e0 100644 +--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c ++++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +@@ -473,7 +473,13 @@ static int jdi_panel_probe(struct mipi_dsi_device *dsi) + if (ret < 0) + return ret; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ jdi_panel_del(jdi); ++ return ret; ++ } ++ ++ return 0; + } + + static int jdi_panel_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +index 86e4213e8bb13..daccb1fd5fdad 100644 +--- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c ++++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +@@ -406,7 +406,13 @@ static int kingdisplay_panel_probe(struct mipi_dsi_device *dsi) + if (err < 0) + return err; + +- return mipi_dsi_attach(dsi); ++ err = mipi_dsi_attach(dsi); ++ if (err < 0) { ++ kingdisplay_panel_del(kingdisplay); ++ return err; ++ } ++ ++ return 0; + } + + static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c +index 533cd3934b8b7..839b263fb3c0f 100644 +--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c ++++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c +@@ -656,7 +656,13 @@ static int nt36672a_panel_probe(struct mipi_dsi_device *dsi) + if (err < 0) + return err; + +- return mipi_dsi_attach(dsi); ++ err = mipi_dsi_attach(dsi); ++ if (err < 0) { ++ drm_panel_remove(&pinfo->base); ++ return err; ++ } ++ ++ return 0; + } + + static int nt36672a_panel_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c +index 3c20beeb17819..3991f5d950af4 100644 +--- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c ++++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c +@@ -241,7 +241,13 @@ static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi) + if (ret < 0) + return ret; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ wuxga_nt_panel_del(wuxga_nt); ++ return ret; ++ } ++ ++ return 0; + } + + static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c +index a3782830ae3c4..1fb579a574d9f 100644 +--- a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c ++++ b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c +@@ -199,7 +199,13 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi) + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->lanes = 4; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ drm_panel_remove(&ctx->panel); ++ return ret; ++ } ++ ++ return 0; + } + + static int rb070d30_panel_dsi_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +index ea63799ff2a1e..29fde3823212b 100644 +--- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c ++++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +@@ -247,6 +247,7 @@ static int s6e88a0_ams452ef01_probe(struct mipi_dsi_device *dsi) + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "Failed to attach to DSI host: %d\n", ret); ++ drm_panel_remove(&ctx->panel); + return ret; + } + +diff --git a/drivers/gpu/drm/panel/panel-samsung-sofef00.c b/drivers/gpu/drm/panel/panel-samsung-sofef00.c +index 8cb1853574bb8..6d107e14fcc55 100644 +--- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c ++++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c +@@ -302,6 +302,7 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi) + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "Failed to attach to DSI host: %d\n", ret); ++ drm_panel_remove(&ctx->panel); + return ret; + } + +diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +index b937e24dac8e0..25829a0a8e801 100644 +--- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c ++++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +@@ -296,7 +296,13 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) + if (ret < 0) + return ret; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret < 0) { ++ sharp_nt_panel_del(sharp_nt); ++ return ret; ++ } ++ ++ return 0; + } + + static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi) +diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c +index 9b6c4e6c38a1b..b7b654f2dfd90 100644 +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -721,6 +721,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc, + err = panel_dpi_probe(dev, panel); + if (err) + goto free_ddc; ++ desc = panel->desc; + } else { + if (!of_get_display_timing(dev->of_node, "panel-timing", &dt)) + panel_simple_parse_panel_timing_node(dev, panel, &dt); +diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c +index 0fce73b9a6469..70bd84b7ef2b0 100644 +--- a/drivers/gpu/drm/radeon/atombios_encoders.c ++++ b/drivers/gpu/drm/radeon/atombios_encoders.c +@@ -198,7 +198,8 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, + * so don't register a backlight device + */ + if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) && +- (rdev->pdev->device == 0x6741)) ++ (rdev->pdev->device == 0x6741) && ++ !dmi_match(DMI_PRODUCT_NAME, "iMac12,1")) + return; + + if (!radeon_encoder->enc_priv) +diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c +index 458f92a708879..a36a4f2c76b09 100644 +--- a/drivers/gpu/drm/radeon/radeon_gem.c ++++ b/drivers/gpu/drm/radeon/radeon_gem.c +@@ -61,7 +61,7 @@ static vm_fault_t radeon_gem_fault(struct vm_fault *vmf) + goto unlock_resv; + + ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, +- TTM_BO_VM_NUM_PREFAULT, 1); ++ TTM_BO_VM_NUM_PREFAULT); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + goto unlock_mclk; + +diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +index 482fb0ae6cb5d..0e14907f2043e 100644 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -648,6 +648,8 @@ void radeon_driver_lastclose_kms(struct drm_device *dev) + int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) + { + struct radeon_device *rdev = dev->dev_private; ++ struct radeon_fpriv *fpriv; ++ struct radeon_vm *vm; + int r; + + file_priv->driver_priv = NULL; +@@ -660,48 +662,52 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) + + /* new gpu have virtual address space support */ + if (rdev->family >= CHIP_CAYMAN) { +- struct radeon_fpriv *fpriv; +- struct radeon_vm *vm; + + fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); + if (unlikely(!fpriv)) { + r = -ENOMEM; +- goto out_suspend; ++ goto err_suspend; + } + + if (rdev->accel_working) { + vm = &fpriv->vm; + r = radeon_vm_init(rdev, vm); +- if (r) { +- kfree(fpriv); +- goto out_suspend; +- } ++ if (r) ++ goto err_fpriv; + + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); +- if (r) { +- radeon_vm_fini(rdev, vm); +- kfree(fpriv); +- goto out_suspend; +- } ++ if (r) ++ goto err_vm_fini; + + /* map the ib pool buffer read only into + * virtual address space */ + vm->ib_bo_va = radeon_vm_bo_add(rdev, vm, + rdev->ring_tmp_bo.bo); ++ if (!vm->ib_bo_va) { ++ r = -ENOMEM; ++ goto err_vm_fini; ++ } ++ + r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va, + RADEON_VA_IB_OFFSET, + RADEON_VM_PAGE_READABLE | + RADEON_VM_PAGE_SNOOPED); +- if (r) { +- radeon_vm_fini(rdev, vm); +- kfree(fpriv); +- goto out_suspend; +- } ++ if (r) ++ goto err_vm_fini; + } + file_priv->driver_priv = fpriv; + } + +-out_suspend: ++ pm_runtime_mark_last_busy(dev->dev); ++ pm_runtime_put_autosuspend(dev->dev); ++ return 0; ++ ++err_vm_fini: ++ radeon_vm_fini(rdev, vm); ++err_fpriv: ++ kfree(fpriv); ++ ++err_suspend: + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); + return r; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +index ea7e39d035457..ee7e375ee6724 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +@@ -215,6 +215,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) + const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode; + struct rcar_du_device *rcdu = rcrtc->dev; + unsigned long mode_clock = mode->clock * 1000; ++ unsigned int hdse_offset; + u32 dsmr; + u32 escr; + +@@ -298,10 +299,15 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) + | DSMR_DIPM_DISP | DSMR_CSPM; + rcar_du_crtc_write(rcrtc, DSMR, dsmr); + ++ hdse_offset = 19; ++ if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2)) ++ hdse_offset += 25; ++ + /* Display timings */ +- rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19); ++ rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - ++ hdse_offset); + rcar_du_crtc_write(rcrtc, HDER, mode->htotal - mode->hsync_start + +- mode->hdisplay - 19); ++ mode->hdisplay - hdse_offset); + rcar_du_crtc_write(rcrtc, HSWR, mode->hsync_end - + mode->hsync_start - 1); + rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1); +@@ -836,6 +842,7 @@ rcar_du_crtc_mode_valid(struct drm_crtc *crtc, + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + struct rcar_du_device *rcdu = rcrtc->dev; + bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; ++ unsigned int min_sync_porch; + unsigned int vbp; + + if (interlaced && !rcar_du_has(rcdu, RCAR_DU_FEATURE_INTERLACED)) +@@ -843,9 +850,14 @@ rcar_du_crtc_mode_valid(struct drm_crtc *crtc, + + /* + * The hardware requires a minimum combined horizontal sync and back +- * porch of 20 pixels and a minimum vertical back porch of 3 lines. ++ * porch of 20 pixels (when CMM isn't used) or 45 pixels (when CMM is ++ * used), and a minimum vertical back porch of 3 lines. + */ +- if (mode->htotal - mode->hsync_start < 20) ++ min_sync_porch = 20; ++ if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2)) ++ min_sync_porch += 25; ++ ++ if (mode->htotal - mode->hsync_start < min_sync_porch) + return MODE_HBLANK_NARROW; + + vbp = (mode->vtotal - mode->vsync_end) / (interlaced ? 2 : 1); +diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +index a2262bee5aa47..59c3d8ef6bf9a 100644 +--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +@@ -268,6 +268,8 @@ struct dw_mipi_dsi_rockchip { + struct dw_mipi_dsi *dmd; + const struct rockchip_dw_dsi_chip_data *cdata; + struct dw_mipi_dsi_plat_data pdata; ++ ++ bool dsi_bound; + }; + + struct dphy_pll_parameter_map { +@@ -773,10 +775,6 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) + if (mux < 0) + return; + +- pm_runtime_get_sync(dsi->dev); +- if (dsi->slave) +- pm_runtime_get_sync(dsi->slave->dev); +- + /* + * For the RK3399, the clk of grf must be enabled before writing grf + * register. And for RK3288 or other soc, this grf_clk must be NULL, +@@ -795,20 +793,10 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) + clk_disable_unprepare(dsi->grf_clk); + } + +-static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) +-{ +- struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); +- +- if (dsi->slave) +- pm_runtime_put(dsi->slave->dev); +- pm_runtime_put(dsi->dev); +-} +- + static const struct drm_encoder_helper_funcs + dw_mipi_dsi_encoder_helper_funcs = { + .atomic_check = dw_mipi_dsi_encoder_atomic_check, + .enable = dw_mipi_dsi_encoder_enable, +- .disable = dw_mipi_dsi_encoder_disable, + }; + + static int rockchip_dsi_drm_create_encoder(struct dw_mipi_dsi_rockchip *dsi, +@@ -938,10 +926,14 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, + put_device(second); + } + ++ pm_runtime_get_sync(dsi->dev); ++ if (dsi->slave) ++ pm_runtime_get_sync(dsi->slave->dev); ++ + ret = clk_prepare_enable(dsi->pllref_clk); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to enable pllref_clk: %d\n", ret); +- return ret; ++ goto out_pm_runtime; + } + + /* +@@ -953,7 +945,7 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, + ret = clk_prepare_enable(dsi->grf_clk); + if (ret) { + DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); +- return ret; ++ goto out_pll_clk; + } + + dw_mipi_dsi_rockchip_config(dsi); +@@ -965,16 +957,27 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, + ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to create drm encoder\n"); +- return ret; ++ goto out_pll_clk; + } + + ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to bind: %d\n", ret); +- return ret; ++ goto out_pll_clk; + } + ++ dsi->dsi_bound = true; ++ + return 0; ++ ++out_pll_clk: ++ clk_disable_unprepare(dsi->pllref_clk); ++out_pm_runtime: ++ pm_runtime_put(dsi->dev); ++ if (dsi->slave) ++ pm_runtime_put(dsi->slave->dev); ++ ++ return ret; + } + + static void dw_mipi_dsi_rockchip_unbind(struct device *dev, +@@ -986,9 +989,15 @@ static void dw_mipi_dsi_rockchip_unbind(struct device *dev, + if (dsi->is_slave) + return; + ++ dsi->dsi_bound = false; ++ + dw_mipi_dsi_unbind(dsi->dmd); + + clk_disable_unprepare(dsi->pllref_clk); ++ ++ pm_runtime_put(dsi->dev); ++ if (dsi->slave) ++ pm_runtime_put(dsi->slave->dev); + } + + static const struct component_ops dw_mipi_dsi_rockchip_ops = { +@@ -1276,6 +1285,36 @@ static const struct phy_ops dw_mipi_dsi_dphy_ops = { + .exit = dw_mipi_dsi_dphy_exit, + }; + ++static int __maybe_unused dw_mipi_dsi_rockchip_resume(struct device *dev) ++{ ++ struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev); ++ int ret; ++ ++ /* ++ * Re-configure DSI state, if we were previously initialized. We need ++ * to do this before rockchip_drm_drv tries to re-enable() any panels. ++ */ ++ if (dsi->dsi_bound) { ++ ret = clk_prepare_enable(dsi->grf_clk); ++ if (ret) { ++ DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); ++ return ret; ++ } ++ ++ dw_mipi_dsi_rockchip_config(dsi); ++ if (dsi->slave) ++ dw_mipi_dsi_rockchip_config(dsi->slave); ++ ++ clk_disable_unprepare(dsi->grf_clk); ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops dw_mipi_dsi_rockchip_pm_ops = { ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, dw_mipi_dsi_rockchip_resume) ++}; ++ + static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1397,14 +1436,10 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "Failed to probe dw_mipi_dsi: %d\n", ret); +- goto err_clkdisable; ++ return ret; + } + + return 0; +- +-err_clkdisable: +- clk_disable_unprepare(dsi->pllref_clk); +- return ret; + } + + static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev) +@@ -1593,6 +1628,7 @@ struct platform_driver dw_mipi_dsi_rockchip_driver = { + .remove = dw_mipi_dsi_rockchip_remove, + .driver = { + .of_match_table = dw_mipi_dsi_rockchip_dt_ids, ++ .pm = &dw_mipi_dsi_rockchip_pm_ops, + .name = "dw-mipi-dsi-rockchip", + }, + }; +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 830bdd5e9b7ce..8677c82716784 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -529,13 +529,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + return ret; + } + +- ret = clk_prepare_enable(hdmi->vpll_clk); +- if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", +- ret); +- return ret; +- } +- + hdmi->phy = devm_phy_optional_get(dev, "hdmi"); + if (IS_ERR(hdmi->phy)) { + ret = PTR_ERR(hdmi->phy); +@@ -544,6 +537,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + return ret; + } + ++ ret = clk_prepare_enable(hdmi->vpll_clk); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ++ ret); ++ return ret; ++ } ++ + drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); + drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); + +diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +index ca7cc82125cbc..8c873fcd0e99f 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c ++++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +@@ -902,6 +902,7 @@ static const struct vop_win_phy rk3399_win01_data = { + .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0), + .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1), + .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12), ++ .x_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 21), + .y_mir_en = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 22), + .act_info = VOP_REG(RK3288_WIN0_ACT_INFO, 0x1fff1fff, 0), + .dsp_info = VOP_REG(RK3288_WIN0_DSP_INFO, 0x0fff0fff, 0), +@@ -912,6 +913,7 @@ static const struct vop_win_phy rk3399_win01_data = { + .uv_vir = VOP_REG(RK3288_WIN0_VIR, 0x3fff, 16), + .src_alpha_ctl = VOP_REG(RK3288_WIN0_SRC_ALPHA_CTRL, 0xff, 0), + .dst_alpha_ctl = VOP_REG(RK3288_WIN0_DST_ALPHA_CTRL, 0xff, 0), ++ .channel = VOP_REG(RK3288_WIN0_CTRL2, 0xff, 0), + }; + + /* +@@ -922,11 +924,11 @@ static const struct vop_win_phy rk3399_win01_data = { + static const struct vop_win_data rk3399_vop_win_data[] = { + { .base = 0x00, .phy = &rk3399_win01_data, + .type = DRM_PLANE_TYPE_PRIMARY }, +- { .base = 0x40, .phy = &rk3288_win01_data, ++ { .base = 0x40, .phy = &rk3368_win01_data, + .type = DRM_PLANE_TYPE_OVERLAY }, +- { .base = 0x00, .phy = &rk3288_win23_data, ++ { .base = 0x00, .phy = &rk3368_win23_data, + .type = DRM_PLANE_TYPE_OVERLAY }, +- { .base = 0x50, .phy = &rk3288_win23_data, ++ { .base = 0x50, .phy = &rk3368_win23_data, + .type = DRM_PLANE_TYPE_CURSOR }, + }; + +diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig +index 5755f0432e774..8c796de53222c 100644 +--- a/drivers/gpu/drm/sun4i/Kconfig ++++ b/drivers/gpu/drm/sun4i/Kconfig +@@ -46,6 +46,7 @@ config DRM_SUN6I_DSI + default MACH_SUN8I + select CRC_CCITT + select DRM_MIPI_DSI ++ select RESET_CONTROLLER + select PHY_SUN6I_MIPI_DPHY + help + Choose this option if you want have an Allwinner SoC with +diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h +index a55a38ad849c1..022cafa6c06cb 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_csc.h ++++ b/drivers/gpu/drm/sun4i/sun8i_csc.h +@@ -16,8 +16,8 @@ struct sun8i_mixer; + #define CCSC10_OFFSET 0xA0000 + #define CCSC11_OFFSET 0xF0000 + +-#define SUN8I_CSC_CTRL(base) (base + 0x0) +-#define SUN8I_CSC_COEFF(base, i) (base + 0x10 + 4 * i) ++#define SUN8I_CSC_CTRL(base) ((base) + 0x0) ++#define SUN8I_CSC_COEFF(base, i) ((base) + 0x10 + 4 * (i)) + + #define SUN8I_CSC_CTRL_EN BIT(0) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +index b64d93da651d2..5e2b0175df36f 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c ++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +@@ -658,8 +658,10 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node) + return -EPROBE_DEFER; + + phy = platform_get_drvdata(pdev); +- if (!phy) ++ if (!phy) { ++ put_device(&pdev->dev); + return -EPROBE_DEFER; ++ } + + hdmi->phy = phy; + +diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c +index 8d37d6b00562a..611cd8dad46ed 100644 +--- a/drivers/gpu/drm/tegra/drm.c ++++ b/drivers/gpu/drm/tegra/drm.c +@@ -21,6 +21,10 @@ + #include <drm/drm_prime.h> + #include <drm/drm_vblank.h> + ++#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) ++#include <asm/dma-iommu.h> ++#endif ++ + #include "dc.h" + #include "drm.h" + #include "gem.h" +@@ -936,6 +940,17 @@ int host1x_client_iommu_attach(struct host1x_client *client) + struct iommu_group *group = NULL; + int err; + ++#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) ++ if (client->dev->archdata.mapping) { ++ struct dma_iommu_mapping *mapping = ++ to_dma_iommu_mapping(client->dev); ++ arm_iommu_detach_device(client->dev); ++ arm_iommu_release_mapping(mapping); ++ ++ domain = iommu_get_domain_for_dev(client->dev); ++ } ++#endif ++ + /* + * If the host1x client is already attached to an IOMMU domain that is + * not the shared IOMMU domain, don't try to attach it to a different +diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c +index de288cba39055..ba3722f1b8651 100644 +--- a/drivers/gpu/drm/tegra/gr2d.c ++++ b/drivers/gpu/drm/tegra/gr2d.c +@@ -4,9 +4,11 @@ + */ + + #include <linux/clk.h> ++#include <linux/delay.h> + #include <linux/iommu.h> + #include <linux/module.h> + #include <linux/of_device.h> ++#include <linux/reset.h> + + #include "drm.h" + #include "gem.h" +@@ -19,6 +21,7 @@ struct gr2d_soc { + struct gr2d { + struct tegra_drm_client client; + struct host1x_channel *channel; ++ struct reset_control *rst; + struct clk *clk; + + const struct gr2d_soc *soc; +@@ -208,6 +211,12 @@ static int gr2d_probe(struct platform_device *pdev) + if (!syncpts) + return -ENOMEM; + ++ gr2d->rst = devm_reset_control_get(dev, NULL); ++ if (IS_ERR(gr2d->rst)) { ++ dev_err(dev, "cannot get reset\n"); ++ return PTR_ERR(gr2d->rst); ++ } ++ + gr2d->clk = devm_clk_get(dev, NULL); + if (IS_ERR(gr2d->clk)) { + dev_err(dev, "cannot get clock\n"); +@@ -220,6 +229,14 @@ static int gr2d_probe(struct platform_device *pdev) + return err; + } + ++ usleep_range(2000, 4000); ++ ++ err = reset_control_deassert(gr2d->rst); ++ if (err < 0) { ++ dev_err(dev, "failed to deassert reset: %d\n", err); ++ goto disable_clk; ++ } ++ + INIT_LIST_HEAD(&gr2d->client.base.list); + gr2d->client.base.ops = &gr2d_client_ops; + gr2d->client.base.dev = dev; +@@ -234,8 +251,7 @@ static int gr2d_probe(struct platform_device *pdev) + err = host1x_client_register(&gr2d->client.base); + if (err < 0) { + dev_err(dev, "failed to register host1x client: %d\n", err); +- clk_disable_unprepare(gr2d->clk); +- return err; ++ goto assert_rst; + } + + /* initialize address register map */ +@@ -245,6 +261,13 @@ static int gr2d_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, gr2d); + + return 0; ++ ++assert_rst: ++ (void)reset_control_assert(gr2d->rst); ++disable_clk: ++ clk_disable_unprepare(gr2d->clk); ++ ++ return err; + } + + static int gr2d_remove(struct platform_device *pdev) +@@ -259,6 +282,12 @@ static int gr2d_remove(struct platform_device *pdev) + return err; + } + ++ err = reset_control_assert(gr2d->rst); ++ if (err < 0) ++ dev_err(&pdev->dev, "failed to assert reset: %d\n", err); ++ ++ usleep_range(2000, 4000); ++ + clk_disable_unprepare(gr2d->clk); + + return 0; +diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c +index 776f825df52fa..aba9d0c9d9031 100644 +--- a/drivers/gpu/drm/tegra/submit.c ++++ b/drivers/gpu/drm/tegra/submit.c +@@ -475,8 +475,10 @@ static void release_job(struct host1x_job *job) + kfree(job_data->used_mappings); + kfree(job_data); + +- if (pm_runtime_enabled(client->base.dev)) ++ if (pm_runtime_enabled(client->base.dev)) { ++ pm_runtime_mark_last_busy(client->base.dev); + pm_runtime_put_autosuspend(client->base.dev); ++ } + } + + int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data, +diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c +index c02010ff2b7f2..da4af53719917 100644 +--- a/drivers/gpu/drm/tegra/vic.c ++++ b/drivers/gpu/drm/tegra/vic.c +@@ -5,6 +5,7 @@ + + #include <linux/clk.h> + #include <linux/delay.h> ++#include <linux/dma-mapping.h> + #include <linux/host1x.h> + #include <linux/iommu.h> + #include <linux/module.h> +@@ -232,10 +233,8 @@ static int vic_load_firmware(struct vic *vic) + + if (!client->group) { + virt = dma_alloc_coherent(vic->dev, size, &iova, GFP_KERNEL); +- +- err = dma_mapping_error(vic->dev, iova); +- if (err < 0) +- return err; ++ if (!virt) ++ return -ENOMEM; + } else { + virt = tegra_drm_alloc(tegra, size, &iova); + } +diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c +index 481b48bde0473..5a6e89825bc2f 100644 +--- a/drivers/gpu/drm/tiny/simpledrm.c ++++ b/drivers/gpu/drm/tiny/simpledrm.c +@@ -458,7 +458,7 @@ static struct drm_display_mode simpledrm_mode(unsigned int width, + { + struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) }; + +- mode.clock = 60 /* Hz */ * mode.hdisplay * mode.vdisplay; ++ mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */; + drm_mode_set_name(&mode); + + return mode; +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index bb9e02c31946e..900edaf5d68ee 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -724,6 +724,8 @@ int ttm_mem_evict_first(struct ttm_device *bdev, + ret = ttm_bo_evict(bo, ctx); + if (locked) + ttm_bo_unreserve(bo); ++ else ++ ttm_bo_move_to_lru_tail_unlocked(bo); + + ttm_bo_put(bo); + return ret; +diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c +index f56be5bc0861e..4a655ab23c89d 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c ++++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c +@@ -171,89 +171,6 @@ vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, + } + EXPORT_SYMBOL(ttm_bo_vm_reserve); + +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-/** +- * ttm_bo_vm_insert_huge - Insert a pfn for PUD or PMD faults +- * @vmf: Fault data +- * @bo: The buffer object +- * @page_offset: Page offset from bo start +- * @fault_page_size: The size of the fault in pages. +- * @pgprot: The page protections. +- * Does additional checking whether it's possible to insert a PUD or PMD +- * pfn and performs the insertion. +- * +- * Return: VM_FAULT_NOPAGE on successful insertion, VM_FAULT_FALLBACK if +- * a huge fault was not possible, or on insertion error. +- */ +-static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, +- struct ttm_buffer_object *bo, +- pgoff_t page_offset, +- pgoff_t fault_page_size, +- pgprot_t pgprot) +-{ +- pgoff_t i; +- vm_fault_t ret; +- unsigned long pfn; +- pfn_t pfnt; +- struct ttm_tt *ttm = bo->ttm; +- bool write = vmf->flags & FAULT_FLAG_WRITE; +- +- /* Fault should not cross bo boundary. */ +- page_offset &= ~(fault_page_size - 1); +- if (page_offset + fault_page_size > bo->resource->num_pages) +- goto out_fallback; +- +- if (bo->resource->bus.is_iomem) +- pfn = ttm_bo_io_mem_pfn(bo, page_offset); +- else +- pfn = page_to_pfn(ttm->pages[page_offset]); +- +- /* pfn must be fault_page_size aligned. */ +- if ((pfn & (fault_page_size - 1)) != 0) +- goto out_fallback; +- +- /* Check that memory is contiguous. */ +- if (!bo->resource->bus.is_iomem) { +- for (i = 1; i < fault_page_size; ++i) { +- if (page_to_pfn(ttm->pages[page_offset + i]) != pfn + i) +- goto out_fallback; +- } +- } else if (bo->bdev->funcs->io_mem_pfn) { +- for (i = 1; i < fault_page_size; ++i) { +- if (ttm_bo_io_mem_pfn(bo, page_offset + i) != pfn + i) +- goto out_fallback; +- } +- } +- +- pfnt = __pfn_to_pfn_t(pfn, PFN_DEV); +- if (fault_page_size == (HPAGE_PMD_SIZE >> PAGE_SHIFT)) +- ret = vmf_insert_pfn_pmd_prot(vmf, pfnt, pgprot, write); +-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +- else if (fault_page_size == (HPAGE_PUD_SIZE >> PAGE_SHIFT)) +- ret = vmf_insert_pfn_pud_prot(vmf, pfnt, pgprot, write); +-#endif +- else +- WARN_ON_ONCE(ret = VM_FAULT_FALLBACK); +- +- if (ret != VM_FAULT_NOPAGE) +- goto out_fallback; +- +- return VM_FAULT_NOPAGE; +-out_fallback: +- count_vm_event(THP_FAULT_FALLBACK); +- return VM_FAULT_FALLBACK; +-} +-#else +-static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, +- struct ttm_buffer_object *bo, +- pgoff_t page_offset, +- pgoff_t fault_page_size, +- pgprot_t pgprot) +-{ +- return VM_FAULT_FALLBACK; +-} +-#endif +- + /** + * ttm_bo_vm_fault_reserved - TTM fault helper + * @vmf: The struct vm_fault given as argument to the fault callback +@@ -261,7 +178,6 @@ static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, + * @num_prefault: Maximum number of prefault pages. The caller may want to + * specify this based on madvice settings and the size of the GPU object + * backed by the memory. +- * @fault_page_size: The size of the fault in pages. + * + * This function inserts one or more page table entries pointing to the + * memory backing the buffer object, and then returns a return code +@@ -275,8 +191,7 @@ static vm_fault_t ttm_bo_vm_insert_huge(struct vm_fault *vmf, + */ + vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, + pgprot_t prot, +- pgoff_t num_prefault, +- pgoff_t fault_page_size) ++ pgoff_t num_prefault) + { + struct vm_area_struct *vma = vmf->vma; + struct ttm_buffer_object *bo = vma->vm_private_data; +@@ -327,11 +242,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, + prot = pgprot_decrypted(prot); + } + +- /* We don't prefault on huge faults. Yet. */ +- if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && fault_page_size != 1) +- return ttm_bo_vm_insert_huge(vmf, bo, page_offset, +- fault_page_size, prot); +- + /* + * Speculatively prefault a number of pages. Only error on + * first page. +@@ -429,7 +339,7 @@ vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) + + prot = vma->vm_page_prot; + if (drm_dev_enter(ddev, &idx)) { +- ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); ++ ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT); + drm_dev_exit(idx); + } else { + ret = ttm_bo_vm_dummy_page(vmf, prot); +@@ -519,11 +429,6 @@ int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, + + switch (bo->resource->mem_type) { + case TTM_PL_SYSTEM: +- if (unlikely(bo->ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { +- ret = ttm_tt_swapin(bo->ttm); +- if (unlikely(ret != 0)) +- return ret; +- } + fallthrough; + case TTM_PL_TT: + ret = ttm_bo_vm_access_kmap(bo, offset, buf, len, write); +diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c +index 3750fd2161317..930574ad2bca9 100644 +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -30,7 +30,7 @@ static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, + int bval = (i + block * EDID_LENGTH) << 8; + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x02, (0x80 | (0x02 << 5)), bval, +- 0xA1, read_buff, 2, HZ); ++ 0xA1, read_buff, 2, 1000); + if (ret < 1) { + DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); + kfree(read_buff); +diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c +index 5689da118197e..772b5831bcc6f 100644 +--- a/drivers/gpu/drm/v3d/v3d_gem.c ++++ b/drivers/gpu/drm/v3d/v3d_gem.c +@@ -197,8 +197,8 @@ v3d_clean_caches(struct v3d_dev *v3d) + + V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF); + if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & +- V3D_L2TCACTL_L2TFLS), 100)) { +- DRM_ERROR("Timeout waiting for L1T write combiner flush\n"); ++ V3D_L2TCACTL_TMUWCF), 100)) { ++ DRM_ERROR("Timeout waiting for TMU write combiner flush\n"); + } + + mutex_lock(&v3d->cache_clean_lock); +diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c +index f28779715ccda..c9e8b3a63c621 100644 +--- a/drivers/gpu/drm/vboxvideo/vbox_main.c ++++ b/drivers/gpu/drm/vboxvideo/vbox_main.c +@@ -127,8 +127,8 @@ int vbox_hw_init(struct vbox_private *vbox) + /* Create guest-heap mem-pool use 2^4 = 16 byte chunks */ + vbox->guest_pool = devm_gen_pool_create(vbox->ddev.dev, 4, -1, + "vboxvideo-accel"); +- if (!vbox->guest_pool) +- return -ENOMEM; ++ if (IS_ERR(vbox->guest_pool)) ++ return PTR_ERR(vbox->guest_pool); + + ret = gen_pool_add_virt(vbox->guest_pool, + (unsigned long)vbox->guest_heap, +diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c +index fddaeb0b09c11..f642bd6e71ff4 100644 +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -391,7 +391,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); + if (!bo) +- return ERR_PTR(-ENOMEM); ++ return NULL; + + bo->madv = VC4_MADV_WILLNEED; + refcount_set(&bo->usecnt, 0); +diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c +index 18f5009ce90e3..3e61184e194c9 100644 +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -32,6 +32,7 @@ + #include <linux/clk.h> + #include <linux/component.h> + #include <linux/of_device.h> ++#include <linux/pm_runtime.h> + + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -42,6 +43,7 @@ + #include <drm/drm_vblank.h> + + #include "vc4_drv.h" ++#include "vc4_hdmi.h" + #include "vc4_regs.h" + + #define HVS_FIFO_LATENCY_PIX 6 +@@ -496,8 +498,10 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) + enum vc4_encoder_type encoder_type; + const struct vc4_pv_data *pv_data; + struct drm_encoder *encoder; ++ struct vc4_hdmi *vc4_hdmi; + unsigned encoder_sel; + int channel; ++ int ret; + + if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, + "brcm,bcm2711-pixelvalve2") || +@@ -525,7 +529,22 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) + if (WARN_ON(!encoder)) + return 0; + +- return vc4_crtc_disable(crtc, encoder, NULL, channel); ++ vc4_hdmi = encoder_to_vc4_hdmi(encoder); ++ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); ++ if (ret) ++ return ret; ++ ++ ret = vc4_crtc_disable(crtc, encoder, NULL, channel); ++ if (ret) ++ return ret; ++ ++ /* ++ * post_crtc_powerdown will have called pm_runtime_put, so we ++ * don't need it here otherwise we'll get the reference counting ++ * wrong. ++ */ ++ ++ return 0; + } + + static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, +@@ -691,14 +710,14 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) + struct drm_crtc *crtc = &vc4_crtc->base; + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); +- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); +- u32 chan = vc4_state->assigned_channel; ++ u32 chan = vc4_crtc->current_hvs_channel; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); ++ spin_lock(&vc4_crtc->irq_lock); + if (vc4_crtc->event && +- (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)) || +- vc4_state->feed_txp)) { ++ (vc4_crtc->current_dlist == HVS_READ(SCALER_DISPLACTX(chan)) || ++ vc4_crtc->feeds_txp)) { + drm_crtc_send_vblank_event(crtc, vc4_crtc->event); + vc4_crtc->event = NULL; + drm_crtc_vblank_put(crtc); +@@ -711,6 +730,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) + */ + vc4_hvs_unmask_underrun(dev, chan); + } ++ spin_unlock(&vc4_crtc->irq_lock); + spin_unlock_irqrestore(&dev->event_lock, flags); + } + +@@ -876,7 +896,6 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) + return NULL; + + old_vc4_state = to_vc4_crtc_state(crtc->state); +- vc4_state->feed_txp = old_vc4_state->feed_txp; + vc4_state->margins = old_vc4_state->margins; + vc4_state->assigned_channel = old_vc4_state->assigned_channel; + +@@ -937,6 +956,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { + static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { + .mode_valid = vc4_crtc_mode_valid, + .atomic_check = vc4_crtc_atomic_check, ++ .atomic_begin = vc4_hvs_atomic_begin, + .atomic_flush = vc4_hvs_atomic_flush, + .atomic_enable = vc4_crtc_atomic_enable, + .atomic_disable = vc4_crtc_atomic_disable, +@@ -1111,6 +1131,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, + return PTR_ERR(primary_plane); + } + ++ spin_lock_init(&vc4_crtc->irq_lock); + drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, + crtc_funcs, NULL); + drm_crtc_helper_add(crtc, crtc_helper_funcs); +diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h +index ef73e0aaf7261..4b550ebd9572d 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -495,6 +495,33 @@ struct vc4_crtc { + struct drm_pending_vblank_event *event; + + struct debugfs_regset32 regset; ++ ++ /** ++ * @feeds_txp: True if the CRTC feeds our writeback controller. ++ */ ++ bool feeds_txp; ++ ++ /** ++ * @irq_lock: Spinlock protecting the resources shared between ++ * the atomic code and our vblank handler. ++ */ ++ spinlock_t irq_lock; ++ ++ /** ++ * @current_dlist: Start offset of the display list currently ++ * set in the HVS for that CRTC. Protected by @irq_lock, and ++ * copied in vc4_hvs_update_dlist() for the CRTC interrupt ++ * handler to have access to that value. ++ */ ++ unsigned int current_dlist; ++ ++ /** ++ * @current_hvs_channel: HVS channel currently assigned to the ++ * CRTC. Protected by @irq_lock, and copied in ++ * vc4_hvs_atomic_begin() for the CRTC interrupt handler to have ++ * access to that value. ++ */ ++ unsigned int current_hvs_channel; + }; + + static inline struct vc4_crtc * +@@ -521,7 +548,6 @@ struct vc4_crtc_state { + struct drm_crtc_state base; + /* Dlist area for this CRTC configuration. */ + struct drm_mm_node mm; +- bool feed_txp; + bool txp_armed; + unsigned int assigned_channel; + +@@ -908,6 +934,7 @@ extern struct platform_driver vc4_hvs_driver; + void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output); + int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output); + int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); ++void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state); + void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state); + void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state); + void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); +diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c +index a185027911ce5..d09c1ea60c04e 100644 +--- a/drivers/gpu/drm/vc4/vc4_dsi.c ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -1262,7 +1262,6 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) + { + struct vc4_dsi *dsi = host_to_dsi(host); +- int ret; + + dsi->lanes = device->lanes; + dsi->channel = device->channel; +@@ -1297,18 +1296,15 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host, + return 0; + } + +- ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops); +- if (ret) { +- mipi_dsi_host_unregister(&dsi->dsi_host); +- return ret; +- } +- +- return 0; ++ return component_add(&dsi->pdev->dev, &vc4_dsi_ops); + } + + static int vc4_dsi_host_detach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) + { ++ struct vc4_dsi *dsi = host_to_dsi(host); ++ ++ component_del(&dsi->pdev->dev, &vc4_dsi_ops); + return 0; + } + +@@ -1706,9 +1702,7 @@ static int vc4_dsi_dev_remove(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct vc4_dsi *dsi = dev_get_drvdata(dev); + +- component_del(&pdev->dev, &vc4_dsi_ops); + mipi_dsi_host_unregister(&dsi->dsi_host); +- + return 0; + } + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index ed8a4b7f8b6e2..9170d948b4483 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -94,6 +94,7 @@ + # define VC4_HD_M_SW_RST BIT(2) + # define VC4_HD_M_ENABLE BIT(0) + ++#define HSM_MIN_CLOCK_FREQ 120000000 + #define CEC_CLOCK_FREQ 40000 + + #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) +@@ -161,12 +162,16 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) + static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} + #endif + ++static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder); ++ + static enum drm_connector_status + vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + { + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + bool connected = false; + ++ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); ++ + if (vc4_hdmi->hpd_gpio && + gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) { + connected = true; +@@ -187,10 +192,13 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + } + } + ++ vc4_hdmi_enable_scrambling(&vc4_hdmi->encoder.base.base); ++ pm_runtime_put(&vc4_hdmi->pdev->dev); + return connector_status_connected; + } + + cec_phys_addr_invalidate(vc4_hdmi->cec_adap); ++ pm_runtime_put(&vc4_hdmi->pdev->dev); + return connector_status_disconnected; + } + +@@ -627,7 +635,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder, + vc4_hdmi->variant->phy_disable(vc4_hdmi); + + clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); +- clk_disable_unprepare(vc4_hdmi->hsm_clock); + clk_disable_unprepare(vc4_hdmi->pixel_clock); + + ret = pm_runtime_put(&vc4_hdmi->pdev->dev); +@@ -893,28 +900,10 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, + conn_state_to_vc4_hdmi_conn_state(conn_state); + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); +- unsigned long bvb_rate, pixel_rate, hsm_rate; ++ unsigned long pixel_rate = vc4_conn_state->pixel_rate; ++ unsigned long bvb_rate, hsm_rate; + int ret; + +- ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); +- if (ret < 0) { +- DRM_ERROR("Failed to retain power domain: %d\n", ret); +- return; +- } +- +- pixel_rate = vc4_conn_state->pixel_rate; +- ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); +- if (ret) { +- DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); +- return; +- } +- +- ret = clk_prepare_enable(vc4_hdmi->pixel_clock); +- if (ret) { +- DRM_ERROR("Failed to turn on pixel clock: %d\n", ret); +- return; +- } +- + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in +@@ -938,13 +927,25 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, + return; + } + +- ret = clk_prepare_enable(vc4_hdmi->hsm_clock); +- if (ret) { +- DRM_ERROR("Failed to turn on HSM clock: %d\n", ret); +- clk_disable_unprepare(vc4_hdmi->pixel_clock); ++ ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); ++ if (ret < 0) { ++ DRM_ERROR("Failed to retain power domain: %d\n", ret); + return; + } + ++ ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); ++ if (ret) { ++ DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); ++ goto err_put_runtime_pm; ++ } ++ ++ ret = clk_prepare_enable(vc4_hdmi->pixel_clock); ++ if (ret) { ++ DRM_ERROR("Failed to turn on pixel clock: %d\n", ret); ++ goto err_put_runtime_pm; ++ } ++ ++ + vc4_hdmi_cec_update_clk_div(vc4_hdmi); + + if (pixel_rate > 297000000) +@@ -957,17 +958,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, + ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate); + if (ret) { + DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); +- clk_disable_unprepare(vc4_hdmi->hsm_clock); +- clk_disable_unprepare(vc4_hdmi->pixel_clock); +- return; ++ goto err_disable_pixel_clock; + } + + ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); + if (ret) { + DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); +- clk_disable_unprepare(vc4_hdmi->hsm_clock); +- clk_disable_unprepare(vc4_hdmi->pixel_clock); +- return; ++ goto err_disable_pixel_clock; + } + + if (vc4_hdmi->variant->phy_init) +@@ -980,6 +977,15 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, + + if (vc4_hdmi->variant->set_timings) + vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode); ++ ++ return; ++ ++err_disable_pixel_clock: ++ clk_disable_unprepare(vc4_hdmi->pixel_clock); ++err_put_runtime_pm: ++ pm_runtime_put(&vc4_hdmi->pdev->dev); ++ ++ return; + } + + static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder, +@@ -1084,6 +1090,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, + unsigned long long tmds_rate; + + if (vc4_hdmi->variant->unsupported_odd_h_timings && ++ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && + ((mode->hdisplay % 2) || (mode->hsync_start % 2) || + (mode->hsync_end % 2) || (mode->htotal % 2))) + return -EINVAL; +@@ -1131,6 +1138,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + + if (vc4_hdmi->variant->unsupported_odd_h_timings && ++ !(mode->flags & DRM_MODE_FLAG_DBLCLK) && + ((mode->hdisplay % 2) || (mode->hsync_start % 2) || + (mode->hsync_end % 2) || (mode->htotal % 2))) + return MODE_H_ILLEGAL; +@@ -2098,6 +2106,27 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) + return 0; + } + ++static int __maybe_unused vc4_hdmi_runtime_suspend(struct device *dev) ++{ ++ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); ++ ++ clk_disable_unprepare(vc4_hdmi->hsm_clock); ++ ++ return 0; ++} ++ ++static int vc4_hdmi_runtime_resume(struct device *dev) ++{ ++ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_prepare_enable(vc4_hdmi->hsm_clock); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ + static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + { + const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); +@@ -2161,6 +2190,31 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + vc4_hdmi->disable_4kp60 = true; + } + ++ /* ++ * If we boot without any cable connected to the HDMI connector, ++ * the firmware will skip the HSM initialization and leave it ++ * with a rate of 0, resulting in a bus lockup when we're ++ * accessing the registers even if it's enabled. ++ * ++ * Let's put a sensible default at runtime_resume so that we ++ * don't end up in this situation. ++ */ ++ ret = clk_set_min_rate(vc4_hdmi->hsm_clock, HSM_MIN_CLOCK_FREQ); ++ if (ret) ++ goto err_put_ddc; ++ ++ /* ++ * We need to have the device powered up at this point to call ++ * our reset hook and for the CEC init. ++ */ ++ ret = vc4_hdmi_runtime_resume(dev); ++ if (ret) ++ goto err_put_ddc; ++ ++ pm_runtime_get_noresume(dev); ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ + if (vc4_hdmi->variant->reset) + vc4_hdmi->variant->reset(vc4_hdmi); + +@@ -2172,8 +2226,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); + } + +- pm_runtime_enable(dev); +- + drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); + +@@ -2197,6 +2249,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) + vc4_hdmi_debugfs_regs, + vc4_hdmi); + ++ pm_runtime_put_sync(dev); ++ + return 0; + + err_free_cec: +@@ -2207,6 +2261,7 @@ err_destroy_conn: + vc4_hdmi_connector_destroy(&vc4_hdmi->connector); + err_destroy_encoder: + drm_encoder_cleanup(encoder); ++ pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + err_put_ddc: + put_device(&vc4_hdmi->ddc->dev); +@@ -2352,11 +2407,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = { + {} + }; + ++static const struct dev_pm_ops vc4_hdmi_pm_ops = { ++ SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend, ++ vc4_hdmi_runtime_resume, ++ NULL) ++}; ++ + struct platform_driver vc4_hdmi_driver = { + .probe = vc4_hdmi_dev_probe, + .remove = vc4_hdmi_dev_remove, + .driver = { + .name = "vc4_hdmi", + .of_match_table = vc4_hdmi_dt_match, ++ .pm = &vc4_hdmi_pm_ops, + }, + }; +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index c239045e05d6f..604933e20e6a2 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -365,17 +365,16 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); ++ unsigned long flags; + + if (crtc->state->event) { +- unsigned long flags; +- + crtc->state->event->pipe = drm_crtc_index(crtc); + + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irqsave(&dev->event_lock, flags); + +- if (!vc4_state->feed_txp || vc4_state->txp_armed) { ++ if (!vc4_crtc->feeds_txp || vc4_state->txp_armed) { + vc4_crtc->event = crtc->state->event; + crtc->state->event = NULL; + } +@@ -388,6 +387,22 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) + HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), + vc4_state->mm.start); + } ++ ++ spin_lock_irqsave(&vc4_crtc->irq_lock, flags); ++ vc4_crtc->current_dlist = vc4_state->mm.start; ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); ++} ++ ++void vc4_hvs_atomic_begin(struct drm_crtc *crtc, ++ struct drm_atomic_state *state) ++{ ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&vc4_crtc->irq_lock, flags); ++ vc4_crtc->current_hvs_channel = vc4_state->assigned_channel; ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, flags); + } + + void vc4_hvs_atomic_enable(struct drm_crtc *crtc, +@@ -395,10 +410,9 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, + { + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); +- struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); +- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(new_crtc_state); + struct drm_display_mode *mode = &crtc->state->adjusted_mode; +- bool oneshot = vc4_state->feed_txp; ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ bool oneshot = vc4_crtc->feeds_txp; + + vc4_hvs_update_dlist(crtc); + vc4_hvs_init_channel(vc4, crtc, mode, oneshot); +diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c +index f0b3e4cf5bceb..6030d4a821555 100644 +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -233,6 +233,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, + unsigned int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + u32 dispctrl; + u32 dsp3_mux; +@@ -253,7 +254,7 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, + * TXP IP, and we need to disable the FIFO2 -> pixelvalve1 + * route. + */ +- if (vc4_state->feed_txp) ++ if (vc4_crtc->feeds_txp) + dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX); + else + dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); +@@ -337,10 +338,10 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + struct drm_device *dev = state->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; +- struct drm_crtc_state *old_crtc_state; + struct drm_crtc_state *new_crtc_state; + struct drm_crtc *crtc; + struct vc4_hvs_state *old_hvs_state; ++ unsigned int channel; + int i; + + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { +@@ -353,30 +354,32 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); + } + +- if (vc4->hvs->hvs5) +- clk_set_min_rate(hvs->core_clk, 500000000); +- + old_hvs_state = vc4_hvs_get_old_global_state(state); +- if (!old_hvs_state) ++ if (IS_ERR(old_hvs_state)) + return; + +- for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { +- struct vc4_crtc_state *vc4_crtc_state = +- to_vc4_crtc_state(old_crtc_state); +- unsigned int channel = vc4_crtc_state->assigned_channel; ++ for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { ++ struct drm_crtc_commit *commit; + int ret; + +- if (channel == VC4_HVS_CHANNEL_DISABLED) ++ if (!old_hvs_state->fifo_state[channel].in_use) + continue; + +- if (!old_hvs_state->fifo_state[channel].in_use) ++ commit = old_hvs_state->fifo_state[channel].pending_commit; ++ if (!commit) + continue; + +- ret = drm_crtc_commit_wait(old_hvs_state->fifo_state[channel].pending_commit); ++ ret = drm_crtc_commit_wait(commit); + if (ret) + drm_err(dev, "Timed out waiting for commit\n"); ++ ++ drm_crtc_commit_put(commit); ++ old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + ++ if (vc4->hvs->hvs5) ++ clk_set_min_rate(hvs->core_clk, 500000000); ++ + drm_atomic_helper_commit_modeset_disables(dev, state); + + vc4_ctm_commit(vc4, state); +@@ -410,8 +413,8 @@ static int vc4_atomic_commit_setup(struct drm_atomic_state *state) + unsigned int i; + + hvs_state = vc4_hvs_get_new_global_state(state); +- if (!hvs_state) +- return -EINVAL; ++ if (WARN_ON(IS_ERR(hvs_state))) ++ return PTR_ERR(hvs_state); + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_crtc_state = +@@ -668,12 +671,6 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) + + for (i = 0; i < HVS_NUM_CHANNELS; i++) { + state->fifo_state[i].in_use = old_state->fifo_state[i].in_use; +- +- if (!old_state->fifo_state[i].pending_commit) +- continue; +- +- state->fifo_state[i].pending_commit = +- drm_crtc_commit_get(old_state->fifo_state[i].pending_commit); + } + + return &state->base; +@@ -762,8 +759,8 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, + unsigned int i; + + hvs_new_state = vc4_hvs_get_global_state(state); +- if (!hvs_new_state) +- return -EINVAL; ++ if (IS_ERR(hvs_new_state)) ++ return PTR_ERR(hvs_new_state); + + for (i = 0; i < ARRAY_SIZE(hvs_new_state->fifo_state); i++) + if (!hvs_new_state->fifo_state[i].in_use) +diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c +index 2fc7f4b5fa098..9809ca3e29451 100644 +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -391,7 +391,6 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc, + { + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); +- struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + int ret; + + ret = vc4_hvs_atomic_check(crtc, state); +@@ -399,7 +398,6 @@ static int vc4_txp_atomic_check(struct drm_crtc *crtc, + return ret; + + crtc_state->no_vblank = true; +- vc4_state->feed_txp = true; + + return 0; + } +@@ -437,6 +435,7 @@ static void vc4_txp_atomic_disable(struct drm_crtc *crtc, + + static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = { + .atomic_check = vc4_txp_atomic_check, ++ .atomic_begin = vc4_hvs_atomic_begin, + .atomic_flush = vc4_hvs_atomic_flush, + .atomic_enable = vc4_txp_atomic_enable, + .atomic_disable = vc4_txp_atomic_disable, +@@ -482,6 +481,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) + + vc4_crtc->pdev = pdev; + vc4_crtc->data = &vc4_txp_crtc_data; ++ vc4_crtc->feeds_txp = true; + + txp->pdev = pdev; + +diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c +index 2e71e91278b45..93a41d018dca6 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_vq.c ++++ b/drivers/gpu/drm/virtio/virtgpu_vq.c +@@ -91,9 +91,7 @@ virtio_gpu_get_vbuf(struct virtio_gpu_device *vgdev, + { + struct virtio_gpu_vbuffer *vbuf; + +- vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL); +- if (!vbuf) +- return ERR_PTR(-ENOMEM); ++ vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL | __GFP_NOFAIL); + + BUG_ON(size > MAX_INLINE_CMD_SIZE || + size < sizeof(struct virtio_gpu_ctrl_hdr)); +@@ -147,10 +145,6 @@ static void *virtio_gpu_alloc_cmd_resp(struct virtio_gpu_device *vgdev, + + vbuf = virtio_gpu_get_vbuf(vgdev, cmd_size, + resp_size, resp_buf, cb); +- if (IS_ERR(vbuf)) { +- *vbuffer_p = NULL; +- return ERR_CAST(vbuf); +- } + *vbuffer_p = vbuf; + return (struct virtio_gpu_command *)vbuf->buf; + } +diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile +index bc323f7d40321..18edc7ca5b454 100644 +--- a/drivers/gpu/drm/vmwgfx/Makefile ++++ b/drivers/gpu/drm/vmwgfx/Makefile +@@ -9,9 +9,8 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ + vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \ + vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \ + vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \ +- vmwgfx_devcaps.o ttm_object.o ttm_memory.o ++ vmwgfx_devcaps.o ttm_object.o ttm_memory.o vmwgfx_system_manager.o + + vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o +-vmwgfx-$(CONFIG_TRANSPARENT_HUGEPAGE) += vmwgfx_thp.o + + obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o +diff --git a/drivers/gpu/drm/vmwgfx/ttm_memory.c b/drivers/gpu/drm/vmwgfx/ttm_memory.c +index edd17c30d5a51..2ced4c06ca451 100644 +--- a/drivers/gpu/drm/vmwgfx/ttm_memory.c ++++ b/drivers/gpu/drm/vmwgfx/ttm_memory.c +@@ -34,7 +34,6 @@ + #include <linux/mm.h> + #include <linux/module.h> + #include <linux/slab.h> +-#include <linux/swap.h> + + #include <drm/drm_device.h> + #include <drm/drm_file.h> +@@ -173,69 +172,7 @@ static struct kobj_type ttm_mem_zone_kobj_type = { + .sysfs_ops = &ttm_mem_zone_ops, + .default_attrs = ttm_mem_zone_attrs, + }; +- +-static struct attribute ttm_mem_global_lower_mem_limit = { +- .name = "lower_mem_limit", +- .mode = S_IRUGO | S_IWUSR +-}; +- +-static ssize_t ttm_mem_global_show(struct kobject *kobj, +- struct attribute *attr, +- char *buffer) +-{ +- struct ttm_mem_global *glob = +- container_of(kobj, struct ttm_mem_global, kobj); +- uint64_t val = 0; +- +- spin_lock(&glob->lock); +- val = glob->lower_mem_limit; +- spin_unlock(&glob->lock); +- /* convert from number of pages to KB */ +- val <<= (PAGE_SHIFT - 10); +- return snprintf(buffer, PAGE_SIZE, "%llu\n", +- (unsigned long long) val); +-} +- +-static ssize_t ttm_mem_global_store(struct kobject *kobj, +- struct attribute *attr, +- const char *buffer, +- size_t size) +-{ +- int chars; +- uint64_t val64; +- unsigned long val; +- struct ttm_mem_global *glob = +- container_of(kobj, struct ttm_mem_global, kobj); +- +- chars = sscanf(buffer, "%lu", &val); +- if (chars == 0) +- return size; +- +- val64 = val; +- /* convert from KB to number of pages */ +- val64 >>= (PAGE_SHIFT - 10); +- +- spin_lock(&glob->lock); +- glob->lower_mem_limit = val64; +- spin_unlock(&glob->lock); +- +- return size; +-} +- +-static struct attribute *ttm_mem_global_attrs[] = { +- &ttm_mem_global_lower_mem_limit, +- NULL +-}; +- +-static const struct sysfs_ops ttm_mem_global_ops = { +- .show = &ttm_mem_global_show, +- .store = &ttm_mem_global_store, +-}; +- +-static struct kobj_type ttm_mem_glob_kobj_type = { +- .sysfs_ops = &ttm_mem_global_ops, +- .default_attrs = ttm_mem_global_attrs, +-}; ++static struct kobj_type ttm_mem_glob_kobj_type = {0}; + + static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob, + bool from_wq, uint64_t extra) +@@ -435,11 +372,6 @@ int ttm_mem_global_init(struct ttm_mem_global *glob, struct device *dev) + + si_meminfo(&si); + +- spin_lock(&glob->lock); +- /* set it as 0 by default to keep original behavior of OOM */ +- glob->lower_mem_limit = 0; +- spin_unlock(&glob->lock); +- + ret = ttm_mem_init_kernel_zone(glob, &si); + if (unlikely(ret != 0)) + goto out_no_zone; +@@ -527,35 +459,6 @@ void ttm_mem_global_free(struct ttm_mem_global *glob, + } + EXPORT_SYMBOL(ttm_mem_global_free); + +-/* +- * check if the available mem is under lower memory limit +- * +- * a. if no swap disk at all or free swap space is under swap_mem_limit +- * but available system mem is bigger than sys_mem_limit, allow TTM +- * allocation; +- * +- * b. if the available system mem is less than sys_mem_limit but free +- * swap disk is bigger than swap_mem_limit, allow TTM allocation. +- */ +-bool +-ttm_check_under_lowerlimit(struct ttm_mem_global *glob, +- uint64_t num_pages, +- struct ttm_operation_ctx *ctx) +-{ +- int64_t available; +- +- /* We allow over commit during suspend */ +- if (ctx->force_alloc) +- return false; +- +- available = get_nr_swap_pages() + si_mem_available(); +- available -= num_pages; +- if (available < glob->lower_mem_limit) +- return true; +- +- return false; +-} +- + static int ttm_mem_global_reserve(struct ttm_mem_global *glob, + struct ttm_mem_zone *single_zone, + uint64_t amount, bool reserve) +diff --git a/drivers/gpu/drm/vmwgfx/ttm_memory.h b/drivers/gpu/drm/vmwgfx/ttm_memory.h +index c50dba7744854..7b0d617ebcb1e 100644 +--- a/drivers/gpu/drm/vmwgfx/ttm_memory.h ++++ b/drivers/gpu/drm/vmwgfx/ttm_memory.h +@@ -50,8 +50,6 @@ + * @work: The workqueue callback for the shrink queue. + * @lock: Lock to protect the @shrink - and the memory accounting members, + * that is, essentially the whole structure with some exceptions. +- * @lower_mem_limit: include lower limit of swap space and lower limit of +- * system memory. + * @zones: Array of pointers to accounting zones. + * @num_zones: Number of populated entries in the @zones array. + * @zone_kernel: Pointer to the kernel zone. +@@ -69,7 +67,6 @@ extern struct ttm_mem_global { + struct workqueue_struct *swap_queue; + struct work_struct work; + spinlock_t lock; +- uint64_t lower_mem_limit; + struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES]; + unsigned int num_zones; + struct ttm_mem_zone *zone_kernel; +@@ -91,6 +88,5 @@ int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, + void ttm_mem_global_free_page(struct ttm_mem_global *glob, + struct page *page, uint64_t size); + size_t ttm_round_pot(size_t size); +-bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, uint64_t num_pages, +- struct ttm_operation_ctx *ctx); ++ + #endif +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +index 67db472d3493c..a3bfbb6c3e14a 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +@@ -145,6 +145,13 @@ struct vmw_fifo_state *vmw_fifo_create(struct vmw_private *dev_priv) + (unsigned int) max, + (unsigned int) min, + (unsigned int) fifo->capabilities); ++ ++ if (unlikely(min >= max)) { ++ drm_warn(&dev_priv->drm, ++ "FIFO memory is not usable. Driver failed to initialize."); ++ return ERR_PTR(-ENXIO); ++ } ++ + return fifo; + } + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index ab9a1750e1dff..8449d09c06f7a 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -707,23 +707,15 @@ static int vmw_dma_masks(struct vmw_private *dev_priv) + static int vmw_vram_manager_init(struct vmw_private *dev_priv) + { + int ret; +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +- ret = vmw_thp_init(dev_priv); +-#else + ret = ttm_range_man_init(&dev_priv->bdev, TTM_PL_VRAM, false, + dev_priv->vram_size >> PAGE_SHIFT); +-#endif + ttm_resource_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false); + return ret; + } + + static void vmw_vram_manager_fini(struct vmw_private *dev_priv) + { +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +- vmw_thp_fini(dev_priv); +-#else + ttm_range_man_fini(&dev_priv->bdev, TTM_PL_VRAM); +-#endif + } + + static int vmw_setup_pci_resources(struct vmw_private *dev, +@@ -1071,6 +1063,12 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) + "3D will be disabled.\n"); + dev_priv->has_mob = false; + } ++ if (vmw_sys_man_init(dev_priv) != 0) { ++ drm_info(&dev_priv->drm, ++ "No MOB page table memory available. " ++ "3D will be disabled.\n"); ++ dev_priv->has_mob = false; ++ } + } + + if (dev_priv->has_mob && (dev_priv->capabilities & SVGA_CAP_DX)) { +@@ -1121,8 +1119,10 @@ out_no_fifo: + vmw_overlay_close(dev_priv); + vmw_kms_close(dev_priv); + out_no_kms: +- if (dev_priv->has_mob) ++ if (dev_priv->has_mob) { + vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB); ++ vmw_sys_man_fini(dev_priv); ++ } + if (dev_priv->has_gmr) + vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR); + vmw_devcaps_destroy(dev_priv); +@@ -1172,8 +1172,10 @@ static void vmw_driver_unload(struct drm_device *dev) + vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR); + + vmw_release_device_early(dev_priv); +- if (dev_priv->has_mob) ++ if (dev_priv->has_mob) { + vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB); ++ vmw_sys_man_fini(dev_priv); ++ } + vmw_devcaps_destroy(dev_priv); + vmw_vram_manager_fini(dev_priv); + ttm_device_fini(&dev_priv->bdev); +@@ -1617,34 +1619,40 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver); + if (ret) +- return ret; ++ goto out_error; + + ret = pcim_enable_device(pdev); + if (ret) +- return ret; ++ goto out_error; + + vmw = devm_drm_dev_alloc(&pdev->dev, &driver, + struct vmw_private, drm); +- if (IS_ERR(vmw)) +- return PTR_ERR(vmw); ++ if (IS_ERR(vmw)) { ++ ret = PTR_ERR(vmw); ++ goto out_error; ++ } + + pci_set_drvdata(pdev, &vmw->drm); + + ret = ttm_mem_global_init(&ttm_mem_glob, &pdev->dev); + if (ret) +- return ret; ++ goto out_error; + + ret = vmw_driver_load(vmw, ent->device); + if (ret) +- return ret; ++ goto out_release; + + ret = drm_dev_register(&vmw->drm, 0); +- if (ret) { +- vmw_driver_unload(&vmw->drm); +- return ret; +- } ++ if (ret) ++ goto out_unload; + + return 0; ++out_unload: ++ vmw_driver_unload(&vmw->drm); ++out_release: ++ ttm_mem_global_release(&ttm_mem_glob); ++out_error: ++ return ret; + } + + static int __init vmwgfx_init(void) +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +index a833751099b55..f9f28516ffb41 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +@@ -59,11 +59,8 @@ + #define VMWGFX_DRIVER_MINOR 19 + #define VMWGFX_DRIVER_PATCHLEVEL 0 + #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) +-#define VMWGFX_MAX_RELOCATIONS 2048 +-#define VMWGFX_MAX_VALIDATIONS 2048 + #define VMWGFX_MAX_DISPLAYS 16 + #define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768 +-#define VMWGFX_ENABLE_SCREEN_TARGET_OTABLE 1 + + #define VMWGFX_PCI_ID_SVGA2 0x0405 + #define VMWGFX_PCI_ID_SVGA3 0x0406 +@@ -82,8 +79,9 @@ + VMWGFX_NUM_GB_SURFACE +\ + VMWGFX_NUM_GB_SCREEN_TARGET) + +-#define VMW_PL_GMR (TTM_PL_PRIV + 0) +-#define VMW_PL_MOB (TTM_PL_PRIV + 1) ++#define VMW_PL_GMR (TTM_PL_PRIV + 0) ++#define VMW_PL_MOB (TTM_PL_PRIV + 1) ++#define VMW_PL_SYSTEM (TTM_PL_PRIV + 2) + + #define VMW_RES_CONTEXT ttm_driver_type0 + #define VMW_RES_SURFACE ttm_driver_type1 +@@ -1039,7 +1037,6 @@ extern struct ttm_placement vmw_vram_placement; + extern struct ttm_placement vmw_vram_sys_placement; + extern struct ttm_placement vmw_vram_gmr_placement; + extern struct ttm_placement vmw_sys_placement; +-extern struct ttm_placement vmw_evictable_placement; + extern struct ttm_placement vmw_srf_placement; + extern struct ttm_placement vmw_mob_placement; + extern struct ttm_placement vmw_nonfixed_placement; +@@ -1115,15 +1112,14 @@ extern int vmw_execbuf_fence_commands(struct drm_file *file_priv, + struct vmw_private *dev_priv, + struct vmw_fence_obj **p_fence, + uint32_t *p_handle); +-extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, ++extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, + struct vmw_fpriv *vmw_fp, + int ret, + struct drm_vmw_fence_rep __user + *user_fence_rep, + struct vmw_fence_obj *fence, + uint32_t fence_handle, +- int32_t out_fence_fd, +- struct sync_file *sync_file); ++ int32_t out_fence_fd); + bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); + + /** +@@ -1251,6 +1247,12 @@ int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); + int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); + void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type); + ++/** ++ * System memory manager ++ */ ++int vmw_sys_man_init(struct vmw_private *dev_priv); ++void vmw_sys_man_fini(struct vmw_private *dev_priv); ++ + /** + * Prime - vmwgfx_prime.c + */ +@@ -1550,16 +1552,7 @@ void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo, + pgoff_t start, pgoff_t end); + vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf); + vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf); +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf, +- enum page_entry_size pe_size); +-#endif + +-/* Transparent hugepage support - vmwgfx_thp.c */ +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-extern int vmw_thp_init(struct vmw_private *dev_priv); +-void vmw_thp_fini(struct vmw_private *dev_priv); +-#endif + + /** + * VMW_DEBUG_KMS - Debug output for kernel mode-setting +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +index 5f2ffa9de5c8f..9144e8f88c812 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +@@ -3823,17 +3823,17 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, + * Also if copying fails, user-space will be unable to signal the fence object + * so we wait for it immediately, and then unreference the user-space reference. + */ +-void ++int + vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, + struct vmw_fpriv *vmw_fp, int ret, + struct drm_vmw_fence_rep __user *user_fence_rep, + struct vmw_fence_obj *fence, uint32_t fence_handle, +- int32_t out_fence_fd, struct sync_file *sync_file) ++ int32_t out_fence_fd) + { + struct drm_vmw_fence_rep fence_rep; + + if (user_fence_rep == NULL) +- return; ++ return 0; + + memset(&fence_rep, 0, sizeof(fence_rep)); + +@@ -3861,20 +3861,14 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, + * handle. + */ + if (unlikely(ret != 0) && (fence_rep.error == 0)) { +- if (sync_file) +- fput(sync_file->file); +- +- if (fence_rep.fd != -1) { +- put_unused_fd(fence_rep.fd); +- fence_rep.fd = -1; +- } +- + ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle, + TTM_REF_USAGE); + VMW_DEBUG_USER("Fence copy error. Syncing.\n"); + (void) vmw_fence_obj_wait(fence, false, false, + VMW_FENCE_WAIT_TIMEOUT); + } ++ ++ return ret ? -EFAULT : 0; + } + + /** +@@ -4212,16 +4206,23 @@ int vmw_execbuf_process(struct drm_file *file_priv, + + (void) vmw_fence_obj_wait(fence, false, false, + VMW_FENCE_WAIT_TIMEOUT); ++ } ++ } ++ ++ ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, ++ user_fence_rep, fence, handle, out_fence_fd); ++ ++ if (sync_file) { ++ if (ret) { ++ /* usercopy of fence failed, put the file object */ ++ fput(sync_file->file); ++ put_unused_fd(out_fence_fd); + } else { + /* Link the fence with the FD created earlier */ + fd_install(out_fence_fd, sync_file->file); + } + } + +- vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, +- user_fence_rep, fence, handle, out_fence_fd, +- sync_file); +- + /* Don't unreference when handing fence out */ + if (unlikely(out_fence != NULL)) { + *out_fence = fence; +@@ -4239,7 +4240,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, + */ + vmw_validation_unref_lists(&val_ctx); + +- return 0; ++ return ret; + + out_unlock_binding: + mutex_unlock(&dev_priv->binding_mutex); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +index 9fe12329a4d58..b4d9d7258a546 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -1159,7 +1159,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + } + + vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, +- handle, -1, NULL); ++ handle, -1); + vmw_fence_obj_unreference(&fence); + return 0; + out_no_create: +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +index 74fa419092138..14e8f665b13be 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -2516,7 +2516,7 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv, + if (file_priv) + vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), + ret, user_fence_rep, fence, +- handle, -1, NULL); ++ handle, -1); + if (out_fence) + *out_fence = fence; + else +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +index f9394207dd3cc..632e587519722 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 OR MIT + /************************************************************************** + * +- * Copyright 2012-2015 VMware, Inc., Palo Alto, CA., USA ++ * Copyright 2012-2021 VMware, Inc., Palo Alto, CA., USA + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the +@@ -29,12 +29,6 @@ + + #include "vmwgfx_drv.h" + +-/* +- * If we set up the screen target otable, screen objects stop working. +- */ +- +-#define VMW_OTABLE_SETUP_SUB ((VMWGFX_ENABLE_SCREEN_TARGET_OTABLE ? 0 : 1)) +- + #ifdef CONFIG_64BIT + #define VMW_PPN_SIZE 8 + #define VMW_MOBFMT_PTDEPTH_0 SVGA3D_MOBFMT_PT64_0 +@@ -75,7 +69,7 @@ static const struct vmw_otable pre_dx_tables[] = { + {VMWGFX_NUM_GB_CONTEXT * sizeof(SVGAOTableContextEntry), NULL, true}, + {VMWGFX_NUM_GB_SHADER * sizeof(SVGAOTableShaderEntry), NULL, true}, + {VMWGFX_NUM_GB_SCREEN_TARGET * sizeof(SVGAOTableScreenTargetEntry), +- NULL, VMWGFX_ENABLE_SCREEN_TARGET_OTABLE} ++ NULL, true} + }; + + static const struct vmw_otable dx_tables[] = { +@@ -84,7 +78,7 @@ static const struct vmw_otable dx_tables[] = { + {VMWGFX_NUM_GB_CONTEXT * sizeof(SVGAOTableContextEntry), NULL, true}, + {VMWGFX_NUM_GB_SHADER * sizeof(SVGAOTableShaderEntry), NULL, true}, + {VMWGFX_NUM_GB_SCREEN_TARGET * sizeof(SVGAOTableScreenTargetEntry), +- NULL, VMWGFX_ENABLE_SCREEN_TARGET_OTABLE}, ++ NULL, true}, + {VMWGFX_NUM_DXCONTEXT * sizeof(SVGAOTableDXContextEntry), NULL, true}, + }; + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c +index e5a9a5cbd01a7..922317d1acc8a 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c +@@ -477,7 +477,7 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf) + else + prot = vm_get_page_prot(vma->vm_flags); + +- ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault, 1); ++ ret = ttm_bo_vm_fault_reserved(vmf, prot, num_prefault); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret; + +@@ -486,73 +486,3 @@ out_unlock: + + return ret; + } +- +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf, +- enum page_entry_size pe_size) +-{ +- struct vm_area_struct *vma = vmf->vma; +- struct ttm_buffer_object *bo = (struct ttm_buffer_object *) +- vma->vm_private_data; +- struct vmw_buffer_object *vbo = +- container_of(bo, struct vmw_buffer_object, base); +- pgprot_t prot; +- vm_fault_t ret; +- pgoff_t fault_page_size; +- bool write = vmf->flags & FAULT_FLAG_WRITE; +- +- switch (pe_size) { +- case PE_SIZE_PMD: +- fault_page_size = HPAGE_PMD_SIZE >> PAGE_SHIFT; +- break; +-#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +- case PE_SIZE_PUD: +- fault_page_size = HPAGE_PUD_SIZE >> PAGE_SHIFT; +- break; +-#endif +- default: +- WARN_ON_ONCE(1); +- return VM_FAULT_FALLBACK; +- } +- +- /* Always do write dirty-tracking and COW on PTE level. */ +- if (write && (READ_ONCE(vbo->dirty) || is_cow_mapping(vma->vm_flags))) +- return VM_FAULT_FALLBACK; +- +- ret = ttm_bo_vm_reserve(bo, vmf); +- if (ret) +- return ret; +- +- if (vbo->dirty) { +- pgoff_t allowed_prefault; +- unsigned long page_offset; +- +- page_offset = vmf->pgoff - +- drm_vma_node_start(&bo->base.vma_node); +- if (page_offset >= bo->resource->num_pages || +- vmw_resources_clean(vbo, page_offset, +- page_offset + PAGE_SIZE, +- &allowed_prefault)) { +- ret = VM_FAULT_SIGBUS; +- goto out_unlock; +- } +- +- /* +- * Write protect, so we get a new fault on write, and can +- * split. +- */ +- prot = vm_get_page_prot(vma->vm_flags & ~VM_SHARED); +- } else { +- prot = vm_get_page_prot(vma->vm_flags); +- } +- +- ret = ttm_bo_vm_fault_reserved(vmf, prot, 1, fault_page_size); +- if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) +- return ret; +- +-out_unlock: +- dma_resv_unlock(bo->base.resv); +- +- return ret; +-} +-#endif +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +index d85310b2608dd..f5e90d0e2d0f8 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +@@ -1872,8 +1872,8 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) + int i, ret; + + +- /* Do nothing if Screen Target support is turned off */ +- if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE || !dev_priv->has_mob) ++ /* Do nothing if there's no support for MOBs */ ++ if (!dev_priv->has_mob) + return -ENOSYS; + + if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c +new file mode 100644 +index 0000000000000..b0005b03a6174 +--- /dev/null ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c +@@ -0,0 +1,90 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* ++ * Copyright 2021 VMware, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, ++ * modify, merge, publish, distribute, sublicense, and/or sell copies ++ * of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS ++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++ * SOFTWARE. ++ * ++ */ ++ ++#include "vmwgfx_drv.h" ++ ++#include <drm/ttm/ttm_bo_driver.h> ++#include <drm/ttm/ttm_device.h> ++#include <drm/ttm/ttm_placement.h> ++#include <drm/ttm/ttm_resource.h> ++#include <linux/slab.h> ++ ++ ++static int vmw_sys_man_alloc(struct ttm_resource_manager *man, ++ struct ttm_buffer_object *bo, ++ const struct ttm_place *place, ++ struct ttm_resource **res) ++{ ++ *res = kzalloc(sizeof(**res), GFP_KERNEL); ++ if (!*res) ++ return -ENOMEM; ++ ++ ttm_resource_init(bo, place, *res); ++ return 0; ++} ++ ++static void vmw_sys_man_free(struct ttm_resource_manager *man, ++ struct ttm_resource *res) ++{ ++ kfree(res); ++} ++ ++static const struct ttm_resource_manager_func vmw_sys_manager_func = { ++ .alloc = vmw_sys_man_alloc, ++ .free = vmw_sys_man_free, ++}; ++ ++int vmw_sys_man_init(struct vmw_private *dev_priv) ++{ ++ struct ttm_device *bdev = &dev_priv->bdev; ++ struct ttm_resource_manager *man = ++ kzalloc(sizeof(*man), GFP_KERNEL); ++ ++ if (!man) ++ return -ENOMEM; ++ ++ man->use_tt = true; ++ man->func = &vmw_sys_manager_func; ++ ++ ttm_resource_manager_init(man, 0); ++ ttm_set_driver_manager(bdev, VMW_PL_SYSTEM, man); ++ ttm_resource_manager_set_used(man, true); ++ return 0; ++} ++ ++void vmw_sys_man_fini(struct vmw_private *dev_priv) ++{ ++ struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, ++ VMW_PL_SYSTEM); ++ ++ ttm_resource_manager_evict_all(&dev_priv->bdev, man); ++ ++ ttm_resource_manager_set_used(man, false); ++ ttm_resource_manager_cleanup(man); ++ ++ ttm_set_driver_manager(&dev_priv->bdev, VMW_PL_SYSTEM, NULL); ++ kfree(man); ++} +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +deleted file mode 100644 +index 2a3d3468e4e0a..0000000000000 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c ++++ /dev/null +@@ -1,184 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 OR MIT +-/* +- * Huge page-table-entry support for IO memory. +- * +- * Copyright (C) 2007-2019 Vmware, Inc. All rights reservedd. +- */ +-#include "vmwgfx_drv.h" +-#include <drm/ttm/ttm_bo_driver.h> +-#include <drm/ttm/ttm_placement.h> +-#include <drm/ttm/ttm_range_manager.h> +- +-/** +- * struct vmw_thp_manager - Range manager implementing huge page alignment +- * +- * @manager: TTM resource manager. +- * @mm: The underlying range manager. Protected by @lock. +- * @lock: Manager lock. +- */ +-struct vmw_thp_manager { +- struct ttm_resource_manager manager; +- struct drm_mm mm; +- spinlock_t lock; +-}; +- +-static struct vmw_thp_manager *to_thp_manager(struct ttm_resource_manager *man) +-{ +- return container_of(man, struct vmw_thp_manager, manager); +-} +- +-static const struct ttm_resource_manager_func vmw_thp_func; +- +-static int vmw_thp_insert_aligned(struct ttm_buffer_object *bo, +- struct drm_mm *mm, struct drm_mm_node *node, +- unsigned long align_pages, +- const struct ttm_place *place, +- struct ttm_resource *mem, +- unsigned long lpfn, +- enum drm_mm_insert_mode mode) +-{ +- if (align_pages >= bo->page_alignment && +- (!bo->page_alignment || align_pages % bo->page_alignment == 0)) { +- return drm_mm_insert_node_in_range(mm, node, +- mem->num_pages, +- align_pages, 0, +- place->fpfn, lpfn, mode); +- } +- +- return -ENOSPC; +-} +- +-static int vmw_thp_get_node(struct ttm_resource_manager *man, +- struct ttm_buffer_object *bo, +- const struct ttm_place *place, +- struct ttm_resource **res) +-{ +- struct vmw_thp_manager *rman = to_thp_manager(man); +- struct drm_mm *mm = &rman->mm; +- struct ttm_range_mgr_node *node; +- unsigned long align_pages; +- unsigned long lpfn; +- enum drm_mm_insert_mode mode = DRM_MM_INSERT_BEST; +- int ret; +- +- node = kzalloc(struct_size(node, mm_nodes, 1), GFP_KERNEL); +- if (!node) +- return -ENOMEM; +- +- ttm_resource_init(bo, place, &node->base); +- +- lpfn = place->lpfn; +- if (!lpfn) +- lpfn = man->size; +- +- mode = DRM_MM_INSERT_BEST; +- if (place->flags & TTM_PL_FLAG_TOPDOWN) +- mode = DRM_MM_INSERT_HIGH; +- +- spin_lock(&rman->lock); +- if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)) { +- align_pages = (HPAGE_PUD_SIZE >> PAGE_SHIFT); +- if (node->base.num_pages >= align_pages) { +- ret = vmw_thp_insert_aligned(bo, mm, &node->mm_nodes[0], +- align_pages, place, +- &node->base, lpfn, mode); +- if (!ret) +- goto found_unlock; +- } +- } +- +- align_pages = (HPAGE_PMD_SIZE >> PAGE_SHIFT); +- if (node->base.num_pages >= align_pages) { +- ret = vmw_thp_insert_aligned(bo, mm, &node->mm_nodes[0], +- align_pages, place, &node->base, +- lpfn, mode); +- if (!ret) +- goto found_unlock; +- } +- +- ret = drm_mm_insert_node_in_range(mm, &node->mm_nodes[0], +- node->base.num_pages, +- bo->page_alignment, 0, +- place->fpfn, lpfn, mode); +-found_unlock: +- spin_unlock(&rman->lock); +- +- if (unlikely(ret)) { +- kfree(node); +- } else { +- node->base.start = node->mm_nodes[0].start; +- *res = &node->base; +- } +- +- return ret; +-} +- +-static void vmw_thp_put_node(struct ttm_resource_manager *man, +- struct ttm_resource *res) +-{ +- struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res); +- struct vmw_thp_manager *rman = to_thp_manager(man); +- +- spin_lock(&rman->lock); +- drm_mm_remove_node(&node->mm_nodes[0]); +- spin_unlock(&rman->lock); +- +- kfree(node); +-} +- +-int vmw_thp_init(struct vmw_private *dev_priv) +-{ +- struct vmw_thp_manager *rman; +- +- rman = kzalloc(sizeof(*rman), GFP_KERNEL); +- if (!rman) +- return -ENOMEM; +- +- ttm_resource_manager_init(&rman->manager, +- dev_priv->vram_size >> PAGE_SHIFT); +- +- rman->manager.func = &vmw_thp_func; +- drm_mm_init(&rman->mm, 0, rman->manager.size); +- spin_lock_init(&rman->lock); +- +- ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, &rman->manager); +- ttm_resource_manager_set_used(&rman->manager, true); +- return 0; +-} +- +-void vmw_thp_fini(struct vmw_private *dev_priv) +-{ +- struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); +- struct vmw_thp_manager *rman = to_thp_manager(man); +- struct drm_mm *mm = &rman->mm; +- int ret; +- +- ttm_resource_manager_set_used(man, false); +- +- ret = ttm_resource_manager_evict_all(&dev_priv->bdev, man); +- if (ret) +- return; +- spin_lock(&rman->lock); +- drm_mm_clean(mm); +- drm_mm_takedown(mm); +- spin_unlock(&rman->lock); +- ttm_resource_manager_cleanup(man); +- ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, NULL); +- kfree(rman); +-} +- +-static void vmw_thp_debug(struct ttm_resource_manager *man, +- struct drm_printer *printer) +-{ +- struct vmw_thp_manager *rman = to_thp_manager(man); +- +- spin_lock(&rman->lock); +- drm_mm_print(&rman->mm, printer); +- spin_unlock(&rman->lock); +-} +- +-static const struct ttm_resource_manager_func vmw_thp_func = { +- .alloc = vmw_thp_get_node, +- .free = vmw_thp_put_node, +- .debug = vmw_thp_debug +-}; +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +index 8b8991e3ed2d0..450bb1e9626f7 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +@@ -92,6 +92,13 @@ static const struct ttm_place gmr_vram_placement_flags[] = { + } + }; + ++static const struct ttm_place vmw_sys_placement_flags = { ++ .fpfn = 0, ++ .lpfn = 0, ++ .mem_type = VMW_PL_SYSTEM, ++ .flags = 0 ++}; ++ + struct ttm_placement vmw_vram_gmr_placement = { + .num_placement = 2, + .placement = vram_gmr_placement_flags, +@@ -113,28 +120,11 @@ struct ttm_placement vmw_sys_placement = { + .busy_placement = &sys_placement_flags + }; + +-static const struct ttm_place evictable_placement_flags[] = { +- { +- .fpfn = 0, +- .lpfn = 0, +- .mem_type = TTM_PL_SYSTEM, +- .flags = 0 +- }, { +- .fpfn = 0, +- .lpfn = 0, +- .mem_type = TTM_PL_VRAM, +- .flags = 0 +- }, { +- .fpfn = 0, +- .lpfn = 0, +- .mem_type = VMW_PL_GMR, +- .flags = 0 +- }, { +- .fpfn = 0, +- .lpfn = 0, +- .mem_type = VMW_PL_MOB, +- .flags = 0 +- } ++struct ttm_placement vmw_pt_sys_placement = { ++ .num_placement = 1, ++ .placement = &vmw_sys_placement_flags, ++ .num_busy_placement = 1, ++ .busy_placement = &vmw_sys_placement_flags + }; + + static const struct ttm_place nonfixed_placement_flags[] = { +@@ -156,13 +146,6 @@ static const struct ttm_place nonfixed_placement_flags[] = { + } + }; + +-struct ttm_placement vmw_evictable_placement = { +- .num_placement = 4, +- .placement = evictable_placement_flags, +- .num_busy_placement = 1, +- .busy_placement = &sys_placement_flags +-}; +- + struct ttm_placement vmw_srf_placement = { + .num_placement = 1, + .num_busy_placement = 2, +@@ -484,6 +467,9 @@ static int vmw_ttm_bind(struct ttm_device *bdev, + &vmw_be->vsgt, ttm->num_pages, + vmw_be->gmr_id); + break; ++ case VMW_PL_SYSTEM: ++ /* Nothing to be done for a system bind */ ++ break; + default: + BUG(); + } +@@ -507,6 +493,8 @@ static void vmw_ttm_unbind(struct ttm_device *bdev, + case VMW_PL_MOB: + vmw_mob_unbind(vmw_be->dev_priv, vmw_be->mob); + break; ++ case VMW_PL_SYSTEM: ++ break; + default: + BUG(); + } +@@ -628,6 +616,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource * + + switch (mem->mem_type) { + case TTM_PL_SYSTEM: ++ case VMW_PL_SYSTEM: + case VMW_PL_GMR: + case VMW_PL_MOB: + return 0; +@@ -674,6 +663,11 @@ static void vmw_swap_notify(struct ttm_buffer_object *bo) + (void) ttm_bo_wait(bo, false, false); + } + ++static bool vmw_memtype_is_system(uint32_t mem_type) ++{ ++ return mem_type == TTM_PL_SYSTEM || mem_type == VMW_PL_SYSTEM; ++} ++ + static int vmw_move(struct ttm_buffer_object *bo, + bool evict, + struct ttm_operation_ctx *ctx, +@@ -684,7 +678,7 @@ static int vmw_move(struct ttm_buffer_object *bo, + struct ttm_resource_manager *new_man = ttm_manager_type(bo->bdev, new_mem->mem_type); + int ret; + +- if (new_man->use_tt && new_mem->mem_type != TTM_PL_SYSTEM) { ++ if (new_man->use_tt && !vmw_memtype_is_system(new_mem->mem_type)) { + ret = vmw_ttm_bind(bo->bdev, bo->ttm, new_mem); + if (ret) + return ret; +@@ -693,7 +687,7 @@ static int vmw_move(struct ttm_buffer_object *bo, + vmw_move_notify(bo, bo->resource, new_mem); + + if (old_man->use_tt && new_man->use_tt) { +- if (bo->resource->mem_type == TTM_PL_SYSTEM) { ++ if (vmw_memtype_is_system(bo->resource->mem_type)) { + ttm_bo_move_null(bo, new_mem); + return 0; + } +@@ -740,7 +734,7 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv, + int ret; + + ret = vmw_bo_create_kernel(dev_priv, bo_size, +- &vmw_sys_placement, ++ &vmw_pt_sys_placement, + &bo); + if (unlikely(ret != 0)) + return ret; +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +index e6b1f98ec99f0..0a4c340252ec4 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c +@@ -61,9 +61,6 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma) + .fault = vmw_bo_vm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +- .huge_fault = vmw_bo_vm_huge_fault, +-#endif + }; + struct drm_file *file_priv = filp->private_data; + struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev); +diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig +index 6dab94adf25e5..6815b4db17c1b 100644 +--- a/drivers/gpu/host1x/Kconfig ++++ b/drivers/gpu/host1x/Kconfig +@@ -2,6 +2,7 @@ + config TEGRA_HOST1X + tristate "NVIDIA Tegra host1x driver" + depends on ARCH_TEGRA || (ARM && COMPILE_TEST) ++ select DMA_SHARED_BUFFER + select IOMMU_IOVA + help + Driver for the NVIDIA Tegra host1x hardware. +diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c +index fbb6447b8659e..3872e4cd26989 100644 +--- a/drivers/gpu/host1x/dev.c ++++ b/drivers/gpu/host1x/dev.c +@@ -18,6 +18,10 @@ + #include <trace/events/host1x.h> + #undef CREATE_TRACE_POINTS + ++#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) ++#include <asm/dma-iommu.h> ++#endif ++ + #include "bus.h" + #include "channel.h" + #include "debug.h" +@@ -238,6 +242,17 @@ static struct iommu_domain *host1x_iommu_attach(struct host1x *host) + struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev); + int err; + ++#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) ++ if (host->dev->archdata.mapping) { ++ struct dma_iommu_mapping *mapping = ++ to_dma_iommu_mapping(host->dev); ++ arm_iommu_detach_device(host->dev); ++ arm_iommu_release_mapping(mapping); ++ ++ domain = iommu_get_domain_for_dev(host->dev); ++ } ++#endif ++ + /* + * We may not always want to enable IOMMU support (for example if the + * host1x firewall is already enabled and we don't support addressing +diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c +index d198a10848c6b..a89a408182e60 100644 +--- a/drivers/gpu/host1x/syncpt.c ++++ b/drivers/gpu/host1x/syncpt.c +@@ -225,27 +225,12 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, + void *ref; + struct host1x_waitlist *waiter; + int err = 0, check_count = 0; +- u32 val; + + if (value) +- *value = 0; +- +- /* first check cache */ +- if (host1x_syncpt_is_expired(sp, thresh)) { +- if (value) +- *value = host1x_syncpt_load(sp); ++ *value = host1x_syncpt_load(sp); + ++ if (host1x_syncpt_is_expired(sp, thresh)) + return 0; +- } +- +- /* try to read from register */ +- val = host1x_hw_syncpt_load(sp->host, sp); +- if (host1x_syncpt_is_expired(sp, thresh)) { +- if (value) +- *value = val; +- +- goto done; +- } + + if (!timeout) { + err = -EAGAIN; +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 3c33bf572d6d3..9235ab7161e3a 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -207,14 +207,14 @@ config HID_CHERRY + + config HID_CHICONY + tristate "Chicony devices" +- depends on HID ++ depends on USB_HID + default !EXPERT + help + Support for Chicony Tactical pad and special keys on Chicony keyboards. + + config HID_CORSAIR + tristate "Corsair devices" +- depends on HID && USB && LEDS_CLASS ++ depends on USB_HID && LEDS_CLASS + help + Support for Corsair devices that are not fully compliant with the + HID standard. +@@ -245,7 +245,7 @@ config HID_MACALLY + + config HID_PRODIKEYS + tristate "Prodikeys PC-MIDI Keyboard support" +- depends on HID && SND ++ depends on USB_HID && SND + select SND_RAWMIDI + help + Support for Prodikeys PC-MIDI Keyboard device support. +@@ -553,7 +553,7 @@ config HID_LENOVO + + config HID_LOGITECH + tristate "Logitech devices" +- depends on HID ++ depends on USB_HID + depends on LEDS_CLASS + default !EXPERT + help +@@ -919,7 +919,7 @@ config HID_SAITEK + + config HID_SAMSUNG + tristate "Samsung InfraRed remote control or keyboards" +- depends on HID ++ depends on USB_HID + help + Support for Samsung InfraRed remote control or keyboards. + +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +index 05c007b213f24..561bb27f42b10 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +@@ -36,11 +36,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_ + { + union cmd_response cmd_resp; + +- /* Get response with status within a max of 800 ms timeout */ ++ /* Get response with status within a max of 1600 ms timeout */ + if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp, + (cmd_resp.response_v2.response == sensor_sts && + cmd_resp.response_v2.status == 0 && (sid == 0xff || +- cmd_resp.response_v2.sensor_id == sid)), 500, 800000)) ++ cmd_resp.response_v2.sensor_id == sid)), 500, 1600000)) + return cmd_resp.response_v2.response; + + return SENSOR_DISABLED; +@@ -88,6 +88,44 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata) + writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); + } + ++static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata) ++{ ++ if (readl(privdata->mmio + AMD_P2C_MSG(4))) { ++ writel(0, privdata->mmio + AMD_P2C_MSG(4)); ++ writel(0xf, privdata->mmio + AMD_P2C_MSG(5)); ++ } ++} ++ ++static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata) ++{ ++ if (privdata->mp2_ops->clear_intr) ++ privdata->mp2_ops->clear_intr(privdata); ++} ++ ++static irqreturn_t amd_sfh_irq_handler(int irq, void *data) ++{ ++ amd_sfh_clear_intr(data); ++ ++ return IRQ_HANDLED; ++} ++ ++static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata) ++{ ++ int rc; ++ ++ pci_intx(privdata->pdev, true); ++ ++ rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq, ++ amd_sfh_irq_handler, 0, DRIVER_NAME, privdata); ++ if (rc) { ++ dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n", ++ privdata->pdev->irq, rc); ++ return rc; ++ } ++ ++ return 0; ++} ++ + void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) + { + union sfh_cmd_param cmd_param; +@@ -192,6 +230,8 @@ static void amd_mp2_pci_remove(void *privdata) + struct amd_mp2_dev *mp2 = privdata; + amd_sfh_hid_client_deinit(privdata); + mp2->mp2_ops->stop_all(mp2); ++ pci_intx(mp2->pdev, false); ++ amd_sfh_clear_intr(mp2); + } + + static const struct amd_mp2_ops amd_sfh_ops_v2 = { +@@ -199,6 +239,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = { + .stop = amd_stop_sensor_v2, + .stop_all = amd_stop_all_sensor_v2, + .response = amd_sfh_wait_response_v2, ++ .clear_intr = amd_sfh_clear_intr_v2, ++ .init_intr = amd_sfh_irq_init_v2, + }; + + static const struct amd_mp2_ops amd_sfh_ops = { +@@ -224,6 +266,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata) + } + } + ++static int amd_sfh_irq_init(struct amd_mp2_dev *privdata) ++{ ++ if (privdata->mp2_ops->init_intr) ++ return privdata->mp2_ops->init_intr(privdata); ++ ++ return 0; ++} ++ + static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { + struct amd_mp2_dev *privdata; +@@ -257,9 +307,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i + + mp2_select_ops(privdata); + ++ rc = amd_sfh_irq_init(privdata); ++ if (rc) { ++ dev_err(&pdev->dev, "amd_sfh_irq_init failed\n"); ++ return rc; ++ } ++ + rc = amd_sfh_hid_client_init(privdata); +- if (rc) ++ if (rc) { ++ amd_sfh_clear_intr(privdata); ++ dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n"); + return rc; ++ } ++ ++ amd_sfh_clear_intr(privdata); + + return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata); + } +@@ -287,6 +348,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev) + } + } + ++ schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP)); ++ amd_sfh_clear_intr(mp2); ++ + return 0; + } + +@@ -310,6 +374,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev) + } + } + ++ cancel_delayed_work_sync(&cl_data->work_buffer); ++ amd_sfh_clear_intr(mp2); ++ + return 0; + } + +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h +index 1ff6f83cb6fd1..00fc083dc1239 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h +@@ -48,7 +48,7 @@ union sfh_cmd_base { + } s; + struct { + u32 cmd_id : 4; +- u32 intr_enable : 1; ++ u32 intr_disable : 1; + u32 rsvd1 : 3; + u32 length : 7; + u32 mem_type : 1; +@@ -140,5 +140,7 @@ struct amd_mp2_ops { + void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx); + void (*stop_all)(struct amd_mp2_dev *privdata); + int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts); ++ void (*clear_intr)(struct amd_mp2_dev *privdata); ++ int (*init_intr)(struct amd_mp2_dev *privdata); + }; + #endif +diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c +index 0c36972193821..07eb3281b88db 100644 +--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c ++++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c +@@ -26,6 +26,7 @@ + #define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02 + #define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05 + #define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04 ++#define ILLUMINANCE_MASK GENMASK(14, 0) + + int get_report_descriptor(int sensor_idx, u8 *rep_desc) + { +@@ -245,7 +246,8 @@ u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_ + get_common_inputs(&als_input.common_property, report_id); + /* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */ + if (supported_input == V2_STATUS) +- als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5)); ++ als_input.illuminance_value = ++ readl(privdata->mmio + AMD_C2P_MSG(5)) & ILLUMINANCE_MASK; + else + als_input.illuminance_value = + (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER; +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 6ccfa0cb997ab..b683c0e8557d4 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -429,7 +429,7 @@ static int apple_input_configured(struct hid_device *hdev, + + if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) { + hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n"); +- asc->quirks = 0; ++ asc->quirks &= ~APPLE_HAS_FN; + } + + return 0; +diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c +index f3ecddc519ee8..08c9a9a60ae47 100644 +--- a/drivers/hid/hid-asus.c ++++ b/drivers/hid/hid-asus.c +@@ -1028,8 +1028,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) + if (drvdata->quirks & QUIRK_IS_MULTITOUCH) + drvdata->tp = &asus_i2c_tp; + +- if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && +- hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + + if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { +@@ -1057,8 +1056,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) + drvdata->tp = &asus_t100chi_tp; + } + +- if ((drvdata->quirks & QUIRK_MEDION_E1239T) && +- hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if ((drvdata->quirks & QUIRK_MEDION_E1239T) && hid_is_usb(hdev)) { + struct usb_host_interface *alt = + to_usb_interface(hdev->dev.parent)->altsetting; + +diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c +index db6da21ade063..74ad8bf98bfd5 100644 +--- a/drivers/hid/hid-bigbenff.c ++++ b/drivers/hid/hid-bigbenff.c +@@ -191,7 +191,7 @@ static void bigben_worker(struct work_struct *work) + struct bigben_device, worker); + struct hid_field *report_field = bigben->report->field[0]; + +- if (bigben->removed) ++ if (bigben->removed || !report_field) + return; + + if (bigben->work_led) { +diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c +index ca556d39da2ae..f04d2aa23efe4 100644 +--- a/drivers/hid/hid-chicony.c ++++ b/drivers/hid/hid-chicony.c +@@ -114,6 +114,9 @@ static int ch_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int ret; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + hdev->quirks |= HID_QUIRK_INPUT_PER_APP; + ret = hid_parse(hdev); + if (ret) { +diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c +index 902a60e249ed2..8c895c820b672 100644 +--- a/drivers/hid/hid-corsair.c ++++ b/drivers/hid/hid-corsair.c +@@ -553,7 +553,12 @@ static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id) + int ret; + unsigned long quirks = id->driver_data; + struct corsair_drvdata *drvdata; +- struct usb_interface *usbif = to_usb_interface(dev->dev.parent); ++ struct usb_interface *usbif; ++ ++ if (!hid_is_usb(dev)) ++ return -EINVAL; ++ ++ usbif = to_usb_interface(dev->dev.parent); + + drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata), + GFP_KERNEL); +diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c +index fa57d05badf70..f48d3534e0200 100644 +--- a/drivers/hid/hid-debug.c ++++ b/drivers/hid/hid-debug.c +@@ -825,7 +825,9 @@ static const char *keys[KEY_MAX + 1] = { + [KEY_F22] = "F22", [KEY_F23] = "F23", + [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", + [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", +- [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", ++ [KEY_PROG4] = "Prog4", ++ [KEY_ALL_APPLICATIONS] = "AllApplications", ++ [KEY_SUSPEND] = "Suspend", + [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", + [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost", + [KEY_PRINT] = "Print", [KEY_HP] = "HP", +@@ -934,6 +936,7 @@ static const char *keys[KEY_MAX + 1] = { + [KEY_ASSISTANT] = "Assistant", + [KEY_KBD_LAYOUT_NEXT] = "KbdLayoutNext", + [KEY_EMOJI_PICKER] = "EmojiPicker", ++ [KEY_DICTATE] = "Dictate", + [KEY_BRIGHTNESS_MIN] = "BrightnessMin", + [KEY_BRIGHTNESS_MAX] = "BrightnessMax", + [KEY_BRIGHTNESS_AUTO] = "BrightnessAuto", +diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c +index 021049805bb71..3091355d48df6 100644 +--- a/drivers/hid/hid-elan.c ++++ b/drivers/hid/hid-elan.c +@@ -50,7 +50,7 @@ struct elan_drvdata { + + static int is_not_elan_touchpad(struct hid_device *hdev) + { +- if (hdev->bus == BUS_USB) { ++ if (hid_is_usb(hdev)) { + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + + return (intf->altsetting->desc.bInterfaceNumber != +diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c +index 383dfda8c12fc..9b42b0cdeef06 100644 +--- a/drivers/hid/hid-elo.c ++++ b/drivers/hid/hid-elo.c +@@ -230,6 +230,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) + int ret; + struct usb_device *udev; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; +@@ -259,6 +262,7 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) + + return 0; + err_free: ++ usb_put_dev(udev); + kfree(priv); + return ret; + } +diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c +index 4ef1c3b8094ea..183eeb3863b38 100644 +--- a/drivers/hid/hid-ft260.c ++++ b/drivers/hid/hid-ft260.c +@@ -915,6 +915,9 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id) + struct ft260_get_chip_version_report version; + int ret; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; +diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c +index 8123b871a3ebf..0403beb3104b9 100644 +--- a/drivers/hid/hid-google-hammer.c ++++ b/drivers/hid/hid-google-hammer.c +@@ -585,6 +585,8 @@ static void hammer_remove(struct hid_device *hdev) + static const struct hid_device_id hammer_devices[] = { + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) }, ++ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, ++ USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, +diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c +index 0a38e8e9bc783..403506b9697e7 100644 +--- a/drivers/hid/hid-holtek-kbd.c ++++ b/drivers/hid/hid-holtek-kbd.c +@@ -140,12 +140,17 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, + static int holtek_kbd_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- int ret = hid_parse(hdev); ++ struct usb_interface *intf; ++ int ret; ++ ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; + ++ ret = hid_parse(hdev); + if (!ret) + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + ++ intf = to_usb_interface(hdev->dev.parent); + if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) { + struct hid_input *hidinput; + list_for_each_entry(hidinput, &hdev->inputs, list) { +diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c +index 195b735b001d0..7c907939bfae1 100644 +--- a/drivers/hid/hid-holtek-mouse.c ++++ b/drivers/hid/hid-holtek-mouse.c +@@ -62,6 +62,29 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, + return rdesc; + } + ++static int holtek_mouse_probe(struct hid_device *hdev, ++ const struct hid_device_id *id) ++{ ++ int ret; ++ ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ hid_err(hdev, "hid parse failed: %d\n", ret); ++ return ret; ++ } ++ ++ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); ++ if (ret) { ++ hid_err(hdev, "hw start failed: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static const struct hid_device_id holtek_mouse_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, + USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, +@@ -83,6 +106,7 @@ static struct hid_driver holtek_mouse_driver = { + .name = "holtek_mouse", + .id_table = holtek_mouse_devices, + .report_fixup = holtek_mouse_report_fixup, ++ .probe = holtek_mouse_probe, + }; + + module_hid_driver(holtek_mouse_driver); +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 29564b370341e..645a5f566d233 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -394,6 +394,8 @@ + #define USB_DEVICE_ID_HP_X2 0x074d + #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 + #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 ++#define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF ++#define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 + #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 + #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A + +@@ -496,6 +498,7 @@ + #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d + #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 + #define USB_DEVICE_ID_GOOGLE_DON 0x5050 ++#define USB_DEVICE_ID_GOOGLE_EEL 0x5057 + + #define USB_VENDOR_ID_GOTOP 0x08f2 + #define USB_DEVICE_ID_SUPER_Q2 0x007f +@@ -881,6 +884,7 @@ + #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 + #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 + #define USB_DEVICE_ID_MS_POWER_COVER 0x07da ++#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de + #define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd + #define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb + #define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0 +@@ -1276,6 +1280,9 @@ + #define USB_DEVICE_ID_WEIDA_8752 0xC300 + #define USB_DEVICE_ID_WEIDA_8755 0xC301 + ++#define USB_VENDOR_ID_WINBOND 0x0416 ++#define USB_DEVICE_ID_TSTP_MTOUCH 0xc168 ++ + #define USB_VENDOR_ID_WISEGROUP 0x0925 + #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 + #define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888 +@@ -1346,6 +1353,7 @@ + #define USB_VENDOR_ID_UGTIZER 0x2179 + #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053 + #define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077 ++#define USB_DEVICE_ID_UGTIZER_TABLET_WP5540 0x0004 + + #define USB_VENDOR_ID_VIEWSONIC 0x0543 + #define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621 +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 4b5ebeacd2836..3172987a9ebd3 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -160,6 +160,7 @@ static int hidinput_setkeycode(struct input_dev *dev, + if (usage) { + *old_keycode = usage->type == EV_KEY ? + usage->code : KEY_RESERVED; ++ usage->type = EV_KEY; + usage->code = ke->keycode; + + clear_bit(*old_keycode, dev->keybit); +@@ -324,6 +325,10 @@ static const struct hid_device_id hid_battery_quirks[] = { + HID_BATTERY_QUIRK_IGNORE }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), ++ HID_BATTERY_QUIRK_IGNORE }, ++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100), ++ HID_BATTERY_QUIRK_IGNORE }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), + HID_BATTERY_QUIRK_IGNORE }, + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), +@@ -650,10 +655,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + code += KEY_MACRO1; + else + code += BTN_TRIGGER_HAPPY - 0x1e; +- } else { +- goto ignore; ++ break; + } +- break; ++ fallthrough; + default: + switch (field->physical) { + case HID_GD_MOUSE: +@@ -987,6 +991,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; + case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break; + ++ case 0x0d8: map_key_clear(KEY_DICTATE); break; + case 0x0d9: map_key_clear(KEY_EMOJI_PICKER); break; + + case 0x0e0: map_abs_clear(ABS_VOLUME); break; +@@ -1078,6 +1083,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + + case 0x29d: map_key_clear(KEY_KBD_LAYOUT_NEXT); break; + ++ case 0x2a2: map_key_clear(KEY_ALL_APPLICATIONS); break; ++ + case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV); break; + case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT); break; + case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP); break; +@@ -1328,6 +1335,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + + input = field->hidinput->input; + ++ if (usage->type == EV_ABS && ++ (((*quirks & HID_QUIRK_X_INVERT) && usage->code == ABS_X) || ++ ((*quirks & HID_QUIRK_Y_INVERT) && usage->code == ABS_Y))) { ++ value = field->logical_maximum - value; ++ } ++ + if (usage->hat_min < usage->hat_max || usage->hat_dir) { + int hat_dir = usage->hat_dir; + if (!hat_dir) +diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c +index d40af911df635..fb3f7258009c2 100644 +--- a/drivers/hid/hid-lg.c ++++ b/drivers/hid/hid-lg.c +@@ -749,12 +749,18 @@ static int lg_raw_event(struct hid_device *hdev, struct hid_report *report, + + static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) + { +- struct usb_interface *iface = to_usb_interface(hdev->dev.parent); +- __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; ++ struct usb_interface *iface; ++ __u8 iface_num; + unsigned int connect_mask = HID_CONNECT_DEFAULT; + struct lg_drv_data *drv_data; + int ret; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ ++ iface = to_usb_interface(hdev->dev.parent); ++ iface_num = iface->cur_altsetting->desc.bInterfaceNumber; ++ + /* G29 only work with the 1st interface */ + if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) && + (iface_num != 0)) { +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index a0017b010c342..7106b921b53cf 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1777,7 +1777,7 @@ static int logi_dj_probe(struct hid_device *hdev, + case recvr_type_bluetooth: no_dj_interfaces = 2; break; + case recvr_type_dinovo: no_dj_interfaces = 2; break; + } +- if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if (hid_is_usb(hdev)) { + intf = to_usb_interface(hdev->dev.parent); + if (intf && intf->altsetting->desc.bInterfaceNumber >= + no_dj_interfaces) { +diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c +index 686788ebf3e1e..b8b08f0a8c541 100644 +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -57,6 +57,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie + #define MOUSE_REPORT_ID 0x29 + #define MOUSE2_REPORT_ID 0x12 + #define DOUBLE_REPORT_ID 0xf7 ++#define USB_BATTERY_TIMEOUT_MS 60000 ++ + /* These definitions are not precise, but they're close enough. (Bits + * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem + * to be some kind of bit mask -- 0x20 may be a near-field reading, +@@ -140,6 +142,7 @@ struct magicmouse_sc { + + struct hid_device *hdev; + struct delayed_work work; ++ struct timer_list battery_timer; + }; + + static int magicmouse_firm_touch(struct magicmouse_sc *msc) +@@ -256,8 +259,11 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda + unsigned long now = jiffies; + int step_x = msc->touches[id].scroll_x - x; + int step_y = msc->touches[id].scroll_y - y; +- int step_hr = ((64 - (int)scroll_speed) * msc->scroll_accel) / +- SCROLL_HR_STEPS; ++ int step_hr = ++ max_t(int, ++ ((64 - (int)scroll_speed) * msc->scroll_accel) / ++ SCROLL_HR_STEPS, ++ 1); + int step_x_hr = msc->touches[id].scroll_x_hr - x; + int step_y_hr = msc->touches[id].scroll_y_hr - y; + +@@ -735,6 +741,44 @@ static void magicmouse_enable_mt_work(struct work_struct *work) + hid_err(msc->hdev, "unable to request touch data (%d)\n", ret); + } + ++static int magicmouse_fetch_battery(struct hid_device *hdev) ++{ ++#ifdef CONFIG_HID_BATTERY_STRENGTH ++ struct hid_report_enum *report_enum; ++ struct hid_report *report; ++ ++ if (!hdev->battery || hdev->vendor != USB_VENDOR_ID_APPLE || ++ (hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2 && ++ hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2)) ++ return -1; ++ ++ report_enum = &hdev->report_enum[hdev->battery_report_type]; ++ report = report_enum->report_id_hash[hdev->battery_report_id]; ++ ++ if (!report || report->maxfield < 1) ++ return -1; ++ ++ if (hdev->battery_capacity == hdev->battery_max) ++ return -1; ++ ++ hid_hw_request(hdev, report, HID_REQ_GET_REPORT); ++ return 0; ++#else ++ return -1; ++#endif ++} ++ ++static void magicmouse_battery_timer_tick(struct timer_list *t) ++{ ++ struct magicmouse_sc *msc = from_timer(msc, t, battery_timer); ++ struct hid_device *hdev = msc->hdev; ++ ++ if (magicmouse_fetch_battery(hdev) == 0) { ++ mod_timer(&msc->battery_timer, ++ jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS)); ++ } ++} ++ + static int magicmouse_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +@@ -742,11 +786,6 @@ static int magicmouse_probe(struct hid_device *hdev, + struct hid_report *report; + int ret; + +- if (id->vendor == USB_VENDOR_ID_APPLE && +- id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && +- hdev->type != HID_TYPE_USBMOUSE) +- return -ENODEV; +- + msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL); + if (msc == NULL) { + hid_err(hdev, "can't alloc magicmouse descriptor\n"); +@@ -772,6 +811,16 @@ static int magicmouse_probe(struct hid_device *hdev, + return ret; + } + ++ timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0); ++ mod_timer(&msc->battery_timer, ++ jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS)); ++ magicmouse_fetch_battery(hdev); ++ ++ if (id->vendor == USB_VENDOR_ID_APPLE && ++ (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || ++ (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && hdev->type != HID_TYPE_USBMOUSE))) ++ return 0; ++ + if (!msc->input) { + hid_err(hdev, "magicmouse input not registered\n"); + ret = -ENOMEM; +@@ -824,6 +873,7 @@ static int magicmouse_probe(struct hid_device *hdev, + + return 0; + err_stop_hw: ++ del_timer_sync(&msc->battery_timer); + hid_hw_stop(hdev); + return ret; + } +@@ -832,17 +882,52 @@ static void magicmouse_remove(struct hid_device *hdev) + { + struct magicmouse_sc *msc = hid_get_drvdata(hdev); + +- if (msc) ++ if (msc) { + cancel_delayed_work_sync(&msc->work); ++ del_timer_sync(&msc->battery_timer); ++ } + + hid_hw_stop(hdev); + } + ++static __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize) ++{ ++ /* ++ * Change the usage from: ++ * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0 ++ * 0x09, 0x0b, // Usage (Vendor Usage 0x0b) 3 ++ * To: ++ * 0x05, 0x01, // Usage Page (Generic Desktop) 0 ++ * 0x09, 0x02, // Usage (Mouse) 2 ++ */ ++ if (hdev->vendor == USB_VENDOR_ID_APPLE && ++ (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || ++ hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) && ++ *rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) { ++ hid_info(hdev, ++ "fixing up magicmouse battery report descriptor\n"); ++ *rsize = *rsize - 1; ++ rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL); ++ if (!rdesc) ++ return NULL; ++ ++ rdesc[0] = 0x05; ++ rdesc[1] = 0x01; ++ rdesc[2] = 0x09; ++ rdesc[3] = 0x02; ++ } ++ ++ return rdesc; ++} ++ + static const struct hid_device_id magic_mice[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 }, + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, ++ USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 }, + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, +@@ -858,6 +943,7 @@ static struct hid_driver magicmouse_driver = { + .id_table = magic_mice, + .probe = magicmouse_probe, + .remove = magicmouse_remove, ++ .report_fixup = magicmouse_report_fixup, + .raw_event = magicmouse_raw_event, + .event = magicmouse_event, + .input_mapping = magicmouse_input_mapping, +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 3ea7cb1cda84c..e1afddb7b33d8 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -193,6 +193,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); + /* reserved 0x0014 */ + #define MT_CLS_WIN_8_FORCE_MULTI_INPUT 0x0015 + #define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016 ++#define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017 + + /* vendor specific classes */ + #define MT_CLS_3M 0x0101 +@@ -294,6 +295,13 @@ static const struct mt_class mt_classes[] = { + MT_QUIRK_WIN8_PTP_BUTTONS | + MT_QUIRK_DISABLE_WAKEUP, + .export_all_inputs = true }, ++ { .name = MT_CLS_WIN_8_NO_STICKY_FINGERS, ++ .quirks = MT_QUIRK_ALWAYS_VALID | ++ MT_QUIRK_IGNORE_DUPLICATES | ++ MT_QUIRK_HOVERING | ++ MT_QUIRK_CONTACT_CNT_ACCURATE | ++ MT_QUIRK_WIN8_PTP_BUTTONS, ++ .export_all_inputs = true }, + + /* + * vendor specific classes +@@ -2120,6 +2128,11 @@ static const struct hid_device_id mt_devices[] = { + MT_USB_DEVICE(USB_VENDOR_ID_VTL, + USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) }, + ++ /* Winbond Electronics Corp. */ ++ { .driver_data = MT_CLS_WIN_8_NO_STICKY_FINGERS, ++ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8, ++ USB_VENDOR_ID_WINBOND, USB_DEVICE_ID_TSTP_MTOUCH) }, ++ + /* Wistron panels */ + { .driver_data = MT_CLS_NSMU, + MT_USB_DEVICE(USB_VENDOR_ID_WISTRON, +diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c +index 2666af02d5c1a..e4e9471d0f1e9 100644 +--- a/drivers/hid/hid-prodikeys.c ++++ b/drivers/hid/hid-prodikeys.c +@@ -798,12 +798,18 @@ static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, + static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int ret; +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; ++ struct usb_interface *intf; ++ unsigned short ifnum; + unsigned long quirks = id->driver_data; + struct pk_device *pk; + struct pcmidi_snd *pm = NULL; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ ++ intf = to_usb_interface(hdev->dev.parent); ++ ifnum = intf->cur_altsetting->desc.bInterfaceNumber; ++ + pk = kzalloc(sizeof(*pk), GFP_KERNEL); + if (pk == NULL) { + hid_err(hdev, "can't alloc descriptor\n"); +diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c +index 2e104682c22b9..544d1197aca48 100644 +--- a/drivers/hid/hid-quirks.c ++++ b/drivers/hid/hid-quirks.c +@@ -124,6 +124,7 @@ static const struct hid_device_id hid_quirks[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, +@@ -186,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT }, +diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c +index 4556d2a50f754..d94ee0539421e 100644 +--- a/drivers/hid/hid-roccat-arvo.c ++++ b/drivers/hid/hid-roccat-arvo.c +@@ -344,6 +344,9 @@ static int arvo_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c +index ce5f22519956a..e95d59cd8d075 100644 +--- a/drivers/hid/hid-roccat-isku.c ++++ b/drivers/hid/hid-roccat-isku.c +@@ -324,6 +324,9 @@ static int isku_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c +index 1ca64481145ee..e8522eacf7973 100644 +--- a/drivers/hid/hid-roccat-kone.c ++++ b/drivers/hid/hid-roccat-kone.c +@@ -749,6 +749,9 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c +index 0316edf8c5bb4..1896c69ea512f 100644 +--- a/drivers/hid/hid-roccat-koneplus.c ++++ b/drivers/hid/hid-roccat-koneplus.c +@@ -431,6 +431,9 @@ static int koneplus_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c +index 5248b3c7cf785..cf8eeb33a1257 100644 +--- a/drivers/hid/hid-roccat-konepure.c ++++ b/drivers/hid/hid-roccat-konepure.c +@@ -133,6 +133,9 @@ static int konepure_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c +index 9600128815705..6fb9b9563769d 100644 +--- a/drivers/hid/hid-roccat-kovaplus.c ++++ b/drivers/hid/hid-roccat-kovaplus.c +@@ -501,6 +501,9 @@ static int kovaplus_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c +index 4a88a76d5c622..d5ddf0d68346b 100644 +--- a/drivers/hid/hid-roccat-lua.c ++++ b/drivers/hid/hid-roccat-lua.c +@@ -160,6 +160,9 @@ static int lua_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c +index 989927defe8db..4fcc8e7d276f2 100644 +--- a/drivers/hid/hid-roccat-pyra.c ++++ b/drivers/hid/hid-roccat-pyra.c +@@ -449,6 +449,9 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-ryos.c b/drivers/hid/hid-roccat-ryos.c +index 3956a6c9c5217..5bf1971a2b14d 100644 +--- a/drivers/hid/hid-roccat-ryos.c ++++ b/drivers/hid/hid-roccat-ryos.c +@@ -141,6 +141,9 @@ static int ryos_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c +index 818701f7a0281..a784bb4ee6512 100644 +--- a/drivers/hid/hid-roccat-savu.c ++++ b/drivers/hid/hid-roccat-savu.c +@@ -113,6 +113,9 @@ static int savu_probe(struct hid_device *hdev, + { + int retval; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c +index 2e1c31156eca0..cf5992e970940 100644 +--- a/drivers/hid/hid-samsung.c ++++ b/drivers/hid/hid-samsung.c +@@ -152,6 +152,9 @@ static int samsung_probe(struct hid_device *hdev, + int ret; + unsigned int cmask = HID_CONNECT_DEFAULT; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index d1b107d547f54..60ec2b29d54de 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -3000,7 +3000,6 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + sc->quirks = quirks; + hid_set_drvdata(hdev, sc); + sc->hdev = hdev; +- usbdev = to_usb_device(sc->hdev->dev.parent->parent); + + ret = hid_parse(hdev); + if (ret) { +@@ -3038,14 +3037,23 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + */ + if (!(hdev->claimed & HID_CLAIMED_INPUT)) { + hid_err(hdev, "failed to claim input\n"); +- hid_hw_stop(hdev); +- return -ENODEV; ++ ret = -ENODEV; ++ goto err; + } + + if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { ++ if (!hid_is_usb(hdev)) { ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ usbdev = to_usb_device(sc->hdev->dev.parent->parent); ++ + sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC); +- if (!sc->ghl_urb) +- return -ENOMEM; ++ if (!sc->ghl_urb) { ++ ret = -ENOMEM; ++ goto err; ++ } + + if (sc->quirks & GHL_GUITAR_PS3WIIU) + ret = ghl_init_urb(sc, usbdev, ghl_ps3wiiu_magic_data, +@@ -3055,7 +3063,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + ARRAY_SIZE(ghl_ps4_magic_data)); + if (ret) { + hid_err(hdev, "error preparing URB\n"); +- return ret; ++ goto err; + } + + timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0); +@@ -3064,6 +3072,10 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + } + + return ret; ++ ++err: ++ hid_hw_stop(hdev); ++ return ret; + } + + static void sony_remove(struct hid_device *hdev) +diff --git a/drivers/hid/hid-thrustmaster.c b/drivers/hid/hid-thrustmaster.c +index d44550aa88057..0c92b7f9b8b81 100644 +--- a/drivers/hid/hid-thrustmaster.c ++++ b/drivers/hid/hid-thrustmaster.c +@@ -274,6 +274,9 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i + int ret = 0; + struct tm_wheel *tm_wheel = 0; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed with error %d\n", ret); +diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c +index d70cd3d7f583b..ac3fd870673d2 100644 +--- a/drivers/hid/hid-u2fzero.c ++++ b/drivers/hid/hid-u2fzero.c +@@ -132,7 +132,7 @@ static int u2fzero_recv(struct u2fzero_device *dev, + + ret = (wait_for_completion_timeout( + &ctx.done, msecs_to_jiffies(USB_CTRL_SET_TIMEOUT))); +- if (ret < 0) { ++ if (ret == 0) { + usb_kill_urb(dev->urb); + hid_err(hdev, "urb submission timed out"); + } else { +@@ -191,6 +191,8 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data, + struct u2f_hid_msg resp; + int ret; + size_t actual_length; ++ /* valid packets must have a correct header */ ++ int min_length = offsetof(struct u2f_hid_msg, init.data); + + if (!dev->present) { + hid_dbg(dev->hdev, "device not present"); +@@ -200,12 +202,12 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data, + ret = u2fzero_recv(dev, &req, &resp); + + /* ignore errors or packets without data */ +- if (ret < offsetof(struct u2f_hid_msg, init.data)) ++ if (ret < min_length) + return 0; + + /* only take the minimum amount of data it is safe to take */ +- actual_length = min3((size_t)ret - offsetof(struct u2f_hid_msg, +- init.data), U2F_HID_MSG_LEN(resp), max); ++ actual_length = min3((size_t)ret - min_length, ++ U2F_HID_MSG_LEN(resp), max); + + memcpy(data, resp.init.data, actual_length); + +@@ -288,7 +290,7 @@ static int u2fzero_probe(struct hid_device *hdev, + unsigned int minor; + int ret; + +- if (!hid_is_using_ll_driver(hdev, &usb_hid_driver)) ++ if (!hid_is_usb(hdev)) + return -EINVAL; + + dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); +diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c +index 6a9865dd703c0..d8ab0139e5cda 100644 +--- a/drivers/hid/hid-uclogic-core.c ++++ b/drivers/hid/hid-uclogic-core.c +@@ -164,6 +164,9 @@ static int uclogic_probe(struct hid_device *hdev, + struct uclogic_drvdata *drvdata = NULL; + bool params_initialized = false; + ++ if (!hid_is_usb(hdev)) ++ return -EINVAL; ++ + /* + * libinput requires the pad interface to be on a different node + * than the pen, so use QUIRK_MULTI_INPUT for all tablets. +diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c +index 3d67b748a3b95..3e70f969fb849 100644 +--- a/drivers/hid/hid-uclogic-params.c ++++ b/drivers/hid/hid-uclogic-params.c +@@ -66,7 +66,7 @@ static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev, + __u8 idx, size_t len) + { + int rc; +- struct usb_device *udev = hid_to_usb_dev(hdev); ++ struct usb_device *udev; + __u8 *buf = NULL; + + /* Check arguments */ +@@ -75,6 +75,8 @@ static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev, + goto cleanup; + } + ++ udev = hid_to_usb_dev(hdev); ++ + buf = kmalloc(len, GFP_KERNEL); + if (buf == NULL) { + rc = -ENOMEM; +@@ -450,7 +452,7 @@ static int uclogic_params_frame_init_v1_buttonpad( + { + int rc; + bool found = false; +- struct usb_device *usb_dev = hid_to_usb_dev(hdev); ++ struct usb_device *usb_dev; + char *str_buf = NULL; + const size_t str_len = 16; + +@@ -460,6 +462,8 @@ static int uclogic_params_frame_init_v1_buttonpad( + goto cleanup; + } + ++ usb_dev = hid_to_usb_dev(hdev); ++ + /* + * Enable generic button mode + */ +@@ -707,9 +711,9 @@ static int uclogic_params_huion_init(struct uclogic_params *params, + struct hid_device *hdev) + { + int rc; +- struct usb_device *udev = hid_to_usb_dev(hdev); +- struct usb_interface *iface = to_usb_interface(hdev->dev.parent); +- __u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; ++ struct usb_device *udev; ++ struct usb_interface *iface; ++ __u8 bInterfaceNumber; + bool found; + /* The resulting parameters (noop) */ + struct uclogic_params p = {0, }; +@@ -723,6 +727,10 @@ static int uclogic_params_huion_init(struct uclogic_params *params, + goto cleanup; + } + ++ udev = hid_to_usb_dev(hdev); ++ iface = to_usb_interface(hdev->dev.parent); ++ bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; ++ + /* If it's not a pen interface */ + if (bInterfaceNumber != 0) { + /* TODO: Consider marking the interface invalid */ +@@ -834,21 +842,25 @@ int uclogic_params_init(struct uclogic_params *params, + struct hid_device *hdev) + { + int rc; +- struct usb_device *udev = hid_to_usb_dev(hdev); +- __u8 bNumInterfaces = udev->config->desc.bNumInterfaces; +- struct usb_interface *iface = to_usb_interface(hdev->dev.parent); +- __u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; ++ struct usb_device *udev; ++ __u8 bNumInterfaces; ++ struct usb_interface *iface; ++ __u8 bInterfaceNumber; + bool found; + /* The resulting parameters (noop) */ + struct uclogic_params p = {0, }; + + /* Check arguments */ +- if (params == NULL || hdev == NULL || +- !hid_is_using_ll_driver(hdev, &usb_hid_driver)) { ++ if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { + rc = -EINVAL; + goto cleanup; + } + ++ udev = hid_to_usb_dev(hdev); ++ bNumInterfaces = udev->config->desc.bNumInterfaces; ++ iface = to_usb_interface(hdev->dev.parent); ++ bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; ++ + /* + * Set replacement report descriptor if the original matches the + * specified size. Otherwise keep interface unchanged. +diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c +index cd7ada48b1d9f..576518e704ee6 100644 +--- a/drivers/hid/hid-vivaldi.c ++++ b/drivers/hid/hid-vivaldi.c +@@ -57,6 +57,9 @@ static int vivaldi_probe(struct hid_device *hdev, + int ret; + + drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ + hid_set_drvdata(hdev, drvdata); + + ret = hid_parse(hdev); +@@ -71,10 +74,11 @@ static void vivaldi_feature_mapping(struct hid_device *hdev, + struct hid_usage *usage) + { + struct vivaldi_data *drvdata = hid_get_drvdata(hdev); ++ struct hid_report *report = field->report; + int fn_key; + int ret; + u32 report_len; +- u8 *buf; ++ u8 *report_data, *buf; + + if (field->logical != HID_USAGE_FN_ROW_PHYSMAP || + (usage->hid & HID_USAGE_PAGE) != HID_UP_ORDINAL) +@@ -86,12 +90,24 @@ static void vivaldi_feature_mapping(struct hid_device *hdev, + if (fn_key > drvdata->max_function_row_key) + drvdata->max_function_row_key = fn_key; + +- buf = hid_alloc_report_buf(field->report, GFP_KERNEL); +- if (!buf) ++ report_data = buf = hid_alloc_report_buf(report, GFP_KERNEL); ++ if (!report_data) + return; + +- report_len = hid_report_len(field->report); +- ret = hid_hw_raw_request(hdev, field->report->id, buf, ++ report_len = hid_report_len(report); ++ if (!report->id) { ++ /* ++ * hid_hw_raw_request() will stuff report ID (which will be 0) ++ * into the first byte of the buffer even for unnumbered ++ * reports, so we need to account for this to avoid getting ++ * -EOVERFLOW in return. ++ * Note that hid_alloc_report_buf() adds 7 bytes to the size ++ * so we can safely say that we have space for an extra byte. ++ */ ++ report_len++; ++ } ++ ++ ret = hid_hw_raw_request(hdev, report->id, report_data, + report_len, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + if (ret < 0) { +@@ -100,7 +116,16 @@ static void vivaldi_feature_mapping(struct hid_device *hdev, + goto out; + } + +- ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, ++ if (!report->id) { ++ /* ++ * Undo the damage from hid_hw_raw_request() for unnumbered ++ * reports. ++ */ ++ report_data++; ++ report_len--; ++ } ++ ++ ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, report_data, + report_len, 0); + if (ret) { + dev_warn(&hdev->dev, "failed to report feature %d\n", +diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c +index a6f0257a26de3..b96ae15e0ad91 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c ++++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c +@@ -111,7 +111,7 @@ static int i2c_hid_acpi_probe(struct i2c_client *client) + } + + return i2c_hid_core_probe(client, &ihid_acpi->ops, +- hid_descriptor_address); ++ hid_descriptor_address, 0); + } + + static const struct acpi_device_id i2c_hid_acpi_match[] = { +diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c +index 517141138b007..4804d71e5293a 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-core.c ++++ b/drivers/hid/i2c-hid/i2c-hid-core.c +@@ -912,7 +912,7 @@ static void i2c_hid_core_shutdown_tail(struct i2c_hid *ihid) + } + + int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, +- u16 hid_descriptor_address) ++ u16 hid_descriptor_address, u32 quirks) + { + int ret; + struct i2c_hid *ihid; +@@ -1009,6 +1009,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, + goto err_mem_free; + } + ++ hid->quirks |= quirks; ++ + return 0; + + err_mem_free: +diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c +index 52674149a2750..ec6c73f75ffe0 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c ++++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c +@@ -27,7 +27,6 @@ struct i2c_hid_of_goodix { + + struct regulator *vdd; + struct notifier_block nb; +- struct mutex regulator_mutex; + struct gpio_desc *reset_gpio; + const struct goodix_i2c_hid_timing_data *timings; + }; +@@ -67,8 +66,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb, + container_of(nb, struct i2c_hid_of_goodix, nb); + int ret = NOTIFY_OK; + +- mutex_lock(&ihid_goodix->regulator_mutex); +- + switch (event) { + case REGULATOR_EVENT_PRE_DISABLE: + gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); +@@ -87,8 +84,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb, + break; + } + +- mutex_unlock(&ihid_goodix->regulator_mutex); +- + return ret; + } + +@@ -102,8 +97,6 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client, + if (!ihid_goodix) + return -ENOMEM; + +- mutex_init(&ihid_goodix->regulator_mutex); +- + ihid_goodix->ops.power_up = goodix_i2c_hid_power_up; + ihid_goodix->ops.power_down = goodix_i2c_hid_power_down; + +@@ -130,27 +123,30 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client, + * long. Holding the controller in reset apparently draws extra + * power. + */ +- mutex_lock(&ihid_goodix->regulator_mutex); + ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify; + ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb); +- if (ret) { +- mutex_unlock(&ihid_goodix->regulator_mutex); ++ if (ret) + return dev_err_probe(&client->dev, ret, + "regulator notifier request failed\n"); +- } + + /* + * If someone else is holding the regulator on (or the regulator is + * an always-on one) we might never be told to deassert reset. Do it +- * now. Here we'll assume that someone else might have _just +- * barely_ turned the regulator on so we'll do the full +- * "post_power_delay" just in case. ++ * now... and temporarily bump the regulator reference count just to ++ * make sure it is impossible for this to race with our own notifier! ++ * We also assume that someone else might have _just barely_ turned ++ * the regulator on so we'll do the full "post_power_delay" just in ++ * case. + */ +- if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) ++ if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) { ++ ret = regulator_enable(ihid_goodix->vdd); ++ if (ret) ++ return ret; + goodix_i2c_hid_deassert_reset(ihid_goodix, true); +- mutex_unlock(&ihid_goodix->regulator_mutex); ++ regulator_disable(ihid_goodix->vdd); ++ } + +- return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001); ++ return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); + } + + static const struct goodix_i2c_hid_timing_data goodix_gt7375p_timing_data = { +diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c +index 4bf7cea926379..97a27a803f58d 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-of.c ++++ b/drivers/hid/i2c-hid/i2c-hid-of.c +@@ -21,6 +21,7 @@ + + #include <linux/delay.h> + #include <linux/device.h> ++#include <linux/hid.h> + #include <linux/i2c.h> + #include <linux/kernel.h> + #include <linux/module.h> +@@ -71,6 +72,7 @@ static int i2c_hid_of_probe(struct i2c_client *client, + struct device *dev = &client->dev; + struct i2c_hid_of *ihid_of; + u16 hid_descriptor_address; ++ u32 quirks = 0; + int ret; + u32 val; + +@@ -105,8 +107,14 @@ static int i2c_hid_of_probe(struct i2c_client *client, + if (ret) + return ret; + ++ if (device_property_read_bool(dev, "touchscreen-inverted-x")) ++ quirks |= HID_QUIRK_X_INVERT; ++ ++ if (device_property_read_bool(dev, "touchscreen-inverted-y")) ++ quirks |= HID_QUIRK_Y_INVERT; ++ + return i2c_hid_core_probe(client, &ihid_of->ops, +- hid_descriptor_address); ++ hid_descriptor_address, quirks); + } + + static const struct of_device_id i2c_hid_of_match[] = { +diff --git a/drivers/hid/i2c-hid/i2c-hid.h b/drivers/hid/i2c-hid/i2c-hid.h +index 05a7827d211af..236cc062d5ef8 100644 +--- a/drivers/hid/i2c-hid/i2c-hid.h ++++ b/drivers/hid/i2c-hid/i2c-hid.h +@@ -32,7 +32,7 @@ struct i2chid_ops { + }; + + int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, +- u16 hid_descriptor_address); ++ u16 hid_descriptor_address, u32 quirks); + int i2c_hid_core_remove(struct i2c_client *client); + + void i2c_hid_core_shutdown(struct i2c_client *client); +diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c +index 1c5039081db27..8e9d9450cb835 100644 +--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c ++++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c +@@ -266,7 +266,8 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work) + + if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag + && IPC_IS_ISH_ILUP(fwsts)) { +- disable_irq_wake(pdev->irq); ++ if (device_may_wakeup(&pdev->dev)) ++ disable_irq_wake(pdev->irq); + + ish_set_host_ready(dev); + +@@ -337,7 +338,8 @@ static int __maybe_unused ish_suspend(struct device *device) + */ + pci_save_state(pdev); + +- enable_irq_wake(pdev->irq); ++ if (device_may_wakeup(&pdev->dev)) ++ enable_irq_wake(pdev->irq); + } + } else { + /* +diff --git a/drivers/hid/surface-hid/surface_hid.c b/drivers/hid/surface-hid/surface_hid.c +index a3a70e4f3f6c9..d4aa8c81903ae 100644 +--- a/drivers/hid/surface-hid/surface_hid.c ++++ b/drivers/hid/surface-hid/surface_hid.c +@@ -209,7 +209,7 @@ static int surface_hid_probe(struct ssam_device *sdev) + + shid->notif.base.priority = 1; + shid->notif.base.fn = ssam_hid_event_fn; +- shid->notif.event.reg = SSAM_EVENT_REGISTRY_REG; ++ shid->notif.event.reg = SSAM_EVENT_REGISTRY_REG(sdev->uid.target); + shid->notif.event.id.target_category = sdev->uid.category; + shid->notif.event.id.instance = sdev->uid.instance; + shid->notif.event.mask = SSAM_EVENT_MASK_STRICT; +@@ -230,7 +230,7 @@ static void surface_hid_remove(struct ssam_device *sdev) + } + + static const struct ssam_device_id surface_hid_match[] = { +- { SSAM_SDEV(HID, 0x02, SSAM_ANY_IID, 0x00) }, ++ { SSAM_SDEV(HID, SSAM_ANY_TID, SSAM_ANY_IID, 0x00) }, + { }, + }; + MODULE_DEVICE_TABLE(ssam, surface_hid_match); +diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c +index 8fe3efcb83271..fc06d8bb42e0f 100644 +--- a/drivers/hid/uhid.c ++++ b/drivers/hid/uhid.c +@@ -28,11 +28,22 @@ + + struct uhid_device { + struct mutex devlock; ++ ++ /* This flag tracks whether the HID device is usable for commands from ++ * userspace. The flag is already set before hid_add_device(), which ++ * runs in workqueue context, to allow hid_add_device() to communicate ++ * with userspace. ++ * However, if hid_add_device() fails, the flag is cleared without ++ * holding devlock. ++ * We guarantee that if @running changes from true to false while you're ++ * holding @devlock, it's still fine to access @hid. ++ */ + bool running; + + __u8 *rd_data; + uint rd_size; + ++ /* When this is NULL, userspace may use UHID_CREATE/UHID_CREATE2. */ + struct hid_device *hid; + struct uhid_event input_buf; + +@@ -63,9 +74,18 @@ static void uhid_device_add_worker(struct work_struct *work) + if (ret) { + hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret); + +- hid_destroy_device(uhid->hid); +- uhid->hid = NULL; ++ /* We used to call hid_destroy_device() here, but that's really ++ * messy to get right because we have to coordinate with ++ * concurrent writes from userspace that might be in the middle ++ * of using uhid->hid. ++ * Just leave uhid->hid as-is for now, and clean it up when ++ * userspace tries to close or reinitialize the uhid instance. ++ * ++ * However, we do have to clear the ->running flag and do a ++ * wakeup to make sure userspace knows that the device is gone. ++ */ + uhid->running = false; ++ wake_up_interruptible(&uhid->report_wait); + } + } + +@@ -474,7 +494,7 @@ static int uhid_dev_create2(struct uhid_device *uhid, + void *rd_data; + int ret; + +- if (uhid->running) ++ if (uhid->hid) + return -EALREADY; + + rd_size = ev->u.create2.rd_size; +@@ -556,7 +576,7 @@ static int uhid_dev_create(struct uhid_device *uhid, + + static int uhid_dev_destroy(struct uhid_device *uhid) + { +- if (!uhid->running) ++ if (!uhid->hid) + return -EINVAL; + + uhid->running = false; +@@ -565,6 +585,7 @@ static int uhid_dev_destroy(struct uhid_device *uhid) + cancel_work_sync(&uhid->worker); + + hid_destroy_device(uhid->hid); ++ uhid->hid = NULL; + kfree(uhid->rd_data); + + return 0; +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index 93f49b766376e..b1bbf297f66b0 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -726,7 +726,7 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, + * Skip the query for this type and modify defaults based on + * interface number. + */ +- if (features->type == WIRELESS) { ++ if (features->type == WIRELESS && intf) { + if (intf->cur_altsetting->desc.bInterfaceNumber == 0) + features->device_type = WACOM_DEVICETYPE_WL_MONITOR; + else +@@ -2217,7 +2217,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) + if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) { + char *product_name = wacom->hdev->name; + +- if (hid_is_using_ll_driver(wacom->hdev, &usb_hid_driver)) { ++ if (hid_is_usb(wacom->hdev)) { + struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent); + struct usb_device *dev = interface_to_usbdev(intf); + product_name = dev->product; +@@ -2454,6 +2454,9 @@ static void wacom_wireless_work(struct work_struct *work) + + wacom_destroy_battery(wacom); + ++ if (!usbdev) ++ return; ++ + /* Stylus interface */ + hdev1 = usb_get_intfdata(usbdev->config->interface[1]); + wacom1 = hid_get_drvdata(hdev1); +@@ -2733,8 +2736,6 @@ static void wacom_mode_change_work(struct work_struct *work) + static int wacom_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct usb_interface *intf = to_usb_interface(hdev->dev.parent); +- struct usb_device *dev = interface_to_usbdev(intf); + struct wacom *wacom; + struct wacom_wac *wacom_wac; + struct wacom_features *features; +@@ -2769,8 +2770,14 @@ static int wacom_probe(struct hid_device *hdev, + wacom_wac->hid_data.inputmode = -1; + wacom_wac->mode_report = -1; + +- wacom->usbdev = dev; +- wacom->intf = intf; ++ if (hid_is_usb(hdev)) { ++ struct usb_interface *intf = to_usb_interface(hdev->dev.parent); ++ struct usb_device *dev = interface_to_usbdev(intf); ++ ++ wacom->usbdev = dev; ++ wacom->intf = intf; ++ } ++ + mutex_init(&wacom->lock); + INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work); + INIT_WORK(&wacom->wireless_work, wacom_wireless_work); +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index 33a6908995b1b..a7176fc0635dd 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -2588,6 +2588,24 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, + } + } + ++static bool wacom_wac_slot_is_active(struct input_dev *dev, int key) ++{ ++ struct input_mt *mt = dev->mt; ++ struct input_mt_slot *s; ++ ++ if (!mt) ++ return false; ++ ++ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { ++ if (s->key == key && ++ input_mt_get_value(s, ABS_MT_TRACKING_ID) >= 0) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + static void wacom_wac_finger_event(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage, __s32 value) + { +@@ -2603,6 +2621,9 @@ static void wacom_wac_finger_event(struct hid_device *hdev, + return; + + switch (equivalent_usage) { ++ case HID_DG_CONFIDENCE: ++ wacom_wac->hid_data.confidence = value; ++ break; + case HID_GD_X: + wacom_wac->hid_data.x = value; + break; +@@ -2635,8 +2656,14 @@ static void wacom_wac_finger_event(struct hid_device *hdev, + } + + if (usage->usage_index + 1 == field->report_count) { +- if (equivalent_usage == wacom_wac->hid_data.last_slot_field) +- wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); ++ if (equivalent_usage == wacom_wac->hid_data.last_slot_field) { ++ bool touch_removed = wacom_wac_slot_is_active(wacom_wac->touch_input, ++ wacom_wac->hid_data.id) && !wacom_wac->hid_data.tipswitch; ++ ++ if (wacom_wac->hid_data.confidence || touch_removed) { ++ wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); ++ } ++ } + } + } + +@@ -2653,6 +2680,12 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, + + wacom_wac->is_invalid_bt_frame = false; + ++ hid_data->confidence = true; ++ ++ hid_data->cc_report = 0; ++ hid_data->cc_index = -1; ++ hid_data->cc_value_index = -1; ++ + for (i = 0; i < report->maxfield; i++) { + struct hid_field *field = report->field[i]; + int j; +@@ -2686,11 +2719,14 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev, + hid_data->cc_index >= 0) { + struct hid_field *field = report->field[hid_data->cc_index]; + int value = field->value[hid_data->cc_value_index]; +- if (value) ++ if (value) { + hid_data->num_expected = value; ++ hid_data->num_received = 0; ++ } + } + else { + hid_data->num_expected = wacom_wac->features.touch_max; ++ hid_data->num_received = 0; + } + } + +@@ -2718,6 +2754,7 @@ static void wacom_wac_finger_report(struct hid_device *hdev, + + input_sync(input); + wacom_wac->hid_data.num_received = 0; ++ wacom_wac->hid_data.num_expected = 0; + + /* keep touch state for pen event */ + wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac); +diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h +index 8b2d4e5b2303c..466b62cc16dc1 100644 +--- a/drivers/hid/wacom_wac.h ++++ b/drivers/hid/wacom_wac.h +@@ -301,6 +301,7 @@ struct hid_data { + bool barrelswitch; + bool barrelswitch2; + bool serialhi; ++ bool confidence; + int x; + int y; + int pressure; +diff --git a/drivers/hsi/hsi_core.c b/drivers/hsi/hsi_core.c +index ec90713564e32..884066109699c 100644 +--- a/drivers/hsi/hsi_core.c ++++ b/drivers/hsi/hsi_core.c +@@ -102,6 +102,7 @@ struct hsi_client *hsi_new_client(struct hsi_port *port, + if (device_register(&cl->device) < 0) { + pr_err("hsi: failed to register client: %s\n", info->name); + put_device(&cl->device); ++ goto err; + } + + return cl; +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 7f11ea07d698f..f2d05bff42453 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -480,7 +480,7 @@ module_param(pressure_report_delay, uint, (S_IRUGO | S_IWUSR)); + MODULE_PARM_DESC(pressure_report_delay, "Delay in secs in reporting pressure"); + static atomic_t trans_id = ATOMIC_INIT(0); + +-static int dm_ring_size = 20 * 1024; ++static int dm_ring_size = VMBUS_RING_SIZE(16 * 1024); + + /* + * Driver specific state. +@@ -1660,6 +1660,13 @@ static int balloon_connect_vsp(struct hv_device *dev) + unsigned long t; + int ret; + ++ /* ++ * max_pkt_size should be large enough for one vmbus packet header plus ++ * our receive buffer size. Hyper-V sends messages up to ++ * HV_HYP_PAGE_SIZE bytes long on balloon channel. ++ */ ++ dev->channel->max_pkt_size = HV_HYP_PAGE_SIZE * 2; ++ + ret = vmbus_open(dev->channel, dm_ring_size, dm_ring_size, NULL, 0, + balloon_onchannelcallback, dev); + if (ret) +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 392c1ac4f8193..44bd0b6ff5059 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -2027,8 +2027,10 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel) + kobj->kset = dev->channels_kset; + ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL, + "%u", relid); +- if (ret) ++ if (ret) { ++ kobject_put(kobj); + return ret; ++ } + + ret = sysfs_create_group(kobj, &vmbus_chan_group); + +@@ -2037,6 +2039,7 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel) + * The calling functions' error handling paths will cleanup the + * empty channel directory. + */ ++ kobject_put(kobj); + dev_err(device, "Unable to set up channel sysfs files\n"); + return ret; + } +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index c4578e8f34bb5..ccdaeafed0bb7 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1317,7 +1317,7 @@ config SENSORS_LM90 + Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658, + MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, + ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG, +- Philips SA56004, GMT G781, and Texas Instruments TMP451 ++ Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461 + sensor chips. + + This driver can also be built as a module. If so, the module +diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c +index d519aca4a9d64..fb6d14d213a18 100644 +--- a/drivers/hwmon/adt7470.c ++++ b/drivers/hwmon/adt7470.c +@@ -662,6 +662,9 @@ static int adt7470_fan_write(struct device *dev, u32 attr, int channel, long val + struct adt7470_data *data = dev_get_drvdata(dev); + int err; + ++ if (val <= 0) ++ return -EINVAL; ++ + val = FAN_RPM_TO_PERIOD(val); + val = clamp_val(val, 1, 65534); + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index 731d5117f9f10..14389fd7afb89 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -729,7 +729,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + corsairpsu_check_cmd_support(priv); + + priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsairpsu", priv, +- &corsairpsu_chip_info, 0); ++ &corsairpsu_chip_info, NULL); + + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); +diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c +index 774c1b0715d91..9cb1c3588038f 100644 +--- a/drivers/hwmon/dell-smm-hwmon.c ++++ b/drivers/hwmon/dell-smm-hwmon.c +@@ -326,7 +326,7 @@ static int i8k_enable_fan_auto_mode(const struct dell_smm_data *data, bool enabl + } + + /* +- * Set the fan speed (off, low, high). Returns the new fan status. ++ * Set the fan speed (off, low, high, ...). + */ + static int i8k_set_fan(const struct dell_smm_data *data, int fan, int speed) + { +@@ -338,7 +338,7 @@ static int i8k_set_fan(const struct dell_smm_data *data, int fan, int speed) + speed = (speed < 0) ? 0 : ((speed > data->i8k_fan_max) ? data->i8k_fan_max : speed); + regs.ebx = (fan & 0xff) | (speed << 8); + +- return i8k_smm(®s) ? : i8k_get_fan_status(data, fan); ++ return i8k_smm(®s); + } + + static int __init i8k_get_temp_type(int sensor) +@@ -452,7 +452,7 @@ static int + i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd, unsigned long arg) + { + int val = 0; +- int speed; ++ int speed, err; + unsigned char buff[16]; + int __user *argp = (int __user *)arg; + +@@ -513,7 +513,11 @@ i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd + if (copy_from_user(&speed, argp + 1, sizeof(int))) + return -EFAULT; + +- val = i8k_set_fan(data, val, speed); ++ err = i8k_set_fan(data, val, speed); ++ if (err < 0) ++ return err; ++ ++ val = i8k_get_fan_status(data, val); + break; + + default: +@@ -623,10 +627,9 @@ static void __init i8k_init_procfs(struct device *dev) + { + struct dell_smm_data *data = dev_get_drvdata(dev); + +- /* Register the proc entry */ +- proc_create_data("i8k", 0, NULL, &i8k_proc_ops, data); +- +- devm_add_action_or_reset(dev, i8k_exit_procfs, NULL); ++ /* Only register exit function if creation was successful */ ++ if (proc_create_data("i8k", 0, NULL, &i8k_proc_ops, data)) ++ devm_add_action_or_reset(dev, i8k_exit_procfs, NULL); + } + + #else +diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c +index 8d3b1dae31df1..3ae961986fc31 100644 +--- a/drivers/hwmon/hwmon.c ++++ b/drivers/hwmon/hwmon.c +@@ -214,12 +214,14 @@ static int hwmon_thermal_add_sensor(struct device *dev, int index) + + tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata, + &hwmon_thermal_ops); +- /* +- * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV, +- * so ignore that error but forward any other error. +- */ +- if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV)) +- return PTR_ERR(tzd); ++ if (IS_ERR(tzd)) { ++ if (PTR_ERR(tzd) != -ENODEV) ++ return PTR_ERR(tzd); ++ dev_info(dev, "temp%d_input not attached to any thermal zone\n", ++ index + 1); ++ devm_kfree(dev, tdata); ++ return 0; ++ } + + err = devm_add_action(dev, hwmon_thermal_remove_sensor, &tdata->node); + if (err) +@@ -796,8 +798,10 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, + dev_set_drvdata(hdev, drvdata); + dev_set_name(hdev, HWMON_ID_FORMAT, id); + err = device_register(hdev); +- if (err) +- goto free_hwmon; ++ if (err) { ++ put_device(hdev); ++ goto ida_remove; ++ } + + INIT_LIST_HEAD(&hwdev->tzdata); + +diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c +index 567b7c521f388..1c9493c708132 100644 +--- a/drivers/hwmon/lm90.c ++++ b/drivers/hwmon/lm90.c +@@ -35,13 +35,14 @@ + * explicitly as max6659, or if its address is not 0x4c. + * These chips lack the remote temperature offset feature. + * +- * This driver also supports the MAX6654 chip made by Maxim. This chip can +- * be at 9 different addresses, similar to MAX6680/MAX6681. The MAX6654 is +- * otherwise similar to MAX6657/MAX6658/MAX6659. Extended range is available +- * by setting the configuration register accordingly, and is done during +- * initialization. Extended precision is only available at conversion rates +- * of 1 Hz and slower. Note that extended precision is not enabled by +- * default, as this driver initializes all chips to 2 Hz by design. ++ * This driver also supports the MAX6654 chip made by Maxim. This chip can be ++ * at 9 different addresses, similar to MAX6680/MAX6681. The MAX6654 is similar ++ * to MAX6657/MAX6658/MAX6659, but does not support critical temperature ++ * limits. Extended range is available by setting the configuration register ++ * accordingly, and is done during initialization. Extended precision is only ++ * available at conversion rates of 1 Hz and slower. Note that extended ++ * precision is not enabled by default, as this driver initializes all chips ++ * to 2 Hz by design. + * + * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and + * MAX6692 chips made by Maxim. These are again similar to the LM86, +@@ -69,10 +70,10 @@ + * This driver also supports the G781 from GMT. This device is compatible + * with the ADM1032. + * +- * This driver also supports TMP451 from Texas Instruments. This device is +- * supported in both compatibility and extended mode. It's mostly compatible +- * with ADT7461 except for local temperature low byte register and max +- * conversion rate. ++ * This driver also supports TMP451 and TMP461 from Texas Instruments. ++ * Those devices are supported in both compatibility and extended mode. ++ * They are mostly compatible with ADT7461 except for local temperature ++ * low byte register and max conversion rate. + * + * Since the LM90 was the first chipset supported by this driver, most + * comments will refer to this chipset, but are actually general and +@@ -112,7 +113,7 @@ static const unsigned short normal_i2c[] = { + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; + + enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, +- max6646, w83l771, max6696, sa56004, g781, tmp451, max6654 }; ++ max6646, w83l771, max6696, sa56004, g781, tmp451, tmp461, max6654 }; + + /* + * The LM90 registers +@@ -168,8 +169,12 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, + + #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ + +-/* TMP451 registers */ ++/* TMP451/TMP461 registers */ + #define TMP451_REG_R_LOCAL_TEMPL 0x15 ++#define TMP451_REG_CONALERT 0x22 ++ ++#define TMP461_REG_CHEN 0x16 ++#define TMP461_REG_DFC 0x24 + + /* + * Device flags +@@ -182,7 +187,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, + #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ + #define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ + #define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ +-#define LM90_PAUSE_FOR_CONFIG (1 << 8) /* Pause conversion for config */ ++#define LM90_HAVE_EXTENDED_TEMP (1 << 8) /* extended temperature support*/ ++#define LM90_PAUSE_FOR_CONFIG (1 << 9) /* Pause conversion for config */ ++#define LM90_HAVE_CRIT (1 << 10)/* Chip supports CRIT/OVERT register */ ++#define LM90_HAVE_CRIT_ALRM_SWP (1 << 11)/* critical alarm bits swapped */ + + /* LM90 status */ + #define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */ +@@ -192,6 +200,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, + #define LM90_STATUS_RHIGH (1 << 4) /* remote high temp limit tripped */ + #define LM90_STATUS_LLOW (1 << 5) /* local low temp limit tripped */ + #define LM90_STATUS_LHIGH (1 << 6) /* local high temp limit tripped */ ++#define LM90_STATUS_BUSY (1 << 7) /* conversion is ongoing */ + + #define MAX6696_STATUS2_R2THRM (1 << 1) /* remote2 THERM limit tripped */ + #define MAX6696_STATUS2_R2OPEN (1 << 2) /* remote2 is an open circuit */ +@@ -229,6 +238,7 @@ static const struct i2c_device_id lm90_id[] = { + { "w83l771", w83l771 }, + { "sa56004", sa56004 }, + { "tmp451", tmp451 }, ++ { "tmp461", tmp461 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm90_id); +@@ -326,6 +336,10 @@ static const struct of_device_id __maybe_unused lm90_of_match[] = { + .compatible = "ti,tmp451", + .data = (void *)tmp451 + }, ++ { ++ .compatible = "ti,tmp461", ++ .data = (void *)tmp461 ++ }, + { }, + }; + MODULE_DEVICE_TABLE(of, lm90_of_match); +@@ -344,85 +358,99 @@ struct lm90_params { + static const struct lm90_params lm90_params[] = { + [adm1032] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT +- | LM90_HAVE_BROKEN_ALERT, ++ | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, + .max_convrate = 10, + }, + [adt7461] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT +- | LM90_HAVE_BROKEN_ALERT, ++ | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP ++ | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, + .max_convrate = 10, + }, + [g781] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT +- | LM90_HAVE_BROKEN_ALERT, ++ | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, +- .max_convrate = 8, ++ .max_convrate = 7, + }, + [lm86] = { +- .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT ++ | LM90_HAVE_CRIT, + .alert_alarms = 0x7b, + .max_convrate = 9, + }, + [lm90] = { +- .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT ++ | LM90_HAVE_CRIT, + .alert_alarms = 0x7b, + .max_convrate = 9, + }, + [lm99] = { +- .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT ++ | LM90_HAVE_CRIT, + .alert_alarms = 0x7b, + .max_convrate = 9, + }, + [max6646] = { ++ .flags = LM90_HAVE_CRIT | LM90_HAVE_BROKEN_ALERT, + .alert_alarms = 0x7c, + .max_convrate = 6, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, + }, + [max6654] = { ++ .flags = LM90_HAVE_BROKEN_ALERT, + .alert_alarms = 0x7c, + .max_convrate = 7, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, + }, + [max6657] = { +- .flags = LM90_PAUSE_FOR_CONFIG, ++ .flags = LM90_PAUSE_FOR_CONFIG | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, + .max_convrate = 8, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, + }, + [max6659] = { +- .flags = LM90_HAVE_EMERGENCY, ++ .flags = LM90_HAVE_EMERGENCY | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, + .max_convrate = 8, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, + }, + [max6680] = { +- .flags = LM90_HAVE_OFFSET, ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_CRIT ++ | LM90_HAVE_CRIT_ALRM_SWP | LM90_HAVE_BROKEN_ALERT, + .alert_alarms = 0x7c, + .max_convrate = 7, + }, + [max6696] = { + .flags = LM90_HAVE_EMERGENCY +- | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, ++ | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3 | LM90_HAVE_CRIT, + .alert_alarms = 0x1c7c, + .max_convrate = 6, + .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, + }, + [w83l771] = { +- .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, + .max_convrate = 8, + }, + [sa56004] = { +- .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT, + .alert_alarms = 0x7b, + .max_convrate = 9, + .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, + }, + [tmp451] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT +- | LM90_HAVE_BROKEN_ALERT, ++ | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT, ++ .alert_alarms = 0x7c, ++ .max_convrate = 9, ++ .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, ++ }, ++ [tmp461] = { ++ .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT ++ | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT, + .alert_alarms = 0x7c, + .max_convrate = 9, + .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, +@@ -651,20 +679,22 @@ static int lm90_update_limits(struct device *dev) + struct i2c_client *client = data->client; + int val; + +- val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT); +- if (val < 0) +- return val; +- data->temp8[LOCAL_CRIT] = val; ++ if (data->flags & LM90_HAVE_CRIT) { ++ val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT); ++ if (val < 0) ++ return val; ++ data->temp8[LOCAL_CRIT] = val; + +- val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT); +- if (val < 0) +- return val; +- data->temp8[REMOTE_CRIT] = val; ++ val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT); ++ if (val < 0) ++ return val; ++ data->temp8[REMOTE_CRIT] = val; + +- val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST); +- if (val < 0) +- return val; +- data->temp_hyst = val; ++ val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST); ++ if (val < 0) ++ return val; ++ data->temp_hyst = val; ++ } + + val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH); + if (val < 0) +@@ -792,7 +822,7 @@ static int lm90_update_device(struct device *dev) + val = lm90_read_reg(client, LM90_REG_R_STATUS); + if (val < 0) + return val; +- data->alarms = val; /* lower 8 bit of alarms */ ++ data->alarms = val & ~LM90_STATUS_BUSY; + + if (data->kind == max6696) { + val = lm90_select_remote_channel(data, 1); +@@ -819,7 +849,7 @@ static int lm90_update_device(struct device *dev) + * Re-enable ALERT# output if it was originally enabled and + * relevant alarms are all clear + */ +- if (!(data->config_orig & 0x80) && ++ if ((client->irq || !(data->config_orig & 0x80)) && + !(data->alarms & data->alert_alarms)) { + if (data->config & 0x80) { + dev_dbg(&client->dev, "Re-enabling ALERT#\n"); +@@ -998,7 +1028,7 @@ static int lm90_get_temp11(struct lm90_data *data, int index) + s16 temp11 = data->temp11[index]; + int temp; + +- if (data->kind == adt7461 || data->kind == tmp451) ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) + temp = temp_from_u16_adt7461(data, temp11); + else if (data->kind == max6646) + temp = temp_from_u16(temp11); +@@ -1035,7 +1065,7 @@ static int lm90_set_temp11(struct lm90_data *data, int index, long val) + val -= 16000; + } + +- if (data->kind == adt7461 || data->kind == tmp451) ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) + data->temp11[index] = temp_to_u16_adt7461(data, val); + else if (data->kind == max6646) + data->temp11[index] = temp_to_u8(val) << 8; +@@ -1062,7 +1092,7 @@ static int lm90_get_temp8(struct lm90_data *data, int index) + s8 temp8 = data->temp8[index]; + int temp; + +- if (data->kind == adt7461 || data->kind == tmp451) ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) + temp = temp_from_u8_adt7461(data, temp8); + else if (data->kind == max6646) + temp = temp_from_u8(temp8); +@@ -1098,7 +1128,7 @@ static int lm90_set_temp8(struct lm90_data *data, int index, long val) + val -= 16000; + } + +- if (data->kind == adt7461 || data->kind == tmp451) ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) + data->temp8[index] = temp_to_u8_adt7461(data, val); + else if (data->kind == max6646) + data->temp8[index] = temp_to_u8(val); +@@ -1116,7 +1146,7 @@ static int lm90_get_temphyst(struct lm90_data *data, int index) + { + int temp; + +- if (data->kind == adt7461 || data->kind == tmp451) ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) + temp = temp_from_u8_adt7461(data, data->temp8[index]); + else if (data->kind == max6646) + temp = temp_from_u8(data->temp8[index]); +@@ -1136,15 +1166,15 @@ static int lm90_set_temphyst(struct lm90_data *data, long val) + int temp; + int err; + +- if (data->kind == adt7461 || data->kind == tmp451) ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) + temp = temp_from_u8_adt7461(data, data->temp8[LOCAL_CRIT]); + else if (data->kind == max6646) + temp = temp_from_u8(data->temp8[LOCAL_CRIT]); + else + temp = temp_from_s8(data->temp8[LOCAL_CRIT]); + +- /* prevent integer underflow */ +- val = max(val, -128000l); ++ /* prevent integer overflow/underflow */ ++ val = clamp_val(val, -128000l, 255000l); + + data->temp_hyst = hyst_to_reg(temp - val); + err = i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, +@@ -1175,6 +1205,7 @@ static const u8 lm90_temp_emerg_index[3] = { + static const u8 lm90_min_alarm_bits[3] = { 5, 3, 11 }; + static const u8 lm90_max_alarm_bits[3] = { 6, 4, 12 }; + static const u8 lm90_crit_alarm_bits[3] = { 0, 1, 9 }; ++static const u8 lm90_crit_alarm_bits_swapped[3] = { 1, 0, 9 }; + static const u8 lm90_emergency_alarm_bits[3] = { 15, 13, 14 }; + static const u8 lm90_fault_bits[3] = { 0, 2, 10 }; + +@@ -1200,7 +1231,10 @@ static int lm90_temp_read(struct device *dev, u32 attr, int channel, long *val) + *val = (data->alarms >> lm90_max_alarm_bits[channel]) & 1; + break; + case hwmon_temp_crit_alarm: +- *val = (data->alarms >> lm90_crit_alarm_bits[channel]) & 1; ++ if (data->flags & LM90_HAVE_CRIT_ALRM_SWP) ++ *val = (data->alarms >> lm90_crit_alarm_bits_swapped[channel]) & 1; ++ else ++ *val = (data->alarms >> lm90_crit_alarm_bits[channel]) & 1; + break; + case hwmon_temp_emergency_alarm: + *val = (data->alarms >> lm90_emergency_alarm_bits[channel]) & 1; +@@ -1448,12 +1482,11 @@ static int lm90_detect(struct i2c_client *client, + if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0) + return -ENODEV; + +- if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) { ++ if (man_id == 0x01 || man_id == 0x5C || man_id == 0xA1) { + config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2); + if (config2 < 0) + return -ENODEV; +- } else +- config2 = 0; /* Make compiler happy */ ++ } + + if ((address == 0x4C || address == 0x4D) + && man_id == 0x01) { /* National Semiconductor */ +@@ -1627,18 +1660,26 @@ static int lm90_detect(struct i2c_client *client, + && convrate <= 0x08) + name = "g781"; + } else +- if (address == 0x4C +- && man_id == 0x55) { /* Texas Instruments */ +- int local_ext; ++ if (man_id == 0x55 && chip_id == 0x00 && ++ (config1 & 0x1B) == 0x00 && convrate <= 0x09) { ++ int local_ext, conalert, chen, dfc; + + local_ext = i2c_smbus_read_byte_data(client, + TMP451_REG_R_LOCAL_TEMPL); +- +- if (chip_id == 0x00 /* TMP451 */ +- && (config1 & 0x1B) == 0x00 +- && convrate <= 0x09 +- && (local_ext & 0x0F) == 0x00) +- name = "tmp451"; ++ conalert = i2c_smbus_read_byte_data(client, ++ TMP451_REG_CONALERT); ++ chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN); ++ dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC); ++ ++ if ((local_ext & 0x0F) == 0x00 && ++ (conalert & 0xf1) == 0x01 && ++ (chen & 0xfc) == 0x00 && ++ (dfc & 0xfc) == 0x00) { ++ if (address == 0x4c && !(chen & 0x03)) ++ name = "tmp451"; ++ else if (address >= 0x48 && address <= 0x4f) ++ name = "tmp461"; ++ } + } + + if (!name) { /* identification failed */ +@@ -1685,7 +1726,7 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data) + lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ + + /* Check Temperature Range Select */ +- if (data->kind == adt7461 || data->kind == tmp451) { ++ if (data->flags & LM90_HAVE_EXTENDED_TEMP) { + if (config & 0x04) + data->flags |= LM90_FLAG_ADT7461_EXT; + } +@@ -1767,22 +1808,22 @@ static bool lm90_is_tripped(struct i2c_client *client, u16 *status) + + if (st & LM90_STATUS_LLOW) + hwmon_notify_event(data->hwmon_dev, hwmon_temp, +- hwmon_temp_min, 0); ++ hwmon_temp_min_alarm, 0); + if (st & LM90_STATUS_RLOW) + hwmon_notify_event(data->hwmon_dev, hwmon_temp, +- hwmon_temp_min, 1); ++ hwmon_temp_min_alarm, 1); + if (st2 & MAX6696_STATUS2_R2LOW) + hwmon_notify_event(data->hwmon_dev, hwmon_temp, +- hwmon_temp_min, 2); ++ hwmon_temp_min_alarm, 2); + if (st & LM90_STATUS_LHIGH) + hwmon_notify_event(data->hwmon_dev, hwmon_temp, +- hwmon_temp_max, 0); ++ hwmon_temp_max_alarm, 0); + if (st & LM90_STATUS_RHIGH) + hwmon_notify_event(data->hwmon_dev, hwmon_temp, +- hwmon_temp_max, 1); ++ hwmon_temp_max_alarm, 1); + if (st2 & MAX6696_STATUS2_R2HIGH) + hwmon_notify_event(data->hwmon_dev, hwmon_temp, +- hwmon_temp_max, 2); ++ hwmon_temp_max_alarm, 2); + + return true; + } +@@ -1878,11 +1919,14 @@ static int lm90_probe(struct i2c_client *client) + info->config = data->channel_config; + + data->channel_config[0] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | +- HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | +- HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM; ++ HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM; + data->channel_config[1] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | +- HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | +- HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT; ++ HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM | HWMON_T_FAULT; ++ ++ if (data->flags & LM90_HAVE_CRIT) { ++ data->channel_config[0] |= HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST; ++ data->channel_config[1] |= HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST; ++ } + + if (data->flags & LM90_HAVE_OFFSET) + data->channel_config[1] |= HWMON_T_OFFSET; +diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c +index 868243dba1ee0..1ba1e31459690 100644 +--- a/drivers/hwmon/mr75203.c ++++ b/drivers/hwmon/mr75203.c +@@ -93,7 +93,7 @@ + #define VM_CH_REQ BIT(21) + + #define IP_TMR 0x05 +-#define POWER_DELAY_CYCLE_256 0x80 ++#define POWER_DELAY_CYCLE_256 0x100 + #define POWER_DELAY_CYCLE_64 0x40 + + #define PVT_POLL_DELAY_US 20 +diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c +index d209e0afc2caa..66d3e88b54172 100644 +--- a/drivers/hwmon/pmbus/lm25066.c ++++ b/drivers/hwmon/pmbus/lm25066.c +@@ -51,26 +51,31 @@ struct __coeff { + #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) + #define PSC_POWER_L (PSC_NUM_CLASSES + 1) + +-static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { ++static struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = { + [lm25056] = { + [PSC_VOLTAGE_IN] = { + .m = 16296, ++ .b = 1343, + .R = -2, + }, + [PSC_CURRENT_IN] = { + .m = 13797, ++ .b = -1833, + .R = -2, + }, + [PSC_CURRENT_IN_L] = { + .m = 6726, ++ .b = -537, + .R = -2, + }, + [PSC_POWER] = { + .m = 5501, ++ .b = -2908, + .R = -3, + }, + [PSC_POWER_L] = { + .m = 26882, ++ .b = -5646, + .R = -4, + }, + [PSC_TEMPERATURE] = { +@@ -82,26 +87,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { + [lm25066] = { + [PSC_VOLTAGE_IN] = { + .m = 22070, ++ .b = -1800, + .R = -2, + }, + [PSC_VOLTAGE_OUT] = { + .m = 22070, ++ .b = -1800, + .R = -2, + }, + [PSC_CURRENT_IN] = { + .m = 13661, ++ .b = -5200, + .R = -2, + }, + [PSC_CURRENT_IN_L] = { + .m = 6852, ++ .b = -3100, + .R = -2, + }, + [PSC_POWER] = { + .m = 736, ++ .b = -3300, + .R = -2, + }, + [PSC_POWER_L] = { + .m = 369, ++ .b = -1900, + .R = -2, + }, + [PSC_TEMPERATURE] = { +@@ -111,26 +122,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { + [lm5064] = { + [PSC_VOLTAGE_IN] = { + .m = 4611, ++ .b = -642, + .R = -2, + }, + [PSC_VOLTAGE_OUT] = { + .m = 4621, ++ .b = 423, + .R = -2, + }, + [PSC_CURRENT_IN] = { + .m = 10742, ++ .b = 1552, + .R = -2, + }, + [PSC_CURRENT_IN_L] = { + .m = 5456, ++ .b = 2118, + .R = -2, + }, + [PSC_POWER] = { + .m = 1204, ++ .b = 8524, + .R = -3, + }, + [PSC_POWER_L] = { + .m = 612, ++ .b = 11202, + .R = -3, + }, + [PSC_TEMPERATURE] = { +@@ -140,26 +157,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { + [lm5066] = { + [PSC_VOLTAGE_IN] = { + .m = 4587, ++ .b = -1200, + .R = -2, + }, + [PSC_VOLTAGE_OUT] = { + .m = 4587, ++ .b = -2400, + .R = -2, + }, + [PSC_CURRENT_IN] = { + .m = 10753, ++ .b = -1200, + .R = -2, + }, + [PSC_CURRENT_IN_L] = { + .m = 5405, ++ .b = -600, + .R = -2, + }, + [PSC_POWER] = { + .m = 1204, ++ .b = -6000, + .R = -3, + }, + [PSC_POWER_L] = { + .m = 605, ++ .b = -8000, + .R = -3, + }, + [PSC_TEMPERATURE] = { +diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c +index 17518b4cab1b0..f12b9a28a232d 100644 +--- a/drivers/hwmon/pwm-fan.c ++++ b/drivers/hwmon/pwm-fan.c +@@ -336,8 +336,6 @@ static int pwm_fan_probe(struct platform_device *pdev) + return ret; + } + +- ctx->pwm_value = MAX_PWM; +- + pwm_init_state(ctx->pwm, &ctx->pwm_state); + + /* +diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c +index e2a3620cbf489..8988b2ed2ea6f 100644 +--- a/drivers/hwtracing/coresight/coresight-cti-core.c ++++ b/drivers/hwtracing/coresight/coresight-cti-core.c +@@ -175,7 +175,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) + coresight_disclaim_device_unlocked(csdev); + CS_LOCK(drvdata->base); + spin_unlock(&drvdata->spinlock); +- pm_runtime_put(dev); ++ pm_runtime_put(dev->parent); + return 0; + + /* not disabled this call */ +diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c +index 1768684968797..7dddb85b90591 100644 +--- a/drivers/hwtracing/coresight/coresight-trbe.c ++++ b/drivers/hwtracing/coresight/coresight-trbe.c +@@ -366,7 +366,7 @@ static unsigned long __trbe_normal_offset(struct perf_output_handle *handle) + + static unsigned long trbe_normal_offset(struct perf_output_handle *handle) + { +- struct trbe_buf *buf = perf_get_aux(handle); ++ struct trbe_buf *buf = etm_perf_sink_config(handle); + u64 limit = __trbe_normal_offset(handle); + u64 head = PERF_IDX2OFF(handle->head, buf); + +@@ -869,6 +869,10 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp + if (WARN_ON(trbe_csdev)) + return; + ++ /* If the TRBE was not probed on the CPU, we shouldn't be here */ ++ if (WARN_ON(!cpudata->drvdata)) ++ return; ++ + dev = &cpudata->drvdata->pdev->dev; + desc.name = devm_kasprintf(dev, GFP_KERNEL, "trbe%d", cpu); + if (!desc.name) +@@ -950,7 +954,9 @@ static int arm_trbe_probe_coresight(struct trbe_drvdata *drvdata) + return -ENOMEM; + + for_each_cpu(cpu, &drvdata->supported_cpus) { +- smp_call_function_single(cpu, arm_trbe_probe_cpu, drvdata, 1); ++ /* If we fail to probe the CPU, let us defer it to hotplug callbacks */ ++ if (smp_call_function_single(cpu, arm_trbe_probe_cpu, drvdata, 1)) ++ continue; + if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) + arm_trbe_register_coresight_cpu(drvdata, cpu); + if (cpumask_test_cpu(cpu, &drvdata->supported_cpus)) +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index e17790fe35a74..fea403431f228 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -488,7 +488,7 @@ config I2C_BRCMSTB + + config I2C_CADENCE + tristate "Cadence I2C Controller" +- depends on ARCH_ZYNQ || ARM64 || XTENSA ++ depends on ARCH_ZYNQ || ARM64 || XTENSA || COMPILE_TEST + help + Say yes here to select Cadence I2C Host Controller. This controller is + e.g. used by Xilinx Zynq. +@@ -677,7 +677,7 @@ config I2C_IMG + + config I2C_IMX + tristate "IMX I2C interface" +- depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE ++ depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE || COMPILE_TEST + select I2C_SLAVE + help + Say Y here if you want to use the IIC bus controller on +@@ -921,7 +921,7 @@ config I2C_QCOM_GENI + + config I2C_QUP + tristate "Qualcomm QUP based I2C controller" +- depends on ARCH_QCOM ++ depends on ARCH_QCOM || COMPILE_TEST + help + If you say yes to this option, support will be included for the + built-in I2C interface on the Qualcomm SoCs. +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index 37443edbf7546..ad3b124a2e376 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -23,6 +23,11 @@ + #define BCM2835_I2C_FIFO 0x10 + #define BCM2835_I2C_DIV 0x14 + #define BCM2835_I2C_DEL 0x18 ++/* ++ * 16-bit field for the number of SCL cycles to wait after rising SCL ++ * before deciding the slave is not responding. 0 disables the ++ * timeout detection. ++ */ + #define BCM2835_I2C_CLKT 0x1c + + #define BCM2835_I2C_C_READ BIT(0) +@@ -477,6 +482,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) + adap->dev.of_node = pdev->dev.of_node; + adap->quirks = of_device_get_match_data(&pdev->dev); + ++ /* ++ * Disable the hardware clock stretching timeout. SMBUS ++ * specifies a limit for how long the device can stretch the ++ * clock, but core I2C doesn't. ++ */ ++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_CLKT, 0); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0); + + ret = i2c_add_adapter(adap); +diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c +index 490ee3962645d..b00f35c0b0662 100644 +--- a/drivers/i2c/busses/i2c-brcmstb.c ++++ b/drivers/i2c/busses/i2c-brcmstb.c +@@ -673,7 +673,7 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) + + /* set the data in/out register size for compatible SoCs */ + if (of_device_is_compatible(dev->device->of_node, +- "brcmstb,brcmper-i2c")) ++ "brcm,brcmper-i2c")) + dev->data_regsz = sizeof(u8); + else + dev->data_regsz = sizeof(u32); +diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c +index 72df563477b1c..f8639a4457d23 100644 +--- a/drivers/i2c/busses/i2c-cbus-gpio.c ++++ b/drivers/i2c/busses/i2c-cbus-gpio.c +@@ -195,8 +195,9 @@ static u32 cbus_i2c_func(struct i2c_adapter *adapter) + } + + static const struct i2c_algorithm cbus_i2c_algo = { +- .smbus_xfer = cbus_i2c_smbus_xfer, +- .functionality = cbus_i2c_func, ++ .smbus_xfer = cbus_i2c_smbus_xfer, ++ .smbus_xfer_atomic = cbus_i2c_smbus_xfer, ++ .functionality = cbus_i2c_func, + }; + + static int cbus_i2c_remove(struct platform_device *pdev) +diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c +index 0f409a4c2da0d..5b45941bcbddc 100644 +--- a/drivers/i2c/busses/i2c-designware-pcidrv.c ++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c +@@ -39,10 +39,10 @@ enum dw_pci_ctl_id_t { + }; + + struct dw_scl_sda_cfg { +- u32 ss_hcnt; +- u32 fs_hcnt; +- u32 ss_lcnt; +- u32 fs_lcnt; ++ u16 ss_hcnt; ++ u16 fs_hcnt; ++ u16 ss_lcnt; ++ u16 fs_lcnt; + u32 sda_hold; + }; + +diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c +index 89ae78ef1a1cc..98e39a17fb830 100644 +--- a/drivers/i2c/busses/i2c-i801.c ++++ b/drivers/i2c/busses/i2c-i801.c +@@ -763,6 +763,11 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data * + int result = 0; + unsigned char hostc; + ++ if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA) ++ data->block[0] = I2C_SMBUS_BLOCK_MAX; ++ else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) ++ return -EPROTO; ++ + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ +@@ -776,16 +781,6 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data * + } + } + +- if (read_write == I2C_SMBUS_WRITE +- || command == I2C_SMBUS_I2C_BLOCK_DATA) { +- if (data->block[0] < 1) +- data->block[0] = 1; +- if (data->block[0] > I2C_SMBUS_BLOCK_MAX) +- data->block[0] = I2C_SMBUS_BLOCK_MAX; +- } else { +- data->block[0] = 32; /* max for SMBus block reads */ +- } +- + /* Experience has shown that the block buffer can only be used for + SMBus (not I2C) block transactions, even though the datasheet + doesn't mention this limitation. */ +@@ -1493,7 +1488,6 @@ static struct platform_device * + i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, + struct resource *tco_res) + { +- static DEFINE_MUTEX(p2sb_mutex); + struct resource *res; + unsigned int devfn; + u64 base64_addr; +@@ -1506,7 +1500,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, + * enumerated by the PCI subsystem, so we need to unhide/hide it + * to lookup the P2SB BAR. + */ +- mutex_lock(&p2sb_mutex); ++ pci_lock_rescan_remove(); + + devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1); + +@@ -1524,7 +1518,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, + /* Hide the P2SB device, if it was hidden before */ + if (hidden) + pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden); +- mutex_unlock(&p2sb_mutex); ++ pci_unlock_rescan_remove(); + + res = &tco_res[1]; + if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) +diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c +index a6ea1eb1394e1..6c698c10d3cdb 100644 +--- a/drivers/i2c/busses/i2c-mpc.c ++++ b/drivers/i2c/busses/i2c-mpc.c +@@ -119,23 +119,30 @@ static inline void writeccr(struct mpc_i2c *i2c, u32 x) + /* Sometimes 9th clock pulse isn't generated, and slave doesn't release + * the bus, because it wants to send ACK. + * Following sequence of enabling/disabling and sending start/stop generates +- * the 9 pulses, so it's all OK. ++ * the 9 pulses, each with a START then ending with STOP, so it's all OK. + */ + static void mpc_i2c_fixup(struct mpc_i2c *i2c) + { + int k; +- u32 delay_val = 1000000 / i2c->real_clk + 1; +- +- if (delay_val < 2) +- delay_val = 2; ++ unsigned long flags; + + for (k = 9; k; k--) { + writeccr(i2c, 0); +- writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); ++ writeb(0, i2c->base + MPC_I2C_SR); /* clear any status bits */ ++ writeccr(i2c, CCR_MEN | CCR_MSTA); /* START */ ++ readb(i2c->base + MPC_I2C_DR); /* init xfer */ ++ udelay(15); /* let it hit the bus */ ++ local_irq_save(flags); /* should not be delayed further */ ++ writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSTA); /* delay SDA */ + readb(i2c->base + MPC_I2C_DR); +- writeccr(i2c, CCR_MEN); +- udelay(delay_val << 1); ++ if (k != 1) ++ udelay(5); ++ local_irq_restore(flags); + } ++ writeccr(i2c, CCR_MEN); /* Initiate STOP */ ++ readb(i2c->base + MPC_I2C_DR); ++ udelay(15); /* Let STOP propagate */ ++ writeccr(i2c, 0); + } + + static int i2c_mpc_wait_sr(struct mpc_i2c *i2c, int mask) +@@ -492,7 +499,7 @@ static void mpc_i2c_finish(struct mpc_i2c *i2c, int rc) + + static void mpc_i2c_do_action(struct mpc_i2c *i2c) + { +- struct i2c_msg *msg = &i2c->msgs[i2c->curr_msg]; ++ struct i2c_msg *msg = NULL; + int dir = 0; + int recv_len = 0; + u8 byte; +@@ -501,10 +508,13 @@ static void mpc_i2c_do_action(struct mpc_i2c *i2c) + + i2c->cntl_bits &= ~(CCR_RSTA | CCR_MTX | CCR_TXAK); + +- if (msg->flags & I2C_M_RD) +- dir = 1; +- if (msg->flags & I2C_M_RECV_LEN) +- recv_len = 1; ++ if (i2c->action != MPC_I2C_ACTION_STOP) { ++ msg = &i2c->msgs[i2c->curr_msg]; ++ if (msg->flags & I2C_M_RD) ++ dir = 1; ++ if (msg->flags & I2C_M_RECV_LEN) ++ recv_len = 1; ++ } + + switch (i2c->action) { + case MPC_I2C_ACTION_RESTART: +@@ -581,7 +591,7 @@ static void mpc_i2c_do_action(struct mpc_i2c *i2c) + break; + } + +- if (msg->len == i2c->byte_posn) { ++ if (msg && msg->len == i2c->byte_posn) { + i2c->curr_msg++; + i2c->byte_posn = 0; + +@@ -636,7 +646,7 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) + status = readb(i2c->base + MPC_I2C_SR); + if (status & CSR_MIF) { + /* Wait up to 100us for transfer to properly complete */ +- readb_poll_timeout(i2c->base + MPC_I2C_SR, status, !(status & CSR_MCF), 0, 100); ++ readb_poll_timeout_atomic(i2c->base + MPC_I2C_SR, status, status & CSR_MCF, 0, 100); + writeb(0, i2c->base + MPC_I2C_SR); + mpc_i2c_do_intr(i2c, status); + return IRQ_HANDLED; +diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c +index 7d4b3eb7077ad..72acda59eb399 100644 +--- a/drivers/i2c/busses/i2c-mt65xx.c ++++ b/drivers/i2c/busses/i2c-mt65xx.c +@@ -195,7 +195,7 @@ static const u16 mt_i2c_regs_v2[] = { + [OFFSET_CLOCK_DIV] = 0x48, + [OFFSET_SOFTRESET] = 0x50, + [OFFSET_SCL_MIS_COMP_POINT] = 0x90, +- [OFFSET_DEBUGSTAT] = 0xe0, ++ [OFFSET_DEBUGSTAT] = 0xe4, + [OFFSET_DEBUGCTRL] = 0xe8, + [OFFSET_FIFO_STAT] = 0xf4, + [OFFSET_FIFO_THRESH] = 0xf8, +diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c +index c1de8eb66169f..cf54f1cb4c57a 100644 +--- a/drivers/i2c/busses/i2c-qcom-cci.c ++++ b/drivers/i2c/busses/i2c-qcom-cci.c +@@ -558,7 +558,7 @@ static int cci_probe(struct platform_device *pdev) + cci->master[idx].adap.quirks = &cci->data->quirks; + cci->master[idx].adap.algo = &cci_algo; + cci->master[idx].adap.dev.parent = dev; +- cci->master[idx].adap.dev.of_node = child; ++ cci->master[idx].adap.dev.of_node = of_node_get(child); + cci->master[idx].master = idx; + cci->master[idx].cci = cci; + +@@ -643,8 +643,10 @@ static int cci_probe(struct platform_device *pdev) + continue; + + ret = i2c_add_adapter(&cci->master[i].adap); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(cci->master[i].adap.dev.of_node); + goto error_i2c; ++ } + } + + pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); +@@ -655,9 +657,11 @@ static int cci_probe(struct platform_device *pdev) + return 0; + + error_i2c: +- for (; i >= 0; i--) { +- if (cci->master[i].cci) ++ for (--i ; i >= 0; i--) { ++ if (cci->master[i].cci) { + i2c_del_adapter(&cci->master[i].adap); ++ of_node_put(cci->master[i].adap.dev.of_node); ++ } + } + error: + disable_irq(cci->irq); +@@ -673,8 +677,10 @@ static int cci_remove(struct platform_device *pdev) + int i; + + for (i = 0; i < cci->data->num_masters; i++) { +- if (cci->master[i].cci) ++ if (cci->master[i].cci) { + i2c_del_adapter(&cci->master[i].adap); ++ of_node_put(cci->master[i].adap.dev.of_node); ++ } + cci_halt(cci, i); + } + +diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c +index 819ab4ee517e1..02ddb237f69af 100644 +--- a/drivers/i2c/busses/i2c-rk3x.c ++++ b/drivers/i2c/busses/i2c-rk3x.c +@@ -423,8 +423,8 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) + if (!(ipd & REG_INT_MBRF)) + return; + +- /* ack interrupt */ +- i2c_writel(i2c, REG_INT_MBRF, REG_IPD); ++ /* ack interrupt (read also produces a spurious START flag, clear it too) */ ++ i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD); + + /* Can only handle a maximum of 32 bytes at a time */ + if (len > 32) +diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c +index b9b19a2a2ffa0..50d5ae81d2271 100644 +--- a/drivers/i2c/busses/i2c-stm32f7.c ++++ b/drivers/i2c/busses/i2c-stm32f7.c +@@ -1493,6 +1493,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + { + struct stm32f7_i2c_dev *i2c_dev = data; + struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; ++ struct stm32_i2c_dma *dma = i2c_dev->dma; + void __iomem *base = i2c_dev->base; + u32 status, mask; + int ret = IRQ_HANDLED; +@@ -1518,6 +1519,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", + __func__, f7_msg->addr); + writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); ++ if (i2c_dev->use_dma) { ++ stm32f7_i2c_disable_dma_req(i2c_dev); ++ dmaengine_terminate_all(dma->chan_using); ++ } + f7_msg->result = -ENXIO; + } + +@@ -1533,7 +1538,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + /* Clear STOP flag */ + writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); + +- if (i2c_dev->use_dma) { ++ if (i2c_dev->use_dma && !f7_msg->result) { + ret = IRQ_WAKE_THREAD; + } else { + i2c_dev->master_mode = false; +@@ -1546,7 +1551,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) + if (f7_msg->stop) { + mask = STM32F7_I2C_CR2_STOP; + stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask); +- } else if (i2c_dev->use_dma) { ++ } else if (i2c_dev->use_dma && !f7_msg->result) { + ret = IRQ_WAKE_THREAD; + } else if (f7_msg->smbus) { + stm32f7_i2c_smbus_rep_start(i2c_dev); +@@ -1696,12 +1701,23 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, + time_left = wait_for_completion_timeout(&i2c_dev->complete, + i2c_dev->adap.timeout); + ret = f7_msg->result; ++ if (ret) { ++ /* ++ * It is possible that some unsent data have already been ++ * written into TXDR. To avoid sending old data in a ++ * further transfer, flush TXDR in case of any error ++ */ ++ writel_relaxed(STM32F7_I2C_ISR_TXE, ++ i2c_dev->base + STM32F7_I2C_ISR); ++ goto pm_free; ++ } + + if (!time_left) { + dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n", + i2c_dev->msg->addr); + if (i2c_dev->use_dma) + dmaengine_terminate_all(dma->chan_using); ++ stm32f7_i2c_wait_free_bus(i2c_dev); + ret = -ETIMEDOUT; + } + +@@ -1744,13 +1760,22 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, + timeout = wait_for_completion_timeout(&i2c_dev->complete, + i2c_dev->adap.timeout); + ret = f7_msg->result; +- if (ret) ++ if (ret) { ++ /* ++ * It is possible that some unsent data have already been ++ * written into TXDR. To avoid sending old data in a ++ * further transfer, flush TXDR in case of any error ++ */ ++ writel_relaxed(STM32F7_I2C_ISR_TXE, ++ i2c_dev->base + STM32F7_I2C_ISR); + goto pm_free; ++ } + + if (!timeout) { + dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr); + if (i2c_dev->use_dma) + dmaengine_terminate_all(dma->chan_using); ++ stm32f7_i2c_wait_free_bus(i2c_dev); + ret = -ETIMEDOUT; + goto pm_free; + } +diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c +index f10a603b13fb0..5cb21d7da05b6 100644 +--- a/drivers/i2c/busses/i2c-virtio.c ++++ b/drivers/i2c/busses/i2c-virtio.c +@@ -22,24 +22,24 @@ + /** + * struct virtio_i2c - virtio I2C data + * @vdev: virtio device for this controller +- * @completion: completion of virtio I2C message + * @adap: I2C adapter for this controller + * @vq: the virtio virtqueue for communication + */ + struct virtio_i2c { + struct virtio_device *vdev; +- struct completion completion; + struct i2c_adapter adap; + struct virtqueue *vq; + }; + + /** + * struct virtio_i2c_req - the virtio I2C request structure ++ * @completion: completion of virtio I2C message + * @out_hdr: the OUT header of the virtio I2C message + * @buf: the buffer into which data is read, or from which it's written + * @in_hdr: the IN header of the virtio I2C message + */ + struct virtio_i2c_req { ++ struct completion completion; + struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned; + uint8_t *buf ____cacheline_aligned; + struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned; +@@ -47,9 +47,11 @@ struct virtio_i2c_req { + + static void virtio_i2c_msg_done(struct virtqueue *vq) + { +- struct virtio_i2c *vi = vq->vdev->priv; ++ struct virtio_i2c_req *req; ++ unsigned int len; + +- complete(&vi->completion); ++ while ((req = virtqueue_get_buf(vq, &len))) ++ complete(&req->completion); + } + + static int virtio_i2c_prepare_reqs(struct virtqueue *vq, +@@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, + for (i = 0; i < num; i++) { + int outcnt = 0, incnt = 0; + ++ init_completion(&reqs[i].completion); ++ + /* + * We don't support 0 length messages and so filter out + * 0 length transfers by using i2c_adapter_quirks. +@@ -106,24 +110,17 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, + + static int virtio_i2c_complete_reqs(struct virtqueue *vq, + struct virtio_i2c_req *reqs, +- struct i2c_msg *msgs, int num, +- bool timedout) ++ struct i2c_msg *msgs, int num) + { +- struct virtio_i2c_req *req; +- bool failed = timedout; +- unsigned int len; ++ bool failed = false; + int i, j = 0; + + for (i = 0; i < num; i++) { +- /* Detach the ith request from the vq */ +- req = virtqueue_get_buf(vq, &len); ++ struct virtio_i2c_req *req = &reqs[i]; + +- /* +- * Condition req == &reqs[i] should always meet since we have +- * total num requests in the vq. reqs[i] can never be NULL here. +- */ +- if (!failed && (WARN_ON(req != &reqs[i]) || +- req->in_hdr.status != VIRTIO_I2C_MSG_OK)) ++ wait_for_completion(&req->completion); ++ ++ if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) + failed = true; + + i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); +@@ -132,7 +129,7 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, + j++; + } + +- return timedout ? -ETIMEDOUT : j; ++ return j; + } + + static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, +@@ -141,7 +138,6 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + struct virtio_i2c *vi = i2c_get_adapdata(adap); + struct virtqueue *vq = vi->vq; + struct virtio_i2c_req *reqs; +- unsigned long time_left; + int count; + + reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL); +@@ -160,15 +156,9 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + * remote here to clear the virtqueue, so we can try another set of + * messages later on. + */ +- +- reinit_completion(&vi->completion); + virtqueue_kick(vq); + +- time_left = wait_for_completion_timeout(&vi->completion, adap->timeout); +- if (!time_left) +- dev_err(&adap->dev, "virtio i2c backend timeout.\n"); +- +- count = virtio_i2c_complete_reqs(vq, reqs, msgs, count, !time_left); ++ count = virtio_i2c_complete_reqs(vq, reqs, msgs, count); + + err_free: + kfree(reqs); +@@ -215,8 +205,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev) + vdev->priv = vi; + vi->vdev = vdev; + +- init_completion(&vi->completion); +- + ret = virtio_i2c_setup_vqs(vi); + if (ret) + return ret; +diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c +index 126d1393e548b..9ce20652d4942 100644 +--- a/drivers/i2c/busses/i2c-xlr.c ++++ b/drivers/i2c/busses/i2c-xlr.c +@@ -431,11 +431,15 @@ static int xlr_i2c_probe(struct platform_device *pdev) + i2c_set_adapdata(&priv->adap, priv); + ret = i2c_add_numbered_adapter(&priv->adap); + if (ret < 0) +- return ret; ++ goto err_unprepare_clk; + + platform_set_drvdata(pdev, priv); + dev_info(&priv->adap.dev, "Added I2C Bus.\n"); + return 0; ++ ++err_unprepare_clk: ++ clk_unprepare(clk); ++ return ret; + } + + static int xlr_i2c_remove(struct platform_device *pdev) +diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c +index 54964fbe3f033..cfbef70e8ba70 100644 +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -466,14 +466,12 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client) + static int i2c_device_probe(struct device *dev) + { + struct i2c_client *client = i2c_verify_client(dev); +- struct i2c_adapter *adap; + struct i2c_driver *driver; + int status; + + if (!client) + return 0; + +- adap = client->adapter; + client->irq = client->init_irq; + + if (!client->irq) { +@@ -539,14 +537,6 @@ static int i2c_device_probe(struct device *dev) + + dev_dbg(dev, "probe\n"); + +- if (adap->bus_regulator) { +- status = regulator_enable(adap->bus_regulator); +- if (status < 0) { +- dev_err(&adap->dev, "Failed to enable bus regulator\n"); +- goto err_clear_wakeup_irq; +- } +- } +- + status = of_clk_set_defaults(dev->of_node, false); + if (status < 0) + goto err_clear_wakeup_irq; +@@ -604,10 +594,8 @@ put_sync_adapter: + static void i2c_device_remove(struct device *dev) + { + struct i2c_client *client = to_i2c_client(dev); +- struct i2c_adapter *adap; + struct i2c_driver *driver; + +- adap = client->adapter; + driver = to_i2c_driver(dev->driver); + if (driver->remove) { + int status; +@@ -622,8 +610,6 @@ static void i2c_device_remove(struct device *dev) + devres_release_group(&client->dev, client->devres_group_id); + + dev_pm_domain_detach(&client->dev, true); +- if (!pm_runtime_status_suspended(&client->dev) && adap->bus_regulator) +- regulator_disable(adap->bus_regulator); + + dev_pm_clear_wake_irq(&client->dev); + device_init_wakeup(&client->dev, false); +@@ -633,86 +619,6 @@ static void i2c_device_remove(struct device *dev) + pm_runtime_put(&client->adapter->dev); + } + +-#ifdef CONFIG_PM_SLEEP +-static int i2c_resume_early(struct device *dev) +-{ +- struct i2c_client *client = i2c_verify_client(dev); +- int err; +- +- if (!client) +- return 0; +- +- if (pm_runtime_status_suspended(&client->dev) && +- client->adapter->bus_regulator) { +- err = regulator_enable(client->adapter->bus_regulator); +- if (err) +- return err; +- } +- +- return pm_generic_resume_early(&client->dev); +-} +- +-static int i2c_suspend_late(struct device *dev) +-{ +- struct i2c_client *client = i2c_verify_client(dev); +- int err; +- +- if (!client) +- return 0; +- +- err = pm_generic_suspend_late(&client->dev); +- if (err) +- return err; +- +- if (!pm_runtime_status_suspended(&client->dev) && +- client->adapter->bus_regulator) +- return regulator_disable(client->adapter->bus_regulator); +- +- return 0; +-} +-#endif +- +-#ifdef CONFIG_PM +-static int i2c_runtime_resume(struct device *dev) +-{ +- struct i2c_client *client = i2c_verify_client(dev); +- int err; +- +- if (!client) +- return 0; +- +- if (client->adapter->bus_regulator) { +- err = regulator_enable(client->adapter->bus_regulator); +- if (err) +- return err; +- } +- +- return pm_generic_runtime_resume(&client->dev); +-} +- +-static int i2c_runtime_suspend(struct device *dev) +-{ +- struct i2c_client *client = i2c_verify_client(dev); +- int err; +- +- if (!client) +- return 0; +- +- err = pm_generic_runtime_suspend(&client->dev); +- if (err) +- return err; +- +- if (client->adapter->bus_regulator) +- return regulator_disable(client->adapter->bus_regulator); +- return 0; +-} +-#endif +- +-static const struct dev_pm_ops i2c_device_pm = { +- SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early) +- SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL) +-}; +- + static void i2c_device_shutdown(struct device *dev) + { + struct i2c_client *client = i2c_verify_client(dev); +@@ -772,7 +678,6 @@ struct bus_type i2c_bus_type = { + .probe = i2c_device_probe, + .remove = i2c_device_remove, + .shutdown = i2c_device_shutdown, +- .pm = &i2c_device_pm, + }; + EXPORT_SYMBOL_GPL(i2c_bus_type); + +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index bce0e8bb78520..cf5d049342ead 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -535,6 +535,9 @@ static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned lo + sizeof(rdwr_arg))) + return -EFAULT; + ++ if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0) ++ return -EINVAL; ++ + if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) + return -EINVAL; + +diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c +index c3b4c677b4429..dfe18dcd008d4 100644 +--- a/drivers/i3c/master.c ++++ b/drivers/i3c/master.c +@@ -343,7 +343,8 @@ struct bus_type i3c_bus_type = { + static enum i3c_addr_slot_status + i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr) + { +- int status, bitpos = addr * 2; ++ unsigned long status; ++ int bitpos = addr * 2; + + if (addr > I2C_MAX_ADDR) + return I3C_ADDR_SLOT_RSVD; +diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c +index 03a368da51b95..51a8608203de7 100644 +--- a/drivers/i3c/master/dw-i3c-master.c ++++ b/drivers/i3c/master/dw-i3c-master.c +@@ -793,6 +793,10 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m) + return -ENOMEM; + + pos = dw_i3c_master_get_free_pos(master); ++ if (pos < 0) { ++ dw_i3c_master_free_xfer(xfer); ++ return pos; ++ } + cmd = &xfer->cmds[0]; + cmd->cmd_hi = 0x1; + cmd->cmd_lo = COMMAND_PORT_DEV_COUNT(master->maxdevs - pos) | +diff --git a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c +index 783e551a2c85a..97bb49ff5b53b 100644 +--- a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c +@@ -160,9 +160,7 @@ static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr) + unsigned int dat_idx; + u32 dat_w0; + +- for (dat_idx = find_first_bit(hci->DAT_data, hci->DAT_entries); +- dat_idx < hci->DAT_entries; +- dat_idx = find_next_bit(hci->DAT_data, hci->DAT_entries, dat_idx)) { ++ for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) { + dat_w0 = dat_w0_read(dat_idx); + if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr) + return dat_idx; +diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c +index e8693a42ad464..3af763b4a9737 100644 +--- a/drivers/iio/accel/bmc150-accel-core.c ++++ b/drivers/iio/accel/bmc150-accel-core.c +@@ -1782,11 +1782,14 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq, + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(dev, "Unable to register iio device\n"); +- goto err_trigger_unregister; ++ goto err_pm_cleanup; + } + + return 0; + ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(dev); ++ pm_runtime_disable(dev); + err_trigger_unregister: + bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); + err_buffer_cleanup: +diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c +index f41db9e0249a7..a2d29cabb3892 100644 +--- a/drivers/iio/accel/fxls8962af-core.c ++++ b/drivers/iio/accel/fxls8962af-core.c +@@ -154,12 +154,20 @@ struct fxls8962af_data { + u8 watermark; + }; + +-const struct regmap_config fxls8962af_regmap_conf = { ++const struct regmap_config fxls8962af_i2c_regmap_conf = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FXLS8962AF_MAX_REG, + }; +-EXPORT_SYMBOL_GPL(fxls8962af_regmap_conf); ++EXPORT_SYMBOL_GPL(fxls8962af_i2c_regmap_conf); ++ ++const struct regmap_config fxls8962af_spi_regmap_conf = { ++ .reg_bits = 8, ++ .pad_bits = 8, ++ .val_bits = 8, ++ .max_register = FXLS8962AF_MAX_REG, ++}; ++EXPORT_SYMBOL_GPL(fxls8962af_spi_regmap_conf); + + enum { + fxls8962af_idx_x, +diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c +index cfb004b204559..6bde9891effbf 100644 +--- a/drivers/iio/accel/fxls8962af-i2c.c ++++ b/drivers/iio/accel/fxls8962af-i2c.c +@@ -18,7 +18,7 @@ static int fxls8962af_probe(struct i2c_client *client) + { + struct regmap *regmap; + +- regmap = devm_regmap_init_i2c(client, &fxls8962af_regmap_conf); ++ regmap = devm_regmap_init_i2c(client, &fxls8962af_i2c_regmap_conf); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to initialize i2c regmap\n"); + return PTR_ERR(regmap); +diff --git a/drivers/iio/accel/fxls8962af-spi.c b/drivers/iio/accel/fxls8962af-spi.c +index 57108d3d480b6..6f4dff3238d3c 100644 +--- a/drivers/iio/accel/fxls8962af-spi.c ++++ b/drivers/iio/accel/fxls8962af-spi.c +@@ -18,7 +18,7 @@ static int fxls8962af_probe(struct spi_device *spi) + { + struct regmap *regmap; + +- regmap = devm_regmap_init_spi(spi, &fxls8962af_regmap_conf); ++ regmap = devm_regmap_init_spi(spi, &fxls8962af_spi_regmap_conf); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Failed to initialize spi regmap\n"); + return PTR_ERR(regmap); +diff --git a/drivers/iio/accel/fxls8962af.h b/drivers/iio/accel/fxls8962af.h +index b67572c3ef069..9cbe98c3ba9a2 100644 +--- a/drivers/iio/accel/fxls8962af.h ++++ b/drivers/iio/accel/fxls8962af.h +@@ -17,6 +17,7 @@ int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq); + int fxls8962af_core_remove(struct device *dev); + + extern const struct dev_pm_ops fxls8962af_pm_ops; +-extern const struct regmap_config fxls8962af_regmap_conf; ++extern const struct regmap_config fxls8962af_i2c_regmap_conf; ++extern const struct regmap_config fxls8962af_spi_regmap_conf; + + #endif /* _FXLS8962AF_H_ */ +diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c +index a51fdd3c9b5b5..ba6c8ca488b1a 100644 +--- a/drivers/iio/accel/kxcjk-1013.c ++++ b/drivers/iio/accel/kxcjk-1013.c +@@ -1589,14 +1589,16 @@ static int kxcjk1013_probe(struct i2c_client *client, + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); +- goto err_buffer_cleanup; ++ goto err_pm_cleanup; + } + + return 0; + ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(&client->dev); ++ pm_runtime_disable(&client->dev); + err_buffer_cleanup: +- if (data->dready_trig) +- iio_triggered_buffer_cleanup(indio_dev); ++ iio_triggered_buffer_cleanup(indio_dev); + err_trigger_unregister: + if (data->dready_trig) + iio_trigger_unregister(data->dready_trig); +@@ -1618,8 +1620,8 @@ static int kxcjk1013_remove(struct i2c_client *client) + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + ++ iio_triggered_buffer_cleanup(indio_dev); + if (data->dready_trig) { +- iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->dready_trig); + iio_trigger_unregister(data->motion_trig); + } +diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c +index bf7ed9e7d00f4..e56ecc075014e 100644 +--- a/drivers/iio/accel/kxsd9.c ++++ b/drivers/iio/accel/kxsd9.c +@@ -224,14 +224,14 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) + hw_values.chan, + sizeof(hw_values.chan)); + if (ret) { +- dev_err(st->dev, +- "error reading data\n"); +- return ret; ++ dev_err(st->dev, "error reading data: %d\n", ret); ++ goto out; + } + + iio_push_to_buffers_with_timestamp(indio_dev, + &hw_values, + iio_get_time_ns(indio_dev)); ++out: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c +index 715b8138fb715..09c7f10fefb6e 100644 +--- a/drivers/iio/accel/mma8452.c ++++ b/drivers/iio/accel/mma8452.c +@@ -1470,7 +1470,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev) + if (ret) + return ret; + +- indio_dev->trig = trig; ++ indio_dev->trig = iio_trigger_get(trig); + + return 0; + } +diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c +index 4c359fb054801..c53a3398b14c4 100644 +--- a/drivers/iio/accel/mma9551.c ++++ b/drivers/iio/accel/mma9551.c +@@ -495,11 +495,14 @@ static int mma9551_probe(struct i2c_client *client, + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); +- goto out_poweroff; ++ goto err_pm_cleanup; + } + + return 0; + ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(&client->dev); ++ pm_runtime_disable(&client->dev); + out_poweroff: + mma9551_set_device_state(client, false); + +diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c +index ba3ecb3b57dcd..1599b75724d4f 100644 +--- a/drivers/iio/accel/mma9553.c ++++ b/drivers/iio/accel/mma9553.c +@@ -1134,12 +1134,15 @@ static int mma9553_probe(struct i2c_client *client, + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); +- goto out_poweroff; ++ goto err_pm_cleanup; + } + + dev_dbg(&indio_dev->dev, "Registered device %s\n", name); + return 0; + ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(&client->dev); ++ pm_runtime_disable(&client->dev); + out_poweroff: + mma9551_set_device_state(client, false); + return ret; +diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c +index f711756e41e3d..cba57459e90ab 100644 +--- a/drivers/iio/accel/st_accel_i2c.c ++++ b/drivers/iio/accel/st_accel_i2c.c +@@ -193,10 +193,10 @@ static int st_accel_i2c_remove(struct i2c_client *client) + { + struct iio_dev *indio_dev = i2c_get_clientdata(client); + +- st_sensors_power_disable(indio_dev); +- + st_accel_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c +index bb45d9ff95b85..5167fae1ee8ec 100644 +--- a/drivers/iio/accel/st_accel_spi.c ++++ b/drivers/iio/accel/st_accel_spi.c +@@ -143,10 +143,10 @@ static int st_accel_spi_remove(struct spi_device *spi) + { + struct iio_dev *indio_dev = spi_get_drvdata(spi); + +- st_sensors_power_disable(indio_dev); +- + st_accel_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c +index e45c600fccc0b..18c154afbd7ac 100644 +--- a/drivers/iio/adc/ad7124.c ++++ b/drivers/iio/adc/ad7124.c +@@ -76,7 +76,7 @@ + #define AD7124_CONFIG_REF_SEL(x) FIELD_PREP(AD7124_CONFIG_REF_SEL_MSK, x) + #define AD7124_CONFIG_PGA_MSK GENMASK(2, 0) + #define AD7124_CONFIG_PGA(x) FIELD_PREP(AD7124_CONFIG_PGA_MSK, x) +-#define AD7124_CONFIG_IN_BUFF_MSK GENMASK(7, 6) ++#define AD7124_CONFIG_IN_BUFF_MSK GENMASK(6, 5) + #define AD7124_CONFIG_IN_BUFF(x) FIELD_PREP(AD7124_CONFIG_IN_BUFF_MSK, x) + + /* AD7124_FILTER_X */ +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index 2c5c8a3672b2d..aa42ba759fa1a 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -480,8 +480,8 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p) + iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan, + iio_get_time_ns(indio_dev)); + +- iio_trigger_notify_done(indio_dev->trig); + err_unlock: ++ iio_trigger_notify_done(indio_dev->trig); + mutex_unlock(&st->lock); + + return IRQ_HANDLED; +diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c +index ea5ca163d8796..c4de706012e51 100644 +--- a/drivers/iio/adc/at91-sama5d2_adc.c ++++ b/drivers/iio/adc/at91-sama5d2_adc.c +@@ -1377,7 +1377,8 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, + *val = st->conversion_value; + ret = at91_adc_adjust_val_osr(st, val); + if (chan->scan_type.sign == 's') +- *val = sign_extend32(*val, 11); ++ *val = sign_extend32(*val, ++ chan->scan_type.realbits - 1); + st->conversion_done = false; + } + +diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c +index 3e0c0233b4315..df99f1365c398 100644 +--- a/drivers/iio/adc/axp20x_adc.c ++++ b/drivers/iio/adc/axp20x_adc.c +@@ -251,19 +251,8 @@ static int axp22x_adc_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) + { + struct axp20x_adc_iio *info = iio_priv(indio_dev); +- int size; + +- /* +- * N.B.: Unlike the Chinese datasheets tell, the charging current is +- * stored on 12 bits, not 13 bits. Only discharging current is on 13 +- * bits. +- */ +- if (chan->type == IIO_CURRENT && chan->channel == AXP22X_BATT_DISCHRG_I) +- size = 13; +- else +- size = 12; +- +- *val = axp20x_read_variable_width(info->regmap, chan->address, size); ++ *val = axp20x_read_variable_width(info->regmap, chan->address, 12); + if (*val < 0) + return *val; + +@@ -386,9 +375,8 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val, + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CURRENT: +- *val = 0; +- *val2 = 500000; +- return IIO_VAL_INT_PLUS_MICRO; ++ *val = 1; ++ return IIO_VAL_INT; + + case IIO_TEMP: + *val = 100; +diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c +index 16407664182ce..97d162a3cba4e 100644 +--- a/drivers/iio/adc/dln2-adc.c ++++ b/drivers/iio/adc/dln2-adc.c +@@ -248,7 +248,6 @@ static int dln2_adc_set_chan_period(struct dln2_adc *dln2, + static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) + { + int ret, i; +- struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); + u16 conflict; + __le16 value; + int olen = sizeof(value); +@@ -257,13 +256,9 @@ static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) + .chan = channel, + }; + +- ret = iio_device_claim_direct_mode(indio_dev); +- if (ret < 0) +- return ret; +- + ret = dln2_adc_set_chan_enabled(dln2, channel, true); + if (ret < 0) +- goto release_direct; ++ return ret; + + ret = dln2_adc_set_port_enabled(dln2, true, &conflict); + if (ret < 0) { +@@ -300,8 +295,6 @@ disable_port: + dln2_adc_set_port_enabled(dln2, false, NULL); + disable_chan: + dln2_adc_set_chan_enabled(dln2, channel, false); +-release_direct: +- iio_device_release_direct_mode(indio_dev); + + return ret; + } +@@ -337,10 +330,16 @@ static int dln2_adc_read_raw(struct iio_dev *indio_dev, + + switch (mask) { + case IIO_CHAN_INFO_RAW: ++ ret = iio_device_claim_direct_mode(indio_dev); ++ if (ret < 0) ++ return ret; ++ + mutex_lock(&dln2->mutex); + ret = dln2_adc_read(dln2, chan->channel); + mutex_unlock(&dln2->mutex); + ++ iio_device_release_direct_mode(indio_dev); ++ + if (ret < 0) + return ret; + +@@ -656,7 +655,11 @@ static int dln2_adc_probe(struct platform_device *pdev) + return -ENOMEM; + } + iio_trigger_set_drvdata(dln2->trig, dln2); +- devm_iio_trigger_register(dev, dln2->trig); ++ ret = devm_iio_trigger_register(dev, dln2->trig); ++ if (ret) { ++ dev_err(dev, "failed to register trigger: %d\n", ret); ++ return ret; ++ } + iio_trigger_set_immutable(indio_dev, dln2->trig); + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, +diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c +index 42ea8bc7e7805..adc5ceaef8c93 100644 +--- a/drivers/iio/adc/men_z188_adc.c ++++ b/drivers/iio/adc/men_z188_adc.c +@@ -103,6 +103,7 @@ static int men_z188_probe(struct mcb_device *dev, + struct z188_adc *adc; + struct iio_dev *indio_dev; + struct resource *mem; ++ int ret; + + indio_dev = devm_iio_device_alloc(&dev->dev, sizeof(struct z188_adc)); + if (!indio_dev) +@@ -128,8 +129,14 @@ static int men_z188_probe(struct mcb_device *dev, + adc->mem = mem; + mcb_set_drvdata(dev, indio_dev); + +- return iio_device_register(indio_dev); ++ ret = iio_device_register(indio_dev); ++ if (ret) ++ goto err_unmap; ++ ++ return 0; + ++err_unmap: ++ iounmap(adc->base); + err: + mcb_release_mem(mem); + return -ENXIO; +diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c +index 5088de835bb15..e3e75413b49e7 100644 +--- a/drivers/iio/adc/stm32-adc.c ++++ b/drivers/iio/adc/stm32-adc.c +@@ -975,6 +975,7 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) + { + struct stm32_adc *adc = iio_priv(indio_dev); + ++ stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0); + stm32h7_adc_disable(indio_dev); + stm32h7_adc_enter_pwr_down(adc); + } +diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c +index 16fc608db36a5..bd48b073e7200 100644 +--- a/drivers/iio/adc/ti-adc081c.c ++++ b/drivers/iio/adc/ti-adc081c.c +@@ -19,6 +19,7 @@ + #include <linux/i2c.h> + #include <linux/module.h> + #include <linux/mod_devicetable.h> ++#include <linux/property.h> + + #include <linux/iio/iio.h> + #include <linux/iio/buffer.h> +@@ -156,13 +157,16 @@ static int adc081c_probe(struct i2c_client *client, + { + struct iio_dev *iio; + struct adc081c *adc; +- struct adcxx1c_model *model; ++ const struct adcxx1c_model *model; + int err; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -EOPNOTSUPP; + +- model = &adcxx1c_models[id->driver_data]; ++ if (dev_fwnode(&client->dev)) ++ model = device_get_match_data(&client->dev); ++ else ++ model = &adcxx1c_models[id->driver_data]; + + iio = devm_iio_device_alloc(&client->dev, sizeof(*adc)); + if (!iio) +@@ -210,10 +214,17 @@ static const struct i2c_device_id adc081c_id[] = { + }; + MODULE_DEVICE_TABLE(i2c, adc081c_id); + ++static const struct acpi_device_id adc081c_acpi_match[] = { ++ /* Used on some AAEON boards */ ++ { "ADC081C", (kernel_ulong_t)&adcxx1c_models[ADC081C] }, ++ { } ++}; ++MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match); ++ + static const struct of_device_id adc081c_of_match[] = { +- { .compatible = "ti,adc081c" }, +- { .compatible = "ti,adc101c" }, +- { .compatible = "ti,adc121c" }, ++ { .compatible = "ti,adc081c", .data = &adcxx1c_models[ADC081C] }, ++ { .compatible = "ti,adc101c", .data = &adcxx1c_models[ADC101C] }, ++ { .compatible = "ti,adc121c", .data = &adcxx1c_models[ADC121C] }, + { } + }; + MODULE_DEVICE_TABLE(of, adc081c_of_match); +@@ -222,6 +233,7 @@ static struct i2c_driver adc081c_driver = { + .driver = { + .name = "adc081c", + .of_match_table = adc081c_of_match, ++ .acpi_match_table = adc081c_acpi_match, + }, + .probe = adc081c_probe, + .id_table = adc081c_id, +diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c +index 170950d5dd499..e8fc4d01f30b6 100644 +--- a/drivers/iio/adc/ti-tsc2046.c ++++ b/drivers/iio/adc/ti-tsc2046.c +@@ -388,7 +388,7 @@ static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, + mutex_lock(&priv->slock); + + size = 0; +- for_each_set_bit(ch_idx, active_scan_mask, indio_dev->num_channels) { ++ for_each_set_bit(ch_idx, active_scan_mask, ARRAY_SIZE(priv->l)) { + size += tsc2046_adc_group_set_layout(priv, group, ch_idx); + tsc2046_adc_group_set_cmd(priv, group, ch_idx); + group++; +@@ -398,7 +398,7 @@ static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, + priv->xfer.len = size; + priv->time_per_scan_us = size * 8 * priv->time_per_bit_ns / NSEC_PER_USEC; + +- if (priv->scan_interval_us > priv->time_per_scan_us) ++ if (priv->scan_interval_us < priv->time_per_scan_us) + dev_warn(&priv->spi->dev, "The scan interval (%d) is less then calculated scan time (%d)\n", + priv->scan_interval_us, priv->time_per_scan_us); + +@@ -548,7 +548,7 @@ static int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) + * enabled. + */ + size = 0; +- for (ch_idx = 0; ch_idx < priv->dcfg->num_channels; ch_idx++) ++ for (ch_idx = 0; ch_idx < ARRAY_SIZE(priv->l); ch_idx++) + size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx); + + priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); +diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c +index 488ec69967d67..e50718422411d 100644 +--- a/drivers/iio/dac/ad5446.c ++++ b/drivers/iio/dac/ad5446.c +@@ -531,8 +531,15 @@ static int ad5622_write(struct ad5446_state *st, unsigned val) + { + struct i2c_client *client = to_i2c_client(st->dev); + __be16 data = cpu_to_be16(val); ++ int ret; ++ ++ ret = i2c_master_send(client, (char *)&data, sizeof(data)); ++ if (ret < 0) ++ return ret; ++ if (ret != sizeof(data)) ++ return -EIO; + +- return i2c_master_send(client, (char *)&data, sizeof(data)); ++ return 0; + } + + /* +diff --git a/drivers/iio/dac/ad5766.c b/drivers/iio/dac/ad5766.c +index 3104ec32dfaca..dafda84fdea35 100644 +--- a/drivers/iio/dac/ad5766.c ++++ b/drivers/iio/dac/ad5766.c +@@ -503,13 +503,13 @@ static int ad5766_get_output_range(struct ad5766_state *st) + int i, ret, min, max, tmp[2]; + + ret = device_property_read_u32_array(&st->spi->dev, +- "output-range-voltage", ++ "output-range-microvolts", + tmp, 2); + if (ret) + return ret; + +- min = tmp[0] / 1000; +- max = tmp[1] / 1000; ++ min = tmp[0] / 1000000; ++ max = tmp[1] / 1000000; + for (i = 0; i < ARRAY_SIZE(ad5766_span_tbl); i++) { + if (ad5766_span_tbl[i].min != min || + ad5766_span_tbl[i].max != max) +diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c +index 8107f7bbbe3c5..7e2fd32e993a6 100644 +--- a/drivers/iio/dac/ad5770r.c ++++ b/drivers/iio/dac/ad5770r.c +@@ -522,7 +522,7 @@ static int ad5770r_channel_config(struct ad5770r_state *st) + return -EINVAL; + + device_for_each_child_node(&st->spi->dev, child) { +- ret = fwnode_property_read_u32(child, "num", &num); ++ ret = fwnode_property_read_u32(child, "reg", &num); + if (ret) + goto err_child_out; + if (num >= AD5770R_MAX_CHANNELS) { +diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c +index 3e0734ddafe36..600e9725da788 100644 +--- a/drivers/iio/gyro/adxrs290.c ++++ b/drivers/iio/gyro/adxrs290.c +@@ -7,6 +7,7 @@ + */ + + #include <linux/bitfield.h> ++#include <linux/bitops.h> + #include <linux/delay.h> + #include <linux/device.h> + #include <linux/kernel.h> +@@ -124,7 +125,7 @@ static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int * + goto err_unlock; + } + +- *val = temp; ++ *val = sign_extend32(temp, 15); + + err_unlock: + mutex_unlock(&st->lock); +@@ -146,7 +147,7 @@ static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) + } + + /* extract lower 12 bits temperature reading */ +- *val = temp & 0x0FFF; ++ *val = sign_extend32(temp, 11); + + err_unlock: + mutex_unlock(&st->lock); +diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c +index 17b939a367ad0..81a6d09788bd7 100644 +--- a/drivers/iio/gyro/bmg160_core.c ++++ b/drivers/iio/gyro/bmg160_core.c +@@ -1188,11 +1188,14 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(dev, "unable to register iio device\n"); +- goto err_buffer_cleanup; ++ goto err_pm_cleanup; + } + + return 0; + ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(dev); ++ pm_runtime_disable(dev); + err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + err_trigger_unregister: +diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c +index 04dd6a7969ea7..4cfa0d4395605 100644 +--- a/drivers/iio/gyro/itg3200_buffer.c ++++ b/drivers/iio/gyro/itg3200_buffer.c +@@ -61,9 +61,9 @@ static irqreturn_t itg3200_trigger_handler(int irq, void *p) + + iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); + ++error_ret: + iio_trigger_notify_done(indio_dev->trig); + +-error_ret: + return IRQ_HANDLED; + } + +diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c +index 3ef86e16ee656..a8164fe48b857 100644 +--- a/drivers/iio/gyro/st_gyro_i2c.c ++++ b/drivers/iio/gyro/st_gyro_i2c.c +@@ -106,10 +106,10 @@ static int st_gyro_i2c_remove(struct i2c_client *client) + { + struct iio_dev *indio_dev = i2c_get_clientdata(client); + +- st_sensors_power_disable(indio_dev); +- + st_gyro_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c +index 41d835493347c..9d8916871b4bf 100644 +--- a/drivers/iio/gyro/st_gyro_spi.c ++++ b/drivers/iio/gyro/st_gyro_spi.c +@@ -110,10 +110,10 @@ static int st_gyro_spi_remove(struct spi_device *spi) + { + struct iio_dev *indio_dev = spi_get_drvdata(spi); + +- st_sensors_power_disable(indio_dev); +- + st_gyro_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index b9a06ca29beec..d4e692b187cda 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -430,6 +430,8 @@ int __adis_initial_startup(struct adis *adis) + if (ret) + return ret; + ++ adis_enable_irq(adis, false); ++ + if (!adis->data->prod_id_reg) + return 0; + +@@ -526,7 +528,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, + adis->current_page = 0; + } + +- return adis_enable_irq(adis, false); ++ return 0; + } + EXPORT_SYMBOL_GPL(adis_init); + +diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c +index ed129321a14da..f9b4540db1f43 100644 +--- a/drivers/iio/imu/adis16480.c ++++ b/drivers/iio/imu/adis16480.c +@@ -1403,6 +1403,7 @@ static int adis16480_probe(struct spi_device *spi) + { + const struct spi_device_id *id = spi_get_device_id(spi); + const struct adis_data *adis16480_data; ++ irq_handler_t trigger_handler = NULL; + struct iio_dev *indio_dev; + struct adis16480 *st; + int ret; +@@ -1474,8 +1475,12 @@ static int adis16480_probe(struct spi_device *spi) + st->clk_freq = st->chip_info->int_clk; + } + ++ /* Only use our trigger handler if burst mode is supported */ ++ if (adis16480_data->burst_len) ++ trigger_handler = adis16480_trigger_handler; ++ + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, +- adis16480_trigger_handler); ++ trigger_handler); + if (ret) + return ret; + +diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c +index 1dabfd615dabf..f89724481df93 100644 +--- a/drivers/iio/imu/kmx61.c ++++ b/drivers/iio/imu/kmx61.c +@@ -1385,7 +1385,7 @@ static int kmx61_probe(struct i2c_client *client, + ret = iio_device_register(data->acc_indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register acc iio device\n"); +- goto err_buffer_cleanup_mag; ++ goto err_pm_cleanup; + } + + ret = iio_device_register(data->mag_indio_dev); +@@ -1398,6 +1398,9 @@ static int kmx61_probe(struct i2c_client *client, + + err_iio_unregister_acc: + iio_device_unregister(data->acc_indio_dev); ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(&client->dev); ++ pm_runtime_disable(&client->dev); + err_buffer_cleanup_mag: + if (client->irq > 0) + iio_triggered_buffer_cleanup(data->mag_indio_dev); +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +index db45f1fc0b817..a778aceba3b10 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +@@ -1279,6 +1279,8 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr) + int err; + + switch (sensor->id) { ++ case ST_LSM6DSX_ID_GYRO: ++ break; + case ST_LSM6DSX_ID_EXT0: + case ST_LSM6DSX_ID_EXT1: + case ST_LSM6DSX_ID_EXT2: +@@ -1304,8 +1306,8 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr) + } + break; + } +- default: +- break; ++ default: /* should never occur */ ++ return -EINVAL; + } + + if (req_odr > 0) { +@@ -1370,8 +1372,12 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, + if (err < 0) + return err; + ++ /* ++ * we need to wait for sensor settling time before ++ * reading data in order to avoid corrupted samples ++ */ + delay = 1000000000 / sensor->odr; +- usleep_range(delay, 2 * delay); ++ usleep_range(3 * delay, 4 * delay); + + err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data)); + if (err < 0) +diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c +index a95cc2da56be6..c81dbd2f09727 100644 +--- a/drivers/iio/industrialio-buffer.c ++++ b/drivers/iio/industrialio-buffer.c +@@ -1312,6 +1312,11 @@ static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer, + iio_attr->buffer = buffer; + memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr)); + iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL); ++ if (!iio_attr->dev_attr.attr.name) { ++ kfree(iio_attr); ++ return NULL; ++ } ++ + sysfs_attr_init(&iio_attr->dev_attr.attr); + + list_add(&iio_attr->l, &buffer->buffer_attr_list); +@@ -1362,10 +1367,10 @@ static int iio_buffer_register_legacy_sysfs_groups(struct iio_dev *indio_dev, + + return 0; + +-error_free_buffer_attrs: +- kfree(iio_dev_opaque->legacy_buffer_group.attrs); + error_free_scan_el_attrs: + kfree(iio_dev_opaque->legacy_scan_el_group.attrs); ++error_free_buffer_attrs: ++ kfree(iio_dev_opaque->legacy_buffer_group.attrs); + + return ret; + } +@@ -1441,9 +1446,17 @@ static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg + } + + if (copy_to_user(ival, &fd, sizeof(fd))) { +- put_unused_fd(fd); +- ret = -EFAULT; +- goto error_free_ib; ++ /* ++ * "Leak" the fd, as there's not much we can do about this ++ * anyway. 'fd' might have been closed already, as ++ * anon_inode_getfd() called fd_install() on it, which made ++ * it reachable by userland. ++ * ++ * Instead of allowing a malicious user to play tricks with ++ * us, rely on the process exit path to do any necessary ++ * cleanup, as in releasing the file, if still needed. ++ */ ++ return -EFAULT; + } + + return 0; +@@ -1531,6 +1544,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, + sizeof(struct attribute *) * buffer_attrcount); + + buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs); ++ buffer->buffer_group.attrs = attr; + + for (i = 0; i < buffer_attrcount; i++) { + struct attribute *wrapped; +@@ -1538,7 +1552,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, + wrapped = iio_buffer_wrap_attr(buffer, attr[i]); + if (!wrapped) { + ret = -ENOMEM; +- goto error_free_scan_mask; ++ goto error_free_buffer_attrs; + } + attr[i] = wrapped; + } +@@ -1553,8 +1567,6 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, + goto error_free_buffer_attrs; + } + +- buffer->buffer_group.attrs = attr; +- + ret = iio_device_register_sysfs_group(indio_dev, &buffer->buffer_group); + if (ret) + goto error_free_buffer_attr_group_name; +@@ -1583,8 +1595,12 @@ error_cleanup_dynamic: + return ret; + } + +-static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer) ++static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer, ++ struct iio_dev *indio_dev, ++ int index) + { ++ if (index == 0) ++ iio_buffer_unregister_legacy_sysfs_groups(indio_dev); + bitmap_free(buffer->scan_mask); + kfree(buffer->buffer_group.name); + kfree(buffer->buffer_group.attrs); +@@ -1616,7 +1632,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) + buffer = iio_dev_opaque->attached_buffers[i]; + ret = __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev, i); + if (ret) { +- unwind_idx = i; ++ unwind_idx = i - 1; + goto error_unwind_sysfs_and_mask; + } + } +@@ -1638,7 +1654,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev) + error_unwind_sysfs_and_mask: + for (; unwind_idx >= 0; unwind_idx--) { + buffer = iio_dev_opaque->attached_buffers[unwind_idx]; +- __iio_buffer_free_sysfs_and_mask(buffer); ++ __iio_buffer_free_sysfs_and_mask(buffer, indio_dev, unwind_idx); + } + return ret; + } +@@ -1655,11 +1671,9 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) + iio_device_ioctl_handler_unregister(iio_dev_opaque->buffer_ioctl_handler); + kfree(iio_dev_opaque->buffer_ioctl_handler); + +- iio_buffer_unregister_legacy_sysfs_groups(indio_dev); +- + for (i = iio_dev_opaque->attached_buffers_cnt - 1; i >= 0; i--) { + buffer = iio_dev_opaque->attached_buffers[i]; +- __iio_buffer_free_sysfs_and_mask(buffer); ++ __iio_buffer_free_sysfs_and_mask(buffer, indio_dev, i); + } + } + +diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c +index 2dbb37e09b8cf..3e1e86d987cc2 100644 +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -1600,6 +1600,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) + kfree(iio_dev_opaque->chan_attr_group.attrs); + iio_dev_opaque->chan_attr_group.attrs = NULL; + kfree(iio_dev_opaque->groups); ++ iio_dev_opaque->groups = NULL; + } + + static void iio_dev_release(struct device *device) +@@ -1664,7 +1665,13 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) + kfree(iio_dev_opaque); + return NULL; + } +- dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id); ++ ++ if (dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id)) { ++ ida_simple_remove(&iio_ida, iio_dev_opaque->id); ++ kfree(iio_dev_opaque); ++ return NULL; ++ } ++ + INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); + INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); + +diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c +index b23caa2f2aa1f..f504ed351b3e2 100644 +--- a/drivers/iio/industrialio-trigger.c ++++ b/drivers/iio/industrialio-trigger.c +@@ -162,6 +162,39 @@ static struct iio_trigger *iio_trigger_acquire_by_name(const char *name) + return trig; + } + ++static void iio_reenable_work_fn(struct work_struct *work) ++{ ++ struct iio_trigger *trig = container_of(work, struct iio_trigger, ++ reenable_work); ++ ++ /* ++ * This 'might' occur after the trigger state is set to disabled - ++ * in that case the driver should skip reenabling. ++ */ ++ trig->ops->reenable(trig); ++} ++ ++/* ++ * In general, reenable callbacks may need to sleep and this path is ++ * not performance sensitive, so just queue up a work item ++ * to reneable the trigger for us. ++ * ++ * Races that can cause this. ++ * 1) A handler occurs entirely in interrupt context so the counter ++ * the final decrement is still in this interrupt. ++ * 2) The trigger has been removed, but one last interrupt gets through. ++ * ++ * For (1) we must call reenable, but not in atomic context. ++ * For (2) it should be safe to call reenanble, if drivers never blindly ++ * reenable after state is off. ++ */ ++static void iio_trigger_notify_done_atomic(struct iio_trigger *trig) ++{ ++ if (atomic_dec_and_test(&trig->use_count) && trig->ops && ++ trig->ops->reenable) ++ schedule_work(&trig->reenable_work); ++} ++ + void iio_trigger_poll(struct iio_trigger *trig) + { + int i; +@@ -173,7 +206,7 @@ void iio_trigger_poll(struct iio_trigger *trig) + if (trig->subirqs[i].enabled) + generic_handle_irq(trig->subirq_base + i); + else +- iio_trigger_notify_done(trig); ++ iio_trigger_notify_done_atomic(trig); + } + } + } +@@ -535,6 +568,7 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent, + trig->dev.type = &iio_trig_type; + trig->dev.bus = &iio_bus_type; + device_initialize(&trig->dev); ++ INIT_WORK(&trig->reenable_work, iio_reenable_work_fn); + + mutex_init(&trig->pool_lock); + trig->subirq_base = irq_alloc_descs(-1, 0, +@@ -556,7 +590,6 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent, + irq_modify_status(trig->subirq_base + i, + IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); + } +- get_device(&trig->dev); + + return trig; + +diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c +index 1830221da48d2..f0bd0ad34f222 100644 +--- a/drivers/iio/light/ltr501.c ++++ b/drivers/iio/light/ltr501.c +@@ -1273,7 +1273,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) + ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, + als_buf, sizeof(als_buf)); + if (ret < 0) +- return ret; ++ goto done; + if (test_bit(0, indio_dev->active_scan_mask)) + scan.channels[j++] = le16_to_cpu(als_buf[1]); + if (test_bit(1, indio_dev->active_scan_mask)) +diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c +index 07e91846307c7..fc63856ed54de 100644 +--- a/drivers/iio/light/stk3310.c ++++ b/drivers/iio/light/stk3310.c +@@ -546,9 +546,8 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) + mutex_lock(&data->lock); + ret = regmap_field_read(data->reg_flag_nf, &dir); + if (ret < 0) { +- dev_err(&data->client->dev, "register read failed\n"); +- mutex_unlock(&data->lock); +- return ret; ++ dev_err(&data->client->dev, "register read failed: %d\n", ret); ++ goto out; + } + event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, + IIO_EV_TYPE_THRESH, +@@ -560,6 +559,7 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) + ret = regmap_field_write(data->reg_flag_psint, 0); + if (ret < 0) + dev_err(&data->client->dev, "failed to reset interrupts\n"); ++out: + mutex_unlock(&data->lock); + + return IRQ_HANDLED; +diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c +index f96f531753495..3d4d21f979fab 100644 +--- a/drivers/iio/magnetometer/bmc150_magn.c ++++ b/drivers/iio/magnetometer/bmc150_magn.c +@@ -962,13 +962,14 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(dev, "unable to register iio device\n"); +- goto err_disable_runtime_pm; ++ goto err_pm_cleanup; + } + + dev_dbg(dev, "Registered device %s\n", name); + return 0; + +-err_disable_runtime_pm: ++err_pm_cleanup: ++ pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c +index 2dfe4ee99591b..fa78f0a3b53ea 100644 +--- a/drivers/iio/magnetometer/st_magn_i2c.c ++++ b/drivers/iio/magnetometer/st_magn_i2c.c +@@ -102,10 +102,10 @@ static int st_magn_i2c_remove(struct i2c_client *client) + { + struct iio_dev *indio_dev = i2c_get_clientdata(client); + +- st_sensors_power_disable(indio_dev); +- + st_magn_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c +index fba9787963952..ff43cbf61b056 100644 +--- a/drivers/iio/magnetometer/st_magn_spi.c ++++ b/drivers/iio/magnetometer/st_magn_spi.c +@@ -96,10 +96,10 @@ static int st_magn_spi_remove(struct spi_device *spi) + { + struct iio_dev *indio_dev = spi_get_drvdata(spi); + +- st_sensors_power_disable(indio_dev); +- + st_magn_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c +index 52fa98f24478d..6215de677017e 100644 +--- a/drivers/iio/pressure/st_pressure_i2c.c ++++ b/drivers/iio/pressure/st_pressure_i2c.c +@@ -119,10 +119,10 @@ static int st_press_i2c_remove(struct i2c_client *client) + { + struct iio_dev *indio_dev = i2c_get_clientdata(client); + +- st_sensors_power_disable(indio_dev); +- + st_press_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c +index ee393df54cee8..e220cf0b125f1 100644 +--- a/drivers/iio/pressure/st_pressure_spi.c ++++ b/drivers/iio/pressure/st_pressure_spi.c +@@ -102,10 +102,10 @@ static int st_press_spi_remove(struct spi_device *spi) + { + struct iio_dev *indio_dev = spi_get_drvdata(spi); + +- st_sensors_power_disable(indio_dev); +- + st_press_common_remove(indio_dev); + ++ st_sensors_power_disable(indio_dev); ++ + return 0; + } + +@@ -117,6 +117,10 @@ static const struct spi_device_id st_press_id_table[] = { + { LPS33HW_PRESS_DEV_NAME }, + { LPS35HW_PRESS_DEV_NAME }, + { LPS22HH_PRESS_DEV_NAME }, ++ { "lps001wp-press" }, ++ { "lps25h-press", }, ++ { "lps331ap-press" }, ++ { "lps22hb-press" }, + {}, + }; + MODULE_DEVICE_TABLE(spi, st_press_id_table); +diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c +index 33083877cd19d..4353b749ecef2 100644 +--- a/drivers/iio/trigger/stm32-timer-trigger.c ++++ b/drivers/iio/trigger/stm32-timer-trigger.c +@@ -912,6 +912,6 @@ static struct platform_driver stm32_timer_trigger_driver = { + }; + module_platform_driver(stm32_timer_trigger_driver); + +-MODULE_ALIAS("platform: stm32-timer-trigger"); ++MODULE_ALIAS("platform:stm32-timer-trigger"); + MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c +index c903b74f46a46..35f0d5e7533d6 100644 +--- a/drivers/infiniband/core/cm.c ++++ b/drivers/infiniband/core/cm.c +@@ -3322,7 +3322,7 @@ static int cm_lap_handler(struct cm_work *work) + ret = cm_init_av_by_path(param->alternate_path, NULL, &alt_av); + if (ret) { + rdma_destroy_ah_attr(&ah_attr); +- return -EINVAL; ++ goto deref; + } + + spin_lock_irq(&cm_id_priv->lock); +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 704ce595542c5..db7b5de3bc76b 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -67,8 +67,8 @@ static const char * const cma_events[] = { + [RDMA_CM_EVENT_TIMEWAIT_EXIT] = "timewait exit", + }; + +-static void cma_set_mgid(struct rdma_id_private *id_priv, struct sockaddr *addr, +- union ib_gid *mgid); ++static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, ++ enum ib_gid_type gid_type); + + const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event) + { +@@ -766,6 +766,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) + unsigned int p; + u16 pkey, index; + enum ib_port_state port_state; ++ int ret; + int i; + + cma_dev = NULL; +@@ -784,9 +785,14 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) + + if (ib_get_cached_port_state(cur_dev->device, p, &port_state)) + continue; +- for (i = 0; !rdma_query_gid(cur_dev->device, +- p, i, &gid); +- i++) { ++ ++ for (i = 0; i < cur_dev->device->port_data[p].immutable.gid_tbl_len; ++ ++i) { ++ ret = rdma_query_gid(cur_dev->device, p, i, ++ &gid); ++ if (ret) ++ continue; ++ + if (!memcmp(&gid, dgid, sizeof(gid))) { + cma_dev = cur_dev; + sgid = gid; +@@ -1838,17 +1844,19 @@ static void destroy_mc(struct rdma_id_private *id_priv, + if (dev_addr->bound_dev_if) + ndev = dev_get_by_index(dev_addr->net, + dev_addr->bound_dev_if); +- if (ndev) { ++ if (ndev && !send_only) { ++ enum ib_gid_type gid_type; + union ib_gid mgid; + +- cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, +- &mgid); +- +- if (!send_only) +- cma_igmp_send(ndev, &mgid, false); +- +- dev_put(ndev); ++ gid_type = id_priv->cma_dev->default_gid_type ++ [id_priv->id.port_num - ++ rdma_start_port( ++ id_priv->cma_dev->device)]; ++ cma_iboe_set_mgid((struct sockaddr *)&mc->addr, &mgid, ++ gid_type); ++ cma_igmp_send(ndev, &mgid, false); + } ++ dev_put(ndev); + + cancel_work_sync(&mc->iboe_join.work); + } +@@ -3360,22 +3368,30 @@ err: + static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + const struct sockaddr *dst_addr) + { +- if (!src_addr || !src_addr->sa_family) { +- src_addr = (struct sockaddr *) &id->route.addr.src_addr; +- src_addr->sa_family = dst_addr->sa_family; +- if (IS_ENABLED(CONFIG_IPV6) && +- dst_addr->sa_family == AF_INET6) { +- struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *) src_addr; +- struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *) dst_addr; +- src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; +- if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) +- id->route.addr.dev_addr.bound_dev_if = dst_addr6->sin6_scope_id; +- } else if (dst_addr->sa_family == AF_IB) { +- ((struct sockaddr_ib *) src_addr)->sib_pkey = +- ((struct sockaddr_ib *) dst_addr)->sib_pkey; +- } ++ struct sockaddr_storage zero_sock = {}; ++ ++ if (src_addr && src_addr->sa_family) ++ return rdma_bind_addr(id, src_addr); ++ ++ /* ++ * When the src_addr is not specified, automatically supply an any addr ++ */ ++ zero_sock.ss_family = dst_addr->sa_family; ++ if (IS_ENABLED(CONFIG_IPV6) && dst_addr->sa_family == AF_INET6) { ++ struct sockaddr_in6 *src_addr6 = ++ (struct sockaddr_in6 *)&zero_sock; ++ struct sockaddr_in6 *dst_addr6 = ++ (struct sockaddr_in6 *)dst_addr; ++ ++ src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; ++ if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) ++ id->route.addr.dev_addr.bound_dev_if = ++ dst_addr6->sin6_scope_id; ++ } else if (dst_addr->sa_family == AF_IB) { ++ ((struct sockaddr_ib *)&zero_sock)->sib_pkey = ++ ((struct sockaddr_ib *)dst_addr)->sib_pkey; + } +- return rdma_bind_addr(id, src_addr); ++ return rdma_bind_addr(id, (struct sockaddr *)&zero_sock); + } + + /* +@@ -4031,8 +4047,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, + + memset(&req, 0, sizeof req); + offset = cma_user_data_offset(id_priv); +- req.private_data_len = offset + conn_param->private_data_len; +- if (req.private_data_len < conn_param->private_data_len) ++ if (check_add_overflow(offset, conn_param->private_data_len, &req.private_data_len)) + return -EINVAL; + + if (req.private_data_len) { +@@ -4091,8 +4106,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, + + memset(&req, 0, sizeof req); + offset = cma_user_data_offset(id_priv); +- req.private_data_len = offset + conn_param->private_data_len; +- if (req.private_data_len < conn_param->private_data_len) ++ if (check_add_overflow(offset, conn_param->private_data_len, &req.private_data_len)) + return -EINVAL; + + if (req.private_data_len) { +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index f4814bb7f082f..6ab46648af909 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -2461,7 +2461,8 @@ int ib_find_gid(struct ib_device *device, union ib_gid *gid, + ++i) { + ret = rdma_query_gid(device, port, i, &tmp_gid); + if (ret) +- return ret; ++ continue; ++ + if (!memcmp(&tmp_gid, gid, sizeof *gid)) { + *port_num = port; + if (index) +diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c +index 6146c3c1cbe5c..8d709986b88c7 100644 +--- a/drivers/infiniband/core/sysfs.c ++++ b/drivers/infiniband/core/sysfs.c +@@ -757,7 +757,7 @@ static void ib_port_release(struct kobject *kobj) + if (port->hw_stats_data) + kfree(port->hw_stats_data->stats); + kfree(port->hw_stats_data); +- kfree(port); ++ kvfree(port); + } + + static void ib_port_gid_attr_release(struct kobject *kobj) +@@ -1189,7 +1189,7 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, + struct ib_port *p; + int ret; + +- p = kzalloc(struct_size(p, attrs_list, ++ p = kvzalloc(struct_size(p, attrs_list, + attr->gid_tbl_len + attr->pkey_tbl_len), + GFP_KERNEL); + if (!p) +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index 2b72c4fa95506..9d6ac9dff39a2 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -95,6 +95,7 @@ struct ucma_context { + u64 uid; + + struct list_head list; ++ struct list_head mc_list; + struct work_struct close_work; + }; + +@@ -105,6 +106,7 @@ struct ucma_multicast { + + u64 uid; + u8 join_state; ++ struct list_head list; + struct sockaddr_storage addr; + }; + +@@ -198,6 +200,7 @@ static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file) + + INIT_WORK(&ctx->close_work, ucma_close_id); + init_completion(&ctx->comp); ++ INIT_LIST_HEAD(&ctx->mc_list); + /* So list_del() will work if we don't do ucma_finish_ctx() */ + INIT_LIST_HEAD(&ctx->list); + ctx->file = file; +@@ -484,19 +487,19 @@ err1: + + static void ucma_cleanup_multicast(struct ucma_context *ctx) + { +- struct ucma_multicast *mc; +- unsigned long index; ++ struct ucma_multicast *mc, *tmp; + +- xa_for_each(&multicast_table, index, mc) { +- if (mc->ctx != ctx) +- continue; ++ xa_lock(&multicast_table); ++ list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) { ++ list_del(&mc->list); + /* + * At this point mc->ctx->ref is 0 so the mc cannot leave the + * lock on the reader and this is enough serialization + */ +- xa_erase(&multicast_table, index); ++ __xa_erase(&multicast_table, mc->id); + kfree(mc); + } ++ xa_unlock(&multicast_table); + } + + static void ucma_cleanup_mc_events(struct ucma_multicast *mc) +@@ -1469,12 +1472,16 @@ static ssize_t ucma_process_join(struct ucma_file *file, + mc->uid = cmd->uid; + memcpy(&mc->addr, addr, cmd->addr_size); + +- if (xa_alloc(&multicast_table, &mc->id, NULL, xa_limit_32b, ++ xa_lock(&multicast_table); ++ if (__xa_alloc(&multicast_table, &mc->id, NULL, xa_limit_32b, + GFP_KERNEL)) { + ret = -ENOMEM; + goto err_free_mc; + } + ++ list_add_tail(&mc->list, &ctx->mc_list); ++ xa_unlock(&multicast_table); ++ + mutex_lock(&ctx->mutex); + ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr, + join_state, mc); +@@ -1500,8 +1507,11 @@ err_leave_multicast: + mutex_unlock(&ctx->mutex); + ucma_cleanup_mc_events(mc); + err_xa_erase: +- xa_erase(&multicast_table, mc->id); ++ xa_lock(&multicast_table); ++ list_del(&mc->list); ++ __xa_erase(&multicast_table, mc->id); + err_free_mc: ++ xa_unlock(&multicast_table); + kfree(mc); + err_put_ctx: + ucma_put_ctx(ctx); +@@ -1569,15 +1579,17 @@ static ssize_t ucma_leave_multicast(struct ucma_file *file, + mc = ERR_PTR(-EINVAL); + else if (!refcount_inc_not_zero(&mc->ctx->ref)) + mc = ERR_PTR(-ENXIO); +- else +- __xa_erase(&multicast_table, mc->id); +- xa_unlock(&multicast_table); + + if (IS_ERR(mc)) { ++ xa_unlock(&multicast_table); + ret = PTR_ERR(mc); + goto out; + } + ++ list_del(&mc->list); ++ __xa_erase(&multicast_table, mc->id); ++ xa_unlock(&multicast_table); ++ + mutex_lock(&mc->ctx->mutex); + rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr); + mutex_unlock(&mc->ctx->mutex); +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 740e6b2efe0e7..d1345d76d9b12 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -837,11 +837,8 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) + new_mr->device = new_pd->device; + new_mr->pd = new_pd; + new_mr->type = IB_MR_TYPE_USER; +- new_mr->dm = NULL; +- new_mr->sig_attrs = NULL; + new_mr->uobject = uobj; + atomic_inc(&new_pd->usecnt); +- new_mr->iova = cmd.hca_va; + new_uobj->object = new_mr; + + rdma_restrack_new(&new_mr->res, RDMA_RESTRACK_MR); +diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c +index b8d715c68ca44..11a0806469162 100644 +--- a/drivers/infiniband/core/uverbs_marshall.c ++++ b/drivers/infiniband/core/uverbs_marshall.c +@@ -66,7 +66,7 @@ void ib_copy_ah_attr_to_user(struct ib_device *device, + struct rdma_ah_attr *src = ah_attr; + struct rdma_ah_attr conv_ah; + +- memset(&dst->grh.reserved, 0, sizeof(dst->grh.reserved)); ++ memset(&dst->grh, 0, sizeof(dst->grh)); + + if ((ah_attr->type == RDMA_AH_ATTR_TYPE_OPA) && + (rdma_ah_get_dlid(ah_attr) > be16_to_cpu(IB_LID_PERMISSIVE)) && +diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c +index 2f2c7646fce17..a02916a3a79ce 100644 +--- a/drivers/infiniband/core/uverbs_uapi.c ++++ b/drivers/infiniband/core/uverbs_uapi.c +@@ -447,6 +447,9 @@ static int uapi_finalize(struct uverbs_api *uapi) + uapi->num_write_ex = max_write_ex + 1; + data = kmalloc_array(uapi->num_write + uapi->num_write_ex, + sizeof(*uapi->write_methods), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ + for (i = 0; i != uapi->num_write + uapi->num_write_ex; i++) + data[i] = &uapi->notsupp_method; + uapi->write_methods = data; +diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c +index 89a2b21976d63..20a46d8731455 100644 +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -1232,6 +1232,9 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd, + INIT_LIST_HEAD(&qp->rdma_mrs); + INIT_LIST_HEAD(&qp->sig_mrs); + ++ qp->send_cq = attr->send_cq; ++ qp->recv_cq = attr->recv_cq; ++ + rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP); + WARN_ONCE(!udata && !caller, "Missing kernel QP owner"); + rdma_restrack_set_name(&qp->res, udata ? NULL : caller); +diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +index 408dfbcc47b5e..b7ec3a3926785 100644 +--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c ++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c +@@ -3354,8 +3354,11 @@ static void bnxt_re_process_res_ud_wc(struct bnxt_re_qp *qp, + struct ib_wc *wc, + struct bnxt_qplib_cqe *cqe) + { ++ struct bnxt_re_dev *rdev; ++ u16 vlan_id = 0; + u8 nw_type; + ++ rdev = qp->rdev; + wc->opcode = IB_WC_RECV; + wc->status = __rc_to_ib_wc_status(cqe->status); + +@@ -3367,9 +3370,12 @@ static void bnxt_re_process_res_ud_wc(struct bnxt_re_qp *qp, + memcpy(wc->smac, cqe->smac, ETH_ALEN); + wc->wc_flags |= IB_WC_WITH_SMAC; + if (cqe->flags & CQ_RES_UD_FLAGS_META_FORMAT_VLAN) { +- wc->vlan_id = (cqe->cfa_meta & 0xFFF); +- if (wc->vlan_id < 0x1000) +- wc->wc_flags |= IB_WC_WITH_VLAN; ++ vlan_id = (cqe->cfa_meta & 0xFFF); ++ } ++ /* Mark only if vlan_id is non zero */ ++ if (vlan_id && bnxt_re_check_if_vlan_valid(rdev, vlan_id)) { ++ wc->vlan_id = vlan_id; ++ wc->wc_flags |= IB_WC_WITH_VLAN; + } + nw_type = (cqe->flags & CQ_RES_UD_FLAGS_ROCE_IP_VER_MASK) >> + CQ_RES_UD_FLAGS_ROCE_IP_VER_SFT; +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +index d4d4959c2434c..bd153aa7e9ab3 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +@@ -707,12 +707,13 @@ int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, + int rc = 0; + + RCFW_CMD_PREP(req, QUERY_SRQ, cmd_flags); +- req.srq_cid = cpu_to_le32(srq->id); + + /* Configure the request */ + sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); + if (!sbuf) + return -ENOMEM; ++ req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; ++ req.srq_cid = cpu_to_le32(srq->id); + sb = sbuf->sb; + rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, + (void *)sbuf, 0); +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +index 5d384def5e5fe..d2d39126f1852 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +@@ -618,8 +618,6 @@ int bnxt_qplib_alloc_rcfw_channel(struct bnxt_qplib_res *res, + if (!cmdq->cmdq_bitmap) + goto fail; + +- cmdq->bmap_size = bmap_size; +- + /* Allocate one extra to hold the QP1 entries */ + rcfw->qp_tbl_size = qp_tbl_sz + 1; + rcfw->qp_tbl = kcalloc(rcfw->qp_tbl_size, sizeof(struct bnxt_qplib_qp_node), +@@ -667,8 +665,8 @@ void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) + iounmap(cmdq->cmdq_mbox.reg.bar_reg); + iounmap(creq->creq_db.reg.bar_reg); + +- indx = find_first_bit(cmdq->cmdq_bitmap, cmdq->bmap_size); +- if (indx != cmdq->bmap_size) ++ indx = find_first_bit(cmdq->cmdq_bitmap, rcfw->cmdq_depth); ++ if (indx != rcfw->cmdq_depth) + dev_err(&rcfw->pdev->dev, + "disabling RCFW with pending cmd-bit %lx\n", indx); + +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h +index 9474c00465821..0c6d0b70ce890 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h ++++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.h +@@ -152,7 +152,6 @@ struct bnxt_qplib_cmdq_ctx { + wait_queue_head_t waitq; + unsigned long flags; + unsigned long *cmdq_bitmap; +- u32 bmap_size; + u32 seq_num; + }; + +diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c +index d20b4ef2c853d..ffbd9a89981e7 100644 +--- a/drivers/infiniband/hw/cxgb4/qp.c ++++ b/drivers/infiniband/hw/cxgb4/qp.c +@@ -2460,6 +2460,7 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, + memset(attr, 0, sizeof(*attr)); + memset(init_attr, 0, sizeof(*init_attr)); + attr->qp_state = to_ib_qp_state(qhp->attr.state); ++ attr->cur_qp_state = to_ib_qp_state(qhp->attr.state); + init_attr->cap.max_send_wr = qhp->attr.sq_num_entries; + init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries; + init_attr->cap.max_send_sge = qhp->attr.sq_max_sges; +diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c +index 37273dc0c03ca..b0d587254fe66 100644 +--- a/drivers/infiniband/hw/hfi1/chip.c ++++ b/drivers/infiniband/hw/hfi1/chip.c +@@ -8414,6 +8414,8 @@ static void receive_interrupt_common(struct hfi1_ctxtdata *rcd) + */ + static void __hfi1_rcd_eoi_intr(struct hfi1_ctxtdata *rcd) + { ++ if (!rcd->rcvhdrq) ++ return; + clear_recv_intr(rcd); + if (check_packet_present(rcd)) + force_recv_intr(rcd); +diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c +index de411884386bf..385e6cff0d279 100644 +--- a/drivers/infiniband/hw/hfi1/driver.c ++++ b/drivers/infiniband/hw/hfi1/driver.c +@@ -1011,6 +1011,8 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread) + struct hfi1_packet packet; + int skip_pkt = 0; + ++ if (!rcd->rcvhdrq) ++ return RCV_PKT_OK; + /* Control context will always use the slow path interrupt handler */ + needset = (rcd->ctxt == HFI1_CTRL_CTXT) ? 0 : 1; + +diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c +index e3679d076eaaf..ec2a45c5cf575 100644 +--- a/drivers/infiniband/hw/hfi1/init.c ++++ b/drivers/infiniband/hw/hfi1/init.c +@@ -112,7 +112,6 @@ static int hfi1_create_kctxt(struct hfi1_devdata *dd, + rcd->fast_handler = get_dma_rtail_setting(rcd) ? + handle_receive_interrupt_dma_rtail : + handle_receive_interrupt_nodma_rtail; +- rcd->slow_handler = handle_receive_interrupt; + + hfi1_set_seq_cnt(rcd, 1); + +@@ -333,6 +332,8 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa, + rcd->numa_id = numa; + rcd->rcv_array_groups = dd->rcv_entries.ngroups; + rcd->rhf_rcv_function_map = normal_rhf_rcv_functions; ++ rcd->slow_handler = handle_receive_interrupt; ++ rcd->do_interrupt = rcd->slow_handler; + rcd->msix_intr = CCE_NUM_MSIX_VECTORS; + + mutex_init(&rcd->exp_mutex); +@@ -873,18 +874,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) + if (ret) + goto done; + +- /* allocate dummy tail memory for all receive contexts */ +- dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev, +- sizeof(u64), +- &dd->rcvhdrtail_dummy_dma, +- GFP_KERNEL); +- +- if (!dd->rcvhdrtail_dummy_kvaddr) { +- dd_dev_err(dd, "cannot allocate dummy tail memory\n"); +- ret = -ENOMEM; +- goto done; +- } +- + /* dd->rcd can be NULL if early initialization failed */ + for (i = 0; dd->rcd && i < dd->first_dyn_alloc_ctxt; ++i) { + /* +@@ -897,8 +886,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) + if (!rcd) + continue; + +- rcd->do_interrupt = &handle_receive_interrupt; +- + lastfail = hfi1_create_rcvhdrq(dd, rcd); + if (!lastfail) + lastfail = hfi1_setup_eagerbufs(rcd); +@@ -1119,7 +1106,7 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) + rcd->egrbufs.rcvtids = NULL; + + for (e = 0; e < rcd->egrbufs.alloced; e++) { +- if (rcd->egrbufs.buffers[e].dma) ++ if (rcd->egrbufs.buffers[e].addr) + dma_free_coherent(&dd->pcidev->dev, + rcd->egrbufs.buffers[e].len, + rcd->egrbufs.buffers[e].addr, +@@ -1200,6 +1187,11 @@ void hfi1_free_devdata(struct hfi1_devdata *dd) + dd->tx_opstats = NULL; + kfree(dd->comp_vect); + dd->comp_vect = NULL; ++ if (dd->rcvhdrtail_dummy_kvaddr) ++ dma_free_coherent(&dd->pcidev->dev, sizeof(u64), ++ (void *)dd->rcvhdrtail_dummy_kvaddr, ++ dd->rcvhdrtail_dummy_dma); ++ dd->rcvhdrtail_dummy_kvaddr = NULL; + sdma_clean(dd, dd->num_sdma); + rvt_dealloc_device(&dd->verbs_dev.rdi); + } +@@ -1297,6 +1289,15 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, + goto bail; + } + ++ /* allocate dummy tail memory for all receive contexts */ ++ dd->rcvhdrtail_dummy_kvaddr = ++ dma_alloc_coherent(&dd->pcidev->dev, sizeof(u64), ++ &dd->rcvhdrtail_dummy_dma, GFP_KERNEL); ++ if (!dd->rcvhdrtail_dummy_kvaddr) { ++ ret = -ENOMEM; ++ goto bail; ++ } ++ + atomic_set(&dd->ipoib_rsm_usr_num, 0); + return dd; + +@@ -1504,13 +1505,6 @@ static void cleanup_device_data(struct hfi1_devdata *dd) + + free_credit_return(dd); + +- if (dd->rcvhdrtail_dummy_kvaddr) { +- dma_free_coherent(&dd->pcidev->dev, sizeof(u64), +- (void *)dd->rcvhdrtail_dummy_kvaddr, +- dd->rcvhdrtail_dummy_dma); +- dd->rcvhdrtail_dummy_kvaddr = NULL; +- } +- + /* + * Free any resources still in use (usually just kernel contexts) + * at unload; we do for ctxtcnt, because that's what we allocate. +diff --git a/drivers/infiniband/hw/hfi1/ipoib_main.c b/drivers/infiniband/hw/hfi1/ipoib_main.c +index e594a961f513e..3e475814b6fa6 100644 +--- a/drivers/infiniband/hw/hfi1/ipoib_main.c ++++ b/drivers/infiniband/hw/hfi1/ipoib_main.c +@@ -22,26 +22,35 @@ static int hfi1_ipoib_dev_init(struct net_device *dev) + int ret; + + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); ++ if (!dev->tstats) ++ return -ENOMEM; + + ret = priv->netdev_ops->ndo_init(dev); + if (ret) +- return ret; ++ goto out_ret; + + ret = hfi1_netdev_add_data(priv->dd, + qpn_from_mac(priv->netdev->dev_addr), + dev); + if (ret < 0) { + priv->netdev_ops->ndo_uninit(dev); +- return ret; ++ goto out_ret; + } + + return 0; ++out_ret: ++ free_percpu(dev->tstats); ++ dev->tstats = NULL; ++ return ret; + } + + static void hfi1_ipoib_dev_uninit(struct net_device *dev) + { + struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev); + ++ free_percpu(dev->tstats); ++ dev->tstats = NULL; ++ + hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr)); + + priv->netdev_ops->ndo_uninit(dev); +@@ -166,12 +175,7 @@ static void hfi1_ipoib_netdev_dtor(struct net_device *dev) + hfi1_ipoib_rxq_deinit(priv->netdev); + + free_percpu(dev->tstats); +-} +- +-static void hfi1_ipoib_free_rdma_netdev(struct net_device *dev) +-{ +- hfi1_ipoib_netdev_dtor(dev); +- free_netdev(dev); ++ dev->tstats = NULL; + } + + static void hfi1_ipoib_set_id(struct net_device *dev, int id) +@@ -211,24 +215,23 @@ static int hfi1_ipoib_setup_rn(struct ib_device *device, + priv->port_num = port_num; + priv->netdev_ops = netdev->netdev_ops; + +- netdev->netdev_ops = &hfi1_ipoib_netdev_ops; +- + ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey); + + rc = hfi1_ipoib_txreq_init(priv); + if (rc) { + dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc); +- hfi1_ipoib_free_rdma_netdev(netdev); + return rc; + } + + rc = hfi1_ipoib_rxq_init(netdev); + if (rc) { + dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc); +- hfi1_ipoib_free_rdma_netdev(netdev); ++ hfi1_ipoib_txreq_deinit(priv); + return rc; + } + ++ netdev->netdev_ops = &hfi1_ipoib_netdev_ops; ++ + netdev->priv_destructor = hfi1_ipoib_netdev_dtor; + netdev->needs_free_netdev = true; + +diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c +index 2b6c24b7b5865..f07d328689d3d 100644 +--- a/drivers/infiniband/hw/hfi1/sdma.c ++++ b/drivers/infiniband/hw/hfi1/sdma.c +@@ -838,8 +838,8 @@ struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd, + if (current->nr_cpus_allowed != 1) + goto out; + +- cpu_id = smp_processor_id(); + rcu_read_lock(); ++ cpu_id = smp_processor_id(); + rht_node = rhashtable_lookup(dd->sdma_rht, &cpu_id, + sdma_rht_params); + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index d5f3faa1627a4..96fe73ba689c1 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -33,6 +33,7 @@ + #include <linux/acpi.h> + #include <linux/etherdevice.h> + #include <linux/interrupt.h> ++#include <linux/iopoll.h> + #include <linux/kernel.h> + #include <linux/types.h> + #include <net/addrconf.h> +@@ -1050,9 +1051,14 @@ static u32 hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, + unsigned long instance_stage, + unsigned long reset_stage) + { ++#define HW_RESET_TIMEOUT_US 1000000 ++#define HW_RESET_SLEEP_US 1000 ++ + struct hns_roce_v2_priv *priv = hr_dev->priv; + struct hnae3_handle *handle = priv->handle; + const struct hnae3_ae_ops *ops = handle->ae_algo->ops; ++ unsigned long val; ++ int ret; + + /* When hardware reset is detected, we should stop sending mailbox&cmq& + * doorbell to hardware. If now in .init_instance() function, we should +@@ -1064,7 +1070,11 @@ static u32 hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, + * again. + */ + hr_dev->dis_db = true; +- if (!ops->get_hw_reset_stat(handle)) ++ ++ ret = read_poll_timeout(ops->ae_dev_reset_cnt, val, ++ val > hr_dev->reset_cnt, HW_RESET_SLEEP_US, ++ HW_RESET_TIMEOUT_US, false, handle); ++ if (!ret) + hr_dev->is_reset = true; + + if (!hr_dev->is_reset || reset_stage == HNS_ROCE_STATE_RST_INIT || +@@ -1594,11 +1604,17 @@ static int hns_roce_config_global_param(struct hns_roce_dev *hr_dev) + { + struct hns_roce_cmq_desc desc; + struct hns_roce_cmq_req *req = (struct hns_roce_cmq_req *)desc.data; ++ u32 clock_cycles_of_1us; + + hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_CFG_GLOBAL_PARAM, + false); + +- hr_reg_write(req, CFG_GLOBAL_PARAM_1US_CYCLES, 0x3e8); ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) ++ clock_cycles_of_1us = HNS_ROCE_1NS_CFG; ++ else ++ clock_cycles_of_1us = HNS_ROCE_1US_CFG; ++ ++ hr_reg_write(req, CFG_GLOBAL_PARAM_1US_CYCLES, clock_cycles_of_1us); + hr_reg_write(req, CFG_GLOBAL_PARAM_UDP_PORT, ROCE_V2_UDP_DPORT); + + return hns_roce_cmq_send(hr_dev, &desc, 1); +@@ -3328,7 +3344,7 @@ static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev, + memset(cq_context, 0, sizeof(*cq_context)); + + hr_reg_write(cq_context, CQC_CQ_ST, V2_CQ_STATE_VALID); +- hr_reg_write(cq_context, CQC_ARM_ST, REG_NXT_CEQE); ++ hr_reg_write(cq_context, CQC_ARM_ST, NO_ARMED); + hr_reg_write(cq_context, CQC_SHIFT, ilog2(hr_cq->cq_depth)); + hr_reg_write(cq_context, CQC_CEQN, hr_cq->vector); + hr_reg_write(cq_context, CQC_CQN, hr_cq->cqn); +@@ -4399,8 +4415,8 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, + mtu = ib_mtu_enum_to_int(ib_mtu); + if (WARN_ON(mtu <= 0)) + return -EINVAL; +-#define MAX_LP_MSG_LEN 65536 +- /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 64KB */ ++#define MAX_LP_MSG_LEN 16384 ++ /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 16KB */ + lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu); + if (WARN_ON(lp_pktn_ini >= 0xF)) + return -EINVAL; +@@ -4802,6 +4818,30 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp, + return ret; + } + ++static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout) ++{ ++#define QP_ACK_TIMEOUT_MAX_HIP08 20 ++#define QP_ACK_TIMEOUT_OFFSET 10 ++#define QP_ACK_TIMEOUT_MAX 31 ++ ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { ++ if (*timeout > QP_ACK_TIMEOUT_MAX_HIP08) { ++ ibdev_warn(&hr_dev->ib_dev, ++ "Local ACK timeout shall be 0 to 20.\n"); ++ return false; ++ } ++ *timeout += QP_ACK_TIMEOUT_OFFSET; ++ } else if (hr_dev->pci_dev->revision > PCI_REVISION_ID_HIP08) { ++ if (*timeout > QP_ACK_TIMEOUT_MAX) { ++ ibdev_warn(&hr_dev->ib_dev, ++ "Local ACK timeout shall be 0 to 31.\n"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static int hns_roce_v2_set_opt_fields(struct ib_qp *ibqp, + const struct ib_qp_attr *attr, + int attr_mask, +@@ -4811,6 +4851,7 @@ static int hns_roce_v2_set_opt_fields(struct ib_qp *ibqp, + struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); + struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); + int ret = 0; ++ u8 timeout; + + if (attr_mask & IB_QP_AV) { + ret = hns_roce_v2_set_path(ibqp, attr, attr_mask, context, +@@ -4820,12 +4861,10 @@ static int hns_roce_v2_set_opt_fields(struct ib_qp *ibqp, + } + + if (attr_mask & IB_QP_TIMEOUT) { +- if (attr->timeout < 31) { +- hr_reg_write(context, QPC_AT, attr->timeout); ++ timeout = attr->timeout; ++ if (check_qp_timeout_cfg_range(hr_dev, &timeout)) { ++ hr_reg_write(context, QPC_AT, timeout); + hr_reg_clear(qpc_mask, QPC_AT); +- } else { +- ibdev_warn(&hr_dev->ib_dev, +- "Local ACK timeout shall be 0 to 30.\n"); + } + } + +@@ -4882,7 +4921,9 @@ static int hns_roce_v2_set_opt_fields(struct ib_qp *ibqp, + set_access_flags(hr_qp, context, qpc_mask, attr, attr_mask); + + if (attr_mask & IB_QP_MIN_RNR_TIMER) { +- hr_reg_write(context, QPC_MIN_RNR_TIME, attr->min_rnr_timer); ++ hr_reg_write(context, QPC_MIN_RNR_TIME, ++ hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 ? ++ HNS_ROCE_RNR_TIMER_10NS : attr->min_rnr_timer); + hr_reg_clear(qpc_mask, QPC_MIN_RNR_TIME); + } + +@@ -5499,6 +5540,16 @@ static int hns_roce_v2_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) + + hr_reg_write(cq_context, CQC_CQ_MAX_CNT, cq_count); + hr_reg_clear(cqc_mask, CQC_CQ_MAX_CNT); ++ ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { ++ if (cq_period * HNS_ROCE_CLOCK_ADJUST > USHRT_MAX) { ++ dev_info(hr_dev->dev, ++ "cq_period(%u) reached the upper limit, adjusted to 65.\n", ++ cq_period); ++ cq_period = HNS_ROCE_MAX_CQ_PERIOD; ++ } ++ cq_period *= HNS_ROCE_CLOCK_ADJUST; ++ } + hr_reg_write(cq_context, CQC_CQ_PERIOD, cq_period); + hr_reg_clear(cqc_mask, CQC_CQ_PERIOD); + +@@ -5894,6 +5945,15 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq, + hr_reg_write(eqc, EQC_EQ_PROD_INDX, HNS_ROCE_EQ_INIT_PROD_IDX); + hr_reg_write(eqc, EQC_EQ_MAX_CNT, eq->eq_max_cnt); + ++ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { ++ if (eq->eq_period * HNS_ROCE_CLOCK_ADJUST > USHRT_MAX) { ++ dev_info(hr_dev->dev, "eq_period(%u) reached the upper limit, adjusted to 65.\n", ++ eq->eq_period); ++ eq->eq_period = HNS_ROCE_MAX_EQ_PERIOD; ++ } ++ eq->eq_period *= HNS_ROCE_CLOCK_ADJUST; ++ } ++ + hr_reg_write(eqc, EQC_EQ_PERIOD, eq->eq_period); + hr_reg_write(eqc, EQC_EQE_REPORT_TIMER, HNS_ROCE_EQ_INIT_REPORT_TIMER); + hr_reg_write(eqc, EQC_EQE_BA_L, bt_ba >> 3); +@@ -6397,10 +6457,8 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) + if (!hr_dev) + return 0; + +- hr_dev->is_reset = true; + hr_dev->active = false; + hr_dev->dis_db = true; +- + hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN; + + return 0; +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index 4d904d5e82be4..35c61da7ba156 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -1444,6 +1444,14 @@ struct hns_roce_dip { + struct list_head node; /* all dips are on a list */ + }; + ++/* only for RNR timeout issue of HIP08 */ ++#define HNS_ROCE_CLOCK_ADJUST 1000 ++#define HNS_ROCE_MAX_CQ_PERIOD 65 ++#define HNS_ROCE_MAX_EQ_PERIOD 65 ++#define HNS_ROCE_RNR_TIMER_10NS 1 ++#define HNS_ROCE_1US_CFG 999 ++#define HNS_ROCE_1NS_CFG 0 ++ + #define HNS_ROCE_AEQ_DEFAULT_BURST_NUM 0x0 + #define HNS_ROCE_AEQ_DEFAULT_INTERVAL 0x0 + #define HNS_ROCE_CEQ_DEFAULT_BURST_NUM 0x0 +diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c +index 5d39bd08582af..1f2209de88122 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_main.c ++++ b/drivers/infiniband/hw/hns/hns_roce_main.c +@@ -269,6 +269,9 @@ static enum rdma_link_layer hns_roce_get_link_layer(struct ib_device *device, + static int hns_roce_query_pkey(struct ib_device *ib_dev, u32 port, u16 index, + u16 *pkey) + { ++ if (index > 0) ++ return -EINVAL; ++ + *pkey = PKEY_ID; + + return 0; +@@ -349,7 +352,7 @@ static int hns_roce_mmap(struct ib_ucontext *context, + return rdma_user_mmap_io(context, vma, + to_hr_ucontext(context)->uar.pfn, + PAGE_SIZE, +- pgprot_noncached(vma->vm_page_prot), ++ pgprot_device(vma->vm_page_prot), + NULL); + + /* vm_pgoff: 1 -- TPTR */ +diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c +index 6eee9deadd122..e64ef6903fb4f 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_srq.c ++++ b/drivers/infiniband/hw/hns/hns_roce_srq.c +@@ -259,7 +259,7 @@ static int alloc_srq_wrid(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) + + static void free_srq_wrid(struct hns_roce_srq *srq) + { +- kfree(srq->wrid); ++ kvfree(srq->wrid); + srq->wrid = NULL; + } + +diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c +index 7de525a5ccf8c..aa119441eb45c 100644 +--- a/drivers/infiniband/hw/irdma/hw.c ++++ b/drivers/infiniband/hw/irdma/hw.c +@@ -60,6 +60,8 @@ static void irdma_iwarp_ce_handler(struct irdma_sc_cq *iwcq) + { + struct irdma_cq *cq = iwcq->back_cq; + ++ if (!cq->user_mode) ++ cq->armed = false; + if (cq->ibcq.comp_handler) + cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); + } +@@ -146,6 +148,7 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, + qp->flush_code = FLUSH_PROT_ERR; + break; + case IRDMA_AE_AMP_BAD_QP: ++ case IRDMA_AE_WQE_UNEXPECTED_OPCODE: + qp->flush_code = FLUSH_LOC_QP_OP_ERR; + break; + case IRDMA_AE_AMP_BAD_STAG_KEY: +@@ -156,7 +159,6 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, + case IRDMA_AE_PRIV_OPERATION_DENIED: + case IRDMA_AE_IB_INVALID_REQUEST: + case IRDMA_AE_IB_REMOTE_ACCESS_ERROR: +- case IRDMA_AE_IB_REMOTE_OP_ERROR: + qp->flush_code = FLUSH_REM_ACCESS_ERR; + qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; + break; +@@ -184,6 +186,9 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, + case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS: + qp->flush_code = FLUSH_MW_BIND_ERR; + break; ++ case IRDMA_AE_IB_REMOTE_OP_ERROR: ++ qp->flush_code = FLUSH_REM_OP_ERR; ++ break; + default: + qp->flush_code = FLUSH_FATAL_ERR; + break; +diff --git a/drivers/infiniband/hw/irdma/main.h b/drivers/infiniband/hw/irdma/main.h +index b678fe712447e..8b215f3cee891 100644 +--- a/drivers/infiniband/hw/irdma/main.h ++++ b/drivers/infiniband/hw/irdma/main.h +@@ -541,6 +541,7 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, + void (*callback_fcn)(struct irdma_cqp_request *cqp_request), + void *cb_param); + void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request); ++bool irdma_cq_empty(struct irdma_cq *iwcq); + int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event, + void *ptr); + int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, +diff --git a/drivers/infiniband/hw/irdma/pble.c b/drivers/infiniband/hw/irdma/pble.c +index aeeb1c310965d..fed49da770f3b 100644 +--- a/drivers/infiniband/hw/irdma/pble.c ++++ b/drivers/infiniband/hw/irdma/pble.c +@@ -25,8 +25,7 @@ void irdma_destroy_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) + list_del(&chunk->list); + if (chunk->type == PBLE_SD_PAGED) + irdma_pble_free_paged_mem(chunk); +- if (chunk->bitmapbuf) +- kfree(chunk->bitmapmem.va); ++ bitmap_free(chunk->bitmapbuf); + kfree(chunk->chunkmem.va); + } + } +@@ -283,7 +282,6 @@ add_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) + "PBLE: next_fpm_addr = %llx chunk_size[%llu] = 0x%llx\n", + pble_rsrc->next_fpm_addr, chunk->size, chunk->size); + pble_rsrc->unallocated_pble -= (u32)(chunk->size >> 3); +- list_add(&chunk->list, &pble_rsrc->pinfo.clist); + sd_reg_val = (sd_entry_type == IRDMA_SD_TYPE_PAGED) ? + sd_entry->u.pd_table.pd_page_addr.pa : + sd_entry->u.bp.addr.pa; +@@ -295,12 +293,12 @@ add_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) + goto error; + } + ++ list_add(&chunk->list, &pble_rsrc->pinfo.clist); + sd_entry->valid = true; + return 0; + + error: +- if (chunk->bitmapbuf) +- kfree(chunk->bitmapmem.va); ++ bitmap_free(chunk->bitmapbuf); + kfree(chunk->chunkmem.va); + + return ret_code; +diff --git a/drivers/infiniband/hw/irdma/pble.h b/drivers/infiniband/hw/irdma/pble.h +index e1b3b8118a2ca..aa20827dcc9de 100644 +--- a/drivers/infiniband/hw/irdma/pble.h ++++ b/drivers/infiniband/hw/irdma/pble.h +@@ -78,7 +78,6 @@ struct irdma_chunk { + u32 pg_cnt; + enum irdma_alloc_type type; + struct irdma_sc_dev *dev; +- struct irdma_virt_mem bitmapmem; + struct irdma_virt_mem chunkmem; + }; + +diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c +index ac91ea5296db9..feebfe6bf31ad 100644 +--- a/drivers/infiniband/hw/irdma/utils.c ++++ b/drivers/infiniband/hw/irdma/utils.c +@@ -2284,15 +2284,10 @@ enum irdma_status_code irdma_prm_add_pble_mem(struct irdma_pble_prm *pprm, + + sizeofbitmap = (u64)pchunk->size >> pprm->pble_shift; + +- pchunk->bitmapmem.size = sizeofbitmap >> 3; +- pchunk->bitmapmem.va = kzalloc(pchunk->bitmapmem.size, GFP_KERNEL); +- +- if (!pchunk->bitmapmem.va) ++ pchunk->bitmapbuf = bitmap_zalloc(sizeofbitmap, GFP_KERNEL); ++ if (!pchunk->bitmapbuf) + return IRDMA_ERR_NO_MEMORY; + +- pchunk->bitmapbuf = pchunk->bitmapmem.va; +- bitmap_zero(pchunk->bitmapbuf, sizeofbitmap); +- + pchunk->sizeofbitmap = sizeofbitmap; + /* each pble is 8 bytes hence shift by 3 */ + pprm->total_pble_alloc += pchunk->size >> 3; +@@ -2536,3 +2531,18 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event) + ibevent.element.qp = &iwqp->ibqp; + iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context); + } ++ ++bool irdma_cq_empty(struct irdma_cq *iwcq) ++{ ++ struct irdma_cq_uk *ukcq; ++ u64 qword3; ++ __le64 *cqe; ++ u8 polarity; ++ ++ ukcq = &iwcq->sc_cq.cq_uk; ++ cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq); ++ get_64bit_val(cqe, 24, &qword3); ++ polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); ++ ++ return polarity != ukcq->polarity; ++} +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 102dc9342f2a2..8bbc4620a97a2 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3604,18 +3604,31 @@ static int irdma_req_notify_cq(struct ib_cq *ibcq, + struct irdma_cq *iwcq; + struct irdma_cq_uk *ukcq; + unsigned long flags; +- enum irdma_cmpl_notify cq_notify = IRDMA_CQ_COMPL_EVENT; ++ enum irdma_cmpl_notify cq_notify; ++ bool promo_event = false; ++ int ret = 0; + ++ cq_notify = notify_flags == IB_CQ_SOLICITED ? ++ IRDMA_CQ_COMPL_SOLICITED : IRDMA_CQ_COMPL_EVENT; + iwcq = to_iwcq(ibcq); + ukcq = &iwcq->sc_cq.cq_uk; +- if (notify_flags == IB_CQ_SOLICITED) +- cq_notify = IRDMA_CQ_COMPL_SOLICITED; + + spin_lock_irqsave(&iwcq->lock, flags); +- irdma_uk_cq_request_notification(ukcq, cq_notify); ++ /* Only promote to arm the CQ for any event if the last arm event was solicited. */ ++ if (iwcq->last_notify == IRDMA_CQ_COMPL_SOLICITED && notify_flags != IB_CQ_SOLICITED) ++ promo_event = true; ++ ++ if (!iwcq->armed || promo_event) { ++ iwcq->armed = true; ++ iwcq->last_notify = cq_notify; ++ irdma_uk_cq_request_notification(ukcq, cq_notify); ++ } ++ ++ if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && !irdma_cq_empty(iwcq)) ++ ret = 1; + spin_unlock_irqrestore(&iwcq->lock, flags); + +- return 0; ++ return ret; + } + + static int irdma_roce_port_immutable(struct ib_device *ibdev, u32 port_num, +diff --git a/drivers/infiniband/hw/irdma/verbs.h b/drivers/infiniband/hw/irdma/verbs.h +index 5c244cd321a3a..d0fdef8d09ead 100644 +--- a/drivers/infiniband/hw/irdma/verbs.h ++++ b/drivers/infiniband/hw/irdma/verbs.h +@@ -110,6 +110,8 @@ struct irdma_cq { + u16 cq_size; + u16 cq_num; + bool user_mode; ++ bool armed; ++ enum irdma_cmpl_notify last_notify; + u32 polled_cmpls; + u32 cq_mem_size; + struct irdma_dma_mem kmem; +diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c +index f367f4a4abffc..53d83212cda81 100644 +--- a/drivers/infiniband/hw/mlx4/main.c ++++ b/drivers/infiniband/hw/mlx4/main.c +@@ -2217,6 +2217,11 @@ static const struct ib_device_ops mlx4_ib_hw_stats_ops = { + .get_hw_stats = mlx4_ib_get_hw_stats, + }; + ++static const struct ib_device_ops mlx4_ib_hw_stats_ops1 = { ++ .alloc_hw_device_stats = mlx4_ib_alloc_hw_device_stats, ++ .get_hw_stats = mlx4_ib_get_hw_stats, ++}; ++ + static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev) + { + struct mlx4_ib_diag_counters *diag = ibdev->diag_counters; +@@ -2229,9 +2234,16 @@ static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev) + return 0; + + for (i = 0; i < MLX4_DIAG_COUNTERS_TYPES; i++) { +- /* i == 1 means we are building port counters */ +- if (i && !per_port) +- continue; ++ /* ++ * i == 1 means we are building port counters, set a different ++ * stats ops without port stats callback. ++ */ ++ if (i && !per_port) { ++ ib_set_device_ops(&ibdev->ib_dev, ++ &mlx4_ib_hw_stats_ops1); ++ ++ return 0; ++ } + + ret = __mlx4_ib_alloc_diag_counters(ibdev, &diag[i].name, + &diag[i].offset, +@@ -3237,7 +3249,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, + case MLX4_DEV_EVENT_PORT_MGMT_CHANGE: + ew = kmalloc(sizeof *ew, GFP_ATOMIC); + if (!ew) +- break; ++ return; + + INIT_WORK(&ew->work, handle_port_mgmt_change_event); + memcpy(&ew->ib_eqe, eqe, sizeof *eqe); +diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c +index 8662f462e2a5f..3a1a4ac9dd33d 100644 +--- a/drivers/infiniband/hw/mlx4/qp.c ++++ b/drivers/infiniband/hw/mlx4/qp.c +@@ -1099,8 +1099,10 @@ static int create_qp_common(struct ib_pd *pd, struct ib_qp_init_attr *init_attr, + if (dev->steering_support == + MLX4_STEERING_MODE_DEVICE_MANAGED) + qp->flags |= MLX4_IB_QP_NETIF; +- else ++ else { ++ err = -EINVAL; + goto err; ++ } + } + + err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp); +diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c +index dcb3653db72d7..f652d083ff20f 100644 +--- a/drivers/infiniband/hw/qedr/verbs.c ++++ b/drivers/infiniband/hw/qedr/verbs.c +@@ -1941,6 +1941,7 @@ static int qedr_create_user_qp(struct qedr_dev *dev, + /* db offset was calculated in copy_qp_uresp, now set in the user q */ + if (qedr_qp_has_sq(qp)) { + qp->usq.db_addr = ctx->dpi_addr + uresp.sq_db_offset; ++ qp->sq.max_wr = attrs->cap.max_send_wr; + rc = qedr_db_recovery_add(dev, qp->usq.db_addr, + &qp->usq.db_rec_data->db_data, + DB_REC_WIDTH_32B, +@@ -1951,6 +1952,7 @@ static int qedr_create_user_qp(struct qedr_dev *dev, + + if (qedr_qp_has_rq(qp)) { + qp->urq.db_addr = ctx->dpi_addr + uresp.rq_db_offset; ++ qp->rq.max_wr = attrs->cap.max_recv_wr; + rc = qedr_db_recovery_add(dev, qp->urq.db_addr, + &qp->urq.db_rec_data->db_data, + DB_REC_WIDTH_32B, +@@ -2744,15 +2746,18 @@ int qedr_query_qp(struct ib_qp *ibqp, + int rc = 0; + + memset(¶ms, 0, sizeof(params)); +- +- rc = dev->ops->rdma_query_qp(dev->rdma_ctx, qp->qed_qp, ¶ms); +- if (rc) +- goto err; +- + memset(qp_attr, 0, sizeof(*qp_attr)); + memset(qp_init_attr, 0, sizeof(*qp_init_attr)); + +- qp_attr->qp_state = qedr_get_ibqp_state(params.state); ++ if (qp->qp_type != IB_QPT_GSI) { ++ rc = dev->ops->rdma_query_qp(dev->rdma_ctx, qp->qed_qp, ¶ms); ++ if (rc) ++ goto err; ++ qp_attr->qp_state = qedr_get_ibqp_state(params.state); ++ } else { ++ qp_attr->qp_state = qedr_get_ibqp_state(QED_ROCE_QP_STATE_RTS); ++ } ++ + qp_attr->cur_qp_state = qedr_get_ibqp_state(params.state); + qp_attr->path_mtu = ib_mtu_int_to_enum(params.mtu); + qp_attr->path_mig_state = IB_MIG_MIGRATED; +diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c +index 0a3b28142c05b..41c272980f91c 100644 +--- a/drivers/infiniband/hw/qib/qib_sysfs.c ++++ b/drivers/infiniband/hw/qib/qib_sysfs.c +@@ -541,7 +541,7 @@ static struct attribute *port_diagc_attributes[] = { + }; + + static const struct attribute_group port_diagc_group = { +- .name = "linkcontrol", ++ .name = "diag_counters", + .attrs = port_diagc_attributes, + }; + +diff --git a/drivers/infiniband/hw/qib/qib_user_sdma.c b/drivers/infiniband/hw/qib/qib_user_sdma.c +index ac11943a5ddb0..bf2f30d67949d 100644 +--- a/drivers/infiniband/hw/qib/qib_user_sdma.c ++++ b/drivers/infiniband/hw/qib/qib_user_sdma.c +@@ -941,7 +941,7 @@ static int qib_user_sdma_queue_pkts(const struct qib_devdata *dd, + &addrlimit) || + addrlimit > type_max(typeof(pkt->addrlimit))) { + ret = -EINVAL; +- goto free_pbc; ++ goto free_pkt; + } + pkt->addrlimit = addrlimit; + +diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c +index 3305f2744bfaa..ae50b56e89132 100644 +--- a/drivers/infiniband/sw/rdmavt/qp.c ++++ b/drivers/infiniband/sw/rdmavt/qp.c +@@ -3073,6 +3073,8 @@ do_write: + case IB_WR_ATOMIC_FETCH_AND_ADD: + if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) + goto inv_err; ++ if (unlikely(wqe->atomic_wr.remote_addr & (sizeof(u64) - 1))) ++ goto inv_err; + if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64), + wqe->atomic_wr.remote_addr, + wqe->atomic_wr.rkey, +diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h +index f0c954575bdec..4fd73b51fabf2 100644 +--- a/drivers/infiniband/sw/rxe/rxe_loc.h ++++ b/drivers/infiniband/sw/rxe/rxe_loc.h +@@ -86,6 +86,7 @@ struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key, + int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length); + int advance_dma_data(struct rxe_dma_info *dma, unsigned int length); + int rxe_invalidate_mr(struct rxe_qp *qp, u32 rkey); ++int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe); + int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); + void rxe_mr_cleanup(struct rxe_pool_entry *arg); + +diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c +index 5890a82462161..bedcf15aaea75 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mr.c ++++ b/drivers/infiniband/sw/rxe/rxe_mr.c +@@ -48,8 +48,14 @@ static void rxe_mr_init(int access, struct rxe_mr *mr) + u32 lkey = mr->pelem.index << 8 | rxe_get_next_key(-1); + u32 rkey = (access & IB_ACCESS_REMOTE) ? lkey : 0; + +- mr->ibmr.lkey = lkey; +- mr->ibmr.rkey = rkey; ++ /* set ibmr->l/rkey and also copy into private l/rkey ++ * for user MRs these will always be the same ++ * for cases where caller 'owns' the key portion ++ * they may be different until REG_MR WQE is executed. ++ */ ++ mr->lkey = mr->ibmr.lkey = lkey; ++ mr->rkey = mr->ibmr.rkey = rkey; ++ + mr->state = RXE_MR_STATE_INVALID; + mr->type = RXE_MR_TYPE_NONE; + mr->map_shift = ilog2(RXE_BUF_PER_MAP); +@@ -191,10 +197,8 @@ int rxe_mr_init_fast(struct rxe_pd *pd, int max_pages, struct rxe_mr *mr) + { + int err; + +- rxe_mr_init(0, mr); +- +- /* In fastreg, we also set the rkey */ +- mr->ibmr.rkey = mr->ibmr.lkey; ++ /* always allow remote access for FMRs */ ++ rxe_mr_init(IB_ACCESS_REMOTE, mr); + + err = rxe_mr_alloc(mr, max_pages); + if (err) +@@ -507,8 +511,8 @@ struct rxe_mr *lookup_mr(struct rxe_pd *pd, int access, u32 key, + if (!mr) + return NULL; + +- if (unlikely((type == RXE_LOOKUP_LOCAL && mr_lkey(mr) != key) || +- (type == RXE_LOOKUP_REMOTE && mr_rkey(mr) != key) || ++ if (unlikely((type == RXE_LOOKUP_LOCAL && mr->lkey != key) || ++ (type == RXE_LOOKUP_REMOTE && mr->rkey != key) || + mr_pd(mr) != pd || (access && !(access & mr->access)) || + mr->state != RXE_MR_STATE_VALID)) { + rxe_drop_ref(mr); +@@ -531,9 +535,9 @@ int rxe_invalidate_mr(struct rxe_qp *qp, u32 rkey) + goto err; + } + +- if (rkey != mr->ibmr.rkey) { +- pr_err("%s: rkey (%#x) doesn't match mr->ibmr.rkey (%#x)\n", +- __func__, rkey, mr->ibmr.rkey); ++ if (rkey != mr->rkey) { ++ pr_err("%s: rkey (%#x) doesn't match mr->rkey (%#x)\n", ++ __func__, rkey, mr->rkey); + ret = -EINVAL; + goto err_drop_ref; + } +@@ -554,6 +558,49 @@ err: + return ret; + } + ++/* user can (re)register fast MR by executing a REG_MR WQE. ++ * user is expected to hold a reference on the ib mr until the ++ * WQE completes. ++ * Once a fast MR is created this is the only way to change the ++ * private keys. It is the responsibility of the user to maintain ++ * the ib mr keys in sync with rxe mr keys. ++ */ ++int rxe_reg_fast_mr(struct rxe_qp *qp, struct rxe_send_wqe *wqe) ++{ ++ struct rxe_mr *mr = to_rmr(wqe->wr.wr.reg.mr); ++ u32 key = wqe->wr.wr.reg.key; ++ u32 access = wqe->wr.wr.reg.access; ++ ++ /* user can only register MR in free state */ ++ if (unlikely(mr->state != RXE_MR_STATE_FREE)) { ++ pr_warn("%s: mr->lkey = 0x%x not free\n", ++ __func__, mr->lkey); ++ return -EINVAL; ++ } ++ ++ /* user can only register mr with qp in same protection domain */ ++ if (unlikely(qp->ibqp.pd != mr->ibmr.pd)) { ++ pr_warn("%s: qp->pd and mr->pd don't match\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ /* user is only allowed to change key portion of l/rkey */ ++ if (unlikely((mr->lkey & ~0xff) != (key & ~0xff))) { ++ pr_warn("%s: key = 0x%x has wrong index mr->lkey = 0x%x\n", ++ __func__, key, mr->lkey); ++ return -EINVAL; ++ } ++ ++ mr->access = access; ++ mr->lkey = key; ++ mr->rkey = (access & IB_ACCESS_REMOTE) ? key : 0; ++ mr->iova = wqe->wr.wr.reg.mr->iova; ++ mr->state = RXE_MR_STATE_VALID; ++ ++ return 0; ++} ++ + int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) + { + struct rxe_mr *mr = to_rmr(ibmr); +diff --git a/drivers/infiniband/sw/rxe/rxe_mw.c b/drivers/infiniband/sw/rxe/rxe_mw.c +index 5ba77df7598ed..a5e2ea7d80f02 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mw.c ++++ b/drivers/infiniband/sw/rxe/rxe_mw.c +@@ -21,7 +21,7 @@ int rxe_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata) + } + + rxe_add_index(mw); +- ibmw->rkey = (mw->pelem.index << 8) | rxe_get_next_key(-1); ++ mw->rkey = ibmw->rkey = (mw->pelem.index << 8) | rxe_get_next_key(-1); + mw->state = (mw->ibmw.type == IB_MW_TYPE_2) ? + RXE_MW_STATE_FREE : RXE_MW_STATE_VALID; + spin_lock_init(&mw->lock); +@@ -71,6 +71,8 @@ int rxe_dealloc_mw(struct ib_mw *ibmw) + static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + struct rxe_mw *mw, struct rxe_mr *mr) + { ++ u32 key = wqe->wr.wr.mw.rkey & 0xff; ++ + if (mw->ibmw.type == IB_MW_TYPE_1) { + if (unlikely(mw->state != RXE_MW_STATE_VALID)) { + pr_err_once( +@@ -108,7 +110,7 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + } + } + +- if (unlikely((wqe->wr.wr.mw.rkey & 0xff) == (mw->ibmw.rkey & 0xff))) { ++ if (unlikely(key == (mw->rkey & 0xff))) { + pr_err_once("attempt to bind MW with same key\n"); + return -EINVAL; + } +@@ -161,13 +163,9 @@ static int rxe_check_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + static void rxe_do_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + struct rxe_mw *mw, struct rxe_mr *mr) + { +- u32 rkey; +- u32 new_rkey; +- +- rkey = mw->ibmw.rkey; +- new_rkey = (rkey & 0xffffff00) | (wqe->wr.wr.mw.rkey & 0x000000ff); ++ u32 key = wqe->wr.wr.mw.rkey & 0xff; + +- mw->ibmw.rkey = new_rkey; ++ mw->rkey = (mw->rkey & ~0xff) | key; + mw->access = wqe->wr.wr.mw.access; + mw->state = RXE_MW_STATE_VALID; + mw->addr = wqe->wr.wr.mw.addr; +@@ -197,29 +195,29 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe) + struct rxe_mw *mw; + struct rxe_mr *mr; + struct rxe_dev *rxe = to_rdev(qp->ibqp.device); ++ u32 mw_rkey = wqe->wr.wr.mw.mw_rkey; ++ u32 mr_lkey = wqe->wr.wr.mw.mr_lkey; + unsigned long flags; + +- mw = rxe_pool_get_index(&rxe->mw_pool, +- wqe->wr.wr.mw.mw_rkey >> 8); ++ mw = rxe_pool_get_index(&rxe->mw_pool, mw_rkey >> 8); + if (unlikely(!mw)) { + ret = -EINVAL; + goto err; + } + +- if (unlikely(mw->ibmw.rkey != wqe->wr.wr.mw.mw_rkey)) { ++ if (unlikely(mw->rkey != mw_rkey)) { + ret = -EINVAL; + goto err_drop_mw; + } + + if (likely(wqe->wr.wr.mw.length)) { +- mr = rxe_pool_get_index(&rxe->mr_pool, +- wqe->wr.wr.mw.mr_lkey >> 8); ++ mr = rxe_pool_get_index(&rxe->mr_pool, mr_lkey >> 8); + if (unlikely(!mr)) { + ret = -EINVAL; + goto err_drop_mw; + } + +- if (unlikely(mr->ibmr.lkey != wqe->wr.wr.mw.mr_lkey)) { ++ if (unlikely(mr->lkey != mr_lkey)) { + ret = -EINVAL; + goto err_drop_mr; + } +@@ -292,7 +290,7 @@ int rxe_invalidate_mw(struct rxe_qp *qp, u32 rkey) + goto err; + } + +- if (rkey != mw->ibmw.rkey) { ++ if (rkey != mw->rkey) { + ret = -EINVAL; + goto err_drop_ref; + } +@@ -323,7 +321,7 @@ struct rxe_mw *rxe_lookup_mw(struct rxe_qp *qp, int access, u32 rkey) + if (!mw) + return NULL; + +- if (unlikely((rxe_mw_rkey(mw) != rkey) || rxe_mw_pd(mw) != pd || ++ if (unlikely((mw->rkey != rkey) || rxe_mw_pd(mw) != pd || + (mw->ibmw.type == IB_MW_TYPE_2 && mw->qp != qp) || + (mw->length == 0) || + (access && !(access & mw->access)) || +diff --git a/drivers/infiniband/sw/rxe/rxe_opcode.c b/drivers/infiniband/sw/rxe/rxe_opcode.c +index 3ef5a10a6efd8..47ebaac8f4754 100644 +--- a/drivers/infiniband/sw/rxe/rxe_opcode.c ++++ b/drivers/infiniband/sw/rxe/rxe_opcode.c +@@ -117,7 +117,7 @@ struct rxe_opcode_info rxe_opcode[RXE_NUM_OPCODE] = { + } + }, + [IB_OPCODE_RC_SEND_MIDDLE] = { +- .name = "IB_OPCODE_RC_SEND_MIDDLE]", ++ .name = "IB_OPCODE_RC_SEND_MIDDLE", + .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_SEND_MASK + | RXE_MIDDLE_MASK, + .length = RXE_BTH_BYTES, +diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h +index 742e6ec93686c..b5a70cbe94aac 100644 +--- a/drivers/infiniband/sw/rxe/rxe_param.h ++++ b/drivers/infiniband/sw/rxe/rxe_param.h +@@ -113,7 +113,7 @@ enum rxe_device_param { + /* default/initial rxe port parameters */ + enum rxe_port_param { + RXE_PORT_GID_TBL_LEN = 1024, +- RXE_PORT_PORT_CAP_FLAGS = RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP, ++ RXE_PORT_PORT_CAP_FLAGS = IB_PORT_CM_SUP, + RXE_PORT_MAX_MSG_SZ = 0x800000, + RXE_PORT_BAD_PKEY_CNTR = 0, + RXE_PORT_QKEY_VIOL_CNTR = 0, +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index 1ab6af7ddb254..ed326d82725cd 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -367,6 +367,7 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd, + + err2: + rxe_queue_cleanup(qp->sq.queue); ++ qp->sq.queue = NULL; + err1: + qp->pd = NULL; + qp->rcq = NULL; +diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c +index 3894197a82f62..fc996fd31e589 100644 +--- a/drivers/infiniband/sw/rxe/rxe_req.c ++++ b/drivers/infiniband/sw/rxe/rxe_req.c +@@ -572,7 +572,6 @@ static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe, + static int rxe_do_local_ops(struct rxe_qp *qp, struct rxe_send_wqe *wqe) + { + u8 opcode = wqe->wr.opcode; +- struct rxe_mr *mr; + u32 rkey; + int ret; + +@@ -590,14 +589,11 @@ static int rxe_do_local_ops(struct rxe_qp *qp, struct rxe_send_wqe *wqe) + } + break; + case IB_WR_REG_MR: +- mr = to_rmr(wqe->wr.wr.reg.mr); +- rxe_add_ref(mr); +- mr->state = RXE_MR_STATE_VALID; +- mr->access = wqe->wr.wr.reg.access; +- mr->ibmr.lkey = wqe->wr.wr.reg.key; +- mr->ibmr.rkey = wqe->wr.wr.reg.key; +- mr->iova = wqe->wr.wr.reg.mr->iova; +- rxe_drop_ref(mr); ++ ret = rxe_reg_fast_mr(qp, wqe); ++ if (unlikely(ret)) { ++ wqe->status = IB_WC_LOC_QP_OP_ERR; ++ return ret; ++ } + break; + case IB_WR_BIND_MW: + ret = rxe_bind_mw(qp, wqe); +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h +index ac2a2148027f4..d90b1d77de347 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.h ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.h +@@ -313,6 +313,8 @@ struct rxe_mr { + + struct ib_umem *umem; + ++ u32 lkey; ++ u32 rkey; + enum rxe_mr_state state; + enum rxe_mr_type type; + u64 va; +@@ -350,6 +352,7 @@ struct rxe_mw { + enum rxe_mw_state state; + struct rxe_qp *qp; /* Type 2 only */ + struct rxe_mr *mr; ++ u32 rkey; + int access; + u64 addr; + u64 length; +@@ -474,26 +477,11 @@ static inline struct rxe_pd *mr_pd(struct rxe_mr *mr) + return to_rpd(mr->ibmr.pd); + } + +-static inline u32 mr_lkey(struct rxe_mr *mr) +-{ +- return mr->ibmr.lkey; +-} +- +-static inline u32 mr_rkey(struct rxe_mr *mr) +-{ +- return mr->ibmr.rkey; +-} +- + static inline struct rxe_pd *rxe_mw_pd(struct rxe_mw *mw) + { + return to_rpd(mw->ibmw.pd); + } + +-static inline u32 rxe_mw_rkey(struct rxe_mw *mw) +-{ +- return mw->ibmw.rkey; +-} +- + int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name); + + void rxe_mc_cleanup(struct rxe_pool_entry *arg); +diff --git a/drivers/infiniband/sw/siw/siw.h b/drivers/infiniband/sw/siw/siw.h +index 368959ae9a8cc..df03d84c6868a 100644 +--- a/drivers/infiniband/sw/siw/siw.h ++++ b/drivers/infiniband/sw/siw/siw.h +@@ -644,14 +644,9 @@ static inline struct siw_sqe *orq_get_current(struct siw_qp *qp) + return &qp->orq[qp->orq_get % qp->attrs.orq_size]; + } + +-static inline struct siw_sqe *orq_get_tail(struct siw_qp *qp) +-{ +- return &qp->orq[qp->orq_put % qp->attrs.orq_size]; +-} +- + static inline struct siw_sqe *orq_get_free(struct siw_qp *qp) + { +- struct siw_sqe *orq_e = orq_get_tail(qp); ++ struct siw_sqe *orq_e = &qp->orq[qp->orq_put % qp->attrs.orq_size]; + + if (READ_ONCE(orq_e->flags) == 0) + return orq_e; +diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c +index 60116f20653c7..875ea6f1b04a2 100644 +--- a/drivers/infiniband/sw/siw/siw_qp_rx.c ++++ b/drivers/infiniband/sw/siw/siw_qp_rx.c +@@ -1153,11 +1153,12 @@ static int siw_check_tx_fence(struct siw_qp *qp) + + spin_lock_irqsave(&qp->orq_lock, flags); + +- rreq = orq_get_current(qp); +- + /* free current orq entry */ ++ rreq = orq_get_current(qp); + WRITE_ONCE(rreq->flags, 0); + ++ qp->orq_get++; ++ + if (qp->tx_ctx.orq_fence) { + if (unlikely(tx_waiting->wr_status != SIW_WR_QUEUED)) { + pr_warn("siw: [QP %u]: fence resume: bad status %d\n", +@@ -1165,10 +1166,12 @@ static int siw_check_tx_fence(struct siw_qp *qp) + rv = -EPROTO; + goto out; + } +- /* resume SQ processing */ ++ /* resume SQ processing, if possible */ + if (tx_waiting->sqe.opcode == SIW_OP_READ || + tx_waiting->sqe.opcode == SIW_OP_READ_LOCAL_INV) { +- rreq = orq_get_tail(qp); ++ ++ /* SQ processing was stopped because of a full ORQ */ ++ rreq = orq_get_free(qp); + if (unlikely(!rreq)) { + pr_warn("siw: [QP %u]: no ORQE\n", qp_id(qp)); + rv = -EPROTO; +@@ -1181,15 +1184,14 @@ static int siw_check_tx_fence(struct siw_qp *qp) + resume_tx = 1; + + } else if (siw_orq_empty(qp)) { ++ /* ++ * SQ processing was stopped by fenced work request. ++ * Resume since all previous Read's are now completed. ++ */ + qp->tx_ctx.orq_fence = 0; + resume_tx = 1; +- } else { +- pr_warn("siw: [QP %u]: fence resume: orq idx: %d:%d\n", +- qp_id(qp), qp->orq_get, qp->orq_put); +- rv = -EPROTO; + } + } +- qp->orq_get++; + out: + spin_unlock_irqrestore(&qp->orq_lock, flags); + +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 1b36350601faa..aa3f60d54a70f 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -311,7 +311,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + + if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) { + siw_dbg(base_dev, "too many QP's\n"); +- return -ENOMEM; ++ rv = -ENOMEM; ++ goto err_atomic; + } + if (attrs->qp_type != IB_QPT_RC) { + siw_dbg(base_dev, "only RC QP's supported\n"); +diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +index bc8824b4ee0d4..a23438bacf12c 100644 +--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c ++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c +@@ -867,7 +867,7 @@ static struct rtrs_clt_sess *get_next_path_min_latency(struct path_it *it) + struct rtrs_clt_sess *min_path = NULL; + struct rtrs_clt *clt = it->clt; + struct rtrs_clt_sess *sess; +- ktime_t min_latency = INT_MAX; ++ ktime_t min_latency = KTIME_MAX; + ktime_t latency; + + list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) { +@@ -2664,6 +2664,8 @@ static void rtrs_clt_dev_release(struct device *dev) + { + struct rtrs_clt *clt = container_of(dev, struct rtrs_clt, dev); + ++ mutex_destroy(&clt->paths_ev_mutex); ++ mutex_destroy(&clt->paths_mutex); + kfree(clt); + } + +@@ -2693,6 +2695,8 @@ static struct rtrs_clt *alloc_clt(const char *sessname, size_t paths_num, + return ERR_PTR(-ENOMEM); + } + ++ clt->dev.class = rtrs_clt_dev_class; ++ clt->dev.release = rtrs_clt_dev_release; + uuid_gen(&clt->paths_uuid); + INIT_LIST_HEAD_RCU(&clt->paths_list); + clt->paths_num = paths_num; +@@ -2709,53 +2713,51 @@ static struct rtrs_clt *alloc_clt(const char *sessname, size_t paths_num, + init_waitqueue_head(&clt->permits_wait); + mutex_init(&clt->paths_ev_mutex); + mutex_init(&clt->paths_mutex); ++ device_initialize(&clt->dev); + +- clt->dev.class = rtrs_clt_dev_class; +- clt->dev.release = rtrs_clt_dev_release; + err = dev_set_name(&clt->dev, "%s", sessname); + if (err) +- goto err; ++ goto err_put; ++ + /* + * Suppress user space notification until + * sysfs files are created + */ + dev_set_uevent_suppress(&clt->dev, true); +- err = device_register(&clt->dev); +- if (err) { +- put_device(&clt->dev); +- goto err; +- } ++ err = device_add(&clt->dev); ++ if (err) ++ goto err_put; + + clt->kobj_paths = kobject_create_and_add("paths", &clt->dev.kobj); + if (!clt->kobj_paths) { + err = -ENOMEM; +- goto err_dev; ++ goto err_del; + } + err = rtrs_clt_create_sysfs_root_files(clt); + if (err) { + kobject_del(clt->kobj_paths); + kobject_put(clt->kobj_paths); +- goto err_dev; ++ goto err_del; + } + dev_set_uevent_suppress(&clt->dev, false); + kobject_uevent(&clt->dev.kobj, KOBJ_ADD); + + return clt; +-err_dev: +- device_unregister(&clt->dev); +-err: ++err_del: ++ device_del(&clt->dev); ++err_put: + free_percpu(clt->pcpu_path); +- kfree(clt); ++ put_device(&clt->dev); + return ERR_PTR(err); + } + + static void free_clt(struct rtrs_clt *clt) + { +- free_permits(clt); + free_percpu(clt->pcpu_path); +- mutex_destroy(&clt->paths_ev_mutex); +- mutex_destroy(&clt->paths_mutex); +- /* release callback will free clt in last put */ ++ ++ /* ++ * release callback will free clt and destroy mutexes in last put ++ */ + device_unregister(&clt->dev); + } + +@@ -2866,6 +2868,7 @@ void rtrs_clt_close(struct rtrs_clt *clt) + rtrs_clt_destroy_sess_files(sess, NULL); + kobject_put(&sess->kobj); + } ++ free_permits(clt); + free_clt(clt); + } + EXPORT_SYMBOL(rtrs_clt_close); +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index 71eda91e810cf..5d416ec228717 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -4038,9 +4038,11 @@ static void srp_remove_one(struct ib_device *device, void *client_data) + spin_unlock(&host->target_lock); + + /* +- * Wait for tl_err and target port removal tasks. ++ * srp_queue_remove_work() queues a call to ++ * srp_remove_target(). The latter function cancels ++ * target->tl_err_work so waiting for the remove works to ++ * finish is sufficient. + */ +- flush_workqueue(system_long_wq); + flush_workqueue(srp_remove_wq); + + kfree(host); +diff --git a/drivers/input/input.c b/drivers/input/input.c +index ccaeb24263854..c3139bc2aa0db 100644 +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -2285,6 +2285,12 @@ int input_register_device(struct input_dev *dev) + /* KEY_RESERVED is not supposed to be transmitted to userspace. */ + __clear_bit(KEY_RESERVED, dev->keybit); + ++ /* Buttonpads should not map BTN_RIGHT and/or BTN_MIDDLE. */ ++ if (test_bit(INPUT_PROP_BUTTONPAD, dev->propbit)) { ++ __clear_bit(BTN_RIGHT, dev->keybit); ++ __clear_bit(BTN_MIDDLE, dev->keybit); ++ } ++ + /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ + input_cleanse_bitmasks(dev); + +diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c +index 6c554c11a7ac3..ea58805c480fa 100644 +--- a/drivers/input/joystick/iforce/iforce-usb.c ++++ b/drivers/input/joystick/iforce/iforce-usb.c +@@ -92,7 +92,7 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 id, + id, + USB_TYPE_VENDOR | USB_DIR_IN | + USB_RECIP_INTERFACE, +- 0, 0, buf, IFORCE_MAX_LENGTH, HZ); ++ 0, 0, buf, IFORCE_MAX_LENGTH, 1000); + if (status < 0) { + dev_err(&iforce_usb->intf->dev, + "usb_submit_urb failed: %d\n", status); +diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c +index 429411c6c0a8e..a85a4f33aea8c 100644 +--- a/drivers/input/joystick/spaceball.c ++++ b/drivers/input/joystick/spaceball.c +@@ -19,6 +19,7 @@ + #include <linux/module.h> + #include <linux/input.h> + #include <linux/serio.h> ++#include <asm/unaligned.h> + + #define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver" + +@@ -75,9 +76,15 @@ static void spaceball_process_packet(struct spaceball* spaceball) + + case 'D': /* Ball data */ + if (spaceball->idx != 15) return; +- for (i = 0; i < 6; i++) ++ /* ++ * Skip first three bytes; read six axes worth of data. ++ * Axis values are signed 16-bit big-endian. ++ */ ++ data += 3; ++ for (i = 0; i < ARRAY_SIZE(spaceball_axes); i++) { + input_report_abs(dev, spaceball_axes[i], +- (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2])); ++ (__s16)get_unaligned_be16(&data[i * 2])); ++ } + break; + + case 'K': /* Button data */ +diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig +index e75650e98c9ef..e402915cc0c00 100644 +--- a/drivers/input/keyboard/Kconfig ++++ b/drivers/input/keyboard/Kconfig +@@ -556,7 +556,7 @@ config KEYBOARD_PMIC8XXX + + config KEYBOARD_SAMSUNG + tristate "Samsung keypad support" +- depends on HAVE_CLK ++ depends on HAS_IOMEM && HAVE_CLK + select INPUT_MATRIXKMAP + help + Say Y here if you want to use the keypad on your Samsung mobile +diff --git a/drivers/input/misc/ariel-pwrbutton.c b/drivers/input/misc/ariel-pwrbutton.c +index 17bbaac8b80c8..cdc80715b5fd6 100644 +--- a/drivers/input/misc/ariel-pwrbutton.c ++++ b/drivers/input/misc/ariel-pwrbutton.c +@@ -149,12 +149,19 @@ static const struct of_device_id ariel_pwrbutton_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match); + ++static const struct spi_device_id ariel_pwrbutton_spi_ids[] = { ++ { .name = "wyse-ariel-ec-input" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(spi, ariel_pwrbutton_spi_ids); ++ + static struct spi_driver ariel_pwrbutton_driver = { + .driver = { + .name = "dell-wyse-ariel-ec-input", + .of_match_table = ariel_pwrbutton_of_match, + }, + .probe = ariel_pwrbutton_probe, ++ .id_table = ariel_pwrbutton_spi_ids, + }; + module_spi_driver(ariel_pwrbutton_driver); + +diff --git a/drivers/input/misc/iqs626a.c b/drivers/input/misc/iqs626a.c +index d57e996732cf4..23b5dd9552dcc 100644 +--- a/drivers/input/misc/iqs626a.c ++++ b/drivers/input/misc/iqs626a.c +@@ -456,9 +456,10 @@ struct iqs626_private { + unsigned int suspend_mode; + }; + +-static int iqs626_parse_events(struct iqs626_private *iqs626, +- const struct fwnode_handle *ch_node, +- enum iqs626_ch_id ch_id) ++static noinline_for_stack int ++iqs626_parse_events(struct iqs626_private *iqs626, ++ const struct fwnode_handle *ch_node, ++ enum iqs626_ch_id ch_id) + { + struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; + struct i2c_client *client = iqs626->client; +@@ -604,9 +605,10 @@ static int iqs626_parse_events(struct iqs626_private *iqs626, + return 0; + } + +-static int iqs626_parse_ati_target(struct iqs626_private *iqs626, +- const struct fwnode_handle *ch_node, +- enum iqs626_ch_id ch_id) ++static noinline_for_stack int ++iqs626_parse_ati_target(struct iqs626_private *iqs626, ++ const struct fwnode_handle *ch_node, ++ enum iqs626_ch_id ch_id) + { + struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; + struct i2c_client *client = iqs626->client; +@@ -885,9 +887,10 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626, + return 0; + } + +-static int iqs626_parse_channel(struct iqs626_private *iqs626, +- const struct fwnode_handle *ch_node, +- enum iqs626_ch_id ch_id) ++static noinline_for_stack int ++iqs626_parse_channel(struct iqs626_private *iqs626, ++ const struct fwnode_handle *ch_node, ++ enum iqs626_ch_id ch_id) + { + struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; + struct i2c_client *client = iqs626->client; +diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c +index bfa26651c0be7..627048bc6a12e 100644 +--- a/drivers/input/mouse/appletouch.c ++++ b/drivers/input/mouse/appletouch.c +@@ -916,6 +916,8 @@ static int atp_probe(struct usb_interface *iface, + set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + set_bit(BTN_LEFT, input_dev->keybit); + ++ INIT_WORK(&dev->work, atp_reinit); ++ + error = input_register_device(dev->input); + if (error) + goto err_free_buffer; +@@ -923,8 +925,6 @@ static int atp_probe(struct usb_interface *iface, + /* save our data pointer in this interface device */ + usb_set_intfdata(iface, dev); + +- INIT_WORK(&dev->work, atp_reinit); +- + return 0; + + err_free_buffer: +diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c +index 47af62c122672..e1758d5ffe421 100644 +--- a/drivers/input/mouse/elan_i2c_core.c ++++ b/drivers/input/mouse/elan_i2c_core.c +@@ -186,55 +186,21 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, + return 0; + } + +-static int elan_enable_power(struct elan_tp_data *data) ++static int elan_set_power(struct elan_tp_data *data, bool on) + { + int repeat = ETP_RETRY_COUNT; + int error; + +- error = regulator_enable(data->vcc); +- if (error) { +- dev_err(&data->client->dev, +- "failed to enable regulator: %d\n", error); +- return error; +- } +- + do { +- error = data->ops->power_control(data->client, true); ++ error = data->ops->power_control(data->client, on); + if (error >= 0) + return 0; + + msleep(30); + } while (--repeat > 0); + +- dev_err(&data->client->dev, "failed to enable power: %d\n", error); +- return error; +-} +- +-static int elan_disable_power(struct elan_tp_data *data) +-{ +- int repeat = ETP_RETRY_COUNT; +- int error; +- +- do { +- error = data->ops->power_control(data->client, false); +- if (!error) { +- error = regulator_disable(data->vcc); +- if (error) { +- dev_err(&data->client->dev, +- "failed to disable regulator: %d\n", +- error); +- /* Attempt to power the chip back up */ +- data->ops->power_control(data->client, true); +- break; +- } +- +- return 0; +- } +- +- msleep(30); +- } while (--repeat > 0); +- +- dev_err(&data->client->dev, "failed to disable power: %d\n", error); ++ dev_err(&data->client->dev, "failed to set power %s: %d\n", ++ on ? "on" : "off", error); + return error; + } + +@@ -1399,9 +1365,19 @@ static int __maybe_unused elan_suspend(struct device *dev) + /* Enable wake from IRQ */ + data->irq_wake = (enable_irq_wake(client->irq) == 0); + } else { +- ret = elan_disable_power(data); ++ ret = elan_set_power(data, false); ++ if (ret) ++ goto err; ++ ++ ret = regulator_disable(data->vcc); ++ if (ret) { ++ dev_err(dev, "error %d disabling regulator\n", ret); ++ /* Attempt to power the chip back up */ ++ elan_set_power(data, true); ++ } + } + ++err: + mutex_unlock(&data->sysfs_mutex); + return ret; + } +@@ -1412,12 +1388,18 @@ static int __maybe_unused elan_resume(struct device *dev) + struct elan_tp_data *data = i2c_get_clientdata(client); + int error; + +- if (device_may_wakeup(dev) && data->irq_wake) { ++ if (!device_may_wakeup(dev)) { ++ error = regulator_enable(data->vcc); ++ if (error) { ++ dev_err(dev, "error %d enabling regulator\n", error); ++ goto err; ++ } ++ } else if (data->irq_wake) { + disable_irq_wake(client->irq); + data->irq_wake = false; + } + +- error = elan_enable_power(data); ++ error = elan_set_power(data, true); + if (error) { + dev_err(dev, "power up when resuming failed: %d\n", error); + goto err; +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 2d0bc029619ff..ece97f8c6a3e3 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -517,6 +517,19 @@ static void elantech_report_trackpoint(struct psmouse *psmouse, + case 0x16008020U: + case 0x26800010U: + case 0x36808000U: ++ ++ /* ++ * This firmware misreport coordinates for trackpoint ++ * occasionally. Discard packets outside of [-127, 127] range ++ * to prevent cursor jumps. ++ */ ++ if (packet[4] == 0x80 || packet[5] == 0x80 || ++ packet[1] >> 7 == packet[4] >> 7 || ++ packet[2] >> 7 == packet[5] >> 7) { ++ elantech_debug("discarding packet [%6ph]\n", packet); ++ break; ++ ++ } + x = packet[4] - (int)((packet[1]^0x80) << 1); + y = (int)((packet[2]^0x80) << 1) - packet[5]; + +@@ -1575,7 +1588,13 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = { + */ + static int elantech_change_report_id(struct psmouse *psmouse) + { +- unsigned char param[2] = { 0x10, 0x03 }; ++ /* ++ * NOTE: the code is expecting to receive param[] as an array of 3 ++ * items (see __ps2_command()), even if in this case only 2 are ++ * actually needed. Make sure the array size is 3 to avoid potential ++ * stack out-of-bound accesses. ++ */ ++ unsigned char param[3] = { 0x10, 0x03 }; + + if (elantech_write_reg_params(psmouse, 0x7, param) || + elantech_read_reg_params(psmouse, 0x7, param) || +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index a5a0035536462..148a7c5fd0e22 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -272,6 +272,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), + }, + }, ++ { ++ /* Fujitsu Lifebook T725 laptop */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"), ++ }, ++ }, + { + /* Fujitsu Lifebook U745 */ + .matches = { +@@ -840,6 +847,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"), + }, + }, ++ { ++ /* Fujitsu Lifebook T725 laptop */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"), ++ }, ++ }, + { + /* Fujitsu U574 laptop */ + /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ +@@ -981,6 +995,24 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { + { } + }; + ++static const struct dmi_system_id i8042_dmi_probe_defer_table[] __initconst = { ++ { ++ /* ASUS ZenBook UX425UA */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"), ++ }, ++ }, ++ { ++ /* ASUS ZenBook UM325UA */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), ++ }, ++ }, ++ { } ++}; ++ + #endif /* CONFIG_X86 */ + + #ifdef CONFIG_PNP +@@ -1301,6 +1333,9 @@ static int __init i8042_platform_init(void) + if (dmi_check_system(i8042_dmi_kbdreset_table)) + i8042_kbdreset = true; + ++ if (dmi_check_system(i8042_dmi_probe_defer_table)) ++ i8042_probe_defer = true; ++ + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index 0b9f1d0a8f8b0..3fc0a89cc785c 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -45,6 +45,10 @@ static bool i8042_unlock; + module_param_named(unlock, i8042_unlock, bool, 0); + MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); + ++static bool i8042_probe_defer; ++module_param_named(probe_defer, i8042_probe_defer, bool, 0); ++MODULE_PARM_DESC(probe_defer, "Allow deferred probing."); ++ + enum i8042_controller_reset_mode { + I8042_RESET_NEVER, + I8042_RESET_ALWAYS, +@@ -711,7 +715,7 @@ static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) + * LCS/Telegraphics. + */ + +-static int __init i8042_check_mux(void) ++static int i8042_check_mux(void) + { + unsigned char mux_version; + +@@ -740,10 +744,10 @@ static int __init i8042_check_mux(void) + /* + * The following is used to test AUX IRQ delivery. + */ +-static struct completion i8042_aux_irq_delivered __initdata; +-static bool i8042_irq_being_tested __initdata; ++static struct completion i8042_aux_irq_delivered; ++static bool i8042_irq_being_tested; + +-static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) ++static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id) + { + unsigned long flags; + unsigned char str, data; +@@ -770,7 +774,7 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) + * verifies success by readinng CTR. Used when testing for presence of AUX + * port. + */ +-static int __init i8042_toggle_aux(bool on) ++static int i8042_toggle_aux(bool on) + { + unsigned char param; + int i; +@@ -798,7 +802,7 @@ static int __init i8042_toggle_aux(bool on) + * the presence of an AUX interface. + */ + +-static int __init i8042_check_aux(void) ++static int i8042_check_aux(void) + { + int retval = -1; + bool irq_registered = false; +@@ -1005,7 +1009,7 @@ static int i8042_controller_init(void) + + if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { + pr_err("Can't read CTR while initializing i8042\n"); +- return -EIO; ++ return i8042_probe_defer ? -EPROBE_DEFER : -EIO; + } + + } while (n < 2 || ctr[0] != ctr[1]); +@@ -1320,7 +1324,7 @@ static void i8042_shutdown(struct platform_device *dev) + i8042_controller_reset(false); + } + +-static int __init i8042_create_kbd_port(void) ++static int i8042_create_kbd_port(void) + { + struct serio *serio; + struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; +@@ -1349,7 +1353,7 @@ static int __init i8042_create_kbd_port(void) + return 0; + } + +-static int __init i8042_create_aux_port(int idx) ++static int i8042_create_aux_port(int idx) + { + struct serio *serio; + int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; +@@ -1386,13 +1390,13 @@ static int __init i8042_create_aux_port(int idx) + return 0; + } + +-static void __init i8042_free_kbd_port(void) ++static void i8042_free_kbd_port(void) + { + kfree(i8042_ports[I8042_KBD_PORT_NO].serio); + i8042_ports[I8042_KBD_PORT_NO].serio = NULL; + } + +-static void __init i8042_free_aux_ports(void) ++static void i8042_free_aux_ports(void) + { + int i; + +@@ -1402,7 +1406,7 @@ static void __init i8042_free_aux_ports(void) + } + } + +-static void __init i8042_register_ports(void) ++static void i8042_register_ports(void) + { + int i; + +@@ -1443,7 +1447,7 @@ static void i8042_free_irqs(void) + i8042_aux_irq_registered = i8042_kbd_irq_registered = false; + } + +-static int __init i8042_setup_aux(void) ++static int i8042_setup_aux(void) + { + int (*aux_enable)(void); + int error; +@@ -1485,7 +1489,7 @@ static int __init i8042_setup_aux(void) + return error; + } + +-static int __init i8042_setup_kbd(void) ++static int i8042_setup_kbd(void) + { + int error; + +@@ -1535,7 +1539,7 @@ static int i8042_kbd_bind_notifier(struct notifier_block *nb, + return 0; + } + +-static int __init i8042_probe(struct platform_device *dev) ++static int i8042_probe(struct platform_device *dev) + { + int error; + +@@ -1600,6 +1604,7 @@ static struct platform_driver i8042_driver = { + .pm = &i8042_pm_ops, + #endif + }, ++ .probe = i8042_probe, + .remove = i8042_remove, + .shutdown = i8042_shutdown, + }; +@@ -1610,7 +1615,6 @@ static struct notifier_block i8042_kbd_bind_notifier_block = { + + static int __init i8042_init(void) + { +- struct platform_device *pdev; + int err; + + dbg_init(); +@@ -1626,17 +1630,29 @@ static int __init i8042_init(void) + /* Set this before creating the dev to allow i8042_command to work right away */ + i8042_present = true; + +- pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); +- if (IS_ERR(pdev)) { +- err = PTR_ERR(pdev); ++ err = platform_driver_register(&i8042_driver); ++ if (err) + goto err_platform_exit; ++ ++ i8042_platform_device = platform_device_alloc("i8042", -1); ++ if (!i8042_platform_device) { ++ err = -ENOMEM; ++ goto err_unregister_driver; + } + ++ err = platform_device_add(i8042_platform_device); ++ if (err) ++ goto err_free_device; ++ + bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block); + panic_blink = i8042_panic_blink; + + return 0; + ++err_free_device: ++ platform_device_put(i8042_platform_device); ++err_unregister_driver: ++ platform_driver_unregister(&i8042_driver); + err_platform_exit: + i8042_platform_exit(); + return err; +diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c +index 05de92c0293bc..eb66cd2689b7c 100644 +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -1882,7 +1882,7 @@ static int mxt_read_info_block(struct mxt_data *data) + if (error) { + dev_err(&client->dev, "Error %d parsing object table\n", error); + mxt_free_object_table(data); +- goto err_free_mem; ++ return error; + } + + data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START); +diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c +index 68f542bb809f4..b9e2219efbb8f 100644 +--- a/drivers/input/touchscreen/elants_i2c.c ++++ b/drivers/input/touchscreen/elants_i2c.c +@@ -117,6 +117,19 @@ + #define ELAN_POWERON_DELAY_USEC 500 + #define ELAN_RESET_DELAY_MSEC 20 + ++/* FW boot code version */ ++#define BC_VER_H_BYTE_FOR_EKTH3900x1_I2C 0x72 ++#define BC_VER_H_BYTE_FOR_EKTH3900x2_I2C 0x82 ++#define BC_VER_H_BYTE_FOR_EKTH3900x3_I2C 0x92 ++#define BC_VER_H_BYTE_FOR_EKTH5312x1_I2C 0x6D ++#define BC_VER_H_BYTE_FOR_EKTH5312x2_I2C 0x6E ++#define BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C 0x77 ++#define BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C 0x78 ++#define BC_VER_H_BYTE_FOR_EKTH5312x1_I2C_USB 0x67 ++#define BC_VER_H_BYTE_FOR_EKTH5312x2_I2C_USB 0x68 ++#define BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C_USB 0x74 ++#define BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C_USB 0x75 ++ + enum elants_chip_id { + EKTH3500, + EKTF3624, +@@ -736,6 +749,37 @@ static int elants_i2c_validate_remark_id(struct elants_data *ts, + return 0; + } + ++static bool elants_i2c_should_check_remark_id(struct elants_data *ts) ++{ ++ struct i2c_client *client = ts->client; ++ const u8 bootcode_version = ts->iap_version; ++ bool check; ++ ++ /* I2C eKTH3900 and eKTH5312 are NOT support Remark ID */ ++ if ((bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x1_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x2_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x3_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x1_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x2_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x1_I2C_USB) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x2_I2C_USB) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C_USB) || ++ (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C_USB)) { ++ dev_dbg(&client->dev, ++ "eKTH3900/eKTH5312(0x%02x) are not support remark id\n", ++ bootcode_version); ++ check = false; ++ } else if (bootcode_version >= 0x60) { ++ check = true; ++ } else { ++ check = false; ++ } ++ ++ return check; ++} ++ + static int elants_i2c_do_update_firmware(struct i2c_client *client, + const struct firmware *fw, + bool force) +@@ -749,7 +793,7 @@ static int elants_i2c_do_update_firmware(struct i2c_client *client, + u16 send_id; + int page, n_fw_pages; + int error; +- bool check_remark_id = ts->iap_version >= 0x60; ++ bool check_remark_id = elants_i2c_should_check_remark_id(ts); + + /* Recovery mode detection! */ + if (force) { +diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c +index 4f53d3c57e698..5051a1766aac6 100644 +--- a/drivers/input/touchscreen/goodix.c ++++ b/drivers/input/touchscreen/goodix.c +@@ -162,6 +162,7 @@ static const struct goodix_chip_id goodix_chip_ids[] = { + { .id = "911", .data = >911_chip_data }, + { .id = "9271", .data = >911_chip_data }, + { .id = "9110", .data = >911_chip_data }, ++ { .id = "9111", .data = >911_chip_data }, + { .id = "927", .data = >911_chip_data }, + { .id = "928", .data = >911_chip_data }, + +diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c +index 6abae665ca71d..9d1dea6996a22 100644 +--- a/drivers/input/touchscreen/st1232.c ++++ b/drivers/input/touchscreen/st1232.c +@@ -92,7 +92,7 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts) + unsigned int retries; + int error; + +- for (retries = 10; retries; retries--) { ++ for (retries = 100; retries; retries--) { + error = st1232_ts_read_data(ts, REG_STATUS, 1); + if (!error) { + switch (ts->read_buf[0]) { +diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c +index 83e685557a197..cfc943423241f 100644 +--- a/drivers/input/touchscreen/ti_am335x_tsc.c ++++ b/drivers/input/touchscreen/ti_am335x_tsc.c +@@ -131,7 +131,8 @@ static void titsc_step_config(struct titsc *ts_dev) + u32 stepenable; + + config = STEPCONFIG_MODE_HWSYNC | +- STEPCONFIG_AVG_16 | ts_dev->bit_xp; ++ STEPCONFIG_AVG_16 | ts_dev->bit_xp | ++ STEPCONFIG_INM_ADCREFM; + switch (ts_dev->wires) { + case 4: + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; +@@ -195,7 +196,10 @@ static void titsc_step_config(struct titsc *ts_dev) + STEPCONFIG_OPENDLY); + + end_step++; +- config |= STEPCONFIG_INP(ts_dev->inp_yn); ++ config = STEPCONFIG_MODE_HWSYNC | ++ STEPCONFIG_AVG_16 | ts_dev->bit_yp | ++ ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | ++ STEPCONFIG_INP(ts_dev->inp_yn); + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), + STEPCONFIG_OPENDLY); +diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c +index b8d901099378d..1e70b8d2a8d79 100644 +--- a/drivers/input/touchscreen/zinitix.c ++++ b/drivers/input/touchscreen/zinitix.c +@@ -488,6 +488,15 @@ static int zinitix_ts_probe(struct i2c_client *client) + return error; + } + ++ error = devm_request_threaded_irq(&client->dev, client->irq, ++ NULL, zinitix_ts_irq_handler, ++ IRQF_ONESHOT | IRQF_NO_AUTOEN, ++ client->name, bt541); ++ if (error) { ++ dev_err(&client->dev, "Failed to request IRQ: %d\n", error); ++ return error; ++ } ++ + error = zinitix_init_input_dev(bt541); + if (error) { + dev_err(&client->dev, +@@ -513,15 +522,6 @@ static int zinitix_ts_probe(struct i2c_client *client) + return -EINVAL; + } + +- error = devm_request_threaded_irq(&client->dev, client->irq, +- NULL, zinitix_ts_irq_handler, +- IRQF_ONESHOT | IRQF_NO_AUTOEN, +- client->name, bt541); +- if (error) { +- dev_err(&client->dev, "Failed to request IRQ: %d\n", error); +- return error; +- } +- + return 0; + } + +diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c +index 54de49ca7808a..ddf1805ded0c0 100644 +--- a/drivers/interconnect/qcom/icc-rpm.c ++++ b/drivers/interconnect/qcom/icc-rpm.c +@@ -68,6 +68,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) + rate = max(sum_bw, max_peak_bw); + + do_div(rate, qn->buswidth); ++ rate = min_t(u64, rate, LONG_MAX); + + if (qn->rate == rate) + return 0; +diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h +index 416815a525d67..bb95edf74415b 100644 +--- a/drivers/iommu/amd/amd_iommu.h ++++ b/drivers/iommu/amd/amd_iommu.h +@@ -14,6 +14,7 @@ + extern irqreturn_t amd_iommu_int_thread(int irq, void *data); + extern irqreturn_t amd_iommu_int_handler(int irq, void *data); + extern void amd_iommu_apply_erratum_63(u16 devid); ++extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu); + extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu); + extern int amd_iommu_init_devices(void); + extern void amd_iommu_uninit_devices(void); +diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h +index 8dbe61e2b3c15..b6e0bf186cf54 100644 +--- a/drivers/iommu/amd/amd_iommu_types.h ++++ b/drivers/iommu/amd/amd_iommu_types.h +@@ -110,6 +110,7 @@ + #define PASID_MASK 0x0000ffff + + /* MMIO status bits */ ++#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK (1 << 0) + #define MMIO_STATUS_EVT_INT_MASK (1 << 1) + #define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2) + #define MMIO_STATUS_PPR_INT_MASK (1 << 6) +@@ -643,8 +644,6 @@ struct amd_iommu { + /* DebugFS Info */ + struct dentry *debugfs; + #endif +- /* IRQ notifier for IntCapXT interrupt */ +- struct irq_affinity_notify intcapxt_notify; + }; + + static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev) +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 2a822b229bd05..204ed33c56dce 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -21,6 +21,7 @@ + #include <linux/export.h> + #include <linux/kmemleak.h> + #include <linux/mem_encrypt.h> ++#include <linux/iopoll.h> + #include <asm/pci-direct.h> + #include <asm/iommu.h> + #include <asm/apic.h> +@@ -654,6 +655,16 @@ static int __init alloc_command_buffer(struct amd_iommu *iommu) + return iommu->cmd_buf ? 0 : -ENOMEM; + } + ++/* ++ * This function restarts event logging in case the IOMMU experienced ++ * an event log buffer overflow. ++ */ ++void amd_iommu_restart_event_logging(struct amd_iommu *iommu) ++{ ++ iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN); ++ iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN); ++} ++ + /* + * This function resets the command buffer if the IOMMU stopped fetching + * commands from it. +@@ -804,16 +815,27 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) + { + #ifdef CONFIG_IRQ_REMAP + u32 status, i; ++ u64 entry; + + if (!iommu->ga_log) + return -EINVAL; + +- status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); +- + /* Check if already running */ +- if (status & (MMIO_STATUS_GALOG_RUN_MASK)) ++ status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); ++ if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK))) + return 0; + ++ entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; ++ memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, ++ &entry, sizeof(entry)); ++ entry = (iommu_virt_to_phys(iommu->ga_log_tail) & ++ (BIT_ULL(52)-1)) & ~7ULL; ++ memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, ++ &entry, sizeof(entry)); ++ writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); ++ writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); ++ ++ + iommu_feature_enable(iommu, CONTROL_GAINT_EN); + iommu_feature_enable(iommu, CONTROL_GALOG_EN); + +@@ -821,9 +843,10 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) + status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); + if (status & (MMIO_STATUS_GALOG_RUN_MASK)) + break; ++ udelay(10); + } + +- if (i >= LOOP_TIMEOUT) ++ if (WARN_ON(i >= LOOP_TIMEOUT)) + return -EINVAL; + #endif /* CONFIG_IRQ_REMAP */ + return 0; +@@ -832,8 +855,6 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) + static int iommu_init_ga_log(struct amd_iommu *iommu) + { + #ifdef CONFIG_IRQ_REMAP +- u64 entry; +- + if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) + return 0; + +@@ -847,16 +868,6 @@ static int iommu_init_ga_log(struct amd_iommu *iommu) + if (!iommu->ga_log_tail) + goto err_out; + +- entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; +- memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, +- &entry, sizeof(entry)); +- entry = (iommu_virt_to_phys(iommu->ga_log_tail) & +- (BIT_ULL(52)-1)) & ~7ULL; +- memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, +- &entry, sizeof(entry)); +- writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); +- writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); +- + return 0; + err_out: + free_ga_log(iommu); +@@ -2013,48 +2024,18 @@ union intcapxt { + }; + } __attribute__ ((packed)); + +-/* +- * There isn't really any need to mask/unmask at the irqchip level because +- * the 64-bit INTCAPXT registers can be updated atomically without tearing +- * when the affinity is being updated. +- */ +-static void intcapxt_unmask_irq(struct irq_data *data) +-{ +-} +- +-static void intcapxt_mask_irq(struct irq_data *data) +-{ +-} + + static struct irq_chip intcapxt_controller; + + static int intcapxt_irqdomain_activate(struct irq_domain *domain, + struct irq_data *irqd, bool reserve) + { +- struct amd_iommu *iommu = irqd->chip_data; +- struct irq_cfg *cfg = irqd_cfg(irqd); +- union intcapxt xt; +- +- xt.capxt = 0ULL; +- xt.dest_mode_logical = apic->dest_mode_logical; +- xt.vector = cfg->vector; +- xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); +- xt.destid_24_31 = cfg->dest_apicid >> 24; +- +- /** +- * Current IOMMU implemtation uses the same IRQ for all +- * 3 IOMMU interrupts. +- */ +- writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); +- writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); +- writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); + return 0; + } + + static void intcapxt_irqdomain_deactivate(struct irq_domain *domain, + struct irq_data *irqd) + { +- intcapxt_mask_irq(irqd); + } + + +@@ -2088,6 +2069,38 @@ static void intcapxt_irqdomain_free(struct irq_domain *domain, unsigned int virq + irq_domain_free_irqs_top(domain, virq, nr_irqs); + } + ++ ++static void intcapxt_unmask_irq(struct irq_data *irqd) ++{ ++ struct amd_iommu *iommu = irqd->chip_data; ++ struct irq_cfg *cfg = irqd_cfg(irqd); ++ union intcapxt xt; ++ ++ xt.capxt = 0ULL; ++ xt.dest_mode_logical = apic->dest_mode_logical; ++ xt.vector = cfg->vector; ++ xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); ++ xt.destid_24_31 = cfg->dest_apicid >> 24; ++ ++ /** ++ * Current IOMMU implementation uses the same IRQ for all ++ * 3 IOMMU interrupts. ++ */ ++ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); ++ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); ++ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); ++} ++ ++static void intcapxt_mask_irq(struct irq_data *irqd) ++{ ++ struct amd_iommu *iommu = irqd->chip_data; ++ ++ writeq(0, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); ++ writeq(0, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); ++ writeq(0, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); ++} ++ ++ + static int intcapxt_set_affinity(struct irq_data *irqd, + const struct cpumask *mask, bool force) + { +@@ -2097,8 +2110,12 @@ static int intcapxt_set_affinity(struct irq_data *irqd, + ret = parent->chip->irq_set_affinity(parent, mask, force); + if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) + return ret; ++ return 0; ++} + +- return intcapxt_irqdomain_activate(irqd->domain, irqd, false); ++static int intcapxt_set_wake(struct irq_data *irqd, unsigned int on) ++{ ++ return on ? -EOPNOTSUPP : 0; + } + + static struct irq_chip intcapxt_controller = { +@@ -2108,7 +2125,8 @@ static struct irq_chip intcapxt_controller = { + .irq_ack = irq_chip_ack_parent, + .irq_retrigger = irq_chip_retrigger_hierarchy, + .irq_set_affinity = intcapxt_set_affinity, +- .flags = IRQCHIP_SKIP_SET_WAKE, ++ .irq_set_wake = intcapxt_set_wake, ++ .flags = IRQCHIP_MASK_ON_SUSPEND, + }; + + static const struct irq_domain_ops intcapxt_domain_ops = { +@@ -2170,7 +2188,6 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu) + return ret; + } + +- iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); + return 0; + } + +@@ -2193,6 +2210,10 @@ static int iommu_init_irq(struct amd_iommu *iommu) + + iommu->int_enabled = true; + enable_faults: ++ ++ if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE) ++ iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); ++ + iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); + + if (iommu->ppr_log != NULL) +diff --git a/drivers/iommu/amd/io_pgtable.c b/drivers/iommu/amd/io_pgtable.c +index 182c93a43efd8..1eddf557636d7 100644 +--- a/drivers/iommu/amd/io_pgtable.c ++++ b/drivers/iommu/amd/io_pgtable.c +@@ -519,12 +519,6 @@ static void v1_free_pgtable(struct io_pgtable *iop) + + dom = container_of(pgtable, struct protection_domain, iop); + +- /* Update data structure */ +- amd_iommu_domain_clr_pt_root(dom); +- +- /* Make changes visible to IOMMUs */ +- amd_iommu_domain_update(dom); +- + /* Page-table is not visible to IOMMU anymore, so free it */ + BUG_ON(pgtable->mode < PAGE_MODE_NONE || + pgtable->mode > PAGE_MODE_6_LEVEL); +@@ -532,6 +526,12 @@ static void v1_free_pgtable(struct io_pgtable *iop) + root = (unsigned long)pgtable->root; + freelist = free_sub_pt(root, pgtable->mode, freelist); + ++ /* Update data structure */ ++ amd_iommu_domain_clr_pt_root(dom); ++ ++ /* Make changes visible to IOMMUs */ ++ amd_iommu_domain_update(dom); ++ + free_page_list(freelist); + } + +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index 1722bb161841f..f46eb73970216 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -742,7 +742,8 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { } + #endif /* !CONFIG_IRQ_REMAP */ + + #define AMD_IOMMU_INT_MASK \ +- (MMIO_STATUS_EVT_INT_MASK | \ ++ (MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \ ++ MMIO_STATUS_EVT_INT_MASK | \ + MMIO_STATUS_PPR_INT_MASK | \ + MMIO_STATUS_GALOG_INT_MASK) + +@@ -752,7 +753,7 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data) + u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); + + while (status & AMD_IOMMU_INT_MASK) { +- /* Enable EVT and PPR and GA interrupts again */ ++ /* Enable interrupt sources again */ + writel(AMD_IOMMU_INT_MASK, + iommu->mmio_base + MMIO_STATUS_OFFSET); + +@@ -773,6 +774,11 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data) + } + #endif + ++ if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) { ++ pr_info_ratelimited("IOMMU event log overflow\n"); ++ amd_iommu_restart_event_logging(iommu); ++ } ++ + /* + * Hardware bug: ERBT1312 + * When re-enabling interrupt (by writing 1 +diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c +index a9e568276c99f..a45c5536d2506 100644 +--- a/drivers/iommu/amd/iommu_v2.c ++++ b/drivers/iommu/amd/iommu_v2.c +@@ -928,10 +928,8 @@ static int __init amd_iommu_v2_init(void) + { + int ret; + +- pr_info("AMD IOMMUv2 driver by Joerg Roedel <jroedel@suse.de>\n"); +- + if (!amd_iommu_v2_supported()) { +- pr_info("AMD IOMMUv2 functionality not available on this system\n"); ++ pr_info("AMD IOMMUv2 functionality not available on this system - This is not a bug.\n"); + /* + * Load anyway to provide the symbols to other modules + * which may use AMD IOMMUv2 optionally. +@@ -946,6 +944,8 @@ static int __init amd_iommu_v2_init(void) + + amd_iommu_register_ppr_notifier(&ppr_nb); + ++ pr_info("AMD IOMMUv2 loaded and initialized\n"); ++ + return 0; + + out: +diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c +index fdfa39ec2a4d4..ad69eeb5ac5ba 100644 +--- a/drivers/iommu/apple-dart.c ++++ b/drivers/iommu/apple-dart.c +@@ -70,6 +70,8 @@ + #define DART_ERROR_ADDR_HI 0x54 + #define DART_ERROR_ADDR_LO 0x50 + ++#define DART_STREAMS_ENABLE 0xfc ++ + #define DART_TCR(sid) (0x100 + 4 * (sid)) + #define DART_TCR_TRANSLATE_ENABLE BIT(7) + #define DART_TCR_BYPASS0_ENABLE BIT(8) +@@ -301,6 +303,9 @@ static int apple_dart_hw_reset(struct apple_dart *dart) + apple_dart_hw_disable_dma(&stream_map); + apple_dart_hw_clear_all_ttbrs(&stream_map); + ++ /* enable all streams globally since TCR is used to control isolation */ ++ writel(DART_STREAM_ALL, dart->regs + DART_STREAMS_ENABLE); ++ + /* clear any pending errors before the interrupt is unmasked */ + writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR); + +diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +index 55690af1b25d0..c998960495b4e 100644 +--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c ++++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +@@ -51,7 +51,7 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie, + info->fsynr1 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR1); + info->far = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_FAR); + info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); +- info->ttbr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0); ++ info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0); + info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR); + } + +diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c +index 896bea04c347e..2d60216440009 100644 +--- a/drivers/iommu/dma-iommu.c ++++ b/drivers/iommu/dma-iommu.c +@@ -593,6 +593,9 @@ static dma_addr_t __iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys, + memset(padding_start, 0, padding_size); + } + ++ if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) ++ arch_sync_dma_for_device(phys, org_size, dir); ++ + iova = __iommu_dma_map(dev, phys, aligned_size, prot, dma_mask); + if (iova == DMA_MAPPING_ERROR && is_swiotlb_buffer(dev, phys)) + swiotlb_tbl_unmap_single(dev, phys, org_size, dir, attrs); +@@ -828,17 +831,13 @@ static void iommu_dma_sync_sg_for_cpu(struct device *dev, + struct scatterlist *sg; + int i; + +- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) +- return; +- +- for_each_sg(sgl, sg, nelems, i) { +- if (!dev_is_dma_coherent(dev)) ++ if (dev_is_untrusted(dev)) ++ for_each_sg(sgl, sg, nelems, i) ++ iommu_dma_sync_single_for_cpu(dev, sg_dma_address(sg), ++ sg->length, dir); ++ else if (!dev_is_dma_coherent(dev)) ++ for_each_sg(sgl, sg, nelems, i) + arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir); +- +- if (is_swiotlb_buffer(dev, sg_phys(sg))) +- swiotlb_sync_single_for_cpu(dev, sg_phys(sg), +- sg->length, dir); +- } + } + + static void iommu_dma_sync_sg_for_device(struct device *dev, +@@ -848,17 +847,14 @@ static void iommu_dma_sync_sg_for_device(struct device *dev, + struct scatterlist *sg; + int i; + +- if (dev_is_dma_coherent(dev) && !dev_is_untrusted(dev)) +- return; +- +- for_each_sg(sgl, sg, nelems, i) { +- if (is_swiotlb_buffer(dev, sg_phys(sg))) +- swiotlb_sync_single_for_device(dev, sg_phys(sg), +- sg->length, dir); +- +- if (!dev_is_dma_coherent(dev)) ++ if (dev_is_untrusted(dev)) ++ for_each_sg(sgl, sg, nelems, i) ++ iommu_dma_sync_single_for_device(dev, ++ sg_dma_address(sg), ++ sg->length, dir); ++ else if (!dev_is_dma_coherent(dev)) ++ for_each_sg(sgl, sg, nelems, i) + arch_sync_dma_for_device(sg_phys(sg), sg->length, dir); +- } + } + + static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, +@@ -867,14 +863,9 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, + { + phys_addr_t phys = page_to_phys(page) + offset; + bool coherent = dev_is_dma_coherent(dev); +- dma_addr_t dma_handle; + +- dma_handle = __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev), ++ return __iommu_dma_map_swiotlb(dev, phys, size, dma_get_mask(dev), + coherent, dir, attrs); +- if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) && +- dma_handle != DMA_MAPPING_ERROR) +- arch_sync_dma_for_device(phys, size, dir); +- return dma_handle; + } + + static void iommu_dma_unmap_page(struct device *dev, dma_addr_t dma_handle, +@@ -1016,15 +1007,16 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, + + if (static_branch_unlikely(&iommu_deferred_attach_enabled)) { + ret = iommu_deferred_attach(dev, domain); +- goto out; ++ if (ret) ++ goto out; + } + +- if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) +- iommu_dma_sync_sg_for_device(dev, sg, nents, dir); +- + if (dev_is_untrusted(dev)) + return iommu_dma_map_sg_swiotlb(dev, sg, nents, dir, attrs); + ++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) ++ iommu_dma_sync_sg_for_device(dev, sg, nents, dir); ++ + /* + * Work out how much IOVA space we need, and align the segments to + * IOVA granules for the IOMMU driver to handle. With some clever +diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c +index d75f59ae28e6e..0b3076144beb7 100644 +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -412,6 +412,7 @@ static int __init intel_iommu_setup(char *str) + { + if (!str) + return -EINVAL; ++ + while (*str) { + if (!strncmp(str, "on", 2)) { + dmar_disabled = 0; +@@ -441,13 +442,16 @@ static int __init intel_iommu_setup(char *str) + } else if (!strncmp(str, "tboot_noforce", 13)) { + pr_info("Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n"); + intel_iommu_tboot_noforce = 1; ++ } else { ++ pr_notice("Unknown option - '%s'\n", str); + } + + str += strcspn(str, ","); + while (*str == ',') + str++; + } +- return 0; ++ ++ return 1; + } + __setup("intel_iommu=", intel_iommu_setup); + +@@ -1222,13 +1226,11 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level, + pte = &pte[pfn_level_offset(pfn, level)]; + + do { +- unsigned long level_pfn; ++ unsigned long level_pfn = pfn & level_mask(level); + + if (!dma_pte_present(pte)) + goto next; + +- level_pfn = pfn & level_mask(level); +- + /* If range covers entire pagetable, free it */ + if (start_pfn <= level_pfn && + last_pfn >= level_pfn + level_size(level) - 1) { +@@ -1249,7 +1251,7 @@ static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level, + freelist); + } + next: +- pfn += level_size(level); ++ pfn = level_pfn + level_size(level); + } while (!first_pte_in_page(++pte) && pfn <= last_pfn); + + if (first_pte) +@@ -2649,7 +2651,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, + spin_unlock_irqrestore(&device_domain_lock, flags); + + /* PASID table is mandatory for a PCI device in scalable mode. */ +- if (dev && dev_is_pci(dev) && sm_supported(iommu)) { ++ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { + ret = intel_pasid_alloc_table(dev); + if (ret) { + dev_err(dev, "PASID table allocation failed\n"); +diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c +index f912fe45bea2c..a673195978843 100644 +--- a/drivers/iommu/intel/irq_remapping.c ++++ b/drivers/iommu/intel/irq_remapping.c +@@ -569,9 +569,8 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) + fn, &intel_ir_domain_ops, + iommu); + if (!iommu->ir_domain) { +- irq_domain_free_fwnode(fn); + pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id); +- goto out_free_bitmap; ++ goto out_free_fwnode; + } + iommu->ir_msi_domain = + arch_create_remap_msi_irq_domain(iommu->ir_domain, +@@ -595,7 +594,7 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) + + if (dmar_enable_qi(iommu)) { + pr_err("Failed to enable queued invalidation\n"); +- goto out_free_bitmap; ++ goto out_free_ir_domain; + } + } + +@@ -619,6 +618,14 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) + + return 0; + ++out_free_ir_domain: ++ if (iommu->ir_msi_domain) ++ irq_domain_remove(iommu->ir_msi_domain); ++ iommu->ir_msi_domain = NULL; ++ irq_domain_remove(iommu->ir_domain); ++ iommu->ir_domain = NULL; ++out_free_fwnode: ++ irq_domain_free_fwnode(fn); + out_free_bitmap: + bitmap_free(bitmap); + out_free_pages: +diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c +index bfb6acb651e5f..be066c1503d37 100644 +--- a/drivers/iommu/io-pgtable-arm-v7s.c ++++ b/drivers/iommu/io-pgtable-arm-v7s.c +@@ -246,13 +246,17 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, + __GFP_ZERO | ARM_V7S_TABLE_GFP_DMA, get_order(size)); + else if (lvl == 2) + table = kmem_cache_zalloc(data->l2_tables, gfp); ++ ++ if (!table) ++ return NULL; ++ + phys = virt_to_phys(table); + if (phys != (arm_v7s_iopte)phys) { + /* Doesn't fit in PTE */ + dev_err(dev, "Page table does not fit in PTE: %pa", &phys); + goto out_free; + } +- if (table && !cfg->coherent_walk) { ++ if (!cfg->coherent_walk) { + dma = dma_map_single(dev, table, size, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma)) + goto out_free; +diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c +index dd9e47189d0d9..94ff319ae8acc 100644 +--- a/drivers/iommu/io-pgtable-arm.c ++++ b/drivers/iommu/io-pgtable-arm.c +@@ -315,11 +315,12 @@ static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data, + static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table, + arm_lpae_iopte *ptep, + arm_lpae_iopte curr, +- struct io_pgtable_cfg *cfg) ++ struct arm_lpae_io_pgtable *data) + { + arm_lpae_iopte old, new; ++ struct io_pgtable_cfg *cfg = &data->iop.cfg; + +- new = __pa(table) | ARM_LPAE_PTE_TYPE_TABLE; ++ new = paddr_to_iopte(__pa(table), data) | ARM_LPAE_PTE_TYPE_TABLE; + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS) + new |= ARM_LPAE_PTE_NSTABLE; + +@@ -380,7 +381,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova, + if (!cptep) + return -ENOMEM; + +- pte = arm_lpae_install_table(cptep, ptep, 0, cfg); ++ pte = arm_lpae_install_table(cptep, ptep, 0, data); + if (pte) + __arm_lpae_free_pages(cptep, tblsz, cfg); + } else if (!cfg->coherent_walk && !(pte & ARM_LPAE_PTE_SW_SYNC)) { +@@ -592,7 +593,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data, + __arm_lpae_init_pte(data, blk_paddr, pte, lvl, 1, &tablep[i]); + } + +- pte = arm_lpae_install_table(tablep, ptep, blk_pte, cfg); ++ pte = arm_lpae_install_table(tablep, ptep, blk_pte, data); + if (pte != blk_pte) { + __arm_lpae_free_pages(tablep, tablesz, cfg); + /* +diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c +index 3303d707bab4b..7f409e9eea4b7 100644 +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -206,9 +206,14 @@ static struct dev_iommu *dev_iommu_get(struct device *dev) + + static void dev_iommu_free(struct device *dev) + { +- iommu_fwspec_free(dev); +- kfree(dev->iommu); ++ struct dev_iommu *param = dev->iommu; ++ + dev->iommu = NULL; ++ if (param->fwspec) { ++ fwnode_handle_put(param->fwspec->iommu_fwnode); ++ kfree(param->fwspec); ++ } ++ kfree(param); + } + + static int __iommu_probe_device(struct device *dev, struct list_head *group_list) +@@ -287,11 +292,11 @@ int iommu_probe_device(struct device *dev) + */ + mutex_lock(&group->mutex); + iommu_alloc_default_domain(group, dev); +- mutex_unlock(&group->mutex); + + if (group->default_domain) { + ret = __iommu_attach_device(group->default_domain, dev); + if (ret) { ++ mutex_unlock(&group->mutex); + iommu_group_put(group); + goto err_release; + } +@@ -299,6 +304,7 @@ int iommu_probe_device(struct device *dev) + + iommu_create_device_direct_mappings(group, dev); + ++ mutex_unlock(&group->mutex); + iommu_group_put(group); + + if (ops->probe_finalize) +diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c +index 9e8bc802ac053..920fcc27c9a1e 100644 +--- a/drivers/iommu/iova.c ++++ b/drivers/iommu/iova.c +@@ -83,8 +83,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad) + if (!has_iova_flush_queue(iovad)) + return; + +- if (timer_pending(&iovad->fq_timer)) +- del_timer(&iovad->fq_timer); ++ del_timer_sync(&iovad->fq_timer); + + fq_destroy_all_entries(iovad); + +diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c +index d837adfd1da55..25b834104790c 100644 +--- a/drivers/iommu/mtk_iommu.c ++++ b/drivers/iommu/mtk_iommu.c +@@ -550,7 +550,9 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, + phys_addr_t pa; + + pa = dom->iop->iova_to_phys(dom->iop, iova); +- if (dom->data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE) ++ if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) && ++ dom->data->enable_4GB && ++ pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE) + pa &= ~BIT_ULL(32); + + return pa; +diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c +index 5cb260820eda6..7f23ad61c094f 100644 +--- a/drivers/iommu/rockchip-iommu.c ++++ b/drivers/iommu/rockchip-iommu.c +@@ -200,8 +200,8 @@ static inline phys_addr_t rk_dte_pt_address(u32 dte) + #define DTE_HI_MASK2 GENMASK(7, 4) + #define DTE_HI_SHIFT1 24 /* shift bit 8 to bit 32 */ + #define DTE_HI_SHIFT2 32 /* shift bit 4 to bit 36 */ +-#define PAGE_DESC_HI_MASK1 GENMASK_ULL(39, 36) +-#define PAGE_DESC_HI_MASK2 GENMASK_ULL(35, 32) ++#define PAGE_DESC_HI_MASK1 GENMASK_ULL(35, 32) ++#define PAGE_DESC_HI_MASK2 GENMASK_ULL(39, 36) + + static inline phys_addr_t rk_dte_pt_address_v2(u32 dte) + { +diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c +index 0a281833f6117..abbdaeb4bf8f1 100644 +--- a/drivers/iommu/tegra-smmu.c ++++ b/drivers/iommu/tegra-smmu.c +@@ -808,8 +808,10 @@ static struct tegra_smmu *tegra_smmu_find(struct device_node *np) + return NULL; + + mc = platform_get_drvdata(pdev); +- if (!mc) ++ if (!mc) { ++ put_device(&pdev->dev); + return NULL; ++ } + + return mc->smmu; + } +diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c +index 53e0fb0562c11..c91ddb0cf1448 100644 +--- a/drivers/irqchip/irq-armada-370-xp.c ++++ b/drivers/irqchip/irq-armada-370-xp.c +@@ -232,16 +232,12 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, + int hwirq, i; + + mutex_lock(&msi_used_lock); ++ hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR, ++ order_base_2(nr_irqs)); ++ mutex_unlock(&msi_used_lock); + +- hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR, +- 0, nr_irqs, 0); +- if (hwirq >= PCI_MSI_DOORBELL_NR) { +- mutex_unlock(&msi_used_lock); ++ if (hwirq < 0) + return -ENOSPC; +- } +- +- bitmap_set(msi_used, hwirq, nr_irqs); +- mutex_unlock(&msi_used_lock); + + for (i = 0; i < nr_irqs; i++) { + irq_domain_set_info(domain, virq + i, hwirq + i, +@@ -250,7 +246,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, + NULL, NULL); + } + +- return hwirq; ++ return 0; + } + + static void armada_370_xp_msi_free(struct irq_domain *domain, +@@ -259,7 +255,7 @@ static void armada_370_xp_msi_free(struct irq_domain *domain, + struct irq_data *d = irq_domain_get_irq_data(domain, virq); + + mutex_lock(&msi_used_lock); +- bitmap_clear(msi_used, d->hwirq, nr_irqs); ++ bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs)); + mutex_unlock(&msi_used_lock); + } + +diff --git a/drivers/irqchip/irq-aspeed-scu-ic.c b/drivers/irqchip/irq-aspeed-scu-ic.c +index f3c6855a4cefb..18b77c3e6db4b 100644 +--- a/drivers/irqchip/irq-aspeed-scu-ic.c ++++ b/drivers/irqchip/irq-aspeed-scu-ic.c +@@ -76,8 +76,8 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc) + generic_handle_domain_irq(scu_ic->irq_domain, + bit - scu_ic->irq_shift); + +- regmap_update_bits(scu_ic->scu, scu_ic->reg, mask, +- BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); ++ regmap_write_bits(scu_ic->scu, scu_ic->reg, mask, ++ BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); + } + + chained_irq_exit(chip, desc); +diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c +index e3483789f4df3..1bd0621c4ce2a 100644 +--- a/drivers/irqchip/irq-bcm6345-l1.c ++++ b/drivers/irqchip/irq-bcm6345-l1.c +@@ -140,7 +140,7 @@ static void bcm6345_l1_irq_handle(struct irq_desc *desc) + for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { + irq = irq_linear_revmap(intc->domain, base + hwirq); + if (irq) +- do_IRQ(irq); ++ generic_handle_irq(irq); + else + spurious_interrupt(); + } +diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c +index eb0882d153666..0cb584d9815b9 100644 +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -742,7 +742,7 @@ static struct its_collection *its_build_invall_cmd(struct its_node *its, + + its_fixup_cmd(cmd); + +- return NULL; ++ return desc->its_invall_cmd.col; + } + + static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, +diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c +index fd4e9a37fea67..7bbccb13b896b 100644 +--- a/drivers/irqchip/irq-gic-v3.c ++++ b/drivers/irqchip/irq-gic-v3.c +@@ -920,6 +920,22 @@ static int __gic_update_rdist_properties(struct redist_region *region, + { + u64 typer = gic_read_typer(ptr + GICR_TYPER); + ++ /* Boot-time cleanip */ ++ if ((typer & GICR_TYPER_VLPIS) && (typer & GICR_TYPER_RVPEID)) { ++ u64 val; ++ ++ /* Deactivate any present vPE */ ++ val = gicr_read_vpendbaser(ptr + SZ_128K + GICR_VPENDBASER); ++ if (val & GICR_VPENDBASER_Valid) ++ gicr_write_vpendbaser(GICR_VPENDBASER_PendingLast, ++ ptr + SZ_128K + GICR_VPENDBASER); ++ ++ /* Mark the VPE table as invalid */ ++ val = gicr_read_vpropbaser(ptr + SZ_128K + GICR_VPROPBASER); ++ val &= ~GICR_VPROPBASER_4_1_VALID; ++ gicr_write_vpropbaser(val, ptr + SZ_128K + GICR_VPROPBASER); ++ } ++ + gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS); + + /* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */ +diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c +index b31c4cff4d3a5..599bb6fc5f0a2 100644 +--- a/drivers/irqchip/irq-nvic.c ++++ b/drivers/irqchip/irq-nvic.c +@@ -26,7 +26,7 @@ + + #define NVIC_ISER 0x000 + #define NVIC_ICER 0x080 +-#define NVIC_IPR 0x300 ++#define NVIC_IPR 0x400 + + #define NVIC_MAX_BANKS 16 + /* +diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c +index fd9f275592d29..50a56820c99bc 100644 +--- a/drivers/irqchip/irq-realtek-rtl.c ++++ b/drivers/irqchip/irq-realtek-rtl.c +@@ -62,7 +62,7 @@ static struct irq_chip realtek_ictl_irq = { + + static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) + { +- irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq); ++ irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq); + + return 0; + } +@@ -76,16 +76,20 @@ static void realtek_irq_dispatch(struct irq_desc *desc) + { + struct irq_chip *chip = irq_desc_get_chip(desc); + struct irq_domain *domain; +- unsigned int pending; ++ unsigned long pending; ++ unsigned int soc_int; + + chained_irq_enter(chip, desc); + pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR)); ++ + if (unlikely(!pending)) { + spurious_interrupt(); + goto out; + } ++ + domain = irq_desc_get_handler_data(desc); +- generic_handle_domain_irq(domain, __ffs(pending)); ++ for_each_set_bit(soc_int, &pending, 32) ++ generic_handle_domain_irq(domain, soc_int); + + out: + chained_irq_exit(chip, desc); +@@ -95,7 +99,8 @@ out: + * SoC interrupts are cascaded to MIPS CPU interrupts according to the + * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for + * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts +- * thus go into 4 IRRs. ++ * thus go into 4 IRRs. A routing value of '0' means the interrupt is left ++ * disconnected. Routing values {1..15} connect to output lines {0..14}. + */ + static int __init map_interrupts(struct device_node *node, struct irq_domain *domain) + { +@@ -134,7 +139,7 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do + of_node_put(cpu_ictl); + + cpu_int = be32_to_cpup(imap + 2); +- if (cpu_int > 7) ++ if (cpu_int > 7 || cpu_int < 2) + return -EINVAL; + + if (!(mips_irqs_set & BIT(cpu_int))) { +@@ -143,7 +148,8 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do + mips_irqs_set |= BIT(cpu_int); + } + +- regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32; ++ /* Use routing values (1..6) for CPU interrupts (2..7) */ ++ regs[(soc_int * 4) / 32] |= (cpu_int - 1) << (soc_int * 4) % 32; + imap += 3; + } + +diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c +index cf74cfa820453..09cc98266d30f 100644 +--- a/drivers/irqchip/irq-sifive-plic.c ++++ b/drivers/irqchip/irq-sifive-plic.c +@@ -163,7 +163,13 @@ static void plic_irq_eoi(struct irq_data *d) + { + struct plic_handler *handler = this_cpu_ptr(&plic_handlers); + +- writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); ++ if (irqd_irq_masked(d)) { ++ plic_irq_unmask(d); ++ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); ++ plic_irq_mask(d); ++ } else { ++ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); ++ } + } + + static struct irq_chip plic_chip = { +@@ -392,3 +398,4 @@ out_free_priv: + + IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init); + IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */ ++IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_init); /* for firmware driver */ +diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c +index 55891e4204460..a41b4b2645941 100644 +--- a/drivers/isdn/mISDN/core.c ++++ b/drivers/isdn/mISDN/core.c +@@ -381,7 +381,7 @@ mISDNInit(void) + err = mISDN_inittimer(&debug); + if (err) + goto error2; +- err = l1_init(&debug); ++ err = Isdnl1_Init(&debug); + if (err) + goto error3; + err = Isdnl2_Init(&debug); +@@ -395,7 +395,7 @@ mISDNInit(void) + error5: + Isdnl2_cleanup(); + error4: +- l1_cleanup(); ++ Isdnl1_cleanup(); + error3: + mISDN_timer_cleanup(); + error2: +@@ -408,7 +408,7 @@ static void mISDN_cleanup(void) + { + misdn_sock_cleanup(); + Isdnl2_cleanup(); +- l1_cleanup(); ++ Isdnl1_cleanup(); + mISDN_timer_cleanup(); + class_unregister(&mISDN_class); + +diff --git a/drivers/isdn/mISDN/core.h b/drivers/isdn/mISDN/core.h +index 23b44d3033279..42599f49c189d 100644 +--- a/drivers/isdn/mISDN/core.h ++++ b/drivers/isdn/mISDN/core.h +@@ -60,8 +60,8 @@ struct Bprotocol *get_Bprotocol4id(u_int); + extern int mISDN_inittimer(u_int *); + extern void mISDN_timer_cleanup(void); + +-extern int l1_init(u_int *); +-extern void l1_cleanup(void); ++extern int Isdnl1_Init(u_int *); ++extern void Isdnl1_cleanup(void); + extern int Isdnl2_Init(u_int *); + extern void Isdnl2_cleanup(void); + +diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c +index 98a3bc6c17009..7b31c25a550e3 100644 +--- a/drivers/isdn/mISDN/layer1.c ++++ b/drivers/isdn/mISDN/layer1.c +@@ -398,7 +398,7 @@ create_l1(struct dchannel *dch, dchannel_l1callback *dcb) { + EXPORT_SYMBOL(create_l1); + + int +-l1_init(u_int *deb) ++Isdnl1_Init(u_int *deb) + { + debug = deb; + l1fsm_s.state_count = L1S_STATE_COUNT; +@@ -409,7 +409,7 @@ l1_init(u_int *deb) + } + + void +-l1_cleanup(void) ++Isdnl1_cleanup(void) + { + mISDN_FsmFree(&l1fsm_s); + } +diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c +index d1657c46ee2f8..9fdfc1b9a1a0c 100644 +--- a/drivers/leds/leds-lp55xx-common.c ++++ b/drivers/leds/leds-lp55xx-common.c +@@ -439,6 +439,8 @@ int lp55xx_init_device(struct lp55xx_chip *chip) + return -EINVAL; + + if (pdata->enable_gpiod) { ++ gpiod_direction_output(pdata->enable_gpiod, 0); ++ + gpiod_set_consumer_name(pdata->enable_gpiod, "LP55xx enable"); + gpiod_set_value(pdata->enable_gpiod, 0); + usleep_range(1000, 2000); /* Keep enable down at least 1ms */ +@@ -694,7 +696,7 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev, + of_property_read_u8(np, "clock-mode", &pdata->clock_mode); + + pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable", +- GPIOD_OUT_LOW); ++ GPIOD_ASIS); + if (IS_ERR(pdata->enable_gpiod)) + return ERR_CAST(pdata->enable_gpiod); + +diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c +index 0d6e2231a2c75..4e34854d12389 100644 +--- a/drivers/mailbox/mailbox-mpfs.c ++++ b/drivers/mailbox/mailbox-mpfs.c +@@ -232,7 +232,7 @@ static int mpfs_mbox_probe(struct platform_device *pdev) + } + + static const struct of_device_id mpfs_mbox_of_match[] = { +- {.compatible = "microchip,polarfire-soc-mailbox", }, ++ {.compatible = "microchip,mpfs-mailbox", }, + {}, + }; + MODULE_DEVICE_TABLE(of, mpfs_mbox_of_match); +diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c +index 64175a893312e..3583c2aad0edc 100644 +--- a/drivers/mailbox/mtk-cmdq-mailbox.c ++++ b/drivers/mailbox/mtk-cmdq-mailbox.c +@@ -195,7 +195,6 @@ static void cmdq_task_exec_done(struct cmdq_task *task, int sta) + struct cmdq_task_cb *cb = &task->pkt->async_cb; + struct cmdq_cb_data data; + +- WARN_ON(cb->cb == (cmdq_async_flush_cb)NULL); + data.sta = sta; + data.data = cb->data; + data.pkt = task->pkt; +@@ -532,7 +531,8 @@ static int cmdq_probe(struct platform_device *pdev) + struct device_node *phandle = dev->of_node; + struct device_node *node; + int alias_id = 0; +- char clk_name[4] = "gce"; ++ static const char * const clk_name = "gce"; ++ static const char * const clk_names[] = { "gce0", "gce1" }; + + cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); + if (!cmdq) +@@ -570,12 +570,9 @@ static int cmdq_probe(struct platform_device *pdev) + + if (cmdq->gce_num > 1) { + for_each_child_of_node(phandle->parent, node) { +- char clk_id[8]; +- + alias_id = of_alias_get_id(node, clk_name); +- if (alias_id < cmdq->gce_num) { +- snprintf(clk_id, sizeof(clk_id), "%s%d", clk_name, alias_id); +- cmdq->clocks[alias_id].id = clk_id; ++ if (alias_id >= 0 && alias_id < cmdq->gce_num) { ++ cmdq->clocks[alias_id].id = clk_names[alias_id]; + cmdq->clocks[alias_id].clk = of_clk_get(node, 0); + if (IS_ERR(cmdq->clocks[alias_id].clk)) { + dev_err(dev, "failed to get gce clk: %d\n", alias_id); +@@ -663,7 +660,7 @@ static const struct gce_plat gce_plat_v5 = { + .thread_nr = 24, + .shift = 3, + .control_by_sw = true, +- .gce_num = 2 ++ .gce_num = 1 + }; + + static const struct gce_plat gce_plat_v6 = { +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index 0595559de174a..183a58c893774 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -378,7 +378,7 @@ static void do_btree_node_write(struct btree *b) + struct bvec_iter_all iter_all; + + bio_for_each_segment_all(bv, b->bio, iter_all) { +- memcpy(bvec_virt(bv), addr, PAGE_SIZE); ++ memcpy(page_address(bv->bv_page), addr, PAGE_SIZE); + addr += PAGE_SIZE; + } + +diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c +index f2874c77ff797..3f72c0f40613d 100644 +--- a/drivers/md/bcache/super.c ++++ b/drivers/md/bcache/super.c +@@ -885,9 +885,9 @@ static void bcache_device_free(struct bcache_device *d) + bcache_device_detach(d); + + if (disk) { +- blk_cleanup_disk(disk); + ida_simple_remove(&bcache_device_idx, + first_minor_to_idx(disk->first_minor)); ++ blk_cleanup_disk(disk); + } + + bioset_exit(&d->bio_split); +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 76d9da49fda75..5f33700d12473 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -489,7 +489,7 @@ static void start_io_acct(struct dm_io *io) + struct mapped_device *md = io->md; + struct bio *bio = io->orig_bio; + +- io->start_time = bio_start_io_acct(bio); ++ bio_start_io_acct_time(bio, io->start_time); + if (unlikely(dm_stats_used(&md->stats))) + dm_stats_account_io(&md->stats, bio_data_dir(bio), + bio->bi_iter.bi_sector, bio_sectors(bio), +@@ -535,7 +535,7 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) + io->md = md; + spin_lock_init(&io->endio_lock); + +- start_io_acct(io); ++ io->start_time = jiffies; + + return io; + } +@@ -1514,9 +1514,6 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md, + ci->sector = bio->bi_iter.bi_sector; + } + +-#define __dm_part_stat_sub(part, field, subnd) \ +- (part_stat_get(part, field) -= (subnd)) +- + /* + * Entry point to split a bio into clones and submit them to the targets. + */ +@@ -1553,23 +1550,12 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md, + GFP_NOIO, &md->queue->bio_split); + ci.io->orig_bio = b; + +- /* +- * Adjust IO stats for each split, otherwise upon queue +- * reentry there will be redundant IO accounting. +- * NOTE: this is a stop-gap fix, a proper fix involves +- * significant refactoring of DM core's bio splitting +- * (by eliminating DM's splitting and just using bio_split) +- */ +- part_stat_lock(); +- __dm_part_stat_sub(dm_disk(md)->part0, +- sectors[op_stat_group(bio_op(bio))], ci.sector_count); +- part_stat_unlock(); +- + bio_chain(b, bio); + trace_block_split(b, bio->bi_iter.bi_sector); + ret = submit_bio_noacct(bio); + } + } ++ start_io_acct(ci.io); + + /* drop the extra reference count */ + dm_io_dec_pending(ci.io, errno_to_blk_status(error)); +@@ -1794,8 +1780,10 @@ static struct mapped_device *alloc_dev(int minor) + if (IS_ENABLED(CONFIG_DAX_DRIVER)) { + md->dax_dev = alloc_dax(md, md->disk->disk_name, + &dm_dax_ops, 0); +- if (IS_ERR(md->dax_dev)) ++ if (IS_ERR(md->dax_dev)) { ++ md->dax_dev = NULL; + goto bad; ++ } + } + + format_dev_t(md->name, MKDEV(_major, minor)); +@@ -2168,7 +2156,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait) + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); + +- blk_set_queue_dying(md->queue); ++ blk_mark_disk_dead(md->disk); + + /* + * Take suspend_lock so that presuspend and postsuspend methods +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 6c0c3d0d905aa..2d31a079be33f 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -2193,6 +2193,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) + + if (!num_sectors || num_sectors > max_sectors) + num_sectors = max_sectors; ++ rdev->sb_start = sb_start; + } + sb = page_address(rdev->sb_page); + sb->data_size = cpu_to_le64(num_sectors); +@@ -2976,7 +2977,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + * -write_error - clears WriteErrorSeen + * {,-}failfast - set/clear FailFast + */ ++ ++ struct mddev *mddev = rdev->mddev; + int err = -EINVAL; ++ bool need_update_sb = false; ++ + if (cmd_match(buf, "faulty") && rdev->mddev->pers) { + md_error(rdev->mddev, rdev); + if (test_bit(Faulty, &rdev->flags)) +@@ -2991,7 +2996,6 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + if (rdev->raid_disk >= 0) + err = -EBUSY; + else { +- struct mddev *mddev = rdev->mddev; + err = 0; + if (mddev_is_clustered(mddev)) + err = md_cluster_ops->remove_disk(mddev, rdev); +@@ -3008,10 +3012,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + } else if (cmd_match(buf, "writemostly")) { + set_bit(WriteMostly, &rdev->flags); + mddev_create_serial_pool(rdev->mddev, rdev, false); ++ need_update_sb = true; + err = 0; + } else if (cmd_match(buf, "-writemostly")) { + mddev_destroy_serial_pool(rdev->mddev, rdev, false); + clear_bit(WriteMostly, &rdev->flags); ++ need_update_sb = true; + err = 0; + } else if (cmd_match(buf, "blocked")) { + set_bit(Blocked, &rdev->flags); +@@ -3037,9 +3043,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + err = 0; + } else if (cmd_match(buf, "failfast")) { + set_bit(FailFast, &rdev->flags); ++ need_update_sb = true; + err = 0; + } else if (cmd_match(buf, "-failfast")) { + clear_bit(FailFast, &rdev->flags); ++ need_update_sb = true; + err = 0; + } else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0 && + !test_bit(Journal, &rdev->flags)) { +@@ -3118,6 +3126,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) + clear_bit(ExternalBbl, &rdev->flags); + err = 0; + } ++ if (need_update_sb) ++ md_update_sb(mddev, 1); + if (!err) + sysfs_notify_dirent_safe(rdev->sysfs_state); + return err ? err : len; +@@ -5862,13 +5872,6 @@ int md_run(struct mddev *mddev) + if (err) + goto exit_bio_set; + } +- if (mddev->level != 1 && mddev->level != 10 && +- !bioset_initialized(&mddev->io_acct_set)) { +- err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE, +- offsetof(struct md_io_acct, bio_clone), 0); +- if (err) +- goto exit_sync_set; +- } + + spin_lock(&pers_lock); + pers = find_pers(mddev->level, mddev->clevel); +@@ -6045,9 +6048,6 @@ bitmap_abort: + module_put(pers->owner); + md_bitmap_destroy(mddev); + abort: +- if (mddev->level != 1 && mddev->level != 10) +- bioset_exit(&mddev->io_acct_set); +-exit_sync_set: + bioset_exit(&mddev->sync_set); + exit_bio_set: + bioset_exit(&mddev->bio_set); +@@ -8580,6 +8580,23 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev, + } + EXPORT_SYMBOL_GPL(md_submit_discard_bio); + ++int acct_bioset_init(struct mddev *mddev) ++{ ++ int err = 0; ++ ++ if (!bioset_initialized(&mddev->io_acct_set)) ++ err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE, ++ offsetof(struct md_io_acct, bio_clone), 0); ++ return err; ++} ++EXPORT_SYMBOL_GPL(acct_bioset_init); ++ ++void acct_bioset_exit(struct mddev *mddev) ++{ ++ bioset_exit(&mddev->io_acct_set); ++} ++EXPORT_SYMBOL_GPL(acct_bioset_exit); ++ + static void md_end_io_acct(struct bio *bio) + { + struct md_io_acct *md_io_acct = bio->bi_private; +diff --git a/drivers/md/md.h b/drivers/md/md.h +index 4c96c36bd01a1..62852d7011457 100644 +--- a/drivers/md/md.h ++++ b/drivers/md/md.h +@@ -721,6 +721,8 @@ extern void md_error(struct mddev *mddev, struct md_rdev *rdev); + extern void md_finish_reshape(struct mddev *mddev); + void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev, + struct bio *bio, sector_t start, sector_t size); ++int acct_bioset_init(struct mddev *mddev); ++void acct_bioset_exit(struct mddev *mddev); + void md_account_bio(struct mddev *mddev, struct bio **bio); + + extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio); +diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c +index 70532335c7c7e..cb670f16e98e9 100644 +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -423,9 +423,9 @@ static int rebalance_children(struct shadow_spine *s, + + memcpy(n, dm_block_data(child), + dm_bm_block_size(dm_tm_get_bm(info->tm))); +- dm_tm_unlock(info->tm, child); + + dm_tm_dec(info->tm, dm_block_location(child)); ++ dm_tm_unlock(info->tm, child); + return 0; + } + +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index 0703ca7a7d9a4..5ce64e93aae74 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -81,14 +81,16 @@ void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + } + + static int insert_at(size_t value_size, struct btree_node *node, unsigned index, +- uint64_t key, void *value) +- __dm_written_to_disk(value) ++ uint64_t key, void *value) ++ __dm_written_to_disk(value) + { + uint32_t nr_entries = le32_to_cpu(node->header.nr_entries); ++ uint32_t max_entries = le32_to_cpu(node->header.max_entries); + __le64 key_le = cpu_to_le64(key); + + if (index > nr_entries || +- index >= le32_to_cpu(node->header.max_entries)) { ++ index >= max_entries || ++ nr_entries >= max_entries) { + DMERR("too many entries in btree node for insert"); + __dm_unbless_for_disk(value); + return -ENOMEM; +diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c +index 4a6a2a9b4eb49..bfbfa750e0160 100644 +--- a/drivers/md/persistent-data/dm-space-map-common.c ++++ b/drivers/md/persistent-data/dm-space-map-common.c +@@ -283,6 +283,11 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result) + struct disk_index_entry ie_disk; + struct dm_block *blk; + ++ if (b >= ll->nr_blocks) { ++ DMERR_LIMIT("metadata block out of bounds"); ++ return -EINVAL; ++ } ++ + b = do_div(index, ll->entries_per_block); + r = ll->load_ie(ll, index, &ie_disk); + if (r < 0) +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 62c8b6adac70e..b59a77b31b90d 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -356,7 +356,21 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks + return array_sectors; + } + +-static void raid0_free(struct mddev *mddev, void *priv); ++static void free_conf(struct mddev *mddev, struct r0conf *conf) ++{ ++ kfree(conf->strip_zone); ++ kfree(conf->devlist); ++ kfree(conf); ++ mddev->private = NULL; ++} ++ ++static void raid0_free(struct mddev *mddev, void *priv) ++{ ++ struct r0conf *conf = priv; ++ ++ free_conf(mddev, conf); ++ acct_bioset_exit(mddev); ++} + + static int raid0_run(struct mddev *mddev) + { +@@ -370,11 +384,16 @@ static int raid0_run(struct mddev *mddev) + if (md_check_no_bitmap(mddev)) + return -EINVAL; + ++ if (acct_bioset_init(mddev)) { ++ pr_err("md/raid0:%s: alloc acct bioset failed.\n", mdname(mddev)); ++ return -ENOMEM; ++ } ++ + /* if private is not null, we are here after takeover */ + if (mddev->private == NULL) { + ret = create_strip_zones(mddev, &conf); + if (ret < 0) +- return ret; ++ goto exit_acct_set; + mddev->private = conf; + } + conf = mddev->private; +@@ -413,17 +432,16 @@ static int raid0_run(struct mddev *mddev) + dump_zones(mddev); + + ret = md_integrity_register(mddev); ++ if (ret) ++ goto free; + + return ret; +-} + +-static void raid0_free(struct mddev *mddev, void *priv) +-{ +- struct r0conf *conf = priv; +- +- kfree(conf->strip_zone); +- kfree(conf->devlist); +- kfree(conf); ++free: ++ free_conf(mddev, conf); ++exit_acct_set: ++ acct_bioset_exit(mddev); ++ return ret; + } + + static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 19598bd38939d..9fa4794936426 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1502,6 +1502,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, + * allocate memory, or a reader on WriteMostly + * is waiting for behind writes to flush */ + if (bitmap && ++ test_bit(WriteMostly, &rdev->flags) && + (atomic_read(&bitmap->behind_writes) + < mddev->bitmap_info.max_write_behind) && + !waitqueue_active(&bitmap->behind_wait)) { +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 02ed53b20654c..b9d062f0a02b2 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -7446,12 +7446,19 @@ static int raid5_run(struct mddev *mddev) + struct md_rdev *rdev; + struct md_rdev *journal_dev = NULL; + sector_t reshape_offset = 0; +- int i; ++ int i, ret = 0; + long long min_offset_diff = 0; + int first = 1; + +- if (mddev_init_writes_pending(mddev) < 0) ++ if (acct_bioset_init(mddev)) { ++ pr_err("md/raid456:%s: alloc acct bioset failed.\n", mdname(mddev)); + return -ENOMEM; ++ } ++ ++ if (mddev_init_writes_pending(mddev) < 0) { ++ ret = -ENOMEM; ++ goto exit_acct_set; ++ } + + if (mddev->recovery_cp != MaxSector) + pr_notice("md/raid:%s: not clean -- starting background reconstruction\n", +@@ -7482,7 +7489,8 @@ static int raid5_run(struct mddev *mddev) + (mddev->bitmap_info.offset || mddev->bitmap_info.file)) { + pr_notice("md/raid:%s: array cannot have both journal and bitmap\n", + mdname(mddev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit_acct_set; + } + + if (mddev->reshape_position != MaxSector) { +@@ -7507,13 +7515,15 @@ static int raid5_run(struct mddev *mddev) + if (journal_dev) { + pr_warn("md/raid:%s: don't support reshape with journal - aborting.\n", + mdname(mddev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit_acct_set; + } + + if (mddev->new_level != mddev->level) { + pr_warn("md/raid:%s: unsupported reshape required - aborting.\n", + mdname(mddev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit_acct_set; + } + old_disks = mddev->raid_disks - mddev->delta_disks; + /* reshape_position must be on a new-stripe boundary, and one +@@ -7529,7 +7539,8 @@ static int raid5_run(struct mddev *mddev) + if (sector_div(here_new, chunk_sectors * new_data_disks)) { + pr_warn("md/raid:%s: reshape_position not on a stripe boundary\n", + mdname(mddev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit_acct_set; + } + reshape_offset = here_new * chunk_sectors; + /* here_new is the stripe we will write to */ +@@ -7551,7 +7562,8 @@ static int raid5_run(struct mddev *mddev) + else if (mddev->ro == 0) { + pr_warn("md/raid:%s: in-place reshape must be started in read-only mode - aborting\n", + mdname(mddev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit_acct_set; + } + } else if (mddev->reshape_backwards + ? (here_new * chunk_sectors + min_offset_diff <= +@@ -7561,7 +7573,8 @@ static int raid5_run(struct mddev *mddev) + /* Reading from the same stripe as writing to - bad */ + pr_warn("md/raid:%s: reshape_position too early for auto-recovery - aborting.\n", + mdname(mddev)); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit_acct_set; + } + pr_debug("md/raid:%s: reshape will continue\n", mdname(mddev)); + /* OK, we should be able to continue; */ +@@ -7585,8 +7598,10 @@ static int raid5_run(struct mddev *mddev) + else + conf = mddev->private; + +- if (IS_ERR(conf)) +- return PTR_ERR(conf); ++ if (IS_ERR(conf)) { ++ ret = PTR_ERR(conf); ++ goto exit_acct_set; ++ } + + if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) { + if (!journal_dev) { +@@ -7786,7 +7801,10 @@ abort: + free_conf(conf); + mddev->private = NULL; + pr_warn("md/raid:%s: failed to run raid set.\n", mdname(mddev)); +- return -EIO; ++ ret = -EIO; ++exit_acct_set: ++ acct_bioset_exit(mddev); ++ return ret; + } + + static void raid5_free(struct mddev *mddev, void *priv) +@@ -7794,6 +7812,7 @@ static void raid5_free(struct mddev *mddev, void *priv) + struct r5conf *conf = priv; + + free_conf(conf); ++ acct_bioset_exit(mddev); + mddev->to_remove = &raid5_attrs_group; + } + +diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig +index b07812657cee6..f3f24c63536b6 100644 +--- a/drivers/media/Kconfig ++++ b/drivers/media/Kconfig +@@ -141,10 +141,10 @@ config MEDIA_TEST_SUPPORT + prompt "Test drivers" if MEDIA_SUPPORT_FILTER + default y if !MEDIA_SUPPORT_FILTER + help +- Those drivers should not be used on production Kernels, but +- can be useful on debug ones. It enables several dummy drivers +- that simulate a real hardware. Very useful to test userspace +- applications and to validate if the subsystem core is doesn't ++ These drivers should not be used on production kernels, but ++ can be useful on debug ones. This option enables several dummy drivers ++ that simulate real hardware. Very useful to test userspace ++ applications and to validate if the subsystem core doesn't + have regressions. + + Say Y if you want to use some virtual test driver. +diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c +index 79fa36de8a04a..1f599e300e42e 100644 +--- a/drivers/media/cec/core/cec-adap.c ++++ b/drivers/media/cec/core/cec-adap.c +@@ -161,10 +161,10 @@ static void cec_queue_event(struct cec_adapter *adap, + u64 ts = ktime_get_ns(); + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, ev, ts); +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + + /* Notify userspace that the CEC pin changed state at the given time. */ +@@ -178,11 +178,12 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, + }; + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); +- list_for_each_entry(fh, &adap->devnode.fhs, list) ++ mutex_lock(&adap->devnode.lock_fhs); ++ list_for_each_entry(fh, &adap->devnode.fhs, list) { + if (fh->mode_follower == CEC_MODE_MONITOR_PIN) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); +- mutex_unlock(&adap->devnode.lock); ++ } ++ mutex_unlock(&adap->devnode.lock_fhs); + } + EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event); + +@@ -195,10 +196,10 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts) + }; + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event); + +@@ -211,10 +212,10 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts) + }; + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) + cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event); + +@@ -286,12 +287,12 @@ static void cec_queue_msg_monitor(struct cec_adapter *adap, + u32 monitor_mode = valid_la ? CEC_MODE_MONITOR : + CEC_MODE_MONITOR_ALL; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) { + if (fh->mode_follower >= monitor_mode) + cec_queue_msg_fh(fh, msg); + } +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + + /* +@@ -302,12 +303,12 @@ static void cec_queue_msg_followers(struct cec_adapter *adap, + { + struct cec_fh *fh; + +- mutex_lock(&adap->devnode.lock); ++ mutex_lock(&adap->devnode.lock_fhs); + list_for_each_entry(fh, &adap->devnode.fhs, list) { + if (fh->mode_follower == CEC_MODE_FOLLOWER) + cec_queue_msg_fh(fh, msg); + } +- mutex_unlock(&adap->devnode.lock); ++ mutex_unlock(&adap->devnode.lock_fhs); + } + + /* Notify userspace of an adapter state change. */ +@@ -1199,6 +1200,7 @@ void cec_received_msg_ts(struct cec_adapter *adap, + if (abort) + dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT; + msg->flags = dst->flags; ++ msg->sequence = dst->sequence; + /* Remove it from the wait_queue */ + list_del_init(&data->list); + +@@ -1572,6 +1574,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + /* Disabling monitor all mode should always succeed */ + if (adap->monitor_all_cnt) + WARN_ON(call_op(adap, adap_monitor_all_enable, false)); ++ /* serialize adap_enable */ + mutex_lock(&adap->devnode.lock); + if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { + WARN_ON(adap->ops->adap_enable(adap, false)); +@@ -1583,14 +1586,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + return; + } + ++ /* serialize adap_enable */ + mutex_lock(&adap->devnode.lock); + adap->last_initiator = 0xff; + adap->transmit_in_progress = false; + +- if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && +- adap->ops->adap_enable(adap, true)) { +- mutex_unlock(&adap->devnode.lock); +- return; ++ if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) { ++ if (adap->ops->adap_enable(adap, true)) { ++ mutex_unlock(&adap->devnode.lock); ++ return; ++ } + } + + if (adap->monitor_all_cnt && +diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c +index 769e6b4cddce3..52c30e4e20055 100644 +--- a/drivers/media/cec/core/cec-api.c ++++ b/drivers/media/cec/core/cec-api.c +@@ -586,6 +586,7 @@ static int cec_open(struct inode *inode, struct file *filp) + return err; + } + ++ /* serialize adap_enable */ + mutex_lock(&devnode->lock); + if (list_empty(&devnode->fhs) && + !adap->needs_hpd && +@@ -624,7 +625,9 @@ static int cec_open(struct inode *inode, struct file *filp) + } + #endif + ++ mutex_lock(&devnode->lock_fhs); + list_add(&fh->list, &devnode->fhs); ++ mutex_unlock(&devnode->lock_fhs); + mutex_unlock(&devnode->lock); + + return 0; +@@ -653,8 +656,11 @@ static int cec_release(struct inode *inode, struct file *filp) + cec_monitor_all_cnt_dec(adap); + mutex_unlock(&adap->lock); + ++ /* serialize adap_enable */ + mutex_lock(&devnode->lock); ++ mutex_lock(&devnode->lock_fhs); + list_del(&fh->list); ++ mutex_unlock(&devnode->lock_fhs); + if (cec_is_registered(adap) && list_empty(&devnode->fhs) && + !adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) { + WARN_ON(adap->ops->adap_enable(adap, false)); +diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c +index 551689d371a71..ec67065d52021 100644 +--- a/drivers/media/cec/core/cec-core.c ++++ b/drivers/media/cec/core/cec-core.c +@@ -169,8 +169,10 @@ static void cec_devnode_unregister(struct cec_adapter *adap) + devnode->registered = false; + devnode->unregistered = true; + ++ mutex_lock(&devnode->lock_fhs); + list_for_each_entry(fh, &devnode->fhs, list) + wake_up_interruptible(&fh->wait); ++ mutex_unlock(&devnode->lock_fhs); + + mutex_unlock(&devnode->lock); + +@@ -272,6 +274,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, + + /* adap->devnode initialization */ + INIT_LIST_HEAD(&adap->devnode.fhs); ++ mutex_init(&adap->devnode.lock_fhs); + mutex_init(&adap->devnode.lock); + + adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name); +diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c +index 8c613aa649c6f..0eb90cc0ffb0f 100644 +--- a/drivers/media/cec/core/cec-pin.c ++++ b/drivers/media/cec/core/cec-pin.c +@@ -1033,6 +1033,7 @@ static int cec_pin_thread_func(void *_adap) + { + struct cec_adapter *adap = _adap; + struct cec_pin *pin = adap->pin; ++ bool irq_enabled = false; + + for (;;) { + wait_event_interruptible(pin->kthread_waitq, +@@ -1060,6 +1061,7 @@ static int cec_pin_thread_func(void *_adap) + ns_to_ktime(pin->work_rx_msg.rx_ts)); + msg->len = 0; + } ++ + if (pin->work_tx_status) { + unsigned int tx_status = pin->work_tx_status; + +@@ -1083,27 +1085,39 @@ static int cec_pin_thread_func(void *_adap) + switch (atomic_xchg(&pin->work_irq_change, + CEC_PIN_IRQ_UNCHANGED)) { + case CEC_PIN_IRQ_DISABLE: +- pin->ops->disable_irq(adap); ++ if (irq_enabled) { ++ pin->ops->disable_irq(adap); ++ irq_enabled = false; ++ } + cec_pin_high(pin); + cec_pin_to_idle(pin); + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); + break; + case CEC_PIN_IRQ_ENABLE: ++ if (irq_enabled) ++ break; + pin->enable_irq_failed = !pin->ops->enable_irq(adap); + if (pin->enable_irq_failed) { + cec_pin_to_idle(pin); + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); ++ } else { ++ irq_enabled = true; + } + break; + default: + break; + } +- + if (kthread_should_stop()) + break; + } ++ if (pin->ops->disable_irq && irq_enabled) ++ pin->ops->disable_irq(adap); ++ hrtimer_cancel(&pin->timer); ++ cec_pin_read(pin); ++ cec_pin_to_idle(pin); ++ pin->state = CEC_ST_OFF; + return 0; + } + +@@ -1130,13 +1144,7 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable) + hrtimer_start(&pin->timer, ns_to_ktime(0), + HRTIMER_MODE_REL); + } else { +- if (pin->ops->disable_irq) +- pin->ops->disable_irq(adap); +- hrtimer_cancel(&pin->timer); + kthread_stop(pin->kthread); +- cec_pin_read(pin); +- cec_pin_to_idle(pin); +- pin->state = CEC_ST_OFF; + } + return 0; + } +@@ -1157,11 +1165,8 @@ void cec_pin_start_timer(struct cec_pin *pin) + if (pin->state != CEC_ST_RX_IRQ) + return; + +- atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED); +- pin->ops->disable_irq(pin->adap); +- cec_pin_high(pin); +- cec_pin_to_idle(pin); +- hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); ++ atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_DISABLE); ++ wake_up_interruptible(&pin->kthread_waitq); + } + + static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts, +diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c +index baf5772c52a96..be32159777142 100644 +--- a/drivers/media/common/saa7146/saa7146_fops.c ++++ b/drivers/media/common/saa7146/saa7146_fops.c +@@ -521,7 +521,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) + ERR("out of memory. aborting.\n"); + kfree(vv); + v4l2_ctrl_handler_free(hdl); +- return -1; ++ return -ENOMEM; + } + + saa7146_video_uops.init(dev,vv); +diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c +index 508ac295eb06e..033b0c83272fe 100644 +--- a/drivers/media/common/videobuf2/videobuf2-core.c ++++ b/drivers/media/common/videobuf2/videobuf2-core.c +@@ -68,13 +68,13 @@ module_param(debug, int, 0644); + err; \ + }) + +-#define call_ptr_memop(vb, op, args...) \ ++#define call_ptr_memop(op, vb, args...) \ + ({ \ + struct vb2_queue *_q = (vb)->vb2_queue; \ + void *ptr; \ + \ + log_memop(vb, op); \ +- ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL; \ ++ ptr = _q->mem_ops->op ? _q->mem_ops->op(vb, args) : NULL; \ + if (!IS_ERR_OR_NULL(ptr)) \ + (vb)->cnt_mem_ ## op++; \ + ptr; \ +@@ -144,9 +144,9 @@ module_param(debug, int, 0644); + ((vb)->vb2_queue->mem_ops->op ? \ + (vb)->vb2_queue->mem_ops->op(args) : 0) + +-#define call_ptr_memop(vb, op, args...) \ ++#define call_ptr_memop(op, vb, args...) \ + ((vb)->vb2_queue->mem_ops->op ? \ +- (vb)->vb2_queue->mem_ops->op(args) : NULL) ++ (vb)->vb2_queue->mem_ops->op(vb, args) : NULL) + + #define call_void_memop(vb, op, args...) \ + do { \ +@@ -230,9 +230,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) + if (size < vb->planes[plane].length) + goto free; + +- mem_priv = call_ptr_memop(vb, alloc, +- q->alloc_devs[plane] ? : q->dev, +- q->dma_attrs, size, q->dma_dir, q->gfp_flags); ++ mem_priv = call_ptr_memop(alloc, ++ vb, ++ q->alloc_devs[plane] ? : q->dev, ++ size); + if (IS_ERR_OR_NULL(mem_priv)) { + if (mem_priv) + ret = PTR_ERR(mem_priv); +@@ -975,7 +976,7 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) + if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) + return NULL; + +- return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv); ++ return call_ptr_memop(vaddr, vb, vb->planes[plane_no].mem_priv); + + } + EXPORT_SYMBOL_GPL(vb2_plane_vaddr); +@@ -985,7 +986,7 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) + if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) + return NULL; + +- return call_ptr_memop(vb, cookie, vb->planes[plane_no].mem_priv); ++ return call_ptr_memop(cookie, vb, vb->planes[plane_no].mem_priv); + } + EXPORT_SYMBOL_GPL(vb2_plane_cookie); + +@@ -1125,10 +1126,11 @@ static int __prepare_userptr(struct vb2_buffer *vb) + vb->planes[plane].data_offset = 0; + + /* Acquire each plane's memory */ +- mem_priv = call_ptr_memop(vb, get_userptr, +- q->alloc_devs[plane] ? : q->dev, +- planes[plane].m.userptr, +- planes[plane].length, q->dma_dir); ++ mem_priv = call_ptr_memop(get_userptr, ++ vb, ++ q->alloc_devs[plane] ? : q->dev, ++ planes[plane].m.userptr, ++ planes[plane].length); + if (IS_ERR(mem_priv)) { + dprintk(q, 1, "failed acquiring userspace memory for plane %d\n", + plane); +@@ -1249,9 +1251,11 @@ static int __prepare_dmabuf(struct vb2_buffer *vb) + vb->planes[plane].data_offset = 0; + + /* Acquire each plane's memory */ +- mem_priv = call_ptr_memop(vb, attach_dmabuf, +- q->alloc_devs[plane] ? : q->dev, +- dbuf, planes[plane].length, q->dma_dir); ++ mem_priv = call_ptr_memop(attach_dmabuf, ++ vb, ++ q->alloc_devs[plane] ? : q->dev, ++ dbuf, ++ planes[plane].length); + if (IS_ERR(mem_priv)) { + dprintk(q, 1, "failed to attach dmabuf\n"); + ret = PTR_ERR(mem_priv); +@@ -2187,8 +2191,10 @@ int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type, + + vb_plane = &vb->planes[plane]; + +- dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, +- flags & O_ACCMODE); ++ dbuf = call_ptr_memop(get_dmabuf, ++ vb, ++ vb_plane->mem_priv, ++ flags & O_ACCMODE); + if (IS_ERR_OR_NULL(dbuf)) { + dprintk(q, 1, "failed to export buffer %d, plane %d\n", + index, plane); +diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c +index a7f61ba854405..f8c65b0401054 100644 +--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c ++++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c +@@ -40,6 +40,8 @@ struct vb2_dc_buf { + + /* DMABUF related */ + struct dma_buf_attachment *db_attach; ++ ++ struct vb2_buffer *vb; + }; + + /*********************************************/ +@@ -66,14 +68,14 @@ static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt) + /* callbacks for all buffers */ + /*********************************************/ + +-static void *vb2_dc_cookie(void *buf_priv) ++static void *vb2_dc_cookie(struct vb2_buffer *vb, void *buf_priv) + { + struct vb2_dc_buf *buf = buf_priv; + + return &buf->dma_addr; + } + +-static void *vb2_dc_vaddr(void *buf_priv) ++static void *vb2_dc_vaddr(struct vb2_buffer *vb, void *buf_priv) + { + struct vb2_dc_buf *buf = buf_priv; + struct dma_buf_map map; +@@ -137,9 +139,9 @@ static void vb2_dc_put(void *buf_priv) + kfree(buf); + } + +-static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, +- unsigned long size, enum dma_data_direction dma_dir, +- gfp_t gfp_flags) ++static void *vb2_dc_alloc(struct vb2_buffer *vb, ++ struct device *dev, ++ unsigned long size) + { + struct vb2_dc_buf *buf; + +@@ -150,11 +152,12 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, + if (!buf) + return ERR_PTR(-ENOMEM); + +- buf->attrs = attrs; ++ buf->attrs = vb->vb2_queue->dma_attrs; + buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, +- GFP_KERNEL | gfp_flags, buf->attrs); ++ GFP_KERNEL | vb->vb2_queue->gfp_flags, ++ buf->attrs); + if (!buf->cookie) { +- dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); ++ dev_err(dev, "dma_alloc_coherent of size %lu failed\n", size); + kfree(buf); + return ERR_PTR(-ENOMEM); + } +@@ -165,11 +168,12 @@ static void *vb2_dc_alloc(struct device *dev, unsigned long attrs, + /* Prevent the device from being released while the buffer is used */ + buf->dev = get_device(dev); + buf->size = size; +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + + buf->handler.refcount = &buf->refcount; + buf->handler.put = vb2_dc_put; + buf->handler.arg = buf; ++ buf->vb = vb; + + refcount_set(&buf->refcount, 1); + +@@ -200,9 +204,9 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma) + + vma->vm_ops->open(vma); + +- pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n", +- __func__, (unsigned long)buf->dma_addr, vma->vm_start, +- buf->size); ++ pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %lu\n", ++ __func__, (unsigned long)buf->dma_addr, vma->vm_start, ++ buf->size); + + return 0; + } +@@ -397,7 +401,9 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) + return sgt; + } + +-static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags) ++static struct dma_buf *vb2_dc_get_dmabuf(struct vb2_buffer *vb, ++ void *buf_priv, ++ unsigned long flags) + { + struct vb2_dc_buf *buf = buf_priv; + struct dma_buf *dbuf; +@@ -459,8 +465,8 @@ static void vb2_dc_put_userptr(void *buf_priv) + kfree(buf); + } + +-static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, +- unsigned long size, enum dma_data_direction dma_dir) ++static void *vb2_dc_get_userptr(struct vb2_buffer *vb, struct device *dev, ++ unsigned long vaddr, unsigned long size) + { + struct vb2_dc_buf *buf; + struct frame_vector *vec; +@@ -490,7 +496,8 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, + return ERR_PTR(-ENOMEM); + + buf->dev = dev; +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; ++ buf->vb = vb; + + offset = lower_32_bits(offset_in_page(vaddr)); + vec = vb2_create_framevec(vaddr, size); +@@ -660,8 +667,8 @@ static void vb2_dc_detach_dmabuf(void *mem_priv) + kfree(buf); + } + +-static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, +- unsigned long size, enum dma_data_direction dma_dir) ++static void *vb2_dc_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, ++ struct dma_buf *dbuf, unsigned long size) + { + struct vb2_dc_buf *buf; + struct dma_buf_attachment *dba; +@@ -677,6 +684,8 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, + return ERR_PTR(-ENOMEM); + + buf->dev = dev; ++ buf->vb = vb; ++ + /* create attachment for the dmabuf with the user device */ + dba = dma_buf_attach(dbuf, buf->dev); + if (IS_ERR(dba)) { +@@ -685,7 +694,7 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, + return dba; + } + +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + buf->size = size; + buf->db_attach = dba; + +diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c +index c5b06a5095661..0d6389dd9b0c6 100644 +--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c ++++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c +@@ -51,6 +51,8 @@ struct vb2_dma_sg_buf { + struct vb2_vmarea_handler handler; + + struct dma_buf_attachment *db_attach; ++ ++ struct vb2_buffer *vb; + }; + + static void vb2_dma_sg_put(void *buf_priv); +@@ -96,9 +98,8 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf, + return 0; + } + +-static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, +- unsigned long size, enum dma_data_direction dma_dir, +- gfp_t gfp_flags) ++static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev, ++ unsigned long size) + { + struct vb2_dma_sg_buf *buf; + struct sg_table *sgt; +@@ -113,7 +114,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, + return ERR_PTR(-ENOMEM); + + buf->vaddr = NULL; +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + buf->offset = 0; + buf->size = size; + /* size is already page aligned */ +@@ -130,7 +131,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, + if (!buf->pages) + goto fail_pages_array_alloc; + +- ret = vb2_dma_sg_alloc_compacted(buf, gfp_flags); ++ ret = vb2_dma_sg_alloc_compacted(buf, vb->vb2_queue->gfp_flags); + if (ret) + goto fail_pages_alloc; + +@@ -154,6 +155,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs, + buf->handler.refcount = &buf->refcount; + buf->handler.put = vb2_dma_sg_put; + buf->handler.arg = buf; ++ buf->vb = vb; + + refcount_set(&buf->refcount, 1); + +@@ -213,9 +215,8 @@ static void vb2_dma_sg_finish(void *buf_priv) + dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir); + } + +-static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, +- unsigned long size, +- enum dma_data_direction dma_dir) ++static void *vb2_dma_sg_get_userptr(struct vb2_buffer *vb, struct device *dev, ++ unsigned long vaddr, unsigned long size) + { + struct vb2_dma_sg_buf *buf; + struct sg_table *sgt; +@@ -230,10 +231,11 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr, + + buf->vaddr = NULL; + buf->dev = dev; +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + buf->offset = vaddr & ~PAGE_MASK; + buf->size = size; + buf->dma_sgt = &buf->sg_table; ++ buf->vb = vb; + vec = vb2_create_framevec(vaddr, size); + if (IS_ERR(vec)) + goto userptr_fail_pfnvec; +@@ -292,7 +294,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv) + kfree(buf); + } + +-static void *vb2_dma_sg_vaddr(void *buf_priv) ++static void *vb2_dma_sg_vaddr(struct vb2_buffer *vb, void *buf_priv) + { + struct vb2_dma_sg_buf *buf = buf_priv; + struct dma_buf_map map; +@@ -511,7 +513,9 @@ static const struct dma_buf_ops vb2_dma_sg_dmabuf_ops = { + .release = vb2_dma_sg_dmabuf_ops_release, + }; + +-static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags) ++static struct dma_buf *vb2_dma_sg_get_dmabuf(struct vb2_buffer *vb, ++ void *buf_priv, ++ unsigned long flags) + { + struct vb2_dma_sg_buf *buf = buf_priv; + struct dma_buf *dbuf; +@@ -605,8 +609,8 @@ static void vb2_dma_sg_detach_dmabuf(void *mem_priv) + kfree(buf); + } + +-static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, +- unsigned long size, enum dma_data_direction dma_dir) ++static void *vb2_dma_sg_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, ++ struct dma_buf *dbuf, unsigned long size) + { + struct vb2_dma_sg_buf *buf; + struct dma_buf_attachment *dba; +@@ -630,14 +634,15 @@ static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, + return dba; + } + +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + buf->size = size; + buf->db_attach = dba; ++ buf->vb = vb; + + return buf; + } + +-static void *vb2_dma_sg_cookie(void *buf_priv) ++static void *vb2_dma_sg_cookie(struct vb2_buffer *vb, void *buf_priv) + { + struct vb2_dma_sg_buf *buf = buf_priv; + +diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c +index 83f95258ec8c6..ef36abd912dcc 100644 +--- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c ++++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c +@@ -34,13 +34,12 @@ struct vb2_vmalloc_buf { + + static void vb2_vmalloc_put(void *buf_priv); + +-static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, +- unsigned long size, enum dma_data_direction dma_dir, +- gfp_t gfp_flags) ++static void *vb2_vmalloc_alloc(struct vb2_buffer *vb, struct device *dev, ++ unsigned long size) + { + struct vb2_vmalloc_buf *buf; + +- buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags); ++ buf = kzalloc(sizeof(*buf), GFP_KERNEL | vb->vb2_queue->gfp_flags); + if (!buf) + return ERR_PTR(-ENOMEM); + +@@ -52,7 +51,7 @@ static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, + return ERR_PTR(-ENOMEM); + } + +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + buf->handler.refcount = &buf->refcount; + buf->handler.put = vb2_vmalloc_put; + buf->handler.arg = buf; +@@ -71,9 +70,8 @@ static void vb2_vmalloc_put(void *buf_priv) + } + } + +-static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, +- unsigned long size, +- enum dma_data_direction dma_dir) ++static void *vb2_vmalloc_get_userptr(struct vb2_buffer *vb, struct device *dev, ++ unsigned long vaddr, unsigned long size) + { + struct vb2_vmalloc_buf *buf; + struct frame_vector *vec; +@@ -84,7 +82,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, + if (!buf) + return ERR_PTR(-ENOMEM); + +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + offset = vaddr & ~PAGE_MASK; + buf->size = size; + vec = vb2_create_framevec(vaddr, size); +@@ -147,7 +145,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) + kfree(buf); + } + +-static void *vb2_vmalloc_vaddr(void *buf_priv) ++static void *vb2_vmalloc_vaddr(struct vb2_buffer *vb, void *buf_priv) + { + struct vb2_vmalloc_buf *buf = buf_priv; + +@@ -339,7 +337,9 @@ static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = { + .release = vb2_vmalloc_dmabuf_ops_release, + }; + +-static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags) ++static struct dma_buf *vb2_vmalloc_get_dmabuf(struct vb2_buffer *vb, ++ void *buf_priv, ++ unsigned long flags) + { + struct vb2_vmalloc_buf *buf = buf_priv; + struct dma_buf *dbuf; +@@ -403,8 +403,10 @@ static void vb2_vmalloc_detach_dmabuf(void *mem_priv) + kfree(buf); + } + +-static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, +- unsigned long size, enum dma_data_direction dma_dir) ++static void *vb2_vmalloc_attach_dmabuf(struct vb2_buffer *vb, ++ struct device *dev, ++ struct dma_buf *dbuf, ++ unsigned long size) + { + struct vb2_vmalloc_buf *buf; + +@@ -416,7 +418,7 @@ static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, + return ERR_PTR(-ENOMEM); + + buf->dbuf = dbuf; +- buf->dma_dir = dma_dir; ++ buf->dma_dir = vb->vb2_queue->dma_dir; + buf->size = size; + + return buf; +diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c +index 5d5a48475a54f..01f288fa37e0e 100644 +--- a/drivers/media/dvb-core/dmxdev.c ++++ b/drivers/media/dvb-core/dmxdev.c +@@ -1413,7 +1413,7 @@ static const struct dvb_device dvbdev_dvr = { + }; + int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) + { +- int i; ++ int i, ret; + + if (dmxdev->demux->open(dmxdev->demux) < 0) + return -EUSERS; +@@ -1432,14 +1432,26 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) + DMXDEV_STATE_FREE); + } + +- dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, ++ ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, + DVB_DEVICE_DEMUX, dmxdev->filternum); +- dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, ++ if (ret < 0) ++ goto err_register_dvbdev; ++ ++ ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, + dmxdev, DVB_DEVICE_DVR, dmxdev->filternum); ++ if (ret < 0) ++ goto err_register_dvr_dvbdev; + + dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192); + + return 0; ++ ++err_register_dvr_dvbdev: ++ dvb_unregister_device(dmxdev->dvbdev); ++err_register_dvbdev: ++ vfree(dmxdev->filter); ++ dmxdev->filter = NULL; ++ return ret; + } + + EXPORT_SYMBOL(dvb_dmxdev_init); +diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c +index bb02354a48b81..d67f2dd997d06 100644 +--- a/drivers/media/dvb-frontends/dib8000.c ++++ b/drivers/media/dvb-frontends/dib8000.c +@@ -4473,8 +4473,10 @@ static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_ad + + state->timf_default = cfg->pll->timf; + +- if (dib8000_identify(&state->i2c) == 0) ++ if (dib8000_identify(&state->i2c) == 0) { ++ kfree(fe); + goto error; ++ } + + dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); + +diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c +index e4528784f8477..fff212c0bf3b5 100644 +--- a/drivers/media/dvb-frontends/mn88443x.c ++++ b/drivers/media/dvb-frontends/mn88443x.c +@@ -204,11 +204,18 @@ struct mn88443x_priv { + struct regmap *regmap_t; + }; + +-static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) ++static int mn88443x_cmn_power_on(struct mn88443x_priv *chip) + { ++ struct device *dev = &chip->client_s->dev; + struct regmap *r_t = chip->regmap_t; ++ int ret; + +- clk_prepare_enable(chip->mclk); ++ ret = clk_prepare_enable(chip->mclk); ++ if (ret) { ++ dev_err(dev, "Failed to prepare and enable mclk: %d\n", ++ ret); ++ return ret; ++ } + + gpiod_set_value_cansleep(chip->reset_gpio, 1); + usleep_range(100, 1000); +@@ -222,6 +229,8 @@ static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) + } else { + regmap_write(r_t, HIZSET3, 0x8f); + } ++ ++ return 0; + } + + static void mn88443x_cmn_power_off(struct mn88443x_priv *chip) +@@ -738,7 +747,10 @@ static int mn88443x_probe(struct i2c_client *client, + chip->fe.demodulator_priv = chip; + i2c_set_clientdata(client, chip); + +- mn88443x_cmn_power_on(chip); ++ ret = mn88443x_cmn_power_on(chip); ++ if (ret) ++ goto err_i2c_t; ++ + mn88443x_s_sleep(chip); + mn88443x_t_sleep(chip); + +diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c +index 2bf9467b917d1..71991f8638e6b 100644 +--- a/drivers/media/firewire/firedtv-avc.c ++++ b/drivers/media/firewire/firedtv-avc.c +@@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) + read_pos += program_info_length; + write_pos += program_info_length; + } +- while (read_pos < length) { ++ while (read_pos + 4 < length) { ++ if (write_pos + 4 >= sizeof(c->operand) - 4) { ++ ret = -EINVAL; ++ goto out; ++ } + c->operand[write_pos++] = msg[read_pos++]; + c->operand[write_pos++] = msg[read_pos++]; + c->operand[write_pos++] = msg[read_pos++]; +@@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) + c->operand[write_pos++] = es_info_length >> 8; + c->operand[write_pos++] = es_info_length & 0xff; + if (es_info_length > 0) { ++ if (read_pos >= length) { ++ ret = -EINVAL; ++ goto out; ++ } + pmt_cmd_id = msg[read_pos++]; + if (pmt_cmd_id != 1 && pmt_cmd_id != 4) + dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n", + pmt_cmd_id); + +- if (es_info_length > sizeof(c->operand) - 4 - +- write_pos) { ++ if (es_info_length > sizeof(c->operand) - 4 - write_pos || ++ es_info_length > length - read_pos) { + ret = -EINVAL; + goto out; + } +diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c +index 9363d005e2b61..e0d57e09dab0c 100644 +--- a/drivers/media/firewire/firedtv-ci.c ++++ b/drivers/media/firewire/firedtv-ci.c +@@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) + } else { + data_length = msg->msg[3]; + } ++ if (data_length > sizeof(msg->msg) - data_pos) ++ return -EINVAL; + + return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length); + } +diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig +index 08feb3e8c1bf6..6157e73eef24e 100644 +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -597,6 +597,7 @@ config VIDEO_AK881X + config VIDEO_THS8200 + tristate "Texas Instruments THS8200 video encoder" + depends on VIDEO_V4L2 && I2C ++ select V4L2_ASYNC + help + Support for the Texas Instruments THS8200 video encoder. + +diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c +index 81cdf37216ca7..c249507aa2dbc 100644 +--- a/drivers/media/i2c/imx258.c ++++ b/drivers/media/i2c/imx258.c +@@ -1260,18 +1260,18 @@ static int imx258_probe(struct i2c_client *client) + return -ENOMEM; + + imx258->clk = devm_clk_get_optional(&client->dev, NULL); ++ if (IS_ERR(imx258->clk)) ++ return dev_err_probe(&client->dev, PTR_ERR(imx258->clk), ++ "error getting clock\n"); + if (!imx258->clk) { + dev_dbg(&client->dev, + "no clock provided, using clock-frequency property\n"); + + device_property_read_u32(&client->dev, "clock-frequency", &val); +- if (val != IMX258_INPUT_CLOCK_FREQ) +- return -EINVAL; +- } else if (IS_ERR(imx258->clk)) { +- return dev_err_probe(&client->dev, PTR_ERR(imx258->clk), +- "error getting clock\n"); ++ } else { ++ val = clk_get_rate(imx258->clk); + } +- if (clk_get_rate(imx258->clk) != IMX258_INPUT_CLOCK_FREQ) { ++ if (val != IMX258_INPUT_CLOCK_FREQ) { + dev_err(&client->dev, "input clock frequency not supported\n"); + return -EINVAL; + } +diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c +index 0dce92872176d..4d9b64c61f603 100644 +--- a/drivers/media/i2c/imx274.c ++++ b/drivers/media/i2c/imx274.c +@@ -1367,6 +1367,10 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd, + int min, max, def; + int ret; + ++ ret = pm_runtime_resume_and_get(&imx274->client->dev); ++ if (ret < 0) ++ return ret; ++ + mutex_lock(&imx274->lock); + ret = imx274_set_frame_interval(imx274, fi->interval); + +@@ -1398,6 +1402,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd, + + unlock: + mutex_unlock(&imx274->lock); ++ pm_runtime_put(&imx274->client->dev); + + return ret; + } +diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c +index 92376592455ee..56674173524fd 100644 +--- a/drivers/media/i2c/ir-kbd-i2c.c ++++ b/drivers/media/i2c/ir-kbd-i2c.c +@@ -791,6 +791,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) + rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | + RC_PROTO_BIT_RC6_6A_32; + ir_codes = RC_MAP_HAUPPAUGE; ++ ir->polling_interval = 125; + probe_tx = true; + break; + } +diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c +index 6eb88ef997836..3ae1b28c8351b 100644 +--- a/drivers/media/i2c/mt9p031.c ++++ b/drivers/media/i2c/mt9p031.c +@@ -78,7 +78,9 @@ + #define MT9P031_PIXEL_CLOCK_INVERT (1 << 15) + #define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8) + #define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0) +-#define MT9P031_FRAME_RESTART 0x0b ++#define MT9P031_RESTART 0x0b ++#define MT9P031_FRAME_PAUSE_RESTART (1 << 1) ++#define MT9P031_FRAME_RESTART (1 << 0) + #define MT9P031_SHUTTER_DELAY 0x0c + #define MT9P031_RST 0x0d + #define MT9P031_RST_ENABLE 1 +@@ -444,9 +446,23 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031) + static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) + { + struct mt9p031 *mt9p031 = to_mt9p031(subdev); ++ struct i2c_client *client = v4l2_get_subdevdata(subdev); ++ int val; + int ret; + + if (!enable) { ++ /* enable pause restart */ ++ val = MT9P031_FRAME_PAUSE_RESTART; ++ ret = mt9p031_write(client, MT9P031_RESTART, val); ++ if (ret < 0) ++ return ret; ++ ++ /* enable restart + keep pause restart set */ ++ val |= MT9P031_FRAME_RESTART; ++ ret = mt9p031_write(client, MT9P031_RESTART, val); ++ if (ret < 0) ++ return ret; ++ + /* Stop sensor readout */ + ret = mt9p031_set_output_control(mt9p031, + MT9P031_OUTPUT_CONTROL_CEN, 0); +@@ -466,6 +482,16 @@ static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) + if (ret < 0) + return ret; + ++ /* ++ * - clear pause restart ++ * - don't clear restart as clearing restart manually can cause ++ * undefined behavior ++ */ ++ val = MT9P031_FRAME_RESTART; ++ ret = mt9p031_write(client, MT9P031_RESTART, val); ++ if (ret < 0) ++ return ret; ++ + return mt9p031_pll_enable(mt9p031); + } + +diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c +index ce50f3ea87b8e..92f6c3a940cfb 100644 +--- a/drivers/media/i2c/ov8865.c ++++ b/drivers/media/i2c/ov8865.c +@@ -2330,27 +2330,27 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on) + if (ret) { + dev_err(sensor->dev, + "failed to enable DOVDD regulator\n"); +- goto disable; ++ return ret; + } + + ret = regulator_enable(sensor->avdd); + if (ret) { + dev_err(sensor->dev, + "failed to enable AVDD regulator\n"); +- goto disable; ++ goto disable_dovdd; + } + + ret = regulator_enable(sensor->dvdd); + if (ret) { + dev_err(sensor->dev, + "failed to enable DVDD regulator\n"); +- goto disable; ++ goto disable_avdd; + } + + ret = clk_prepare_enable(sensor->extclk); + if (ret) { + dev_err(sensor->dev, "failed to enable EXTCLK clock\n"); +- goto disable; ++ goto disable_dvdd; + } + + gpiod_set_value_cansleep(sensor->reset, 0); +@@ -2359,14 +2359,16 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on) + /* Time to enter streaming mode according to power timings. */ + usleep_range(10000, 12000); + } else { +-disable: + gpiod_set_value_cansleep(sensor->powerdown, 1); + gpiod_set_value_cansleep(sensor->reset, 1); + + clk_disable_unprepare(sensor->extclk); + ++disable_dvdd: + regulator_disable(sensor->dvdd); ++disable_avdd: + regulator_disable(sensor->avdd); ++disable_dovdd: + regulator_disable(sensor->dovdd); + } + +@@ -2891,14 +2893,16 @@ static int ov8865_probe(struct i2c_client *client) + if (ret) + goto error_mutex; + ++ mutex_lock(&sensor->mutex); + ret = ov8865_state_init(sensor); ++ mutex_unlock(&sensor->mutex); + if (ret) + goto error_ctrls; + + /* Runtime PM */ + +- pm_runtime_enable(sensor->dev); + pm_runtime_set_suspended(sensor->dev); ++ pm_runtime_enable(sensor->dev); + + /* V4L2 subdev register */ + +diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c +index 6070aaf0b32ea..4dafa9f1cf522 100644 +--- a/drivers/media/i2c/tda1997x.c ++++ b/drivers/media/i2c/tda1997x.c +@@ -1248,13 +1248,13 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr) + { + struct v4l2_subdev *sd = &state->sd; + union hdmi_infoframe frame; +- u8 buffer[40]; ++ u8 buffer[40] = { 0 }; + u8 reg; + int len, err; + + /* read data */ + len = io_readn(sd, addr, sizeof(buffer), buffer); +- err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); ++ err = hdmi_infoframe_unpack(&frame, buffer, len); + if (err) { + v4l_err(state->client, + "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", +@@ -1928,13 +1928,13 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr) + { + struct tda1997x_state *state = to_state(sd); + union hdmi_infoframe frame; +- u8 buffer[40]; ++ u8 buffer[40] = { 0 }; + int len, err; + + /* read data */ + len = io_readn(sd, addr, sizeof(buffer), buffer); + v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); +- err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); ++ err = hdmi_infoframe_unpack(&frame, buffer, len); + if (err) { + v4l_err(state->client, + "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", +diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c +index 6a4c7cb0ad0f9..486c8ec0fa60d 100644 +--- a/drivers/media/pci/b2c2/flexcop-pci.c ++++ b/drivers/media/pci/b2c2/flexcop-pci.c +@@ -185,6 +185,8 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) + dma_addr_t cur_addr = + fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; + u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; ++ if (cur_pos > fc_pci->dma[0].size * 2) ++ goto error; + + deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", + jiffies_to_usecs(jiffies - fc_pci->last_irq), +@@ -225,6 +227,7 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) + ret = IRQ_NONE; + } + ++error: + spin_unlock_irqrestore(&fc_pci->irq_lock, flags); + return ret; + } +diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c +index ab14d35214aa8..25dc8d4dc5b73 100644 +--- a/drivers/media/pci/cx23885/cx23885-alsa.c ++++ b/drivers/media/pci/cx23885/cx23885-alsa.c +@@ -550,7 +550,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) + SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, sizeof(struct cx23885_audio_dev), &card); + if (err < 0) +- goto error; ++ goto error_msg; + + chip = (struct cx23885_audio_dev *) card->private_data; + chip->dev = dev; +@@ -576,6 +576,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) + + error: + snd_card_free(card); ++error_msg: + pr_err("%s(): Failed to register analog audio adapter\n", + __func__); + +diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c +index e2d56dca5be40..5ad03b2a50bdb 100644 +--- a/drivers/media/pci/ivtv/ivtvfb.c ++++ b/drivers/media/pci/ivtv/ivtvfb.c +@@ -36,7 +36,7 @@ + #include <linux/fb.h> + #include <linux/ivtvfb.h> + +-#ifdef CONFIG_X86_64 ++#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) + #include <asm/memtype.h> + #endif + +@@ -1157,7 +1157,7 @@ static int ivtvfb_init_card(struct ivtv *itv) + { + int rc; + +-#ifdef CONFIG_X86_64 ++#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) + if (pat_enabled()) { + if (ivtvfb_force_pat) { + pr_info("PAT is enabled. Write-combined framebuffer caching will be disabled.\n"); +diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +index 6f3125c2d0976..77bae14685513 100644 +--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c ++++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +@@ -258,19 +258,24 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id) + if ((reg40 & AVL_IRQ_ASSERTED) != 0) { + /* IRQ is being signaled */ + reg_isr = readw(ndev->bmmio0 + REG_ISR); +- if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) { +- iret = netup_i2c_interrupt(&ndev->i2c[0]); +- } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) { +- iret = netup_i2c_interrupt(&ndev->i2c[1]); +- } else if (reg_isr & NETUP_UNIDVB_IRQ_SPI) { ++ if (reg_isr & NETUP_UNIDVB_IRQ_SPI) + iret = netup_spi_interrupt(ndev->spi); +- } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) { +- iret = netup_dma_interrupt(&ndev->dma[0]); +- } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) { +- iret = netup_dma_interrupt(&ndev->dma[1]); +- } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) { +- iret = netup_ci_interrupt(ndev); ++ else if (!ndev->old_fw) { ++ if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) { ++ iret = netup_i2c_interrupt(&ndev->i2c[0]); ++ } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) { ++ iret = netup_i2c_interrupt(&ndev->i2c[1]); ++ } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) { ++ iret = netup_dma_interrupt(&ndev->dma[0]); ++ } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) { ++ iret = netup_dma_interrupt(&ndev->dma[1]); ++ } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) { ++ iret = netup_ci_interrupt(ndev); ++ } else { ++ goto err; ++ } + } else { ++err: + dev_err(&pci_dev->dev, + "%s(): unknown interrupt 0x%x\n", + __func__, reg_isr); +diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c +index 2214c74bbbf15..3947701cd6c7e 100644 +--- a/drivers/media/pci/saa7146/hexium_gemini.c ++++ b/drivers/media/pci/saa7146/hexium_gemini.c +@@ -284,7 +284,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d + hexium_set_input(hexium, 0); + hexium->cur_input = 0; + +- saa7146_vv_init(dev, &vv_data); ++ ret = saa7146_vv_init(dev, &vv_data); ++ if (ret) { ++ i2c_del_adapter(&hexium->i2c_adapter); ++ kfree(hexium); ++ return ret; ++ } + + vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input; + vv_data.vid_ops.vidioc_g_input = vidioc_g_input; +diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c +index 39d14c179d229..2eb4bee16b71f 100644 +--- a/drivers/media/pci/saa7146/hexium_orion.c ++++ b/drivers/media/pci/saa7146/hexium_orion.c +@@ -355,10 +355,16 @@ static struct saa7146_ext_vv vv_data; + static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) + { + struct hexium *hexium = (struct hexium *) dev->ext_priv; ++ int ret; + + DEB_EE("\n"); + +- saa7146_vv_init(dev, &vv_data); ++ ret = saa7146_vv_init(dev, &vv_data); ++ if (ret) { ++ pr_err("Error in saa7146_vv_init()\n"); ++ return ret; ++ } ++ + vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input; + vv_data.vid_ops.vidioc_g_input = vidioc_g_input; + vv_data.vid_ops.vidioc_s_input = vidioc_s_input; +diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c +index 73fc901ecf3db..bf0b9b0914cd5 100644 +--- a/drivers/media/pci/saa7146/mxb.c ++++ b/drivers/media/pci/saa7146/mxb.c +@@ -683,10 +683,16 @@ static struct saa7146_ext_vv vv_data; + static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) + { + struct mxb *mxb; ++ int ret; + + DEB_EE("dev:%p\n", dev); + +- saa7146_vv_init(dev, &vv_data); ++ ret = saa7146_vv_init(dev, &vv_data); ++ if (ret) { ++ ERR("Error in saa7146_vv_init()"); ++ return ret; ++ } ++ + if (mxb_probe(dev)) { + saa7146_vv_release(dev); + return -1; +diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c +index 887b492e4ad1c..14a119b43bca0 100644 +--- a/drivers/media/platform/allegro-dvt/allegro-core.c ++++ b/drivers/media/platform/allegro-dvt/allegro-core.c +@@ -2185,6 +2185,15 @@ static irqreturn_t allegro_irq_thread(int irq, void *data) + { + struct allegro_dev *dev = data; + ++ /* ++ * The firmware is initialized after the mailbox is setup. We further ++ * check the AL5_ITC_CPU_IRQ_STA register, if the firmware actually ++ * triggered the interrupt. Although this should not happen, make sure ++ * that we ignore interrupts, if the mailbox is not initialized. ++ */ ++ if (!dev->mbox_status) ++ return IRQ_NONE; ++ + allegro_mbox_notify(dev->mbox_status); + + return IRQ_HANDLED; +diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c +index 7bb6babdcade0..debc7509c173c 100644 +--- a/drivers/media/platform/aspeed-video.c ++++ b/drivers/media/platform/aspeed-video.c +@@ -500,6 +500,10 @@ static void aspeed_video_enable_mode_detect(struct aspeed_video *video) + aspeed_video_update(video, VE_INTERRUPT_CTRL, 0, + VE_INTERRUPT_MODE_DETECT); + ++ /* Disable mode detect in order to re-trigger */ ++ aspeed_video_update(video, VE_SEQ_CTRL, ++ VE_SEQ_CTRL_TRIG_MODE_DET, 0); ++ + /* Trigger mode detect */ + aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET); + } +@@ -552,6 +556,8 @@ static void aspeed_video_irq_res_change(struct aspeed_video *video, ulong delay) + set_bit(VIDEO_RES_CHANGE, &video->flags); + clear_bit(VIDEO_FRAME_INPRG, &video->flags); + ++ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL; ++ + aspeed_video_off(video); + aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR); + +@@ -786,10 +792,6 @@ static void aspeed_video_get_resolution(struct aspeed_video *video) + return; + } + +- /* Disable mode detect in order to re-trigger */ +- aspeed_video_update(video, VE_SEQ_CTRL, +- VE_SEQ_CTRL_TRIG_MODE_DET, 0); +- + aspeed_video_check_and_set_polarity(video); + + aspeed_video_enable_mode_detect(video); +@@ -1337,7 +1339,6 @@ static void aspeed_video_resolution_work(struct work_struct *work) + struct delayed_work *dwork = to_delayed_work(work); + struct aspeed_video *video = container_of(dwork, struct aspeed_video, + res_work); +- u32 input_status = video->v4l2_input_status; + + aspeed_video_on(video); + +@@ -1350,8 +1351,7 @@ static void aspeed_video_resolution_work(struct work_struct *work) + aspeed_video_get_resolution(video); + + if (video->detected_timings.width != video->active_timings.width || +- video->detected_timings.height != video->active_timings.height || +- input_status != video->v4l2_input_status) { ++ video->detected_timings.height != video->active_timings.height) { + static const struct v4l2_event ev = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, +diff --git a/drivers/media/platform/atmel/atmel-isc-base.c b/drivers/media/platform/atmel/atmel-isc-base.c +index 136ab7cf36edc..ebf264b980f91 100644 +--- a/drivers/media/platform/atmel/atmel-isc-base.c ++++ b/drivers/media/platform/atmel/atmel-isc-base.c +@@ -123,11 +123,9 @@ static int isc_clk_prepare(struct clk_hw *hw) + struct isc_clk *isc_clk = to_isc_clk(hw); + int ret; + +- if (isc_clk->id == ISC_ISPCK) { +- ret = pm_runtime_resume_and_get(isc_clk->dev); +- if (ret < 0) +- return ret; +- } ++ ret = pm_runtime_resume_and_get(isc_clk->dev); ++ if (ret < 0) ++ return ret; + + return isc_wait_clk_stable(hw); + } +@@ -138,8 +136,7 @@ static void isc_clk_unprepare(struct clk_hw *hw) + + isc_wait_clk_stable(hw); + +- if (isc_clk->id == ISC_ISPCK) +- pm_runtime_put_sync(isc_clk->dev); ++ pm_runtime_put_sync(isc_clk->dev); + } + + static int isc_clk_enable(struct clk_hw *hw) +@@ -186,16 +183,13 @@ static int isc_clk_is_enabled(struct clk_hw *hw) + u32 status; + int ret; + +- if (isc_clk->id == ISC_ISPCK) { +- ret = pm_runtime_resume_and_get(isc_clk->dev); +- if (ret < 0) +- return 0; +- } ++ ret = pm_runtime_resume_and_get(isc_clk->dev); ++ if (ret < 0) ++ return 0; + + regmap_read(isc_clk->regmap, ISC_CLKSR, &status); + +- if (isc_clk->id == ISC_ISPCK) +- pm_runtime_put_sync(isc_clk->dev); ++ pm_runtime_put_sync(isc_clk->dev); + + return status & ISC_CLK(isc_clk->id) ? 1 : 0; + } +@@ -325,6 +319,9 @@ static int isc_clk_register(struct isc_device *isc, unsigned int id) + const char *parent_names[3]; + int num_parents; + ++ if (id == ISC_ISPCK && !isc->ispck_required) ++ return 0; ++ + num_parents = of_clk_get_parent_count(np); + if (num_parents < 1 || num_parents > 3) + return -EINVAL; +diff --git a/drivers/media/platform/atmel/atmel-isc.h b/drivers/media/platform/atmel/atmel-isc.h +index 19cc60dfcbe0f..2bfcb135ef13b 100644 +--- a/drivers/media/platform/atmel/atmel-isc.h ++++ b/drivers/media/platform/atmel/atmel-isc.h +@@ -178,6 +178,7 @@ struct isc_reg_offsets { + * @hclock: Hclock clock input (refer datasheet) + * @ispck: iscpck clock (refer datasheet) + * @isc_clks: ISC clocks ++ * @ispck_required: ISC requires ISP Clock initialization + * @dcfg: DMA master configuration, architecture dependent + * + * @dev: Registered device driver +@@ -252,6 +253,7 @@ struct isc_device { + struct clk *hclock; + struct clk *ispck; + struct isc_clk isc_clks[2]; ++ bool ispck_required; + u32 dcfg; + + struct device *dev; +diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c +index b66f1d174e9d7..e29a9193bac81 100644 +--- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c ++++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c +@@ -454,6 +454,9 @@ static int atmel_isc_probe(struct platform_device *pdev) + /* sama5d2-isc - 8 bits per beat */ + isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8; + ++ /* sama5d2-isc : ISPCK is required and mandatory */ ++ isc->ispck_required = true; ++ + ret = isc_pipeline_init(isc); + if (ret) + return ret; +@@ -476,22 +479,6 @@ static int atmel_isc_probe(struct platform_device *pdev) + dev_err(dev, "failed to init isc clock: %d\n", ret); + goto unprepare_hclk; + } +- +- isc->ispck = isc->isc_clks[ISC_ISPCK].clk; +- +- ret = clk_prepare_enable(isc->ispck); +- if (ret) { +- dev_err(dev, "failed to enable ispck: %d\n", ret); +- goto unprepare_hclk; +- } +- +- /* ispck should be greater or equal to hclock */ +- ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); +- if (ret) { +- dev_err(dev, "failed to set ispck rate: %d\n", ret); +- goto unprepare_clk; +- } +- + ret = v4l2_device_register(dev, &isc->v4l2_dev); + if (ret) { + dev_err(dev, "unable to register v4l2 device.\n"); +@@ -545,19 +532,35 @@ static int atmel_isc_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + pm_request_idle(dev); + ++ isc->ispck = isc->isc_clks[ISC_ISPCK].clk; ++ ++ ret = clk_prepare_enable(isc->ispck); ++ if (ret) { ++ dev_err(dev, "failed to enable ispck: %d\n", ret); ++ goto cleanup_subdev; ++ } ++ ++ /* ispck should be greater or equal to hclock */ ++ ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); ++ if (ret) { ++ dev_err(dev, "failed to set ispck rate: %d\n", ret); ++ goto unprepare_clk; ++ } ++ + regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver); + dev_info(dev, "Microchip ISC version %x\n", ver); + + return 0; + ++unprepare_clk: ++ clk_disable_unprepare(isc->ispck); ++ + cleanup_subdev: + isc_subdev_cleanup(isc); + + unregister_v4l2_device: + v4l2_device_unregister(&isc->v4l2_dev); + +-unprepare_clk: +- clk_disable_unprepare(isc->ispck); + unprepare_hclk: + clk_disable_unprepare(isc->hclock); + +diff --git a/drivers/media/platform/atmel/atmel-sama7g5-isc.c b/drivers/media/platform/atmel/atmel-sama7g5-isc.c +index f2785131ff569..9c05acafd0724 100644 +--- a/drivers/media/platform/atmel/atmel-sama7g5-isc.c ++++ b/drivers/media/platform/atmel/atmel-sama7g5-isc.c +@@ -447,6 +447,9 @@ static int microchip_xisc_probe(struct platform_device *pdev) + /* sama7g5-isc RAM access port is full AXI4 - 32 bits per beat */ + isc->dcfg = ISC_DCFG_YMBSIZE_BEATS32 | ISC_DCFG_CMBSIZE_BEATS32; + ++ /* sama7g5-isc : ISPCK does not exist, ISC is clocked by MCK */ ++ isc->ispck_required = false; ++ + ret = isc_pipeline_init(isc); + if (ret) + return ret; +@@ -470,25 +473,10 @@ static int microchip_xisc_probe(struct platform_device *pdev) + goto unprepare_hclk; + } + +- isc->ispck = isc->isc_clks[ISC_ISPCK].clk; +- +- ret = clk_prepare_enable(isc->ispck); +- if (ret) { +- dev_err(dev, "failed to enable ispck: %d\n", ret); +- goto unprepare_hclk; +- } +- +- /* ispck should be greater or equal to hclock */ +- ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); +- if (ret) { +- dev_err(dev, "failed to set ispck rate: %d\n", ret); +- goto unprepare_clk; +- } +- + ret = v4l2_device_register(dev, &isc->v4l2_dev); + if (ret) { + dev_err(dev, "unable to register v4l2 device.\n"); +- goto unprepare_clk; ++ goto unprepare_hclk; + } + + ret = xisc_parse_dt(dev, isc); +@@ -549,8 +537,6 @@ cleanup_subdev: + unregister_v4l2_device: + v4l2_device_unregister(&isc->v4l2_dev); + +-unprepare_clk: +- clk_disable_unprepare(isc->ispck); + unprepare_hclk: + clk_disable_unprepare(isc->hclock); + +diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c +index 0e312b0842d7f..9a2640a9c75c6 100644 +--- a/drivers/media/platform/coda/coda-common.c ++++ b/drivers/media/platform/coda/coda-common.c +@@ -1537,11 +1537,13 @@ static void coda_pic_run_work(struct work_struct *work) + + if (!wait_for_completion_timeout(&ctx->completion, + msecs_to_jiffies(1000))) { +- dev_err(dev->dev, "CODA PIC_RUN timeout\n"); ++ if (ctx->use_bit) { ++ dev_err(dev->dev, "CODA PIC_RUN timeout\n"); + +- ctx->hold = true; ++ ctx->hold = true; + +- coda_hw_reset(ctx); ++ coda_hw_reset(ctx); ++ } + + if (ctx->ops->run_timeout) + ctx->ops->run_timeout(ctx); +diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c +index b11cfbe166dd3..a72f4655e5ad5 100644 +--- a/drivers/media/platform/coda/coda-jpeg.c ++++ b/drivers/media/platform/coda/coda-jpeg.c +@@ -1127,7 +1127,8 @@ static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR); + coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR); + coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_STRM_CTRL); ++ coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256), ++ CODA9_REG_JPEG_BBC_STRM_CTRL); + coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL); + coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR); + coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); +@@ -1257,6 +1258,23 @@ static void coda9_jpeg_finish_encode(struct coda_ctx *ctx) + coda_hw_reset(ctx); + } + ++static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u32 end_addr, wr_ptr; ++ ++ /* Handle missing BBC overflow interrupt via timeout */ ++ end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR); ++ wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); ++ if (wr_ptr >= end_addr - 256) { ++ v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n"); ++ coda9_jpeg_finish_encode(ctx); ++ return; ++ } ++ ++ coda_hw_reset(ctx); ++} ++ + static void coda9_jpeg_release(struct coda_ctx *ctx) + { + int i; +@@ -1276,6 +1294,7 @@ const struct coda_context_ops coda9_jpeg_encode_ops = { + .start_streaming = coda9_jpeg_start_encoding, + .prepare_run = coda9_jpeg_prepare_encode, + .finish_run = coda9_jpeg_finish_encode, ++ .run_timeout = coda9_jpeg_encode_timeout, + .release = coda9_jpeg_release, + }; + +diff --git a/drivers/media/platform/coda/imx-vdoa.c b/drivers/media/platform/coda/imx-vdoa.c +index 8bc0d83718193..dd6e2e320264e 100644 +--- a/drivers/media/platform/coda/imx-vdoa.c ++++ b/drivers/media/platform/coda/imx-vdoa.c +@@ -287,7 +287,11 @@ static int vdoa_probe(struct platform_device *pdev) + struct resource *res; + int ret; + +- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) { ++ dev_err(&pdev->dev, "DMA enable failed\n"); ++ return ret; ++ } + + vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL); + if (!vdoa) +diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/imx-jpeg/mxc-jpeg.c +index 755138063ee61..fc905ea78b175 100644 +--- a/drivers/media/platform/imx-jpeg/mxc-jpeg.c ++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg.c +@@ -575,6 +575,10 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv) + + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ++ if (!dst_buf || !src_buf) { ++ dev_err(dev, "No source or destination buffer.\n"); ++ goto job_unlock; ++ } + jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf); + + if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) { +@@ -2088,6 +2092,8 @@ err_m2m: + v4l2_device_unregister(&jpeg->v4l2_dev); + + err_register: ++ mxc_jpeg_detach_pm_domains(jpeg); ++ + err_irq: + return ret; + } +diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c +index 4321edc0c23d9..8e9c6fee75a48 100644 +--- a/drivers/media/platform/imx-pxp.c ++++ b/drivers/media/platform/imx-pxp.c +@@ -1661,6 +1661,8 @@ static int pxp_probe(struct platform_device *pdev) + if (irq < 0) + return irq; + ++ spin_lock_init(&dev->irqlock); ++ + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler, + IRQF_ONESHOT, dev_name(&pdev->dev), dev); + if (ret < 0) { +@@ -1678,8 +1680,6 @@ static int pxp_probe(struct platform_device *pdev) + goto err_clk; + } + +- spin_lock_init(&dev->irqlock); +- + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + goto err_clk; +diff --git a/drivers/media/platform/meson/ge2d/ge2d.c b/drivers/media/platform/meson/ge2d/ge2d.c +index a1393fefa8aea..9b1e973e78da3 100644 +--- a/drivers/media/platform/meson/ge2d/ge2d.c ++++ b/drivers/media/platform/meson/ge2d/ge2d.c +@@ -779,11 +779,7 @@ static int ge2d_s_ctrl(struct v4l2_ctrl *ctrl) + * If the rotation parameter changes the OUTPUT frames + * parameters, take them in account + */ +- if (fmt.width != ctx->out.pix_fmt.width || +- fmt.height != ctx->out.pix_fmt.width || +- fmt.bytesperline > ctx->out.pix_fmt.bytesperline || +- fmt.sizeimage > ctx->out.pix_fmt.sizeimage) +- ctx->out.pix_fmt = fmt; ++ ctx->out.pix_fmt = fmt; + + break; + } +diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +index 416f356af363d..d97a6765693f1 100644 +--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c ++++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +@@ -793,7 +793,7 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) + { + struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q); + struct venc_enc_param param; +- int ret; ++ int ret, pm_ret; + int i; + + /* Once state turn into MTK_STATE_ABORT, we need stop_streaming +@@ -845,9 +845,9 @@ static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count) + return 0; + + err_set_param: +- ret = pm_runtime_put(&ctx->dev->plat_dev->dev); +- if (ret < 0) +- mtk_v4l2_err("pm_runtime_put fail %d", ret); ++ pm_ret = pm_runtime_put(&ctx->dev->plat_dev->dev); ++ if (pm_ret < 0) ++ mtk_v4l2_err("pm_runtime_put fail %d", pm_ret); + + err_start_stream: + for (i = 0; i < q->num_buffers; ++i) { +diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +index 45d1870c83dd7..4ced20ca647b1 100644 +--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c ++++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c +@@ -218,11 +218,11 @@ static int fops_vcodec_release(struct file *file) + mtk_v4l2_debug(1, "[%d] encoder", ctx->id); + mutex_lock(&dev->dev_mutex); + ++ v4l2_m2m_ctx_release(ctx->m2m_ctx); + mtk_vcodec_enc_release(ctx); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->ctrl_hdl); +- v4l2_m2m_ctx_release(ctx->m2m_ctx); + + list_del_init(&ctx->list); + kfree(ctx); +diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c +index ec290dde59cfd..7f1647da0ade0 100644 +--- a/drivers/media/platform/mtk-vpu/mtk_vpu.c ++++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c +@@ -848,7 +848,8 @@ static int mtk_vpu_probe(struct platform_device *pdev) + vpu->wdt.wq = create_singlethread_workqueue("vpu_wdt"); + if (!vpu->wdt.wq) { + dev_err(dev, "initialize wdt workqueue failed\n"); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto clk_unprepare; + } + INIT_WORK(&vpu->wdt.ws, vpu_wdt_reset_func); + mutex_init(&vpu->vpu_mutex); +@@ -942,6 +943,8 @@ disable_vpu_clk: + vpu_clock_disable(vpu); + workqueue_destroy: + destroy_workqueue(vpu->wdt.wq); ++clk_unprepare: ++ clk_unprepare(vpu->clk); + + return ret; + } +diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c +index 91b15842c5558..1f0181b6353c9 100644 +--- a/drivers/media/platform/qcom/venus/core.c ++++ b/drivers/media/platform/qcom/venus/core.c +@@ -349,11 +349,11 @@ static int venus_probe(struct platform_device *pdev) + + ret = venus_firmware_init(core); + if (ret) +- goto err_runtime_disable; ++ goto err_of_depopulate; + + ret = venus_boot(core); + if (ret) +- goto err_runtime_disable; ++ goto err_firmware_deinit; + + ret = hfi_core_resume(core, true); + if (ret) +@@ -385,6 +385,10 @@ err_dev_unregister: + v4l2_device_unregister(&core->v4l2_dev); + err_venus_shutdown: + venus_shutdown(core); ++err_firmware_deinit: ++ venus_firmware_deinit(core); ++err_of_depopulate: ++ of_platform_depopulate(dev); + err_runtime_disable: + pm_runtime_put_noidle(dev); + pm_runtime_set_suspended(dev); +@@ -472,7 +476,8 @@ static __maybe_unused int venus_runtime_suspend(struct device *dev) + err_video_path: + icc_set_bw(core->cpucfg_path, kbps_to_icc(1000), 0); + err_cpucfg_path: +- pm_ops->core_power(core, POWER_ON); ++ if (pm_ops->core_power) ++ pm_ops->core_power(core, POWER_ON); + + return ret; + } +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index 3e2345eb47f7c..a591dd315ebcc 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -163,14 +163,12 @@ static u32 load_per_type(struct venus_core *core, u32 session_type) + struct venus_inst *inst = NULL; + u32 mbs_per_sec = 0; + +- mutex_lock(&core->lock); + list_for_each_entry(inst, &core->instances, list) { + if (inst->session_type != session_type) + continue; + + mbs_per_sec += load_per_instance(inst); + } +- mutex_unlock(&core->lock); + + return mbs_per_sec; + } +@@ -219,14 +217,12 @@ static int load_scale_bw(struct venus_core *core) + struct venus_inst *inst = NULL; + u32 mbs_per_sec, avg, peak, total_avg = 0, total_peak = 0; + +- mutex_lock(&core->lock); + list_for_each_entry(inst, &core->instances, list) { + mbs_per_sec = load_per_instance(inst); + mbs_to_bw(inst, mbs_per_sec, &avg, &peak); + total_avg += avg; + total_peak += peak; + } +- mutex_unlock(&core->lock); + + /* + * keep minimum bandwidth vote for "video-mem" path, +@@ -253,8 +249,9 @@ static int load_scale_v1(struct venus_inst *inst) + struct device *dev = core->dev; + u32 mbs_per_sec; + unsigned int i; +- int ret; ++ int ret = 0; + ++ mutex_lock(&core->lock); + mbs_per_sec = load_per_type(core, VIDC_SESSION_TYPE_ENC) + + load_per_type(core, VIDC_SESSION_TYPE_DEC); + +@@ -279,17 +276,19 @@ set_freq: + if (ret) { + dev_err(dev, "failed to set clock rate %lu (%d)\n", + freq, ret); +- return ret; ++ goto exit; + } + + ret = load_scale_bw(core); + if (ret) { + dev_err(dev, "failed to set bandwidth (%d)\n", + ret); +- return ret; ++ goto exit; + } + +- return 0; ++exit: ++ mutex_unlock(&core->lock); ++ return ret; + } + + static int core_get_v1(struct venus_core *core) +@@ -587,8 +586,8 @@ min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load, bool lo + if (inst->session_type == VIDC_SESSION_TYPE_DEC) + vpp_freq = inst_pos->clk_data.vpp_freq; + else if (inst->session_type == VIDC_SESSION_TYPE_ENC) +- vpp_freq = low_power ? inst_pos->clk_data.vpp_freq : +- inst_pos->clk_data.low_power_freq; ++ vpp_freq = low_power ? inst_pos->clk_data.low_power_freq : ++ inst_pos->clk_data.vpp_freq; + else + continue; + +@@ -1085,12 +1084,16 @@ static unsigned long calculate_inst_freq(struct venus_inst *inst, + if (inst->state != INST_START) + return 0; + +- if (inst->session_type == VIDC_SESSION_TYPE_ENC) ++ if (inst->session_type == VIDC_SESSION_TYPE_ENC) { + vpp_freq_per_mb = inst->flags & VENUS_LOW_POWER ? + inst->clk_data.low_power_freq : + inst->clk_data.vpp_freq; + +- vpp_freq = mbs_per_sec * vpp_freq_per_mb; ++ vpp_freq = mbs_per_sec * vpp_freq_per_mb; ++ } else { ++ vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq; ++ } ++ + /* 21 / 20 is overhead factor */ + vpp_freq += vpp_freq / 20; + vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq; +@@ -1112,13 +1115,13 @@ static int load_scale_v4(struct venus_inst *inst) + struct device *dev = core->dev; + unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; + unsigned long filled_len = 0; +- int i, ret; ++ int i, ret = 0; + + for (i = 0; i < inst->num_input_bufs; i++) + filled_len = max(filled_len, inst->payloads[i]); + + if (inst->session_type == VIDC_SESSION_TYPE_DEC && !filled_len) +- return 0; ++ return ret; + + freq = calculate_inst_freq(inst, filled_len); + inst->clk_data.freq = freq; +@@ -1134,7 +1137,6 @@ static int load_scale_v4(struct venus_inst *inst) + freq_core2 += inst->clk_data.freq; + } + } +- mutex_unlock(&core->lock); + + freq = max(freq_core1, freq_core2); + +@@ -1158,17 +1160,19 @@ set_freq: + if (ret) { + dev_err(dev, "failed to set clock rate %lu (%d)\n", + freq, ret); +- return ret; ++ goto exit; + } + + ret = load_scale_bw(core); + if (ret) { + dev_err(dev, "failed to set bandwidth (%d)\n", + ret); +- return ret; ++ goto exit; + } + +- return 0; ++exit: ++ mutex_unlock(&core->lock); ++ return ret; + } + + static const struct venus_pm_ops pm_ops_v4 = { +diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c +index e28eff0396888..0c5e2f7e04beb 100644 +--- a/drivers/media/platform/rcar-vin/rcar-csi2.c ++++ b/drivers/media/platform/rcar-vin/rcar-csi2.c +@@ -445,16 +445,23 @@ static int rcsi2_wait_phy_start(struct rcar_csi2 *priv, + static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps) + { + const struct rcsi2_mbps_reg *hsfreq; ++ const struct rcsi2_mbps_reg *hsfreq_prev = NULL; + +- for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) ++ for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) { + if (hsfreq->mbps >= mbps) + break; ++ hsfreq_prev = hsfreq; ++ } + + if (!hsfreq->mbps) { + dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps); + return -ERANGE; + } + ++ if (hsfreq_prev && ++ ((mbps - hsfreq_prev->mbps) <= (hsfreq->mbps - mbps))) ++ hsfreq = hsfreq_prev; ++ + rcsi2_write(priv, PHYPLL_REG, PHYPLL_HSFREQRANGE(hsfreq->reg)); + + return 0; +@@ -553,6 +560,8 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) + + /* Code is validated in set_fmt. */ + format = rcsi2_code_to_fmt(priv->mf.code); ++ if (!format) ++ return -EINVAL; + + /* + * Enable all supported CSI-2 channels with virtual channel and +@@ -980,10 +989,17 @@ static int rcsi2_phtw_write_mbps(struct rcar_csi2 *priv, unsigned int mbps, + const struct rcsi2_mbps_reg *values, u16 code) + { + const struct rcsi2_mbps_reg *value; ++ const struct rcsi2_mbps_reg *prev_value = NULL; + +- for (value = values; value->mbps; value++) ++ for (value = values; value->mbps; value++) { + if (value->mbps >= mbps) + break; ++ prev_value = value; ++ } ++ ++ if (prev_value && ++ ((mbps - prev_value->mbps) <= (value->mbps - mbps))) ++ value = prev_value; + + if (!value->mbps) { + dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps); +diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c +index f5f722ab1d4e8..520d044bfb8d5 100644 +--- a/drivers/media/platform/rcar-vin/rcar-dma.c ++++ b/drivers/media/platform/rcar-vin/rcar-dma.c +@@ -904,7 +904,8 @@ static void rvin_fill_hw_slot(struct rvin_dev *vin, int slot) + vin->format.sizeimage / 2; + break; + } +- } else if (vin->state != RUNNING || list_empty(&vin->buf_list)) { ++ } else if ((vin->state != STOPPED && vin->state != RUNNING) || ++ list_empty(&vin->buf_list)) { + vin->buf_hw[slot].buffer = NULL; + vin->buf_hw[slot].type = FULL; + phys_addr = vin->scratch_phys; +diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c +index 0d141155f0e3e..eb8c79bac540f 100644 +--- a/drivers/media/platform/rcar-vin/rcar-v4l2.c ++++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c +@@ -175,20 +175,27 @@ static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix) + break; + } + +- /* HW limit width to a multiple of 32 (2^5) for NV12/16 else 2 (2^1) */ ++ /* Hardware limits width alignment based on format. */ + switch (pix->pixelformat) { ++ /* Multiple of 32 (2^5) for NV12/16. */ + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + walign = 5; + break; +- default: ++ /* Multiple of 2 (2^1) for YUV. */ ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_UYVY: + walign = 1; + break; ++ /* No multiple for RGB. */ ++ default: ++ walign = 0; ++ break; + } + + /* Limit to VIN capabilities */ +- v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign, +- &pix->height, 4, vin->info->max_height, 2, 0); ++ v4l_bound_align_image(&pix->width, 5, vin->info->max_width, walign, ++ &pix->height, 2, vin->info->max_height, 0, 0); + + pix->bytesperline = rvin_format_bytesperline(vin, pix); + pix->sizeimage = rvin_format_sizeimage(pix); +diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +index 7474150b94ed3..560f928c37520 100644 +--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c ++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +@@ -426,7 +426,7 @@ static void rkisp1_debug_init(struct rkisp1_device *rkisp1) + { + struct rkisp1_debug *debug = &rkisp1->debug; + +- debug->debugfs_dir = debugfs_create_dir(RKISP1_DRIVER_NAME, NULL); ++ debug->debugfs_dir = debugfs_create_dir(dev_name(rkisp1->dev), NULL); + debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir, + &debug->data_loss); + debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir, +diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c +index eba2b9f040df0..f336a95432732 100644 +--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c ++++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c +@@ -1283,11 +1283,15 @@ static int s5p_mfc_probe(struct platform_device *pdev) + spin_lock_init(&dev->condlock); + dev->plat_dev = pdev; + if (!dev->plat_dev) { +- dev_err(&pdev->dev, "No platform data specified\n"); ++ mfc_err("No platform data specified\n"); + return -ENODEV; + } + + dev->variant = of_device_get_match_data(&pdev->dev); ++ if (!dev->variant) { ++ dev_err(&pdev->dev, "Failed to get device MFC hardware variant information\n"); ++ return -ENOENT; ++ } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->regs_base = devm_ioremap_resource(&pdev->dev, res); +diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c +index d914ccef98317..6110718645a4f 100644 +--- a/drivers/media/platform/stm32/stm32-dcmi.c ++++ b/drivers/media/platform/stm32/stm32-dcmi.c +@@ -128,6 +128,7 @@ struct stm32_dcmi { + int sequence; + struct list_head buffers; + struct dcmi_buf *active; ++ int irq; + + struct v4l2_device v4l2_dev; + struct video_device *vdev; +@@ -1759,6 +1760,14 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) + return ret; + } + ++ ret = devm_request_threaded_irq(dcmi->dev, dcmi->irq, dcmi_irq_callback, ++ dcmi_irq_thread, IRQF_ONESHOT, ++ dev_name(dcmi->dev), dcmi); ++ if (ret) { ++ dev_err(dcmi->dev, "Unable to request irq %d\n", dcmi->irq); ++ return ret; ++ } ++ + return 0; + } + +@@ -1914,6 +1923,8 @@ static int dcmi_probe(struct platform_device *pdev) + if (irq <= 0) + return irq ? irq : -ENXIO; + ++ dcmi->irq = irq; ++ + dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!dcmi->res) { + dev_err(&pdev->dev, "Could not get resource\n"); +@@ -1926,14 +1937,6 @@ static int dcmi_probe(struct platform_device *pdev) + return PTR_ERR(dcmi->regs); + } + +- ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback, +- dcmi_irq_thread, IRQF_ONESHOT, +- dev_name(&pdev->dev), dcmi); +- if (ret) { +- dev_err(&pdev->dev, "Unable to request irq %d\n", irq); +- return ret; +- } +- + mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(mclk)) { + if (PTR_ERR(mclk) != -EPROBE_DEFER) +diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c +index 07b2161392d21..5ba3e29f794fd 100644 +--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c ++++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c +@@ -467,7 +467,7 @@ static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = { + static int sun6i_video_open(struct file *file) + { + struct sun6i_video *video = video_drvdata(file); +- int ret; ++ int ret = 0; + + if (mutex_lock_interruptible(&video->lock)) + return -ERESTARTSYS; +@@ -481,10 +481,8 @@ static int sun6i_video_open(struct file *file) + goto fh_release; + + /* check if already powered */ +- if (!v4l2_fh_is_singular_file(file)) { +- ret = -EBUSY; ++ if (!v4l2_fh_is_singular_file(file)) + goto unlock; +- } + + ret = sun6i_csi_set_power(video->csi, true); + if (ret < 0) +diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c +index 1123768731676..484046471c03f 100644 +--- a/drivers/media/radio/radio-wl1273.c ++++ b/drivers/media/radio/radio-wl1273.c +@@ -1279,7 +1279,7 @@ static int wl1273_fm_vidioc_querycap(struct file *file, void *priv, + + strscpy(capability->driver, WL1273_FM_DRIVER_NAME, + sizeof(capability->driver)); +- strscpy(capability->card, "Texas Instruments Wl1273 FM Radio", ++ strscpy(capability->card, "TI Wl1273 FM Radio", + sizeof(capability->card)); + strscpy(capability->bus_info, radio->bus_type, + sizeof(capability->bus_info)); +diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c +index f491420d7b538..76d39e2e87706 100644 +--- a/drivers/media/radio/si470x/radio-si470x-i2c.c ++++ b/drivers/media/radio/si470x/radio-si470x-i2c.c +@@ -11,7 +11,7 @@ + + /* driver definitions */ + #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>"; +-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" ++#define DRIVER_CARD "Silicon Labs Si470x FM Radio" + #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" + #define DRIVER_VERSION "1.0.2" + +@@ -368,7 +368,7 @@ static int si470x_i2c_probe(struct i2c_client *client) + if (radio->hdl.error) { + retval = radio->hdl.error; + dev_err(&client->dev, "couldn't register control\n"); +- goto err_dev; ++ goto err_all; + } + + /* video device initialization */ +@@ -463,7 +463,6 @@ static int si470x_i2c_probe(struct i2c_client *client) + return 0; + err_all: + v4l2_ctrl_handler_free(&radio->hdl); +-err_dev: + v4l2_device_unregister(&radio->v4l2_dev); + err_initial: + return retval; +diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c +index fedff68d8c496..3f8634a465730 100644 +--- a/drivers/media/radio/si470x/radio-si470x-usb.c ++++ b/drivers/media/radio/si470x/radio-si470x-usb.c +@@ -16,7 +16,7 @@ + + /* driver definitions */ + #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" +-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" ++#define DRIVER_CARD "Silicon Labs Si470x FM Radio" + #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" + #define DRIVER_VERSION "1.0.10" + +diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c +index effaa5751d6c9..3e9988ee785f0 100644 +--- a/drivers/media/rc/igorplugusb.c ++++ b/drivers/media/rc/igorplugusb.c +@@ -64,9 +64,11 @@ static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len) + if (start >= len) { + dev_err(ir->dev, "receive overflow invalid: %u", overflow); + } else { +- if (overflow > 0) ++ if (overflow > 0) { + dev_warn(ir->dev, "receive overflow, at least %u lost", + overflow); ++ ir_raw_event_reset(ir->rc); ++ } + + do { + rawir.duration = ir->buf_in[i] * 85; +diff --git a/drivers/media/rc/ir_toy.c b/drivers/media/rc/ir_toy.c +index 48d52baec1a1c..1aa7989e756cc 100644 +--- a/drivers/media/rc/ir_toy.c ++++ b/drivers/media/rc/ir_toy.c +@@ -310,7 +310,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count) + buf[i] = cpu_to_be16(v); + } + +- buf[count] = 0xffff; ++ buf[count] = cpu_to_be16(0xffff); + + irtoy->tx_buf = buf; + irtoy->tx_len = size; +diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c +index 5bc23e8c6d91d..4f77d4ebacdc5 100644 +--- a/drivers/media/rc/ite-cir.c ++++ b/drivers/media/rc/ite-cir.c +@@ -242,7 +242,7 @@ static irqreturn_t ite_cir_isr(int irq, void *data) + } + + /* check for the receive interrupt */ +- if (iflags & ITE_IRQ_RX_FIFO) { ++ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { + /* read the FIFO bytes */ + rx_bytes = dev->params->get_rx_bytes(dev, rx_buf, + ITE_RX_FIFO_LEN); +diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c +index e03dd1f0144f0..5f296f985b07a 100644 +--- a/drivers/media/rc/mceusb.c ++++ b/drivers/media/rc/mceusb.c +@@ -1386,6 +1386,7 @@ static void mceusb_dev_recv(struct urb *urb) + case -ECONNRESET: + case -ENOENT: + case -EILSEQ: ++ case -EPROTO: + case -ESHUTDOWN: + usb_unlink_urb(urb); + return; +@@ -1429,7 +1430,7 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) + */ + ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), + USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, +- data, USB_CTRL_MSG_SZ, HZ * 3); ++ data, USB_CTRL_MSG_SZ, 3000); + dev_dbg(dev, "set address - ret = %d", ret); + dev_dbg(dev, "set address - data[0] = %d, data[1] = %d", + data[0], data[1]); +@@ -1437,20 +1438,20 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) + /* set feature: bit rate 38400 bps */ + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), + USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, +- 0xc04e, 0x0000, NULL, 0, HZ * 3); ++ 0xc04e, 0x0000, NULL, 0, 3000); + + dev_dbg(dev, "set feature - ret = %d", ret); + + /* bRequest 4: set char length to 8 bits */ + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), + 4, USB_TYPE_VENDOR, +- 0x0808, 0x0000, NULL, 0, HZ * 3); ++ 0x0808, 0x0000, NULL, 0, 3000); + dev_dbg(dev, "set char length - retB = %d", ret); + + /* bRequest 2: set handshaking to use DTR/DSR */ + ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), + 2, USB_TYPE_VENDOR, +- 0x0000, 0x0100, NULL, 0, HZ * 3); ++ 0x0000, 0x0100, NULL, 0, 3000); + dev_dbg(dev, "set handshake - retC = %d", ret); + + /* device resume */ +diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c +index ac85464864b9d..cb22316b3f002 100644 +--- a/drivers/media/rc/redrat3.c ++++ b/drivers/media/rc/redrat3.c +@@ -404,7 +404,7 @@ static int redrat3_send_cmd(int cmd, struct redrat3_dev *rr3) + udev = rr3->udev; + res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), cmd, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- 0x0000, 0x0000, data, sizeof(u8), HZ * 10); ++ 0x0000, 0x0000, data, sizeof(u8), 10000); + + if (res < 0) { + dev_err(rr3->dev, "%s: Error sending rr3 cmd res %d, data %d", +@@ -480,7 +480,7 @@ static u32 redrat3_get_timeout(struct redrat3_dev *rr3) + pipe = usb_rcvctrlpipe(rr3->udev, 0); + ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5); ++ RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, 5000); + if (ret != len) + dev_warn(rr3->dev, "Failed to read timeout from hardware\n"); + else { +@@ -510,7 +510,7 @@ static int redrat3_set_timeout(struct rc_dev *rc_dev, unsigned int timeoutus) + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), RR3_SET_IR_PARAM, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + RR3_IR_IO_SIG_TIMEOUT, 0, timeout, sizeof(*timeout), +- HZ * 25); ++ 25000); + dev_dbg(dev, "set ir parm timeout %d ret 0x%02x\n", + be32_to_cpu(*timeout), ret); + +@@ -542,32 +542,32 @@ static void redrat3_reset(struct redrat3_dev *rr3) + *val = 0x01; + rc = usb_control_msg(udev, rxpipe, RR3_RESET, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- RR3_CPUCS_REG_ADDR, 0, val, len, HZ * 25); ++ RR3_CPUCS_REG_ADDR, 0, val, len, 25000); + dev_dbg(dev, "reset returned 0x%02x\n", rc); + + *val = length_fuzz; + rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +- RR3_IR_IO_LENGTH_FUZZ, 0, val, len, HZ * 25); ++ RR3_IR_IO_LENGTH_FUZZ, 0, val, len, 25000); + dev_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc); + + *val = (65536 - (minimum_pause * 2000)) / 256; + rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +- RR3_IR_IO_MIN_PAUSE, 0, val, len, HZ * 25); ++ RR3_IR_IO_MIN_PAUSE, 0, val, len, 25000); + dev_dbg(dev, "set ir parm min pause %d rc 0x%02x\n", *val, rc); + + *val = periods_measure_carrier; + rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +- RR3_IR_IO_PERIODS_MF, 0, val, len, HZ * 25); ++ RR3_IR_IO_PERIODS_MF, 0, val, len, 25000); + dev_dbg(dev, "set ir parm periods measure carrier %d rc 0x%02x", *val, + rc); + + *val = RR3_DRIVER_MAXLENS; + rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +- RR3_IR_IO_MAX_LENGTHS, 0, val, len, HZ * 25); ++ RR3_IR_IO_MAX_LENGTHS, 0, val, len, 25000); + dev_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc); + + kfree(val); +@@ -585,7 +585,7 @@ static void redrat3_get_firmware_rev(struct redrat3_dev *rr3) + rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0), + RR3_FW_VERSION, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- 0, 0, buffer, RR3_FW_VERSION_LEN, HZ * 5); ++ 0, 0, buffer, RR3_FW_VERSION_LEN, 5000); + + if (rc >= 0) + dev_info(rr3->dev, "Firmware rev: %s", buffer); +@@ -825,14 +825,14 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf, + + pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress); + ret = usb_bulk_msg(rr3->udev, pipe, irdata, +- sendbuf_len, &ret_len, 10 * HZ); ++ sendbuf_len, &ret_len, 10000); + dev_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret); + + /* now tell the hardware to transmit what we sent it */ + pipe = usb_rcvctrlpipe(rr3->udev, 0); + ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- 0, 0, irdata, 2, HZ * 10); ++ 0, 0, irdata, 2, 10000); + + if (ret < 0) + dev_err(dev, "Error: control msg send failed, rc %d\n", ret); +diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c +index b91a1e845b972..506f52c1af101 100644 +--- a/drivers/media/spi/cxd2880-spi.c ++++ b/drivers/media/spi/cxd2880-spi.c +@@ -618,7 +618,7 @@ fail_frontend: + fail_attach: + dvb_unregister_adapter(&dvb_spi->adapter); + fail_adapter: +- if (!dvb_spi->vcc_supply) ++ if (dvb_spi->vcc_supply) + regulator_disable(dvb_spi->vcc_supply); + fail_regulator: + kfree(dvb_spi); +diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c +index 75617709c8ce2..82620613d56b8 100644 +--- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c ++++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c +@@ -564,6 +564,10 @@ static int vidtv_bridge_remove(struct platform_device *pdev) + + static void vidtv_bridge_dev_release(struct device *dev) + { ++ struct vidtv_dvb *dvb; ++ ++ dvb = dev_get_drvdata(dev); ++ kfree(dvb); + } + + static struct platform_device vidtv_bridge_dev = { +diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c +index 78e6fd600d8ef..44247049a3190 100644 +--- a/drivers/media/tuners/msi001.c ++++ b/drivers/media/tuners/msi001.c +@@ -442,6 +442,13 @@ static int msi001_probe(struct spi_device *spi) + V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1); + dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops, + V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000); ++ if (dev->hdl.error) { ++ ret = dev->hdl.error; ++ dev_err(&spi->dev, "Could not initialize controls\n"); ++ /* control init failed, free handler */ ++ goto err_ctrl_handler_free; ++ } ++ + v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false); + dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops, + V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1); +diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c +index fefb2625f6558..75ddf7ed1faff 100644 +--- a/drivers/media/tuners/si2157.c ++++ b/drivers/media/tuners/si2157.c +@@ -90,7 +90,7 @@ static int si2157_init(struct dvb_frontend *fe) + dev_dbg(&client->dev, "\n"); + + /* Try to get Xtal trim property, to verify tuner still running */ +- memcpy(cmd.args, "\x15\x00\x04\x02", 4); ++ memcpy(cmd.args, "\x15\x00\x02\x04", 4); + cmd.wlen = 4; + cmd.rlen = 4; + ret = si2157_cmd_execute(client, &cmd); +diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c +index 5d38171b7638c..bfeb92d93de39 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -87,7 +87,7 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, + 0, + fc_usb->data, + sizeof(u32), +- B2C2_WAIT_FOR_OPERATION_RDW * HZ); ++ B2C2_WAIT_FOR_OPERATION_RDW); + + if (ret != sizeof(u32)) { + err("error while %s dword from %d (%d).", read ? "reading" : +@@ -155,7 +155,7 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, + wIndex, + fc_usb->data, + buflen, +- nWaitTime * HZ); ++ nWaitTime); + if (ret != buflen) + ret = -EIO; + +@@ -248,13 +248,13 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, + /* DKT 020208 - add this to support special case of DiSEqC */ + case USB_FUNC_I2C_CHECKWRITE: + pipe = B2C2_USB_CTRL_PIPE_OUT; +- nWaitTime = 2; ++ nWaitTime = 2000; + request_type |= USB_DIR_OUT; + break; + case USB_FUNC_I2C_READ: + case USB_FUNC_I2C_REPEATREAD: + pipe = B2C2_USB_CTRL_PIPE_IN; +- nWaitTime = 2; ++ nWaitTime = 2000; + request_type |= USB_DIR_IN; + break; + default: +@@ -281,7 +281,7 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, + wIndex, + fc_usb->data, + buflen, +- nWaitTime * HZ); ++ nWaitTime); + + if (ret != buflen) + ret = -EIO; +diff --git a/drivers/media/usb/b2c2/flexcop-usb.h b/drivers/media/usb/b2c2/flexcop-usb.h +index 2f230bf72252b..c7cca1a5ee59d 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.h ++++ b/drivers/media/usb/b2c2/flexcop-usb.h +@@ -91,13 +91,13 @@ typedef enum { + UTILITY_SRAM_TESTVERIFY = 0x16, + } flexcop_usb_utility_function_t; + +-#define B2C2_WAIT_FOR_OPERATION_RW (1*HZ) +-#define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ) +-#define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ) ++#define B2C2_WAIT_FOR_OPERATION_RW 1000 ++#define B2C2_WAIT_FOR_OPERATION_RDW 3000 ++#define B2C2_WAIT_FOR_OPERATION_WDW 1000 + +-#define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ) +-#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ) +-#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ) ++#define B2C2_WAIT_FOR_OPERATION_V8READ 3000 ++#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3000 ++#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3000 + + typedef enum { + V8_MEMORY_PAGE_DVB_CI = 0x20, +diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c +index 76aac06f9fb8e..cba03b2864738 100644 +--- a/drivers/media/usb/cpia2/cpia2_usb.c ++++ b/drivers/media/usb/cpia2/cpia2_usb.c +@@ -550,7 +550,7 @@ static int write_packet(struct usb_device *udev, + 0, /* index */ + buf, /* buffer */ + size, +- HZ); ++ 1000); + + kfree(buf); + return ret; +@@ -582,7 +582,7 @@ static int read_packet(struct usb_device *udev, + 0, /* index */ + buf, /* buffer */ + size, +- HZ); ++ 1000); + + if (ret >= 0) + memcpy(registers, buf, size); +diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c +index 7865fa0a82957..cd5861a30b6f8 100644 +--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c ++++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c +@@ -931,8 +931,6 @@ static int mxl111sf_init(struct dvb_usb_device *d) + .len = sizeof(eeprom), .buf = eeprom }, + }; + +- mutex_init(&state->msg_lock); +- + ret = get_chip_info(state); + if (mxl_fail(ret)) + pr_err("failed to get chip info during probe"); +@@ -1074,6 +1072,14 @@ static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, + return 0; + } + ++static int mxl111sf_probe(struct dvb_usb_device *dev) ++{ ++ struct mxl111sf_state *state = d_to_priv(dev); ++ ++ mutex_init(&state->msg_lock); ++ return 0; ++} ++ + static struct dvb_usb_device_properties mxl111sf_props_dvbt = { + .driver_name = KBUILD_MODNAME, + .owner = THIS_MODULE, +@@ -1083,6 +1089,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = { + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + ++ .probe = mxl111sf_probe, + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_dvbt, + .tuner_attach = mxl111sf_attach_tuner, +@@ -1124,6 +1131,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = { + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + ++ .probe = mxl111sf_probe, + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_atsc, + .tuner_attach = mxl111sf_attach_tuner, +@@ -1165,6 +1173,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = { + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + ++ .probe = mxl111sf_probe, + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_mh, + .tuner_attach = mxl111sf_attach_tuner, +@@ -1233,6 +1242,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + ++ .probe = mxl111sf_probe, + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_atsc_mh, + .tuner_attach = mxl111sf_attach_tuner, +@@ -1311,6 +1321,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = { + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + ++ .probe = mxl111sf_probe, + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_mercury, + .tuner_attach = mxl111sf_attach_tuner, +@@ -1381,6 +1392,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = { + .generic_bulk_ctrl_endpoint = 0x02, + .generic_bulk_ctrl_endpoint_response = 0x81, + ++ .probe = mxl111sf_probe, + .i2c_algo = &mxl111sf_i2c_algo, + .frontend_attach = mxl111sf_frontend_attach_mercury_mh, + .tuner_attach = mxl111sf_attach_tuner, +diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c +index 1c39b61cde29b..86788771175b7 100644 +--- a/drivers/media/usb/dvb-usb/az6027.c ++++ b/drivers/media/usb/dvb-usb/az6027.c +@@ -391,6 +391,7 @@ static struct rc_map_table rc_map_az6027_table[] = { + /* remote control stuff (does not work with my box) */ + static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state) + { ++ *state = REMOTE_NO_KEY_PRESSED; + return 0; + } + +diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c +index 70219b3e85666..7ea8f68b0f458 100644 +--- a/drivers/media/usb/dvb-usb/dib0700_core.c ++++ b/drivers/media/usb/dvb-usb/dib0700_core.c +@@ -618,8 +618,6 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) + deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint); + if (onoff) + st->channel_state |= 1 << (adap->id); +- else +- st->channel_state |= 1 << ~(adap->id); + } else { + if (onoff) + st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2); +diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c +index 02b51d1a1b67c..aff60c10cb0b2 100644 +--- a/drivers/media/usb/dvb-usb/dibusb-common.c ++++ b/drivers/media/usb/dvb-usb/dibusb-common.c +@@ -223,7 +223,7 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) + u8 *buf; + int rc; + +- buf = kmalloc(2, GFP_KERNEL); ++ buf = kzalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + +diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c +index f0e686b05dc63..ca75ebdc10b37 100644 +--- a/drivers/media/usb/dvb-usb/dw2102.c ++++ b/drivers/media/usb/dvb-usb/dw2102.c +@@ -2150,46 +2150,153 @@ static struct dvb_usb_device_properties s6x0_properties = { + } + }; + +-static const struct dvb_usb_device_description d1100 = { +- "Prof 1100 USB ", +- {&dw2102_table[PROF_1100], NULL}, +- {NULL}, +-}; ++static struct dvb_usb_device_properties p1100_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .size_of_priv = sizeof(struct dw2102_state), ++ .firmware = P1100_FIRMWARE, ++ .no_reconnect = 1, + +-static const struct dvb_usb_device_description d660 = { +- "TeVii S660 USB", +- {&dw2102_table[TEVII_S660], NULL}, +- {NULL}, +-}; ++ .i2c_algo = &s6x0_i2c_algo, ++ .rc.core = { ++ .rc_interval = 150, ++ .rc_codes = RC_MAP_TBS_NEC, ++ .module_name = "dw2102", ++ .allowed_protos = RC_PROTO_BIT_NEC, ++ .rc_query = prof_rc_query, ++ }, + +-static const struct dvb_usb_device_description d480_1 = { +- "TeVii S480.1 USB", +- {&dw2102_table[TEVII_S480_1], NULL}, +- {NULL}, ++ .generic_bulk_ctrl_endpoint = 0x81, ++ .num_adapters = 1, ++ .download_firmware = dw2102_load_firmware, ++ .read_mac_address = s6x0_read_mac_address, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = stv0288_frontend_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } ++ }, ++ .num_device_descs = 1, ++ .devices = { ++ {"Prof 1100 USB ", ++ {&dw2102_table[PROF_1100], NULL}, ++ {NULL}, ++ }, ++ } + }; + +-static const struct dvb_usb_device_description d480_2 = { +- "TeVii S480.2 USB", +- {&dw2102_table[TEVII_S480_2], NULL}, +- {NULL}, +-}; ++static struct dvb_usb_device_properties s660_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .size_of_priv = sizeof(struct dw2102_state), ++ .firmware = S660_FIRMWARE, ++ .no_reconnect = 1, + +-static const struct dvb_usb_device_description d7500 = { +- "Prof 7500 USB DVB-S2", +- {&dw2102_table[PROF_7500], NULL}, +- {NULL}, +-}; ++ .i2c_algo = &s6x0_i2c_algo, ++ .rc.core = { ++ .rc_interval = 150, ++ .rc_codes = RC_MAP_TEVII_NEC, ++ .module_name = "dw2102", ++ .allowed_protos = RC_PROTO_BIT_NEC, ++ .rc_query = dw2102_rc_query, ++ }, + +-static const struct dvb_usb_device_description d421 = { +- "TeVii S421 PCI", +- {&dw2102_table[TEVII_S421], NULL}, +- {NULL}, ++ .generic_bulk_ctrl_endpoint = 0x81, ++ .num_adapters = 1, ++ .download_firmware = dw2102_load_firmware, ++ .read_mac_address = s6x0_read_mac_address, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = ds3000_frontend_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } ++ }, ++ .num_device_descs = 3, ++ .devices = { ++ {"TeVii S660 USB", ++ {&dw2102_table[TEVII_S660], NULL}, ++ {NULL}, ++ }, ++ {"TeVii S480.1 USB", ++ {&dw2102_table[TEVII_S480_1], NULL}, ++ {NULL}, ++ }, ++ {"TeVii S480.2 USB", ++ {&dw2102_table[TEVII_S480_2], NULL}, ++ {NULL}, ++ }, ++ } + }; + +-static const struct dvb_usb_device_description d632 = { +- "TeVii S632 USB", +- {&dw2102_table[TEVII_S632], NULL}, +- {NULL}, ++static struct dvb_usb_device_properties p7500_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .size_of_priv = sizeof(struct dw2102_state), ++ .firmware = P7500_FIRMWARE, ++ .no_reconnect = 1, ++ ++ .i2c_algo = &s6x0_i2c_algo, ++ .rc.core = { ++ .rc_interval = 150, ++ .rc_codes = RC_MAP_TBS_NEC, ++ .module_name = "dw2102", ++ .allowed_protos = RC_PROTO_BIT_NEC, ++ .rc_query = prof_rc_query, ++ }, ++ ++ .generic_bulk_ctrl_endpoint = 0x81, ++ .num_adapters = 1, ++ .download_firmware = dw2102_load_firmware, ++ .read_mac_address = s6x0_read_mac_address, ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .frontend_attach = prof_7500_frontend_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ }, ++ } }, ++ } ++ }, ++ .num_device_descs = 1, ++ .devices = { ++ {"Prof 7500 USB DVB-S2", ++ {&dw2102_table[PROF_7500], NULL}, ++ {NULL}, ++ }, ++ } + }; + + static struct dvb_usb_device_properties su3000_properties = { +@@ -2273,6 +2380,59 @@ static struct dvb_usb_device_properties su3000_properties = { + } + }; + ++static struct dvb_usb_device_properties s421_properties = { ++ .caps = DVB_USB_IS_AN_I2C_ADAPTER, ++ .usb_ctrl = DEVICE_SPECIFIC, ++ .size_of_priv = sizeof(struct dw2102_state), ++ .power_ctrl = su3000_power_ctrl, ++ .num_adapters = 1, ++ .identify_state = su3000_identify_state, ++ .i2c_algo = &su3000_i2c_algo, ++ ++ .rc.core = { ++ .rc_interval = 150, ++ .rc_codes = RC_MAP_SU3000, ++ .module_name = "dw2102", ++ .allowed_protos = RC_PROTO_BIT_RC5, ++ .rc_query = su3000_rc_query, ++ }, ++ ++ .read_mac_address = su3000_read_mac_address, ++ ++ .generic_bulk_ctrl_endpoint = 0x01, ++ ++ .adapter = { ++ { ++ .num_frontends = 1, ++ .fe = {{ ++ .streaming_ctrl = su3000_streaming_ctrl, ++ .frontend_attach = m88rs2000_frontend_attach, ++ .stream = { ++ .type = USB_BULK, ++ .count = 8, ++ .endpoint = 0x82, ++ .u = { ++ .bulk = { ++ .buffersize = 4096, ++ } ++ } ++ } ++ } }, ++ } ++ }, ++ .num_device_descs = 2, ++ .devices = { ++ { "TeVii S421 PCI", ++ { &dw2102_table[TEVII_S421], NULL }, ++ { NULL }, ++ }, ++ { "TeVii S632 USB", ++ { &dw2102_table[TEVII_S632], NULL }, ++ { NULL }, ++ }, ++ } ++}; ++ + static struct dvb_usb_device_properties t220_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, +@@ -2390,101 +2550,33 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { + static int dw2102_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { +- int retval = -ENOMEM; +- struct dvb_usb_device_properties *p1100; +- struct dvb_usb_device_properties *s660; +- struct dvb_usb_device_properties *p7500; +- struct dvb_usb_device_properties *s421; +- +- p1100 = kmemdup(&s6x0_properties, +- sizeof(struct dvb_usb_device_properties), GFP_KERNEL); +- if (!p1100) +- goto err0; +- +- /* copy default structure */ +- /* fill only different fields */ +- p1100->firmware = P1100_FIRMWARE; +- p1100->devices[0] = d1100; +- p1100->rc.core.rc_query = prof_rc_query; +- p1100->rc.core.rc_codes = RC_MAP_TBS_NEC; +- p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach; +- +- s660 = kmemdup(&s6x0_properties, +- sizeof(struct dvb_usb_device_properties), GFP_KERNEL); +- if (!s660) +- goto err1; +- +- s660->firmware = S660_FIRMWARE; +- s660->num_device_descs = 3; +- s660->devices[0] = d660; +- s660->devices[1] = d480_1; +- s660->devices[2] = d480_2; +- s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach; +- +- p7500 = kmemdup(&s6x0_properties, +- sizeof(struct dvb_usb_device_properties), GFP_KERNEL); +- if (!p7500) +- goto err2; +- +- p7500->firmware = P7500_FIRMWARE; +- p7500->devices[0] = d7500; +- p7500->rc.core.rc_query = prof_rc_query; +- p7500->rc.core.rc_codes = RC_MAP_TBS_NEC; +- p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach; +- +- +- s421 = kmemdup(&su3000_properties, +- sizeof(struct dvb_usb_device_properties), GFP_KERNEL); +- if (!s421) +- goto err3; +- +- s421->num_device_descs = 2; +- s421->devices[0] = d421; +- s421->devices[1] = d632; +- s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach; +- +- if (0 == dvb_usb_device_init(intf, &dw2102_properties, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, &dw2104_properties, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, &dw3101_properties, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, &s6x0_properties, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, p1100, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, s660, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, p7500, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, s421, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, &su3000_properties, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, &t220_properties, +- THIS_MODULE, NULL, adapter_nr) || +- 0 == dvb_usb_device_init(intf, &tt_s2_4600_properties, +- THIS_MODULE, NULL, adapter_nr)) { +- +- /* clean up copied properties */ +- kfree(s421); +- kfree(p7500); +- kfree(s660); +- kfree(p1100); ++ if (!(dvb_usb_device_init(intf, &dw2102_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &dw2104_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &dw3101_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &s6x0_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &p1100_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &s660_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &p7500_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &s421_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &su3000_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &t220_properties, ++ THIS_MODULE, NULL, adapter_nr) && ++ dvb_usb_device_init(intf, &tt_s2_4600_properties, ++ THIS_MODULE, NULL, adapter_nr))) { + + return 0; + } + +- retval = -ENODEV; +- kfree(s421); +-err3: +- kfree(p7500); +-err2: +- kfree(s660); +-err1: +- kfree(p1100); +-err0: +- return retval; ++ return -ENODEV; + } + + static void dw2102_disconnect(struct usb_interface *intf) +diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c +index 4bb5b82599a79..691e05833db19 100644 +--- a/drivers/media/usb/dvb-usb/m920x.c ++++ b/drivers/media/usb/dvb-usb/m920x.c +@@ -274,6 +274,13 @@ static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu + /* Should check for ack here, if we knew how. */ + } + if (msg[i].flags & I2C_M_RD) { ++ char *read = kmalloc(1, GFP_KERNEL); ++ if (!read) { ++ ret = -ENOMEM; ++ kfree(read); ++ goto unlock; ++ } ++ + for (j = 0; j < msg[i].len; j++) { + /* Last byte of transaction? + * Send STOP, otherwise send ACK. */ +@@ -281,9 +288,12 @@ static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int nu + + if ((ret = m920x_read(d->udev, M9206_I2C, 0x0, + 0x20 | stop, +- &msg[i].buf[j], 1)) != 0) ++ read, 1)) != 0) + goto unlock; ++ msg[i].buf[j] = read[0]; + } ++ ++ kfree(read); + } else { + for (j = 0; j < msg[i].len; j++) { + /* Last byte of transaction? Then send STOP. */ +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index c1e0dccb74088..ebc430b05f21c 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -3625,8 +3625,10 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, + + if (dev->is_audio_only) { + retval = em28xx_audio_setup(dev); +- if (retval) +- return -ENODEV; ++ if (retval) { ++ retval = -ENODEV; ++ goto err_deinit_media; ++ } + em28xx_init_extension(dev); + + return 0; +@@ -3645,7 +3647,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, + dev_err(&dev->intf->dev, + "%s: em28xx_i2c_register bus 0 - error [%d]!\n", + __func__, retval); +- return retval; ++ goto err_deinit_media; + } + + /* register i2c bus 1 */ +@@ -3661,9 +3663,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, + "%s: em28xx_i2c_register bus 1 - error [%d]!\n", + __func__, retval); + +- em28xx_i2c_unregister(dev, 0); +- +- return retval; ++ goto err_unreg_i2c; + } + } + +@@ -3671,6 +3671,12 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, + em28xx_card_setup(dev); + + return 0; ++ ++err_unreg_i2c: ++ em28xx_i2c_unregister(dev, 0); ++err_deinit_media: ++ em28xx_unregister_media_device(dev); ++ return retval; + } + + static int em28xx_duplicate_dev(struct em28xx *dev) +@@ -4139,8 +4145,11 @@ static void em28xx_usb_disconnect(struct usb_interface *intf) + + em28xx_close_extension(dev); + +- if (dev->dev_next) ++ if (dev->dev_next) { ++ em28xx_close_extension(dev->dev_next); + em28xx_release_resources(dev->dev_next); ++ } ++ + em28xx_release_resources(dev); + + if (dev->dev_next) { +diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c +index 584fa400cd7d8..c837cc528a335 100644 +--- a/drivers/media/usb/em28xx/em28xx-core.c ++++ b/drivers/media/usb/em28xx/em28xx-core.c +@@ -89,7 +89,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, + mutex_lock(&dev->ctrl_urb_lock); + ret = usb_control_msg(udev, pipe, req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- 0x0000, reg, dev->urb_buf, len, HZ); ++ 0x0000, reg, dev->urb_buf, len, 1000); + if (ret < 0) { + em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x failed with error %i\n", + pipe, +@@ -158,7 +158,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, + memcpy(dev->urb_buf, buf, len); + ret = usb_control_msg(udev, pipe, req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- 0x0000, reg, dev->urb_buf, len, HZ); ++ 0x0000, reg, dev->urb_buf, len, 1000); + mutex_unlock(&dev->ctrl_urb_lock); + + if (ret < 0) { +@@ -1154,8 +1154,9 @@ int em28xx_suspend_extension(struct em28xx *dev) + dev_info(&dev->intf->dev, "Suspending extensions\n"); + mutex_lock(&em28xx_devlist_mutex); + list_for_each_entry(ops, &em28xx_extension_devlist, next) { +- if (ops->suspend) +- ops->suspend(dev); ++ if (!ops->suspend) ++ continue; ++ ops->suspend(dev); + if (dev->dev_next) + ops->suspend(dev->dev_next); + } +diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +index d38dee1792e41..3915d551d59e7 100644 +--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c ++++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +@@ -1467,7 +1467,7 @@ static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) + for (address = 0; address < fwsize; address += 0x800) { + memcpy(fw_ptr, fw_entry->data + address, 0x800); + ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, +- 0, fw_ptr, 0x800, HZ); ++ 0, fw_ptr, 0x800, 1000); + } + + trace_firmware("Upload done, releasing device's CPU"); +@@ -1605,7 +1605,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw) + ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]); + + ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt, +- &actual_length, HZ); ++ &actual_length, 1000); + ret |= (actual_length != bcnt); + if (ret) break; + fw_done += bcnt; +@@ -3438,7 +3438,7 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, + 0xa0,0xc0, + address,0, + hdw->fw_buffer+address, +- 0x800,HZ); ++ 0x800,1000); + if (ret < 0) break; + } + +@@ -3977,7 +3977,7 @@ void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) + /* Write the CPUCS register on the 8051. The lsb of the register + is the reset bit; a 1 asserts reset while a 0 clears it. */ + pipe = usb_sndctrlpipe(hdw->usb_dev, 0); +- ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ); ++ ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,1000); + if (ret < 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "cpureset_assert(%d) error=%d",val,ret); +diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c +index 3b0e4ed75d99c..acf18e2251a52 100644 +--- a/drivers/media/usb/s2255/s2255drv.c ++++ b/drivers/media/usb/s2255/s2255drv.c +@@ -1882,7 +1882,7 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, + Value, Index, buf, +- TransferBufferLength, HZ * 5); ++ TransferBufferLength, USB_CTRL_SET_TIMEOUT); + + if (r >= 0) + memcpy(TransferBuffer, buf, TransferBufferLength); +@@ -1891,7 +1891,7 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request, + r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), + Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE, + Value, Index, buf, +- TransferBufferLength, HZ * 5); ++ TransferBufferLength, USB_CTRL_SET_TIMEOUT); + } + kfree(buf); + return r; +diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c +index b4f8bc5db1389..4e1698f788187 100644 +--- a/drivers/media/usb/stk1160/stk1160-core.c ++++ b/drivers/media/usb/stk1160/stk1160-core.c +@@ -65,7 +65,7 @@ int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value) + return -ENOMEM; + ret = usb_control_msg(dev->udev, pipe, 0x00, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- 0x00, reg, buf, sizeof(u8), HZ); ++ 0x00, reg, buf, sizeof(u8), 1000); + if (ret < 0) { + stk1160_err("read failed on reg 0x%x (%d)\n", + reg, ret); +@@ -85,7 +85,7 @@ int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value) + + ret = usb_control_msg(dev->udev, pipe, 0x01, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- value, reg, NULL, 0, HZ); ++ value, reg, NULL, 0, 1000); + if (ret < 0) { + stk1160_err("write failed on reg 0x%x (%d)\n", + reg, ret); +diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c +index 3f650ede0c3dc..e293f6f3d1bc9 100644 +--- a/drivers/media/usb/tm6000/tm6000-video.c ++++ b/drivers/media/usb/tm6000/tm6000-video.c +@@ -852,8 +852,7 @@ static int vidioc_querycap(struct file *file, void *priv, + struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; + + strscpy(cap->driver, "tm6000", sizeof(cap->driver)); +- strscpy(cap->card, "Trident TVMaster TM5600/6000/6010", +- sizeof(cap->card)); ++ strscpy(cap->card, "Trident TM5600/6000/6010", sizeof(cap->card)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | + V4L2_CAP_DEVICE_CAPS; +diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c +index bfda46a36dc50..38822cedd93a9 100644 +--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c ++++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c +@@ -327,7 +327,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, + result = mutex_lock_interruptible(&dec->usb_mutex); + if (result) { + printk("%s: Failed to lock usb mutex.\n", __func__); +- goto err; ++ goto err_free; + } + + b[0] = 0xaa; +@@ -349,7 +349,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, + if (result) { + printk("%s: command bulk message failed: error %d\n", + __func__, result); +- goto err; ++ goto err_mutex_unlock; + } + + result = usb_bulk_msg(dec->udev, dec->result_pipe, b, +@@ -358,7 +358,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, + if (result) { + printk("%s: result bulk message failed: error %d\n", + __func__, result); +- goto err; ++ goto err_mutex_unlock; + } else { + if (debug) { + printk(KERN_DEBUG "%s: result: %*ph\n", +@@ -371,9 +371,9 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, + memcpy(cmd_result, &b[4], b[3]); + } + +-err: ++err_mutex_unlock: + mutex_unlock(&dec->usb_mutex); +- ++err_free: + kfree(b); + return result; + } +diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c +index 6acb8013de08b..c9d208677bcd8 100644 +--- a/drivers/media/usb/uvc/uvc_v4l2.c ++++ b/drivers/media/usb/uvc/uvc_v4l2.c +@@ -472,10 +472,13 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, + uvc_simplify_fraction(&timeperframe.numerator, + &timeperframe.denominator, 8, 333); + +- if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + parm->parm.capture.timeperframe = timeperframe; +- else ++ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; ++ } else { + parm->parm.output.timeperframe = timeperframe; ++ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; ++ } + + return 0; + } +diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c +index e16464606b140..1b4cc934109e8 100644 +--- a/drivers/media/usb/uvc/uvc_video.c ++++ b/drivers/media/usb/uvc/uvc_video.c +@@ -115,6 +115,11 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, + case 5: /* Invalid unit */ + case 6: /* Invalid control */ + case 7: /* Invalid Request */ ++ /* ++ * The firmware has not properly implemented ++ * the control or there has been a HW error. ++ */ ++ return -EIO; + case 8: /* Invalid value within range */ + return -EINVAL; + default: /* reserved or unknown */ +@@ -1958,6 +1963,10 @@ static int uvc_video_start_transfer(struct uvc_streaming *stream, + if (ep == NULL) + return -EIO; + ++ /* Reject broken descriptors. */ ++ if (usb_endpoint_maxp(&ep->desc) == 0) ++ return -EIO; ++ + ret = uvc_init_video_bulk(stream, ep, gfp_flags); + } + +diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h +index cce5e38133cd3..c3ea6a53869f5 100644 +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -189,7 +189,7 @@ + /* Maximum status buffer size in bytes of interrupt URB. */ + #define UVC_MAX_STATUS_SIZE 16 + +-#define UVC_CTRL_CONTROL_TIMEOUT 500 ++#define UVC_CTRL_CONTROL_TIMEOUT 5000 + #define UVC_CTRL_STREAMING_TIMEOUT 5000 + + /* Maximum allowed number of control mappings per device */ +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index 47aff3b197426..80aaf07b16f28 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -744,10 +744,6 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64, + /* + * x86 is the only compat architecture with different struct alignment + * between 32-bit and 64-bit tasks. +- * +- * On all other architectures, v4l2_event32 and v4l2_event32_time32 are +- * the same as v4l2_event and v4l2_event_time32, so we can use the native +- * handlers, converting v4l2_event to v4l2_event_time32 if necessary. + */ + struct v4l2_event32 { + __u32 type; +@@ -765,21 +761,6 @@ struct v4l2_event32 { + __u32 reserved[8]; + }; + +-#ifdef CONFIG_COMPAT_32BIT_TIME +-struct v4l2_event32_time32 { +- __u32 type; +- union { +- compat_s64 value64; +- __u8 data[64]; +- } u; +- __u32 pending; +- __u32 sequence; +- struct old_timespec32 timestamp; +- __u32 id; +- __u32 reserved[8]; +-}; +-#endif +- + static int put_v4l2_event32(struct v4l2_event *p64, + struct v4l2_event32 __user *p32) + { +@@ -795,7 +776,22 @@ static int put_v4l2_event32(struct v4l2_event *p64, + return 0; + } + ++#endif ++ + #ifdef CONFIG_COMPAT_32BIT_TIME ++struct v4l2_event32_time32 { ++ __u32 type; ++ union { ++ compat_s64 value64; ++ __u8 data[64]; ++ } u; ++ __u32 pending; ++ __u32 sequence; ++ struct old_timespec32 timestamp; ++ __u32 id; ++ __u32 reserved[8]; ++}; ++ + static int put_v4l2_event32_time32(struct v4l2_event *p64, + struct v4l2_event32_time32 __user *p32) + { +@@ -811,7 +807,6 @@ static int put_v4l2_event32_time32(struct v4l2_event *p64, + return 0; + } + #endif +-#endif + + struct v4l2_edid32 { + __u32 pad; +@@ -873,9 +868,7 @@ static int put_v4l2_edid32(struct v4l2_edid *p64, + #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32) + #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32) + #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32) +-#ifdef CONFIG_X86_64 + #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32) +-#endif + #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32) + #endif + +@@ -929,10 +922,10 @@ unsigned int v4l2_compat_translate_cmd(unsigned int cmd) + #ifdef CONFIG_X86_64 + case VIDIOC_DQEVENT32: + return VIDIOC_DQEVENT; ++#endif + #ifdef CONFIG_COMPAT_32BIT_TIME + case VIDIOC_DQEVENT32_TIME32: + return VIDIOC_DQEVENT; +-#endif + #endif + } + return cmd; +@@ -1025,10 +1018,10 @@ int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd) + #ifdef CONFIG_X86_64 + case VIDIOC_DQEVENT32: + return put_v4l2_event32(parg, arg); ++#endif + #ifdef CONFIG_COMPAT_32BIT_TIME + case VIDIOC_DQEVENT32_TIME32: + return put_v4l2_event32_time32(parg, arg); +-#endif + #endif + } + return 0; +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 05d5db3d85e58..c7308a2a80a0f 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -869,7 +869,7 @@ static void v4l_print_default(const void *arg, bool write_only) + pr_cont("driver-specific ioctl\n"); + } + +-static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) ++static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl) + { + __u32 i; + +@@ -878,23 +878,41 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) + for (i = 0; i < c->count; i++) + c->controls[i].reserved2[0] = 0; + +- /* V4L2_CID_PRIVATE_BASE cannot be used as control class +- when using extended controls. +- Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL +- is it allowed for backwards compatibility. +- */ +- if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE) +- return 0; +- if (!c->which) +- return 1; ++ switch (c->which) { ++ case V4L2_CID_PRIVATE_BASE: ++ /* ++ * V4L2_CID_PRIVATE_BASE cannot be used as control class ++ * when using extended controls. ++ * Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL ++ * is it allowed for backwards compatibility. ++ */ ++ if (ioctl == VIDIOC_G_CTRL || ioctl == VIDIOC_S_CTRL) ++ return false; ++ break; ++ case V4L2_CTRL_WHICH_DEF_VAL: ++ /* Default value cannot be changed */ ++ if (ioctl == VIDIOC_S_EXT_CTRLS || ++ ioctl == VIDIOC_TRY_EXT_CTRLS) { ++ c->error_idx = c->count; ++ return false; ++ } ++ return true; ++ case V4L2_CTRL_WHICH_CUR_VAL: ++ return true; ++ case V4L2_CTRL_WHICH_REQUEST_VAL: ++ c->error_idx = c->count; ++ return false; ++ } ++ + /* Check that all controls are from the same control class. */ + for (i = 0; i < c->count; i++) { + if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) { +- c->error_idx = i; +- return 0; ++ c->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i : ++ c->count; ++ return false; + } + } +- return 1; ++ return true; + } + + static int check_fmt(struct file *file, enum v4l2_buf_type type) +@@ -2070,6 +2088,7 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, + static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) + { ++ struct video_device *vfd = video_devdata(file); + struct v4l2_streamparm *p = arg; + v4l2_std_id std; + int ret = check_fmt(file, p->type); +@@ -2081,7 +2100,8 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + return -EINVAL; +- p->parm.capture.readbuffers = 2; ++ if (vfd->device_caps & V4L2_CAP_READWRITE) ++ p->parm.capture.readbuffers = 2; + ret = ops->vidioc_g_std(file, fh, &std); + if (ret == 0) + v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); +@@ -2187,7 +2207,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; +- if (check_ext_ctrls(&ctrls, 1)) { ++ if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) { + int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); + + if (ret == 0) +@@ -2206,6 +2226,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, + test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ctrl; ++ int ret; + + if (vfh && vfh->ctrl_handler) + return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); +@@ -2221,9 +2242,11 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, + ctrls.controls = &ctrl; + ctrl.id = p->id; + ctrl.value = p->value; +- if (check_ext_ctrls(&ctrls, 1)) +- return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); +- return -EINVAL; ++ if (!check_ext_ctrls(&ctrls, VIDIOC_S_CTRL)) ++ return -EINVAL; ++ ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls); ++ p->value = ctrl.value; ++ return ret; + } + + static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, +@@ -2243,8 +2266,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, + vfd, vfd->v4l2_dev->mdev, p); + if (ops->vidioc_g_ext_ctrls == NULL) + return -ENOTTY; +- return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : +- -EINVAL; ++ return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ? ++ ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL; + } + + static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, +@@ -2264,8 +2287,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, + vfd, vfd->v4l2_dev->mdev, p); + if (ops->vidioc_s_ext_ctrls == NULL) + return -ENOTTY; +- return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : +- -EINVAL; ++ return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ? ++ ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL; + } + + static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, +@@ -2285,8 +2308,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, + vfd, vfd->v4l2_dev->mdev, p); + if (ops->vidioc_try_ext_ctrls == NULL) + return -ENOTTY; +- return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : +- -EINVAL; ++ return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ? ++ ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL; + } + + /* +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index d062c2f8250f4..75a8c38df9394 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -263,7 +263,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + + ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev); + if (ret < 0) +- goto err; ++ goto err_unmap_nandirq; + + init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait); + +@@ -272,7 +272,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + if (ret != 0) { + dev_err(&dev->dev, "failed to install irq (%d)\n", + fsl_ifc_ctrl_dev->irq); +- goto err_irq; ++ goto err_unmap_nandirq; + } + + if (fsl_ifc_ctrl_dev->nand_irq) { +@@ -281,17 +281,16 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + if (ret != 0) { + dev_err(&dev->dev, "failed to install irq (%d)\n", + fsl_ifc_ctrl_dev->nand_irq); +- goto err_nandirq; ++ goto err_free_irq; + } + } + + return 0; + +-err_nandirq: +- free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev); +- irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq); +-err_irq: ++err_free_irq: + free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev); ++err_unmap_nandirq: ++ irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq); + irq_dispose_mapping(fsl_ifc_ctrl_dev->irq); + err: + iounmap(fsl_ifc_ctrl_dev->gregs); +diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c +index 45eed659b0c6d..8618702233002 100644 +--- a/drivers/memory/renesas-rpc-if.c ++++ b/drivers/memory/renesas-rpc-if.c +@@ -160,10 +160,62 @@ static const struct regmap_access_table rpcif_volatile_table = { + .n_yes_ranges = ARRAY_SIZE(rpcif_volatile_ranges), + }; + ++ ++/* ++ * Custom accessor functions to ensure SMRDR0 and SMWDR0 are always accessed ++ * with proper width. Requires SMENR_SPIDE to be correctly set before! ++ */ ++static int rpcif_reg_read(void *context, unsigned int reg, unsigned int *val) ++{ ++ struct rpcif *rpc = context; ++ ++ if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { ++ u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); ++ ++ if (spide == 0x8) { ++ *val = readb(rpc->base + reg); ++ return 0; ++ } else if (spide == 0xC) { ++ *val = readw(rpc->base + reg); ++ return 0; ++ } else if (spide != 0xF) { ++ return -EILSEQ; ++ } ++ } ++ ++ *val = readl(rpc->base + reg); ++ return 0; ++ ++} ++ ++static int rpcif_reg_write(void *context, unsigned int reg, unsigned int val) ++{ ++ struct rpcif *rpc = context; ++ ++ if (reg == RPCIF_SMRDR0 || reg == RPCIF_SMWDR0) { ++ u32 spide = readl(rpc->base + RPCIF_SMENR) & RPCIF_SMENR_SPIDE(0xF); ++ ++ if (spide == 0x8) { ++ writeb(val, rpc->base + reg); ++ return 0; ++ } else if (spide == 0xC) { ++ writew(val, rpc->base + reg); ++ return 0; ++ } else if (spide != 0xF) { ++ return -EILSEQ; ++ } ++ } ++ ++ writel(val, rpc->base + reg); ++ return 0; ++} ++ + static const struct regmap_config rpcif_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, ++ .reg_read = rpcif_reg_read, ++ .reg_write = rpcif_reg_write, + .fast_io = true, + .max_register = RPCIF_PHYINT, + .volatile_table = &rpcif_volatile_table, +@@ -173,17 +225,15 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct resource *res; +- void __iomem *base; + + rpc->dev = dev; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); +- base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(base)) +- return PTR_ERR(base); ++ rpc->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) ++ return PTR_ERR(rpc->base); + +- rpc->regmap = devm_regmap_init_mmio(&pdev->dev, base, +- &rpcif_regmap_config); ++ rpc->regmap = devm_regmap_init(&pdev->dev, NULL, rpc, &rpcif_regmap_config); + if (IS_ERR(rpc->regmap)) { + dev_err(&pdev->dev, + "failed to init regmap for rpcif, error %ld\n", +@@ -194,7 +244,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev) + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap"); + rpc->dirmap = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(rpc->dirmap)) +- rpc->dirmap = NULL; ++ return PTR_ERR(rpc->dirmap); + rpc->size = resource_size(res); + + rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); +@@ -354,20 +404,16 @@ void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, + nbytes = op->data.nbytes; + rpc->xferlen = nbytes; + +- rpc->enable |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)) | +- RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); ++ rpc->enable |= RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); + } + } + EXPORT_SYMBOL(rpcif_prepare); + + int rpcif_manual_xfer(struct rpcif *rpc) + { +- u32 smenr, smcr, pos = 0, max = 4; ++ u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4; + int ret = 0; + +- if (rpc->bus_size == 2) +- max = 8; +- + pm_runtime_get_sync(rpc->dev); + + regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, +@@ -378,37 +424,36 @@ int rpcif_manual_xfer(struct rpcif *rpc) + regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option); + regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy); + regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr); ++ regmap_write(rpc->regmap, RPCIF_SMADR, rpc->smadr); + smenr = rpc->enable; + + switch (rpc->dir) { + case RPCIF_DATA_OUT: + while (pos < rpc->xferlen) { +- u32 nbytes = rpc->xferlen - pos; +- u32 data[2]; ++ u32 bytes_left = rpc->xferlen - pos; ++ u32 nbytes, data[2]; + + smcr = rpc->smcr | RPCIF_SMCR_SPIE; +- if (nbytes > max) { +- nbytes = max; ++ ++ /* nbytes may only be 1, 2, 4, or 8 */ ++ nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); ++ if (bytes_left > nbytes) + smcr |= RPCIF_SMCR_SSLKP; +- } ++ ++ smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); ++ regmap_write(rpc->regmap, RPCIF_SMENR, smenr); + + memcpy(data, rpc->buffer + pos, nbytes); +- if (nbytes > 4) { ++ if (nbytes == 8) { + regmap_write(rpc->regmap, RPCIF_SMWDR1, + data[0]); + regmap_write(rpc->regmap, RPCIF_SMWDR0, + data[1]); +- } else if (nbytes > 2) { ++ } else { + regmap_write(rpc->regmap, RPCIF_SMWDR0, + data[0]); +- } else { +- regmap_write(rpc->regmap, RPCIF_SMWDR0, +- data[0] << 16); + } + +- regmap_write(rpc->regmap, RPCIF_SMADR, +- rpc->smadr + pos); +- regmap_write(rpc->regmap, RPCIF_SMENR, smenr); + regmap_write(rpc->regmap, RPCIF_SMCR, smcr); + ret = wait_msg_xfer_end(rpc); + if (ret) +@@ -448,14 +493,16 @@ int rpcif_manual_xfer(struct rpcif *rpc) + break; + } + while (pos < rpc->xferlen) { +- u32 nbytes = rpc->xferlen - pos; +- u32 data[2]; ++ u32 bytes_left = rpc->xferlen - pos; ++ u32 nbytes, data[2]; + +- if (nbytes > max) +- nbytes = max; ++ /* nbytes may only be 1, 2, 4, or 8 */ ++ nbytes = bytes_left >= max ? max : (1 << ilog2(bytes_left)); + + regmap_write(rpc->regmap, RPCIF_SMADR, + rpc->smadr + pos); ++ smenr &= ~RPCIF_SMENR_SPIDE(0xF); ++ smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); + regmap_write(rpc->regmap, RPCIF_SMENR, smenr); + regmap_write(rpc->regmap, RPCIF_SMCR, + rpc->smcr | RPCIF_SMCR_SPIE); +@@ -463,18 +510,14 @@ int rpcif_manual_xfer(struct rpcif *rpc) + if (ret) + goto err_out; + +- if (nbytes > 4) { ++ if (nbytes == 8) { + regmap_read(rpc->regmap, RPCIF_SMRDR1, + &data[0]); + regmap_read(rpc->regmap, RPCIF_SMRDR0, + &data[1]); +- } else if (nbytes > 2) { +- regmap_read(rpc->regmap, RPCIF_SMRDR0, +- &data[0]); +- } else { ++ } else { + regmap_read(rpc->regmap, RPCIF_SMRDR0, + &data[0]); +- data[0] >>= 16; + } + memcpy(rpc->buffer + pos, data, nbytes); + +diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c +index c3462dbc8c22b..6fc90f2160e93 100644 +--- a/drivers/memory/tegra/tegra20-emc.c ++++ b/drivers/memory/tegra/tegra20-emc.c +@@ -1117,4 +1117,5 @@ module_platform_driver(tegra_emc_driver); + + MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>"); + MODULE_DESCRIPTION("NVIDIA Tegra20 EMC driver"); ++MODULE_SOFTDEP("pre: governor_simpleondemand"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c +index acf36676e388d..487e4cc2951e0 100644 +--- a/drivers/memstick/core/ms_block.c ++++ b/drivers/memstick/core/ms_block.c +@@ -1736,7 +1736,7 @@ static int msb_init_card(struct memstick_dev *card) + msb->pages_in_block = boot_block->attr.block_size * 2; + msb->block_size = msb->page_size * msb->pages_in_block; + +- if (msb->page_size > PAGE_SIZE) { ++ if ((size_t)msb->page_size > PAGE_SIZE) { + /* this isn't supported by linux at all, anyway*/ + dbg("device page %d size isn't supported", msb->page_size); + return -EINVAL; +diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c +index f9a93b0565e15..435d4c058b20e 100644 +--- a/drivers/memstick/host/jmb38x_ms.c ++++ b/drivers/memstick/host/jmb38x_ms.c +@@ -882,7 +882,7 @@ static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt) + + iounmap(host->addr); + err_out_free: +- kfree(msh); ++ memstick_free_host(msh); + return NULL; + } + +diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c +index e79a0218c492e..1d35d147552d4 100644 +--- a/drivers/memstick/host/r592.c ++++ b/drivers/memstick/host/r592.c +@@ -838,15 +838,15 @@ static void r592_remove(struct pci_dev *pdev) + } + memstick_remove_host(dev->host); + ++ if (dev->dummy_dma_page) ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->dummy_dma_page, ++ dev->dummy_dma_page_physical_address); ++ + free_irq(dev->irq, dev); + iounmap(dev->mmio); + pci_release_regions(pdev); + pci_disable_device(pdev); + memstick_free_host(dev->host); +- +- if (dev->dummy_dma_page) +- dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->dummy_dma_page, +- dev->dummy_dma_page_physical_address); + } + + #ifdef CONFIG_PM_SLEEP +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index ca0edab91aeb6..d2f3452455389 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -1194,6 +1194,7 @@ config MFD_SI476X_CORE + config MFD_SIMPLE_MFD_I2C + tristate + depends on I2C ++ select MFD_CORE + select REGMAP_I2C + help + This driver creates a single register map with the intention for it +diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c +index 20cb294c75122..5d3715a28b28e 100644 +--- a/drivers/mfd/altera-sysmgr.c ++++ b/drivers/mfd/altera-sysmgr.c +@@ -153,7 +153,7 @@ static int sysmgr_probe(struct platform_device *pdev) + if (!base) + return -ENOMEM; + +- sysmgr_config.max_register = resource_size(res) - 3; ++ sysmgr_config.max_register = resource_size(res) - 4; + regmap = devm_regmap_init_mmio(dev, base, &sysmgr_config); + } + +diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c +index d2f5c073fdf31..559eb4d352b68 100644 +--- a/drivers/mfd/atmel-flexcom.c ++++ b/drivers/mfd/atmel-flexcom.c +@@ -87,8 +87,7 @@ static const struct of_device_id atmel_flexcom_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match); + +-#ifdef CONFIG_PM_SLEEP +-static int atmel_flexcom_resume(struct device *dev) ++static int __maybe_unused atmel_flexcom_resume_noirq(struct device *dev) + { + struct atmel_flexcom *ddata = dev_get_drvdata(dev); + int err; +@@ -105,16 +104,16 @@ static int atmel_flexcom_resume(struct device *dev) + + return 0; + } +-#endif + +-static SIMPLE_DEV_PM_OPS(atmel_flexcom_pm_ops, NULL, +- atmel_flexcom_resume); ++static const struct dev_pm_ops atmel_flexcom_pm_ops = { ++ .resume_noirq = atmel_flexcom_resume_noirq, ++}; + + static struct platform_driver atmel_flexcom_driver = { + .probe = atmel_flexcom_probe, + .driver = { + .name = "atmel_flexcom", +- .pm = &atmel_flexcom_pm_ops, ++ .pm = pm_ptr(&atmel_flexcom_pm_ops), + .of_match_table = atmel_flexcom_of_match, + }, + }; +diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c +index 83e676a096dc1..852129ea07666 100644 +--- a/drivers/mfd/dln2.c ++++ b/drivers/mfd/dln2.c +@@ -50,6 +50,7 @@ enum dln2_handle { + DLN2_HANDLE_GPIO, + DLN2_HANDLE_I2C, + DLN2_HANDLE_SPI, ++ DLN2_HANDLE_ADC, + DLN2_HANDLES + }; + +@@ -653,6 +654,7 @@ enum { + DLN2_ACPI_MATCH_GPIO = 0, + DLN2_ACPI_MATCH_I2C = 1, + DLN2_ACPI_MATCH_SPI = 2, ++ DLN2_ACPI_MATCH_ADC = 3, + }; + + static struct dln2_platform_data dln2_pdata_gpio = { +@@ -683,6 +685,16 @@ static struct mfd_cell_acpi_match dln2_acpi_match_spi = { + .adr = DLN2_ACPI_MATCH_SPI, + }; + ++/* Only one ADC port supported */ ++static struct dln2_platform_data dln2_pdata_adc = { ++ .handle = DLN2_HANDLE_ADC, ++ .port = 0, ++}; ++ ++static struct mfd_cell_acpi_match dln2_acpi_match_adc = { ++ .adr = DLN2_ACPI_MATCH_ADC, ++}; ++ + static const struct mfd_cell dln2_devs[] = { + { + .name = "dln2-gpio", +@@ -702,6 +714,12 @@ static const struct mfd_cell dln2_devs[] = { + .platform_data = &dln2_pdata_spi, + .pdata_size = sizeof(struct dln2_platform_data), + }, ++ { ++ .name = "dln2-adc", ++ .acpi_match = &dln2_acpi_match_adc, ++ .platform_data = &dln2_pdata_adc, ++ .pdata_size = sizeof(struct dln2_platform_data), ++ }, + }; + + static void dln2_stop(struct dln2_dev *dln2) +diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c +index 3f1d976eb67cb..f2ea6540a01e1 100644 +--- a/drivers/mfd/intel-lpss-acpi.c ++++ b/drivers/mfd/intel-lpss-acpi.c +@@ -136,6 +136,7 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev) + { + struct intel_lpss_platform_info *info; + const struct acpi_device_id *id; ++ int ret; + + id = acpi_match_device(intel_lpss_acpi_ids, &pdev->dev); + if (!id) +@@ -149,10 +150,14 @@ static int intel_lpss_acpi_probe(struct platform_device *pdev) + info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + info->irq = platform_get_irq(pdev, 0); + ++ ret = intel_lpss_probe(&pdev->dev, info); ++ if (ret) ++ return ret; ++ + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + +- return intel_lpss_probe(&pdev->dev, info); ++ return 0; + } + + static int intel_lpss_acpi_remove(struct platform_device *pdev) +diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c +index 79f5c6a18815a..684a011a63968 100644 +--- a/drivers/mfd/mfd-core.c ++++ b/drivers/mfd/mfd-core.c +@@ -198,6 +198,7 @@ static int mfd_add_device(struct device *parent, int id, + if (of_device_is_compatible(np, cell->of_compatible)) { + /* Ignore 'disabled' devices error free */ + if (!of_device_is_available(np)) { ++ of_node_put(np); + ret = 0; + goto fail_alias; + } +@@ -205,6 +206,7 @@ static int mfd_add_device(struct device *parent, int id, + ret = mfd_match_of_node_to_dev(pdev, np, cell); + if (ret == -EAGAIN) + continue; ++ of_node_put(np); + if (ret) + goto fail_alias; + +diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c +index 6fb206da27298..265464b5d7cc5 100644 +--- a/drivers/mfd/motorola-cpcap.c ++++ b/drivers/mfd/motorola-cpcap.c +@@ -202,6 +202,13 @@ static const struct of_device_id cpcap_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, cpcap_of_match); + ++static const struct spi_device_id cpcap_spi_ids[] = { ++ { .name = "cpcap", }, ++ { .name = "6556002", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(spi, cpcap_spi_ids); ++ + static const struct regmap_config cpcap_regmap_config = { + .reg_bits = 16, + .reg_stride = 4, +@@ -342,6 +349,7 @@ static struct spi_driver cpcap_driver = { + .pm = &cpcap_pm, + }, + .probe = cpcap_probe, ++ .id_table = cpcap_spi_ids, + }; + module_spi_driver(cpcap_driver); + +diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c +index 6b7956604a0f0..9890882db1ed3 100644 +--- a/drivers/mfd/sprd-sc27xx-spi.c ++++ b/drivers/mfd/sprd-sc27xx-spi.c +@@ -236,6 +236,12 @@ static const struct of_device_id sprd_pmic_match[] = { + }; + MODULE_DEVICE_TABLE(of, sprd_pmic_match); + ++static const struct spi_device_id sprd_pmic_spi_ids[] = { ++ { .name = "sc2731", .driver_data = (unsigned long)&sc2731_data }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(spi, sprd_pmic_spi_ids); ++ + static struct spi_driver sprd_pmic_driver = { + .driver = { + .name = "sc27xx-pmic", +@@ -243,6 +249,7 @@ static struct spi_driver sprd_pmic_driver = { + .pm = &sprd_pmic_pm_ops, + }, + .probe = sprd_pmic_probe, ++ .id_table = sprd_pmic_spi_ids, + }; + + static int __init sprd_pmic_init(void) +diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c +index 6e105cca27d47..67e2707af4bce 100644 +--- a/drivers/mfd/tps65910.c ++++ b/drivers/mfd/tps65910.c +@@ -436,15 +436,6 @@ static void tps65910_power_off(void) + + tps65910 = dev_get_drvdata(&tps65910_i2c_client->dev); + +- /* +- * The PWR_OFF bit needs to be set separately, before transitioning +- * to the OFF state. It enables the "sequential" power-off mode on +- * TPS65911, it's a NO-OP on TPS65910. +- */ +- if (regmap_set_bits(tps65910->regmap, TPS65910_DEVCTRL, +- DEVCTRL_PWR_OFF_MASK) < 0) +- return; +- + regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, + DEVCTRL_DEV_OFF_MASK | DEVCTRL_DEV_ON_MASK, + DEVCTRL_DEV_OFF_MASK); +@@ -504,6 +495,19 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, + tps65910_sleepinit(tps65910, pmic_plat_data); + + if (pmic_plat_data->pm_off && !pm_power_off) { ++ /* ++ * The PWR_OFF bit needs to be set separately, before ++ * transitioning to the OFF state. It enables the "sequential" ++ * power-off mode on TPS65911, it's a NO-OP on TPS65910. ++ */ ++ ret = regmap_set_bits(tps65910->regmap, TPS65910_DEVCTRL, ++ DEVCTRL_PWR_OFF_MASK); ++ if (ret) { ++ dev_err(&i2c->dev, "failed to set power-off mode: %d\n", ++ ret); ++ return ret; ++ } ++ + tps65910_i2c_client = i2c; + pm_power_off = tps65910_power_off; + } +diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c +index baf83594a01d3..5121edb0d9eff 100644 +--- a/drivers/misc/cardreader/rtsx_pcr.c ++++ b/drivers/misc/cardreader/rtsx_pcr.c +@@ -1803,8 +1803,6 @@ static int rtsx_pci_runtime_suspend(struct device *device) + mutex_lock(&pcr->pcr_mutex); + rtsx_pci_power_off(pcr, HOST_ENTER_S3); + +- free_irq(pcr->irq, (void *)pcr); +- + mutex_unlock(&pcr->pcr_mutex); + + pcr->is_runtime_suspended = true; +@@ -1825,8 +1823,6 @@ static int rtsx_pci_runtime_resume(struct device *device) + mutex_lock(&pcr->pcr_mutex); + + rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00); +- rtsx_pci_acquire_irq(pcr); +- synchronize_irq(pcr->irq); + + if (pcr->ops->fetch_vendor_settings) + pcr->ops->fetch_vendor_settings(pcr); +diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c +index 632325474233a..9193b812bc07e 100644 +--- a/drivers/misc/eeprom/at25.c ++++ b/drivers/misc/eeprom/at25.c +@@ -17,8 +17,6 @@ + #include <linux/spi/spi.h> + #include <linux/spi/eeprom.h> + #include <linux/property.h> +-#include <linux/of.h> +-#include <linux/of_device.h> + #include <linux/math.h> + + /* +@@ -376,28 +374,31 @@ MODULE_DEVICE_TABLE(spi, at25_spi_ids); + static int at25_probe(struct spi_device *spi) + { + struct at25_data *at25 = NULL; +- struct spi_eeprom chip; + int err; + int sr; + u8 id[FM25_ID_LEN]; + u8 sernum[FM25_SN_LEN]; ++ bool is_fram; + int i; +- const struct of_device_id *match; +- bool is_fram = 0; + +- match = of_match_device(of_match_ptr(at25_of_match), &spi->dev); +- if (match && !strcmp(match->compatible, "cypress,fm25")) +- is_fram = 1; ++ err = device_property_match_string(&spi->dev, "compatible", "cypress,fm25"); ++ if (err >= 0) ++ is_fram = true; ++ else ++ is_fram = false; ++ ++ at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL); ++ if (!at25) ++ return -ENOMEM; + + /* Chip description */ +- if (!spi->dev.platform_data) { +- if (!is_fram) { +- err = at25_fw_to_chip(&spi->dev, &chip); +- if (err) +- return err; +- } +- } else +- chip = *(struct spi_eeprom *)spi->dev.platform_data; ++ if (spi->dev.platform_data) { ++ memcpy(&at25->chip, spi->dev.platform_data, sizeof(at25->chip)); ++ } else if (!is_fram) { ++ err = at25_fw_to_chip(&spi->dev, &at25->chip); ++ if (err) ++ return err; ++ } + + /* Ping the chip ... the status register is pretty portable, + * unlike probing manufacturer IDs. We do expect that system +@@ -409,12 +410,7 @@ static int at25_probe(struct spi_device *spi) + return -ENXIO; + } + +- at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL); +- if (!at25) +- return -ENOMEM; +- + mutex_init(&at25->lock); +- at25->chip = chip; + at25->spi = spi; + spi_set_drvdata(spi, at25); + +@@ -431,7 +427,7 @@ static int at25_probe(struct spi_device *spi) + dev_err(&spi->dev, "Error: unsupported size (id %02x)\n", id[7]); + return -ENODEV; + } +- chip.byte_len = int_pow(2, id[7] - 0x21 + 4) * 1024; ++ at25->chip.byte_len = int_pow(2, id[7] - 0x21 + 4) * 1024; + + if (at25->chip.byte_len > 64 * 1024) + at25->chip.flags |= EE_ADDR3; +@@ -464,7 +460,7 @@ static int at25_probe(struct spi_device *spi) + at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM; + at25->nvmem_config.name = dev_name(&spi->dev); + at25->nvmem_config.dev = &spi->dev; +- at25->nvmem_config.read_only = chip.flags & EE_READONLY; ++ at25->nvmem_config.read_only = at25->chip.flags & EE_READONLY; + at25->nvmem_config.root_only = true; + at25->nvmem_config.owner = THIS_MODULE; + at25->nvmem_config.compat = true; +@@ -474,17 +470,18 @@ static int at25_probe(struct spi_device *spi) + at25->nvmem_config.priv = at25; + at25->nvmem_config.stride = 1; + at25->nvmem_config.word_size = 1; +- at25->nvmem_config.size = chip.byte_len; ++ at25->nvmem_config.size = at25->chip.byte_len; + + at25->nvmem = devm_nvmem_register(&spi->dev, &at25->nvmem_config); + if (IS_ERR(at25->nvmem)) + return PTR_ERR(at25->nvmem); + + dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n", +- (chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024), +- (chip.byte_len < 1024) ? "Byte" : "KByte", ++ (at25->chip.byte_len < 1024) ? ++ at25->chip.byte_len : (at25->chip.byte_len / 1024), ++ (at25->chip.byte_len < 1024) ? "Byte" : "KByte", + at25->chip.name, is_fram ? "fram" : "eeprom", +- (chip.flags & EE_READONLY) ? " (readonly)" : "", ++ (at25->chip.flags & EE_READONLY) ? " (readonly)" : "", + at25->chip.page_size); + return 0; + } +diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c +index bb9c4512c968c..9fbfe784d7101 100644 +--- a/drivers/misc/eeprom/ee1004.c ++++ b/drivers/misc/eeprom/ee1004.c +@@ -114,6 +114,9 @@ static ssize_t ee1004_eeprom_read(struct i2c_client *client, char *buf, + if (offset + count > EE1004_PAGE_SIZE) + count = EE1004_PAGE_SIZE - offset; + ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ + return i2c_smbus_read_i2c_block_data_or_emulated(client, offset, count, buf); + } + +diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c +index ad6ced4546556..86d8fb8c0148b 100644 +--- a/drivers/misc/fastrpc.c ++++ b/drivers/misc/fastrpc.c +@@ -719,16 +719,18 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) + static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen) + { + u64 size = 0; +- int i; ++ int oix; + + size = ALIGN(metalen, FASTRPC_ALIGN); +- for (i = 0; i < ctx->nscalars; i++) { ++ for (oix = 0; oix < ctx->nbufs; oix++) { ++ int i = ctx->olaps[oix].raix; ++ + if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) { + +- if (ctx->olaps[i].offset == 0) ++ if (ctx->olaps[oix].offset == 0) + size = ALIGN(size, FASTRPC_ALIGN); + +- size += (ctx->olaps[i].mend - ctx->olaps[i].mstart); ++ size += (ctx->olaps[oix].mend - ctx->olaps[oix].mstart); + } + } + +@@ -1284,7 +1286,14 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp) + } + + if (copy_to_user(argp, &bp, sizeof(bp))) { +- dma_buf_put(buf->dmabuf); ++ /* ++ * The usercopy failed, but we can't do much about it, as ++ * dma_buf_fd() already called fd_install() and made the ++ * file descriptor accessible for the current process. It ++ * might already be closed and dmabuf no longer valid when ++ * we reach this point. Therefore "leak" the fd and rely on ++ * the process exit path to do any required cleanup. ++ */ + return -EFAULT; + } + +diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c +index 8d2568c63f19e..a8e683964ab03 100644 +--- a/drivers/misc/habanalabs/common/firmware_if.c ++++ b/drivers/misc/habanalabs/common/firmware_if.c +@@ -1703,6 +1703,9 @@ static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, + return rc; + } + ++ /* here we can mark the descriptor as valid as the content has been validated */ ++ fw_loader->dynamic_loader.fw_desc_valid = true; ++ + return 0; + } + +@@ -1759,7 +1762,13 @@ static int hl_fw_dynamic_read_and_validate_descriptor(struct hl_device *hdev, + return rc; + } + +- /* extract address copy the descriptor from */ ++ /* ++ * extract address to copy the descriptor from ++ * in addition, as the descriptor value is going to be over-ridden by new data- we mark it ++ * as invalid. ++ * it will be marked again as valid once validated ++ */ ++ fw_loader->dynamic_loader.fw_desc_valid = false; + src = hdev->pcie_bar[region->bar_id] + region->offset_in_bar + + response->ram_offset; + memcpy_fromio(fw_desc, src, sizeof(struct lkd_fw_comms_desc)); +@@ -2239,6 +2248,9 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, + dev_info(hdev->dev, + "Loading firmware to device, may take some time...\n"); + ++ /* initialize FW descriptor as invalid */ ++ fw_loader->dynamic_loader.fw_desc_valid = false; ++ + /* + * In this stage, "cpu_dyn_regs" contains only LKD's hard coded values! + * It will be updated from FW after hl_fw_dynamic_request_descriptor(). +@@ -2325,7 +2337,8 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, + return 0; + + protocol_err: +- fw_read_errors(hdev, le32_to_cpu(dyn_regs->cpu_boot_err0), ++ if (fw_loader->dynamic_loader.fw_desc_valid) ++ fw_read_errors(hdev, le32_to_cpu(dyn_regs->cpu_boot_err0), + le32_to_cpu(dyn_regs->cpu_boot_err1), + le32_to_cpu(dyn_regs->cpu_boot_dev_sts0), + le32_to_cpu(dyn_regs->cpu_boot_dev_sts1)); +diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h +index bebebcb163ee8..dfcd87b98ca08 100644 +--- a/drivers/misc/habanalabs/common/habanalabs.h ++++ b/drivers/misc/habanalabs/common/habanalabs.h +@@ -992,6 +992,7 @@ struct fw_response { + * @image_region: region to copy the FW image to + * @fw_image_size: size of FW image to load + * @wait_for_bl_timeout: timeout for waiting for boot loader to respond ++ * @fw_desc_valid: true if FW descriptor has been validated and hence the data can be used + */ + struct dynamic_fw_load_mgr { + struct fw_response response; +@@ -999,6 +1000,7 @@ struct dynamic_fw_load_mgr { + struct pci_mem_region *image_region; + size_t fw_image_size; + u32 wait_for_bl_timeout; ++ bool fw_desc_valid; + }; + + /** +diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c +index 0f54730c7ed56..98828030b5a4d 100644 +--- a/drivers/misc/lattice-ecp3-config.c ++++ b/drivers/misc/lattice-ecp3-config.c +@@ -76,12 +76,12 @@ static void firmware_load(const struct firmware *fw, void *context) + + if (fw == NULL) { + dev_err(&spi->dev, "Cannot load firmware, aborting\n"); +- return; ++ goto out; + } + + if (fw->size == 0) { + dev_err(&spi->dev, "Error: Firmware size is 0!\n"); +- return; ++ goto out; + } + + /* Fill dummy data (24 stuffing bits for commands) */ +@@ -103,7 +103,7 @@ static void firmware_load(const struct firmware *fw, void *context) + dev_err(&spi->dev, + "Error: No supported FPGA detected (JEDEC_ID=%08x)!\n", + jedec_id); +- return; ++ goto out; + } + + dev_info(&spi->dev, "FPGA %s detected\n", ecp3_dev[i].name); +@@ -116,7 +116,7 @@ static void firmware_load(const struct firmware *fw, void *context) + buffer = kzalloc(fw->size + 8, GFP_KERNEL); + if (!buffer) { + dev_err(&spi->dev, "Error: Can't allocate memory!\n"); +- return; ++ goto out; + } + + /* +@@ -155,7 +155,7 @@ static void firmware_load(const struct firmware *fw, void *context) + "Error: Timeout waiting for FPGA to clear (status=%08x)!\n", + status); + kfree(buffer); +- return; ++ goto out; + } + + dev_info(&spi->dev, "Configuring the FPGA...\n"); +@@ -181,7 +181,7 @@ static void firmware_load(const struct firmware *fw, void *context) + release_firmware(fw); + + kfree(buffer); +- ++out: + complete(&data->fw_loaded); + } + +diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile +index aa12097668d33..e2984ce51fe4d 100644 +--- a/drivers/misc/lkdtm/Makefile ++++ b/drivers/misc/lkdtm/Makefile +@@ -20,7 +20,7 @@ CFLAGS_REMOVE_rodata.o += $(CC_FLAGS_LTO) + + OBJCOPYFLAGS := + OBJCOPYFLAGS_rodata_objcopy.o := \ +- --rename-section .noinstr.text=.rodata,alloc,readonly,load ++ --rename-section .noinstr.text=.rodata,alloc,readonly,load,contents + targets += rodata.o rodata_objcopy.o + $(obj)/rodata_objcopy.o: $(obj)/rodata.o FORCE + $(call if_changed,objcopy) +diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c +index be41843df75bc..cebcca6d6d3ef 100644 +--- a/drivers/misc/mei/hbm.c ++++ b/drivers/misc/mei/hbm.c +@@ -672,10 +672,14 @@ static void mei_hbm_cl_dma_map_res(struct mei_device *dev, + if (!cl) + return; + +- dev_dbg(dev->dev, "cl dma map result = %d\n", res->status); +- cl->status = res->status; +- if (!cl->status) ++ if (res->status) { ++ dev_err(dev->dev, "cl dma map failed %d\n", res->status); ++ cl->status = -EFAULT; ++ } else { ++ dev_dbg(dev->dev, "cl dma map succeeded\n"); + cl->dma_mapped = 1; ++ cl->status = 0; ++ } + wake_up(&cl->wait); + } + +@@ -698,10 +702,14 @@ static void mei_hbm_cl_dma_unmap_res(struct mei_device *dev, + if (!cl) + return; + +- dev_dbg(dev->dev, "cl dma unmap result = %d\n", res->status); +- cl->status = res->status; +- if (!cl->status) ++ if (res->status) { ++ dev_err(dev->dev, "cl dma unmap failed %d\n", res->status); ++ cl->status = -EFAULT; ++ } else { ++ dev_dbg(dev->dev, "cl dma unmap succeeded\n"); + cl->dma_mapped = 0; ++ cl->status = 0; ++ } + wake_up(&cl->wait); + } + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index 431af5e8be2f8..b575d0bfd0d68 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -1682,31 +1682,31 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) + struct mmc_card *card = mq->card; + struct mmc_host *host = card->host; + blk_status_t error = BLK_STS_OK; +- int retries = 0; + + do { + u32 status; + int err; ++ int retries = 0; + +- mmc_blk_rw_rq_prep(mqrq, card, 1, mq); ++ while (retries++ <= MMC_READ_SINGLE_RETRIES) { ++ mmc_blk_rw_rq_prep(mqrq, card, 1, mq); + +- mmc_wait_for_req(host, mrq); ++ mmc_wait_for_req(host, mrq); + +- err = mmc_send_status(card, &status); +- if (err) +- goto error_exit; +- +- if (!mmc_host_is_spi(host) && +- !mmc_ready_for_data(status)) { +- err = mmc_blk_fix_state(card, req); ++ err = mmc_send_status(card, &status); + if (err) + goto error_exit; +- } + +- if (mrq->cmd->error && retries++ < MMC_READ_SINGLE_RETRIES) +- continue; ++ if (!mmc_host_is_spi(host) && ++ !mmc_ready_for_data(status)) { ++ err = mmc_blk_fix_state(card, req); ++ if (err) ++ goto error_exit; ++ } + +- retries = 0; ++ if (!mrq->cmd->error) ++ break; ++ } + + if (mrq->cmd->error || + mrq->data->error || +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 240c5af793dce..368f10405e132 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -2264,7 +2264,7 @@ void mmc_start_host(struct mmc_host *host) + _mmc_detect_change(host, 0, false); + } + +-void mmc_stop_host(struct mmc_host *host) ++void __mmc_stop_host(struct mmc_host *host) + { + if (host->slot.cd_irq >= 0) { + mmc_gpio_set_cd_wake(host, false); +@@ -2273,6 +2273,11 @@ void mmc_stop_host(struct mmc_host *host) + + host->rescan_disable = 1; + cancel_delayed_work_sync(&host->detect); ++} ++ ++void mmc_stop_host(struct mmc_host *host) ++{ ++ __mmc_stop_host(host); + + /* clear pm flags now and let card drivers set them as needed */ + host->pm_flags = 0; +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index 7931a4f0137d2..f5f3f623ea492 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -70,6 +70,7 @@ static inline void mmc_delay(unsigned int ms) + + void mmc_rescan(struct work_struct *work); + void mmc_start_host(struct mmc_host *host); ++void __mmc_stop_host(struct mmc_host *host); + void mmc_stop_host(struct mmc_host *host); + + void _mmc_detect_change(struct mmc_host *host, unsigned long delay, +diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c +index d4683b1d263fd..cf140f4ec8643 100644 +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -80,9 +80,18 @@ static void mmc_host_classdev_release(struct device *dev) + kfree(host); + } + ++static int mmc_host_classdev_shutdown(struct device *dev) ++{ ++ struct mmc_host *host = cls_dev_to_mmc_host(dev); ++ ++ __mmc_stop_host(host); ++ return 0; ++} ++ + static struct class mmc_host_class = { + .name = "mmc_host", + .dev_release = mmc_host_classdev_release, ++ .shutdown_pre = mmc_host_classdev_shutdown, + .pm = MMC_HOST_CLASS_DEV_PM_OPS, + }; + +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index 4646b7a03db6b..44e134fa04afb 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -66,7 +66,7 @@ static const unsigned int sd_au_size[] = { + __res & __mask; \ + }) + +-#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 ++#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 1000 + #define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 + + struct sd_busy_data { +@@ -1663,6 +1663,12 @@ static int sd_poweroff_notify(struct mmc_card *card) + goto out; + } + ++ /* Find out when the command is completed. */ ++ err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, ++ MMC_BUSY_EXTR_SINGLE); ++ if (err) ++ goto out; ++ + cb_data.card = card; + cb_data.reg_buf = reg_buf; + err = __mmc_poll_for_busy(card, SD_POWEROFF_NOTIFY_TIMEOUT_MS, +diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c +index 68edf7a615be5..5447c47157aa5 100644 +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -708,6 +708,8 @@ try_again: + if (host->ops->init_card) + host->ops->init_card(host, card); + ++ card->ocr = ocr_card; ++ + /* + * If the host and card support UHS-I mode request the card + * to switch to 1.8V signaling level. No 1.8v signalling if +@@ -820,7 +822,7 @@ try_again: + goto mismatch; + } + } +- card->ocr = ocr_card; ++ + mmc_fixup_device(card, sdio_fixup_methods); + + if (card->type == MMC_TYPE_SD_COMBO) { +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index 380f9aa56eb26..1e8f1bb3cad7c 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -2086,7 +2086,8 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t) + * delayed. Allowing the transfer to take place + * avoids races and keeps things simple. + */ +- if (err != -ETIMEDOUT) { ++ if (err != -ETIMEDOUT && ++ host->dir_status == DW_MCI_RECV_STATUS) { + state = STATE_SENDING_DATA; + continue; + } +diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c +index 7cd9c0ec2fcfe..28aa78aa08f3f 100644 +--- a/drivers/mmc/host/meson-mx-sdhc-mmc.c ++++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c +@@ -135,6 +135,7 @@ static void meson_mx_sdhc_start_cmd(struct mmc_host *mmc, + struct mmc_command *cmd) + { + struct meson_mx_sdhc_host *host = mmc_priv(mmc); ++ bool manual_stop = false; + u32 ictl, send; + int pack_len; + +@@ -172,12 +173,27 @@ static void meson_mx_sdhc_start_cmd(struct mmc_host *mmc, + else + /* software flush: */ + ictl |= MESON_SDHC_ICTL_DATA_XFER_OK; ++ ++ /* ++ * Mimic the logic from the vendor driver where (only) ++ * SD_IO_RW_EXTENDED commands with more than one block set the ++ * MESON_SDHC_MISC_MANUAL_STOP bit. This fixes the firmware ++ * download in the brcmfmac driver for a BCM43362/1 card. ++ * Without this sdio_memcpy_toio() (with a size of 219557 ++ * bytes) times out if MESON_SDHC_MISC_MANUAL_STOP is not set. ++ */ ++ manual_stop = cmd->data->blocks > 1 && ++ cmd->opcode == SD_IO_RW_EXTENDED; + } else { + pack_len = 0; + + ictl |= MESON_SDHC_ICTL_RESP_OK; + } + ++ regmap_update_bits(host->regmap, MESON_SDHC_MISC, ++ MESON_SDHC_MISC_MANUAL_STOP, ++ manual_stop ? MESON_SDHC_MISC_MANUAL_STOP : 0); ++ + if (cmd->opcode == MMC_STOP_TRANSMISSION) + send |= MESON_SDHC_SEND_DATA_STOP; + +@@ -838,6 +854,11 @@ static int meson_mx_sdhc_probe(struct platform_device *pdev) + goto err_disable_pclk; + + irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ ret = irq; ++ goto err_disable_pclk; ++ } ++ + ret = devm_request_threaded_irq(dev, irq, meson_mx_sdhc_irq, + meson_mx_sdhc_irq_thread, IRQF_ONESHOT, + NULL, host); +diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c +index d4a48916bfb67..3a19a05ef55a7 100644 +--- a/drivers/mmc/host/meson-mx-sdio.c ++++ b/drivers/mmc/host/meson-mx-sdio.c +@@ -662,6 +662,11 @@ static int meson_mx_mmc_probe(struct platform_device *pdev) + } + + irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ ret = irq; ++ goto error_free_mmc; ++ } ++ + ret = devm_request_threaded_irq(host->controller_dev, irq, + meson_mx_mmc_irq, + meson_mx_mmc_irq_thread, IRQF_ONESHOT, +diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c +index f4c8e1a61f537..b431cdd27353b 100644 +--- a/drivers/mmc/host/mmc_spi.c ++++ b/drivers/mmc/host/mmc_spi.c +@@ -1514,6 +1514,12 @@ static int mmc_spi_remove(struct spi_device *spi) + return 0; + } + ++static const struct spi_device_id mmc_spi_dev_ids[] = { ++ { "mmc-spi-slot"}, ++ { }, ++}; ++MODULE_DEVICE_TABLE(spi, mmc_spi_dev_ids); ++ + static const struct of_device_id mmc_spi_of_match_table[] = { + { .compatible = "mmc-spi-slot", }, + {}, +@@ -1525,6 +1531,7 @@ static struct spi_driver mmc_spi_driver = { + .name = "mmc_spi", + .of_match_table = mmc_spi_of_match_table, + }, ++ .id_table = mmc_spi_dev_ids, + .probe = mmc_spi_probe, + .remove = mmc_spi_remove, + }; +diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c +index fdaa11f92fe6f..a75d3dd34d18c 100644 +--- a/drivers/mmc/host/mmci_stm32_sdmmc.c ++++ b/drivers/mmc/host/mmci_stm32_sdmmc.c +@@ -441,6 +441,8 @@ static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode) + return -EINVAL; + } + ++ writel_relaxed(0, dlyb->base + DLYB_CR); ++ + phase = end_of_len - max_len / 2; + sdmmc_dlyb_set_cfgr(dlyb, dlyb->unit, phase, false); + +diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c +index 6c9d38132f74c..b6eb75f4bbfc6 100644 +--- a/drivers/mmc/host/moxart-mmc.c ++++ b/drivers/mmc/host/moxart-mmc.c +@@ -566,37 +566,37 @@ static int moxart_probe(struct platform_device *pdev) + if (!mmc) { + dev_err(dev, "mmc_alloc_host failed\n"); + ret = -ENOMEM; +- goto out; ++ goto out_mmc; + } + + ret = of_address_to_resource(node, 0, &res_mmc); + if (ret) { + dev_err(dev, "of_address_to_resource failed\n"); +- goto out; ++ goto out_mmc; + } + + irq = irq_of_parse_and_map(node, 0); + if (irq <= 0) { + dev_err(dev, "irq_of_parse_and_map failed\n"); + ret = -EINVAL; +- goto out; ++ goto out_mmc; + } + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); +- goto out; ++ goto out_mmc; + } + + reg_mmc = devm_ioremap_resource(dev, &res_mmc); + if (IS_ERR(reg_mmc)) { + ret = PTR_ERR(reg_mmc); +- goto out; ++ goto out_mmc; + } + + ret = mmc_of_parse(mmc); + if (ret) +- goto out; ++ goto out_mmc; + + host = mmc_priv(mmc); + host->mmc = mmc; +@@ -621,6 +621,14 @@ static int moxart_probe(struct platform_device *pdev) + ret = -EPROBE_DEFER; + goto out; + } ++ if (!IS_ERR(host->dma_chan_tx)) { ++ dma_release_channel(host->dma_chan_tx); ++ host->dma_chan_tx = NULL; ++ } ++ if (!IS_ERR(host->dma_chan_rx)) { ++ dma_release_channel(host->dma_chan_rx); ++ host->dma_chan_rx = NULL; ++ } + dev_dbg(dev, "PIO mode transfer enabled\n"); + host->have_dma = false; + } else { +@@ -675,6 +683,11 @@ static int moxart_probe(struct platform_device *pdev) + return 0; + + out: ++ if (!IS_ERR_OR_NULL(host->dma_chan_tx)) ++ dma_release_channel(host->dma_chan_tx); ++ if (!IS_ERR_OR_NULL(host->dma_chan_rx)) ++ dma_release_channel(host->dma_chan_rx); ++out_mmc: + if (mmc) + mmc_free_host(mmc); + return ret; +@@ -687,17 +700,17 @@ static int moxart_remove(struct platform_device *pdev) + + dev_set_drvdata(&pdev->dev, NULL); + +- if (!IS_ERR(host->dma_chan_tx)) ++ if (!IS_ERR_OR_NULL(host->dma_chan_tx)) + dma_release_channel(host->dma_chan_tx); +- if (!IS_ERR(host->dma_chan_rx)) ++ if (!IS_ERR_OR_NULL(host->dma_chan_rx)) + dma_release_channel(host->dma_chan_rx); + mmc_remove_host(mmc); +- mmc_free_host(mmc); + + writel(0, host->base + REG_INTERRUPT_MASK); + writel(0, host->base + REG_POWER_CONTROL); + writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, + host->base + REG_CLOCK_CONTROL); ++ mmc_free_host(mmc); + + return 0; + } +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index b06b4dcb7c782..1ac92015992ed 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -8,6 +8,7 @@ + #include <linux/clk.h> + #include <linux/delay.h> + #include <linux/dma-mapping.h> ++#include <linux/iopoll.h> + #include <linux/ioport.h> + #include <linux/irq.h> + #include <linux/of_address.h> +@@ -627,12 +628,11 @@ static void msdc_reset_hw(struct msdc_host *host) + u32 val; + + sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST); +- while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST) +- cpu_relax(); ++ readl_poll_timeout(host->base + MSDC_CFG, val, !(val & MSDC_CFG_RST), 0, 0); + + sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR); +- while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR) +- cpu_relax(); ++ readl_poll_timeout(host->base + MSDC_FIFOCS, val, ++ !(val & MSDC_FIFOCS_CLR), 0, 0); + + val = readl(host->base + MSDC_INT); + writel(val, host->base + MSDC_INT); +@@ -805,8 +805,9 @@ static void msdc_gate_clock(struct msdc_host *host) + clk_disable_unprepare(host->h_clk); + } + +-static void msdc_ungate_clock(struct msdc_host *host) ++static int msdc_ungate_clock(struct msdc_host *host) + { ++ u32 val; + int ret; + + clk_prepare_enable(host->h_clk); +@@ -816,11 +817,11 @@ static void msdc_ungate_clock(struct msdc_host *host) + ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); + if (ret) { + dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); +- return; ++ return ret; + } + +- while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) +- cpu_relax(); ++ return readl_poll_timeout(host->base + MSDC_CFG, val, ++ (val & MSDC_CFG_CKSTB), 1, 20000); + } + + static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) +@@ -831,6 +832,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + u32 div; + u32 sclk; + u32 tune_reg = host->dev_comp->pad_tune_reg; ++ u32 val; + + if (!hz) { + dev_dbg(host->dev, "set mclk to 0\n"); +@@ -911,8 +913,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) + else + clk_prepare_enable(clk_get_parent(host->src_clk)); + +- while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) +- cpu_relax(); ++ readl_poll_timeout(host->base + MSDC_CFG, val, (val & MSDC_CFG_CKSTB), 0, 0); + sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); + mmc->actual_clock = sclk; + host->mclk = hz; +@@ -1222,13 +1223,13 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, + static inline bool msdc_cmd_is_ready(struct msdc_host *host, + struct mmc_request *mrq, struct mmc_command *cmd) + { +- /* The max busy time we can endure is 20ms */ +- unsigned long tmo = jiffies + msecs_to_jiffies(20); ++ u32 val; ++ int ret; + +- while ((readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) && +- time_before(jiffies, tmo)) +- cpu_relax(); +- if (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) { ++ /* The max busy time we can endure is 20ms */ ++ ret = readl_poll_timeout_atomic(host->base + SDC_STS, val, ++ !(val & SDC_STS_CMDBUSY), 1, 20000); ++ if (ret) { + dev_err(host->dev, "CMD bus busy detected\n"); + host->error |= REQ_CMD_BUSY; + msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd); +@@ -1236,12 +1237,10 @@ static inline bool msdc_cmd_is_ready(struct msdc_host *host, + } + + if (mmc_resp_type(cmd) == MMC_RSP_R1B || cmd->data) { +- tmo = jiffies + msecs_to_jiffies(20); + /* R1B or with data, should check SDCBUSY */ +- while ((readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) && +- time_before(jiffies, tmo)) +- cpu_relax(); +- if (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) { ++ ret = readl_poll_timeout_atomic(host->base + SDC_STS, val, ++ !(val & SDC_STS_SDCBUSY), 1, 20000); ++ if (ret) { + dev_err(host->dev, "Controller busy detected\n"); + host->error |= REQ_CMD_BUSY; + msdc_cmd_done(host, MSDC_INT_CMDTMO, mrq, cmd); +@@ -1366,6 +1365,8 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events, + (MSDC_INT_XFER_COMPL | MSDC_INT_DATCRCERR | MSDC_INT_DATTMO + | MSDC_INT_DMA_BDCSERR | MSDC_INT_DMA_GPDCSERR + | MSDC_INT_DMA_PROTECT); ++ u32 val; ++ int ret; + + spin_lock_irqsave(&host->lock, flags); + done = !host->data; +@@ -1382,8 +1383,14 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events, + readl(host->base + MSDC_DMA_CFG)); + sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, + 1); +- while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS) +- cpu_relax(); ++ ++ ret = readl_poll_timeout_atomic(host->base + MSDC_DMA_CFG, val, ++ !(val & MSDC_DMA_CFG_STS), 1, 20000); ++ if (ret) { ++ dev_dbg(host->dev, "DMA stop timed out\n"); ++ return false; ++ } ++ + sdr_clr_bits(host->base + MSDC_INTEN, data_ints_mask); + dev_dbg(host->dev, "DMA stop\n"); + +@@ -2330,6 +2337,7 @@ static void msdc_cqe_enable(struct mmc_host *mmc) + static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) + { + struct msdc_host *host = mmc_priv(mmc); ++ unsigned int val = 0; + + /* disable cmdq irq */ + sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INT_CMDQ); +@@ -2339,6 +2347,9 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) + if (recovery) { + sdr_set_field(host->base + MSDC_DMA_CTRL, + MSDC_DMA_CTRL_STOP, 1); ++ if (WARN_ON(readl_poll_timeout(host->base + MSDC_DMA_CFG, val, ++ !(val & MSDC_DMA_CFG_STS), 1, 3000))) ++ return; + msdc_reset_hw(host); + } + } +@@ -2593,7 +2604,11 @@ static int msdc_drv_probe(struct platform_device *pdev) + spin_lock_init(&host->lock); + + platform_set_drvdata(pdev, mmc); +- msdc_ungate_clock(host); ++ ret = msdc_ungate_clock(host); ++ if (ret) { ++ dev_err(&pdev->dev, "Cannot ungate clocks!\n"); ++ goto release_mem; ++ } + msdc_init_hw(host); + + if (mmc->caps2 & MMC_CAP2_CQE) { +@@ -2752,8 +2767,12 @@ static int __maybe_unused msdc_runtime_resume(struct device *dev) + { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct msdc_host *host = mmc_priv(mmc); ++ int ret; ++ ++ ret = msdc_ungate_clock(host); ++ if (ret) ++ return ret; + +- msdc_ungate_clock(host); + msdc_restore_reg(host); + return 0; + } +diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c +index 947581de78601..8c3655d3be961 100644 +--- a/drivers/mmc/host/mxs-mmc.c ++++ b/drivers/mmc/host/mxs-mmc.c +@@ -552,6 +552,11 @@ static const struct of_device_id mxs_mmc_dt_ids[] = { + }; + MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); + ++static void mxs_mmc_regulator_disable(void *regulator) ++{ ++ regulator_disable(regulator); ++} ++ + static int mxs_mmc_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +@@ -591,6 +596,11 @@ static int mxs_mmc_probe(struct platform_device *pdev) + "Failed to enable vmmc regulator: %d\n", ret); + goto out_mmc_free; + } ++ ++ ret = devm_add_action_or_reset(&pdev->dev, mxs_mmc_regulator_disable, ++ reg_vmmc); ++ if (ret) ++ goto out_mmc_free; + } + + ssp->clk = devm_clk_get(&pdev->dev, NULL); +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index a4407f391f66a..f5b2684ad8058 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -673,7 +673,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) + + /* Issue CMD19 twice for each tap */ + for (i = 0; i < 2 * priv->tap_num; i++) { +- int cmd_error; ++ int cmd_error = 0; + + /* Set sampling clock position */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, i % priv->tap_num); +diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c +index e658f01742420..60f19369de845 100644 +--- a/drivers/mmc/host/sdhci-esdhc-imx.c ++++ b/drivers/mmc/host/sdhci-esdhc-imx.c +@@ -300,7 +300,6 @@ static struct esdhc_soc_data usdhc_imx8qxp_data = { + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES +- | ESDHC_FLAG_CQHCI + | ESDHC_FLAG_STATE_LOST_IN_LPMODE + | ESDHC_FLAG_CLK_RATE_LOST_IN_PM_RUNTIME, + }; +@@ -309,7 +308,6 @@ static struct esdhc_soc_data usdhc_imx8mm_data = { + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING + | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 + | ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES +- | ESDHC_FLAG_CQHCI + | ESDHC_FLAG_STATE_LOST_IN_LPMODE, + }; + +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index a593b1fbd69e5..0f3658b36513c 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -524,12 +524,16 @@ static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) + + static int esdhc_of_enable_dma(struct sdhci_host *host) + { ++ int ret; + u32 value; + struct device *dev = mmc_dev(host->mmc); + + if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") || +- of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) +- dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); ++ of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) { ++ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); ++ if (ret) ++ return ret; ++ } + + value = sdhci_readl(host, ESDHC_DMA_SYSCTL); + +diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c +index 8f4d1f003f656..fd188b6d88f49 100644 +--- a/drivers/mmc/host/sdhci-omap.c ++++ b/drivers/mmc/host/sdhci-omap.c +@@ -62,6 +62,8 @@ + #define SDHCI_OMAP_IE 0x234 + #define INT_CC_EN BIT(0) + ++#define SDHCI_OMAP_ISE 0x238 ++ + #define SDHCI_OMAP_AC12 0x23c + #define AC12_V1V8_SIGEN BIT(19) + #define AC12_SCLK_SEL BIT(23) +@@ -113,6 +115,8 @@ struct sdhci_omap_host { + u32 hctl; + u32 sysctl; + u32 capa; ++ u32 ie; ++ u32 ise; + }; + + static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host); +@@ -682,7 +686,8 @@ static void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode, + { + struct mmc_host *mmc = host->mmc; + +- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); + } + + static int sdhci_omap_enable_dma(struct sdhci_host *host) +@@ -1244,14 +1249,23 @@ static void sdhci_omap_context_save(struct sdhci_omap_host *omap_host) + { + omap_host->con = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); + omap_host->hctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL); ++ omap_host->sysctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL); + omap_host->capa = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA); ++ omap_host->ie = sdhci_omap_readl(omap_host, SDHCI_OMAP_IE); ++ omap_host->ise = sdhci_omap_readl(omap_host, SDHCI_OMAP_ISE); + } + ++/* Order matters here, HCTL must be restored in two phases */ + static void sdhci_omap_context_restore(struct sdhci_omap_host *omap_host) + { +- sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, omap_host->con); + sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl); + sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, omap_host->capa); ++ sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl); ++ ++ sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, omap_host->sysctl); ++ sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, omap_host->con); ++ sdhci_omap_writel(omap_host, SDHCI_OMAP_IE, omap_host->ie); ++ sdhci_omap_writel(omap_host, SDHCI_OMAP_ISE, omap_host->ise); + } + + static int __maybe_unused sdhci_omap_suspend(struct device *dev) +diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c +index d0f2edfe296c8..c2b26ada104d6 100644 +--- a/drivers/mmc/host/sdhci-pci-core.c ++++ b/drivers/mmc/host/sdhci-pci-core.c +@@ -1951,6 +1951,7 @@ static const struct pci_device_id pci_ids[] = { + SDHCI_PCI_DEVICE(INTEL, JSL_SD, intel_byt_sd), + SDHCI_PCI_DEVICE(INTEL, LKF_EMMC, intel_glk_emmc), + SDHCI_PCI_DEVICE(INTEL, LKF_SD, intel_byt_sd), ++ SDHCI_PCI_DEVICE(INTEL, ADL_EMMC, intel_glk_emmc), + SDHCI_PCI_DEVICE(O2, 8120, o2), + SDHCI_PCI_DEVICE(O2, 8220, o2), + SDHCI_PCI_DEVICE(O2, 8221, o2), +diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c +index 4fd99c1e82ba3..ad50f16658fe2 100644 +--- a/drivers/mmc/host/sdhci-pci-gli.c ++++ b/drivers/mmc/host/sdhci-pci-gli.c +@@ -12,6 +12,7 @@ + #include <linux/pci.h> + #include <linux/mmc/mmc.h> + #include <linux/delay.h> ++#include <linux/of.h> + #include "sdhci.h" + #include "sdhci-pci.h" + #include "cqhci.h" +@@ -116,6 +117,8 @@ + #define PCI_GLI_9755_PECONF 0x44 + #define PCI_GLI_9755_LFCLK GENMASK(14, 12) + #define PCI_GLI_9755_DMACLK BIT(29) ++#define PCI_GLI_9755_INVERT_CD BIT(30) ++#define PCI_GLI_9755_INVERT_WP BIT(31) + + #define PCI_GLI_9755_CFG2 0x48 + #define PCI_GLI_9755_CFG2_L1DLY GENMASK(28, 24) +@@ -570,6 +573,14 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot) + gl9755_wt_on(pdev); + + pci_read_config_dword(pdev, PCI_GLI_9755_PECONF, &value); ++ /* ++ * Apple ARM64 platforms using these chips may have ++ * inverted CD/WP detection. ++ */ ++ if (of_property_read_bool(pdev->dev.of_node, "cd-inverted")) ++ value |= PCI_GLI_9755_INVERT_CD; ++ if (of_property_read_bool(pdev->dev.of_node, "wp-inverted")) ++ value |= PCI_GLI_9755_INVERT_WP; + value &= ~PCI_GLI_9755_LFCLK; + value &= ~PCI_GLI_9755_DMACLK; + pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); +diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h +index 8f90c4163bb5c..dcd99d5057ee1 100644 +--- a/drivers/mmc/host/sdhci-pci.h ++++ b/drivers/mmc/host/sdhci-pci.h +@@ -59,6 +59,7 @@ + #define PCI_DEVICE_ID_INTEL_JSL_SD 0x4df8 + #define PCI_DEVICE_ID_INTEL_LKF_EMMC 0x98c4 + #define PCI_DEVICE_ID_INTEL_LKF_SD 0x98f8 ++#define PCI_DEVICE_ID_INTEL_ADL_EMMC 0x54c4 + + #define PCI_DEVICE_ID_SYSKONNECT_8000 0x8000 + #define PCI_DEVICE_ID_VIA_95D0 0x95d0 +diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c +index a5001875876b9..9762ffab2e236 100644 +--- a/drivers/mmc/host/sdhci-tegra.c ++++ b/drivers/mmc/host/sdhci-tegra.c +@@ -356,23 +356,6 @@ static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap) + } + } + +-static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc, +- struct mmc_ios *ios) +-{ +- struct sdhci_host *host = mmc_priv(mmc); +- u32 val; +- +- val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL); +- +- if (ios->enhanced_strobe) +- val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE; +- else +- val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE; +- +- sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL); +- +-} +- + static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +@@ -793,6 +776,32 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + } + } + ++static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc, ++ struct mmc_ios *ios) ++{ ++ struct sdhci_host *host = mmc_priv(mmc); ++ u32 val; ++ ++ val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL); ++ ++ if (ios->enhanced_strobe) { ++ val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE; ++ /* ++ * When CMD13 is sent from mmc_select_hs400es() after ++ * switching to HS400ES mode, the bus is operating at ++ * either MMC_HIGH_26_MAX_DTR or MMC_HIGH_52_MAX_DTR. ++ * To meet Tegra SDHCI requirement at HS400ES mode, force SDHCI ++ * interface clock to MMC_HS200_MAX_DTR (200 MHz) so that host ++ * controller CAR clock and the interface clock are rate matched. ++ */ ++ tegra_sdhci_set_clock(host, MMC_HS200_MAX_DTR); ++ } else { ++ val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE; ++ } ++ ++ sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL); ++} ++ + static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host) + { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 2d80a04e11d87..7728f26adb19f 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -771,7 +771,19 @@ static void sdhci_adma_table_pre(struct sdhci_host *host, + len -= offset; + } + +- BUG_ON(len > 65536); ++ /* ++ * The block layer forces a minimum segment size of PAGE_SIZE, ++ * so 'len' can be too big here if PAGE_SIZE >= 64KiB. Write ++ * multiple descriptors, noting that the ADMA table is sized ++ * for 4KiB chunks anyway, so it will be big enough. ++ */ ++ while (len > host->max_adma) { ++ int n = 32 * 1024; /* 32KiB*/ ++ ++ __sdhci_adma_write_desc(host, &desc, addr, n, ADMA2_TRAN_VALID); ++ addr += n; ++ len -= n; ++ } + + /* tran, valid */ + if (len) +@@ -3952,6 +3964,7 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev, + * descriptor for each segment, plus 1 for a nop end descriptor. + */ + host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1; ++ host->max_adma = 65536; + + host->max_timeout_count = 0xE; + +@@ -4617,10 +4630,12 @@ int sdhci_setup_host(struct sdhci_host *host) + * be larger than 64 KiB though. + */ + if (host->flags & SDHCI_USE_ADMA) { +- if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) ++ if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) { ++ host->max_adma = 65532; /* 32-bit alignment */ + mmc->max_seg_size = 65535; +- else ++ } else { + mmc->max_seg_size = 65536; ++ } + } else { + mmc->max_seg_size = mmc->max_req_size; + } +diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h +index e8d04e42a5afd..6c689be3e48f6 100644 +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -340,7 +340,8 @@ struct sdhci_adma2_64_desc { + + /* + * Maximum segments assuming a 512KiB maximum requisition size and a minimum +- * 4KiB page size. ++ * 4KiB page size. Note this also allows enough for multiple descriptors in ++ * case of PAGE_SIZE >= 64KiB. + */ + #define SDHCI_MAX_SEGS 128 + +@@ -543,6 +544,7 @@ struct sdhci_host { + unsigned int blocks; /* remaining PIO blocks */ + + int sg_count; /* Mapped sg entries */ ++ int max_adma; /* Max. length in ADMA descriptor */ + + void *adma_table; /* ADMA descriptor table */ + void *align_buffer; /* Bounce buffer */ +diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c +index e2affa52ef469..a5850d83908be 100644 +--- a/drivers/mmc/host/tmio_mmc_core.c ++++ b/drivers/mmc/host/tmio_mmc_core.c +@@ -960,14 +960,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + case MMC_POWER_OFF: + tmio_mmc_power_off(host); + /* For R-Car Gen2+, we need to reset SDHI specific SCC */ +- if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) { +- host->reset(host); +- +- if (host->native_hotplug) +- tmio_mmc_enable_mmc_irqs(host, +- TMIO_STAT_CARD_REMOVE | +- TMIO_STAT_CARD_INSERT); +- } ++ if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) ++ tmio_mmc_reset(host); + + host->set_clock(host, 0); + break; +@@ -1175,6 +1169,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) + if (mmc_can_gpio_cd(mmc)) + _host->ops.get_cd = mmc_gpio_get_cd; + ++ /* must be set before tmio_mmc_reset() */ + _host->native_hotplug = !(mmc_can_gpio_cd(mmc) || + mmc->caps & MMC_CAP_NEEDS_POLL || + !mmc_card_is_removable(mmc)); +@@ -1295,10 +1290,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) + if (host->clk_cache) + host->set_clock(host, host->clk_cache); + +- if (host->native_hotplug) +- tmio_mmc_enable_mmc_irqs(host, +- TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); +- + tmio_mmc_enable_dma(host, true); + + return 0; +diff --git a/drivers/most/most_usb.c b/drivers/most/most_usb.c +index 2640c5b326a49..acabb7715b423 100644 +--- a/drivers/most/most_usb.c ++++ b/drivers/most/most_usb.c +@@ -149,7 +149,8 @@ static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf) + retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + DRCI_READ_REQ, req_type, + 0x0000, +- reg, dma_buf, sizeof(*dma_buf), 5 * HZ); ++ reg, dma_buf, sizeof(*dma_buf), ++ USB_CTRL_GET_TIMEOUT); + *buf = le16_to_cpu(*dma_buf); + kfree(dma_buf); + +@@ -176,7 +177,7 @@ static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data) + reg, + NULL, + 0, +- 5 * HZ); ++ USB_CTRL_SET_TIMEOUT); + } + + static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep) +diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig +index aef14990e5f7c..19726ebd973d0 100644 +--- a/drivers/mtd/chips/Kconfig ++++ b/drivers/mtd/chips/Kconfig +@@ -55,12 +55,14 @@ choice + LITTLE_ENDIAN_BYTE, if the bytes are reversed. + + config MTD_CFI_NOSWAP ++ depends on !ARCH_IXP4XX || CPU_BIG_ENDIAN + bool "NO" + + config MTD_CFI_BE_BYTE_SWAP + bool "BIG_ENDIAN_BYTE" + + config MTD_CFI_LE_BYTE_SWAP ++ depends on !ARCH_IXP4XX + bool "LITTLE_ENDIAN_BYTE" + + endchoice +diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c +index 9802e265fca80..2b317ed6c103f 100644 +--- a/drivers/mtd/devices/mtd_dataflash.c ++++ b/drivers/mtd/devices/mtd_dataflash.c +@@ -96,6 +96,13 @@ struct dataflash { + struct mtd_info mtd; + }; + ++static const struct spi_device_id dataflash_dev_ids[] = { ++ { "at45" }, ++ { "dataflash" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(spi, dataflash_dev_ids); ++ + #ifdef CONFIG_OF + static const struct of_device_id dataflash_dt_ids[] = { + { .compatible = "atmel,at45", }, +@@ -927,6 +934,7 @@ static struct spi_driver dataflash_driver = { + .name = "mtd_dataflash", + .of_match_table = of_match_ptr(dataflash_dt_ids), + }, ++ .id_table = dataflash_dev_ids, + + .probe = dataflash_probe, + .remove = dataflash_remove, +diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c +index 6ed6c51fac69e..d503821a3e606 100644 +--- a/drivers/mtd/devices/phram.c ++++ b/drivers/mtd/devices/phram.c +@@ -264,16 +264,20 @@ static int phram_setup(const char *val) + } + } + +- if (erasesize) +- div_u64_rem(len, (uint32_t)erasesize, &rem); +- + if (len == 0 || erasesize == 0 || erasesize > len +- || erasesize > UINT_MAX || rem) { ++ || erasesize > UINT_MAX) { + parse_err("illegal erasesize or len\n"); + ret = -EINVAL; + goto error; + } + ++ div_u64_rem(len, (uint32_t)erasesize, &rem); ++ if (rem) { ++ parse_err("len is not multiple of erasesize\n"); ++ ret = -EINVAL; ++ goto error; ++ } ++ + ret = register_device(name, start, len, (uint32_t)erasesize); + if (ret) + goto error; +diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c +index ecb050ba95cdf..dc164c18f8429 100644 +--- a/drivers/mtd/hyperbus/rpc-if.c ++++ b/drivers/mtd/hyperbus/rpc-if.c +@@ -124,7 +124,9 @@ static int rpcif_hb_probe(struct platform_device *pdev) + if (!hyperbus) + return -ENOMEM; + +- rpcif_sw_init(&hyperbus->rpc, pdev->dev.parent); ++ error = rpcif_sw_init(&hyperbus->rpc, pdev->dev.parent); ++ if (error) ++ return error; + + platform_set_drvdata(pdev, hyperbus); + +@@ -150,9 +152,9 @@ static int rpcif_hb_remove(struct platform_device *pdev) + { + struct rpcif_hyperbus *hyperbus = platform_get_drvdata(pdev); + int error = hyperbus_unregister_device(&hyperbus->hbdev); +- struct rpcif *rpc = dev_get_drvdata(pdev->dev.parent); + +- rpcif_disable_rpm(rpc); ++ rpcif_disable_rpm(&hyperbus->rpc); ++ + return error; + } + +diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig +index aaa164b977fe8..4945caa88345b 100644 +--- a/drivers/mtd/maps/Kconfig ++++ b/drivers/mtd/maps/Kconfig +@@ -302,7 +302,7 @@ config MTD_DC21285 + + config MTD_IXP4XX + tristate "CFI Flash device mapped on Intel IXP4xx based systems" +- depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX ++ depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX && MTD_CFI_ADV_OPTIONS + help + This enables MTD access to flash devices on platforms based + on Intel's IXP4xx family of network processors such as the +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index c8fd7f758938b..61f236e0378a6 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -546,6 +546,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd) + config.stride = 1; + config.read_only = true; + config.root_only = true; ++ config.ignore_wp = true; + config.no_of_node = !of_device_is_compatible(node, "nvmem-cells"); + config.priv = mtd; + +@@ -724,8 +725,6 @@ int del_mtd_device(struct mtd_info *mtd) + + mutex_lock(&mtd_table_mutex); + +- debugfs_remove_recursive(mtd->dbg.dfs_dir); +- + if (idr_find(&mtd_idr, mtd->index) != mtd) { + ret = -ENODEV; + goto out_error; +@@ -741,6 +740,8 @@ int del_mtd_device(struct mtd_info *mtd) + mtd->index, mtd->name, mtd->usecount); + ret = -EBUSY; + } else { ++ debugfs_remove_recursive(mtd->dbg.dfs_dir); ++ + /* Try to remove the NVMEM provider */ + if (mtd->nvmem) + nvmem_unregister(mtd->nvmem); +@@ -825,12 +826,12 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, + + /* OTP nvmem will be registered on the physical device */ + config.dev = mtd->dev.parent; +- /* just reuse the compatible as name */ +- config.name = compatible; ++ config.name = kasprintf(GFP_KERNEL, "%s-%s", dev_name(&mtd->dev), compatible); + config.id = NVMEM_DEVID_NONE; + config.owner = THIS_MODULE; + config.type = NVMEM_TYPE_OTP; + config.root_only = true; ++ config.ignore_wp = true; + config.reg_read = reg_read; + config.size = size; + config.of_node = np; +@@ -842,6 +843,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, + nvmem = NULL; + + of_node_put(np); ++ kfree(config.name); + + return nvmem; + } +diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c +index 04af12b66110c..357661b62c94d 100644 +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -312,7 +312,7 @@ static int __mtd_del_partition(struct mtd_info *mtd) + if (err) + return err; + +- list_del(&child->part.node); ++ list_del(&mtd->part.node); + free_partition(mtd); + + return 0; +diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c +index ff1697f899ba6..13de39aa3288f 100644 +--- a/drivers/mtd/nand/raw/ams-delta.c ++++ b/drivers/mtd/nand/raw/ams-delta.c +@@ -217,9 +217,8 @@ static int gpio_nand_setup_interface(struct nand_chip *this, int csline, + + static int gpio_nand_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -370,6 +369,13 @@ static int gpio_nand_probe(struct platform_device *pdev) + /* Release write protection */ + gpiod_set_value(priv->gpiod_nwp, 0); + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + /* Scan to find existence of the device */ + err = nand_scan(this, 1); + if (err) +diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c +index 9cbcc698c64d8..53bd10738418b 100644 +--- a/drivers/mtd/nand/raw/arasan-nand-controller.c ++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c +@@ -973,6 +973,21 @@ static int anfc_setup_interface(struct nand_chip *chip, int target, + nvddr = nand_get_nvddr_timings(conf); + if (IS_ERR(nvddr)) + return PTR_ERR(nvddr); ++ ++ /* ++ * The controller only supports data payload requests which are ++ * a multiple of 4. In practice, most data accesses are 4-byte ++ * aligned and this is not an issue. However, rounding up will ++ * simply be refused by the controller if we reached the end of ++ * the device *and* we are using the NV-DDR interface(!). In ++ * this situation, unaligned data requests ending at the device ++ * boundary will confuse the controller and cannot be performed. ++ * ++ * This is something that happens in nand_read_subpage() when ++ * selecting software ECC support and must be avoided. ++ */ ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT) ++ return -ENOTSUPP; + } else { + sdr = nand_get_sdr_timings(conf); + if (IS_ERR(sdr)) +diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c +index 99116896cfd6c..5aa3a06d740c7 100644 +--- a/drivers/mtd/nand/raw/au1550nd.c ++++ b/drivers/mtd/nand/raw/au1550nd.c +@@ -239,9 +239,8 @@ static int au1550nd_exec_op(struct nand_chip *this, + + static int au1550nd_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -310,6 +309,13 @@ static int au1550nd_probe(struct platform_device *pdev) + if (pd->devwidth) + this->options |= NAND_BUSWIDTH_16; + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + ret = nand_scan(this, 1); + if (ret) { + dev_err(&pdev->dev, "NAND scan failed with %d\n", ret); +diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c +index f75929783b941..aee78f5f4f156 100644 +--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c ++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c +@@ -2106,7 +2106,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, + mtd->oobsize / trans, + host->hwcfg.sector_size_1k); + +- if (!ret) { ++ if (ret != -EBADMSG) { + *err_addr = brcmnand_get_uncorrecc_addr(ctrl); + + if (*err_addr) +diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c +index 118da9944e3bc..45fec8c192aba 100644 +--- a/drivers/mtd/nand/raw/davinci_nand.c ++++ b/drivers/mtd/nand/raw/davinci_nand.c +@@ -371,77 +371,6 @@ correct: + return corrected; + } + +-/** +- * nand_read_page_hwecc_oob_first - hw ecc, read oob first +- * @chip: nand chip info structure +- * @buf: buffer to store read data +- * @oob_required: caller requires OOB data read to chip->oob_poi +- * @page: page number to read +- * +- * Hardware ECC for large page chips, require OOB to be read first. For this +- * ECC mode, the write_page method is re-used from ECC_HW. These methods +- * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with +- * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from +- * the data area, by overwriting the NAND manufacturer bad block markings. +- */ +-static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip, +- uint8_t *buf, +- int oob_required, int page) +-{ +- struct mtd_info *mtd = nand_to_mtd(chip); +- int i, eccsize = chip->ecc.size, ret; +- int eccbytes = chip->ecc.bytes; +- int eccsteps = chip->ecc.steps; +- uint8_t *p = buf; +- uint8_t *ecc_code = chip->ecc.code_buf; +- uint8_t *ecc_calc = chip->ecc.calc_buf; +- unsigned int max_bitflips = 0; +- +- /* Read the OOB area first */ +- ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); +- if (ret) +- return ret; +- +- ret = nand_read_page_op(chip, page, 0, NULL, 0); +- if (ret) +- return ret; +- +- ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, +- chip->ecc.total); +- if (ret) +- return ret; +- +- for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { +- int stat; +- +- chip->ecc.hwctl(chip, NAND_ECC_READ); +- +- ret = nand_read_data_op(chip, p, eccsize, false, false); +- if (ret) +- return ret; +- +- chip->ecc.calculate(chip, p, &ecc_calc[i]); +- +- stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL); +- if (stat == -EBADMSG && +- (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { +- /* check for empty pages with bitflips */ +- stat = nand_check_erased_ecc_chunk(p, eccsize, +- &ecc_code[i], +- eccbytes, NULL, 0, +- chip->ecc.strength); +- } +- +- if (stat < 0) { +- mtd->ecc_stats.failed++; +- } else { +- mtd->ecc_stats.corrected += stat; +- max_bitflips = max_t(unsigned int, max_bitflips, stat); +- } +- } +- return max_bitflips; +-} +- + /*----------------------------------------------------------------------*/ + + /* An ECC layout for using 4-bit ECC with small-page flash, storing +@@ -651,7 +580,7 @@ static int davinci_nand_attach_chip(struct nand_chip *chip) + } else if (chunks == 4 || chunks == 8) { + mtd_set_ooblayout(mtd, + nand_get_large_page_ooblayout()); +- chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first; ++ chip->ecc.read_page = nand_read_page_hwecc_oob_first; + } else { + return -EIO; + } +diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c +index a3e66155ae405..6b2bda815b880 100644 +--- a/drivers/mtd/nand/raw/fsmc_nand.c ++++ b/drivers/mtd/nand/raw/fsmc_nand.c +@@ -15,6 +15,7 @@ + + #include <linux/clk.h> + #include <linux/completion.h> ++#include <linux/delay.h> + #include <linux/dmaengine.h> + #include <linux/dma-direction.h> + #include <linux/dma-mapping.h> +@@ -93,6 +94,14 @@ + + #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) + ++/* ++ * According to SPEAr300 Reference Manual (RM0082) ++ * TOUDEL = 7ns (Output delay from the flip-flops to the board) ++ * TINDEL = 5ns (Input delay from the board to the flipflop) ++ */ ++#define TOUTDEL 7000 ++#define TINDEL 5000 ++ + struct fsmc_nand_timings { + u8 tclr; + u8 tar; +@@ -277,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, + { + unsigned long hclk = clk_get_rate(host->clk); + unsigned long hclkn = NSEC_PER_SEC / hclk; +- u32 thiz, thold, twait, tset; ++ u32 thiz, thold, twait, tset, twait_min; + + if (sdrt->tRC_min < 30000) + return -EOPNOTSUPP; +@@ -309,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, + else if (tims->thold > FSMC_THOLD_MASK) + tims->thold = FSMC_THOLD_MASK; + +- twait = max(sdrt->tRP_min, sdrt->tWP_min); +- tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; +- if (tims->twait == 0) +- tims->twait = 1; +- else if (tims->twait > FSMC_TWAIT_MASK) +- tims->twait = FSMC_TWAIT_MASK; +- + tset = max(sdrt->tCS_min - sdrt->tWP_min, + sdrt->tCEA_max - sdrt->tREA_max); + tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; +@@ -324,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, + else if (tims->tset > FSMC_TSET_MASK) + tims->tset = FSMC_TSET_MASK; + ++ /* ++ * According to SPEAr300 Reference Manual (RM0082) which gives more ++ * information related to FSMSC timings than the SPEAr600 one (RM0305), ++ * twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL ++ */ ++ twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000) ++ + TOUTDEL + TINDEL; ++ twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min); ++ ++ tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; ++ if (tims->twait == 0) ++ tims->twait = 1; ++ else if (tims->twait > FSMC_TWAIT_MASK) ++ tims->twait = FSMC_TWAIT_MASK; ++ + return 0; + } + +@@ -438,8 +455,10 @@ static int fsmc_correct_ecc1(struct nand_chip *chip, + unsigned char *read_ecc, + unsigned char *calc_ecc) + { ++ bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER; ++ + return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc, +- chip->ecc.size, false); ++ chip->ecc.size, sm_order); + } + + /* Count the number of 0's in buff upto a max of max_bits */ +@@ -662,6 +681,9 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, + instr->ctx.waitrdy.timeout_ms); + break; + } ++ ++ if (instr->delay_ns) ++ ndelay(instr->delay_ns); + } + + return ret; +diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c +index fb7a086de35e5..fdf073d2e1b6c 100644 +--- a/drivers/mtd/nand/raw/gpio.c ++++ b/drivers/mtd/nand/raw/gpio.c +@@ -163,9 +163,8 @@ static int gpio_nand_exec_op(struct nand_chip *chip, + + static int gpio_nand_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -365,6 +364,13 @@ static int gpio_nand_probe(struct platform_device *pdev) + if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) + gpiod_direction_output(gpiomtd->nwp, 1); + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + ret = nand_scan(chip, 1); + if (ret) + goto err_wp; +diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +index 4d08e4ab5c1b6..668d69fe4cf27 100644 +--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c ++++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +@@ -713,14 +713,32 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this, + (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0); + } + +-static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this) ++static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this) + { + struct gpmi_nfc_hardware_timing *hw = &this->hw; + struct resources *r = &this->resources; + void __iomem *gpmi_regs = r->gpmi_regs; + unsigned int dll_wait_time_us; ++ int ret; + +- clk_set_rate(r->clock[0], hw->clk_rate); ++ /* Clock dividers do NOT guarantee a clean clock signal on its output ++ * during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8, ++ * all clock dividers provide these guarantee. ++ */ ++ if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this)) ++ clk_disable_unprepare(r->clock[0]); ++ ++ ret = clk_set_rate(r->clock[0], hw->clk_rate); ++ if (ret) { ++ dev_err(this->dev, "cannot set clock rate to %lu Hz: %d\n", hw->clk_rate, ret); ++ return ret; ++ } ++ ++ if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this)) { ++ ret = clk_prepare_enable(r->clock[0]); ++ if (ret) ++ return ret; ++ } + + writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0); + writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1); +@@ -739,6 +757,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this) + + /* Wait for the DLL to settle. */ + udelay(dll_wait_time_us); ++ ++ return 0; + } + + static int gpmi_setup_interface(struct nand_chip *chip, int chipnr, +@@ -1034,15 +1054,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) + r->clock[i] = clk; + } + +- if (GPMI_IS_MX6(this)) +- /* +- * Set the default value for the gpmi clock. +- * +- * If you want to use the ONFI nand which is in the +- * Synchronous Mode, you should change the clock as you need. +- */ +- clk_set_rate(r->clock[0], 22000000); +- + return 0; + + err_clock: +@@ -2280,7 +2291,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip, + */ + if (this->hw.must_apply_timings) { + this->hw.must_apply_timings = false; +- gpmi_nfc_apply_timings(this); ++ ret = gpmi_nfc_apply_timings(this); ++ if (ret) ++ goto out_pm; + } + + dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs); +@@ -2409,6 +2422,7 @@ unmap: + + this->bch = false; + ++out_pm: + pm_runtime_mark_last_busy(this->dev); + pm_runtime_put_autosuspend(this->dev); + +diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c +index efe0ffe4f1abc..9054559e52dda 100644 +--- a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c ++++ b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.c +@@ -68,9 +68,14 @@ static struct ingenic_ecc *ingenic_ecc_get(struct device_node *np) + struct ingenic_ecc *ecc; + + pdev = of_find_device_by_node(np); +- if (!pdev || !platform_get_drvdata(pdev)) ++ if (!pdev) + return ERR_PTR(-EPROBE_DEFER); + ++ if (!platform_get_drvdata(pdev)) { ++ put_device(&pdev->dev); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ + ecc = platform_get_drvdata(pdev); + clk_prepare_enable(ecc->clk); + +diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c +index 0e9d426fe4f2b..b18861bdcdc88 100644 +--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c ++++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c +@@ -32,6 +32,7 @@ struct jz_soc_info { + unsigned long addr_offset; + unsigned long cmd_offset; + const struct mtd_ooblayout_ops *oob_layout; ++ bool oob_first; + }; + + struct ingenic_nand_cs { +@@ -240,6 +241,9 @@ static int ingenic_nand_attach_chip(struct nand_chip *chip) + if (chip->bbt_options & NAND_BBT_USE_FLASH) + chip->bbt_options |= NAND_BBT_NO_OOB; + ++ if (nfc->soc_info->oob_first) ++ chip->ecc.read_page = nand_read_page_hwecc_oob_first; ++ + /* For legacy reasons we use a different layout on the qi,lb60 board. */ + if (of_machine_is_compatible("qi,lb60")) + mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops); +@@ -534,6 +538,7 @@ static const struct jz_soc_info jz4740_soc_info = { + .data_offset = 0x00000000, + .cmd_offset = 0x00008000, + .addr_offset = 0x00010000, ++ .oob_first = true, + }; + + static const struct jz_soc_info jz4725b_soc_info = { +diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c +index b9784f3da7a11..7c1c80dae826a 100644 +--- a/drivers/mtd/nand/raw/intel-nand-controller.c ++++ b/drivers/mtd/nand/raw/intel-nand-controller.c +@@ -609,6 +609,11 @@ static int ebu_nand_probe(struct platform_device *pdev) + dev_err(dev, "failed to get chip select: %d\n", ret); + return ret; + } ++ if (cs >= MAX_CS) { ++ dev_err(dev, "got invalid chip select: %d\n", cs); ++ return -EINVAL; ++ } ++ + ebu_host->cs_num = cs; + + resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs); +diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c +index bcd4a556c959c..5b9271b9c3265 100644 +--- a/drivers/mtd/nand/raw/mpc5121_nfc.c ++++ b/drivers/mtd/nand/raw/mpc5121_nfc.c +@@ -291,7 +291,6 @@ static int ads5121_chipselect_init(struct mtd_info *mtd) + /* Control chips select signal on ADS5121 board */ + static void ads5121_select_chip(struct nand_chip *nand, int chip) + { +- struct mtd_info *mtd = nand_to_mtd(nand); + struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand); + u8 v; + +@@ -605,9 +604,8 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) + + static int mpc5121_nfc_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -772,6 +770,13 @@ static int mpc5121_nfc_probe(struct platform_device *op) + goto error; + } + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + /* Detect NAND chips */ + retval = nand_scan(chip, be32_to_cpup(chips_no)); + if (retval) { +diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c +index 3d6c6e8805207..d5a2110eb38ed 100644 +--- a/drivers/mtd/nand/raw/nand_base.c ++++ b/drivers/mtd/nand/raw/nand_base.c +@@ -926,7 +926,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, + struct nand_sdr_timings *spec_timings) + { + const struct nand_controller_ops *ops = chip->controller->ops; +- int best_mode = 0, mode, ret; ++ int best_mode = 0, mode, ret = -EOPNOTSUPP; + + iface->type = NAND_SDR_IFACE; + +@@ -977,7 +977,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip, + struct nand_nvddr_timings *spec_timings) + { + const struct nand_controller_ops *ops = chip->controller->ops; +- int best_mode = 0, mode, ret; ++ int best_mode = 0, mode, ret = -EOPNOTSUPP; + + iface->type = NAND_NVDDR_IFACE; + +@@ -1837,7 +1837,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) + NAND_OP_CMD(NAND_CMD_ERASE1, 0), + NAND_OP_ADDR(2, addrs, 0), + NAND_OP_CMD(NAND_CMD_ERASE2, +- NAND_COMMON_TIMING_MS(conf, tWB_max)), ++ NAND_COMMON_TIMING_NS(conf, tWB_max)), + NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max), + 0), + }; +@@ -3160,6 +3160,73 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, + return max_bitflips; + } + ++/** ++ * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC ++ * data read from OOB area ++ * @chip: nand chip info structure ++ * @buf: buffer to store read data ++ * @oob_required: caller requires OOB data read to chip->oob_poi ++ * @page: page number to read ++ * ++ * Hardware ECC for large page chips, which requires the ECC data to be ++ * extracted from the OOB before the actual data is read. ++ */ ++int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf, ++ int oob_required, int page) ++{ ++ struct mtd_info *mtd = nand_to_mtd(chip); ++ int i, eccsize = chip->ecc.size, ret; ++ int eccbytes = chip->ecc.bytes; ++ int eccsteps = chip->ecc.steps; ++ uint8_t *p = buf; ++ uint8_t *ecc_code = chip->ecc.code_buf; ++ unsigned int max_bitflips = 0; ++ ++ /* Read the OOB area first */ ++ ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); ++ if (ret) ++ return ret; ++ ++ /* Move read cursor to start of page */ ++ ret = nand_change_read_column_op(chip, 0, NULL, 0, false); ++ if (ret) ++ return ret; ++ ++ ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, ++ chip->ecc.total); ++ if (ret) ++ return ret; ++ ++ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { ++ int stat; ++ ++ chip->ecc.hwctl(chip, NAND_ECC_READ); ++ ++ ret = nand_read_data_op(chip, p, eccsize, false, false); ++ if (ret) ++ return ret; ++ ++ stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL); ++ if (stat == -EBADMSG && ++ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { ++ /* check for empty pages with bitflips */ ++ stat = nand_check_erased_ecc_chunk(p, eccsize, ++ &ecc_code[i], ++ eccbytes, NULL, 0, ++ chip->ecc.strength); ++ } ++ ++ if (stat < 0) { ++ mtd->ecc_stats.failed++; ++ } else { ++ mtd->ecc_stats.corrected += stat; ++ max_bitflips = max_t(unsigned int, max_bitflips, stat); ++ } ++ } ++ return max_bitflips; ++} ++EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first); ++ + /** + * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read + * @chip: nand chip info structure +diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c +index 66211c9311d2f..2c87c7d892058 100644 +--- a/drivers/mtd/nand/raw/orion_nand.c ++++ b/drivers/mtd/nand/raw/orion_nand.c +@@ -85,9 +85,8 @@ static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) + + static int orion_nand_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -190,6 +189,13 @@ static int __init orion_nand_probe(struct platform_device *pdev) + return ret; + } + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ nc->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + ret = nand_scan(nc, 1); + if (ret) + goto no_dev; +diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c +index 789f33312c15f..c176036453ed9 100644 +--- a/drivers/mtd/nand/raw/pasemi_nand.c ++++ b/drivers/mtd/nand/raw/pasemi_nand.c +@@ -75,9 +75,8 @@ static int pasemi_device_ready(struct nand_chip *chip) + + static int pasemi_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -154,6 +153,13 @@ static int pasemi_nand_probe(struct platform_device *ofdev) + /* Enable the following for a flash based bad block table */ + chip->bbt_options = NAND_BBT_USE_FLASH; + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + /* Scan to find existence of the device */ + err = nand_scan(chip, 1); + if (err) +diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c +index 7711e1020c21c..0ee08c42cc35b 100644 +--- a/drivers/mtd/nand/raw/plat_nand.c ++++ b/drivers/mtd/nand/raw/plat_nand.c +@@ -21,9 +21,8 @@ struct plat_nand_data { + + static int plat_nand_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -94,6 +93,13 @@ static int plat_nand_probe(struct platform_device *pdev) + goto out; + } + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + /* Scan to find existence of the device */ + err = nand_scan(&data->chip, pdata->chip.nr_chips); + if (err) +diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c +index 04e6f7b267064..0f41a9a421575 100644 +--- a/drivers/mtd/nand/raw/qcom_nandc.c ++++ b/drivers/mtd/nand/raw/qcom_nandc.c +@@ -2,7 +2,6 @@ + /* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + */ +- + #include <linux/clk.h> + #include <linux/slab.h> + #include <linux/bitops.h> +@@ -3063,10 +3062,6 @@ static int qcom_nandc_probe(struct platform_device *pdev) + if (dma_mapping_error(dev, nandc->base_dma)) + return -ENXIO; + +- ret = qcom_nandc_alloc(nandc); +- if (ret) +- goto err_nandc_alloc; +- + ret = clk_prepare_enable(nandc->core_clk); + if (ret) + goto err_core_clk; +@@ -3075,6 +3070,10 @@ static int qcom_nandc_probe(struct platform_device *pdev) + if (ret) + goto err_aon_clk; + ++ ret = qcom_nandc_alloc(nandc); ++ if (ret) ++ goto err_nandc_alloc; ++ + ret = qcom_nandc_setup(nandc); + if (ret) + goto err_setup; +@@ -3086,15 +3085,14 @@ static int qcom_nandc_probe(struct platform_device *pdev) + return 0; + + err_setup: ++ qcom_nandc_unalloc(nandc); ++err_nandc_alloc: + clk_disable_unprepare(nandc->aon_clk); + err_aon_clk: + clk_disable_unprepare(nandc->core_clk); + err_core_clk: +- qcom_nandc_unalloc(nandc); +-err_nandc_alloc: + dma_unmap_resource(dev, res->start, resource_size(res), + DMA_BIDIRECTIONAL, 0); +- + return ret; + } + +diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c +index 70f8305c9b6e1..fb39cc7ebce03 100644 +--- a/drivers/mtd/nand/raw/socrates_nand.c ++++ b/drivers/mtd/nand/raw/socrates_nand.c +@@ -119,9 +119,8 @@ static int socrates_nand_device_ready(struct nand_chip *nand_chip) + + static int socrates_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -175,6 +174,13 @@ static int socrates_nand_probe(struct platform_device *ofdev) + /* TODO: I have no idea what real delay is. */ + nand_chip->legacy.chip_delay = 20; /* 20us command delay time */ + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + dev_set_drvdata(&ofdev->dev, host); + + res = nand_scan(nand_chip, 1); +diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c +index 26751976e5026..236fd8c5a958f 100644 +--- a/drivers/mtd/nand/raw/xway_nand.c ++++ b/drivers/mtd/nand/raw/xway_nand.c +@@ -148,9 +148,8 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len) + + static int xway_attach_chip(struct nand_chip *chip) + { +- chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; +- +- if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && ++ chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +@@ -219,6 +218,13 @@ static int xway_nand_probe(struct platform_device *pdev) + | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P + | cs_flag, EBU_NAND_CON); + ++ /* ++ * This driver assumes that the default ECC engine should be TYPE_SOFT. ++ * Set ->engine_type before registering the NAND devices in order to ++ * provide a driver specific default value. ++ */ ++ data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; ++ + /* Scan to find existence of the device */ + err = nand_scan(&data->chip, 1); + if (err) +diff --git a/drivers/mtd/parsers/qcomsmempart.c b/drivers/mtd/parsers/qcomsmempart.c +index 06a818cd2433f..32ddfea701423 100644 +--- a/drivers/mtd/parsers/qcomsmempart.c ++++ b/drivers/mtd/parsers/qcomsmempart.c +@@ -58,11 +58,11 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) + { ++ size_t len = SMEM_FLASH_PTABLE_HDR_LEN; ++ int ret, i, j, tmpparts, numparts = 0; + struct smem_flash_pentry *pentry; + struct smem_flash_ptable *ptable; +- size_t len = SMEM_FLASH_PTABLE_HDR_LEN; + struct mtd_partition *parts; +- int ret, i, numparts; + char *name, *c; + + if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS) +@@ -87,8 +87,8 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, + } + + /* Ensure that # of partitions is less than the max we have allocated */ +- numparts = le32_to_cpu(ptable->numparts); +- if (numparts > SMEM_FLASH_PTABLE_MAX_PARTS_V4) { ++ tmpparts = le32_to_cpu(ptable->numparts); ++ if (tmpparts > SMEM_FLASH_PTABLE_MAX_PARTS_V4) { + pr_err("Partition numbers exceed the max limit\n"); + return -EINVAL; + } +@@ -116,11 +116,17 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, + return PTR_ERR(ptable); + } + ++ for (i = 0; i < tmpparts; i++) { ++ pentry = &ptable->pentry[i]; ++ if (pentry->name[0] != '\0') ++ numparts++; ++ } ++ + parts = kcalloc(numparts, sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + +- for (i = 0; i < numparts; i++) { ++ for (i = 0, j = 0; i < tmpparts; i++) { + pentry = &ptable->pentry[i]; + if (pentry->name[0] == '\0') + continue; +@@ -135,24 +141,25 @@ static int parse_qcomsmem_part(struct mtd_info *mtd, + for (c = name; *c != '\0'; c++) + *c = tolower(*c); + +- parts[i].name = name; +- parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize; +- parts[i].mask_flags = pentry->attr; +- parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize; ++ parts[j].name = name; ++ parts[j].offset = le32_to_cpu(pentry->offset) * mtd->erasesize; ++ parts[j].mask_flags = pentry->attr; ++ parts[j].size = le32_to_cpu(pentry->length) * mtd->erasesize; + pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n", + i, pentry->name, le32_to_cpu(pentry->offset), + le32_to_cpu(pentry->length), pentry->attr); ++ j++; + } + + pr_debug("SMEM partition table found: ver: %d len: %d\n", +- le32_to_cpu(ptable->version), numparts); ++ le32_to_cpu(ptable->version), tmpparts); + *pparts = parts; + + return numparts; + + out_free_parts: +- while (--i >= 0) +- kfree(parts[i].name); ++ while (--j >= 0) ++ kfree(parts[j].name); + kfree(parts); + *pparts = NULL; + +@@ -166,6 +173,8 @@ static void parse_qcomsmem_cleanup(const struct mtd_partition *pparts, + + for (i = 0; i < nr_parts; i++) + kfree(pparts[i].name); ++ ++ kfree(pparts); + } + + static const struct of_device_id qcomsmem_of_match_table[] = { +diff --git a/drivers/mtd/spi-nor/controllers/hisi-sfc.c b/drivers/mtd/spi-nor/controllers/hisi-sfc.c +index 47fbf1d1e5573..516e502694780 100644 +--- a/drivers/mtd/spi-nor/controllers/hisi-sfc.c ++++ b/drivers/mtd/spi-nor/controllers/hisi-sfc.c +@@ -477,7 +477,6 @@ static int hisi_spi_nor_remove(struct platform_device *pdev) + + hisi_spi_nor_unregister_all(host); + mutex_destroy(&host->lock); +- clk_disable_unprepare(host->clk); + return 0; + } + +diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c +index 1138bdbf41998..75dd13a390404 100644 +--- a/drivers/mtd/spi-nor/xilinx.c ++++ b/drivers/mtd/spi-nor/xilinx.c +@@ -66,7 +66,8 @@ static int xilinx_nor_setup(struct spi_nor *nor, + /* Flash in Power of 2 mode */ + nor->page_size = (nor->page_size == 264) ? 256 : 512; + nor->mtd.writebufsize = nor->page_size; +- nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors; ++ nor->params->size = 8 * nor->page_size * nor->info->n_sectors; ++ nor->mtd.size = nor->params->size; + nor->mtd.erasesize = 8 * nor->page_size; + } else { + /* Flash in Default addressing mode */ +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index f37b1c56f7c43..dd335ae1122b0 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -150,7 +150,7 @@ config NET_FC + + config IFB + tristate "Intermediate Functional Block support" +- depends on NET_CLS_ACT ++ depends on NET_ACT_MIRRED || NFT_FWD_NETDEV + select NET_REDIRECT + help + This is an intermediate driver that allows sharing of +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index 3c8f665c15580..28dccbc0e8d8f 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -138,6 +138,9 @@ static int com20020pci_probe(struct pci_dev *pdev, + return -ENOMEM; + + ci = (struct com20020_pci_card_info *)id->driver_data; ++ if (!ci) ++ return -EINVAL; ++ + priv->ci = ci; + mm = &ci->misc_map; + +diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c +index 6006c2e8fa2bc..a86b1f71762ea 100644 +--- a/drivers/net/bonding/bond_3ad.c ++++ b/drivers/net/bonding/bond_3ad.c +@@ -225,7 +225,7 @@ static inline int __check_agg_selection_timer(struct port *port) + if (bond == NULL) + return 0; + +- return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0; ++ return atomic_read(&BOND_AD_INFO(bond).agg_select_timer) ? 1 : 0; + } + + /** +@@ -1021,8 +1021,8 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr) + if (port->aggregator && + port->aggregator->is_active && + !__port_is_enabled(port)) { +- + __enable_port(port); ++ *update_slave_arr = true; + } + } + break; +@@ -1779,6 +1779,7 @@ static void ad_agg_selection_logic(struct aggregator *agg, + port = port->next_port_in_aggregator) { + __enable_port(port); + } ++ *update_slave_arr = true; + } + } + +@@ -1994,7 +1995,7 @@ static void ad_marker_response_received(struct bond_marker *marker, + */ + void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) + { +- BOND_AD_INFO(bond).agg_select_timer = timeout; ++ atomic_set(&BOND_AD_INFO(bond).agg_select_timer, timeout); + } + + /** +@@ -2277,6 +2278,28 @@ void bond_3ad_update_ad_actor_settings(struct bonding *bond) + spin_unlock_bh(&bond->mode_lock); + } + ++/** ++ * bond_agg_timer_advance - advance agg_select_timer ++ * @bond: bonding structure ++ * ++ * Return true when agg_select_timer reaches 0. ++ */ ++static bool bond_agg_timer_advance(struct bonding *bond) ++{ ++ int val, nval; ++ ++ while (1) { ++ val = atomic_read(&BOND_AD_INFO(bond).agg_select_timer); ++ if (!val) ++ return false; ++ nval = val - 1; ++ if (atomic_cmpxchg(&BOND_AD_INFO(bond).agg_select_timer, ++ val, nval) == val) ++ break; ++ } ++ return nval == 0; ++} ++ + /** + * bond_3ad_state_machine_handler - handle state machines timeout + * @work: work context to fetch bonding struct to work on from +@@ -2312,9 +2335,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) + if (!bond_has_slaves(bond)) + goto re_arm; + +- /* check if agg_select_timer timer after initialize is timed out */ +- if (BOND_AD_INFO(bond).agg_select_timer && +- !(--BOND_AD_INFO(bond).agg_select_timer)) { ++ if (bond_agg_timer_advance(bond)) { + slave = bond_first_slave_rcu(bond); + port = slave ? &(SLAVE_AD_INFO(slave)->port) : NULL; + +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index 7d3752cbf761d..bca36be884b8d 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -1502,14 +1502,14 @@ void bond_alb_monitor(struct work_struct *work) + struct slave *slave; + + if (!bond_has_slaves(bond)) { +- bond_info->tx_rebalance_counter = 0; ++ atomic_set(&bond_info->tx_rebalance_counter, 0); + bond_info->lp_counter = 0; + goto re_arm; + } + + rcu_read_lock(); + +- bond_info->tx_rebalance_counter++; ++ atomic_inc(&bond_info->tx_rebalance_counter); + bond_info->lp_counter++; + + /* send learning packets */ +@@ -1531,7 +1531,7 @@ void bond_alb_monitor(struct work_struct *work) + } + + /* rebalance tx traffic */ +- if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) { ++ if (atomic_read(&bond_info->tx_rebalance_counter) >= BOND_TLB_REBALANCE_TICKS) { + bond_for_each_slave_rcu(bond, slave, iter) { + tlb_clear_slave(bond, slave, 1); + if (slave == rcu_access_pointer(bond->curr_active_slave)) { +@@ -1541,7 +1541,7 @@ void bond_alb_monitor(struct work_struct *work) + bond_info->unbalanced_load = 0; + } + } +- bond_info->tx_rebalance_counter = 0; ++ atomic_set(&bond_info->tx_rebalance_counter, 0); + } + + if (bond_info->rlb_enabled) { +@@ -1611,7 +1611,8 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) + tlb_init_slave(slave); + + /* order a rebalance ASAP */ +- bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; ++ atomic_set(&bond->alb_info.tx_rebalance_counter, ++ BOND_TLB_REBALANCE_TICKS); + + if (bond->alb_info.rlb_enabled) + bond->alb_info.rlb_rebalance = 1; +@@ -1648,7 +1649,8 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char + rlb_clear_slave(bond, slave); + } else if (link == BOND_LINK_UP) { + /* order a rebalance ASAP */ +- bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; ++ atomic_set(&bond_info->tx_rebalance_counter, ++ BOND_TLB_REBALANCE_TICKS); + if (bond->alb_info.rlb_enabled) { + bond->alb_info.rlb_rebalance = 1; + /* If the updelay module parameter is smaller than the +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 77dc79a7f5748..46c3301a5e07d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1096,9 +1096,6 @@ static bool bond_should_notify_peers(struct bonding *bond) + slave = rcu_dereference(bond->curr_active_slave); + rcu_read_unlock(); + +- netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n", +- slave ? slave->dev->name : "NULL"); +- + if (!slave || !bond->send_peer_notif || + bond->send_peer_notif % + max(1, bond->params.peer_notif_delay) != 0 || +@@ -1106,6 +1103,9 @@ static bool bond_should_notify_peers(struct bonding *bond) + test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state)) + return false; + ++ netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n", ++ slave ? slave->dev->name : "NULL"); ++ + return true; + } + +@@ -2377,10 +2377,9 @@ static int __bond_release_one(struct net_device *bond_dev, + bond_select_active_slave(bond); + } + +- if (!bond_has_slaves(bond)) { +- bond_set_carrier(bond); ++ bond_set_carrier(bond); ++ if (!bond_has_slaves(bond)) + eth_hw_addr_random(bond_dev); +- } + + unblock_netpoll_tx(); + synchronize_rcu(); +@@ -3872,8 +3871,8 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb) + skb->l4_hash) + return skb->hash; + +- return __bond_xmit_hash(bond, skb, skb->head, skb->protocol, +- skb->mac_header, skb->network_header, ++ return __bond_xmit_hash(bond, skb, skb->data, skb->protocol, ++ skb_mac_offset(skb), skb_network_offset(skb), + skb_headlen(skb)); + } + +@@ -4843,25 +4842,39 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, + struct bonding *bond = netdev_priv(bond_dev); + struct slave *slave = NULL; + struct list_head *iter; ++ bool xmit_suc = false; ++ bool skb_used = false; + + bond_for_each_slave_rcu(bond, slave, iter) { +- if (bond_is_last_slave(bond, slave)) +- break; +- if (bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) { +- struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); ++ struct sk_buff *skb2; ++ ++ if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) ++ continue; + ++ if (bond_is_last_slave(bond, slave)) { ++ skb2 = skb; ++ skb_used = true; ++ } else { ++ skb2 = skb_clone(skb, GFP_ATOMIC); + if (!skb2) { + net_err_ratelimited("%s: Error: %s: skb_clone() failed\n", + bond_dev->name, __func__); + continue; + } +- bond_dev_queue_xmit(bond, skb2, slave->dev); + } ++ ++ if (bond_dev_queue_xmit(bond, skb2, slave->dev) == NETDEV_TX_OK) ++ xmit_suc = true; + } +- if (slave && bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) +- return bond_dev_queue_xmit(bond, skb, slave->dev); + +- return bond_tx_drop(bond_dev, skb); ++ if (!skb_used) ++ dev_kfree_skb_any(skb); ++ ++ if (xmit_suc) ++ return NETDEV_TX_OK; ++ ++ atomic_long_inc(&bond_dev->tx_dropped); ++ return NET_XMIT_DROP; + } + + /*------------------------- Device initialization ---------------------------*/ +diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c +index a8fde3bc458f6..b93337b5a7211 100644 +--- a/drivers/net/bonding/bond_options.c ++++ b/drivers/net/bonding/bond_options.c +@@ -1526,7 +1526,7 @@ static int bond_option_ad_actor_system_set(struct bonding *bond, + mac = (u8 *)&newval->value; + } + +- if (!is_valid_ether_addr(mac)) ++ if (is_multicast_ether_addr(mac)) + goto err; + + netdev_dbg(bond->dev, "Setting ad_actor_system to %pM\n", mac); +diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c +index fd07561da0348..6a6cdd0bb2585 100644 +--- a/drivers/net/bonding/bond_sysfs_slave.c ++++ b/drivers/net/bonding/bond_sysfs_slave.c +@@ -108,15 +108,15 @@ static ssize_t ad_partner_oper_port_state_show(struct slave *slave, char *buf) + } + static SLAVE_ATTR_RO(ad_partner_oper_port_state); + +-static const struct slave_attribute *slave_attrs[] = { +- &slave_attr_state, +- &slave_attr_mii_status, +- &slave_attr_link_failure_count, +- &slave_attr_perm_hwaddr, +- &slave_attr_queue_id, +- &slave_attr_ad_aggregator_id, +- &slave_attr_ad_actor_oper_port_state, +- &slave_attr_ad_partner_oper_port_state, ++static const struct attribute *slave_attrs[] = { ++ &slave_attr_state.attr, ++ &slave_attr_mii_status.attr, ++ &slave_attr_link_failure_count.attr, ++ &slave_attr_perm_hwaddr.attr, ++ &slave_attr_queue_id.attr, ++ &slave_attr_ad_aggregator_id.attr, ++ &slave_attr_ad_actor_oper_port_state.attr, ++ &slave_attr_ad_partner_oper_port_state.attr, + NULL + }; + +@@ -137,24 +137,10 @@ const struct sysfs_ops slave_sysfs_ops = { + + int bond_sysfs_slave_add(struct slave *slave) + { +- const struct slave_attribute **a; +- int err; +- +- for (a = slave_attrs; *a; ++a) { +- err = sysfs_create_file(&slave->kobj, &((*a)->attr)); +- if (err) { +- kobject_put(&slave->kobj); +- return err; +- } +- } +- +- return 0; ++ return sysfs_create_files(&slave->kobj, slave_attrs); + } + + void bond_sysfs_slave_del(struct slave *slave) + { +- const struct slave_attribute **a; +- +- for (a = slave_attrs; *a; ++a) +- sysfs_remove_file(&slave->kobj, &((*a)->attr)); ++ sysfs_remove_files(&slave->kobj, slave_attrs); + } +diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c +index f49170eadd547..b1b5a82f08299 100644 +--- a/drivers/net/can/dev/bittiming.c ++++ b/drivers/net/can/dev/bittiming.c +@@ -209,7 +209,7 @@ static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt, + const struct can_bittiming_const *btc) + { + struct can_priv *priv = netdev_priv(dev); +- int tseg1, alltseg; ++ unsigned int tseg1, alltseg; + u64 brp64; + + tseg1 = bt->prop_seg + bt->phase_seg1; +diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c +index 7734229aa0788..18d7bb99ec1bd 100644 +--- a/drivers/net/can/flexcan.c ++++ b/drivers/net/can/flexcan.c +@@ -173,9 +173,9 @@ + + /* FLEXCAN interrupt flag register (IFLAG) bits */ + /* Errata ERR005829 step7: Reserve first valid MB */ +-#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO 8 +-#define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP 0 +-#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST (FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1) ++#define FLEXCAN_TX_MB_RESERVED_RX_FIFO 8 ++#define FLEXCAN_TX_MB_RESERVED_RX_MAILBOX 0 ++#define FLEXCAN_RX_MB_RX_MAILBOX_FIRST (FLEXCAN_TX_MB_RESERVED_RX_MAILBOX + 1) + #define FLEXCAN_IFLAG_MB(x) BIT_ULL(x) + #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) + #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) +@@ -234,8 +234,8 @@ + #define FLEXCAN_QUIRK_ENABLE_EACEN_RRS BIT(3) + /* Disable non-correctable errors interrupt and freeze mode */ + #define FLEXCAN_QUIRK_DISABLE_MECR BIT(4) +-/* Use timestamp based offloading */ +-#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) ++/* Use mailboxes (not FIFO) for RX path */ ++#define FLEXCAN_QUIRK_USE_RX_MAILBOX BIT(5) + /* No interrupt for error passive */ + #define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) + /* default to BE register access */ +@@ -252,6 +252,12 @@ + #define FLEXCAN_QUIRK_NR_IRQ_3 BIT(12) + /* Setup 16 mailboxes */ + #define FLEXCAN_QUIRK_NR_MB_16 BIT(13) ++/* Device supports RX via mailboxes */ ++#define FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX BIT(14) ++/* Device supports RTR reception via mailboxes */ ++#define FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR BIT(15) ++/* Device supports RX via FIFO */ ++#define FLEXCAN_QUIRK_SUPPPORT_RX_FIFO BIT(16) + + /* Structure of the message buffer */ + struct flexcan_mb { +@@ -365,7 +371,7 @@ struct flexcan_priv { + + struct clk *clk_ipg; + struct clk *clk_per; +- const struct flexcan_devtype_data *devtype_data; ++ struct flexcan_devtype_data devtype_data; + struct regulator *reg_xceiver; + struct flexcan_stop_mode stm; + +@@ -382,59 +388,78 @@ struct flexcan_priv { + + static const struct flexcan_devtype_data fsl_mcf5441x_devtype_data = { + .quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE | +- FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_NR_MB_16, ++ FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_NR_MB_16 | ++ FLEXCAN_QUIRK_SUPPPORT_RX_FIFO, + }; + + static const struct flexcan_devtype_data fsl_p1010_devtype_data = { + .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE | + FLEXCAN_QUIRK_BROKEN_PERR_STATE | +- FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN, ++ FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_FIFO, + }; + + static const struct flexcan_devtype_data fsl_imx25_devtype_data = { + .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE | +- FLEXCAN_QUIRK_BROKEN_PERR_STATE, ++ FLEXCAN_QUIRK_BROKEN_PERR_STATE | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_FIFO, + }; + + static const struct flexcan_devtype_data fsl_imx28_devtype_data = { +- .quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE, ++ .quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_FIFO, + }; + + static const struct flexcan_devtype_data fsl_imx6q_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | +- FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE | +- FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR, ++ FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_BROKEN_PERR_STATE | ++ FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR, + }; + + static const struct flexcan_devtype_data fsl_imx8qm_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | +- FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE | +- FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW, ++ FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_BROKEN_PERR_STATE | ++ FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR, + }; + + static struct flexcan_devtype_data fsl_imx8mp_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | +- FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | ++ FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX | + FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR | +- FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC, ++ FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR, + }; + + static const struct flexcan_devtype_data fsl_vf610_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | +- FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | +- FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_ECC, ++ FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX | ++ FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SUPPORT_ECC | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR, + }; + + static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | +- FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, ++ FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_USE_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR, + }; + + static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | + FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE | +- FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_SUPPORT_FD | +- FLEXCAN_QUIRK_SUPPORT_ECC, ++ FLEXCAN_QUIRK_USE_RX_MAILBOX | FLEXCAN_QUIRK_SUPPORT_FD | ++ FLEXCAN_QUIRK_SUPPORT_ECC | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR, + }; + + static const struct can_bittiming_const flexcan_bittiming_const = { +@@ -596,7 +621,7 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv) + priv->write(reg_mcr, ®s->mcr); + + /* enable stop request */ +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) { + ret = flexcan_stop_mode_enable_scfw(priv, true); + if (ret < 0) + return ret; +@@ -615,7 +640,7 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv) + int ret; + + /* remove stop request */ +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) { + ret = flexcan_stop_mode_enable_scfw(priv, false); + if (ret < 0) + return ret; +@@ -1018,7 +1043,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, + + mb = flexcan_get_mb(priv, n); + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) { + u32 code; + + do { +@@ -1083,7 +1108,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, + } + + mark_as_read: +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) + flexcan_write64(priv, FLEXCAN_IFLAG_MB(n), ®s->iflag1); + else + priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); +@@ -1109,7 +1134,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) + enum can_state last_state = priv->can.state; + + /* reception interrupt */ +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) { + u64 reg_iflag_rx; + int ret; + +@@ -1169,7 +1194,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) + + /* state change interrupt or broken error state quirk fix is enabled */ + if ((reg_esr & FLEXCAN_ESR_ERR_STATE) || +- (priv->devtype_data->quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE | ++ (priv->devtype_data.quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE | + FLEXCAN_QUIRK_BROKEN_PERR_STATE))) + flexcan_irq_state(dev, reg_esr); + +@@ -1191,11 +1216,11 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) + * (1): enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled + */ + if ((last_state != priv->can.state) && +- (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) && ++ (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) && + !(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) { + switch (priv->can.state) { + case CAN_STATE_ERROR_ACTIVE: +- if (priv->devtype_data->quirks & ++ if (priv->devtype_data.quirks & + FLEXCAN_QUIRK_BROKEN_WERR_STATE) + flexcan_error_irq_enable(priv); + else +@@ -1423,26 +1448,26 @@ static int flexcan_rx_offload_setup(struct net_device *dev) + else + priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN; + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_MB_16) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_MB_16) + priv->mb_count = 16; + else + priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) + + (sizeof(priv->regs->mb[1]) / priv->mb_size); + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) + priv->tx_mb_reserved = +- flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP); ++ flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_RX_MAILBOX); + else + priv->tx_mb_reserved = +- flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_FIFO); ++ flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_RX_FIFO); + priv->tx_mb_idx = priv->mb_count - 1; + priv->tx_mb = flexcan_get_mb(priv, priv->tx_mb_idx); + priv->tx_mask = FLEXCAN_IFLAG_MB(priv->tx_mb_idx); + + priv->offload.mailbox_read = flexcan_mailbox_read; + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { +- priv->offload.mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST; ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) { ++ priv->offload.mb_first = FLEXCAN_RX_MB_RX_MAILBOX_FIRST; + priv->offload.mb_last = priv->mb_count - 2; + + priv->rx_mask = GENMASK_ULL(priv->offload.mb_last, +@@ -1506,7 +1531,7 @@ static int flexcan_chip_start(struct net_device *dev) + if (err) + goto out_chip_disable; + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_ECC) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SUPPORT_ECC) + flexcan_ram_init(dev); + + flexcan_set_bittiming(dev); +@@ -1532,10 +1557,10 @@ static int flexcan_chip_start(struct net_device *dev) + /* MCR + * + * FIFO: +- * - disable for timestamp mode ++ * - disable for mailbox mode + * - enable for FIFO mode + */ +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) + reg_mcr &= ~FLEXCAN_MCR_FEN; + else + reg_mcr |= FLEXCAN_MCR_FEN; +@@ -1586,7 +1611,7 @@ static int flexcan_chip_start(struct net_device *dev) + * on most Flexcan cores, too. Otherwise we don't get + * any error warning or passive interrupts. + */ +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE || ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE || + priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; + else +@@ -1599,7 +1624,7 @@ static int flexcan_chip_start(struct net_device *dev) + netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); + priv->write(reg_ctrl, ®s->ctrl); + +- if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) { ++ if ((priv->devtype_data.quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) { + reg_ctrl2 = priv->read(®s->ctrl2); + reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS; + priv->write(reg_ctrl2, ®s->ctrl2); +@@ -1631,7 +1656,7 @@ static int flexcan_chip_start(struct net_device *dev) + priv->write(reg_fdctrl, ®s->fdctrl); + } + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) { + for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) { + mb = flexcan_get_mb(priv, i); + priv->write(FLEXCAN_MB_CODE_RX_EMPTY, +@@ -1639,7 +1664,7 @@ static int flexcan_chip_start(struct net_device *dev) + } + } else { + /* clear and invalidate unused mailboxes first */ +- for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) { ++ for (i = FLEXCAN_TX_MB_RESERVED_RX_FIFO; i < priv->mb_count; i++) { + mb = flexcan_get_mb(priv, i); + priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, + &mb->can_ctrl); +@@ -1659,7 +1684,7 @@ static int flexcan_chip_start(struct net_device *dev) + priv->write(0x0, ®s->rx14mask); + priv->write(0x0, ®s->rx15mask); + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_DISABLE_RXFG) + priv->write(0x0, ®s->rxfgmask); + + /* clear acceptance filters */ +@@ -1673,7 +1698,7 @@ static int flexcan_chip_start(struct net_device *dev) + * This also works around errata e5295 which generates false + * positive memory errors and put the device in freeze mode. + */ +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_DISABLE_MECR) { + /* Follow the protocol as described in "Detection + * and Correction of Memory Errors" to write to + * MECR register (step 1 - 5) +@@ -1799,7 +1824,7 @@ static int flexcan_open(struct net_device *dev) + if (err) + goto out_can_rx_offload_disable; + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) { + err = request_irq(priv->irq_boff, + flexcan_irq, IRQF_SHARED, dev->name, dev); + if (err) +@@ -1845,7 +1870,7 @@ static int flexcan_close(struct net_device *dev) + netif_stop_queue(dev); + flexcan_chip_interrupts_disable(dev); + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) { + free_irq(priv->irq_err, dev); + free_irq(priv->irq_boff, dev); + } +@@ -2051,9 +2076,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev) + + priv = netdev_priv(dev); + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) + ret = flexcan_setup_stop_mode_scfw(pdev); +- else if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) ++ else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) + ret = flexcan_setup_stop_mode_gpr(pdev); + else + /* return 0 directly if doesn't support stop mode feature */ +@@ -2164,8 +2189,25 @@ static int flexcan_probe(struct platform_device *pdev) + return -ENODEV; + + if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) && +- !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) { +- dev_err(&pdev->dev, "CAN-FD mode doesn't work with FIFO mode!\n"); ++ !((devtype_data->quirks & ++ (FLEXCAN_QUIRK_USE_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR | ++ FLEXCAN_QUIRK_SUPPPORT_RX_FIFO)) == ++ (FLEXCAN_QUIRK_USE_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR))) { ++ dev_err(&pdev->dev, "CAN-FD mode doesn't work in RX-FIFO mode!\n"); ++ return -EINVAL; ++ } ++ ++ if ((devtype_data->quirks & ++ (FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX | ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR)) == ++ FLEXCAN_QUIRK_SUPPPORT_RX_MAILBOX_RTR) { ++ dev_err(&pdev->dev, ++ "Quirks (0x%08x) inconsistent: RX_MAILBOX_RX supported but not RX_MAILBOX\n", ++ devtype_data->quirks); + return -EINVAL; + } + +@@ -2181,9 +2223,10 @@ static int flexcan_probe(struct platform_device *pdev) + dev->flags |= IFF_ECHO; + + priv = netdev_priv(dev); ++ priv->devtype_data = *devtype_data; + + if (of_property_read_bool(pdev->dev.of_node, "big-endian") || +- devtype_data->quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN) { ++ priv->devtype_data.quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN) { + priv->read = flexcan_read_be; + priv->write = flexcan_write_be; + } else { +@@ -2202,10 +2245,9 @@ static int flexcan_probe(struct platform_device *pdev) + priv->clk_ipg = clk_ipg; + priv->clk_per = clk_per; + priv->clk_src = clk_src; +- priv->devtype_data = devtype_data; + priv->reg_xceiver = reg_xceiver; + +- if (devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) { + priv->irq_boff = platform_get_irq(pdev, 1); + if (priv->irq_boff <= 0) { + err = -ENODEV; +@@ -2218,7 +2260,7 @@ static int flexcan_probe(struct platform_device *pdev) + } + } + +- if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) { ++ if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SUPPORT_FD) { + priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | + CAN_CTRLMODE_FD_NON_ISO; + priv->can.bittiming_const = &flexcan_fd_bittiming_const; +diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c +index 74d9899fc904c..eb74cdf26b88c 100644 +--- a/drivers/net/can/kvaser_pciefd.c ++++ b/drivers/net/can/kvaser_pciefd.c +@@ -248,6 +248,9 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); + #define KVASER_PCIEFD_SPACK_EWLR BIT(23) + #define KVASER_PCIEFD_SPACK_EPLR BIT(24) + ++/* Kvaser KCAN_EPACK second word */ ++#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) ++ + struct kvaser_pciefd; + + struct kvaser_pciefd_can { +@@ -1285,7 +1288,10 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, + + can->err_rep_cnt++; + can->can.can_stats.bus_error++; +- stats->rx_errors++; ++ if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) ++ stats->tx_errors++; ++ else ++ stats->rx_errors++; + + can->bec.txerr = bec.txerr; + can->bec.rxerr = bec.rxerr; +diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c +index 2470c47b2e315..25713d6232151 100644 +--- a/drivers/net/can/m_can/m_can.c ++++ b/drivers/net/can/m_can/m_can.c +@@ -204,16 +204,16 @@ enum m_can_reg { + + /* Interrupts for version 3.0.x */ + #define IR_ERR_LEC_30X (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE) +-#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_ELO | IR_BEU | \ +- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ +- IR_RF1L | IR_RF0L) ++#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_BEU | IR_BEC | \ ++ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ ++ IR_RF0L) + #define IR_ERR_ALL_30X (IR_ERR_STATE | IR_ERR_BUS_30X) + + /* Interrupts for version >= 3.1.x */ + #define IR_ERR_LEC_31X (IR_PED | IR_PEA) +-#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BEU | \ +- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ +- IR_RF1L | IR_RF0L) ++#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \ ++ IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ ++ IR_RF0L) + #define IR_ERR_ALL_31X (IR_ERR_STATE | IR_ERR_BUS_31X) + + /* Interrupt Line Select (ILS) */ +@@ -336,6 +336,9 @@ m_can_fifo_read(struct m_can_classdev *cdev, + u32 addr_offset = cdev->mcfg[MRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE + + offset; + ++ if (val_count == 0) ++ return 0; ++ + return cdev->ops->read_fifo(cdev, addr_offset, val, val_count); + } + +@@ -346,6 +349,9 @@ m_can_fifo_write(struct m_can_classdev *cdev, + u32 addr_offset = cdev->mcfg[MRAM_TXB].off + fpi * TXB_ELEMENT_SIZE + + offset; + ++ if (val_count == 0) ++ return 0; ++ + return cdev->ops->write_fifo(cdev, addr_offset, val, val_count); + } + +@@ -517,7 +523,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) + err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA, + cf->data, DIV_ROUND_UP(cf->len, 4)); + if (err) +- goto out_fail; ++ goto out_free_skb; + } + + /* acknowledge rx fifo 0 */ +@@ -532,6 +538,8 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) + + return 0; + ++out_free_skb: ++ kfree_skb(skb); + out_fail: + netdev_err(dev, "FIFO read returned %d\n", err); + return err; +@@ -810,8 +818,6 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus) + { + if (irqstatus & IR_WDI) + netdev_err(dev, "Message RAM Watchdog event due to missing READY\n"); +- if (irqstatus & IR_ELO) +- netdev_err(dev, "Error Logging Overflow\n"); + if (irqstatus & IR_BEU) + netdev_err(dev, "Bit Error Uncorrected\n"); + if (irqstatus & IR_BEC) +@@ -1494,20 +1500,32 @@ static int m_can_dev_setup(struct m_can_classdev *cdev) + case 30: + /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ + can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); +- cdev->can.bittiming_const = &m_can_bittiming_const_30X; +- cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X; ++ cdev->can.bittiming_const = cdev->bit_timing ? ++ cdev->bit_timing : &m_can_bittiming_const_30X; ++ ++ cdev->can.data_bittiming_const = cdev->data_timing ? ++ cdev->data_timing : ++ &m_can_data_bittiming_const_30X; + break; + case 31: + /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ + can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); +- cdev->can.bittiming_const = &m_can_bittiming_const_31X; +- cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; ++ cdev->can.bittiming_const = cdev->bit_timing ? ++ cdev->bit_timing : &m_can_bittiming_const_31X; ++ ++ cdev->can.data_bittiming_const = cdev->data_timing ? ++ cdev->data_timing : ++ &m_can_data_bittiming_const_31X; + break; + case 32: + case 33: + /* Support both MCAN version v3.2.x and v3.3.0 */ +- cdev->can.bittiming_const = &m_can_bittiming_const_31X; +- cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; ++ cdev->can.bittiming_const = cdev->bit_timing ? ++ cdev->bit_timing : &m_can_bittiming_const_31X; ++ ++ cdev->can.data_bittiming_const = cdev->data_timing ? ++ cdev->data_timing : ++ &m_can_data_bittiming_const_31X; + + cdev->can.ctrlmode_supported |= + (m_can_niso_supported(cdev) ? +diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h +index d18b515e6ccc7..2c5d409971686 100644 +--- a/drivers/net/can/m_can/m_can.h ++++ b/drivers/net/can/m_can/m_can.h +@@ -85,6 +85,9 @@ struct m_can_classdev { + struct sk_buff *tx_skb; + struct phy *transceiver; + ++ const struct can_bittiming_const *bit_timing; ++ const struct can_bittiming_const *data_timing; ++ + struct m_can_ops *ops; + + int version; +diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c +index 89cc3d41e952b..b56a54d6c5a9c 100644 +--- a/drivers/net/can/m_can/m_can_pci.c ++++ b/drivers/net/can/m_can/m_can_pci.c +@@ -18,9 +18,14 @@ + + #define M_CAN_PCI_MMIO_BAR 0 + +-#define M_CAN_CLOCK_FREQ_EHL 100000000 + #define CTL_CSR_INT_CTL_OFFSET 0x508 + ++struct m_can_pci_config { ++ const struct can_bittiming_const *bit_timing; ++ const struct can_bittiming_const *data_timing; ++ unsigned int clock_freq; ++}; ++ + struct m_can_pci_priv { + struct m_can_classdev cdev; + +@@ -42,8 +47,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg) + static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count) + { + struct m_can_pci_priv *priv = cdev_to_priv(cdev); ++ void __iomem *src = priv->base + offset; + +- ioread32_rep(priv->base + offset, val, val_count); ++ while (val_count--) { ++ *(unsigned int *)val = ioread32(src); ++ val += 4; ++ src += 4; ++ } + + return 0; + } +@@ -61,8 +71,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, + const void *val, size_t val_count) + { + struct m_can_pci_priv *priv = cdev_to_priv(cdev); ++ void __iomem *dst = priv->base + offset; + +- iowrite32_rep(priv->base + offset, val, val_count); ++ while (val_count--) { ++ iowrite32(*(unsigned int *)val, dst); ++ val += 4; ++ dst += 4; ++ } + + return 0; + } +@@ -74,9 +89,40 @@ static struct m_can_ops m_can_pci_ops = { + .read_fifo = iomap_read_fifo, + }; + ++static const struct can_bittiming_const m_can_bittiming_const_ehl = { ++ .name = KBUILD_MODNAME, ++ .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ ++ .tseg1_max = 64, ++ .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ ++ .tseg2_max = 128, ++ .sjw_max = 128, ++ .brp_min = 1, ++ .brp_max = 512, ++ .brp_inc = 1, ++}; ++ ++static const struct can_bittiming_const m_can_data_bittiming_const_ehl = { ++ .name = KBUILD_MODNAME, ++ .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ ++ .tseg1_max = 16, ++ .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ ++ .tseg2_max = 8, ++ .sjw_max = 4, ++ .brp_min = 1, ++ .brp_max = 32, ++ .brp_inc = 1, ++}; ++ ++static const struct m_can_pci_config m_can_pci_ehl = { ++ .bit_timing = &m_can_bittiming_const_ehl, ++ .data_timing = &m_can_data_bittiming_const_ehl, ++ .clock_freq = 200000000, ++}; ++ + static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) + { + struct device *dev = &pci->dev; ++ const struct m_can_pci_config *cfg; + struct m_can_classdev *mcan_class; + struct m_can_pci_priv *priv; + void __iomem *base; +@@ -104,6 +150,8 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) + if (!mcan_class) + return -ENOMEM; + ++ cfg = (const struct m_can_pci_config *)id->driver_data; ++ + priv = cdev_to_priv(mcan_class); + + priv->base = base; +@@ -115,7 +163,9 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) + mcan_class->dev = &pci->dev; + mcan_class->net->irq = pci_irq_vector(pci, 0); + mcan_class->pm_clock_support = 1; +- mcan_class->can.clock.freq = id->driver_data; ++ mcan_class->bit_timing = cfg->bit_timing; ++ mcan_class->data_timing = cfg->data_timing; ++ mcan_class->can.clock.freq = cfg->clock_freq; + mcan_class->ops = &m_can_pci_ops; + + pci_set_drvdata(pci, mcan_class); +@@ -168,8 +218,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops, + m_can_pci_suspend, m_can_pci_resume); + + static const struct pci_device_id m_can_pci_id_table[] = { +- { PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, }, +- { PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, }, ++ { PCI_VDEVICE(INTEL, 0x4bc1), (kernel_ulong_t)&m_can_pci_ehl, }, ++ { PCI_VDEVICE(INTEL, 0x4bc2), (kernel_ulong_t)&m_can_pci_ehl, }, + { } /* Terminating Entry */ + }; + MODULE_DEVICE_TABLE(pci, m_can_pci_id_table); +diff --git a/drivers/net/can/m_can/tcan4x5x-regmap.c b/drivers/net/can/m_can/tcan4x5x-regmap.c +index ca80dbaf7a3f5..26e212b8ca7a6 100644 +--- a/drivers/net/can/m_can/tcan4x5x-regmap.c ++++ b/drivers/net/can/m_can/tcan4x5x-regmap.c +@@ -12,7 +12,7 @@ + #define TCAN4X5X_SPI_INSTRUCTION_WRITE (0x61 << 24) + #define TCAN4X5X_SPI_INSTRUCTION_READ (0x41 << 24) + +-#define TCAN4X5X_MAX_REGISTER 0x8ffc ++#define TCAN4X5X_MAX_REGISTER 0x87fc + + static int tcan4x5x_regmap_gather_write(void *context, + const void *reg, size_t reg_len, +diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c +index 92a54a5fd4c50..964c8a09226a9 100644 +--- a/drivers/net/can/pch_can.c ++++ b/drivers/net/can/pch_can.c +@@ -692,11 +692,11 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota) + cf->data[i + 1] = data_reg >> 8; + } + +- netif_receive_skb(skb); + rcv_pkts++; + stats->rx_packets++; + quota--; + stats->rx_bytes += cf->len; ++ netif_receive_skb(skb); + + pch_fifo_thresh(priv, obj_num); + obj_num++; +diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c +index ff9d0f5ae0dd2..388521e70837f 100644 +--- a/drivers/net/can/rcar/rcar_canfd.c ++++ b/drivers/net/can/rcar/rcar_canfd.c +@@ -1640,8 +1640,7 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, + ndev = alloc_candev(sizeof(*priv), RCANFD_FIFO_DEPTH); + if (!ndev) { + dev_err(&pdev->dev, "alloc_candev() failed\n"); +- err = -ENOMEM; +- goto fail; ++ return -ENOMEM; + } + priv = netdev_priv(ndev); + +@@ -1735,8 +1734,8 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, + + fail_candev: + netif_napi_del(&priv->napi); +- free_candev(ndev); + fail: ++ free_candev(ndev); + return err; + } + +diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c +index e21b169c14c01..4642b6d4aaf7b 100644 +--- a/drivers/net/can/sja1000/ems_pcmcia.c ++++ b/drivers/net/can/sja1000/ems_pcmcia.c +@@ -234,7 +234,12 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base) + free_sja1000dev(dev); + } + +- err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, ++ if (!card->channels) { ++ err = -ENODEV; ++ goto failure_cleanup; ++ } ++ ++ err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, + DRV_NAME, card); + if (!err) + return 0; +diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c +index 2e93ee7923739..e5c939b63fa65 100644 +--- a/drivers/net/can/softing/softing_cs.c ++++ b/drivers/net/can/softing/softing_cs.c +@@ -293,7 +293,7 @@ static int softingcs_probe(struct pcmcia_device *pcmcia) + return 0; + + platform_failed: +- kfree(dev); ++ platform_device_put(pdev); + mem_failed: + pcmcia_bad: + pcmcia_failed: +diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c +index 7e15368779931..32286f861a195 100644 +--- a/drivers/net/can/softing/softing_fw.c ++++ b/drivers/net/can/softing/softing_fw.c +@@ -565,18 +565,19 @@ int softing_startstop(struct net_device *dev, int up) + if (ret < 0) + goto failed; + } +- /* enable_error_frame */ +- /* ++ ++ /* enable_error_frame ++ * + * Error reporting is switched off at the moment since + * the receiving of them is not yet 100% verified + * This should be enabled sooner or later +- * +- if (error_reporting) { ++ */ ++ if (0 && error_reporting) { + ret = softing_fct_cmd(card, 51, "enable_error_frame"); + if (ret < 0) + goto failed; + } +- */ ++ + /* initialize interface */ + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]); +diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +index 673861ab665a4..9a4791d88683c 100644 +--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c ++++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +@@ -1092,7 +1092,7 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv) + + err = mcp251xfd_chip_rx_int_enable(priv); + if (err) +- return err; ++ goto out_chip_stop; + + err = mcp251xfd_chip_ecc_init(priv); + if (err) +@@ -1336,7 +1336,7 @@ mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv, + len > tx_ring->obj_num || + offset + len > tx_ring->obj_num)) { + netdev_err(priv->ndev, +- "Trying to read to many TEF objects (max=%d, offset=%d, len=%d).\n", ++ "Trying to read too many TEF objects (max=%d, offset=%d, len=%d).\n", + tx_ring->obj_num, offset, len); + return -ERANGE; + } +@@ -2290,8 +2290,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) + * check will fail, too. So leave IRQ handler + * directly. + */ +- if (priv->can.state == CAN_STATE_BUS_OFF) ++ if (priv->can.state == CAN_STATE_BUS_OFF) { ++ can_rx_offload_threaded_irq_finish(&priv->offload); + return IRQ_HANDLED; ++ } + } + + handled = IRQ_HANDLED; +@@ -2623,7 +2625,7 @@ static int mcp251xfd_register_chip_detect(struct mcp251xfd_priv *priv) + if (!mcp251xfd_is_251X(priv) && + priv->devtype_data.model != devtype_data->model) { + netdev_info(ndev, +- "Detected %s, but firmware specifies a %s. Fixing up.", ++ "Detected %s, but firmware specifies a %s. Fixing up.\n", + __mcp251xfd_get_model_str(devtype_data->model), + mcp251xfd_get_model_str(priv)); + } +@@ -2660,7 +2662,7 @@ static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv) + return 0; + + netdev_info(priv->ndev, +- "RX_INT active after softreset, disabling RX_INT support."); ++ "RX_INT active after softreset, disabling RX_INT support.\n"); + devm_gpiod_put(&priv->spi->dev, priv->rx_int); + priv->rx_int = NULL; + +diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c +index 96a13c770e4a1..cd4e7f356e488 100644 +--- a/drivers/net/can/usb/etas_es58x/es58x_core.c ++++ b/drivers/net/can/usb/etas_es58x/es58x_core.c +@@ -664,7 +664,7 @@ int es58x_rx_err_msg(struct net_device *netdev, enum es58x_err error, + struct can_device_stats *can_stats = &can->can_stats; + struct can_frame *cf = NULL; + struct sk_buff *skb; +- int ret; ++ int ret = 0; + + if (!netif_running(netdev)) { + if (net_ratelimit()) +@@ -823,8 +823,6 @@ int es58x_rx_err_msg(struct net_device *netdev, enum es58x_err error, + can->state = CAN_STATE_BUS_OFF; + can_bus_off(netdev); + ret = can->do_set_mode(netdev, CAN_MODE_STOP); +- if (ret) +- return ret; + } + break; + +@@ -881,7 +879,7 @@ int es58x_rx_err_msg(struct net_device *netdev, enum es58x_err error, + ES58X_EVENT_BUSOFF, timestamp); + } + +- return 0; ++ return ret; + } + + /** +@@ -1796,7 +1794,7 @@ static int es58x_open(struct net_device *netdev) + struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev; + int ret; + +- if (atomic_inc_return(&es58x_dev->opened_channel_cnt) == 1) { ++ if (!es58x_dev->opened_channel_cnt) { + ret = es58x_alloc_rx_urbs(es58x_dev); + if (ret) + return ret; +@@ -1814,12 +1812,13 @@ static int es58x_open(struct net_device *netdev) + if (ret) + goto free_urbs; + ++ es58x_dev->opened_channel_cnt++; + netif_start_queue(netdev); + + return ret; + + free_urbs: +- if (atomic_dec_and_test(&es58x_dev->opened_channel_cnt)) ++ if (!es58x_dev->opened_channel_cnt) + es58x_free_urbs(es58x_dev); + netdev_err(netdev, "%s: Could not open the network device: %pe\n", + __func__, ERR_PTR(ret)); +@@ -1854,7 +1853,8 @@ static int es58x_stop(struct net_device *netdev) + + es58x_flush_pending_tx_msg(netdev); + +- if (atomic_dec_and_test(&es58x_dev->opened_channel_cnt)) ++ es58x_dev->opened_channel_cnt--; ++ if (!es58x_dev->opened_channel_cnt) + es58x_free_urbs(es58x_dev); + + return 0; +@@ -2223,7 +2223,6 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf, + init_usb_anchor(&es58x_dev->tx_urbs_idle); + init_usb_anchor(&es58x_dev->tx_urbs_busy); + atomic_set(&es58x_dev->tx_urbs_idle_cnt, 0); +- atomic_set(&es58x_dev->opened_channel_cnt, 0); + usb_set_intfdata(intf, es58x_dev); + + es58x_dev->rx_pipe = usb_rcvbulkpipe(es58x_dev->udev, +diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.h b/drivers/net/can/usb/etas_es58x/es58x_core.h +index 826a15871573a..e5033cb5e6959 100644 +--- a/drivers/net/can/usb/etas_es58x/es58x_core.h ++++ b/drivers/net/can/usb/etas_es58x/es58x_core.h +@@ -373,8 +373,6 @@ struct es58x_operators { + * queue wake/stop logic should prevent this URB from getting + * empty. Please refer to es58x_get_tx_urb() for more details. + * @tx_urbs_idle_cnt: number of urbs in @tx_urbs_idle. +- * @opened_channel_cnt: number of channels opened (c.f. es58x_open() +- * and es58x_stop()). + * @ktime_req_ns: kernel timestamp when es58x_set_realtime_diff_ns() + * was called. + * @realtime_diff_ns: difference in nanoseconds between the clocks of +@@ -384,6 +382,10 @@ struct es58x_operators { + * in RX branches. + * @rx_max_packet_size: Maximum length of bulk-in URB. + * @num_can_ch: Number of CAN channel (i.e. number of elements of @netdev). ++ * @opened_channel_cnt: number of channels opened. Free of race ++ * conditions because its two users (net_device_ops:ndo_open() ++ * and net_device_ops:ndo_close()) guarantee that the network ++ * stack big kernel lock (a.k.a. rtnl_mutex) is being hold. + * @rx_cmd_buf_len: Length of @rx_cmd_buf. + * @rx_cmd_buf: The device might split the URB commands in an + * arbitrary amount of pieces. This buffer is used to concatenate +@@ -406,7 +408,6 @@ struct es58x_device { + struct usb_anchor tx_urbs_busy; + struct usb_anchor tx_urbs_idle; + atomic_t tx_urbs_idle_cnt; +- atomic_t opened_channel_cnt; + + u64 ktime_req_ns; + s64 realtime_diff_ns; +@@ -415,6 +416,7 @@ struct es58x_device { + + u16 rx_max_packet_size; + u8 num_can_ch; ++ u8 opened_channel_cnt; + + u16 rx_cmd_buf_len; + union es58x_urb_cmd rx_cmd_buf; +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 5e892bef46b00..d68d698f2606b 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -191,8 +191,8 @@ struct gs_can { + struct gs_usb { + struct gs_can *canch[GS_MAX_INTF]; + struct usb_anchor rx_submitted; +- atomic_t active_channels; + struct usb_device *udev; ++ u8 active_channels; + }; + + /* 'allocate' a tx context. +@@ -321,7 +321,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + + /* device reports out of range channel id */ + if (hf->channel >= GS_MAX_INTF) +- goto resubmit_urb; ++ goto device_detach; + + dev = usbcan->canch[hf->channel]; + +@@ -406,6 +406,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + + /* USB failure take down all interfaces */ + if (rc == -ENODEV) { ++ device_detach: + for (rc = 0; rc < GS_MAX_INTF; rc++) { + if (usbcan->canch[rc]) + netif_device_detach(usbcan->canch[rc]->netdev); +@@ -507,6 +508,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, + + hf->echo_id = idx; + hf->channel = dev->channel; ++ hf->flags = 0; ++ hf->reserved = 0; + + cf = (struct can_frame *)skb->data; + +@@ -587,7 +590,7 @@ static int gs_can_open(struct net_device *netdev) + if (rc) + return rc; + +- if (atomic_add_return(1, &parent->active_channels) == 1) { ++ if (!parent->active_channels) { + for (i = 0; i < GS_MAX_RX_URBS; i++) { + struct urb *urb; + u8 *buf; +@@ -688,6 +691,7 @@ static int gs_can_open(struct net_device *netdev) + + dev->can.state = CAN_STATE_ERROR_ACTIVE; + ++ parent->active_channels++; + if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) + netif_start_queue(netdev); + +@@ -703,7 +707,8 @@ static int gs_can_close(struct net_device *netdev) + netif_stop_queue(netdev); + + /* Stop polling */ +- if (atomic_dec_and_test(&parent->active_channels)) ++ parent->active_channels--; ++ if (!parent->active_channels) + usb_kill_anchored_urbs(&parent->rx_submitted); + + /* Stop sending URBs */ +@@ -982,8 +987,6 @@ static int gs_usb_probe(struct usb_interface *intf, + + init_usb_anchor(&dev->rx_submitted); + +- atomic_set(&dev->active_channels, 0); +- + usb_set_intfdata(intf, dev); + dev->udev = interface_to_usbdev(intf); + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 59ba7c7beec00..f7af1bf5ab46d 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -28,10 +28,6 @@ + + #include "kvaser_usb.h" + +-/* Forward declaration */ +-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; +- +-#define CAN_USB_CLOCK 8000000 + #define MAX_USBCAN_NET_DEVICES 2 + + /* Command header size */ +@@ -80,6 +76,12 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; + + #define CMD_LEAF_LOG_MESSAGE 106 + ++/* Leaf frequency options */ ++#define KVASER_USB_LEAF_SWOPTION_FREQ_MASK 0x60 ++#define KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK 0 ++#define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) ++#define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) ++ + /* error factors */ + #define M16C_EF_ACKE BIT(0) + #define M16C_EF_CRCE BIT(1) +@@ -340,6 +342,50 @@ struct kvaser_usb_err_summary { + }; + }; + ++static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { ++ .name = "kvaser_usb", ++ .tseg1_min = KVASER_USB_TSEG1_MIN, ++ .tseg1_max = KVASER_USB_TSEG1_MAX, ++ .tseg2_min = KVASER_USB_TSEG2_MIN, ++ .tseg2_max = KVASER_USB_TSEG2_MAX, ++ .sjw_max = KVASER_USB_SJW_MAX, ++ .brp_min = KVASER_USB_BRP_MIN, ++ .brp_max = KVASER_USB_BRP_MAX, ++ .brp_inc = KVASER_USB_BRP_INC, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = { ++ .clock = { ++ .freq = 8000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = { ++ .clock = { ++ .freq = 16000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = { ++ .clock = { ++ .freq = 24000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ ++static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = { ++ .clock = { ++ .freq = 32000000, ++ }, ++ .timestamp_freq = 1, ++ .bittiming_const = &kvaser_usb_leaf_bittiming_const, ++}; ++ + static void * + kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, + const struct sk_buff *skb, int *frame_len, +@@ -471,6 +517,27 @@ static int kvaser_usb_leaf_send_simple_cmd(const struct kvaser_usb *dev, + return rc; + } + ++static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, ++ const struct leaf_cmd_softinfo *softinfo) ++{ ++ u32 sw_options = le32_to_cpu(softinfo->sw_options); ++ ++ dev->fw_version = le32_to_cpu(softinfo->fw_version); ++ dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); ++ ++ switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { ++ case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz; ++ break; ++ case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz; ++ break; ++ case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz; ++ break; ++ } ++} ++ + static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) + { + struct kvaser_cmd cmd; +@@ -486,14 +553,13 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) + + switch (dev->card_data.leaf.family) { + case KVASER_LEAF: +- dev->fw_version = le32_to_cpu(cmd.u.leaf.softinfo.fw_version); +- dev->max_tx_urbs = +- le16_to_cpu(cmd.u.leaf.softinfo.max_outstanding_tx); ++ kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); + break; + case KVASER_USBCAN: + dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version); + dev->max_tx_urbs = + le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); ++ dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz; + break; + } + +@@ -1225,24 +1291,11 @@ static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) + { + struct kvaser_usb_dev_card_data *card_data = &dev->card_data; + +- dev->cfg = &kvaser_usb_leaf_dev_cfg; + card_data->ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; + + return 0; + } + +-static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { +- .name = "kvaser_usb", +- .tseg1_min = KVASER_USB_TSEG1_MIN, +- .tseg1_max = KVASER_USB_TSEG1_MAX, +- .tseg2_min = KVASER_USB_TSEG2_MIN, +- .tseg2_max = KVASER_USB_TSEG2_MAX, +- .sjw_max = KVASER_USB_SJW_MAX, +- .brp_min = KVASER_USB_BRP_MIN, +- .brp_max = KVASER_USB_BRP_MAX, +- .brp_inc = KVASER_USB_BRP_INC, +-}; +- + static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + { + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +@@ -1348,11 +1401,3 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { + .dev_read_bulk_callback = kvaser_usb_leaf_read_bulk_callback, + .dev_frame_to_cmd = kvaser_usb_leaf_frame_to_cmd, + }; +- +-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg = { +- .clock = { +- .freq = CAN_USB_CLOCK, +- }, +- .timestamp_freq = 1, +- .bittiming_const = &kvaser_usb_leaf_bittiming_const, +-}; +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c +index 837b3fecd71e9..af8d3dadbbb8b 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb.c +@@ -841,14 +841,14 @@ static int pcan_usb_start(struct peak_usb_device *dev) + pdev->bec.rxerr = 0; + pdev->bec.txerr = 0; + +- /* be notified on error counter changes (if requested by user) */ +- if (dev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) { +- err = pcan_usb_set_err_frame(dev, PCAN_USB_BERR_MASK); +- if (err) +- netdev_warn(dev->netdev, +- "Asking for BERR reporting error %u\n", +- err); +- } ++ /* always ask the device for BERR reporting, to be able to switch from ++ * WARNING to PASSIVE state ++ */ ++ err = pcan_usb_set_err_frame(dev, PCAN_USB_BERR_MASK); ++ if (err) ++ netdev_warn(dev->netdev, ++ "Asking for BERR reporting error %u\n", ++ err); + + /* if revision greater than 3, can put silent mode on/off */ + if (dev->device_rev > 3) { +@@ -986,7 +986,6 @@ const struct peak_usb_adapter pcan_usb = { + .device_id = PCAN_USB_PRODUCT_ID, + .ctrl_count = 1, + .ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY | +- CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_CC_LEN8_DLC, + .clock = { + .freq = PCAN_USB_CRYSTAL_HZ / 2, +diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c +index 3b883e607d8ba..a579b9b791ede 100644 +--- a/drivers/net/can/xilinx_can.c ++++ b/drivers/net/can/xilinx_can.c +@@ -1762,7 +1762,12 @@ static int xcan_probe(struct platform_device *pdev) + spin_lock_init(&priv->tx_lock); + + /* Get IRQ for the device */ +- ndev->irq = platform_get_irq(pdev, 0); ++ ret = platform_get_irq(pdev, 0); ++ if (ret < 0) ++ goto err_free; ++ ++ ndev->irq = ret; ++ + ndev->flags |= IFF_ECHO; /* We support local echo */ + + platform_set_drvdata(pdev, ndev); +diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig +index a5f1aa911fe2a..9428aac4a6868 100644 +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -36,6 +36,7 @@ config NET_DSA_LANTIQ_GSWIP + config NET_DSA_MT7530 + tristate "MediaTek MT753x and MT7621 Ethernet switch support" + select NET_DSA_TAG_MTK ++ select MEDIATEK_GE_PHY + help + This enables support for the MediaTek MT7530, MT7531, and MT7621 + Ethernet switch chips. +@@ -80,6 +81,7 @@ config NET_DSA_REALTEK_SMI + + config NET_DSA_SMSC_LAN9303 + tristate ++ depends on VLAN_8021Q || VLAN_8021Q=n + select NET_DSA_TAG_LAN9303 + select REGMAP + help +diff --git a/drivers/net/dsa/b53/b53_spi.c b/drivers/net/dsa/b53/b53_spi.c +index 01e37b75471e1..2b88f03e52521 100644 +--- a/drivers/net/dsa/b53/b53_spi.c ++++ b/drivers/net/dsa/b53/b53_spi.c +@@ -349,6 +349,19 @@ static const struct of_device_id b53_spi_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, b53_spi_of_match); + ++static const struct spi_device_id b53_spi_ids[] = { ++ { .name = "bcm5325" }, ++ { .name = "bcm5365" }, ++ { .name = "bcm5395" }, ++ { .name = "bcm5397" }, ++ { .name = "bcm5398" }, ++ { .name = "bcm53115" }, ++ { .name = "bcm53125" }, ++ { .name = "bcm53128" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(spi, b53_spi_ids); ++ + static struct spi_driver b53_spi_driver = { + .driver = { + .name = "b53-switch", +@@ -357,6 +370,7 @@ static struct spi_driver b53_spi_driver = { + .probe = b53_spi_probe, + .remove = b53_spi_remove, + .shutdown = b53_spi_shutdown, ++ .id_table = b53_spi_ids, + }; + + module_spi_driver(b53_spi_driver); +diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c +index 7578a5c38df59..2e314e3021d8b 100644 +--- a/drivers/net/dsa/bcm_sf2.c ++++ b/drivers/net/dsa/bcm_sf2.c +@@ -584,7 +584,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) + get_device(&priv->master_mii_bus->dev); + priv->master_mii_dn = dn; + +- priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev); ++ priv->slave_mii_bus = mdiobus_alloc(); + if (!priv->slave_mii_bus) { + of_node_put(dn); + return -ENOMEM; +@@ -644,8 +644,10 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) + } + + err = mdiobus_register(priv->slave_mii_bus); +- if (err && dn) ++ if (err && dn) { ++ mdiobus_free(priv->slave_mii_bus); + of_node_put(dn); ++ } + + return err; + } +@@ -653,6 +655,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) + static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv) + { + mdiobus_unregister(priv->slave_mii_bus); ++ mdiobus_free(priv->slave_mii_bus); + of_node_put(priv->master_mii_dn); + } + +diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c +index 354655f9ed003..950a54ec4b59b 100644 +--- a/drivers/net/dsa/hirschmann/hellcreek.c ++++ b/drivers/net/dsa/hirschmann/hellcreek.c +@@ -710,8 +710,9 @@ static int __hellcreek_fdb_add(struct hellcreek *hellcreek, + u16 meta = 0; + + dev_dbg(hellcreek->dev, "Add static FDB entry: MAC=%pM, MASK=0x%02x, " +- "OBT=%d, REPRIO_EN=%d, PRIO=%d\n", entry->mac, entry->portmask, +- entry->is_obt, entry->reprio_en, entry->reprio_tc); ++ "OBT=%d, PASS_BLOCKED=%d, REPRIO_EN=%d, PRIO=%d\n", entry->mac, ++ entry->portmask, entry->is_obt, entry->pass_blocked, ++ entry->reprio_en, entry->reprio_tc); + + /* Add mac address */ + hellcreek_write(hellcreek, entry->mac[1] | (entry->mac[0] << 8), HR_FDBWDH); +@@ -722,6 +723,8 @@ static int __hellcreek_fdb_add(struct hellcreek *hellcreek, + meta |= entry->portmask << HR_FDBWRM0_PORTMASK_SHIFT; + if (entry->is_obt) + meta |= HR_FDBWRM0_OBT; ++ if (entry->pass_blocked) ++ meta |= HR_FDBWRM0_PASS_BLOCKED; + if (entry->reprio_en) { + meta |= HR_FDBWRM0_REPRIO_EN; + meta |= entry->reprio_tc << HR_FDBWRM0_REPRIO_TC_SHIFT; +@@ -1049,7 +1052,7 @@ static void hellcreek_setup_tc_identity_mapping(struct hellcreek *hellcreek) + + static int hellcreek_setup_fdb(struct hellcreek *hellcreek) + { +- static struct hellcreek_fdb_entry ptp = { ++ static struct hellcreek_fdb_entry l2_ptp = { + /* MAC: 01-1B-19-00-00-00 */ + .mac = { 0x01, 0x1b, 0x19, 0x00, 0x00, 0x00 }, + .portmask = 0x03, /* Management ports */ +@@ -1060,24 +1063,94 @@ static int hellcreek_setup_fdb(struct hellcreek *hellcreek) + .reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */ + .reprio_en = 1, + }; +- static struct hellcreek_fdb_entry p2p = { ++ static struct hellcreek_fdb_entry udp4_ptp = { ++ /* MAC: 01-00-5E-00-01-81 */ ++ .mac = { 0x01, 0x00, 0x5e, 0x00, 0x01, 0x81 }, ++ .portmask = 0x03, /* Management ports */ ++ .age = 0, ++ .is_obt = 0, ++ .pass_blocked = 0, ++ .is_static = 1, ++ .reprio_tc = 6, ++ .reprio_en = 1, ++ }; ++ static struct hellcreek_fdb_entry udp6_ptp = { ++ /* MAC: 33-33-00-00-01-81 */ ++ .mac = { 0x33, 0x33, 0x00, 0x00, 0x01, 0x81 }, ++ .portmask = 0x03, /* Management ports */ ++ .age = 0, ++ .is_obt = 0, ++ .pass_blocked = 0, ++ .is_static = 1, ++ .reprio_tc = 6, ++ .reprio_en = 1, ++ }; ++ static struct hellcreek_fdb_entry l2_p2p = { + /* MAC: 01-80-C2-00-00-0E */ + .mac = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }, + .portmask = 0x03, /* Management ports */ + .age = 0, + .is_obt = 0, +- .pass_blocked = 0, ++ .pass_blocked = 1, + .is_static = 1, + .reprio_tc = 6, /* TC: 6 as per IEEE 802.1AS */ + .reprio_en = 1, + }; ++ static struct hellcreek_fdb_entry udp4_p2p = { ++ /* MAC: 01-00-5E-00-00-6B */ ++ .mac = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x6b }, ++ .portmask = 0x03, /* Management ports */ ++ .age = 0, ++ .is_obt = 0, ++ .pass_blocked = 1, ++ .is_static = 1, ++ .reprio_tc = 6, ++ .reprio_en = 1, ++ }; ++ static struct hellcreek_fdb_entry udp6_p2p = { ++ /* MAC: 33-33-00-00-00-6B */ ++ .mac = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x6b }, ++ .portmask = 0x03, /* Management ports */ ++ .age = 0, ++ .is_obt = 0, ++ .pass_blocked = 1, ++ .is_static = 1, ++ .reprio_tc = 6, ++ .reprio_en = 1, ++ }; ++ static struct hellcreek_fdb_entry stp = { ++ /* MAC: 01-80-C2-00-00-00 */ ++ .mac = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }, ++ .portmask = 0x03, /* Management ports */ ++ .age = 0, ++ .is_obt = 0, ++ .pass_blocked = 1, ++ .is_static = 1, ++ .reprio_tc = 6, ++ .reprio_en = 1, ++ }; + int ret; + + mutex_lock(&hellcreek->reg_lock); +- ret = __hellcreek_fdb_add(hellcreek, &ptp); ++ ret = __hellcreek_fdb_add(hellcreek, &l2_ptp); ++ if (ret) ++ goto out; ++ ret = __hellcreek_fdb_add(hellcreek, &udp4_ptp); ++ if (ret) ++ goto out; ++ ret = __hellcreek_fdb_add(hellcreek, &udp6_ptp); ++ if (ret) ++ goto out; ++ ret = __hellcreek_fdb_add(hellcreek, &l2_p2p); ++ if (ret) ++ goto out; ++ ret = __hellcreek_fdb_add(hellcreek, &udp4_p2p); ++ if (ret) ++ goto out; ++ ret = __hellcreek_fdb_add(hellcreek, &udp6_p2p); + if (ret) + goto out; +- ret = __hellcreek_fdb_add(hellcreek, &p2p); ++ ret = __hellcreek_fdb_add(hellcreek, &stp); + out: + mutex_unlock(&hellcreek->reg_lock); + +diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c +index 89f920289ae21..0b6f29ee87b56 100644 +--- a/drivers/net/dsa/lan9303-core.c ++++ b/drivers/net/dsa/lan9303-core.c +@@ -10,6 +10,7 @@ + #include <linux/mii.h> + #include <linux/phy.h> + #include <linux/if_bridge.h> ++#include <linux/if_vlan.h> + #include <linux/etherdevice.h> + + #include "lan9303.h" +@@ -1083,21 +1084,27 @@ static void lan9303_adjust_link(struct dsa_switch *ds, int port, + static int lan9303_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phy) + { ++ struct dsa_port *dp = dsa_to_port(ds, port); + struct lan9303 *chip = ds->priv; + +- if (!dsa_is_user_port(ds, port)) ++ if (!dsa_port_is_user(dp)) + return 0; + ++ vlan_vid_add(dp->cpu_dp->master, htons(ETH_P_8021Q), port); ++ + return lan9303_enable_processing_port(chip, port); + } + + static void lan9303_port_disable(struct dsa_switch *ds, int port) + { ++ struct dsa_port *dp = dsa_to_port(ds, port); + struct lan9303 *chip = ds->priv; + +- if (!dsa_is_user_port(ds, port)) ++ if (!dsa_port_is_user(dp)) + return; + ++ vlan_vid_del(dp->cpu_dp->master, htons(ETH_P_8021Q), port); ++ + lan9303_disable_processing_port(chip, port); + lan9303_phy_write(ds, chip->phy_addr_base + port, MII_BMCR, BMCR_PDOWN); + } +@@ -1309,7 +1316,7 @@ static int lan9303_probe_reset_gpio(struct lan9303 *chip, + struct device_node *np) + { + chip->reset_gpio = devm_gpiod_get_optional(chip->dev, "reset", +- GPIOD_OUT_LOW); ++ GPIOD_OUT_HIGH); + if (IS_ERR(chip->reset_gpio)) + return PTR_ERR(chip->reset_gpio); + +diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c +index dbd4486a173ff..9e006a25b636c 100644 +--- a/drivers/net/dsa/lantiq_gswip.c ++++ b/drivers/net/dsa/lantiq_gswip.c +@@ -497,8 +497,9 @@ static int gswip_mdio_rd(struct mii_bus *bus, int addr, int reg) + static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np) + { + struct dsa_switch *ds = priv->ds; ++ int err; + +- ds->slave_mii_bus = devm_mdiobus_alloc(priv->dev); ++ ds->slave_mii_bus = mdiobus_alloc(); + if (!ds->slave_mii_bus) + return -ENOMEM; + +@@ -511,7 +512,11 @@ static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np) + ds->slave_mii_bus->parent = priv->dev; + ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask; + +- return of_mdiobus_register(ds->slave_mii_bus, mdio_np); ++ err = of_mdiobus_register(ds->slave_mii_bus, mdio_np); ++ if (err) ++ mdiobus_free(ds->slave_mii_bus); ++ ++ return err; + } + + static int gswip_pce_table_entry_read(struct gswip_priv *priv, +@@ -2170,8 +2175,10 @@ disable_switch: + gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); + dsa_unregister_switch(priv->ds); + mdio_bus: +- if (mdio_np) ++ if (mdio_np) { + mdiobus_unregister(priv->ds->slave_mii_bus); ++ mdiobus_free(priv->ds->slave_mii_bus); ++ } + put_mdio_node: + of_node_put(mdio_np); + for (i = 0; i < priv->num_gphy_fw; i++) +@@ -2195,6 +2202,7 @@ static int gswip_remove(struct platform_device *pdev) + if (priv->ds->slave_mii_bus) { + mdiobus_unregister(priv->ds->slave_mii_bus); + of_node_put(priv->ds->slave_mii_bus->dev.of_node); ++ mdiobus_free(priv->ds->slave_mii_bus); + } + + for (i = 0; i < priv->num_gphy_fw; i++) +diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c +index 9890672a206d0..fb59efc7f9266 100644 +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2066,7 +2066,7 @@ mt7530_setup_mdio(struct mt7530_priv *priv) + if (priv->irq) + mt7530_setup_mdio_irq(priv); + +- ret = mdiobus_register(bus); ++ ret = devm_mdiobus_register(dev, bus); + if (ret) { + dev_err(dev, "failed to register MDIO bus: %d\n", ret); + if (priv->irq) +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index 8dadcae93c9b5..263da7e2d6be7 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -471,6 +471,12 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) + u16 reg; + int err; + ++ /* The 88e6250 family does not have the PHY detect bit. Instead, ++ * report whether the port is internal. ++ */ ++ if (chip->info->family == MV88E6XXX_FAMILY_6250) ++ return port < chip->info->num_internal_phys; ++ + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); + if (err) { + dev_err(chip->dev, +@@ -640,7 +646,10 @@ static void mv88e6393x_phylink_validate(struct mv88e6xxx_chip *chip, int port, + unsigned long *mask, + struct phylink_link_state *state) + { +- if (port == 0 || port == 9 || port == 10) { ++ bool is_6191x = ++ chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; ++ ++ if (((port == 0 || port == 9) && !is_6191x) || port == 10) { + phylink_set(mask, 10000baseT_Full); + phylink_set(mask, 10000baseKR_Full); + phylink_set(mask, 10000baseCR_Full); +@@ -690,44 +699,48 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, + { + struct mv88e6xxx_chip *chip = ds->priv; + struct mv88e6xxx_port *p; +- int err; ++ int err = 0; + + p = &chip->ports[port]; + +- /* FIXME: is this the correct test? If we're in fixed mode on an +- * internal port, why should we process this any different from +- * PHY mode? On the other hand, the port may be automedia between +- * an internal PHY and the serdes... +- */ +- if ((mode == MLO_AN_PHY) && mv88e6xxx_phy_is_internal(ds, port)) +- return; +- + mv88e6xxx_reg_lock(chip); +- /* In inband mode, the link may come up at any time while the link +- * is not forced down. Force the link down while we reconfigure the +- * interface mode. +- */ +- if (mode == MLO_AN_INBAND && p->interface != state->interface && +- chip->info->ops->port_set_link) +- chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN); +- +- err = mv88e6xxx_port_config_interface(chip, port, state->interface); +- if (err && err != -EOPNOTSUPP) +- goto err_unlock; + +- err = mv88e6xxx_serdes_pcs_config(chip, port, mode, state->interface, +- state->advertising); +- /* FIXME: we should restart negotiation if something changed - which +- * is something we get if we convert to using phylinks PCS operations. +- */ +- if (err > 0) +- err = 0; ++ if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { ++ /* In inband mode, the link may come up at any time while the ++ * link is not forced down. Force the link down while we ++ * reconfigure the interface mode. ++ */ ++ if (mode == MLO_AN_INBAND && ++ p->interface != state->interface && ++ chip->info->ops->port_set_link) ++ chip->info->ops->port_set_link(chip, port, ++ LINK_FORCED_DOWN); ++ ++ err = mv88e6xxx_port_config_interface(chip, port, ++ state->interface); ++ if (err && err != -EOPNOTSUPP) ++ goto err_unlock; ++ ++ err = mv88e6xxx_serdes_pcs_config(chip, port, mode, ++ state->interface, ++ state->advertising); ++ /* FIXME: we should restart negotiation if something changed - ++ * which is something we get if we convert to using phylinks ++ * PCS operations. ++ */ ++ if (err > 0) ++ err = 0; ++ } + + /* Undo the forced down state above after completing configuration +- * irrespective of its state on entry, which allows the link to come up. ++ * irrespective of its state on entry, which allows the link to come ++ * up in the in-band case where there is no separate SERDES. Also ++ * ensure that the link can come up if the PPU is in use and we are ++ * in PHY mode (we treat the PPU as an effective in-band mechanism.) + */ +- if (mode == MLO_AN_INBAND && p->interface != state->interface && +- chip->info->ops->port_set_link) ++ if (chip->info->ops->port_set_link && ++ ((mode == MLO_AN_INBAND && p->interface != state->interface) || ++ (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port)))) + chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); + + p->interface = state->interface; +@@ -750,13 +763,16 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, + ops = chip->info->ops; + + mv88e6xxx_reg_lock(chip); +- /* Internal PHYs propagate their configuration directly to the MAC. +- * External PHYs depend on whether the PPU is enabled for this port. ++ /* Force the link down if we know the port may not be automatically ++ * updated by the switch or if we are using fixed-link mode. + */ +- if (((!mv88e6xxx_phy_is_internal(ds, port) && +- !mv88e6xxx_port_ppu_updates(chip, port)) || ++ if ((!mv88e6xxx_port_ppu_updates(chip, port) || + mode == MLO_AN_FIXED) && ops->port_sync_link) + err = ops->port_sync_link(chip, port, mode, false); ++ ++ if (!err && ops->port_set_speed_duplex) ++ err = ops->port_set_speed_duplex(chip, port, SPEED_UNFORCED, ++ DUPLEX_UNFORCED); + mv88e6xxx_reg_unlock(chip); + + if (err) +@@ -777,11 +793,11 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, + ops = chip->info->ops; + + mv88e6xxx_reg_lock(chip); +- /* Internal PHYs propagate their configuration directly to the MAC. +- * External PHYs depend on whether the PPU is enabled for this port. ++ /* Configure and force the link up if we know that the port may not ++ * automatically updated by the switch or if we are using fixed-link ++ * mode. + */ +- if ((!mv88e6xxx_phy_is_internal(ds, port) && +- !mv88e6xxx_port_ppu_updates(chip, port)) || ++ if (!mv88e6xxx_port_ppu_updates(chip, port) || + mode == MLO_AN_FIXED) { + /* FIXME: for an automedia port, should we force the link + * down here - what if the link comes up due to "other" media +@@ -2275,6 +2291,13 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, + if (!mv88e6xxx_max_vid(chip)) + return -EOPNOTSUPP; + ++ /* The ATU removal procedure needs the FID to be mapped in the VTU, ++ * but FDB deletion runs concurrently with VLAN deletion. Flush the DSA ++ * switchdev workqueue to ensure that all FDB entries are deleted ++ * before we remove the VLAN. ++ */ ++ dsa_flush_workqueue(); ++ + mv88e6xxx_reg_lock(chip); + + err = mv88e6xxx_port_get_pvid(chip, port, &pvid); +@@ -3400,7 +3423,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, + return err; + } + +- bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus)); ++ bus = mdiobus_alloc_size(sizeof(*mdio_bus)); + if (!bus) + return -ENOMEM; + +@@ -3425,14 +3448,14 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, + if (!external) { + err = mv88e6xxx_g2_irq_mdio_setup(chip, bus); + if (err) +- return err; ++ goto out; + } + + err = of_mdiobus_register(bus, np); + if (err) { + dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err); + mv88e6xxx_g2_irq_mdio_free(chip, bus); +- return err; ++ goto out; + } + + if (external) +@@ -3441,21 +3464,26 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, + list_add(&mdio_bus->list, &chip->mdios); + + return 0; ++ ++out: ++ mdiobus_free(bus); ++ return err; + } + + static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) + + { +- struct mv88e6xxx_mdio_bus *mdio_bus; ++ struct mv88e6xxx_mdio_bus *mdio_bus, *p; + struct mii_bus *bus; + +- list_for_each_entry(mdio_bus, &chip->mdios, list) { ++ list_for_each_entry_safe(mdio_bus, p, &chip->mdios, list) { + bus = mdio_bus->bus; + + if (!mdio_bus->external) + mv88e6xxx_g2_irq_mdio_free(chip, bus); + + mdiobus_unregister(bus); ++ mdiobus_free(bus); + } + } + +diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c +index d9817b20ea641..ab41619a809b3 100644 +--- a/drivers/net/dsa/mv88e6xxx/port.c ++++ b/drivers/net/dsa/mv88e6xxx/port.c +@@ -283,7 +283,7 @@ static int mv88e6xxx_port_set_speed_duplex(struct mv88e6xxx_chip *chip, + if (err) + return err; + +- if (speed) ++ if (speed != SPEED_UNFORCED) + dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed); + else + dev_dbg(chip->dev, "p%d: Speed unforced\n", port); +@@ -516,7 +516,7 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, + if (err) + return err; + +- if (speed) ++ if (speed != SPEED_UNFORCED) + dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed); + else + dev_dbg(chip->dev, "p%d: Speed unforced\n", port); +diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c +index 6ea0036787986..2b05ead515cdc 100644 +--- a/drivers/net/dsa/mv88e6xxx/serdes.c ++++ b/drivers/net/dsa/mv88e6xxx/serdes.c +@@ -50,11 +50,22 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, + } + + static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, +- u16 status, u16 lpa, ++ u16 ctrl, u16 status, u16 lpa, + struct phylink_link_state *state) + { ++ state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); ++ + if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { +- state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); ++ /* The Spped and Duplex Resolved register is 1 if AN is enabled ++ * and complete, or if AN is disabled. So with disabled AN we ++ * still get here on link up. But we want to set an_complete ++ * only if AN was enabled, thus we look at BMCR_ANENABLE. ++ * (According to 802.3-2008 section 22.2.4.2.10, we should be ++ * able to get this same value from BMSR_ANEGCAPABLE, but tests ++ * show that these Marvell PHYs don't conform to this part of ++ * the specificaion - BMSR_ANEGCAPABLE is simply always 1.) ++ */ ++ state->an_complete = !!(ctrl & BMCR_ANENABLE); + state->duplex = status & + MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? + DUPLEX_FULL : DUPLEX_HALF; +@@ -81,6 +92,18 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, + dev_err(chip->dev, "invalid PHY speed\n"); + return -EINVAL; + } ++ } else if (state->link && ++ state->interface != PHY_INTERFACE_MODE_SGMII) { ++ /* If Speed and Duplex Resolved register is 0 and link is up, it ++ * means that AN was enabled, but link partner had it disabled ++ * and the PHY invoked the Auto-Negotiation Bypass feature and ++ * linked anyway. ++ */ ++ state->duplex = DUPLEX_FULL; ++ if (state->interface == PHY_INTERFACE_MODE_2500BASEX) ++ state->speed = SPEED_2500; ++ else ++ state->speed = SPEED_1000; + } else { + state->link = false; + } +@@ -168,9 +191,15 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, + int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, + int lane, struct phylink_link_state *state) + { +- u16 lpa, status; ++ u16 lpa, status, ctrl; + int err; + ++ err = mv88e6352_serdes_read(chip, MII_BMCR, &ctrl); ++ if (err) { ++ dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); ++ return err; ++ } ++ + err = mv88e6352_serdes_read(chip, 0x11, &status); + if (err) { + dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); +@@ -183,7 +212,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, + return err; + } + +- return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); ++ return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); + } + + int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, +@@ -801,7 +830,7 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, + bool up) + { + u8 cmode = chip->ports[port].cmode; +- int err = 0; ++ int err; + + switch (cmode) { + case MV88E6XXX_PORT_STS_CMODE_SGMII: +@@ -813,6 +842,9 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, + case MV88E6XXX_PORT_STS_CMODE_RXAUI: + err = mv88e6390_serdes_power_10g(chip, lane, up); + break; ++ default: ++ err = -EINVAL; ++ break; + } + + if (!err && up) +@@ -883,9 +915,16 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, + static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, + int port, int lane, struct phylink_link_state *state) + { +- u16 lpa, status; ++ u16 lpa, status, ctrl; + int err; + ++ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6390_SGMII_BMCR, &ctrl); ++ if (err) { ++ dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); ++ return err; ++ } ++ + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_SGMII_PHY_STATUS, &status); + if (err) { +@@ -900,7 +939,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, + return err; + } + +- return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); ++ return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); + } + + static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, +@@ -1271,9 +1310,31 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) + } + } + +-static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) ++static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane, ++ bool on) + { +- u16 reg, pcs; ++ u16 reg; ++ int err; ++ ++ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6393X_SERDES_CTRL1, ®); ++ if (err) ++ return err; ++ ++ if (on) ++ reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN | ++ MV88E6393X_SERDES_CTRL1_RX_PDOWN); ++ else ++ reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN | ++ MV88E6393X_SERDES_CTRL1_RX_PDOWN; ++ ++ return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6393X_SERDES_CTRL1, reg); ++} ++ ++static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) ++{ ++ u16 reg; + int err; + + /* mv88e6393x family errata 4.6: +@@ -1284,26 +1345,45 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) + * It seems that after this workaround the SERDES is automatically + * powered up (the bit is cleared), so power it down. + */ +- if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE || +- lane == MV88E6393X_PORT10_LANE) { +- err = mv88e6390_serdes_read(chip, lane, +- MDIO_MMD_PHYXS, +- MV88E6393X_SERDES_POC, ®); +- if (err) +- return err; ++ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6393X_SERDES_POC, ®); ++ if (err) ++ return err; + +- reg &= ~MV88E6393X_SERDES_POC_PDOWN; +- reg |= MV88E6393X_SERDES_POC_RESET; ++ reg &= ~MV88E6393X_SERDES_POC_PDOWN; ++ reg |= MV88E6393X_SERDES_POC_RESET; + +- err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, +- MV88E6393X_SERDES_POC, reg); +- if (err) +- return err; ++ err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6393X_SERDES_POC, reg); ++ if (err) ++ return err; + +- err = mv88e6390_serdes_power_sgmii(chip, lane, false); +- if (err) +- return err; +- } ++ err = mv88e6390_serdes_power_sgmii(chip, lane, false); ++ if (err) ++ return err; ++ ++ return mv88e6393x_serdes_power_lane(chip, lane, false); ++} ++ ++int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) ++{ ++ int err; ++ ++ err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE); ++ if (err) ++ return err; ++ ++ err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE); ++ if (err) ++ return err; ++ ++ return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE); ++} ++ ++static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane) ++{ ++ u16 reg, pcs; ++ int err; + + /* mv88e6393x family errata 4.8: + * When a SERDES port is operating in 1000BASE-X or SGMII mode link may +@@ -1334,38 +1414,152 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) + MV88E6393X_ERRATA_4_8_REG, reg); + } + +-int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) ++static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, ++ u8 cmode) ++{ ++ static const struct { ++ u16 dev, reg, val, mask; ++ } fixes[] = { ++ { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, ++ { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, ++ { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, ++ { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, ++ { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, ++ { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, ++ { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, ++ MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, ++ }; ++ int err, i; ++ u16 reg; ++ ++ /* mv88e6393x family errata 5.2: ++ * For optimal signal integrity the following sequence should be applied ++ * to SERDES operating in 10G mode. These registers only apply to 10G ++ * operation and have no effect on other speeds. ++ */ ++ if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER) ++ return 0; ++ ++ for (i = 0; i < ARRAY_SIZE(fixes); ++i) { ++ err = mv88e6390_serdes_read(chip, lane, fixes[i].dev, ++ fixes[i].reg, ®); ++ if (err) ++ return err; ++ ++ reg &= ~fixes[i].mask; ++ reg |= fixes[i].val; ++ ++ err = mv88e6390_serdes_write(chip, lane, fixes[i].dev, ++ fixes[i].reg, reg); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip, ++ int lane, u8 cmode, bool on) + { ++ u16 reg; + int err; + +- err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT0_LANE); ++ if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX) ++ return 0; ++ ++ /* Inband AN is broken on Amethyst in 2500base-x mode when set by ++ * standard mechanism (via cmode). ++ * We can get around this by configuring the PCS mode to 1000base-x ++ * and then writing value 0x58 to register 1e.8000. (This must be done ++ * while SerDes receiver and transmitter are disabled, which is, when ++ * this function is called.) ++ * It seem that when we do this configuration to 2500base-x mode (by ++ * changing PCS mode to 1000base-x and frequency to 3.125 GHz from ++ * 1.25 GHz) and then configure to sgmii or 1000base-x, the device ++ * thinks that it already has SerDes at 1.25 GHz and does not change ++ * the 1e.8000 register, leaving SerDes at 3.125 GHz. ++ * To avoid this, change PCS mode back to 2500base-x when disabling ++ * SerDes from 2500base-x mode. ++ */ ++ err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6393X_SERDES_POC, ®); ++ if (err) ++ return err; ++ ++ reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN); ++ if (on) ++ reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX | ++ MV88E6393X_SERDES_POC_AN; ++ else ++ reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX; ++ reg |= MV88E6393X_SERDES_POC_RESET; ++ ++ err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, ++ MV88E6393X_SERDES_POC, reg); + if (err) + return err; + +- err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT9_LANE); ++ err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58); + if (err) + return err; + +- return mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT10_LANE); ++ return 0; + } + + int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, + bool on) + { + u8 cmode = chip->ports[port].cmode; ++ int err; + + if (port != 0 && port != 9 && port != 10) + return -EOPNOTSUPP; + ++ if (on) { ++ err = mv88e6393x_serdes_erratum_4_8(chip, lane); ++ if (err) ++ return err; ++ ++ err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode); ++ if (err) ++ return err; ++ ++ err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, ++ true); ++ if (err) ++ return err; ++ ++ err = mv88e6393x_serdes_power_lane(chip, lane, true); ++ if (err) ++ return err; ++ } ++ + switch (cmode) { + case MV88E6XXX_PORT_STS_CMODE_SGMII: + case MV88E6XXX_PORT_STS_CMODE_1000BASEX: + case MV88E6XXX_PORT_STS_CMODE_2500BASEX: +- return mv88e6390_serdes_power_sgmii(chip, lane, on); ++ err = mv88e6390_serdes_power_sgmii(chip, lane, on); ++ break; + case MV88E6393X_PORT_STS_CMODE_5GBASER: + case MV88E6393X_PORT_STS_CMODE_10GBASER: +- return mv88e6390_serdes_power_10g(chip, lane, on); ++ err = mv88e6390_serdes_power_10g(chip, lane, on); ++ break; ++ default: ++ err = -EINVAL; ++ break; + } + +- return 0; ++ if (err) ++ return err; ++ ++ if (!on) { ++ err = mv88e6393x_serdes_power_lane(chip, lane, false); ++ if (err) ++ return err; ++ ++ err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, ++ false); ++ } ++ ++ return err; + } +diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h +index cbb3ba30caea9..8dd8ed225b459 100644 +--- a/drivers/net/dsa/mv88e6xxx/serdes.h ++++ b/drivers/net/dsa/mv88e6xxx/serdes.h +@@ -93,6 +93,10 @@ + #define MV88E6393X_SERDES_POC_PCS_MASK 0x0007 + #define MV88E6393X_SERDES_POC_RESET BIT(15) + #define MV88E6393X_SERDES_POC_PDOWN BIT(5) ++#define MV88E6393X_SERDES_POC_AN BIT(3) ++#define MV88E6393X_SERDES_CTRL1 0xf003 ++#define MV88E6393X_SERDES_CTRL1_TX_PDOWN BIT(9) ++#define MV88E6393X_SERDES_CTRL1_RX_PDOWN BIT(8) + + #define MV88E6393X_ERRATA_4_8_REG 0xF074 + #define MV88E6393X_ERRATA_4_8_BIT BIT(14) +diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c +index 341236dcbdb47..1513dfb523de7 100644 +--- a/drivers/net/dsa/ocelot/felix.c ++++ b/drivers/net/dsa/ocelot/felix.c +@@ -290,8 +290,11 @@ static int felix_setup_mmio_filtering(struct felix *felix) + } + } + +- if (cpu < 0) ++ if (cpu < 0) { ++ kfree(tagging_rule); ++ kfree(redirect_rule); + return -EINVAL; ++ } + + tagging_rule->key_type = OCELOT_VCAP_KEY_ETYPE; + *(__be16 *)tagging_rule->key.etype.etype.value = htons(ETH_P_1588); +@@ -1368,12 +1371,12 @@ out: + static bool felix_rxtstamp(struct dsa_switch *ds, int port, + struct sk_buff *skb, unsigned int type) + { +- u8 *extraction = skb->data - ETH_HLEN - OCELOT_TAG_LEN; ++ u32 tstamp_lo = OCELOT_SKB_CB(skb)->tstamp_lo; + struct skb_shared_hwtstamps *shhwtstamps; + struct ocelot *ocelot = ds->priv; +- u32 tstamp_lo, tstamp_hi; + struct timespec64 ts; +- u64 tstamp, val; ++ u32 tstamp_hi; ++ u64 tstamp; + + /* If the "no XTR IRQ" workaround is in use, tell DSA to defer this skb + * for RX timestamping. Then free it, and poll for its copy through +@@ -1388,9 +1391,6 @@ static bool felix_rxtstamp(struct dsa_switch *ds, int port, + ocelot_ptp_gettime64(&ocelot->ptp_info, &ts); + tstamp = ktime_set(ts.tv_sec, ts.tv_nsec); + +- ocelot_xfh_get_rew_val(extraction, &val); +- tstamp_lo = (u32)val; +- + tstamp_hi = tstamp >> 32; + if ((tstamp & 0xffffffff) < tstamp_lo) + tstamp_hi--; +diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c +index 11b42fd812e4a..e53ad283e2596 100644 +--- a/drivers/net/dsa/ocelot/felix_vsc9959.c ++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c +@@ -1066,7 +1066,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) + return PTR_ERR(hw); + } + +- bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); ++ bus = mdiobus_alloc_size(sizeof(*mdio_priv)); + if (!bus) + return -ENOMEM; + +@@ -1086,6 +1086,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) + rc = mdiobus_register(bus); + if (rc < 0) { + dev_err(dev, "failed to register MDIO bus\n"); ++ mdiobus_free(bus); + return rc; + } + +@@ -1135,6 +1136,7 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot) + lynx_pcs_destroy(pcs); + } + mdiobus_unregister(felix->imdio); ++ mdiobus_free(felix->imdio); + } + + static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, +diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c +index de1d34a1f1e47..05e4e75c01076 100644 +--- a/drivers/net/dsa/ocelot/seville_vsc9953.c ++++ b/drivers/net/dsa/ocelot/seville_vsc9953.c +@@ -10,6 +10,7 @@ + #include <linux/pcs-lynx.h> + #include <linux/dsa/ocelot.h> + #include <linux/iopoll.h> ++#include <linux/of_mdio.h> + #include "felix.h" + + #define MSCC_MIIM_CMD_OPR_WRITE BIT(1) +@@ -1110,7 +1111,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev)); + + /* Needed in order to initialize the bus mutex lock */ +- rc = mdiobus_register(bus); ++ rc = devm_of_mdiobus_register(dev, bus, NULL); + if (rc < 0) { + dev_err(dev, "failed to register MDIO bus\n"); + return rc; +@@ -1162,7 +1163,8 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot) + mdio_device_free(pcs->mdio); + lynx_pcs_destroy(pcs); + } +- mdiobus_unregister(felix->imdio); ++ ++ /* mdiobus_unregister and mdiobus_free handled by devres */ + } + + static const struct felix_info seville_info_vsc9953 = { +diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c +index a6bfb6abc51a7..5d476f452396c 100644 +--- a/drivers/net/dsa/qca/ar9331.c ++++ b/drivers/net/dsa/qca/ar9331.c +@@ -378,7 +378,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv) + if (!mnp) + return -ENODEV; + +- ret = of_mdiobus_register(mbus, mnp); ++ ret = devm_of_mdiobus_register(dev, mbus, mnp); + of_node_put(mnp); + if (ret) + return ret; +@@ -1093,7 +1093,6 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev) + } + + irq_domain_remove(priv->irqdomain); +- mdiobus_unregister(priv->mbus); + dsa_unregister_switch(&priv->ds); + + reset_control_assert(priv->sw_reset); +diff --git a/drivers/net/dsa/rtl8366.c b/drivers/net/dsa/rtl8366.c +index 75897a3690969..ffbe5b6b2655b 100644 +--- a/drivers/net/dsa/rtl8366.c ++++ b/drivers/net/dsa/rtl8366.c +@@ -457,7 +457,7 @@ int rtl8366_vlan_del(struct dsa_switch *ds, int port, + * anymore then clear the whole member + * config so it can be reused. + */ +- if (!vlanmc.member && vlanmc.untag) { ++ if (!vlanmc.member) { + vlanmc.vid = 0; + vlanmc.priority = 0; + vlanmc.fid = 0; +diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c +index a89093bc6c6ad..9e3b572ed999e 100644 +--- a/drivers/net/dsa/rtl8366rb.c ++++ b/drivers/net/dsa/rtl8366rb.c +@@ -1350,7 +1350,7 @@ static int rtl8366rb_set_mc_index(struct realtek_smi *smi, int port, int index) + + static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan) + { +- unsigned int max = RTL8366RB_NUM_VLANS; ++ unsigned int max = RTL8366RB_NUM_VLANS - 1; + + if (smi->vlan4k_enabled) + max = RTL8366RB_NUM_VIDS - 1; +diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c +index 1c00d719e5d76..804b37c76b1e6 100644 +--- a/drivers/net/ethernet/altera/altera_tse_main.c ++++ b/drivers/net/ethernet/altera/altera_tse_main.c +@@ -1430,16 +1430,19 @@ static int altera_tse_probe(struct platform_device *pdev) + priv->rxdescmem_busaddr = dma_res->start; + + } else { ++ ret = -ENODEV; + goto err_free_netdev; + } + +- if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) ++ if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) { + dma_set_coherent_mask(priv->device, + DMA_BIT_MASK(priv->dmaops->dmamask)); +- else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) ++ } else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) { + dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); +- else ++ } else { ++ ret = -EIO; + goto err_free_netdev; ++ } + + /* MAC address space */ + ret = request_and_map(pdev, "control_port", &control_port, +diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c +index 0e43000614abd..8f08e0bae3004 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c ++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c +@@ -1288,26 +1288,22 @@ static int handle_invalid_req_id(struct ena_ring *ring, u16 req_id, + + static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id) + { +- struct ena_tx_buffer *tx_info = NULL; ++ struct ena_tx_buffer *tx_info; + +- if (likely(req_id < tx_ring->ring_size)) { +- tx_info = &tx_ring->tx_buffer_info[req_id]; +- if (likely(tx_info->skb)) +- return 0; +- } ++ tx_info = &tx_ring->tx_buffer_info[req_id]; ++ if (likely(tx_info->skb)) ++ return 0; + + return handle_invalid_req_id(tx_ring, req_id, tx_info, false); + } + + static int validate_xdp_req_id(struct ena_ring *xdp_ring, u16 req_id) + { +- struct ena_tx_buffer *tx_info = NULL; ++ struct ena_tx_buffer *tx_info; + +- if (likely(req_id < xdp_ring->ring_size)) { +- tx_info = &xdp_ring->tx_buffer_info[req_id]; +- if (likely(tx_info->xdpf)) +- return 0; +- } ++ tx_info = &xdp_ring->tx_buffer_info[req_id]; ++ if (likely(tx_info->xdpf)) ++ return 0; + + return handle_invalid_req_id(xdp_ring, req_id, tx_info, true); + } +@@ -1332,9 +1328,14 @@ static int ena_clean_tx_irq(struct ena_ring *tx_ring, u32 budget) + + rc = ena_com_tx_comp_req_id_get(tx_ring->ena_com_io_cq, + &req_id); +- if (rc) ++ if (rc) { ++ if (unlikely(rc == -EINVAL)) ++ handle_invalid_req_id(tx_ring, req_id, NULL, ++ false); + break; ++ } + ++ /* validate that the request id points to a valid skb */ + rc = validate_tx_req_id(tx_ring, req_id); + if (rc) + break; +@@ -1427,6 +1428,7 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, + u16 *next_to_clean) + { + struct ena_rx_buffer *rx_info; ++ struct ena_adapter *adapter; + u16 len, req_id, buf = 0; + struct sk_buff *skb; + void *page_addr; +@@ -1439,8 +1441,14 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, + rx_info = &rx_ring->rx_buffer_info[req_id]; + + if (unlikely(!rx_info->page)) { +- netif_err(rx_ring->adapter, rx_err, rx_ring->netdev, +- "Page is NULL\n"); ++ adapter = rx_ring->adapter; ++ netif_err(adapter, rx_err, rx_ring->netdev, ++ "Page is NULL. qid %u req_id %u\n", rx_ring->qid, req_id); ++ ena_increase_stat(&rx_ring->rx_stats.bad_req_id, 1, &rx_ring->syncp); ++ adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID; ++ /* Make sure reset reason is set before triggering the reset */ ++ smp_mb__before_atomic(); ++ set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); + return NULL; + } + +@@ -1896,9 +1904,14 @@ static int ena_clean_xdp_irq(struct ena_ring *xdp_ring, u32 budget) + + rc = ena_com_tx_comp_req_id_get(xdp_ring->ena_com_io_cq, + &req_id); +- if (rc) ++ if (rc) { ++ if (unlikely(rc == -EINVAL)) ++ handle_invalid_req_id(xdp_ring, req_id, NULL, ++ true); + break; ++ } + ++ /* validate that the request id points to a valid xdp_frame */ + rc = validate_xdp_req_id(xdp_ring, req_id); + if (rc) + break; +@@ -4013,10 +4026,6 @@ static u32 ena_calc_max_io_queue_num(struct pci_dev *pdev, + max_num_io_queues = min_t(u32, max_num_io_queues, io_tx_cq_num); + /* 1 IRQ for mgmnt and 1 IRQs for each IO direction */ + max_num_io_queues = min_t(u32, max_num_io_queues, pci_msix_vec_count(pdev) - 1); +- if (unlikely(!max_num_io_queues)) { +- dev_err(&pdev->dev, "The device doesn't have io queues\n"); +- return -EFAULT; +- } + + return max_num_io_queues; + } +diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig +index 4786f0504691d..899c8a2a34b6b 100644 +--- a/drivers/net/ethernet/amd/Kconfig ++++ b/drivers/net/ethernet/amd/Kconfig +@@ -168,7 +168,7 @@ config SUNLANCE + + config AMD_XGBE + tristate "AMD 10GbE Ethernet driver" +- depends on ((OF_NET && OF_ADDRESS) || ACPI || PCI) && HAS_IOMEM ++ depends on (OF_ADDRESS || ACPI || PCI) && HAS_IOMEM + depends on X86 || ARM64 || COMPILE_TEST + depends on PTP_1588_CLOCK_OPTIONAL + select BITREVERSE +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +index b2cd3bdba9f89..533b8519ec352 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h +@@ -1331,6 +1331,10 @@ + #define MDIO_VEND2_PMA_CDR_CONTROL 0x8056 + #endif + ++#ifndef MDIO_VEND2_PMA_MISC_CTRL0 ++#define MDIO_VEND2_PMA_MISC_CTRL0 0x8090 ++#endif ++ + #ifndef MDIO_CTRL1_SPEED1G + #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) + #endif +@@ -1389,6 +1393,10 @@ + #define XGBE_PMA_RX_RST_0_RESET_ON 0x10 + #define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 + ++#define XGBE_PMA_PLL_CTRL_MASK BIT(15) ++#define XGBE_PMA_PLL_CTRL_ENABLE BIT(15) ++#define XGBE_PMA_PLL_CTRL_DISABLE 0x0000 ++ + /* Bit setting and getting macros + * The get macro will extract the current bit field value from within + * the variable +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 17a585adfb49c..e6883d52d230c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -721,7 +721,9 @@ static void xgbe_stop_timers(struct xgbe_prv_data *pdata) + if (!channel->tx_ring) + break; + ++ /* Deactivate the Tx timer */ + del_timer_sync(&channel->tx_timer); ++ channel->tx_timer_active = 0; + } + } + +@@ -2555,6 +2557,14 @@ read_again: + buf2_len = xgbe_rx_buf2_len(rdata, packet, len); + len += buf2_len; + ++ if (buf2_len > rdata->rx.buf.dma_len) { ++ /* Hardware inconsistency within the descriptors ++ * that has resulted in a length underflow. ++ */ ++ error = 1; ++ goto skip_data; ++ } ++ + if (!skb) { + skb = xgbe_create_skb(pdata, napi, rdata, + buf1_len); +@@ -2584,8 +2594,10 @@ skip_data: + if (!last || context_next) + goto read_again; + +- if (!skb) ++ if (!skb || error) { ++ dev_kfree_skb(skb); + goto next_packet; ++ } + + /* Be sure we don't exceed the configured MTU */ + max_len = netdev->mtu + ETH_HLEN; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index 90cb55eb54665..014513ce00a14 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -418,6 +418,9 @@ static void xgbe_pci_remove(struct pci_dev *pdev) + + pci_free_irq_vectors(pdata->pcidev); + ++ /* Disable all interrupts in the hardware */ ++ XP_IOWRITE(pdata, XP_INT_EN, 0x0); ++ + xgbe_free_pdata(pdata); + } + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index 18e48b3bc402b..213769054391c 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -1977,12 +1977,26 @@ static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) + } + } + ++static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable) ++{ ++ XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0, ++ XGBE_PMA_PLL_CTRL_MASK, ++ enable ? XGBE_PMA_PLL_CTRL_ENABLE ++ : XGBE_PMA_PLL_CTRL_DISABLE); ++ ++ /* Wait for command to complete */ ++ usleep_range(100, 200); ++} ++ + static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, + unsigned int cmd, unsigned int sub_cmd) + { + unsigned int s0 = 0; + unsigned int wait; + ++ /* Disable PLL re-initialization during FW command processing */ ++ xgbe_phy_pll_ctrl(pdata, false); ++ + /* Log if a previous command did not complete */ + if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { + netif_dbg(pdata, link, pdata->netdev, +@@ -2003,7 +2017,7 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, + wait = XGBE_RATECHANGE_COUNT; + while (wait--) { + if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) +- return; ++ goto reenable_pll; + + usleep_range(1000, 2000); + } +@@ -2013,6 +2027,10 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, + + /* Reset on error */ + xgbe_phy_rx_reset(pdata); ++ ++reenable_pll: ++ /* Enable PLL re-initialization */ ++ xgbe_phy_pll_ctrl(pdata, true); + } + + static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +index 23b2d390fcdda..ace691d7cd759 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h +@@ -40,10 +40,12 @@ + + #define AQ_DEVICE_ID_AQC113DEV 0x00C0 + #define AQ_DEVICE_ID_AQC113CS 0x94C0 ++#define AQ_DEVICE_ID_AQC113CA 0x34C0 + #define AQ_DEVICE_ID_AQC114CS 0x93C0 + #define AQ_DEVICE_ID_AQC113 0x04C0 + #define AQ_DEVICE_ID_AQC113C 0x14C0 + #define AQ_DEVICE_ID_AQC115C 0x12C0 ++#define AQ_DEVICE_ID_AQC116C 0x11C0 + + #define HW_ATL_NIC_NAME "Marvell (aQuantia) AQtion 10Gbit Network Adapter" + +@@ -53,20 +55,19 @@ + + #define AQ_NIC_RATE_10G BIT(0) + #define AQ_NIC_RATE_5G BIT(1) +-#define AQ_NIC_RATE_5GSR BIT(2) +-#define AQ_NIC_RATE_2G5 BIT(3) +-#define AQ_NIC_RATE_1G BIT(4) +-#define AQ_NIC_RATE_100M BIT(5) +-#define AQ_NIC_RATE_10M BIT(6) +-#define AQ_NIC_RATE_1G_HALF BIT(7) +-#define AQ_NIC_RATE_100M_HALF BIT(8) +-#define AQ_NIC_RATE_10M_HALF BIT(9) ++#define AQ_NIC_RATE_2G5 BIT(2) ++#define AQ_NIC_RATE_1G BIT(3) ++#define AQ_NIC_RATE_100M BIT(4) ++#define AQ_NIC_RATE_10M BIT(5) ++#define AQ_NIC_RATE_1G_HALF BIT(6) ++#define AQ_NIC_RATE_100M_HALF BIT(7) ++#define AQ_NIC_RATE_10M_HALF BIT(8) + +-#define AQ_NIC_RATE_EEE_10G BIT(10) +-#define AQ_NIC_RATE_EEE_5G BIT(11) +-#define AQ_NIC_RATE_EEE_2G5 BIT(12) +-#define AQ_NIC_RATE_EEE_1G BIT(13) +-#define AQ_NIC_RATE_EEE_100M BIT(14) ++#define AQ_NIC_RATE_EEE_10G BIT(9) ++#define AQ_NIC_RATE_EEE_5G BIT(10) ++#define AQ_NIC_RATE_EEE_2G5 BIT(11) ++#define AQ_NIC_RATE_EEE_1G BIT(12) ++#define AQ_NIC_RATE_EEE_100M BIT(13) + #define AQ_NIC_RATE_EEE_MSK (AQ_NIC_RATE_EEE_10G |\ + AQ_NIC_RATE_EEE_5G |\ + AQ_NIC_RATE_EEE_2G5 |\ +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +index bed481816ea31..7442850ca95f0 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +@@ -80,6 +80,8 @@ struct aq_hw_link_status_s { + }; + + struct aq_stats_s { ++ u64 brc; ++ u64 btc; + u64 uprc; + u64 mprc; + u64 bprc; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +index 6c049864dac08..9de0065f89b90 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +@@ -903,8 +903,14 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) + data[++i] = stats->mbtc; + data[++i] = stats->bbrc; + data[++i] = stats->bbtc; +- data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; +- data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; ++ if (stats->brc) ++ data[++i] = stats->brc; ++ else ++ data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; ++ if (stats->btc) ++ data[++i] = stats->btc; ++ else ++ data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; + data[++i] = stats->dma_pkt_rc; + data[++i] = stats->dma_pkt_tc; + data[++i] = stats->dma_oct_rc; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +index d4b1976ee69b9..797a95142d1f4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +@@ -49,6 +49,8 @@ static const struct pci_device_id aq_pci_tbl[] = { + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CA), }, ++ { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC116C), }, + + {} + }; +@@ -85,7 +87,10 @@ static const struct aq_board_revision_s hw_atl_boards[] = { + { AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, + { AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, +- { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc115c, }, ++ { AQ_DEVICE_ID_AQC113CA, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, ++ { AQ_DEVICE_ID_AQC116C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc116c, }, ++ + }; + + MODULE_DEVICE_TABLE(pci, aq_pci_tbl); +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 24122ccda614c..72f8751784c31 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -365,6 +365,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + if (!buff->is_eop) { + buff_ = buff; + do { ++ if (buff_->next >= self->size) { ++ err = -EIO; ++ goto err_exit; ++ } + next_ = buff_->next, + buff_ = &self->buff_ring[next_]; + is_rsc_completed = +@@ -388,6 +392,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + (buff->is_lro && buff->is_cso_err)) { + buff_ = buff; + do { ++ if (buff_->next >= self->size) { ++ err = -EIO; ++ goto err_exit; ++ } + next_ = buff_->next, + buff_ = &self->buff_ring[next_]; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +index d281322d7dd29..f4774cf051c97 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +@@ -362,9 +362,6 @@ unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u + { + unsigned int count; + +- WARN_ONCE(!aq_vec_is_valid_tc(self, tc), +- "Invalid tc %u (#rx=%u, #tx=%u)\n", +- tc, self->rx_rings, self->tx_rings); + if (!aq_vec_is_valid_tc(self, tc)) + return 0; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +index 404cbf60d3f2f..65b9e5846be45 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +@@ -559,6 +559,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, + goto err_exit; + + if (fw.len == 0xFFFFU) { ++ if (sw.len > sizeof(self->rpc)) { ++ printk(KERN_INFO "Invalid sw len: %x\n", sw.len); ++ err = -EINVAL; ++ goto err_exit; ++ } + err = hw_atl_utils_fw_rpc_call(self, sw.len); + if (err < 0) + goto err_exit; +@@ -567,6 +572,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, + + if (rpc) { + if (fw.len) { ++ if (fw.len > sizeof(self->rpc)) { ++ printk(KERN_INFO "Invalid fw len: %x\n", fw.len); ++ err = -EINVAL; ++ goto err_exit; ++ } + err = + hw_atl_utils_fw_downld_dwords(self, + self->rpc_addr, +@@ -857,12 +867,20 @@ static int hw_atl_fw1x_deinit(struct aq_hw_s *self) + int hw_atl_utils_update_stats(struct aq_hw_s *self) + { + struct aq_stats_s *cs = &self->curr_stats; ++ struct aq_stats_s curr_stats = *cs; + struct hw_atl_utils_mbox mbox; ++ bool corrupted_stats = false; + + hw_atl_utils_mpi_read_stats(self, &mbox); + +-#define AQ_SDELTA(_N_) (self->curr_stats._N_ += \ +- mbox.stats._N_ - self->last_stats._N_) ++#define AQ_SDELTA(_N_) \ ++do { \ ++ if (!corrupted_stats && \ ++ ((s64)(mbox.stats._N_ - self->last_stats._N_)) >= 0) \ ++ curr_stats._N_ += mbox.stats._N_ - self->last_stats._N_; \ ++ else \ ++ corrupted_stats = true; \ ++} while (0) + + if (self->aq_link_status.mbps) { + AQ_SDELTA(uprc); +@@ -882,6 +900,9 @@ int hw_atl_utils_update_stats(struct aq_hw_s *self) + AQ_SDELTA(bbrc); + AQ_SDELTA(bbtc); + AQ_SDELTA(dpc); ++ ++ if (!corrupted_stats) ++ *cs = curr_stats; + } + #undef AQ_SDELTA + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +index ee0c22d049354..05086f0040fd9 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +@@ -132,9 +132,6 @@ static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) + if (speed & AQ_NIC_RATE_5G) + rate |= FW2X_RATE_5G; + +- if (speed & AQ_NIC_RATE_5GSR) +- rate |= FW2X_RATE_5G; +- + if (speed & AQ_NIC_RATE_2G5) + rate |= FW2X_RATE_2G5; + +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 92f64048bf691..c76ccdc77ba60 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -65,11 +65,25 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { + AQ_NIC_RATE_5G | + AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | +- AQ_NIC_RATE_1G_HALF | + AQ_NIC_RATE_100M | +- AQ_NIC_RATE_100M_HALF | +- AQ_NIC_RATE_10M | +- AQ_NIC_RATE_10M_HALF, ++ AQ_NIC_RATE_10M, ++}; ++ ++const struct aq_hw_caps_s hw_atl2_caps_aqc115c = { ++ DEFAULT_BOARD_BASIC_CAPABILITIES, ++ .media_type = AQ_HW_MEDIA_TYPE_TP, ++ .link_speed_msk = AQ_NIC_RATE_2G5 | ++ AQ_NIC_RATE_1G | ++ AQ_NIC_RATE_100M | ++ AQ_NIC_RATE_10M, ++}; ++ ++const struct aq_hw_caps_s hw_atl2_caps_aqc116c = { ++ DEFAULT_BOARD_BASIC_CAPABILITIES, ++ .media_type = AQ_HW_MEDIA_TYPE_TP, ++ .link_speed_msk = AQ_NIC_RATE_1G | ++ AQ_NIC_RATE_100M | ++ AQ_NIC_RATE_10M, + }; + + static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h +index de8723f1c28a1..346f0dc9912e5 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.h +@@ -9,6 +9,8 @@ + #include "aq_common.h" + + extern const struct aq_hw_caps_s hw_atl2_caps_aqc113; ++extern const struct aq_hw_caps_s hw_atl2_caps_aqc115c; ++extern const struct aq_hw_caps_s hw_atl2_caps_aqc116c; + extern const struct aq_hw_ops hw_atl2_ops; + + #endif /* HW_ATL2_H */ +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +index b66fa346581ce..6bad64c77b87c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils.h +@@ -239,7 +239,8 @@ struct version_s { + u8 minor; + u16 build; + } phy; +- u32 rsvd; ++ u32 drv_iface_ver:4; ++ u32 rsvd:28; + }; + + struct link_status_s { +@@ -424,7 +425,7 @@ struct cable_diag_status_s { + u16 rsvd2; + }; + +-struct statistics_s { ++struct statistics_a0_s { + struct { + u32 link_up; + u32 link_down; +@@ -457,6 +458,33 @@ struct statistics_s { + u32 reserve_fw_gap; + }; + ++struct __packed statistics_b0_s { ++ u64 rx_good_octets; ++ u64 rx_pause_frames; ++ u64 rx_good_frames; ++ u64 rx_errors; ++ u64 rx_unicast_frames; ++ u64 rx_multicast_frames; ++ u64 rx_broadcast_frames; ++ ++ u64 tx_good_octets; ++ u64 tx_pause_frames; ++ u64 tx_good_frames; ++ u64 tx_errors; ++ u64 tx_unicast_frames; ++ u64 tx_multicast_frames; ++ u64 tx_broadcast_frames; ++ ++ u32 main_loop_cycles; ++}; ++ ++struct __packed statistics_s { ++ union __packed { ++ struct statistics_a0_s a0; ++ struct statistics_b0_s b0; ++ }; ++}; ++ + struct filter_caps_s { + u8 l2_filters_base_index:6; + u8 flexible_filter_mask:2; +@@ -545,7 +573,7 @@ struct management_status_s { + u32 rsvd5; + }; + +-struct fw_interface_out { ++struct __packed fw_interface_out { + struct transaction_counter_s transaction_id; + struct version_s version; + struct link_status_s link_status; +@@ -569,7 +597,6 @@ struct fw_interface_out { + struct core_dump_s core_dump; + u32 rsvd11; + struct statistics_s stats; +- u32 rsvd12; + struct filter_caps_s filter_caps; + struct device_caps_s device_caps; + u32 rsvd13; +@@ -592,6 +619,9 @@ struct fw_interface_out { + #define AQ_HOST_MODE_LOW_POWER 3U + #define AQ_HOST_MODE_SHUTDOWN 4U + ++#define AQ_A2_FW_INTERFACE_A0 0 ++#define AQ_A2_FW_INTERFACE_B0 1 ++ + int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops); + + int hw_atl2_utils_soft_reset(struct aq_hw_s *self); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +index dd259c8f2f4f3..58d426dda3edb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c +@@ -84,7 +84,7 @@ static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self, + if (cnt > AQ_A2_FW_READ_TRY_MAX) + return -ETIME; + if (tid1.transaction_cnt_a != tid1.transaction_cnt_b) +- udelay(1); ++ mdelay(1); + } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b); + + hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords); +@@ -154,7 +154,7 @@ static void a2_link_speed_mask2fw(u32 speed, + { + link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G); + link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G); +- link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR); ++ link_options->rate_N5G = link_options->rate_5G; + link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5); + link_options->rate_N2P5G = link_options->rate_2P5G; + link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); +@@ -192,8 +192,6 @@ static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps) + rate |= AQ_NIC_RATE_10G; + if (lkp_link_caps->rate_5G) + rate |= AQ_NIC_RATE_5G; +- if (lkp_link_caps->rate_N5G) +- rate |= AQ_NIC_RATE_5GSR; + if (lkp_link_caps->rate_2P5G) + rate |= AQ_NIC_RATE_2G5; + if (lkp_link_caps->rate_1G) +@@ -335,15 +333,22 @@ static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) + return 0; + } + +-static int aq_a2_fw_update_stats(struct aq_hw_s *self) ++static void aq_a2_fill_a0_stats(struct aq_hw_s *self, ++ struct statistics_s *stats) + { + struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; +- struct statistics_s stats; +- +- hw_atl2_shared_buffer_read_safe(self, stats, &stats); +- +-#define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \ +- stats.msm._F_ - priv->last_stats.msm._F_) ++ struct aq_stats_s *cs = &self->curr_stats; ++ struct aq_stats_s curr_stats = *cs; ++ bool corrupted_stats = false; ++ ++#define AQ_SDELTA(_N, _F) \ ++do { \ ++ if (!corrupted_stats && \ ++ ((s64)(stats->a0.msm._F - priv->last_stats.a0.msm._F)) >= 0) \ ++ curr_stats._N += stats->a0.msm._F - priv->last_stats.a0.msm._F;\ ++ else \ ++ corrupted_stats = true; \ ++} while (0) + + if (self->aq_link_status.mbps) { + AQ_SDELTA(uprc, rx_unicast_frames); +@@ -362,17 +367,76 @@ static int aq_a2_fw_update_stats(struct aq_hw_s *self) + AQ_SDELTA(mbtc, tx_multicast_octets); + AQ_SDELTA(bbrc, rx_broadcast_octets); + AQ_SDELTA(bbtc, tx_broadcast_octets); ++ ++ if (!corrupted_stats) ++ *cs = curr_stats; + } + #undef AQ_SDELTA +- self->curr_stats.dma_pkt_rc = +- hw_atl_stats_rx_dma_good_pkt_counter_get(self); +- self->curr_stats.dma_pkt_tc = +- hw_atl_stats_tx_dma_good_pkt_counter_get(self); +- self->curr_stats.dma_oct_rc = +- hw_atl_stats_rx_dma_good_octet_counter_get(self); +- self->curr_stats.dma_oct_tc = +- hw_atl_stats_tx_dma_good_octet_counter_get(self); +- self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); ++ ++} ++ ++static void aq_a2_fill_b0_stats(struct aq_hw_s *self, ++ struct statistics_s *stats) ++{ ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ struct aq_stats_s *cs = &self->curr_stats; ++ struct aq_stats_s curr_stats = *cs; ++ bool corrupted_stats = false; ++ ++#define AQ_SDELTA(_N, _F) \ ++do { \ ++ if (!corrupted_stats && \ ++ ((s64)(stats->b0._F - priv->last_stats.b0._F)) >= 0) \ ++ curr_stats._N += stats->b0._F - priv->last_stats.b0._F; \ ++ else \ ++ corrupted_stats = true; \ ++} while (0) ++ ++ if (self->aq_link_status.mbps) { ++ AQ_SDELTA(uprc, rx_unicast_frames); ++ AQ_SDELTA(mprc, rx_multicast_frames); ++ AQ_SDELTA(bprc, rx_broadcast_frames); ++ AQ_SDELTA(erpr, rx_errors); ++ AQ_SDELTA(brc, rx_good_octets); ++ ++ AQ_SDELTA(uptc, tx_unicast_frames); ++ AQ_SDELTA(mptc, tx_multicast_frames); ++ AQ_SDELTA(bptc, tx_broadcast_frames); ++ AQ_SDELTA(erpt, tx_errors); ++ AQ_SDELTA(btc, tx_good_octets); ++ ++ if (!corrupted_stats) ++ *cs = curr_stats; ++ } ++#undef AQ_SDELTA ++} ++ ++static int aq_a2_fw_update_stats(struct aq_hw_s *self) ++{ ++ struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; ++ struct aq_stats_s *cs = &self->curr_stats; ++ struct statistics_s stats; ++ struct version_s version; ++ int err; ++ ++ err = hw_atl2_shared_buffer_read_safe(self, version, &version); ++ if (err) ++ return err; ++ ++ err = hw_atl2_shared_buffer_read_safe(self, stats, &stats); ++ if (err) ++ return err; ++ ++ if (version.drv_iface_ver == AQ_A2_FW_INTERFACE_A0) ++ aq_a2_fill_a0_stats(self, &stats); ++ else ++ aq_a2_fill_b0_stats(self, &stats); ++ ++ cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self); ++ cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self); ++ cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self); ++ cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self); ++ cs->dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); + + memcpy(&priv->last_stats, &stats, sizeof(stats)); + +@@ -499,9 +563,9 @@ u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) + hw_atl2_shared_buffer_read_safe(self, version, &version); + + /* A2 FW version is stored in reverse order */ +- return version.mac.major << 24 | +- version.mac.minor << 16 | +- version.mac.build; ++ return version.bundle.major << 24 | ++ version.bundle.minor << 16 | ++ version.bundle.build; + } + + int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, +diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig +index 92a79c4ffa2c7..0a67612af2281 100644 +--- a/drivers/net/ethernet/arc/Kconfig ++++ b/drivers/net/ethernet/arc/Kconfig +@@ -26,7 +26,7 @@ config ARC_EMAC_CORE + config ARC_EMAC + tristate "ARC EMAC support" + select ARC_EMAC_CORE +- depends on OF_IRQ && OF_NET ++ depends on OF_IRQ + depends on ARC || COMPILE_TEST + help + On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x +@@ -36,7 +36,7 @@ config ARC_EMAC + config EMAC_ROCKCHIP + tristate "Rockchip EMAC support" + select ARC_EMAC_CORE +- depends on OF_IRQ && OF_NET && REGULATOR ++ depends on OF_IRQ && REGULATOR + depends on ARCH_ROCKCHIP || COMPILE_TEST + help + Support for Rockchip RK3036/RK3066/RK3188 EMAC ethernet controllers. +diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c +index 02ae98aabf91c..416a5c99db5a2 100644 +--- a/drivers/net/ethernet/atheros/ag71xx.c ++++ b/drivers/net/ethernet/atheros/ag71xx.c +@@ -1915,15 +1915,12 @@ static int ag71xx_probe(struct platform_device *pdev) + ag->mac_reset = devm_reset_control_get(&pdev->dev, "mac"); + if (IS_ERR(ag->mac_reset)) { + netif_err(ag, probe, ndev, "missing mac reset\n"); +- err = PTR_ERR(ag->mac_reset); +- goto err_free; ++ return PTR_ERR(ag->mac_reset); + } + + ag->mac_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); +- if (!ag->mac_base) { +- err = -ENOMEM; +- goto err_free; +- } ++ if (!ag->mac_base) ++ return -ENOMEM; + + ndev->irq = platform_get_irq(pdev, 0); + err = devm_request_irq(&pdev->dev, ndev->irq, ag71xx_interrupt, +@@ -1931,7 +1928,7 @@ static int ag71xx_probe(struct platform_device *pdev) + if (err) { + netif_err(ag, probe, ndev, "unable to request IRQ %d\n", + ndev->irq); +- goto err_free; ++ return err; + } + + ndev->netdev_ops = &ag71xx_netdev_ops; +@@ -1959,10 +1956,8 @@ static int ag71xx_probe(struct platform_device *pdev) + ag->stop_desc = dmam_alloc_coherent(&pdev->dev, + sizeof(struct ag71xx_desc), + &ag->stop_desc_dma, GFP_KERNEL); +- if (!ag->stop_desc) { +- err = -ENOMEM; +- goto err_free; +- } ++ if (!ag->stop_desc) ++ return -ENOMEM; + + ag->stop_desc->data = 0; + ag->stop_desc->ctrl = 0; +@@ -1977,7 +1972,7 @@ static int ag71xx_probe(struct platform_device *pdev) + err = of_get_phy_mode(np, &ag->phy_if_mode); + if (err) { + netif_err(ag, probe, ndev, "missing phy-mode property in DT\n"); +- goto err_free; ++ return err; + } + + netif_napi_add(ndev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); +@@ -1985,7 +1980,7 @@ static int ag71xx_probe(struct platform_device *pdev) + err = clk_prepare_enable(ag->clk_eth); + if (err) { + netif_err(ag, probe, ndev, "Failed to enable eth clk.\n"); +- goto err_free; ++ return err; + } + + ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, 0); +@@ -2021,8 +2016,6 @@ err_mdio_remove: + ag71xx_mdio_remove(ag); + err_put_clk: + clk_disable_unprepare(ag->clk_eth); +-err_free: +- free_netdev(ndev); + return err; + } + +diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +index 3b51b172b3172..5cbd815c737e7 100644 +--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ++++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +@@ -900,7 +900,7 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, + atl1c_clean_buffer(pdev, buffer_info); + } + +- netdev_reset_queue(adapter->netdev); ++ netdev_tx_reset_queue(netdev_get_tx_queue(adapter->netdev, queue)); + + /* Zero out Tx-buffers */ + memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) * +diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c +index 02a569500234c..376f81796a293 100644 +--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c +@@ -708,7 +708,9 @@ static int bcm4908_enet_probe(struct platform_device *pdev) + + enet->irq_tx = platform_get_irq_byname(pdev, "tx"); + +- dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); ++ err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); ++ if (err) ++ return err; + + err = bcm4908_enet_dma_alloc(enet); + if (err) +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c +index 7fa1b695400d7..0877b3d7f88c5 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -1309,11 +1309,11 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, + struct bcm_sysport_priv *priv = netdev_priv(dev); + struct device *kdev = &priv->pdev->dev; + struct bcm_sysport_tx_ring *ring; ++ unsigned long flags, desc_flags; + struct bcm_sysport_cb *cb; + struct netdev_queue *txq; + u32 len_status, addr_lo; + unsigned int skb_len; +- unsigned long flags; + dma_addr_t mapping; + u16 queue; + int ret; +@@ -1373,8 +1373,10 @@ static netdev_tx_t bcm_sysport_xmit(struct sk_buff *skb, + ring->desc_count--; + + /* Ports are latched, so write upper address first */ ++ spin_lock_irqsave(&priv->desc_lock, desc_flags); + tdma_writel(priv, len_status, TDMA_WRITE_PORT_HI(ring->index)); + tdma_writel(priv, addr_lo, TDMA_WRITE_PORT_LO(ring->index)); ++ spin_unlock_irqrestore(&priv->desc_lock, desc_flags); + + /* Check ring space and update SW control flow */ + if (ring->desc_count == 0) +@@ -2013,6 +2015,7 @@ static int bcm_sysport_open(struct net_device *dev) + } + + /* Initialize both hardware and software ring */ ++ spin_lock_init(&priv->desc_lock); + for (i = 0; i < dev->num_tx_queues; i++) { + ret = bcm_sysport_init_tx_ring(priv, i); + if (ret) { +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h +index 984f76e74b43e..16b73bb9acc78 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.h ++++ b/drivers/net/ethernet/broadcom/bcmsysport.h +@@ -711,6 +711,7 @@ struct bcm_sysport_priv { + int wol_irq; + + /* Transmit rings */ ++ spinlock_t desc_lock; + struct bcm_sysport_tx_ring *tx_rings; + + /* Receive queue */ +diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c +index df8ff839cc621..94eb3a42158e9 100644 +--- a/drivers/net/ethernet/broadcom/bgmac-platform.c ++++ b/drivers/net/ethernet/broadcom/bgmac-platform.c +@@ -172,6 +172,7 @@ static int bgmac_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; + struct bgmac *bgmac; ++ struct resource *regs; + int ret; + + bgmac = bgmac_alloc(&pdev->dev); +@@ -208,15 +209,23 @@ static int bgmac_probe(struct platform_device *pdev) + if (IS_ERR(bgmac->plat.base)) + return PTR_ERR(bgmac->plat.base); + +- bgmac->plat.idm_base = devm_platform_ioremap_resource_byname(pdev, "idm_base"); +- if (IS_ERR(bgmac->plat.idm_base)) +- return PTR_ERR(bgmac->plat.idm_base); +- else ++ /* The idm_base resource is optional for some platforms */ ++ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base"); ++ if (regs) { ++ bgmac->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs); ++ if (IS_ERR(bgmac->plat.idm_base)) ++ return PTR_ERR(bgmac->plat.idm_base); + bgmac->feature_flags &= ~BGMAC_FEAT_IDM_MASK; ++ } + +- bgmac->plat.nicpm_base = devm_platform_ioremap_resource_byname(pdev, "nicpm_base"); +- if (IS_ERR(bgmac->plat.nicpm_base)) +- return PTR_ERR(bgmac->plat.nicpm_base); ++ /* The nicpm_base resource is optional for some platforms */ ++ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base"); ++ if (regs) { ++ bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev, ++ regs); ++ if (IS_ERR(bgmac->plat.nicpm_base)) ++ return PTR_ERR(bgmac->plat.nicpm_base); ++ } + + bgmac->read = platform_bgmac_read; + bgmac->write = platform_bgmac_write; +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +index e789430f407c3..72bdbebf25cec 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +@@ -1850,6 +1850,14 @@ struct bnx2x { + + /* Vxlan/Geneve related information */ + u16 udp_tunnel_ports[BNX2X_UDP_PORT_MAX]; ++ ++#define FW_CAP_INVALIDATE_VF_FP_HSI BIT(0) ++ u32 fw_cap; ++ ++ u32 fw_major; ++ u32 fw_minor; ++ u32 fw_rev; ++ u32 fw_eng; + }; + + /* Tx queues may be less or equal to Rx queues */ +@@ -2525,5 +2533,6 @@ void bnx2x_register_phc(struct bnx2x *bp); + * Meant for implicit re-load flows. + */ + int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp); +- ++int bnx2x_init_firmware(struct bnx2x *bp); ++void bnx2x_release_firmware(struct bnx2x *bp); + #endif /* bnx2x.h */ +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index b5d954cb409ae..41ebbb2c7d3ac 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -2364,10 +2364,8 @@ int bnx2x_compare_fw_ver(struct bnx2x *bp, u32 load_code, bool print_err) + if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP && + load_code != FW_MSG_CODE_DRV_LOAD_COMMON) { + /* build my FW version dword */ +- u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) + +- (BCM_5710_FW_MINOR_VERSION << 8) + +- (BCM_5710_FW_REVISION_VERSION << 16) + +- (BCM_5710_FW_ENGINEERING_VERSION << 24); ++ u32 my_fw = (bp->fw_major) + (bp->fw_minor << 8) + ++ (bp->fw_rev << 16) + (bp->fw_eng << 24); + + /* read loaded FW from chip */ + u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM); +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +index 3f8435208bf49..a84d015da5dfa 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h +@@ -241,6 +241,8 @@ + IRO[221].m2)) + #define XSTORM_VF_TO_PF_OFFSET(funcId) \ + (IRO[48].base + ((funcId) * IRO[48].m1)) ++#define XSTORM_ETH_FUNCTION_INFO_FP_HSI_VALID_E2_OFFSET(fid) \ ++ (IRO[386].base + ((fid) * IRO[386].m1)) + #define COMMON_ASM_INVALID_ASSERT_OPCODE 0x0 + + /* eth hsi version */ +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +index 622fadc50316e..611efee758340 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +@@ -3024,7 +3024,8 @@ struct afex_stats { + + #define BCM_5710_FW_MAJOR_VERSION 7 + #define BCM_5710_FW_MINOR_VERSION 13 +-#define BCM_5710_FW_REVISION_VERSION 15 ++#define BCM_5710_FW_REVISION_VERSION 21 ++#define BCM_5710_FW_REVISION_VERSION_V15 15 + #define BCM_5710_FW_ENGINEERING_VERSION 0 + #define BCM_5710_FW_COMPILE_FLAGS 1 + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h +index 1835d2e451c01..fc7fce642666c 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h +@@ -635,11 +635,13 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, + { + int i, rc; + struct bnx2x_ilt *ilt = BP_ILT(bp); +- struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; ++ struct ilt_client_info *ilt_cli; + + if (!ilt || !ilt->lines) + return -1; + ++ ilt_cli = &ilt->clients[cli_num]; ++ + if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM)) + return 0; + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index ae87296ae1ffa..dc70f6f96d024 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -74,9 +74,19 @@ + __stringify(BCM_5710_FW_MINOR_VERSION) "." \ + __stringify(BCM_5710_FW_REVISION_VERSION) "." \ + __stringify(BCM_5710_FW_ENGINEERING_VERSION) ++ ++#define FW_FILE_VERSION_V15 \ ++ __stringify(BCM_5710_FW_MAJOR_VERSION) "." \ ++ __stringify(BCM_5710_FW_MINOR_VERSION) "." \ ++ __stringify(BCM_5710_FW_REVISION_VERSION_V15) "." \ ++ __stringify(BCM_5710_FW_ENGINEERING_VERSION) ++ + #define FW_FILE_NAME_E1 "bnx2x/bnx2x-e1-" FW_FILE_VERSION ".fw" + #define FW_FILE_NAME_E1H "bnx2x/bnx2x-e1h-" FW_FILE_VERSION ".fw" + #define FW_FILE_NAME_E2 "bnx2x/bnx2x-e2-" FW_FILE_VERSION ".fw" ++#define FW_FILE_NAME_E1_V15 "bnx2x/bnx2x-e1-" FW_FILE_VERSION_V15 ".fw" ++#define FW_FILE_NAME_E1H_V15 "bnx2x/bnx2x-e1h-" FW_FILE_VERSION_V15 ".fw" ++#define FW_FILE_NAME_E2_V15 "bnx2x/bnx2x-e2-" FW_FILE_VERSION_V15 ".fw" + + /* Time in jiffies before concluding the transmitter is hung */ + #define TX_TIMEOUT (5*HZ) +@@ -90,6 +100,9 @@ MODULE_LICENSE("GPL"); + MODULE_FIRMWARE(FW_FILE_NAME_E1); + MODULE_FIRMWARE(FW_FILE_NAME_E1H); + MODULE_FIRMWARE(FW_FILE_NAME_E2); ++MODULE_FIRMWARE(FW_FILE_NAME_E1_V15); ++MODULE_FIRMWARE(FW_FILE_NAME_E1H_V15); ++MODULE_FIRMWARE(FW_FILE_NAME_E2_V15); + + int bnx2x_num_queues; + module_param_named(num_queues, bnx2x_num_queues, int, 0444); +@@ -747,9 +760,7 @@ static int bnx2x_mc_assert(struct bnx2x *bp) + CHIP_IS_E1(bp) ? "everest1" : + CHIP_IS_E1H(bp) ? "everest1h" : + CHIP_IS_E2(bp) ? "everest2" : "everest3", +- BCM_5710_FW_MAJOR_VERSION, +- BCM_5710_FW_MINOR_VERSION, +- BCM_5710_FW_REVISION_VERSION); ++ bp->fw_major, bp->fw_minor, bp->fw_rev); + + return rc; + } +@@ -12302,6 +12313,15 @@ static int bnx2x_init_bp(struct bnx2x *bp) + + bnx2x_read_fwinfo(bp); + ++ if (IS_PF(bp)) { ++ rc = bnx2x_init_firmware(bp); ++ ++ if (rc) { ++ bnx2x_free_mem_bp(bp); ++ return rc; ++ } ++ } ++ + func = BP_FUNC(bp); + + /* need to reset chip if undi was active */ +@@ -12314,6 +12334,7 @@ static int bnx2x_init_bp(struct bnx2x *bp) + + rc = bnx2x_prev_unload(bp); + if (rc) { ++ bnx2x_release_firmware(bp); + bnx2x_free_mem_bp(bp); + return rc; + } +@@ -13311,16 +13332,11 @@ static int bnx2x_check_firmware(struct bnx2x *bp) + /* Check FW version */ + offset = be32_to_cpu(fw_hdr->fw_version.offset); + fw_ver = firmware->data + offset; +- if ((fw_ver[0] != BCM_5710_FW_MAJOR_VERSION) || +- (fw_ver[1] != BCM_5710_FW_MINOR_VERSION) || +- (fw_ver[2] != BCM_5710_FW_REVISION_VERSION) || +- (fw_ver[3] != BCM_5710_FW_ENGINEERING_VERSION)) { ++ if (fw_ver[0] != bp->fw_major || fw_ver[1] != bp->fw_minor || ++ fw_ver[2] != bp->fw_rev || fw_ver[3] != bp->fw_eng) { + BNX2X_ERR("Bad FW version:%d.%d.%d.%d. Should be %d.%d.%d.%d\n", +- fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3], +- BCM_5710_FW_MAJOR_VERSION, +- BCM_5710_FW_MINOR_VERSION, +- BCM_5710_FW_REVISION_VERSION, +- BCM_5710_FW_ENGINEERING_VERSION); ++ fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3], ++ bp->fw_major, bp->fw_minor, bp->fw_rev, bp->fw_eng); + return -EINVAL; + } + +@@ -13398,34 +13414,51 @@ do { \ + (u8 *)bp->arr, len); \ + } while (0) + +-static int bnx2x_init_firmware(struct bnx2x *bp) ++int bnx2x_init_firmware(struct bnx2x *bp) + { +- const char *fw_file_name; ++ const char *fw_file_name, *fw_file_name_v15; + struct bnx2x_fw_file_hdr *fw_hdr; + int rc; + + if (bp->firmware) + return 0; + +- if (CHIP_IS_E1(bp)) ++ if (CHIP_IS_E1(bp)) { + fw_file_name = FW_FILE_NAME_E1; +- else if (CHIP_IS_E1H(bp)) ++ fw_file_name_v15 = FW_FILE_NAME_E1_V15; ++ } else if (CHIP_IS_E1H(bp)) { + fw_file_name = FW_FILE_NAME_E1H; +- else if (!CHIP_IS_E1x(bp)) ++ fw_file_name_v15 = FW_FILE_NAME_E1H_V15; ++ } else if (!CHIP_IS_E1x(bp)) { + fw_file_name = FW_FILE_NAME_E2; +- else { ++ fw_file_name_v15 = FW_FILE_NAME_E2_V15; ++ } else { + BNX2X_ERR("Unsupported chip revision\n"); + return -EINVAL; + } ++ + BNX2X_DEV_INFO("Loading %s\n", fw_file_name); + + rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev); + if (rc) { +- BNX2X_ERR("Can't load firmware file %s\n", +- fw_file_name); +- goto request_firmware_exit; ++ BNX2X_DEV_INFO("Trying to load older fw %s\n", fw_file_name_v15); ++ ++ /* try to load prev version */ ++ rc = request_firmware(&bp->firmware, fw_file_name_v15, &bp->pdev->dev); ++ ++ if (rc) ++ goto request_firmware_exit; ++ ++ bp->fw_rev = BCM_5710_FW_REVISION_VERSION_V15; ++ } else { ++ bp->fw_cap |= FW_CAP_INVALIDATE_VF_FP_HSI; ++ bp->fw_rev = BCM_5710_FW_REVISION_VERSION; + } + ++ bp->fw_major = BCM_5710_FW_MAJOR_VERSION; ++ bp->fw_minor = BCM_5710_FW_MINOR_VERSION; ++ bp->fw_eng = BCM_5710_FW_ENGINEERING_VERSION; ++ + rc = bnx2x_check_firmware(bp); + if (rc) { + BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name); +@@ -13481,7 +13514,7 @@ request_firmware_exit: + return rc; + } + +-static void bnx2x_release_firmware(struct bnx2x *bp) ++void bnx2x_release_firmware(struct bnx2x *bp) + { + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); +@@ -13998,6 +14031,7 @@ static int bnx2x_init_one(struct pci_dev *pdev, + return 0; + + init_one_freemem: ++ bnx2x_release_firmware(bp); + bnx2x_free_mem_bp(bp); + + init_one_exit: +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +index 6fbf735fca31c..5613957314501 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +@@ -758,9 +758,18 @@ static void bnx2x_vf_igu_reset(struct bnx2x *bp, struct bnx2x_virtf *vf) + + void bnx2x_vf_enable_access(struct bnx2x *bp, u8 abs_vfid) + { ++ u16 abs_fid; ++ ++ abs_fid = FW_VF_HANDLE(abs_vfid); ++ + /* set the VF-PF association in the FW */ +- storm_memset_vf_to_pf(bp, FW_VF_HANDLE(abs_vfid), BP_FUNC(bp)); +- storm_memset_func_en(bp, FW_VF_HANDLE(abs_vfid), 1); ++ storm_memset_vf_to_pf(bp, abs_fid, BP_FUNC(bp)); ++ storm_memset_func_en(bp, abs_fid, 1); ++ ++ /* Invalidate fp_hsi version for vfs */ ++ if (bp->fw_cap & FW_CAP_INVALIDATE_VF_FP_HSI) ++ REG_WR8(bp, BAR_XSTRORM_INTMEM + ++ XSTORM_ETH_FUNCTION_INFO_FP_HSI_VALID_E2_OFFSET(abs_fid), 0); + + /* clear vf errors*/ + bnx2x_vf_semi_clear_err(bp, abs_vfid); +diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile +index c6ef7ec2c1151..2bc2b707d6eee 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/Makefile ++++ b/drivers/net/ethernet/broadcom/bnxt/Makefile +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_BNXT) += bnxt_en.o + +-bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o ++bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o bnxt_coredump.o + bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o + bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 62f84cc91e4d1..ce36ee5a250fb 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -4757,8 +4757,10 @@ static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id) + return rc; + + req->vnic_id = cpu_to_le32(vnic->fw_vnic_id); +- req->num_mc_entries = cpu_to_le32(vnic->mc_list_count); +- req->mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping); ++ if (vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_MCAST) { ++ req->num_mc_entries = cpu_to_le32(vnic->mc_list_count); ++ req->mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping); ++ } + req->mask = cpu_to_le32(vnic->rx_mask); + return hwrm_req_send_silent(bp, req); + } +@@ -8004,6 +8006,12 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) + bp->hwrm_cmd_timeout = le16_to_cpu(resp->def_req_timeout); + if (!bp->hwrm_cmd_timeout) + bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT; ++ bp->hwrm_cmd_max_timeout = le16_to_cpu(resp->max_req_timeout) * 1000; ++ if (!bp->hwrm_cmd_max_timeout) ++ bp->hwrm_cmd_max_timeout = HWRM_CMD_MAX_TIMEOUT; ++ else if (bp->hwrm_cmd_max_timeout > HWRM_CMD_MAX_TIMEOUT) ++ netdev_warn(bp->dev, "Device requests max timeout of %d seconds, may trigger hung task watchdog\n", ++ bp->hwrm_cmd_max_timeout / 1000); + + if (resp->hwrm_intf_maj_8b >= 1) { + bp->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len); +@@ -8609,6 +8617,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) + vnic->uc_filter_count = 1; + + vnic->rx_mask = 0; ++ if (test_bit(BNXT_STATE_HALF_OPEN, &bp->state)) ++ goto skip_rx_mask; ++ + if (bp->dev->flags & IFF_BROADCAST) + vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST; + +@@ -8618,7 +8629,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) + if (bp->dev->flags & IFF_ALLMULTI) { + vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + vnic->mc_list_count = 0; +- } else { ++ } else if (bp->dev->flags & IFF_MULTICAST) { + u32 mask = 0; + + bnxt_mc_list_updated(bp, &mask); +@@ -8629,6 +8640,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) + if (rc) + goto err_out; + ++skip_rx_mask: + rc = bnxt_hwrm_set_coal(bp); + if (rc) + netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n", +@@ -10289,13 +10301,15 @@ int bnxt_half_open_nic(struct bnxt *bp) + goto half_open_err; + } + +- rc = bnxt_alloc_mem(bp, false); ++ rc = bnxt_alloc_mem(bp, true); + if (rc) { + netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); + goto half_open_err; + } +- rc = bnxt_init_nic(bp, false); ++ set_bit(BNXT_STATE_HALF_OPEN, &bp->state); ++ rc = bnxt_init_nic(bp, true); + if (rc) { ++ clear_bit(BNXT_STATE_HALF_OPEN, &bp->state); + netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc); + goto half_open_err; + } +@@ -10303,7 +10317,7 @@ int bnxt_half_open_nic(struct bnxt *bp) + + half_open_err: + bnxt_free_skbs(bp); +- bnxt_free_mem(bp, false); ++ bnxt_free_mem(bp, true); + dev_close(bp->dev); + return rc; + } +@@ -10313,9 +10327,10 @@ half_open_err: + */ + void bnxt_half_close_nic(struct bnxt *bp) + { +- bnxt_hwrm_resource_free(bp, false, false); ++ bnxt_hwrm_resource_free(bp, false, true); + bnxt_free_skbs(bp); +- bnxt_free_mem(bp, false); ++ bnxt_free_mem(bp, true); ++ clear_bit(BNXT_STATE_HALF_OPEN, &bp->state); + } + + static void bnxt_reenable_sriov(struct bnxt *bp) +@@ -10731,7 +10746,7 @@ static void bnxt_set_rx_mode(struct net_device *dev) + if (dev->flags & IFF_ALLMULTI) { + mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + vnic->mc_list_count = 0; +- } else { ++ } else if (dev->flags & IFF_MULTICAST) { + mc_update = bnxt_mc_list_updated(bp, &mask); + } + +@@ -10799,9 +10814,10 @@ skip_uc: + !bnxt_promisc_ok(bp)) + vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); +- if (rc && vnic->mc_list_count) { ++ if (rc && (vnic->rx_mask & CFA_L2_SET_RX_MASK_REQ_MASK_MCAST)) { + netdev_info(bp->dev, "Failed setting MC filters rc: %d, turning on ALL_MCAST mode\n", + rc); ++ vnic->rx_mask &= ~CFA_L2_SET_RX_MASK_REQ_MASK_MCAST; + vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + vnic->mc_list_count = 0; + rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); +@@ -13370,7 +13386,9 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + } + + bnxt_inv_fw_health_reg(bp); +- bnxt_dl_register(bp); ++ rc = bnxt_dl_register(bp); ++ if (rc) ++ goto init_err_dl; + + rc = register_netdev(dev); + if (rc) +@@ -13390,6 +13408,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + + init_err_cleanup: + bnxt_dl_unregister(bp); ++init_err_dl: + bnxt_shutdown_tc(bp); + bnxt_clear_int_mode(bp); + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index 19fe6478e9b4b..ca6fdf03e5865 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -1840,6 +1840,7 @@ struct bnxt { + #define BNXT_STATE_DRV_REGISTERED 7 + #define BNXT_STATE_PCI_CHANNEL_IO_FROZEN 8 + #define BNXT_STATE_NAPI_DISABLED 9 ++#define BNXT_STATE_HALF_OPEN 15 /* For offline ethtool tests */ + + #define BNXT_NO_FW_ACCESS(bp) \ + (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) || \ +@@ -1901,7 +1902,8 @@ struct bnxt { + + u16 hwrm_max_req_len; + u16 hwrm_max_ext_req_len; +- int hwrm_cmd_timeout; ++ unsigned int hwrm_cmd_timeout; ++ unsigned int hwrm_cmd_max_timeout; + struct mutex hwrm_cmd_lock; /* serialize hwrm messages */ + struct hwrm_ver_get_output ver_resp; + #define FW_VER_STR_LEN 32 +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +new file mode 100644 +index 0000000000000..156f76bcea7eb +--- /dev/null ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +@@ -0,0 +1,372 @@ ++/* Broadcom NetXtreme-C/E network driver. ++ * ++ * Copyright (c) 2021 Broadcom Limited ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation. ++ */ ++ ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/pci.h> ++#include "bnxt_hsi.h" ++#include "bnxt.h" ++#include "bnxt_hwrm.h" ++#include "bnxt_coredump.h" ++ ++static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, ++ struct bnxt_hwrm_dbg_dma_info *info) ++{ ++ struct hwrm_dbg_cmn_input *cmn_req = msg; ++ __le16 *seq_ptr = msg + info->seq_off; ++ struct hwrm_dbg_cmn_output *cmn_resp; ++ u16 seq = 0, len, segs_off; ++ dma_addr_t dma_handle; ++ void *dma_buf, *resp; ++ int rc, off = 0; ++ ++ dma_buf = hwrm_req_dma_slice(bp, msg, info->dma_len, &dma_handle); ++ if (!dma_buf) { ++ hwrm_req_drop(bp, msg); ++ return -ENOMEM; ++ } ++ ++ hwrm_req_timeout(bp, msg, bp->hwrm_cmd_max_timeout); ++ cmn_resp = hwrm_req_hold(bp, msg); ++ resp = cmn_resp; ++ ++ segs_off = offsetof(struct hwrm_dbg_coredump_list_output, ++ total_segments); ++ cmn_req->host_dest_addr = cpu_to_le64(dma_handle); ++ cmn_req->host_buf_len = cpu_to_le32(info->dma_len); ++ while (1) { ++ *seq_ptr = cpu_to_le16(seq); ++ rc = hwrm_req_send(bp, msg); ++ if (rc) ++ break; ++ ++ len = le16_to_cpu(*((__le16 *)(resp + info->data_len_off))); ++ if (!seq && ++ cmn_req->req_type == cpu_to_le16(HWRM_DBG_COREDUMP_LIST)) { ++ info->segs = le16_to_cpu(*((__le16 *)(resp + ++ segs_off))); ++ if (!info->segs) { ++ rc = -EIO; ++ break; ++ } ++ ++ info->dest_buf_size = info->segs * ++ sizeof(struct coredump_segment_record); ++ info->dest_buf = kmalloc(info->dest_buf_size, ++ GFP_KERNEL); ++ if (!info->dest_buf) { ++ rc = -ENOMEM; ++ break; ++ } ++ } ++ ++ if (info->dest_buf) { ++ if ((info->seg_start + off + len) <= ++ BNXT_COREDUMP_BUF_LEN(info->buf_len)) { ++ memcpy(info->dest_buf + off, dma_buf, len); ++ } else { ++ rc = -ENOBUFS; ++ break; ++ } ++ } ++ ++ if (cmn_req->req_type == ++ cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE)) ++ info->dest_buf_size += len; ++ ++ if (!(cmn_resp->flags & HWRM_DBG_CMN_FLAGS_MORE)) ++ break; ++ ++ seq++; ++ off += len; ++ } ++ hwrm_req_drop(bp, msg); ++ return rc; ++} ++ ++static int bnxt_hwrm_dbg_coredump_list(struct bnxt *bp, ++ struct bnxt_coredump *coredump) ++{ ++ struct bnxt_hwrm_dbg_dma_info info = {NULL}; ++ struct hwrm_dbg_coredump_list_input *req; ++ int rc; ++ ++ rc = hwrm_req_init(bp, req, HWRM_DBG_COREDUMP_LIST); ++ if (rc) ++ return rc; ++ ++ info.dma_len = COREDUMP_LIST_BUF_LEN; ++ info.seq_off = offsetof(struct hwrm_dbg_coredump_list_input, seq_no); ++ info.data_len_off = offsetof(struct hwrm_dbg_coredump_list_output, ++ data_len); ++ ++ rc = bnxt_hwrm_dbg_dma_data(bp, req, &info); ++ if (!rc) { ++ coredump->data = info.dest_buf; ++ coredump->data_size = info.dest_buf_size; ++ coredump->total_segs = info.segs; ++ } ++ return rc; ++} ++ ++static int bnxt_hwrm_dbg_coredump_initiate(struct bnxt *bp, u16 component_id, ++ u16 segment_id) ++{ ++ struct hwrm_dbg_coredump_initiate_input *req; ++ int rc; ++ ++ rc = hwrm_req_init(bp, req, HWRM_DBG_COREDUMP_INITIATE); ++ if (rc) ++ return rc; ++ ++ hwrm_req_timeout(bp, req, bp->hwrm_cmd_max_timeout); ++ req->component_id = cpu_to_le16(component_id); ++ req->segment_id = cpu_to_le16(segment_id); ++ ++ return hwrm_req_send(bp, req); ++} ++ ++static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id, ++ u16 segment_id, u32 *seg_len, ++ void *buf, u32 buf_len, u32 offset) ++{ ++ struct hwrm_dbg_coredump_retrieve_input *req; ++ struct bnxt_hwrm_dbg_dma_info info = {NULL}; ++ int rc; ++ ++ rc = hwrm_req_init(bp, req, HWRM_DBG_COREDUMP_RETRIEVE); ++ if (rc) ++ return rc; ++ ++ req->component_id = cpu_to_le16(component_id); ++ req->segment_id = cpu_to_le16(segment_id); ++ ++ info.dma_len = COREDUMP_RETRIEVE_BUF_LEN; ++ info.seq_off = offsetof(struct hwrm_dbg_coredump_retrieve_input, ++ seq_no); ++ info.data_len_off = offsetof(struct hwrm_dbg_coredump_retrieve_output, ++ data_len); ++ if (buf) { ++ info.dest_buf = buf + offset; ++ info.buf_len = buf_len; ++ info.seg_start = offset; ++ } ++ ++ rc = bnxt_hwrm_dbg_dma_data(bp, req, &info); ++ if (!rc) ++ *seg_len = info.dest_buf_size; ++ ++ return rc; ++} ++ ++static void ++bnxt_fill_coredump_seg_hdr(struct bnxt *bp, ++ struct bnxt_coredump_segment_hdr *seg_hdr, ++ struct coredump_segment_record *seg_rec, u32 seg_len, ++ int status, u32 duration, u32 instance) ++{ ++ memset(seg_hdr, 0, sizeof(*seg_hdr)); ++ memcpy(seg_hdr->signature, "sEgM", 4); ++ if (seg_rec) { ++ seg_hdr->component_id = (__force __le32)seg_rec->component_id; ++ seg_hdr->segment_id = (__force __le32)seg_rec->segment_id; ++ seg_hdr->low_version = seg_rec->version_low; ++ seg_hdr->high_version = seg_rec->version_hi; ++ } else { ++ /* For hwrm_ver_get response Component id = 2 ++ * and Segment id = 0 ++ */ ++ seg_hdr->component_id = cpu_to_le32(2); ++ seg_hdr->segment_id = 0; ++ } ++ seg_hdr->function_id = cpu_to_le16(bp->pdev->devfn); ++ seg_hdr->length = cpu_to_le32(seg_len); ++ seg_hdr->status = cpu_to_le32(status); ++ seg_hdr->duration = cpu_to_le32(duration); ++ seg_hdr->data_offset = cpu_to_le32(sizeof(*seg_hdr)); ++ seg_hdr->instance = cpu_to_le32(instance); ++} ++ ++static void ++bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record, ++ time64_t start, s16 start_utc, u16 total_segs, ++ int status) ++{ ++ time64_t end = ktime_get_real_seconds(); ++ u32 os_ver_major = 0, os_ver_minor = 0; ++ struct tm tm; ++ ++ time64_to_tm(start, 0, &tm); ++ memset(record, 0, sizeof(*record)); ++ memcpy(record->signature, "cOrE", 4); ++ record->flags = 0; ++ record->low_version = 0; ++ record->high_version = 1; ++ record->asic_state = 0; ++ strscpy(record->system_name, utsname()->nodename, ++ sizeof(record->system_name)); ++ record->year = cpu_to_le16(tm.tm_year + 1900); ++ record->month = cpu_to_le16(tm.tm_mon + 1); ++ record->day = cpu_to_le16(tm.tm_mday); ++ record->hour = cpu_to_le16(tm.tm_hour); ++ record->minute = cpu_to_le16(tm.tm_min); ++ record->second = cpu_to_le16(tm.tm_sec); ++ record->utc_bias = cpu_to_le16(start_utc); ++ strcpy(record->commandline, "ethtool -w"); ++ record->total_segments = cpu_to_le32(total_segs); ++ ++ if (sscanf(utsname()->release, "%u.%u", &os_ver_major, &os_ver_minor) != 2) ++ netdev_warn(bp->dev, "Unknown OS release in coredump\n"); ++ record->os_ver_major = cpu_to_le32(os_ver_major); ++ record->os_ver_minor = cpu_to_le32(os_ver_minor); ++ ++ strscpy(record->os_name, utsname()->sysname, sizeof(record->os_name)); ++ time64_to_tm(end, 0, &tm); ++ record->end_year = cpu_to_le16(tm.tm_year + 1900); ++ record->end_month = cpu_to_le16(tm.tm_mon + 1); ++ record->end_day = cpu_to_le16(tm.tm_mday); ++ record->end_hour = cpu_to_le16(tm.tm_hour); ++ record->end_minute = cpu_to_le16(tm.tm_min); ++ record->end_second = cpu_to_le16(tm.tm_sec); ++ record->end_utc_bias = cpu_to_le16(sys_tz.tz_minuteswest * 60); ++ record->asic_id1 = cpu_to_le32(bp->chip_num << 16 | ++ bp->ver_resp.chip_rev << 8 | ++ bp->ver_resp.chip_metal); ++ record->asic_id2 = 0; ++ record->coredump_status = cpu_to_le32(status); ++ record->ioctl_low_version = 0; ++ record->ioctl_high_version = 0; ++} ++ ++static int __bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len) ++{ ++ u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output); ++ u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0; ++ struct coredump_segment_record *seg_record = NULL; ++ struct bnxt_coredump_segment_hdr seg_hdr; ++ struct bnxt_coredump coredump = {NULL}; ++ time64_t start_time; ++ u16 start_utc; ++ int rc = 0, i; ++ ++ if (buf) ++ buf_len = *dump_len; ++ ++ start_time = ktime_get_real_seconds(); ++ start_utc = sys_tz.tz_minuteswest * 60; ++ seg_hdr_len = sizeof(seg_hdr); ++ ++ /* First segment should be hwrm_ver_get response */ ++ *dump_len = seg_hdr_len + ver_get_resp_len; ++ if (buf) { ++ bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, ver_get_resp_len, ++ 0, 0, 0); ++ memcpy(buf + offset, &seg_hdr, seg_hdr_len); ++ offset += seg_hdr_len; ++ memcpy(buf + offset, &bp->ver_resp, ver_get_resp_len); ++ offset += ver_get_resp_len; ++ } ++ ++ rc = bnxt_hwrm_dbg_coredump_list(bp, &coredump); ++ if (rc) { ++ netdev_err(bp->dev, "Failed to get coredump segment list\n"); ++ goto err; ++ } ++ ++ *dump_len += seg_hdr_len * coredump.total_segs; ++ ++ seg_record = (struct coredump_segment_record *)coredump.data; ++ seg_record_len = sizeof(*seg_record); ++ ++ for (i = 0; i < coredump.total_segs; i++) { ++ u16 comp_id = le16_to_cpu(seg_record->component_id); ++ u16 seg_id = le16_to_cpu(seg_record->segment_id); ++ u32 duration = 0, seg_len = 0; ++ unsigned long start, end; ++ ++ if (buf && ((offset + seg_hdr_len) > ++ BNXT_COREDUMP_BUF_LEN(buf_len))) { ++ rc = -ENOBUFS; ++ goto err; ++ } ++ ++ start = jiffies; ++ ++ rc = bnxt_hwrm_dbg_coredump_initiate(bp, comp_id, seg_id); ++ if (rc) { ++ netdev_err(bp->dev, ++ "Failed to initiate coredump for seg = %d\n", ++ seg_record->segment_id); ++ goto next_seg; ++ } ++ ++ /* Write segment data into the buffer */ ++ rc = bnxt_hwrm_dbg_coredump_retrieve(bp, comp_id, seg_id, ++ &seg_len, buf, buf_len, ++ offset + seg_hdr_len); ++ if (rc && rc == -ENOBUFS) ++ goto err; ++ else if (rc) ++ netdev_err(bp->dev, ++ "Failed to retrieve coredump for seg = %d\n", ++ seg_record->segment_id); ++ ++next_seg: ++ end = jiffies; ++ duration = jiffies_to_msecs(end - start); ++ bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, seg_record, seg_len, ++ rc, duration, 0); ++ ++ if (buf) { ++ /* Write segment header into the buffer */ ++ memcpy(buf + offset, &seg_hdr, seg_hdr_len); ++ offset += seg_hdr_len + seg_len; ++ } ++ ++ *dump_len += seg_len; ++ seg_record = ++ (struct coredump_segment_record *)((u8 *)seg_record + ++ seg_record_len); ++ } ++ ++err: ++ if (buf) ++ bnxt_fill_coredump_record(bp, buf + offset, start_time, ++ start_utc, coredump.total_segs + 1, ++ rc); ++ kfree(coredump.data); ++ *dump_len += sizeof(struct bnxt_coredump_record); ++ if (rc == -ENOBUFS) ++ netdev_err(bp->dev, "Firmware returned large coredump buffer\n"); ++ return rc; ++} ++ ++int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len) ++{ ++ if (dump_type == BNXT_DUMP_CRASH) { ++#ifdef CONFIG_TEE_BNXT_FW ++ return tee_bnxt_copy_coredump(buf, 0, *dump_len); ++#else ++ return -EOPNOTSUPP; ++#endif ++ } else { ++ return __bnxt_get_coredump(bp, buf, dump_len); ++ } ++} ++ ++u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type) ++{ ++ u32 len = 0; ++ ++ if (dump_type == BNXT_DUMP_CRASH) ++ len = BNXT_CRASH_DUMP_LEN; ++ else ++ __bnxt_get_coredump(bp, NULL, &len); ++ return len; ++} +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h +index 09c22f8fe3991..b1a1b2fffb194 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.h +@@ -10,6 +10,10 @@ + #ifndef BNXT_COREDUMP_H + #define BNXT_COREDUMP_H + ++#include <linux/utsname.h> ++#include <linux/time.h> ++#include <linux/rtc.h> ++ + struct bnxt_coredump_segment_hdr { + __u8 signature[4]; + __le32 component_id; +@@ -63,4 +67,51 @@ struct bnxt_coredump_record { + __u8 ioctl_high_version; + __le16 rsvd3[313]; + }; ++ ++#define BNXT_CRASH_DUMP_LEN (8 << 20) ++ ++#define COREDUMP_LIST_BUF_LEN 2048 ++#define COREDUMP_RETRIEVE_BUF_LEN 4096 ++ ++struct bnxt_coredump { ++ void *data; ++ int data_size; ++ u16 total_segs; ++}; ++ ++#define BNXT_COREDUMP_BUF_LEN(len) ((len) - sizeof(struct bnxt_coredump_record)) ++ ++struct bnxt_hwrm_dbg_dma_info { ++ void *dest_buf; ++ int dest_buf_size; ++ u16 dma_len; ++ u16 seq_off; ++ u16 data_len_off; ++ u16 segs; ++ u32 seg_start; ++ u32 buf_len; ++}; ++ ++struct hwrm_dbg_cmn_input { ++ __le16 req_type; ++ __le16 cmpl_ring; ++ __le16 seq_id; ++ __le16 target_id; ++ __le64 resp_addr; ++ __le64 host_dest_addr; ++ __le32 host_buf_len; ++}; ++ ++struct hwrm_dbg_cmn_output { ++ __le16 error_code; ++ __le16 req_type; ++ __le16 seq_id; ++ __le16 resp_len; ++ u8 flags; ++ #define HWRM_DBG_CMN_FLAGS_MORE 1 ++}; ++ ++int bnxt_get_coredump(struct bnxt *bp, u16 dump_type, void *buf, u32 *dump_len); ++u32 bnxt_get_coredump_length(struct bnxt *bp, u16 dump_type); ++ + #endif +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +index 9576547df4aba..2a80882971e3d 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +@@ -134,7 +134,7 @@ void bnxt_dl_fw_reporters_create(struct bnxt *bp) + { + struct bnxt_fw_health *health = bp->fw_health; + +- if (!bp->dl || !health) ++ if (!health) + return; + + if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter) +@@ -188,7 +188,7 @@ void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all) + { + struct bnxt_fw_health *health = bp->fw_health; + +- if (!bp->dl || !health) ++ if (!health) + return; + + if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) && +@@ -781,6 +781,7 @@ int bnxt_dl_register(struct bnxt *bp) + { + const struct devlink_ops *devlink_ops; + struct devlink_port_attrs attrs = {}; ++ struct bnxt_dl *bp_dl; + struct devlink *dl; + int rc; + +@@ -795,7 +796,9 @@ int bnxt_dl_register(struct bnxt *bp) + return -ENOMEM; + } + +- bnxt_link_bp_to_dl(bp, dl); ++ bp->dl = dl; ++ bp_dl = devlink_priv(dl); ++ bp_dl->bp = bp; + + /* Add switchdev eswitch mode setting, if SRIOV supported */ + if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) && +@@ -833,7 +836,6 @@ err_dl_port_unreg: + err_dl_unreg: + devlink_unregister(dl); + err_dl_free: +- bnxt_link_bp_to_dl(bp, NULL); + devlink_free(dl); + return rc; + } +@@ -842,9 +844,6 @@ void bnxt_dl_unregister(struct bnxt *bp) + { + struct devlink *dl = bp->dl; + +- if (!dl) +- return; +- + if (BNXT_PF(bp)) { + bnxt_dl_params_unregister(bp); + devlink_port_unregister(&bp->dl_port); +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h +index d889f240da2b2..406dc655a5fc9 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h +@@ -20,19 +20,6 @@ static inline struct bnxt *bnxt_get_bp_from_dl(struct devlink *dl) + return ((struct bnxt_dl *)devlink_priv(dl))->bp; + } + +-/* To clear devlink pointer from bp, pass NULL dl */ +-static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl) +-{ +- bp->dl = dl; +- +- /* add a back pointer in dl to bp */ +- if (dl) { +- struct bnxt_dl *bp_dl = devlink_priv(dl); +- +- bp_dl->bp = bp; +- } +-} +- + #define NVM_OFF_MSIX_VEC_PER_PF_MAX 108 + #define NVM_OFF_MSIX_VEC_PER_PF_MIN 114 + #define NVM_OFF_IGNORE_ARI 164 +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +index 7260910e75fb2..af7de9ee66cf2 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +@@ -25,15 +25,13 @@ + #include "bnxt_hsi.h" + #include "bnxt.h" + #include "bnxt_hwrm.h" ++#include "bnxt_ulp.h" + #include "bnxt_xdp.h" + #include "bnxt_ptp.h" + #include "bnxt_ethtool.h" + #include "bnxt_nvm_defs.h" /* NVRAM content constant and structure defs */ + #include "bnxt_fw_hdr.h" /* Firmware hdr constant and structure defs */ + #include "bnxt_coredump.h" +-#define FLASH_NVRAM_TIMEOUT ((HWRM_CMD_TIMEOUT) * 100) +-#define FLASH_PACKAGE_TIMEOUT ((HWRM_CMD_TIMEOUT) * 200) +-#define INSTALL_PACKAGE_TIMEOUT ((HWRM_CMD_TIMEOUT) * 200) + + static u32 bnxt_get_msglevel(struct net_device *dev) + { +@@ -1945,6 +1943,9 @@ static int bnxt_get_fecparam(struct net_device *dev, + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE: + fec->active_fec |= ETHTOOL_FEC_LLRS; + break; ++ case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_NONE_ACTIVE: ++ fec->active_fec |= ETHTOOL_FEC_OFF; ++ break; + } + return 0; + } +@@ -2167,7 +2168,7 @@ static int bnxt_flash_nvram(struct net_device *dev, u16 dir_type, + req->host_src_addr = cpu_to_le64(dma_handle); + } + +- hwrm_req_timeout(bp, req, FLASH_NVRAM_TIMEOUT); ++ hwrm_req_timeout(bp, req, bp->hwrm_cmd_max_timeout); + req->dir_type = cpu_to_le16(dir_type); + req->dir_ordinal = cpu_to_le16(dir_ordinal); + req->dir_ext = cpu_to_le16(dir_ext); +@@ -2508,8 +2509,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware + return rc; + } + +- hwrm_req_timeout(bp, modify, FLASH_PACKAGE_TIMEOUT); +- hwrm_req_timeout(bp, install, INSTALL_PACKAGE_TIMEOUT); ++ hwrm_req_timeout(bp, modify, bp->hwrm_cmd_max_timeout); ++ hwrm_req_timeout(bp, install, bp->hwrm_cmd_max_timeout); + + hwrm_req_hold(bp, modify); + modify->host_src_addr = cpu_to_le64(dma_handle); +@@ -3408,7 +3409,7 @@ static int bnxt_run_loopback(struct bnxt *bp) + if (!skb) + return -ENOMEM; + data = skb_put(skb, pkt_size); +- eth_broadcast_addr(data); ++ ether_addr_copy(&data[i], bp->dev->dev_addr); + i += ETH_ALEN; + ether_addr_copy(&data[i], bp->dev->dev_addr); + i += ETH_ALEN; +@@ -3502,9 +3503,12 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest, + if (!offline) { + bnxt_run_fw_tests(bp, test_mask, &test_results); + } else { +- rc = bnxt_close_nic(bp, false, false); +- if (rc) ++ bnxt_ulp_stop(bp); ++ rc = bnxt_close_nic(bp, true, false); ++ if (rc) { ++ bnxt_ulp_start(bp, rc); + return; ++ } + bnxt_run_fw_tests(bp, test_mask, &test_results); + + buf[BNXT_MACLPBK_TEST_IDX] = 1; +@@ -3514,6 +3518,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest, + if (rc) { + bnxt_hwrm_mac_loopback(bp, false); + etest->flags |= ETH_TEST_FL_FAILED; ++ bnxt_ulp_start(bp, rc); + return; + } + if (bnxt_run_loopback(bp)) +@@ -3539,7 +3544,8 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest, + } + bnxt_hwrm_phy_loopback(bp, false, false); + bnxt_half_close_nic(bp); +- rc = bnxt_open_nic(bp, false, true); ++ rc = bnxt_open_nic(bp, true, true); ++ bnxt_ulp_start(bp, rc); + } + if (rc || bnxt_test_irq(bp)) { + buf[BNXT_IRQ_TEST_IDX] = 1; +@@ -3609,337 +3615,6 @@ static int bnxt_reset(struct net_device *dev, u32 *flags) + return 0; + } + +-static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, +- struct bnxt_hwrm_dbg_dma_info *info) +-{ +- struct hwrm_dbg_cmn_input *cmn_req = msg; +- __le16 *seq_ptr = msg + info->seq_off; +- struct hwrm_dbg_cmn_output *cmn_resp; +- u16 seq = 0, len, segs_off; +- dma_addr_t dma_handle; +- void *dma_buf, *resp; +- int rc, off = 0; +- +- dma_buf = hwrm_req_dma_slice(bp, msg, info->dma_len, &dma_handle); +- if (!dma_buf) { +- hwrm_req_drop(bp, msg); +- return -ENOMEM; +- } +- +- hwrm_req_timeout(bp, msg, HWRM_COREDUMP_TIMEOUT); +- cmn_resp = hwrm_req_hold(bp, msg); +- resp = cmn_resp; +- +- segs_off = offsetof(struct hwrm_dbg_coredump_list_output, +- total_segments); +- cmn_req->host_dest_addr = cpu_to_le64(dma_handle); +- cmn_req->host_buf_len = cpu_to_le32(info->dma_len); +- while (1) { +- *seq_ptr = cpu_to_le16(seq); +- rc = hwrm_req_send(bp, msg); +- if (rc) +- break; +- +- len = le16_to_cpu(*((__le16 *)(resp + info->data_len_off))); +- if (!seq && +- cmn_req->req_type == cpu_to_le16(HWRM_DBG_COREDUMP_LIST)) { +- info->segs = le16_to_cpu(*((__le16 *)(resp + +- segs_off))); +- if (!info->segs) { +- rc = -EIO; +- break; +- } +- +- info->dest_buf_size = info->segs * +- sizeof(struct coredump_segment_record); +- info->dest_buf = kmalloc(info->dest_buf_size, +- GFP_KERNEL); +- if (!info->dest_buf) { +- rc = -ENOMEM; +- break; +- } +- } +- +- if (info->dest_buf) { +- if ((info->seg_start + off + len) <= +- BNXT_COREDUMP_BUF_LEN(info->buf_len)) { +- memcpy(info->dest_buf + off, dma_buf, len); +- } else { +- rc = -ENOBUFS; +- break; +- } +- } +- +- if (cmn_req->req_type == +- cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE)) +- info->dest_buf_size += len; +- +- if (!(cmn_resp->flags & HWRM_DBG_CMN_FLAGS_MORE)) +- break; +- +- seq++; +- off += len; +- } +- hwrm_req_drop(bp, msg); +- return rc; +-} +- +-static int bnxt_hwrm_dbg_coredump_list(struct bnxt *bp, +- struct bnxt_coredump *coredump) +-{ +- struct bnxt_hwrm_dbg_dma_info info = {NULL}; +- struct hwrm_dbg_coredump_list_input *req; +- int rc; +- +- rc = hwrm_req_init(bp, req, HWRM_DBG_COREDUMP_LIST); +- if (rc) +- return rc; +- +- info.dma_len = COREDUMP_LIST_BUF_LEN; +- info.seq_off = offsetof(struct hwrm_dbg_coredump_list_input, seq_no); +- info.data_len_off = offsetof(struct hwrm_dbg_coredump_list_output, +- data_len); +- +- rc = bnxt_hwrm_dbg_dma_data(bp, req, &info); +- if (!rc) { +- coredump->data = info.dest_buf; +- coredump->data_size = info.dest_buf_size; +- coredump->total_segs = info.segs; +- } +- return rc; +-} +- +-static int bnxt_hwrm_dbg_coredump_initiate(struct bnxt *bp, u16 component_id, +- u16 segment_id) +-{ +- struct hwrm_dbg_coredump_initiate_input *req; +- int rc; +- +- rc = hwrm_req_init(bp, req, HWRM_DBG_COREDUMP_INITIATE); +- if (rc) +- return rc; +- +- hwrm_req_timeout(bp, req, HWRM_COREDUMP_TIMEOUT); +- req->component_id = cpu_to_le16(component_id); +- req->segment_id = cpu_to_le16(segment_id); +- +- return hwrm_req_send(bp, req); +-} +- +-static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id, +- u16 segment_id, u32 *seg_len, +- void *buf, u32 buf_len, u32 offset) +-{ +- struct hwrm_dbg_coredump_retrieve_input *req; +- struct bnxt_hwrm_dbg_dma_info info = {NULL}; +- int rc; +- +- rc = hwrm_req_init(bp, req, HWRM_DBG_COREDUMP_RETRIEVE); +- if (rc) +- return rc; +- +- req->component_id = cpu_to_le16(component_id); +- req->segment_id = cpu_to_le16(segment_id); +- +- info.dma_len = COREDUMP_RETRIEVE_BUF_LEN; +- info.seq_off = offsetof(struct hwrm_dbg_coredump_retrieve_input, +- seq_no); +- info.data_len_off = offsetof(struct hwrm_dbg_coredump_retrieve_output, +- data_len); +- if (buf) { +- info.dest_buf = buf + offset; +- info.buf_len = buf_len; +- info.seg_start = offset; +- } +- +- rc = bnxt_hwrm_dbg_dma_data(bp, req, &info); +- if (!rc) +- *seg_len = info.dest_buf_size; +- +- return rc; +-} +- +-static void +-bnxt_fill_coredump_seg_hdr(struct bnxt *bp, +- struct bnxt_coredump_segment_hdr *seg_hdr, +- struct coredump_segment_record *seg_rec, u32 seg_len, +- int status, u32 duration, u32 instance) +-{ +- memset(seg_hdr, 0, sizeof(*seg_hdr)); +- memcpy(seg_hdr->signature, "sEgM", 4); +- if (seg_rec) { +- seg_hdr->component_id = (__force __le32)seg_rec->component_id; +- seg_hdr->segment_id = (__force __le32)seg_rec->segment_id; +- seg_hdr->low_version = seg_rec->version_low; +- seg_hdr->high_version = seg_rec->version_hi; +- } else { +- /* For hwrm_ver_get response Component id = 2 +- * and Segment id = 0 +- */ +- seg_hdr->component_id = cpu_to_le32(2); +- seg_hdr->segment_id = 0; +- } +- seg_hdr->function_id = cpu_to_le16(bp->pdev->devfn); +- seg_hdr->length = cpu_to_le32(seg_len); +- seg_hdr->status = cpu_to_le32(status); +- seg_hdr->duration = cpu_to_le32(duration); +- seg_hdr->data_offset = cpu_to_le32(sizeof(*seg_hdr)); +- seg_hdr->instance = cpu_to_le32(instance); +-} +- +-static void +-bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record, +- time64_t start, s16 start_utc, u16 total_segs, +- int status) +-{ +- time64_t end = ktime_get_real_seconds(); +- u32 os_ver_major = 0, os_ver_minor = 0; +- struct tm tm; +- +- time64_to_tm(start, 0, &tm); +- memset(record, 0, sizeof(*record)); +- memcpy(record->signature, "cOrE", 4); +- record->flags = 0; +- record->low_version = 0; +- record->high_version = 1; +- record->asic_state = 0; +- strlcpy(record->system_name, utsname()->nodename, +- sizeof(record->system_name)); +- record->year = cpu_to_le16(tm.tm_year + 1900); +- record->month = cpu_to_le16(tm.tm_mon + 1); +- record->day = cpu_to_le16(tm.tm_mday); +- record->hour = cpu_to_le16(tm.tm_hour); +- record->minute = cpu_to_le16(tm.tm_min); +- record->second = cpu_to_le16(tm.tm_sec); +- record->utc_bias = cpu_to_le16(start_utc); +- strcpy(record->commandline, "ethtool -w"); +- record->total_segments = cpu_to_le32(total_segs); +- +- sscanf(utsname()->release, "%u.%u", &os_ver_major, &os_ver_minor); +- record->os_ver_major = cpu_to_le32(os_ver_major); +- record->os_ver_minor = cpu_to_le32(os_ver_minor); +- +- strlcpy(record->os_name, utsname()->sysname, 32); +- time64_to_tm(end, 0, &tm); +- record->end_year = cpu_to_le16(tm.tm_year + 1900); +- record->end_month = cpu_to_le16(tm.tm_mon + 1); +- record->end_day = cpu_to_le16(tm.tm_mday); +- record->end_hour = cpu_to_le16(tm.tm_hour); +- record->end_minute = cpu_to_le16(tm.tm_min); +- record->end_second = cpu_to_le16(tm.tm_sec); +- record->end_utc_bias = cpu_to_le16(sys_tz.tz_minuteswest * 60); +- record->asic_id1 = cpu_to_le32(bp->chip_num << 16 | +- bp->ver_resp.chip_rev << 8 | +- bp->ver_resp.chip_metal); +- record->asic_id2 = 0; +- record->coredump_status = cpu_to_le32(status); +- record->ioctl_low_version = 0; +- record->ioctl_high_version = 0; +-} +- +-static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len) +-{ +- u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output); +- u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0; +- struct coredump_segment_record *seg_record = NULL; +- struct bnxt_coredump_segment_hdr seg_hdr; +- struct bnxt_coredump coredump = {NULL}; +- time64_t start_time; +- u16 start_utc; +- int rc = 0, i; +- +- if (buf) +- buf_len = *dump_len; +- +- start_time = ktime_get_real_seconds(); +- start_utc = sys_tz.tz_minuteswest * 60; +- seg_hdr_len = sizeof(seg_hdr); +- +- /* First segment should be hwrm_ver_get response */ +- *dump_len = seg_hdr_len + ver_get_resp_len; +- if (buf) { +- bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, ver_get_resp_len, +- 0, 0, 0); +- memcpy(buf + offset, &seg_hdr, seg_hdr_len); +- offset += seg_hdr_len; +- memcpy(buf + offset, &bp->ver_resp, ver_get_resp_len); +- offset += ver_get_resp_len; +- } +- +- rc = bnxt_hwrm_dbg_coredump_list(bp, &coredump); +- if (rc) { +- netdev_err(bp->dev, "Failed to get coredump segment list\n"); +- goto err; +- } +- +- *dump_len += seg_hdr_len * coredump.total_segs; +- +- seg_record = (struct coredump_segment_record *)coredump.data; +- seg_record_len = sizeof(*seg_record); +- +- for (i = 0; i < coredump.total_segs; i++) { +- u16 comp_id = le16_to_cpu(seg_record->component_id); +- u16 seg_id = le16_to_cpu(seg_record->segment_id); +- u32 duration = 0, seg_len = 0; +- unsigned long start, end; +- +- if (buf && ((offset + seg_hdr_len) > +- BNXT_COREDUMP_BUF_LEN(buf_len))) { +- rc = -ENOBUFS; +- goto err; +- } +- +- start = jiffies; +- +- rc = bnxt_hwrm_dbg_coredump_initiate(bp, comp_id, seg_id); +- if (rc) { +- netdev_err(bp->dev, +- "Failed to initiate coredump for seg = %d\n", +- seg_record->segment_id); +- goto next_seg; +- } +- +- /* Write segment data into the buffer */ +- rc = bnxt_hwrm_dbg_coredump_retrieve(bp, comp_id, seg_id, +- &seg_len, buf, buf_len, +- offset + seg_hdr_len); +- if (rc && rc == -ENOBUFS) +- goto err; +- else if (rc) +- netdev_err(bp->dev, +- "Failed to retrieve coredump for seg = %d\n", +- seg_record->segment_id); +- +-next_seg: +- end = jiffies; +- duration = jiffies_to_msecs(end - start); +- bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, seg_record, seg_len, +- rc, duration, 0); +- +- if (buf) { +- /* Write segment header into the buffer */ +- memcpy(buf + offset, &seg_hdr, seg_hdr_len); +- offset += seg_hdr_len + seg_len; +- } +- +- *dump_len += seg_len; +- seg_record = +- (struct coredump_segment_record *)((u8 *)seg_record + +- seg_record_len); +- } +- +-err: +- if (buf) +- bnxt_fill_coredump_record(bp, buf + offset, start_time, +- start_utc, coredump.total_segs + 1, +- rc); +- kfree(coredump.data); +- *dump_len += sizeof(struct bnxt_coredump_record); +- if (rc == -ENOBUFS) +- netdev_err(bp->dev, "Firmware returned large coredump buffer\n"); +- return rc; +-} +- + static int bnxt_set_dump(struct net_device *dev, struct ethtool_dump *dump) + { + struct bnxt *bp = netdev_priv(dev); +@@ -3971,10 +3646,7 @@ static int bnxt_get_dump_flag(struct net_device *dev, struct ethtool_dump *dump) + bp->ver_resp.hwrm_fw_rsvd_8b; + + dump->flag = bp->dump_flag; +- if (bp->dump_flag == BNXT_DUMP_CRASH) +- dump->len = BNXT_CRASH_DUMP_LEN; +- else +- bnxt_get_coredump(bp, NULL, &dump->len); ++ dump->len = bnxt_get_coredump_length(bp, bp->dump_flag); + return 0; + } + +@@ -3989,15 +3661,7 @@ static int bnxt_get_dump_data(struct net_device *dev, struct ethtool_dump *dump, + memset(buf, 0, dump->len); + + dump->flag = bp->dump_flag; +- if (dump->flag == BNXT_DUMP_CRASH) { +-#ifdef CONFIG_TEE_BNXT_FW +- return tee_bnxt_copy_coredump(buf, 0, dump->len); +-#endif +- } else { +- return bnxt_get_coredump(bp, buf, &dump->len); +- } +- +- return 0; ++ return bnxt_get_coredump(bp, dump->flag, buf, &dump->len); + } + + static int bnxt_get_ts_info(struct net_device *dev, +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h +index 0a57cb6a4a4bf..11a719f98defd 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h +@@ -22,49 +22,6 @@ struct bnxt_led_cfg { + u8 rsvd; + }; + +-#define COREDUMP_LIST_BUF_LEN 2048 +-#define COREDUMP_RETRIEVE_BUF_LEN 4096 +- +-struct bnxt_coredump { +- void *data; +- int data_size; +- u16 total_segs; +-}; +- +-#define BNXT_COREDUMP_BUF_LEN(len) ((len) - sizeof(struct bnxt_coredump_record)) +- +-struct bnxt_hwrm_dbg_dma_info { +- void *dest_buf; +- int dest_buf_size; +- u16 dma_len; +- u16 seq_off; +- u16 data_len_off; +- u16 segs; +- u32 seg_start; +- u32 buf_len; +-}; +- +-struct hwrm_dbg_cmn_input { +- __le16 req_type; +- __le16 cmpl_ring; +- __le16 seq_id; +- __le16 target_id; +- __le64 resp_addr; +- __le64 host_dest_addr; +- __le32 host_buf_len; +-}; +- +-struct hwrm_dbg_cmn_output { +- __le16 error_code; +- __le16 req_type; +- __le16 seq_id; +- __le16 resp_len; +- u8 flags; +- #define HWRM_DBG_CMN_FLAGS_MORE 1 +-}; +- +-#define BNXT_CRASH_DUMP_LEN (8 << 20) +- + #define BNXT_LED_DFLT_ENA \ + (PORT_LED_CFG_REQ_ENABLES_LED0_ID | \ + PORT_LED_CFG_REQ_ENABLES_LED0_STATE | \ +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c +index bb7327b82d0b2..3a0eeb3737767 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c +@@ -496,7 +496,7 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx) + } + + /* Limit timeout to an upper limit */ +- timeout = min_t(uint, ctx->timeout, HWRM_CMD_MAX_TIMEOUT); ++ timeout = min(ctx->timeout, bp->hwrm_cmd_max_timeout ?: HWRM_CMD_MAX_TIMEOUT); + /* convert timeout to usec */ + timeout *= 1000; + +@@ -595,18 +595,24 @@ timeout_abort: + + /* Last byte of resp contains valid bit */ + valid = ((u8 *)ctx->resp) + len - 1; +- for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; j++) { ++ for (j = 0; j < HWRM_VALID_BIT_DELAY_USEC; ) { + /* make sure we read from updated DMA memory */ + dma_rmb(); + if (*valid) + break; +- usleep_range(1, 5); ++ if (j < 10) { ++ udelay(1); ++ j++; ++ } else { ++ usleep_range(20, 30); ++ j += 20; ++ } + } + + if (j >= HWRM_VALID_BIT_DELAY_USEC) { + if (!(ctx->flags & BNXT_HWRM_CTX_SILENT)) + netdev_err(bp->dev, "Error (timeout: %u) msg {0x%x 0x%x} len:%d v:%d\n", +- hwrm_total_timeout(i), ++ hwrm_total_timeout(i) + j, + le16_to_cpu(ctx->req->req_type), + le16_to_cpu(ctx->req->seq_id), len, + *valid); +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h +index 4d17f0d5363bb..380ef69afb51b 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.h +@@ -58,11 +58,10 @@ void hwrm_update_token(struct bnxt *bp, u16 seq, enum bnxt_hwrm_wait_state s); + + #define BNXT_HWRM_MAX_REQ_LEN (bp->hwrm_max_req_len) + #define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input) +-#define HWRM_CMD_MAX_TIMEOUT 40000 ++#define HWRM_CMD_MAX_TIMEOUT 40000U + #define SHORT_HWRM_CMD_TIMEOUT 20 + #define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout) + #define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4) +-#define HWRM_COREDUMP_TIMEOUT ((HWRM_CMD_TIMEOUT) * 12) + #define BNXT_HWRM_TARGET 0xffff + #define BNXT_HWRM_NO_CMPL_RING -1 + #define BNXT_HWRM_REQ_MAX_SIZE 128 +@@ -95,7 +94,7 @@ static inline unsigned int hwrm_total_timeout(unsigned int n) + } + + +-#define HWRM_VALID_BIT_DELAY_USEC 150 ++#define HWRM_VALID_BIT_DELAY_USEC 50000 + + static inline bool bnxt_cfa_hwrm_message(u16 req_type) + { +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +index e6a4a768b10b2..1471b6130a2b9 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +@@ -1868,7 +1868,7 @@ static int bnxt_tc_setup_indr_block_cb(enum tc_setup_type type, + struct flow_cls_offload *flower = type_data; + struct bnxt *bp = priv->bp; + +- if (flower->common.chain_index) ++ if (!tc_cls_can_offload_and_chain0(bp->dev, type_data)) + return -EOPNOTSUPP; + + switch (type) { +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +index 23c7595d2a1d3..9a67e24f46b27 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -3966,10 +3966,12 @@ static int bcmgenet_probe(struct platform_device *pdev) + + /* Request the WOL interrupt and advertise suspend if available */ + priv->wol_irq_disabled = true; +- err = devm_request_irq(&pdev->dev, priv->wol_irq, bcmgenet_wol_isr, 0, +- dev->name, priv); +- if (!err) +- device_set_wakeup_capable(&pdev->dev, 1); ++ if (priv->wol_irq > 0) { ++ err = devm_request_irq(&pdev->dev, priv->wol_irq, ++ bcmgenet_wol_isr, 0, dev->name, priv); ++ if (!err) ++ device_set_wakeup_capable(&pdev->dev, 1); ++ } + + /* Set the needed headroom to account for any possible + * features enabling/disabling at runtime +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index d13fb1d318215..d71c11a6282ec 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -4739,7 +4739,7 @@ static int macb_probe(struct platform_device *pdev) + + #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) { +- dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); ++ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44)); + bp->hw_dma_cap |= HW_DMA_CAP_64B; + } + #endif +diff --git a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +index 7ff31d1026fb2..e0d34e64fc6cb 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c +@@ -3678,6 +3678,8 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, + MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10); + adapter->params.pci.vpd_cap_addr = + pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD); ++ if (!adapter->params.pci.vpd_cap_addr) ++ return -ENODEV; + ret = get_vpd_params(adapter, &adapter->params.vpd); + if (ret < 0) + return ret; +diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +index 5903bdb78916f..129352bbe1143 100644 +--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c ++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +@@ -2015,12 +2015,15 @@ static int cxgb4_get_module_info(struct net_device *dev, + if (ret) + return ret; + +- if (!sff8472_comp || (sff_diag_type & 4)) { ++ if (!sff8472_comp || (sff_diag_type & SFP_DIAG_ADDRMODE)) { + modinfo->type = ETH_MODULE_SFF_8079; + modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8472; +- modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; ++ if (sff_diag_type & SFP_DIAG_IMPLEMENTED) ++ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; ++ else ++ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2; + } + break; + +diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +index 002fc62ea7262..63bc956d20376 100644 +--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h ++++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +@@ -293,6 +293,8 @@ enum { + #define I2C_PAGE_SIZE 0x100 + #define SFP_DIAG_TYPE_ADDR 0x5c + #define SFP_DIAG_TYPE_LEN 0x1 ++#define SFP_DIAG_ADDRMODE BIT(2) ++#define SFP_DIAG_IMPLEMENTED BIT(6) + #define SFF_8472_COMP_ADDR 0x5e + #define SFF_8472_COMP_LEN 0x1 + #define SFF_REV_ADDR 0x1 +diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c +index bcad69c480740..4af5561cbfc54 100644 +--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c ++++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.c +@@ -870,7 +870,7 @@ static void do_abort_syn_rcv(struct sock *child, struct sock *parent) + * created only after 3 way handshake is done. + */ + sock_orphan(child); +- percpu_counter_inc((child)->sk_prot->orphan_count); ++ INC_ORPHAN_COUNT(child); + chtls_release_resources(child); + chtls_conn_done(child); + } else { +diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h +index b1161bdeda4dc..f61ca657601ca 100644 +--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h ++++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_cm.h +@@ -95,7 +95,7 @@ struct deferred_skb_cb { + #define WSCALE_OK(tp) ((tp)->rx_opt.wscale_ok) + #define TSTAMP_OK(tp) ((tp)->rx_opt.tstamp_ok) + #define SACK_OK(tp) ((tp)->rx_opt.sack_ok) +-#define INC_ORPHAN_COUNT(sk) percpu_counter_inc((sk)->sk_prot->orphan_count) ++#define INC_ORPHAN_COUNT(sk) this_cpu_inc(*(sk)->sk_prot->orphan_count) + + /* TLS SKB */ + #define skb_ulp_tls_inline(skb) (ULP_SKB_CB(skb)->ulp.tls.ofld) +diff --git a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c +index d04a6c1634452..da8d10475a08e 100644 +--- a/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c ++++ b/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c +@@ -32,6 +32,7 @@ + + #include <linux/tcp.h> + #include <linux/ipv6.h> ++#include <net/inet_ecn.h> + #include <net/route.h> + #include <net/ip6_route.h> + +@@ -99,7 +100,7 @@ cxgb_find_route(struct cxgb4_lld_info *lldi, + + rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip, + peer_port, local_port, IPPROTO_TCP, +- tos, 0); ++ tos & ~INET_ECN_MASK, 0); + if (IS_ERR(rt)) + return NULL; + n = dst_neigh_lookup(&rt->dst, &peer_ip); +diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c +index 6e745ca4c4333..012ca11a38cc1 100644 +--- a/drivers/net/ethernet/cortina/gemini.c ++++ b/drivers/net/ethernet/cortina/gemini.c +@@ -305,21 +305,21 @@ static void gmac_speed_set(struct net_device *netdev) + switch (phydev->speed) { + case 1000: + status.bits.speed = GMAC_SPEED_1000; +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII) ++ if (phy_interface_mode_is_rgmii(phydev->interface)) + status.bits.mii_rmii = GMAC_PHY_RGMII_1000; + netdev_dbg(netdev, "connect %s to RGMII @ 1Gbit\n", + phydev_name(phydev)); + break; + case 100: + status.bits.speed = GMAC_SPEED_100; +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII) ++ if (phy_interface_mode_is_rgmii(phydev->interface)) + status.bits.mii_rmii = GMAC_PHY_RGMII_100_10; + netdev_dbg(netdev, "connect %s to RGMII @ 100 Mbit\n", + phydev_name(phydev)); + break; + case 10: + status.bits.speed = GMAC_SPEED_10; +- if (phydev->interface == PHY_INTERFACE_MODE_RGMII) ++ if (phy_interface_mode_is_rgmii(phydev->interface)) + status.bits.mii_rmii = GMAC_PHY_RGMII_100_10; + netdev_dbg(netdev, "connect %s to RGMII @ 10 Mbit\n", + phydev_name(phydev)); +@@ -389,6 +389,9 @@ static int gmac_setup_phy(struct net_device *netdev) + status.bits.mii_rmii = GMAC_PHY_GMII; + break; + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: + netdev_dbg(netdev, + "RGMII: set GMAC0 and GMAC1 to MII/RGMII mode\n"); + status.bits.mii_rmii = GMAC_PHY_RGMII_100_10; +diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c +index 36ab4cbf2ad08..b9d967e419387 100644 +--- a/drivers/net/ethernet/dec/tulip/de4x5.c ++++ b/drivers/net/ethernet/dec/tulip/de4x5.c +@@ -4708,6 +4708,10 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p) + lp->ibn = 3; + lp->active = *p++; + if (MOTO_SROM_BUG) lp->active = 0; ++ /* if (MOTO_SROM_BUG) statement indicates lp->active could ++ * be 8 (i.e. the size of array lp->phy) */ ++ if (WARN_ON(lp->active >= ARRAY_SIZE(lp->phy))) ++ return -EINVAL; + lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1); + lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1); + lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2; +@@ -4999,19 +5003,23 @@ mii_get_phy(struct net_device *dev) + } + if ((j == limit) && (i < DE4X5_MAX_MII)) { + for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++); +- lp->phy[k].addr = i; +- lp->phy[k].id = id; +- lp->phy[k].spd.reg = GENERIC_REG; /* ANLPA register */ +- lp->phy[k].spd.mask = GENERIC_MASK; /* 100Mb/s technologies */ +- lp->phy[k].spd.value = GENERIC_VALUE; /* TX & T4, H/F Duplex */ +- lp->mii_cnt++; +- lp->active++; +- printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name); +- j = de4x5_debug; +- de4x5_debug |= DEBUG_MII; +- de4x5_dbg_mii(dev, k); +- de4x5_debug = j; +- printk("\n"); ++ if (k < DE4X5_MAX_PHY) { ++ lp->phy[k].addr = i; ++ lp->phy[k].id = id; ++ lp->phy[k].spd.reg = GENERIC_REG; /* ANLPA register */ ++ lp->phy[k].spd.mask = GENERIC_MASK; /* 100Mb/s technologies */ ++ lp->phy[k].spd.value = GENERIC_VALUE; /* TX & T4, H/F Duplex */ ++ lp->mii_cnt++; ++ lp->active++; ++ printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name); ++ j = de4x5_debug; ++ de4x5_debug |= DEBUG_MII; ++ de4x5_dbg_mii(dev, k); ++ de4x5_debug = j; ++ printk("\n"); ++ } else { ++ goto purgatory; ++ } + } + } + purgatory: +diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c +index 85b99099c6b94..5babcf05bc2f1 100644 +--- a/drivers/net/ethernet/dec/tulip/winbond-840.c ++++ b/drivers/net/ethernet/dec/tulip/winbond-840.c +@@ -877,7 +877,7 @@ static void init_registers(struct net_device *dev) + 8000 16 longwords 0200 2 longwords 2000 32 longwords + C000 32 longwords 0400 4 longwords */ + +-#if defined (__i386__) && !defined(MODULE) ++#if defined (__i386__) && !defined(MODULE) && !defined(CONFIG_UML) + /* When not a module we can work around broken '486 PCI boards. */ + if (boot_cpu_data.x86 <= 4) { + i |= 0x4800; +diff --git a/drivers/net/ethernet/ezchip/Kconfig b/drivers/net/ethernet/ezchip/Kconfig +index 38aa824efb25d..9241b9b1c7a36 100644 +--- a/drivers/net/ethernet/ezchip/Kconfig ++++ b/drivers/net/ethernet/ezchip/Kconfig +@@ -18,7 +18,7 @@ if NET_VENDOR_EZCHIP + + config EZCHIP_NPS_MANAGEMENT_ENET + tristate "EZchip NPS management enet support" +- depends on OF_IRQ && OF_NET ++ depends on OF_IRQ + depends on HAS_IOMEM + help + Simple LAN device for debug or management purposes. +diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c +index 25c91b3c5fd30..819266d463b07 100644 +--- a/drivers/net/ethernet/fealnx.c ++++ b/drivers/net/ethernet/fealnx.c +@@ -857,7 +857,7 @@ static int netdev_open(struct net_device *dev) + np->bcrvalue |= 0x04; /* big-endian */ + #endif + +-#if defined(__i386__) && !defined(MODULE) ++#if defined(__i386__) && !defined(MODULE) && !defined(CONFIG_UML) + if (boot_cpu_data.x86 <= 4) + np->crvalue = 0xa00; + else +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 7065c71ed7b86..8b7a29e1e221b 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4329,7 +4329,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) + } + + INIT_WORK(&priv->tx_onestep_tstamp, dpaa2_eth_tx_onestep_tstamp); +- ++ mutex_init(&priv->onestep_tstamp_lock); + skb_queue_head_init(&priv->tx_skbs); + + priv->rx_copybreak = DPAA2_ETH_DEFAULT_COPYBREAK; +@@ -4511,12 +4511,12 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) + #ifdef CONFIG_DEBUG_FS + dpaa2_dbg_remove(priv); + #endif ++ ++ unregister_netdev(net_dev); + rtnl_lock(); + dpaa2_eth_disconnect_mac(priv); + rtnl_unlock(); + +- unregister_netdev(net_dev); +- + dpaa2_eth_dl_port_del(priv); + dpaa2_eth_dl_traps_unregister(priv); + dpaa2_eth_dl_unregister(priv); +@@ -4538,10 +4538,12 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) + + fsl_mc_portal_free(priv->mc_io); + +- free_netdev(net_dev); ++ destroy_workqueue(priv->dpaa2_ptp_wq); + + dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); + ++ free_netdev(net_dev); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c +index d6eefbbf163fa..cacd454ac696c 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c +@@ -532,6 +532,7 @@ static int dpaa2_switch_flower_parse_mirror_key(struct flow_cls_offload *cls, + struct flow_rule *rule = flow_cls_offload_flow_rule(cls); + struct flow_dissector *dissector = rule->match.dissector; + struct netlink_ext_ack *extack = cls->common.extack; ++ int ret = -EOPNOTSUPP; + + if (dissector->used_keys & + ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | +@@ -561,9 +562,10 @@ static int dpaa2_switch_flower_parse_mirror_key(struct flow_cls_offload *cls, + } + + *vlan = (u16)match.key->vlan_id; ++ ret = 0; + } + +- return 0; ++ return ret; + } + + static int +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +index 4577226d3c6ad..0536d2c76fbc4 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +@@ -486,14 +486,16 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, + + data_size = sizeof(struct streamid_data); + si_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL); ++ if (!si_data) ++ return -ENOMEM; + cbd.length = cpu_to_le16(data_size); + + dma = dma_map_single(&priv->si->pdev->dev, si_data, + data_size, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->si->pdev->dev, dma)) { + netdev_err(priv->si->ndev, "DMA mapping failed!\n"); +- kfree(si_data); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto out; + } + + cbd.addr[0] = cpu_to_le32(lower_32_bits(dma)); +@@ -512,12 +514,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, + + err = enetc_send_cmd(priv->si, &cbd); + if (err) +- return -EINVAL; ++ goto out; + +- if (!enable) { +- kfree(si_data); +- return 0; +- } ++ if (!enable) ++ goto out; + + /* Enable the entry overwrite again incase space flushed by hardware */ + memset(&cbd, 0, sizeof(cbd)); +@@ -560,6 +560,10 @@ static int enetc_streamid_hw_set(struct enetc_ndev_priv *priv, + } + + err = enetc_send_cmd(priv->si, &cbd); ++out: ++ if (!dma_mapping_error(&priv->si->pdev->dev, dma)) ++ dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_FROM_DEVICE); ++ + kfree(si_data); + + return err; +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index 7b4961daa2540..ed7301b691694 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -377,6 +377,9 @@ struct bufdesc_ex { + #define FEC_ENET_WAKEUP ((uint)0x00020000) /* Wakeup request */ + #define FEC_ENET_TXF (FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2) + #define FEC_ENET_RXF (FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2) ++#define FEC_ENET_RXF_GET(X) (((X) == 0) ? FEC_ENET_RXF_0 : \ ++ (((X) == 1) ? FEC_ENET_RXF_1 : \ ++ FEC_ENET_RXF_2)) + #define FEC_ENET_TS_AVAIL ((uint)0x00010000) + #define FEC_ENET_TS_TIMER ((uint)0x00008000) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index ec87b370bba1f..a3e87e10ee6bd 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1480,7 +1480,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + break; + pkt_received++; + +- writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); ++ writel(FEC_ENET_RXF_GET(queue_id), fep->hwp + FEC_IEVENT); + + /* Check for errors. */ + status ^= BD_ENET_RX_LAST; +diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c +index d9baac0dbc7d0..4c9d05c45c033 100644 +--- a/drivers/net/ethernet/freescale/fman/fman_port.c ++++ b/drivers/net/ethernet/freescale/fman/fman_port.c +@@ -1805,7 +1805,7 @@ static int fman_port_probe(struct platform_device *of_dev) + fman = dev_get_drvdata(&fm_pdev->dev); + if (!fman) { + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + + err = of_property_read_u32(port_node, "cell-index", &val); +@@ -1813,7 +1813,7 @@ static int fman_port_probe(struct platform_device *of_dev) + dev_err(port->dev, "%s: reading cell-index for %pOF failed\n", + __func__, port_node); + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + port_id = (u8)val; + port->dts_params.id = port_id; +@@ -1847,7 +1847,7 @@ static int fman_port_probe(struct platform_device *of_dev) + } else { + dev_err(port->dev, "%s: Illegal port type\n", __func__); + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + + port->dts_params.type = port_type; +@@ -1861,7 +1861,7 @@ static int fman_port_probe(struct platform_device *of_dev) + dev_err(port->dev, "%s: incorrect qman-channel-id\n", + __func__); + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + port->dts_params.qman_channel_id = qman_channel_id; + } +@@ -1871,7 +1871,7 @@ static int fman_port_probe(struct platform_device *of_dev) + dev_err(port->dev, "%s: of_address_to_resource() failed\n", + __func__); + err = -ENOMEM; +- goto return_err; ++ goto put_device; + } + + port->dts_params.fman = fman; +@@ -1896,6 +1896,8 @@ static int fman_port_probe(struct platform_device *of_dev) + + return 0; + ++put_device: ++ put_device(&fm_pdev->dev); + return_err: + of_node_put(port_node); + free_port: +diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c +index d9fc5c456bf3e..39ae965cd4f64 100644 +--- a/drivers/net/ethernet/freescale/fman/mac.c ++++ b/drivers/net/ethernet/freescale/fman/mac.c +@@ -94,14 +94,17 @@ static void mac_exception(void *handle, enum fman_mac_exceptions ex) + __func__, ex); + } + +-static void set_fman_mac_params(struct mac_device *mac_dev, +- struct fman_mac_params *params) ++static int set_fman_mac_params(struct mac_device *mac_dev, ++ struct fman_mac_params *params) + { + struct mac_priv_s *priv = mac_dev->priv; + + params->base_addr = (typeof(params->base_addr)) + devm_ioremap(priv->dev, mac_dev->res->start, + resource_size(mac_dev->res)); ++ if (!params->base_addr) ++ return -ENOMEM; ++ + memcpy(¶ms->addr, mac_dev->addr, sizeof(mac_dev->addr)); + params->max_speed = priv->max_speed; + params->phy_if = mac_dev->phy_if; +@@ -112,6 +115,8 @@ static void set_fman_mac_params(struct mac_device *mac_dev, + params->event_cb = mac_exception; + params->dev_id = mac_dev; + params->internal_phy_node = priv->internal_phy_node; ++ ++ return 0; + } + + static int tgec_initialization(struct mac_device *mac_dev) +@@ -123,7 +128,9 @@ static int tgec_initialization(struct mac_device *mac_dev) + + priv = mac_dev->priv; + +- set_fman_mac_params(mac_dev, ¶ms); ++ err = set_fman_mac_params(mac_dev, ¶ms); ++ if (err) ++ goto _return; + + mac_dev->fman_mac = tgec_config(¶ms); + if (!mac_dev->fman_mac) { +@@ -169,7 +176,9 @@ static int dtsec_initialization(struct mac_device *mac_dev) + + priv = mac_dev->priv; + +- set_fman_mac_params(mac_dev, ¶ms); ++ err = set_fman_mac_params(mac_dev, ¶ms); ++ if (err) ++ goto _return; + + mac_dev->fman_mac = dtsec_config(¶ms); + if (!mac_dev->fman_mac) { +@@ -218,7 +227,9 @@ static int memac_initialization(struct mac_device *mac_dev) + + priv = mac_dev->priv; + +- set_fman_mac_params(mac_dev, ¶ms); ++ err = set_fman_mac_params(mac_dev, ¶ms); ++ if (err) ++ goto _return; + + if (priv->max_speed == SPEED_10000) + params.phy_if = PHY_INTERFACE_MODE_XGMII; +diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c +index 0b68852379da5..27d07468765f0 100644 +--- a/drivers/net/ethernet/freescale/xgmac_mdio.c ++++ b/drivers/net/ethernet/freescale/xgmac_mdio.c +@@ -52,6 +52,7 @@ struct tgec_mdio_controller { + struct mdio_fsl_priv { + struct tgec_mdio_controller __iomem *mdio_base; + bool is_little_endian; ++ bool has_a009885; + bool has_a011043; + }; + +@@ -187,10 +188,10 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) + { + struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; + struct tgec_mdio_controller __iomem *regs = priv->mdio_base; ++ unsigned long flags; + uint16_t dev_addr; + uint32_t mdio_stat; + uint32_t mdio_ctl; +- uint16_t value; + int ret; + bool endian = priv->is_little_endian; + +@@ -222,12 +223,18 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) + return ret; + } + ++ if (priv->has_a009885) ++ /* Once the operation completes, i.e. MDIO_STAT_BSY clears, we ++ * must read back the data register within 16 MDC cycles. ++ */ ++ local_irq_save(flags); ++ + /* Initiate the read */ + xgmac_write32(mdio_ctl | MDIO_CTL_READ, ®s->mdio_ctl, endian); + + ret = xgmac_wait_until_done(&bus->dev, regs, endian); + if (ret) +- return ret; ++ goto irq_restore; + + /* Return all Fs if nothing was there */ + if ((xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) && +@@ -235,13 +242,17 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) + dev_dbg(&bus->dev, + "Error while reading PHY%d reg at %d.%hhu\n", + phy_id, dev_addr, regnum); +- return 0xffff; ++ ret = 0xffff; ++ } else { ++ ret = xgmac_read32(®s->mdio_data, endian) & 0xffff; ++ dev_dbg(&bus->dev, "read %04x\n", ret); + } + +- value = xgmac_read32(®s->mdio_data, endian) & 0xffff; +- dev_dbg(&bus->dev, "read %04x\n", value); ++irq_restore: ++ if (priv->has_a009885) ++ local_irq_restore(flags); + +- return value; ++ return ret; + } + + static int xgmac_mdio_probe(struct platform_device *pdev) +@@ -288,6 +299,8 @@ static int xgmac_mdio_probe(struct platform_device *pdev) + priv->is_little_endian = device_property_read_bool(&pdev->dev, + "little-endian"); + ++ priv->has_a009885 = device_property_read_bool(&pdev->dev, ++ "fsl,erratum-a009885"); + priv->has_a011043 = device_property_read_bool(&pdev->dev, + "fsl,erratum-a011043"); + +@@ -319,9 +332,10 @@ err_ioremap: + static int xgmac_mdio_remove(struct platform_device *pdev) + { + struct mii_bus *bus = platform_get_drvdata(pdev); ++ struct mdio_fsl_priv *priv = bus->priv; + + mdiobus_unregister(bus); +- iounmap(bus->priv); ++ iounmap(priv->mdio_base); + mdiobus_free(bus); + + return 0; +diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h +index 92dc18a4bcc41..b1273dce4795b 100644 +--- a/drivers/net/ethernet/google/gve/gve.h ++++ b/drivers/net/ethernet/google/gve/gve.h +@@ -30,7 +30,7 @@ + #define GVE_MIN_MSIX 3 + + /* Numbers of gve tx/rx stats in stats report. */ +-#define GVE_TX_STATS_REPORT_NUM 5 ++#define GVE_TX_STATS_REPORT_NUM 6 + #define GVE_RX_STATS_REPORT_NUM 2 + + /* Interval to schedule a stats report update, 20000ms. */ +@@ -224,11 +224,6 @@ struct gve_tx_iovec { + u32 iov_padding; /* padding associated with this segment */ + }; + +-struct gve_tx_dma_buf { +- DEFINE_DMA_UNMAP_ADDR(dma); +- DEFINE_DMA_UNMAP_LEN(len); +-}; +- + /* Tracks the memory in the fifo occupied by the skb. Mapped 1:1 to a desc + * ring entry but only used for a pkt_desc not a seg_desc + */ +@@ -236,7 +231,10 @@ struct gve_tx_buffer_state { + struct sk_buff *skb; /* skb for this pkt */ + union { + struct gve_tx_iovec iov[GVE_TX_MAX_IOVEC]; /* segments of this pkt */ +- struct gve_tx_dma_buf buf; ++ struct { ++ DEFINE_DMA_UNMAP_ADDR(dma); ++ DEFINE_DMA_UNMAP_LEN(len); ++ }; + }; + }; + +@@ -280,7 +278,8 @@ struct gve_tx_pending_packet_dqo { + * All others correspond to `skb`'s frags and should be unmapped with + * `dma_unmap_page`. + */ +- struct gve_tx_dma_buf bufs[MAX_SKB_FRAGS + 1]; ++ DEFINE_DMA_UNMAP_ADDR(dma[MAX_SKB_FRAGS + 1]); ++ DEFINE_DMA_UNMAP_LEN(len[MAX_SKB_FRAGS + 1]); + u16 num_bufs; + + /* Linked list index to next element in the list, or -1 if none */ +@@ -414,7 +413,9 @@ struct gve_tx_ring { + u32 q_num ____cacheline_aligned; /* queue idx */ + u32 stop_queue; /* count of queue stops */ + u32 wake_queue; /* count of queue wakes */ ++ u32 queue_timeout; /* count of queue timeouts */ + u32 ntfy_id; /* notification block index */ ++ u32 last_kick_msec; /* Last time the queue was kicked */ + dma_addr_t bus; /* dma address of the descr ring */ + dma_addr_t q_resources_bus; /* dma address of the queue resources */ + dma_addr_t complq_bus_dqo; /* dma address of the dqo.compl_ring */ +@@ -814,7 +815,7 @@ static inline bool gve_is_gqi(struct gve_priv *priv) + /* buffers */ + int gve_alloc_page(struct gve_priv *priv, struct device *dev, + struct page **page, dma_addr_t *dma, +- enum dma_data_direction); ++ enum dma_data_direction, gfp_t gfp_flags); + void gve_free_page(struct device *dev, struct page *page, dma_addr_t dma, + enum dma_data_direction); + /* tx handling */ +diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c +index f089d33dd48e0..ce507464f3d62 100644 +--- a/drivers/net/ethernet/google/gve/gve_adminq.c ++++ b/drivers/net/ethernet/google/gve/gve_adminq.c +@@ -281,7 +281,7 @@ static int gve_adminq_parse_err(struct gve_priv *priv, u32 status) + */ + static int gve_adminq_kick_and_wait(struct gve_priv *priv) + { +- u32 tail, head; ++ int tail, head; + int i; + + tail = ioread32be(&priv->reg_bar0->adminq_event_counter); +diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h +index 47c3d8f313fcf..3953f6f7a4273 100644 +--- a/drivers/net/ethernet/google/gve/gve_adminq.h ++++ b/drivers/net/ethernet/google/gve/gve_adminq.h +@@ -270,6 +270,7 @@ enum gve_stat_names { + TX_LAST_COMPLETION_PROCESSED = 5, + RX_NEXT_EXPECTED_SEQUENCE = 6, + RX_BUFFERS_POSTED = 7, ++ TX_TIMEOUT_CNT = 8, + // stats from NIC + RX_QUEUE_DROP_CNT = 65, + RX_NO_BUFFERS_POSTED = 66, +diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c +index bf8a4a7c43f78..68552848d3888 100644 +--- a/drivers/net/ethernet/google/gve/gve_main.c ++++ b/drivers/net/ethernet/google/gve/gve_main.c +@@ -24,6 +24,9 @@ + #define GVE_VERSION "1.0.0" + #define GVE_VERSION_PREFIX "GVE-" + ++// Minimum amount of time between queue kicks in msec (10 seconds) ++#define MIN_TX_TIMEOUT_GAP (1000 * 10) ++ + const char gve_version_str[] = GVE_VERSION; + static const char gve_version_prefix[] = GVE_VERSION_PREFIX; + +@@ -743,9 +746,9 @@ static void gve_free_rings(struct gve_priv *priv) + + int gve_alloc_page(struct gve_priv *priv, struct device *dev, + struct page **page, dma_addr_t *dma, +- enum dma_data_direction dir) ++ enum dma_data_direction dir, gfp_t gfp_flags) + { +- *page = alloc_page(GFP_KERNEL); ++ *page = alloc_page(gfp_flags); + if (!*page) { + priv->page_alloc_fail++; + return -ENOMEM; +@@ -789,7 +792,7 @@ static int gve_alloc_queue_page_list(struct gve_priv *priv, u32 id, + for (i = 0; i < pages; i++) { + err = gve_alloc_page(priv, &priv->pdev->dev, &qpl->pages[i], + &qpl->page_buses[i], +- gve_qpl_dma_dir(priv, id)); ++ gve_qpl_dma_dir(priv, id), GFP_KERNEL); + /* caller handles clean up */ + if (err) + return -ENOMEM; +@@ -1116,9 +1119,47 @@ static void gve_turnup(struct gve_priv *priv) + + static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue) + { +- struct gve_priv *priv = netdev_priv(dev); ++ struct gve_notify_block *block; ++ struct gve_tx_ring *tx = NULL; ++ struct gve_priv *priv; ++ u32 last_nic_done; ++ u32 current_time; ++ u32 ntfy_idx; ++ ++ netdev_info(dev, "Timeout on tx queue, %d", txqueue); ++ priv = netdev_priv(dev); ++ if (txqueue > priv->tx_cfg.num_queues) ++ goto reset; ++ ++ ntfy_idx = gve_tx_idx_to_ntfy(priv, txqueue); ++ if (ntfy_idx >= priv->num_ntfy_blks) ++ goto reset; + ++ block = &priv->ntfy_blocks[ntfy_idx]; ++ tx = block->tx; ++ ++ current_time = jiffies_to_msecs(jiffies); ++ if (tx->last_kick_msec + MIN_TX_TIMEOUT_GAP > current_time) ++ goto reset; ++ ++ /* Check to see if there are missed completions, which will allow us to ++ * kick the queue. ++ */ ++ last_nic_done = gve_tx_load_event_counter(priv, tx); ++ if (last_nic_done - tx->done) { ++ netdev_info(dev, "Kicking queue %d", txqueue); ++ iowrite32be(GVE_IRQ_MASK, gve_irq_doorbell(priv, block)); ++ napi_schedule(&block->napi); ++ tx->last_kick_msec = current_time; ++ goto out; ++ } // Else reset. ++ ++reset: + gve_schedule_reset(priv); ++ ++out: ++ if (tx) ++ tx->queue_timeout++; + priv->tx_timeo_cnt++; + } + +@@ -1247,6 +1288,11 @@ void gve_handle_report_stats(struct gve_priv *priv) + .value = cpu_to_be64(last_completion), + .queue_id = cpu_to_be32(idx), + }; ++ stats[stats_idx++] = (struct stats) { ++ .stat_name = cpu_to_be32(TX_TIMEOUT_CNT), ++ .value = cpu_to_be64(priv->tx[idx].queue_timeout), ++ .queue_id = cpu_to_be32(idx), ++ }; + } + } + /* rx stats */ +diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c +index 94941d4e47449..97431969a488f 100644 +--- a/drivers/net/ethernet/google/gve/gve_rx.c ++++ b/drivers/net/ethernet/google/gve/gve_rx.c +@@ -79,7 +79,8 @@ static int gve_rx_alloc_buffer(struct gve_priv *priv, struct device *dev, + dma_addr_t dma; + int err; + +- err = gve_alloc_page(priv, dev, &page, &dma, DMA_FROM_DEVICE); ++ err = gve_alloc_page(priv, dev, &page, &dma, DMA_FROM_DEVICE, ++ GFP_ATOMIC); + if (err) + return err; + +@@ -449,6 +450,7 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc, + skb_set_hash(skb, be32_to_cpu(rx_desc->rss_hash), + gve_rss_type(rx_desc->flags_seq)); + ++ skb_record_rx_queue(skb, rx->q_num); + if (skb_is_nonlinear(skb)) + napi_gro_frags(napi); + else +@@ -514,8 +516,13 @@ static bool gve_rx_refill_buffers(struct gve_priv *priv, struct gve_rx_ring *rx) + + gve_rx_free_buffer(dev, page_info, data_slot); + page_info->page = NULL; +- if (gve_rx_alloc_buffer(priv, dev, page_info, data_slot)) ++ if (gve_rx_alloc_buffer(priv, dev, page_info, ++ data_slot)) { ++ u64_stats_update_begin(&rx->statss); ++ rx->rx_buf_alloc_fail++; ++ u64_stats_update_end(&rx->statss); + break; ++ } + } + } + fill_cnt++; +diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c +index 8500621b2cd41..7b18b4fd9e548 100644 +--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c ++++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c +@@ -157,7 +157,7 @@ static int gve_alloc_page_dqo(struct gve_priv *priv, + int err; + + err = gve_alloc_page(priv, &priv->pdev->dev, &buf_state->page_info.page, +- &buf_state->addr, DMA_FROM_DEVICE); ++ &buf_state->addr, DMA_FROM_DEVICE, GFP_KERNEL); + if (err) + return err; + +diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c +index 665ac795a1adf..9922ce46a6351 100644 +--- a/drivers/net/ethernet/google/gve/gve_tx.c ++++ b/drivers/net/ethernet/google/gve/gve_tx.c +@@ -303,15 +303,15 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx, + static void gve_tx_unmap_buf(struct device *dev, struct gve_tx_buffer_state *info) + { + if (info->skb) { +- dma_unmap_single(dev, dma_unmap_addr(&info->buf, dma), +- dma_unmap_len(&info->buf, len), ++ dma_unmap_single(dev, dma_unmap_addr(info, dma), ++ dma_unmap_len(info, len), + DMA_TO_DEVICE); +- dma_unmap_len_set(&info->buf, len, 0); ++ dma_unmap_len_set(info, len, 0); + } else { +- dma_unmap_page(dev, dma_unmap_addr(&info->buf, dma), +- dma_unmap_len(&info->buf, len), ++ dma_unmap_page(dev, dma_unmap_addr(info, dma), ++ dma_unmap_len(info, len), + DMA_TO_DEVICE); +- dma_unmap_len_set(&info->buf, len, 0); ++ dma_unmap_len_set(info, len, 0); + } + } + +@@ -491,7 +491,6 @@ static int gve_tx_add_skb_no_copy(struct gve_priv *priv, struct gve_tx_ring *tx, + struct gve_tx_buffer_state *info; + bool is_gso = skb_is_gso(skb); + u32 idx = tx->req & tx->mask; +- struct gve_tx_dma_buf *buf; + u64 addr; + u32 len; + int i; +@@ -515,9 +514,8 @@ static int gve_tx_add_skb_no_copy(struct gve_priv *priv, struct gve_tx_ring *tx, + tx->dma_mapping_error++; + goto drop; + } +- buf = &info->buf; +- dma_unmap_len_set(buf, len, len); +- dma_unmap_addr_set(buf, dma, addr); ++ dma_unmap_len_set(info, len, len); ++ dma_unmap_addr_set(info, dma, addr); + + payload_nfrags = shinfo->nr_frags; + if (hlen < len) { +@@ -549,10 +547,9 @@ static int gve_tx_add_skb_no_copy(struct gve_priv *priv, struct gve_tx_ring *tx, + tx->dma_mapping_error++; + goto unmap_drop; + } +- buf = &tx->info[idx].buf; + tx->info[idx].skb = NULL; +- dma_unmap_len_set(buf, len, len); +- dma_unmap_addr_set(buf, dma, addr); ++ dma_unmap_len_set(&tx->info[idx], len, len); ++ dma_unmap_addr_set(&tx->info[idx], dma, addr); + + gve_tx_fill_seg_desc(seg_desc, skb, is_gso, len, addr); + } +diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c +index 05ddb6a75c38f..ec394d9916681 100644 +--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c ++++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c +@@ -85,18 +85,16 @@ static void gve_tx_clean_pending_packets(struct gve_tx_ring *tx) + int j; + + for (j = 0; j < cur_state->num_bufs; j++) { +- struct gve_tx_dma_buf *buf = &cur_state->bufs[j]; +- + if (j == 0) { + dma_unmap_single(tx->dev, +- dma_unmap_addr(buf, dma), +- dma_unmap_len(buf, len), +- DMA_TO_DEVICE); ++ dma_unmap_addr(cur_state, dma[j]), ++ dma_unmap_len(cur_state, len[j]), ++ DMA_TO_DEVICE); + } else { + dma_unmap_page(tx->dev, +- dma_unmap_addr(buf, dma), +- dma_unmap_len(buf, len), +- DMA_TO_DEVICE); ++ dma_unmap_addr(cur_state, dma[j]), ++ dma_unmap_len(cur_state, len[j]), ++ DMA_TO_DEVICE); + } + } + if (cur_state->skb) { +@@ -457,15 +455,15 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, + const bool is_gso = skb_is_gso(skb); + u32 desc_idx = tx->dqo_tx.tail; + +- struct gve_tx_pending_packet_dqo *pending_packet; ++ struct gve_tx_pending_packet_dqo *pkt; + struct gve_tx_metadata_dqo metadata; + s16 completion_tag; + int i; + +- pending_packet = gve_alloc_pending_packet(tx); +- pending_packet->skb = skb; +- pending_packet->num_bufs = 0; +- completion_tag = pending_packet - tx->dqo.pending_packets; ++ pkt = gve_alloc_pending_packet(tx); ++ pkt->skb = skb; ++ pkt->num_bufs = 0; ++ completion_tag = pkt - tx->dqo.pending_packets; + + gve_extract_tx_metadata_dqo(skb, &metadata); + if (is_gso) { +@@ -493,8 +491,6 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, + + /* Map the linear portion of skb */ + { +- struct gve_tx_dma_buf *buf = +- &pending_packet->bufs[pending_packet->num_bufs]; + u32 len = skb_headlen(skb); + dma_addr_t addr; + +@@ -502,9 +498,9 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, + if (unlikely(dma_mapping_error(tx->dev, addr))) + goto err; + +- dma_unmap_len_set(buf, len, len); +- dma_unmap_addr_set(buf, dma, addr); +- ++pending_packet->num_bufs; ++ dma_unmap_len_set(pkt, len[pkt->num_bufs], len); ++ dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr); ++ ++pkt->num_bufs; + + gve_tx_fill_pkt_desc_dqo(tx, &desc_idx, skb, len, addr, + completion_tag, +@@ -512,8 +508,6 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, + } + + for (i = 0; i < shinfo->nr_frags; i++) { +- struct gve_tx_dma_buf *buf = +- &pending_packet->bufs[pending_packet->num_bufs]; + const skb_frag_t *frag = &shinfo->frags[i]; + bool is_eop = i == (shinfo->nr_frags - 1); + u32 len = skb_frag_size(frag); +@@ -523,9 +517,9 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, + if (unlikely(dma_mapping_error(tx->dev, addr))) + goto err; + +- dma_unmap_len_set(buf, len, len); +- dma_unmap_addr_set(buf, dma, addr); +- ++pending_packet->num_bufs; ++ dma_unmap_len_set(pkt, len[pkt->num_bufs], len); ++ dma_unmap_addr_set(pkt, dma[pkt->num_bufs], addr); ++ ++pkt->num_bufs; + + gve_tx_fill_pkt_desc_dqo(tx, &desc_idx, skb, len, addr, + completion_tag, is_eop, is_gso); +@@ -552,22 +546,23 @@ static int gve_tx_add_skb_no_copy_dqo(struct gve_tx_ring *tx, + return 0; + + err: +- for (i = 0; i < pending_packet->num_bufs; i++) { +- struct gve_tx_dma_buf *buf = &pending_packet->bufs[i]; +- ++ for (i = 0; i < pkt->num_bufs; i++) { + if (i == 0) { +- dma_unmap_single(tx->dev, dma_unmap_addr(buf, dma), +- dma_unmap_len(buf, len), ++ dma_unmap_single(tx->dev, ++ dma_unmap_addr(pkt, dma[i]), ++ dma_unmap_len(pkt, len[i]), + DMA_TO_DEVICE); + } else { +- dma_unmap_page(tx->dev, dma_unmap_addr(buf, dma), +- dma_unmap_len(buf, len), DMA_TO_DEVICE); ++ dma_unmap_page(tx->dev, ++ dma_unmap_addr(pkt, dma[i]), ++ dma_unmap_len(pkt, len[i]), ++ DMA_TO_DEVICE); + } + } + +- pending_packet->skb = NULL; +- pending_packet->num_bufs = 0; +- gve_free_pending_packet(tx, pending_packet); ++ pkt->skb = NULL; ++ pkt->num_bufs = 0; ++ gve_free_pending_packet(tx, pkt); + + return -1; + } +@@ -725,12 +720,12 @@ static void add_to_list(struct gve_tx_ring *tx, struct gve_index_list *list, + + static void remove_from_list(struct gve_tx_ring *tx, + struct gve_index_list *list, +- struct gve_tx_pending_packet_dqo *pending_packet) ++ struct gve_tx_pending_packet_dqo *pkt) + { + s16 prev_index, next_index; + +- prev_index = pending_packet->prev; +- next_index = pending_packet->next; ++ prev_index = pkt->prev; ++ next_index = pkt->next; + + if (prev_index == -1) { + /* Node is head */ +@@ -747,21 +742,18 @@ static void remove_from_list(struct gve_tx_ring *tx, + } + + static void gve_unmap_packet(struct device *dev, +- struct gve_tx_pending_packet_dqo *pending_packet) ++ struct gve_tx_pending_packet_dqo *pkt) + { +- struct gve_tx_dma_buf *buf; + int i; + + /* SKB linear portion is guaranteed to be mapped */ +- buf = &pending_packet->bufs[0]; +- dma_unmap_single(dev, dma_unmap_addr(buf, dma), +- dma_unmap_len(buf, len), DMA_TO_DEVICE); +- for (i = 1; i < pending_packet->num_bufs; i++) { +- buf = &pending_packet->bufs[i]; +- dma_unmap_page(dev, dma_unmap_addr(buf, dma), +- dma_unmap_len(buf, len), DMA_TO_DEVICE); ++ dma_unmap_single(dev, dma_unmap_addr(pkt, dma[0]), ++ dma_unmap_len(pkt, len[0]), DMA_TO_DEVICE); ++ for (i = 1; i < pkt->num_bufs; i++) { ++ dma_unmap_page(dev, dma_unmap_addr(pkt, dma[i]), ++ dma_unmap_len(pkt, len[i]), DMA_TO_DEVICE); + } +- pending_packet->num_bufs = 0; ++ pkt->num_bufs = 0; + } + + /* Completion types and expected behavior: +diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +index 23d9cbf262c32..740850b64aff5 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +@@ -400,6 +400,10 @@ static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, + return; + + if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { ++ /* DSAF_MAX_PORT_NUM is 6, but DSAF_GE_NUM is 8. ++ We need check to prevent array overflow */ ++ if (port >= DSAF_MAX_PORT_NUM) ++ return; + reg_val_1 = 0x1 << port; + port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off; + /* there is difference between V1 and V2 in register.*/ +diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h +index d701451596c82..47bba4c62f040 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h +@@ -830,6 +830,8 @@ struct hnae3_handle { + + u8 netdev_flags; + struct dentry *hnae3_dbgfs; ++ /* protects concurrent contention between debugfs commands */ ++ struct mutex dbgfs_lock; + + /* Network interface message level enabled bits */ + u32 msg_enable; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +index e54f96251fea9..3205849bdb95b 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +@@ -1021,6 +1021,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, + if (ret) + return ret; + ++ mutex_lock(&handle->dbgfs_lock); + save_buf = &hns3_dbg_cmd[index].buf; + + if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || +@@ -1033,15 +1034,15 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, + read_buf = *save_buf; + } else { + read_buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL); +- if (!read_buf) +- return -ENOMEM; ++ if (!read_buf) { ++ ret = -ENOMEM; ++ goto out; ++ } + + /* save the buffer addr until the last read operation */ + *save_buf = read_buf; +- } + +- /* get data ready for the first time to read */ +- if (!*ppos) { ++ /* get data ready for the first time to read */ + ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd, + read_buf, hns3_dbg_cmd[index].buf_len); + if (ret) +@@ -1050,8 +1051,10 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, + + size = simple_read_from_buffer(buffer, count, ppos, read_buf, + strlen(read_buf)); +- if (size > 0) ++ if (size > 0) { ++ mutex_unlock(&handle->dbgfs_lock); + return size; ++ } + + out: + /* free the buffer for the last read operation */ +@@ -1060,6 +1063,7 @@ out: + *save_buf = NULL; + } + ++ mutex_unlock(&handle->dbgfs_lock); + return ret; + } + +@@ -1132,6 +1136,8 @@ int hns3_dbg_init(struct hnae3_handle *handle) + debugfs_create_dir(hns3_dbg_dentry[i].name, + handle->hnae3_dbgfs); + ++ mutex_init(&handle->dbgfs_lock); ++ + for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { + if ((hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES && + ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) || +@@ -1158,6 +1164,7 @@ int hns3_dbg_init(struct hnae3_handle *handle) + return 0; + + out: ++ mutex_destroy(&handle->dbgfs_lock); + debugfs_remove_recursive(handle->hnae3_dbgfs); + handle->hnae3_dbgfs = NULL; + return ret; +@@ -1173,6 +1180,7 @@ void hns3_dbg_uninit(struct hnae3_handle *handle) + hns3_dbg_cmd[i].buf = NULL; + } + ++ mutex_destroy(&handle->dbgfs_lock); + debugfs_remove_recursive(handle->hnae3_dbgfs); + handle->hnae3_dbgfs = NULL; + } +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +index 5ebd96f6833d6..526fb56c84f24 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +@@ -985,6 +985,7 @@ static int hns3_set_reset(struct net_device *netdev, u32 *flags) + struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); + const struct hnae3_ae_ops *ops = h->ae_algo->ops; + const struct hns3_reset_type_map *rst_type_map; ++ enum ethtool_reset_flags rst_flags; + u32 i, size; + + if (ops->ae_dev_resetting && ops->ae_dev_resetting(h)) +@@ -1004,6 +1005,7 @@ static int hns3_set_reset(struct net_device *netdev, u32 *flags) + for (i = 0; i < size; i++) { + if (rst_type_map[i].rst_flags == *flags) { + rst_type = rst_type_map[i].rst_type; ++ rst_flags = rst_type_map[i].rst_flags; + break; + } + } +@@ -1019,6 +1021,8 @@ static int hns3_set_reset(struct net_device *netdev, u32 *flags) + + ops->reset_event(h->pdev, h); + ++ *flags &= ~rst_flags; ++ + return 0; + } + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +index 91cb578f56b80..375ebf105a9aa 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +@@ -129,7 +129,7 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev, + u32 total_ets_bw = 0; + u8 i; + +- for (i = 0; i < hdev->tc_max; i++) { ++ for (i = 0; i < HNAE3_MAX_TC; i++) { + switch (ets->tc_tsa[i]) { + case IEEE_8021QAZ_TSA_STRICT: + if (hdev->tm_info.tc_info[i].tc_sch_mode != +@@ -286,28 +286,24 @@ err_out: + + static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) + { +- u64 requests[HNAE3_MAX_TC], indications[HNAE3_MAX_TC]; + struct hclge_vport *vport = hclge_get_vport(h); + struct hclge_dev *hdev = vport->back; + int ret; +- u8 i; + + memset(pfc, 0, sizeof(*pfc)); + pfc->pfc_cap = hdev->pfc_max; + pfc->pfc_en = hdev->tm_info.pfc_en; + +- ret = hclge_pfc_tx_stats_get(hdev, requests); +- if (ret) ++ ret = hclge_mac_update_stats(hdev); ++ if (ret) { ++ dev_err(&hdev->pdev->dev, ++ "failed to update MAC stats, ret = %d.\n", ret); + return ret; ++ } + +- ret = hclge_pfc_rx_stats_get(hdev, indications); +- if (ret) +- return ret; ++ hclge_pfc_tx_stats_get(hdev, pfc->requests); ++ hclge_pfc_rx_stats_get(hdev, pfc->indications); + +- for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { +- pfc->requests[i] = requests[i]; +- pfc->indications[i] = indications[i]; +- } + return 0; + } + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index d891390d492f6..66c407d0d507e 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -26,8 +26,6 @@ + #include "hclge_devlink.h" + + #define HCLGE_NAME "hclge" +-#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) +-#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f)) + + #define HCLGE_BUF_SIZE_UNIT 256U + #define HCLGE_BUF_MUL_BY 2 +@@ -548,7 +546,7 @@ static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *desc_num) + return 0; + } + +-static int hclge_mac_update_stats(struct hclge_dev *hdev) ++int hclge_mac_update_stats(struct hclge_dev *hdev) + { + u32 desc_num; + int ret; +@@ -2498,7 +2496,7 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport) + if (hdev->num_msi < hdev->num_nic_msi + hdev->num_roce_msi) + return -EINVAL; + +- roce->rinfo.base_vector = hdev->roce_base_vector; ++ roce->rinfo.base_vector = hdev->num_nic_msi; + + roce->rinfo.netdev = nic->kinfo.netdev; + roce->rinfo.roce_io_base = hdev->hw.io_base; +@@ -2534,10 +2532,6 @@ static int hclge_init_msi(struct hclge_dev *hdev) + hdev->num_msi = vectors; + hdev->num_msi_left = vectors; + +- hdev->base_msi_vector = pdev->irq; +- hdev->roce_base_vector = hdev->base_msi_vector + +- hdev->num_nic_msi; +- + hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi, + sizeof(u16), GFP_KERNEL); + if (!hdev->vector_status) { +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +index 69cd8f87b4c86..2fa6e14c96e5b 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +@@ -824,6 +824,9 @@ struct hclge_vf_vlan_cfg { + (y) = (_k_ ^ ~_v_) & (_k_); \ + } while (0) + ++#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f)) ++#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) ++ + #define HCLGE_MAC_TNL_LOG_SIZE 8 + #define HCLGE_VPORT_NUM 256 + struct hclge_dev { +@@ -876,12 +879,10 @@ struct hclge_dev { + u16 num_msi; + u16 num_msi_left; + u16 num_msi_used; +- u32 base_msi_vector; + u16 *vector_status; + int *vector_irq; + u16 num_nic_msi; /* Num of nic vectors for this PF */ + u16 num_roce_msi; /* Num of roce vectors for this PF */ +- int roce_base_vector; + + unsigned long service_timer_period; + unsigned long service_timer_previous; +@@ -1138,4 +1139,5 @@ void hclge_inform_vf_promisc_info(struct hclge_vport *vport); + int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len); + int hclge_push_vf_link_status(struct hclge_vport *vport); + int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en); ++int hclge_mac_update_stats(struct hclge_dev *hdev); + #endif +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +index 95074e91a8466..429652a8cde16 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +@@ -113,50 +113,50 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, + return 0; + } + +-static int hclge_pfc_stats_get(struct hclge_dev *hdev, +- enum hclge_opcode_type opcode, u64 *stats) +-{ +- struct hclge_desc desc[HCLGE_TM_PFC_PKT_GET_CMD_NUM]; +- int ret, i, j; +- +- if (!(opcode == HCLGE_OPC_QUERY_PFC_RX_PKT_CNT || +- opcode == HCLGE_OPC_QUERY_PFC_TX_PKT_CNT)) +- return -EINVAL; +- +- for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM - 1; i++) { +- hclge_cmd_setup_basic_desc(&desc[i], opcode, true); +- desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); +- } +- +- hclge_cmd_setup_basic_desc(&desc[i], opcode, true); ++static const u16 hclge_pfc_tx_stats_offset[] = { ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri1_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri2_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri3_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri4_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri5_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_pkt_num) ++}; + +- ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_TM_PFC_PKT_GET_CMD_NUM); +- if (ret) +- return ret; ++static const u16 hclge_pfc_rx_stats_offset[] = { ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri1_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri2_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri3_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri4_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri5_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri6_pkt_num), ++ HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri7_pkt_num) ++}; + +- for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM; i++) { +- struct hclge_pfc_stats_cmd *pfc_stats = +- (struct hclge_pfc_stats_cmd *)desc[i].data; ++static void hclge_pfc_stats_get(struct hclge_dev *hdev, bool tx, u64 *stats) ++{ ++ const u16 *offset; ++ int i; + +- for (j = 0; j < HCLGE_TM_PFC_NUM_GET_PER_CMD; j++) { +- u32 index = i * HCLGE_TM_PFC_PKT_GET_CMD_NUM + j; ++ if (tx) ++ offset = hclge_pfc_tx_stats_offset; ++ else ++ offset = hclge_pfc_rx_stats_offset; + +- if (index < HCLGE_MAX_TC_NUM) +- stats[index] = +- le64_to_cpu(pfc_stats->pkt_num[j]); +- } +- } +- return 0; ++ for (i = 0; i < HCLGE_MAX_TC_NUM; i++) ++ stats[i] = HCLGE_STATS_READ(&hdev->mac_stats, offset[i]); + } + +-int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats) ++void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats) + { +- return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_RX_PKT_CNT, stats); ++ hclge_pfc_stats_get(hdev, false, stats); + } + +-int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats) ++void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats) + { +- return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_TX_PKT_CNT, stats); ++ hclge_pfc_stats_get(hdev, true, stats); + } + + int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx) +@@ -1123,7 +1123,6 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) + + static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) + { +-#define DEFAULT_TC_WEIGHT 1 + #define DEFAULT_TC_OFFSET 14 + + struct hclge_ets_tc_weight_cmd *ets_weight; +@@ -1136,13 +1135,7 @@ static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) + for (i = 0; i < HNAE3_MAX_TC; i++) { + struct hclge_pg_info *pg_info; + +- ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT; +- +- if (!(hdev->hw_tc_map & BIT(i))) +- continue; +- +- pg_info = +- &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; ++ pg_info = &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; + ets_weight->tc_weight[i] = pg_info->tc_dwrr[i]; + } + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +index 2ee9b795f71dc..1db7f40b45255 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +@@ -228,8 +228,8 @@ int hclge_tm_dwrr_cfg(struct hclge_dev *hdev); + int hclge_tm_init_hw(struct hclge_dev *hdev, bool init); + int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); + int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); +-int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); +-int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); ++void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); ++void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); + int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate); + int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num); + int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index cf00ad7bb881f..417a08d600b83 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -703,9 +703,9 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) + roundup_size = ilog2(roundup_size); + + for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) { +- tc_valid[i] = !!(hdev->hw_tc_map & BIT(i)); ++ tc_valid[i] = 1; + tc_size[i] = roundup_size; +- tc_offset[i] = rss_size * i; ++ tc_offset[i] = (hdev->hw_tc_map & BIT(i)) ? rss_size * i : 0; + } + + hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_TC_MODE, false); +@@ -2496,8 +2496,7 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data) + break; + } + +- if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER) +- hclgevf_enable_vector(&hdev->misc_vector, true); ++ hclgevf_enable_vector(&hdev->misc_vector, true); + + return IRQ_HANDLED; + } +@@ -2557,7 +2556,7 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev) + hdev->num_msi_left == 0) + return -EINVAL; + +- roce->rinfo.base_vector = hdev->roce_base_vector; ++ roce->rinfo.base_vector = hdev->roce_base_msix_offset; + + roce->rinfo.netdev = nic->kinfo.netdev; + roce->rinfo.roce_io_base = hdev->hw.io_base; +@@ -2823,9 +2822,6 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev) + hdev->num_msi = vectors; + hdev->num_msi_left = vectors; + +- hdev->base_msi_vector = pdev->irq; +- hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset; +- + hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi, + sizeof(u16), GFP_KERNEL); + if (!hdev->vector_status) { +@@ -3013,7 +3009,10 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client, + + /* un-init roce, if it exists */ + if (hdev->roce_client) { ++ while (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) ++ msleep(HCLGEVF_WAIT_RESET_DONE); + clear_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state); ++ + hdev->roce_client->ops->uninit_instance(&hdev->roce, 0); + hdev->roce_client = NULL; + hdev->roce.client = NULL; +@@ -3022,6 +3021,8 @@ static void hclgevf_uninit_client_instance(struct hnae3_client *client, + /* un-init nic/unic, if this was not called by roce client */ + if (client->ops->uninit_instance && hdev->nic_client && + client->type != HNAE3_CLIENT_ROCE) { ++ while (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) ++ msleep(HCLGEVF_WAIT_RESET_DONE); + clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state); + + client->ops->uninit_instance(&hdev->nic, 0); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +index 28288d7e33032..f6f736c0091c0 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +@@ -109,6 +109,8 @@ + #define HCLGEVF_VF_RST_ING 0x07008 + #define HCLGEVF_VF_RST_ING_BIT BIT(16) + ++#define HCLGEVF_WAIT_RESET_DONE 100 ++ + #define HCLGEVF_RSS_IND_TBL_SIZE 512 + #define HCLGEVF_RSS_SET_BITMAP_MSK 0xffff + #define HCLGEVF_RSS_KEY_SIZE 40 +@@ -308,8 +310,6 @@ struct hclgevf_dev { + u16 num_nic_msix; /* Num of nic vectors for this VF */ + u16 num_roce_msix; /* Num of roce vectors for this VF */ + u16 roce_base_msix_offset; +- int roce_base_vector; +- u32 base_msi_vector; + u16 *vector_status; + int *vector_irq; + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +index fdc66fae09601..c5ac6ecf36e10 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +@@ -114,7 +114,8 @@ int hclgevf_send_mbx_msg(struct hclgevf_dev *hdev, + + memcpy(&req->msg, send_msg, sizeof(struct hclge_vf_to_pf_msg)); + +- trace_hclge_vf_mbx_send(hdev, req); ++ if (test_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state)) ++ trace_hclge_vf_mbx_send(hdev, req); + + /* synchronous send */ + if (need_resp) { +diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c +index 27937c5d79567..daec9ce04531b 100644 +--- a/drivers/net/ethernet/i825xx/sni_82596.c ++++ b/drivers/net/ethernet/i825xx/sni_82596.c +@@ -117,9 +117,10 @@ static int sni_82596_probe(struct platform_device *dev) + netdevice->dev_addr[5] = readb(eth_addr + 0x06); + iounmap(eth_addr); + +- if (!netdevice->irq) { ++ if (netdevice->irq < 0) { + printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n", + __FILE__, netdevice->base_addr); ++ retval = netdevice->irq; + goto probe_failed; + } + +diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c +index 6aa6ff89a7651..404921418f422 100644 +--- a/drivers/net/ethernet/ibm/ibmvnic.c ++++ b/drivers/net/ethernet/ibm/ibmvnic.c +@@ -108,6 +108,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter); + static int send_query_phys_parms(struct ibmvnic_adapter *adapter); + static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, + struct ibmvnic_sub_crq_queue *tx_scrq); ++static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter); + + struct ibmvnic_stat { + char name[ETH_GSTRING_LEN]; +@@ -1245,7 +1246,7 @@ static int __ibmvnic_open(struct net_device *netdev) + rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); + if (rc) { + ibmvnic_napi_disable(adapter); +- release_resources(adapter); ++ ibmvnic_disable_irqs(adapter); + return rc; + } + +@@ -1295,7 +1296,6 @@ static int ibmvnic_open(struct net_device *netdev) + rc = init_resources(adapter); + if (rc) { + netdev_err(netdev, "failed to initialize resources\n"); +- release_resources(adapter); + goto out; + } + } +@@ -1312,6 +1312,11 @@ out: + adapter->state = VNIC_OPEN; + rc = 0; + } ++ ++ if (rc) { ++ release_resources(adapter); ++ } ++ + return rc; + } + +@@ -1724,8 +1729,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) + ind_bufp = &tx_scrq->ind_buf; + + if (test_bit(0, &adapter->resetting)) { +- if (!netif_subqueue_stopped(netdev, skb)) +- netif_stop_subqueue(netdev, queue_num); + dev_kfree_skb_any(skb); + + tx_send_failed++; +@@ -2426,6 +2429,7 @@ static void __ibmvnic_reset(struct work_struct *work) + struct ibmvnic_rwi *rwi; + unsigned long flags; + u32 reset_state; ++ int num_fails = 0; + int rc = 0; + + adapter = container_of(work, struct ibmvnic_adapter, ibmvnic_reset); +@@ -2479,11 +2483,23 @@ static void __ibmvnic_reset(struct work_struct *work) + rc = do_hard_reset(adapter, rwi, reset_state); + rtnl_unlock(); + } +- if (rc) { +- /* give backing device time to settle down */ ++ if (rc) ++ num_fails++; ++ else ++ num_fails = 0; ++ ++ /* If auto-priority-failover is enabled we can get ++ * back to back failovers during resets, resulting ++ * in at least two failed resets (from high-priority ++ * backing device to low-priority one and then back) ++ * If resets continue to fail beyond that, give the ++ * adapter some time to settle down before retrying. ++ */ ++ if (num_fails >= 3) { + netdev_dbg(adapter->netdev, +- "[S:%s] Hard reset failed, waiting 60 secs\n", +- adapter_state_to_string(adapter->state)); ++ "[S:%s] Hard reset failed %d times, waiting 60 secs\n", ++ adapter_state_to_string(adapter->state), ++ num_fails); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(60 * HZ); + } +@@ -2541,12 +2557,23 @@ static void __ibmvnic_delayed_reset(struct work_struct *work) + __ibmvnic_reset(&adapter->ibmvnic_reset); + } + ++static void flush_reset_queue(struct ibmvnic_adapter *adapter) ++{ ++ struct list_head *entry, *tmp_entry; ++ ++ if (!list_empty(&adapter->rwi_list)) { ++ list_for_each_safe(entry, tmp_entry, &adapter->rwi_list) { ++ list_del(entry); ++ kfree(list_entry(entry, struct ibmvnic_rwi, list)); ++ } ++ } ++} ++ + static int ibmvnic_reset(struct ibmvnic_adapter *adapter, + enum ibmvnic_reset_reason reason) + { +- struct list_head *entry, *tmp_entry; +- struct ibmvnic_rwi *rwi, *tmp; + struct net_device *netdev = adapter->netdev; ++ struct ibmvnic_rwi *rwi, *tmp; + unsigned long flags; + int ret; + +@@ -2567,7 +2594,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, + + if (adapter->state == VNIC_PROBING) { + netdev_warn(netdev, "Adapter reset during probe\n"); +- adapter->init_done_rc = EAGAIN; ++ adapter->init_done_rc = -EAGAIN; + ret = EAGAIN; + goto err; + } +@@ -2589,10 +2616,9 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter, + /* if we just received a transport event, + * flush reset queue and process this reset + */ +- if (adapter->force_reset_recovery && !list_empty(&adapter->rwi_list)) { +- list_for_each_safe(entry, tmp_entry, &adapter->rwi_list) +- list_del(entry); +- } ++ if (adapter->force_reset_recovery) ++ flush_reset_queue(adapter); ++ + rwi->reset_reason = reason; + list_add_tail(&rwi->list, &adapter->rwi_list); + netdev_dbg(adapter->netdev, "Scheduling reset (reason %s)\n", +@@ -3664,11 +3690,25 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) + struct device *dev = &adapter->vdev->dev; + union ibmvnic_crq crq; + int max_entries; ++ int cap_reqs; ++ ++ /* We send out 6 or 7 REQUEST_CAPABILITY CRQs below (depending on ++ * the PROMISC flag). Initialize this count upfront. When the tasklet ++ * receives a response to all of these, it will send the next protocol ++ * message (QUERY_IP_OFFLOAD). ++ */ ++ if (!(adapter->netdev->flags & IFF_PROMISC) || ++ adapter->promisc_supported) ++ cap_reqs = 7; ++ else ++ cap_reqs = 6; + + if (!retry) { + /* Sub-CRQ entries are 32 byte long */ + int entries_page = 4 * PAGE_SIZE / (sizeof(u64) * 4); + ++ atomic_set(&adapter->running_cap_crqs, cap_reqs); ++ + if (adapter->min_tx_entries_per_subcrq > entries_page || + adapter->min_rx_add_entries_per_subcrq > entries_page) { + dev_err(dev, "Fatal, invalid entries per sub-crq\n"); +@@ -3729,44 +3769,45 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) + adapter->opt_rx_comp_queues; + + adapter->req_rx_add_queues = adapter->max_rx_add_queues; ++ } else { ++ atomic_add(cap_reqs, &adapter->running_cap_crqs); + } +- + memset(&crq, 0, sizeof(crq)); + crq.request_capability.first = IBMVNIC_CRQ_CMD; + crq.request_capability.cmd = REQUEST_CAPABILITY; + + crq.request_capability.capability = cpu_to_be16(REQ_TX_QUEUES); + crq.request_capability.number = cpu_to_be64(adapter->req_tx_queues); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + + crq.request_capability.capability = cpu_to_be16(REQ_RX_QUEUES); + crq.request_capability.number = cpu_to_be64(adapter->req_rx_queues); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + + crq.request_capability.capability = cpu_to_be16(REQ_RX_ADD_QUEUES); + crq.request_capability.number = cpu_to_be64(adapter->req_rx_add_queues); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + + crq.request_capability.capability = + cpu_to_be16(REQ_TX_ENTRIES_PER_SUBCRQ); + crq.request_capability.number = + cpu_to_be64(adapter->req_tx_entries_per_subcrq); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + + crq.request_capability.capability = + cpu_to_be16(REQ_RX_ADD_ENTRIES_PER_SUBCRQ); + crq.request_capability.number = + cpu_to_be64(adapter->req_rx_add_entries_per_subcrq); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + + crq.request_capability.capability = cpu_to_be16(REQ_MTU); + crq.request_capability.number = cpu_to_be64(adapter->req_mtu); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + + if (adapter->netdev->flags & IFF_PROMISC) { +@@ -3774,16 +3815,21 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) + crq.request_capability.capability = + cpu_to_be16(PROMISC_REQUESTED); + crq.request_capability.number = cpu_to_be64(1); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + } + } else { + crq.request_capability.capability = + cpu_to_be16(PROMISC_REQUESTED); + crq.request_capability.number = cpu_to_be64(0); +- atomic_inc(&adapter->running_cap_crqs); ++ cap_reqs--; + ibmvnic_send_crq(adapter, &crq); + } ++ ++ /* Keep at end to catch any discrepancy between expected and actual ++ * CRQs sent. ++ */ ++ WARN_ON(cap_reqs != 0); + } + + static int pending_scrq(struct ibmvnic_adapter *adapter, +@@ -4177,118 +4223,132 @@ static void send_query_map(struct ibmvnic_adapter *adapter) + static void send_query_cap(struct ibmvnic_adapter *adapter) + { + union ibmvnic_crq crq; ++ int cap_reqs; ++ ++ /* We send out 25 QUERY_CAPABILITY CRQs below. Initialize this count ++ * upfront. When the tasklet receives a response to all of these, it ++ * can send out the next protocol messaage (REQUEST_CAPABILITY). ++ */ ++ cap_reqs = 25; ++ ++ atomic_set(&adapter->running_cap_crqs, cap_reqs); + +- atomic_set(&adapter->running_cap_crqs, 0); + memset(&crq, 0, sizeof(crq)); + crq.query_capability.first = IBMVNIC_CRQ_CMD; + crq.query_capability.cmd = QUERY_CAPABILITY; + + crq.query_capability.capability = cpu_to_be16(MIN_TX_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MIN_RX_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MIN_RX_ADD_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MAX_TX_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MAX_RX_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MAX_RX_ADD_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(MIN_TX_ENTRIES_PER_SUBCRQ); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(MIN_RX_ADD_ENTRIES_PER_SUBCRQ); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(MAX_TX_ENTRIES_PER_SUBCRQ); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(MAX_RX_ADD_ENTRIES_PER_SUBCRQ); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(TCP_IP_OFFLOAD); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(PROMISC_SUPPORTED); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MIN_MTU); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MAX_MTU); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MAX_MULTICAST_FILTERS); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(VLAN_HEADER_INSERTION); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(RX_VLAN_HEADER_INSERTION); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(MAX_TX_SG_ENTRIES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(RX_SG_SUPPORTED); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(OPT_TX_COMP_SUB_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(OPT_RX_COMP_QUEUES); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(OPT_RX_BUFADD_Q_PER_RX_COMP_Q); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(OPT_TX_ENTRIES_PER_SUBCRQ); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = + cpu_to_be16(OPT_RXBA_ENTRIES_PER_SUBCRQ); +- atomic_inc(&adapter->running_cap_crqs); + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; + + crq.query_capability.capability = cpu_to_be16(TX_RX_DESC_REQ); +- atomic_inc(&adapter->running_cap_crqs); ++ + ibmvnic_send_crq(adapter, &crq); ++ cap_reqs--; ++ ++ /* Keep at end to catch any discrepancy between expected and actual ++ * CRQs sent. ++ */ ++ WARN_ON(cap_reqs != 0); + } + + static void send_query_ip_offload(struct ibmvnic_adapter *adapter) +@@ -4593,6 +4653,8 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq, + char *name; + + atomic_dec(&adapter->running_cap_crqs); ++ netdev_dbg(adapter->netdev, "Outstanding request-caps: %d\n", ++ atomic_read(&adapter->running_cap_crqs)); + switch (be16_to_cpu(crq->request_capability_rsp.capability)) { + case REQ_TX_QUEUES: + req_value = &adapter->req_tx_queues; +@@ -5069,11 +5131,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, + */ + adapter->login_pending = false; + +- if (!completion_done(&adapter->init_done)) { +- complete(&adapter->init_done); +- adapter->init_done_rc = -EIO; +- } +- + if (adapter->state == VNIC_DOWN) + rc = ibmvnic_reset(adapter, VNIC_RESET_PASSIVE_INIT); + else +@@ -5094,6 +5151,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, + rc); + adapter->failover_pending = false; + } ++ ++ if (!completion_done(&adapter->init_done)) { ++ if (!adapter->init_done_rc) ++ adapter->init_done_rc = -EAGAIN; ++ complete(&adapter->init_done); ++ } ++ + break; + case IBMVNIC_CRQ_INIT_COMPLETE: + dev_info(dev, "Partner initialization complete\n"); +@@ -5114,6 +5178,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, + adapter->fw_done_rc = -EIO; + complete(&adapter->fw_done); + } ++ ++ /* if we got here during crq-init, retry crq-init */ ++ if (!completion_done(&adapter->init_done)) { ++ adapter->init_done_rc = -EAGAIN; ++ complete(&adapter->init_done); ++ } ++ + if (!completion_done(&adapter->stats_done)) + complete(&adapter->stats_done); + if (test_bit(0, &adapter->resetting)) +@@ -5268,12 +5339,6 @@ static void ibmvnic_tasklet(struct tasklet_struct *t) + ibmvnic_handle_crq(crq, adapter); + crq->generic.first = 0; + } +- +- /* remain in tasklet until all +- * capabilities responses are received +- */ +- if (!adapter->wait_capability) +- done = true; + } + /* if capabilities CRQ's were sent in this tasklet, the following + * tasklet must wait until all responses are received +@@ -5414,6 +5479,9 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) + crq->cur = 0; + spin_lock_init(&crq->lock); + ++ /* process any CRQs that were queued before we enabled interrupts */ ++ tasklet_schedule(&adapter->tasklet); ++ + return retrc; + + req_irq_failed: +@@ -5558,7 +5626,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) + } + + rc = ibmvnic_reset_init(adapter, false); +- } while (rc == EAGAIN); ++ } while (rc == -EAGAIN); + + /* We are ignoring the error from ibmvnic_reset_init() assuming that the + * partner is not ready. CRQ is not active. When the partner becomes +@@ -5581,12 +5649,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) + goto ibmvnic_dev_file_err; + + netif_carrier_off(netdev); +- rc = register_netdev(netdev); +- if (rc) { +- dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc); +- goto ibmvnic_register_fail; +- } +- dev_info(&dev->dev, "ibmvnic registered\n"); + + if (init_success) { + adapter->state = VNIC_PROBED; +@@ -5599,6 +5661,14 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) + + adapter->wait_for_reset = false; + adapter->last_reset_time = jiffies; ++ ++ rc = register_netdev(netdev); ++ if (rc) { ++ dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc); ++ goto ibmvnic_register_fail; ++ } ++ dev_info(&dev->dev, "ibmvnic registered\n"); ++ + return 0; + + ibmvnic_register_fail: +@@ -5687,10 +5757,14 @@ static ssize_t failover_store(struct device *dev, struct device_attribute *attr, + be64_to_cpu(session_token)); + rc = plpar_hcall_norets(H_VIOCTL, adapter->vdev->unit_address, + H_SESSION_ERR_DETECTED, session_token, 0, 0); +- if (rc) ++ if (rc) { + netdev_err(netdev, + "H_VIOCTL initiated failover failed, rc %ld\n", + rc); ++ goto last_resort; ++ } ++ ++ return count; + + last_resort: + netdev_dbg(netdev, "Trying to send CRQ_CMD, the last resort\n"); +diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c +index 09ae1939e6db4..36d52246bdc66 100644 +--- a/drivers/net/ethernet/intel/e100.c ++++ b/drivers/net/ethernet/intel/e100.c +@@ -3003,9 +3003,10 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev_priv(netdev); + ++ netif_device_detach(netdev); ++ + if (netif_running(netdev)) + e100_down(nic); +- netif_device_detach(netdev); + + if ((nic->flags & wol_magic) | e100_asf(nic)) { + /* enable reverse auto-negotiation */ +@@ -3022,7 +3023,7 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) + *enable_wake = false; + } + +- pci_clear_master(pdev); ++ pci_disable_device(pdev); + } + + static int __e100_power_off(struct pci_dev *pdev, bool wake) +@@ -3042,8 +3043,6 @@ static int __maybe_unused e100_suspend(struct device *dev_d) + + __e100_shutdown(to_pci_dev(dev_d), &wake); + +- device_wakeup_disable(dev_d); +- + return 0; + } + +@@ -3051,6 +3050,14 @@ static int __maybe_unused e100_resume(struct device *dev_d) + { + struct net_device *netdev = dev_get_drvdata(dev_d); + struct nic *nic = netdev_priv(netdev); ++ int err; ++ ++ err = pci_enable_device(to_pci_dev(dev_d)); ++ if (err) { ++ netdev_err(netdev, "Resume cannot enable PCI device, aborting\n"); ++ return err; ++ } ++ pci_set_master(to_pci_dev(dev_d)); + + /* disable reverse auto-negotiation */ + if (nic->phy == phy_82552_v) { +@@ -3062,10 +3069,11 @@ static int __maybe_unused e100_resume(struct device *dev_d) + smartspeed & ~(E100_82552_REV_ANEG)); + } + +- netif_device_attach(netdev); + if (netif_running(netdev)) + e100_up(nic); + ++ netif_device_attach(netdev); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h +index 3178efd980066..eb6961d901c16 100644 +--- a/drivers/net/ethernet/intel/e1000e/e1000.h ++++ b/drivers/net/ethernet/intel/e1000e/e1000.h +@@ -114,7 +114,8 @@ enum e1000_boards { + board_pch_lpt, + board_pch_spt, + board_pch_cnp, +- board_pch_tgp ++ board_pch_tgp, ++ board_pch_adp + }; + + struct e1000_ps_page { +@@ -501,6 +502,7 @@ extern const struct e1000_info e1000_pch_lpt_info; + extern const struct e1000_info e1000_pch_spt_info; + extern const struct e1000_info e1000_pch_cnp_info; + extern const struct e1000_info e1000_pch_tgp_info; ++extern const struct e1000_info e1000_pch_adp_info; + extern const struct e1000_info e1000_es2_info; + + void e1000e_ptp_init(struct e1000_adapter *adapter); +diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h +index bcf680e838113..13382df2f2eff 100644 +--- a/drivers/net/ethernet/intel/e1000e/hw.h ++++ b/drivers/net/ethernet/intel/e1000e/hw.h +@@ -630,6 +630,7 @@ struct e1000_phy_info { + bool disable_polarity_correction; + bool is_mdix; + bool polarity_correction; ++ bool reset_disable; + bool speed_downgraded; + bool autoneg_wait_to_complete; + }; +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c +index 5e4fc9b4e2adb..d60e2016d03c6 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c +@@ -2050,6 +2050,10 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) + bool blocked = false; + int i = 0; + ++ /* Check the PHY (LCD) reset flag */ ++ if (hw->phy.reset_disable) ++ return true; ++ + while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) && + (i++ < 30)) + usleep_range(10000, 11000); +@@ -4136,9 +4140,9 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) + return ret_val; + + if (!(data & valid_csum_mask)) { +- e_dbg("NVM Checksum Invalid\n"); ++ e_dbg("NVM Checksum valid bit not set\n"); + +- if (hw->mac.type < e1000_pch_cnp) { ++ if (hw->mac.type < e1000_pch_tgp) { + data |= valid_csum_mask; + ret_val = e1000_write_nvm(hw, word, 1, &data); + if (ret_val) +@@ -6021,3 +6025,23 @@ const struct e1000_info e1000_pch_tgp_info = { + .phy_ops = &ich8_phy_ops, + .nvm_ops = &spt_nvm_ops, + }; ++ ++const struct e1000_info e1000_pch_adp_info = { ++ .mac = e1000_pch_adp, ++ .flags = FLAG_IS_ICH ++ | FLAG_HAS_WOL ++ | FLAG_HAS_HW_TIMESTAMP ++ | FLAG_HAS_CTRLEXT_ON_LOAD ++ | FLAG_HAS_AMT ++ | FLAG_HAS_FLASH ++ | FLAG_HAS_JUMBO_FRAMES ++ | FLAG_APME_IN_WUC, ++ .flags2 = FLAG2_HAS_PHY_STATS ++ | FLAG2_HAS_EEE, ++ .pba = 26, ++ .max_hw_frame_size = 9022, ++ .get_variants = e1000_get_variants_ich8lan, ++ .mac_ops = &ich8_mac_ops, ++ .phy_ops = &ich8_phy_ops, ++ .nvm_ops = &spt_nvm_ops, ++}; +diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h +index 2504b11c3169f..638a3ddd7ada8 100644 +--- a/drivers/net/ethernet/intel/e1000e/ich8lan.h ++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h +@@ -271,6 +271,7 @@ + #define I217_CGFREG_ENABLE_MTA_RESET 0x0002 + #define I217_MEMPWR PHY_REG(772, 26) + #define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 ++#define I217_MEMPWR_MOEM 0x1000 + + /* Receive Address Initial CRC Calculation */ + #define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) +diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c +index ebcb2a30add09..ce48e630fe550 100644 +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -52,6 +52,7 @@ static const struct e1000_info *e1000_info_tbl[] = { + [board_pch_spt] = &e1000_pch_spt_info, + [board_pch_cnp] = &e1000_pch_cnp_info, + [board_pch_tgp] = &e1000_pch_tgp_info, ++ [board_pch_adp] = &e1000_pch_adp_info, + }; + + struct e1000_reg_info { +@@ -6346,7 +6347,8 @@ static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter) + u32 mac_data; + u16 phy_data; + +- if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { ++ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID && ++ hw->mac.type >= e1000_pch_adp) { + /* Request ME configure the device for S0ix */ + mac_data = er32(H2ME); + mac_data |= E1000_H2ME_START_DPG; +@@ -6495,7 +6497,8 @@ static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter) + u16 phy_data; + u32 i = 0; + +- if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { ++ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID && ++ hw->mac.type >= e1000_pch_adp) { + /* Request ME unconfigure the device from S0ix */ + mac_data = er32(H2ME); + mac_data &= ~E1000_H2ME_START_DPG; +@@ -6989,8 +6992,21 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev) + struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = to_pci_dev(dev); ++ struct e1000_hw *hw = &adapter->hw; ++ u16 phy_data; + int rc; + ++ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID && ++ hw->mac.type >= e1000_pch_adp) { ++ /* Mask OEM Bits / Gig Disable / Restart AN (772_26[12] = 1) */ ++ e1e_rphy(hw, I217_MEMPWR, &phy_data); ++ phy_data |= I217_MEMPWR_MOEM; ++ e1e_wphy(hw, I217_MEMPWR, phy_data); ++ ++ /* Disable LCD reset */ ++ hw->phy.reset_disable = true; ++ } ++ + e1000e_flush_lpic(pdev); + + e1000e_pm_freeze(dev); +@@ -7012,6 +7028,8 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev) + struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); + struct e1000_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = to_pci_dev(dev); ++ struct e1000_hw *hw = &adapter->hw; ++ u16 phy_data; + int rc; + + /* Introduce S0ix implementation */ +@@ -7022,6 +7040,17 @@ static __maybe_unused int e1000e_pm_resume(struct device *dev) + if (rc) + return rc; + ++ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID && ++ hw->mac.type >= e1000_pch_adp) { ++ /* Unmask OEM Bits / Gig Disable / Restart AN 772_26[12] = 0 */ ++ e1e_rphy(hw, I217_MEMPWR, &phy_data); ++ phy_data &= ~I217_MEMPWR_MOEM; ++ e1e_wphy(hw, I217_MEMPWR, phy_data); ++ ++ /* Enable LCD reset */ ++ hw->phy.reset_disable = false; ++ } ++ + return e1000e_pm_thaw(dev); + } + +@@ -7903,22 +7932,22 @@ static const struct pci_device_id e1000_pci_tbl[] = { + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_TGP_I219_V14), board_pch_tgp }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_TGP_I219_LM15), board_pch_tgp }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_TGP_I219_V15), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_LM23), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_V23), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_LM16), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_V16), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_LM17), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_V17), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_LM22), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_V22), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_LM18), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_V18), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_LM19), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_V19), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_LM20), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_V20), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_LM21), board_pch_tgp }, +- { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_V21), board_pch_tgp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_LM23), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_V23), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_LM16), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_V16), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_LM17), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ADP_I219_V17), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_LM22), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_RPL_I219_V22), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_LM18), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_V18), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_LM19), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_MTP_I219_V19), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_LM20), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_V20), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_LM21), board_pch_adp }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LNP_I219_V21), board_pch_adp }, + + { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ + }; +diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h +index 39fb3d57c0574..56a3a6d1dbe41 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e.h ++++ b/drivers/net/ethernet/intel/i40e/i40e.h +@@ -144,6 +144,7 @@ enum i40e_state_t { + __I40E_VIRTCHNL_OP_PENDING, + __I40E_RECOVERY_MODE, + __I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */ ++ __I40E_IN_REMOVE, + __I40E_VFS_RELEASING, + /* This must be last as it determines the size of the BITMAP */ + __I40E_STATE_SIZE__, +@@ -161,6 +162,7 @@ enum i40e_vsi_state_t { + __I40E_VSI_OVERFLOW_PROMISC, + __I40E_VSI_REINIT_REQUESTED, + __I40E_VSI_DOWN_REQUESTED, ++ __I40E_VSI_RELEASING, + /* This must be last as it determines the size of the BITMAP */ + __I40E_VSI_STATE_SIZE__, + }; +@@ -173,7 +175,6 @@ enum i40e_interrupt_policy { + + struct i40e_lump_tracking { + u16 num_entries; +- u16 search_hint; + u16 list[0]; + #define I40E_PILE_VALID_BIT 0x8000 + #define I40E_IWARP_IRQ_PILE_ID (I40E_PILE_VALID_BIT - 2) +@@ -847,12 +848,12 @@ struct i40e_vsi { + struct rtnl_link_stats64 net_stats_offsets; + struct i40e_eth_stats eth_stats; + struct i40e_eth_stats eth_stats_offsets; +- u32 tx_restart; +- u32 tx_busy; ++ u64 tx_restart; ++ u64 tx_busy; + u64 tx_linearize; + u64 tx_force_wb; +- u32 rx_buf_failed; +- u32 rx_page_failed; ++ u64 rx_buf_failed; ++ u64 rx_page_failed; + + /* These are containers of ring pointers, allocated at run-time */ + struct i40e_ring **rx_rings; +@@ -1247,6 +1248,7 @@ void i40e_ptp_restore_hw_time(struct i40e_pf *pf); + void i40e_ptp_init(struct i40e_pf *pf); + void i40e_ptp_stop(struct i40e_pf *pf); + int i40e_ptp_alloc_pins(struct i40e_pf *pf); ++int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset); + int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi); + i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf); + i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf); +diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +index 291e61ac3e448..1e57cc8c47d7b 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +@@ -240,7 +240,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) + (unsigned long int)vsi->net_stats_offsets.rx_compressed, + (unsigned long int)vsi->net_stats_offsets.tx_compressed); + dev_info(&pf->pdev->dev, +- " tx_restart = %d, tx_busy = %d, rx_buf_failed = %d, rx_page_failed = %d\n", ++ " tx_restart = %llu, tx_busy = %llu, rx_buf_failed = %llu, rx_page_failed = %llu\n", + vsi->tx_restart, vsi->tx_busy, + vsi->rx_buf_failed, vsi->rx_page_failed); + rcu_read_lock(); +@@ -553,6 +553,14 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, + dev_info(&pf->pdev->dev, "vsi %d not found\n", vsi_seid); + return; + } ++ if (vsi->type != I40E_VSI_MAIN && ++ vsi->type != I40E_VSI_FDIR && ++ vsi->type != I40E_VSI_VMDQ2) { ++ dev_info(&pf->pdev->dev, ++ "vsi %d type %d descriptor rings not available\n", ++ vsi_seid, vsi->type); ++ return; ++ } + if (type == RING_TYPE_XDP && !i40e_enabled_xdp_vsi(vsi)) { + dev_info(&pf->pdev->dev, "XDP not enabled on VSI %d\n", vsi_seid); + return; +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index e04b540cedc85..ad73dd2540e71 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -99,6 +99,24 @@ MODULE_LICENSE("GPL v2"); + + static struct workqueue_struct *i40e_wq; + ++static void netdev_hw_addr_refcnt(struct i40e_mac_filter *f, ++ struct net_device *netdev, int delta) ++{ ++ struct netdev_hw_addr *ha; ++ ++ if (!f || !netdev) ++ return; ++ ++ netdev_for_each_mc_addr(ha, netdev) { ++ if (ether_addr_equal(ha->addr, f->macaddr)) { ++ ha->refcount += delta; ++ if (ha->refcount <= 0) ++ ha->refcount = 1; ++ break; ++ } ++ } ++} ++ + /** + * i40e_allocate_dma_mem_d - OS specific memory alloc for shared code + * @hw: pointer to the HW structure +@@ -178,10 +196,6 @@ int i40e_free_virt_mem_d(struct i40e_hw *hw, struct i40e_virt_mem *mem) + * @id: an owner id to stick on the items assigned + * + * Returns the base item index of the lump, or negative for error +- * +- * The search_hint trick and lack of advanced fit-finding only work +- * because we're highly likely to have all the same size lump requests. +- * Linear search time and any fragmentation should be minimal. + **/ + static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile, + u16 needed, u16 id) +@@ -196,8 +210,21 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile, + return -EINVAL; + } + +- /* start the linear search with an imperfect hint */ +- i = pile->search_hint; ++ /* Allocate last queue in the pile for FDIR VSI queue ++ * so it doesn't fragment the qp_pile ++ */ ++ if (pile == pf->qp_pile && pf->vsi[id]->type == I40E_VSI_FDIR) { ++ if (pile->list[pile->num_entries - 1] & I40E_PILE_VALID_BIT) { ++ dev_err(&pf->pdev->dev, ++ "Cannot allocate queue %d for I40E_VSI_FDIR\n", ++ pile->num_entries - 1); ++ return -ENOMEM; ++ } ++ pile->list[pile->num_entries - 1] = id | I40E_PILE_VALID_BIT; ++ return pile->num_entries - 1; ++ } ++ ++ i = 0; + while (i < pile->num_entries) { + /* skip already allocated entries */ + if (pile->list[i] & I40E_PILE_VALID_BIT) { +@@ -216,7 +243,6 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile, + for (j = 0; j < needed; j++) + pile->list[i+j] = id | I40E_PILE_VALID_BIT; + ret = i; +- pile->search_hint = i + j; + break; + } + +@@ -239,7 +265,7 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id) + { + int valid_id = (id | I40E_PILE_VALID_BIT); + int count = 0; +- int i; ++ u16 i; + + if (!pile || index >= pile->num_entries) + return -EINVAL; +@@ -251,8 +277,6 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id) + count++; + } + +- if (count && index < pile->search_hint) +- pile->search_hint = index; + + return count; + } +@@ -754,9 +778,9 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) + struct rtnl_link_stats64 *ns; /* netdev stats */ + struct i40e_eth_stats *oes; + struct i40e_eth_stats *es; /* device's eth stats */ +- u32 tx_restart, tx_busy; ++ u64 tx_restart, tx_busy; + struct i40e_ring *p; +- u32 rx_page, rx_buf; ++ u64 rx_page, rx_buf; + u64 bytes, packets; + unsigned int start; + u64 tx_linearize; +@@ -1790,6 +1814,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, + bool is_add) + { + struct i40e_pf *pf = vsi->back; ++ u16 num_tc_qps = 0; + u16 sections = 0; + u8 netdev_tc = 0; + u16 numtc = 1; +@@ -1797,13 +1822,33 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, + u8 offset; + u16 qmap; + int i; +- u16 num_tc_qps = 0; + + sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID; + offset = 0; ++ /* zero out queue mapping, it will get updated on the end of the function */ ++ memset(ctxt->info.queue_mapping, 0, sizeof(ctxt->info.queue_mapping)); ++ ++ if (vsi->type == I40E_VSI_MAIN) { ++ /* This code helps add more queue to the VSI if we have ++ * more cores than RSS can support, the higher cores will ++ * be served by ATR or other filters. Furthermore, the ++ * non-zero req_queue_pairs says that user requested a new ++ * queue count via ethtool's set_channels, so use this ++ * value for queues distribution across traffic classes ++ */ ++ if (vsi->req_queue_pairs > 0) ++ vsi->num_queue_pairs = vsi->req_queue_pairs; ++ else if (pf->flags & I40E_FLAG_MSIX_ENABLED) ++ vsi->num_queue_pairs = pf->num_lan_msix; ++ } + + /* Number of queues per enabled TC */ +- num_tc_qps = vsi->alloc_queue_pairs; ++ if (vsi->type == I40E_VSI_MAIN || ++ (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs != 0)) ++ num_tc_qps = vsi->num_queue_pairs; ++ else ++ num_tc_qps = vsi->alloc_queue_pairs; ++ + if (enabled_tc && (vsi->back->flags & I40E_FLAG_DCB_ENABLED)) { + /* Find numtc from enabled TC bitmap */ + for (i = 0, numtc = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { +@@ -1881,15 +1926,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, + } + ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); + } +- +- /* Set actual Tx/Rx queue pairs */ +- vsi->num_queue_pairs = offset; +- if ((vsi->type == I40E_VSI_MAIN) && (numtc == 1)) { +- if (vsi->req_queue_pairs > 0) +- vsi->num_queue_pairs = vsi->req_queue_pairs; +- else if (pf->flags & I40E_FLAG_MSIX_ENABLED) +- vsi->num_queue_pairs = pf->num_lan_msix; +- } ++ /* Do not change previously set num_queue_pairs for PFs and VFs*/ ++ if ((vsi->type == I40E_VSI_MAIN && numtc != 1) || ++ (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs == 0) || ++ (vsi->type != I40E_VSI_MAIN && vsi->type != I40E_VSI_SRIOV)) ++ vsi->num_queue_pairs = offset; + + /* Scheduler section valid can only be set for ADD VSI */ + if (is_add) { +@@ -2019,6 +2060,7 @@ static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi, + hlist_for_each_entry_safe(new, h, from, hlist) { + /* We can simply free the wrapper structure */ + hlist_del(&new->hlist); ++ netdev_hw_addr_refcnt(new->f, vsi->netdev, -1); + kfree(new); + } + } +@@ -2366,6 +2408,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) + &tmp_add_list, + &tmp_del_list, + vlan_filters); ++ ++ hlist_for_each_entry(new, &tmp_add_list, hlist) ++ netdev_hw_addr_refcnt(new->f, vsi->netdev, 1); ++ + if (retval) + goto err_no_memory_locked; + +@@ -2498,6 +2544,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) + if (new->f->state == I40E_FILTER_NEW) + new->f->state = new->state; + hlist_del(&new->hlist); ++ netdev_hw_addr_refcnt(new->f, vsi->netdev, -1); + kfree(new); + } + spin_unlock_bh(&vsi->mac_filter_hash_lock); +@@ -2623,7 +2670,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) + + for (v = 0; v < pf->num_alloc_vsi; v++) { + if (pf->vsi[v] && +- (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) { ++ (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED) && ++ !test_bit(__I40E_VSI_RELEASING, pf->vsi[v]->state)) { + int ret = i40e_sync_vsi_filters(pf->vsi[v]); + + if (ret) { +@@ -5426,6 +5474,58 @@ static void i40e_vsi_update_queue_map(struct i40e_vsi *vsi, + sizeof(vsi->info.tc_mapping)); + } + ++/** ++ * i40e_update_adq_vsi_queues - update queue mapping for ADq VSI ++ * @vsi: the VSI being reconfigured ++ * @vsi_offset: offset from main VF VSI ++ */ ++int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset) ++{ ++ struct i40e_vsi_context ctxt = {}; ++ struct i40e_pf *pf; ++ struct i40e_hw *hw; ++ int ret; ++ ++ if (!vsi) ++ return I40E_ERR_PARAM; ++ pf = vsi->back; ++ hw = &pf->hw; ++ ++ ctxt.seid = vsi->seid; ++ ctxt.pf_num = hw->pf_id; ++ ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id + vsi_offset; ++ ctxt.uplink_seid = vsi->uplink_seid; ++ ctxt.connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL; ++ ctxt.flags = I40E_AQ_VSI_TYPE_VF; ++ ctxt.info = vsi->info; ++ ++ i40e_vsi_setup_queue_map(vsi, &ctxt, vsi->tc_config.enabled_tc, ++ false); ++ if (vsi->reconfig_rss) { ++ vsi->rss_size = min_t(int, pf->alloc_rss_size, ++ vsi->num_queue_pairs); ++ ret = i40e_vsi_config_rss(vsi); ++ if (ret) { ++ dev_info(&pf->pdev->dev, "Failed to reconfig rss for num_queues\n"); ++ return ret; ++ } ++ vsi->reconfig_rss = false; ++ } ++ ++ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); ++ if (ret) { ++ dev_info(&pf->pdev->dev, "Update vsi config failed, err %s aq_err %s\n", ++ i40e_stat_str(hw, ret), ++ i40e_aq_str(hw, hw->aq.asq_last_status)); ++ return ret; ++ } ++ /* update the local VSI info with updated queue map */ ++ i40e_vsi_update_queue_map(vsi, &ctxt); ++ vsi->info.valid_sections = 0; ++ ++ return ret; ++} ++ + /** + * i40e_vsi_config_tc - Configure VSI Tx Scheduler for given TC map + * @vsi: VSI to be configured +@@ -5716,24 +5816,6 @@ static void i40e_remove_queue_channels(struct i40e_vsi *vsi) + INIT_LIST_HEAD(&vsi->ch_list); + } + +-/** +- * i40e_is_any_channel - channel exist or not +- * @vsi: ptr to VSI to which channels are associated with +- * +- * Returns true or false if channel(s) exist for associated VSI or not +- **/ +-static bool i40e_is_any_channel(struct i40e_vsi *vsi) +-{ +- struct i40e_channel *ch, *ch_tmp; +- +- list_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) { +- if (ch->initialized) +- return true; +- } +- +- return false; +-} +- + /** + * i40e_get_max_queues_for_channel + * @vsi: ptr to VSI to which channels are associated with +@@ -6240,26 +6322,15 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi, + /* By default we are in VEPA mode, if this is the first VF/VMDq + * VSI to be added switch to VEB mode. + */ +- if ((!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) || +- (!i40e_is_any_channel(vsi))) { +- if (!is_power_of_2(vsi->tc_config.tc_info[0].qcount)) { +- dev_dbg(&pf->pdev->dev, +- "Failed to create channel. Override queues (%u) not power of 2\n", +- vsi->tc_config.tc_info[0].qcount); +- return -EINVAL; +- } + +- if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) { +- pf->flags |= I40E_FLAG_VEB_MODE_ENABLED; ++ if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) { ++ pf->flags |= I40E_FLAG_VEB_MODE_ENABLED; + +- if (vsi->type == I40E_VSI_MAIN) { +- if (pf->flags & I40E_FLAG_TC_MQPRIO) +- i40e_do_reset(pf, I40E_PF_RESET_FLAG, +- true); +- else +- i40e_do_reset_safe(pf, +- I40E_PF_RESET_FLAG); +- } ++ if (vsi->type == I40E_VSI_MAIN) { ++ if (pf->flags & I40E_FLAG_TC_MQPRIO) ++ i40e_do_reset(pf, I40E_PF_RESET_FLAG, true); ++ else ++ i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG); + } + /* now onwards for main VSI, number of queues will be value + * of TC0's queue count +@@ -7912,12 +7983,20 @@ config_tc: + vsi->seid); + need_reset = true; + goto exit; +- } else { +- dev_info(&vsi->back->pdev->dev, +- "Setup channel (id:%u) utilizing num_queues %d\n", +- vsi->seid, vsi->tc_config.tc_info[0].qcount); ++ } else if (enabled_tc && ++ (!is_power_of_2(vsi->tc_config.tc_info[0].qcount))) { ++ netdev_info(netdev, ++ "Failed to create channel. Override queues (%u) not power of 2\n", ++ vsi->tc_config.tc_info[0].qcount); ++ ret = -EINVAL; ++ need_reset = true; ++ goto exit; + } + ++ dev_info(&vsi->back->pdev->dev, ++ "Setup channel (id:%u) utilizing num_queues %d\n", ++ vsi->seid, vsi->tc_config.tc_info[0].qcount); ++ + if (pf->flags & I40E_FLAG_TC_MQPRIO) { + if (vsi->mqprio_qopt.max_rate[0]) { + u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0]; +@@ -8482,9 +8561,8 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi, + err = i40e_add_del_cloud_filter(vsi, filter, true); + + if (err) { +- dev_err(&pf->pdev->dev, +- "Failed to add cloud filter, err %s\n", +- i40e_stat_str(&pf->hw, err)); ++ dev_err(&pf->pdev->dev, "Failed to add cloud filter, err %d\n", ++ err); + goto err; + } + +@@ -8668,6 +8746,27 @@ int i40e_open(struct net_device *netdev) + return 0; + } + ++/** ++ * i40e_netif_set_realnum_tx_rx_queues - Update number of tx/rx queues ++ * @vsi: vsi structure ++ * ++ * This updates netdev's number of tx/rx queues ++ * ++ * Returns status of setting tx/rx queues ++ **/ ++static int i40e_netif_set_realnum_tx_rx_queues(struct i40e_vsi *vsi) ++{ ++ int ret; ++ ++ ret = netif_set_real_num_rx_queues(vsi->netdev, ++ vsi->num_queue_pairs); ++ if (ret) ++ return ret; ++ ++ return netif_set_real_num_tx_queues(vsi->netdev, ++ vsi->num_queue_pairs); ++} ++ + /** + * i40e_vsi_open - + * @vsi: the VSI to open +@@ -8704,13 +8803,7 @@ int i40e_vsi_open(struct i40e_vsi *vsi) + goto err_setup_rx; + + /* Notify the stack of the actual queue counts. */ +- err = netif_set_real_num_tx_queues(vsi->netdev, +- vsi->num_queue_pairs); +- if (err) +- goto err_set_queues; +- +- err = netif_set_real_num_rx_queues(vsi->netdev, +- vsi->num_queue_pairs); ++ err = i40e_netif_set_realnum_tx_rx_queues(vsi); + if (err) + goto err_set_queues; + +@@ -10487,15 +10580,9 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) + } + i40e_get_oem_version(&pf->hw); + +- if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) && +- ((hw->aq.fw_maj_ver == 4 && hw->aq.fw_min_ver <= 33) || +- hw->aq.fw_maj_ver < 4) && hw->mac.type == I40E_MAC_XL710) { +- /* The following delay is necessary for 4.33 firmware and older +- * to recover after EMP reset. 200 ms should suffice but we +- * put here 300 ms to be sure that FW is ready to operate +- * after reset. +- */ +- mdelay(300); ++ if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state)) { ++ /* The following delay is necessary for firmware update. */ ++ mdelay(1000); + } + + /* re-verify the eeprom if we just had an EMP reset */ +@@ -10766,6 +10853,9 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit, + bool lock_acquired) + { + int ret; ++ ++ if (test_bit(__I40E_IN_REMOVE, pf->state)) ++ return; + /* Now we wait for GRST to settle out. + * We don't have to delete the VEBs or VSIs from the hw switch + * because the reset will make them disappear. +@@ -11705,7 +11795,6 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf) + return -ENOMEM; + + pf->irq_pile->num_entries = vectors; +- pf->irq_pile->search_hint = 0; + + /* track first vector for misc interrupts, ignore return */ + (void)i40e_get_lump(pf, pf->irq_pile, 1, I40E_PILE_VALID_BIT - 1); +@@ -12126,6 +12215,8 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count) + + vsi->req_queue_pairs = queue_count; + i40e_prep_for_reset(pf); ++ if (test_bit(__I40E_IN_REMOVE, pf->state)) ++ return pf->alloc_rss_size; + + pf->alloc_rss_size = new_rss_size; + +@@ -12508,7 +12599,6 @@ static int i40e_sw_init(struct i40e_pf *pf) + goto sw_init_done; + } + pf->qp_pile->num_entries = pf->hw.func_caps.num_tx_qp; +- pf->qp_pile->search_hint = 0; + + pf->tx_timeout_recovery_level = 1; + +@@ -12953,6 +13043,10 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog, + if (need_reset) + i40e_prep_for_reset(pf); + ++ /* VSI shall be deleted in a moment, just return EINVAL */ ++ if (test_bit(__I40E_IN_REMOVE, pf->state)) ++ return -EINVAL; ++ + old_prog = xchg(&vsi->xdp_prog, prog); + + if (need_reset) { +@@ -13771,7 +13865,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) + dev_info(&pf->pdev->dev, "Can't remove PF VSI\n"); + return -ENODEV; + } +- ++ set_bit(__I40E_VSI_RELEASING, vsi->state); + uplink_seid = vsi->uplink_seid; + if (vsi->type != I40E_VSI_SRIOV) { + if (vsi->netdev_registered) { +@@ -14101,6 +14195,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, + case I40E_VSI_MAIN: + case I40E_VSI_VMDQ2: + ret = i40e_config_netdev(vsi); ++ if (ret) ++ goto err_netdev; ++ ret = i40e_netif_set_realnum_tx_rx_queues(vsi); + if (ret) + goto err_netdev; + ret = register_netdev(vsi->netdev); +@@ -15403,8 +15500,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && + hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw)) +- dev_info(&pdev->dev, +- "The driver for the device detected a newer version of the NVM image v%u.%u than expected v%u.%u. Please install the most recent version of the network driver.\n", ++ dev_dbg(&pdev->dev, ++ "The driver for the device detected a newer version of the NVM image v%u.%u than v%u.%u.\n", + hw->aq.api_maj_ver, + hw->aq.api_min_ver, + I40E_FW_API_VERSION_MAJOR, +@@ -15840,8 +15937,13 @@ static void i40e_remove(struct pci_dev *pdev) + i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0); + i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0); + +- while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) ++ /* Grab __I40E_RESET_RECOVERY_PENDING and set __I40E_IN_REMOVE ++ * flags, once they are set, i40e_rebuild should not be called as ++ * i40e_prep_for_reset always returns early. ++ */ ++ while (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) + usleep_range(1000, 2000); ++ set_bit(__I40E_IN_REMOVE, pf->state); + + if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { + set_bit(__I40E_VF_RESETS_DISABLED, pf->state); +@@ -16040,6 +16142,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev) + { + struct i40e_pf *pf = pci_get_drvdata(pdev); + ++ if (test_bit(__I40E_IN_REMOVE, pf->state)) ++ return; ++ + i40e_reset_and_rebuild(pf, false, false); + } + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h +index 8d0588a27a053..1908eed4fa5ee 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_register.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_register.h +@@ -413,6 +413,9 @@ + #define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */ + #define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1 + #define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT) ++#define I40E_VFINT_ICR0_ADMINQ_SHIFT 30 ++#define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT) ++#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ + #define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ + #define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0 + #define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11 +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +index 472f56b360b8c..c6f643e54c4f7 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +@@ -183,17 +183,18 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf) + /***********************misc routines*****************************/ + + /** +- * i40e_vc_disable_vf ++ * i40e_vc_reset_vf + * @vf: pointer to the VF info +- * +- * Disable the VF through a SW reset. ++ * @notify_vf: notify vf about reset or not ++ * Reset VF handler. + **/ +-static inline void i40e_vc_disable_vf(struct i40e_vf *vf) ++static void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf) + { + struct i40e_pf *pf = vf->pf; + int i; + +- i40e_vc_notify_vf_reset(vf); ++ if (notify_vf) ++ i40e_vc_notify_vf_reset(vf); + + /* We want to ensure that an actual reset occurs initiated after this + * function was called. However, we do not want to wait forever, so +@@ -211,9 +212,14 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) + usleep_range(10000, 20000); + } + +- dev_warn(&vf->pf->pdev->dev, +- "Failed to initiate reset for VF %d after 200 milliseconds\n", +- vf->vf_id); ++ if (notify_vf) ++ dev_warn(&vf->pf->pdev->dev, ++ "Failed to initiate reset for VF %d after 200 milliseconds\n", ++ vf->vf_id); ++ else ++ dev_dbg(&vf->pf->pdev->dev, ++ "Failed to initiate reset for VF %d after 200 milliseconds\n", ++ vf->vf_id); + } + + /** +@@ -674,14 +680,13 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id, + u16 vsi_queue_id, + struct virtchnl_rxq_info *info) + { ++ u16 pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); + struct i40e_pf *pf = vf->pf; ++ struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx]; + struct i40e_hw *hw = &pf->hw; + struct i40e_hmc_obj_rxq rx_ctx; +- u16 pf_queue_id; + int ret = 0; + +- pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id); +- + /* clear the context structure first */ + memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); + +@@ -719,6 +724,10 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id, + } + rx_ctx.rxmax = info->max_pkt_size; + ++ /* if port VLAN is configured increase the max packet size */ ++ if (vsi->info.pvid) ++ rx_ctx.rxmax += VLAN_HLEN; ++ + /* enable 32bytes desc always */ + rx_ctx.dsize = 1; + +@@ -1367,6 +1376,32 @@ static i40e_status i40e_config_vf_promiscuous_mode(struct i40e_vf *vf, + return aq_ret; + } + ++/** ++ * i40e_sync_vfr_reset ++ * @hw: pointer to hw struct ++ * @vf_id: VF identifier ++ * ++ * Before trigger hardware reset, we need to know if no other process has ++ * reserved the hardware for any reset operations. This check is done by ++ * examining the status of the RSTAT1 register used to signal the reset. ++ **/ ++static int i40e_sync_vfr_reset(struct i40e_hw *hw, int vf_id) ++{ ++ u32 reg; ++ int i; ++ ++ for (i = 0; i < I40E_VFR_WAIT_COUNT; i++) { ++ reg = rd32(hw, I40E_VFINT_ICR0_ENA(vf_id)) & ++ I40E_VFINT_ICR0_ADMINQ_MASK; ++ if (reg) ++ return 0; ++ ++ usleep_range(100, 200); ++ } ++ ++ return -EAGAIN; ++} ++ + /** + * i40e_trigger_vf_reset + * @vf: pointer to the VF structure +@@ -1381,9 +1416,11 @@ static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr) + struct i40e_pf *pf = vf->pf; + struct i40e_hw *hw = &pf->hw; + u32 reg, reg_idx, bit_idx; ++ bool vf_active; ++ u32 radq; + + /* warn the VF */ +- clear_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states); ++ vf_active = test_and_clear_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states); + + /* Disable VF's configuration API during reset. The flag is re-enabled + * in i40e_alloc_vf_res(), when it's safe again to access VF's VSI. +@@ -1397,7 +1434,19 @@ static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr) + * just need to clean up, so don't hit the VFRTRIG register. + */ + if (!flr) { +- /* reset VF using VPGEN_VFRTRIG reg */ ++ /* Sync VFR reset before trigger next one */ ++ radq = rd32(hw, I40E_VFINT_ICR0_ENA(vf->vf_id)) & ++ I40E_VFINT_ICR0_ADMINQ_MASK; ++ if (vf_active && !radq) ++ /* waiting for finish reset by virtual driver */ ++ if (i40e_sync_vfr_reset(hw, vf->vf_id)) ++ dev_info(&pf->pdev->dev, ++ "Reset VF %d never finished\n", ++ vf->vf_id); ++ ++ /* Reset VF using VPGEN_VFRTRIG reg. It is also setting ++ * in progress state in rstat1 register. ++ */ + reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id)); + reg |= I40E_VPGEN_VFRTRIG_VFSWR_MASK; + wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg); +@@ -1868,17 +1917,19 @@ sriov_configure_out: + /***********************virtual channel routines******************/ + + /** +- * i40e_vc_send_msg_to_vf ++ * i40e_vc_send_msg_to_vf_ex + * @vf: pointer to the VF info + * @v_opcode: virtual channel opcode + * @v_retval: virtual channel return value + * @msg: pointer to the msg buffer + * @msglen: msg length ++ * @is_quiet: true for not printing unsuccessful return values, false otherwise + * + * send msg to VF + **/ +-static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, +- u32 v_retval, u8 *msg, u16 msglen) ++static int i40e_vc_send_msg_to_vf_ex(struct i40e_vf *vf, u32 v_opcode, ++ u32 v_retval, u8 *msg, u16 msglen, ++ bool is_quiet) + { + struct i40e_pf *pf; + struct i40e_hw *hw; +@@ -1894,7 +1945,7 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, + abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; + + /* single place to detect unsuccessful return values */ +- if (v_retval) { ++ if (v_retval && !is_quiet) { + vf->num_invalid_msgs++; + dev_info(&pf->pdev->dev, "VF %d failed opcode %d, retval: %d\n", + vf->vf_id, v_opcode, v_retval); +@@ -1924,6 +1975,23 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, + return 0; + } + ++/** ++ * i40e_vc_send_msg_to_vf ++ * @vf: pointer to the VF info ++ * @v_opcode: virtual channel opcode ++ * @v_retval: virtual channel return value ++ * @msg: pointer to the msg buffer ++ * @msglen: msg length ++ * ++ * send msg to VF ++ **/ ++static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, ++ u32 v_retval, u8 *msg, u16 msglen) ++{ ++ return i40e_vc_send_msg_to_vf_ex(vf, v_opcode, v_retval, ++ msg, msglen, false); ++} ++ + /** + * i40e_vc_send_resp_to_vf + * @vf: pointer to the VF info +@@ -1939,6 +2007,32 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf, + return i40e_vc_send_msg_to_vf(vf, opcode, retval, NULL, 0); + } + ++/** ++ * i40e_sync_vf_state ++ * @vf: pointer to the VF info ++ * @state: VF state ++ * ++ * Called from a VF message to synchronize the service with a potential ++ * VF reset state ++ **/ ++static bool i40e_sync_vf_state(struct i40e_vf *vf, enum i40e_vf_states state) ++{ ++ int i; ++ ++ /* When handling some messages, it needs VF state to be set. ++ * It is possible that this flag is cleared during VF reset, ++ * so there is a need to wait until the end of the reset to ++ * handle the request message correctly. ++ */ ++ for (i = 0; i < I40E_VF_STATE_WAIT_COUNT; i++) { ++ if (test_bit(state, &vf->vf_states)) ++ return true; ++ usleep_range(10000, 20000); ++ } ++ ++ return test_bit(state, &vf->vf_states); ++} ++ + /** + * i40e_vc_get_version_msg + * @vf: pointer to the VF info +@@ -1999,7 +2093,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) + size_t len = 0; + int ret; + +- if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -2105,20 +2199,6 @@ err: + return ret; + } + +-/** +- * i40e_vc_reset_vf_msg +- * @vf: pointer to the VF info +- * +- * called from the VF to reset itself, +- * unlike other virtchnl messages, PF driver +- * doesn't send the response back to the VF +- **/ +-static void i40e_vc_reset_vf_msg(struct i40e_vf *vf) +-{ +- if (test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) +- i40e_reset_vf(vf, false); +-} +- + /** + * i40e_vc_config_promiscuous_mode_msg + * @vf: pointer to the VF info +@@ -2136,7 +2216,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) + bool allmulti = false; + bool alluni = false; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err_out; + } +@@ -2217,13 +2297,14 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) + struct virtchnl_vsi_queue_config_info *qci = + (struct virtchnl_vsi_queue_config_info *)msg; + struct virtchnl_queue_pair_info *qpi; +- struct i40e_pf *pf = vf->pf; + u16 vsi_id, vsi_queue_id = 0; +- u16 num_qps_all = 0; ++ struct i40e_pf *pf = vf->pf; + i40e_status aq_ret = 0; + int i, j = 0, idx = 0; ++ struct i40e_vsi *vsi; ++ u16 num_qps_all = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2310,9 +2391,15 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) + pf->vsi[vf->lan_vsi_idx]->num_queue_pairs = + qci->num_queue_pairs; + } else { +- for (i = 0; i < vf->num_tc; i++) +- pf->vsi[vf->ch[i].vsi_idx]->num_queue_pairs = +- vf->ch[i].num_qps; ++ for (i = 0; i < vf->num_tc; i++) { ++ vsi = pf->vsi[vf->ch[i].vsi_idx]; ++ vsi->num_queue_pairs = vf->ch[i].num_qps; ++ ++ if (i40e_update_adq_vsi_queues(vsi, i)) { ++ aq_ret = I40E_ERR_CONFIG; ++ goto error_param; ++ } ++ } + } + + error_param: +@@ -2366,7 +2453,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2538,7 +2625,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg) + struct i40e_pf *pf = vf->pf; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2570,6 +2657,59 @@ error_param: + aq_ret); + } + ++/** ++ * i40e_check_enough_queue - find big enough queue number ++ * @vf: pointer to the VF info ++ * @needed: the number of items needed ++ * ++ * Returns the base item index of the queue, or negative for error ++ **/ ++static int i40e_check_enough_queue(struct i40e_vf *vf, u16 needed) ++{ ++ unsigned int i, cur_queues, more, pool_size; ++ struct i40e_lump_tracking *pile; ++ struct i40e_pf *pf = vf->pf; ++ struct i40e_vsi *vsi; ++ ++ vsi = pf->vsi[vf->lan_vsi_idx]; ++ cur_queues = vsi->alloc_queue_pairs; ++ ++ /* if current allocated queues are enough for need */ ++ if (cur_queues >= needed) ++ return vsi->base_queue; ++ ++ pile = pf->qp_pile; ++ if (cur_queues > 0) { ++ /* if the allocated queues are not zero ++ * just check if there are enough queues for more ++ * behind the allocated queues. ++ */ ++ more = needed - cur_queues; ++ for (i = vsi->base_queue + cur_queues; ++ i < pile->num_entries; i++) { ++ if (pile->list[i] & I40E_PILE_VALID_BIT) ++ break; ++ ++ if (more-- == 1) ++ /* there is enough */ ++ return vsi->base_queue; ++ } ++ } ++ ++ pool_size = 0; ++ for (i = 0; i < pile->num_entries; i++) { ++ if (pile->list[i] & I40E_PILE_VALID_BIT) { ++ pool_size = 0; ++ continue; ++ } ++ if (needed <= ++pool_size) ++ /* there is enough */ ++ return i; ++ } ++ ++ return -ENOMEM; ++} ++ + /** + * i40e_vc_request_queues_msg + * @vf: pointer to the VF info +@@ -2588,7 +2728,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg) + u8 cur_pairs = vf->num_queue_pairs; + struct i40e_pf *pf = vf->pf; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) + return -EINVAL; + + if (req_pairs > I40E_MAX_VF_QUEUES) { +@@ -2604,11 +2744,16 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg) + req_pairs - cur_pairs, + pf->queues_left); + vfres->num_queue_pairs = pf->queues_left + cur_pairs; ++ } else if (i40e_check_enough_queue(vf, req_pairs) < 0) { ++ dev_warn(&pf->pdev->dev, ++ "VF %d requested %d more queues, but there is not enough for it.\n", ++ vf->vf_id, ++ req_pairs - cur_pairs); ++ vfres->num_queue_pairs = cur_pairs; + } else { + /* successful request */ + vf->num_req_queues = req_pairs; +- i40e_vc_notify_vf_reset(vf); +- i40e_reset_vf(vf, false); ++ i40e_vc_reset_vf(vf, true); + return 0; + } + +@@ -2634,7 +2779,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg) + + memset(&stats, 0, sizeof(struct i40e_eth_stats)); + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } +@@ -2668,6 +2813,7 @@ error_param: + * i40e_check_vf_permission + * @vf: pointer to the VF info + * @al: MAC address list from virtchnl ++ * @is_quiet: set true for printing msg without opcode info, false otherwise + * + * Check that the given list of MAC addresses is allowed. Will return -EPERM + * if any address in the list is not valid. Checks the following conditions: +@@ -2682,13 +2828,15 @@ error_param: + * addresses might not be accurate. + **/ + static inline int i40e_check_vf_permission(struct i40e_vf *vf, +- struct virtchnl_ether_addr_list *al) ++ struct virtchnl_ether_addr_list *al, ++ bool *is_quiet) + { + struct i40e_pf *pf = vf->pf; + struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx]; + int mac2add_cnt = 0; + int i; + ++ *is_quiet = false; + for (i = 0; i < al->num_elements; i++) { + struct i40e_mac_filter *f; + u8 *addr = al->list[i].addr; +@@ -2712,6 +2860,7 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, + !ether_addr_equal(addr, vf->default_lan_addr.addr)) { + dev_err(&pf->pdev->dev, + "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n"); ++ *is_quiet = true; + return -EPERM; + } + +@@ -2748,10 +2897,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) + (struct virtchnl_ether_addr_list *)msg; + struct i40e_pf *pf = vf->pf; + struct i40e_vsi *vsi = NULL; ++ bool is_quiet = false; + i40e_status ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { + ret = I40E_ERR_PARAM; + goto error_param; +@@ -2764,7 +2914,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) + */ + spin_lock_bh(&vsi->mac_filter_hash_lock); + +- ret = i40e_check_vf_permission(vf, al); ++ ret = i40e_check_vf_permission(vf, al, &is_quiet); + if (ret) { + spin_unlock_bh(&vsi->mac_filter_hash_lock); + goto error_param; +@@ -2802,8 +2952,8 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) + + error_param: + /* send the response to the VF */ +- return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR, +- ret); ++ return i40e_vc_send_msg_to_vf_ex(vf, VIRTCHNL_OP_ADD_ETH_ADDR, ++ ret, NULL, 0, is_quiet); + } + + /** +@@ -2823,7 +2973,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) + i40e_status ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { + ret = I40E_ERR_PARAM; + goto error_param; +@@ -2967,7 +3117,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) { + aq_ret = I40E_ERR_PARAM; + goto error_param; +@@ -3087,9 +3237,9 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg) + struct i40e_vsi *vsi = NULL; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, vrk->vsi_id) || +- (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) { ++ vrk->key_len != I40E_HKEY_ARRAY_SIZE) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3118,9 +3268,9 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + u16 i; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || + !i40e_vc_isvalid_vsi_id(vf, vrl->vsi_id) || +- (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) { ++ vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3153,7 +3303,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int len = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3189,7 +3339,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg) + struct i40e_hw *hw = &pf->hw; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3214,7 +3364,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + struct i40e_vsi *vsi; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3240,7 +3390,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + struct i40e_vsi *vsi; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3467,7 +3617,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i, ret; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3598,7 +3748,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + int i, ret; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err_out; + } +@@ -3707,7 +3857,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) + i40e_status aq_ret = 0; + u64 speed = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3796,15 +3946,9 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) + + /* set this flag only after making sure all inputs are sane */ + vf->adq_enabled = true; +- /* num_req_queues is set when user changes number of queues via ethtool +- * and this causes issue for default VSI(which depends on this variable) +- * when ADq is enabled, hence reset it. +- */ +- vf->num_req_queues = 0; + + /* reset the VF in order to allocate resources */ +- i40e_vc_notify_vf_reset(vf); +- i40e_reset_vf(vf, false); ++ i40e_vc_reset_vf(vf, true); + + return I40E_SUCCESS; + +@@ -3824,7 +3968,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) + struct i40e_pf *pf = vf->pf; + i40e_status aq_ret = 0; + +- if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { ++ if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { + aq_ret = I40E_ERR_PARAM; + goto err; + } +@@ -3844,8 +3988,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) + } + + /* reset the VF in order to allocate resources */ +- i40e_vc_notify_vf_reset(vf); +- i40e_reset_vf(vf, false); ++ i40e_vc_reset_vf(vf, true); + + return I40E_SUCCESS; + +@@ -3907,7 +4050,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, + i40e_vc_notify_vf_link_state(vf); + break; + case VIRTCHNL_OP_RESET_VF: +- i40e_vc_reset_vf_msg(vf); ++ i40e_vc_reset_vf(vf, false); + ret = 0; + break; + case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: +@@ -4161,7 +4304,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) + /* Force the VF interface down so it has to bring up with new MAC + * address + */ +- i40e_vc_disable_vf(vf); ++ i40e_vc_reset_vf(vf, true); + dev_info(&pf->pdev->dev, "Bring down and up the VF interface to make this change effective.\n"); + + error_param: +@@ -4169,34 +4312,6 @@ error_param: + return ret; + } + +-/** +- * i40e_vsi_has_vlans - True if VSI has configured VLANs +- * @vsi: pointer to the vsi +- * +- * Check if a VSI has configured any VLANs. False if we have a port VLAN or if +- * we have no configured VLANs. Do not call while holding the +- * mac_filter_hash_lock. +- */ +-static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi) +-{ +- bool have_vlans; +- +- /* If we have a port VLAN, then the VSI cannot have any VLANs +- * configured, as all MAC/VLAN filters will be assigned to the PVID. +- */ +- if (vsi->info.pvid) +- return false; +- +- /* Since we don't have a PVID, we know that if the device is in VLAN +- * mode it must be because of a VLAN filter configured on this VSI. +- */ +- spin_lock_bh(&vsi->mac_filter_hash_lock); +- have_vlans = i40e_is_vsi_in_vlan(vsi); +- spin_unlock_bh(&vsi->mac_filter_hash_lock); +- +- return have_vlans; +-} +- + /** + * i40e_ndo_set_vf_port_vlan + * @netdev: network interface device structure +@@ -4253,19 +4368,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, + /* duplicate request, so just return success */ + goto error_pvid; + +- if (i40e_vsi_has_vlans(vsi)) { +- dev_err(&pf->pdev->dev, +- "VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n", +- vf_id); +- /* Administrator Error - knock the VF offline until he does +- * the right thing by reconfiguring his network correctly +- * and then reloading the VF driver. +- */ +- i40e_vc_disable_vf(vf); +- /* During reset the VF got a new VSI, so refresh the pointer. */ +- vsi = pf->vsi[vf->lan_vsi_idx]; +- } +- ++ i40e_vc_reset_vf(vf, true); ++ /* During reset the VF got a new VSI, so refresh a pointer. */ ++ vsi = pf->vsi[vf->lan_vsi_idx]; + /* Locked once because multiple functions below iterate list */ + spin_lock_bh(&vsi->mac_filter_hash_lock); + +@@ -4641,7 +4746,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting) + goto out; + + vf->trusted = setting; +- i40e_vc_disable_vf(vf); ++ i40e_vc_reset_vf(vf, true); + dev_info(&pf->pdev->dev, "VF %u is now %strusted\n", + vf_id, setting ? "" : "un"); + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +index 091e32c1bb46f..03c42fd0fea19 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +@@ -18,6 +18,9 @@ + + #define I40E_MAX_VF_PROMISC_FLAGS 3 + ++#define I40E_VF_STATE_WAIT_COUNT 20 ++#define I40E_VFR_WAIT_COUNT 100 ++ + /* Various queue ctrls */ + enum i40e_queue_ctrl { + I40E_QUEUE_CTRL_UNKNOWN = 0, +diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h +index 68c80f04113c8..9a122aea69793 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf.h ++++ b/drivers/net/ethernet/intel/iavf/iavf.h +@@ -39,6 +39,7 @@ + #include "iavf_txrx.h" + #include "iavf_fdir.h" + #include "iavf_adv_rss.h" ++#include <linux/bitmap.h> + + #define DEFAULT_DEBUG_LEVEL_SHIFT 3 + #define PFX "iavf: " +@@ -177,6 +178,7 @@ enum iavf_state_t { + __IAVF_INIT_VERSION_CHECK, /* aq msg sent, awaiting reply */ + __IAVF_INIT_GET_RESOURCES, /* aq msg sent, awaiting reply */ + __IAVF_INIT_SW, /* got resources, setting up structs */ ++ __IAVF_INIT_FAILED, /* init failed, restarting procedure */ + __IAVF_RESETTING, /* in reset */ + __IAVF_COMM_FAILED, /* communication with PF failed */ + /* Below here, watchdog is running */ +@@ -186,6 +188,10 @@ enum iavf_state_t { + __IAVF_RUNNING, /* opened, working */ + }; + ++enum iavf_critical_section_t { ++ __IAVF_IN_REMOVE_TASK, /* device being removed */ ++}; ++ + #define IAVF_CLOUD_FIELD_OMAC 0x01 + #define IAVF_CLOUD_FIELD_IMAC 0x02 + #define IAVF_CLOUD_FIELD_IVLAN 0x04 +@@ -225,14 +231,12 @@ struct iavf_adapter { + struct work_struct reset_task; + struct work_struct adminq_task; + struct delayed_work client_task; +- struct delayed_work init_task; + wait_queue_head_t down_waitqueue; + struct iavf_q_vector *q_vectors; + struct list_head vlan_filter_list; + struct list_head mac_filter_list; + struct mutex crit_lock; + struct mutex client_lock; +- struct mutex remove_lock; + /* Lock to protect accesses to MAC and VLAN lists */ + spinlock_t mac_vlan_list_lock; + char misc_vector_name[IFNAMSIZ + 9]; +@@ -270,6 +274,7 @@ struct iavf_adapter { + #define IAVF_FLAG_LEGACY_RX BIT(15) + #define IAVF_FLAG_REINIT_ITR_NEEDED BIT(16) + #define IAVF_FLAG_QUEUES_DISABLED BIT(17) ++#define IAVF_FLAG_SETUP_NETDEV_FEATURES BIT(18) + /* duplicates for common code */ + #define IAVF_FLAG_DCB_ENABLED 0 + /* flags for admin queue service task */ +@@ -304,6 +309,7 @@ struct iavf_adapter { + #define IAVF_FLAG_AQ_DEL_FDIR_FILTER BIT(26) + #define IAVF_FLAG_AQ_ADD_ADV_RSS_CFG BIT(27) + #define IAVF_FLAG_AQ_DEL_ADV_RSS_CFG BIT(28) ++#define IAVF_FLAG_AQ_REQUEST_STATS BIT(29) + + /* OS defined structs */ + struct net_device *netdev; +@@ -312,6 +318,7 @@ struct iavf_adapter { + struct iavf_hw hw; /* defined in iavf_type.h */ + + enum iavf_state_t state; ++ enum iavf_state_t last_state; + unsigned long crit_section; + + struct delayed_work watchdog_task; +@@ -393,10 +400,56 @@ struct iavf_device { + extern char iavf_driver_name[]; + extern struct workqueue_struct *iavf_wq; + ++static inline const char *iavf_state_str(enum iavf_state_t state) ++{ ++ switch (state) { ++ case __IAVF_STARTUP: ++ return "__IAVF_STARTUP"; ++ case __IAVF_REMOVE: ++ return "__IAVF_REMOVE"; ++ case __IAVF_INIT_VERSION_CHECK: ++ return "__IAVF_INIT_VERSION_CHECK"; ++ case __IAVF_INIT_GET_RESOURCES: ++ return "__IAVF_INIT_GET_RESOURCES"; ++ case __IAVF_INIT_SW: ++ return "__IAVF_INIT_SW"; ++ case __IAVF_INIT_FAILED: ++ return "__IAVF_INIT_FAILED"; ++ case __IAVF_RESETTING: ++ return "__IAVF_RESETTING"; ++ case __IAVF_COMM_FAILED: ++ return "__IAVF_COMM_FAILED"; ++ case __IAVF_DOWN: ++ return "__IAVF_DOWN"; ++ case __IAVF_DOWN_PENDING: ++ return "__IAVF_DOWN_PENDING"; ++ case __IAVF_TESTING: ++ return "__IAVF_TESTING"; ++ case __IAVF_RUNNING: ++ return "__IAVF_RUNNING"; ++ default: ++ return "__IAVF_UNKNOWN_STATE"; ++ } ++} ++ ++static inline void iavf_change_state(struct iavf_adapter *adapter, ++ enum iavf_state_t state) ++{ ++ if (adapter->state != state) { ++ adapter->last_state = adapter->state; ++ adapter->state = state; ++ } ++ dev_dbg(&adapter->pdev->dev, ++ "state transition from:%s to:%s\n", ++ iavf_state_str(adapter->last_state), ++ iavf_state_str(adapter->state)); ++} ++ + int iavf_up(struct iavf_adapter *adapter); + void iavf_down(struct iavf_adapter *adapter); + int iavf_process_config(struct iavf_adapter *adapter); + void iavf_schedule_reset(struct iavf_adapter *adapter); ++void iavf_schedule_request_stats(struct iavf_adapter *adapter); + void iavf_reset(struct iavf_adapter *adapter); + void iavf_set_ethtool_ops(struct net_device *netdev); + void iavf_update_stats(struct iavf_adapter *adapter); +@@ -454,4 +507,5 @@ void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter); + void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter); + struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, + const u8 *macaddr); ++int iavf_lock_timeout(struct mutex *lock, unsigned int msecs); + #endif /* _IAVF_H_ */ +diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +index 5a359a0a20ecc..461f5237a2f88 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +@@ -354,6 +354,9 @@ static void iavf_get_ethtool_stats(struct net_device *netdev, + struct iavf_adapter *adapter = netdev_priv(netdev); + unsigned int i; + ++ /* Explicitly request stats refresh */ ++ iavf_schedule_request_stats(adapter); ++ + iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats); + + rcu_read_lock(); +@@ -612,23 +615,44 @@ static int iavf_set_ringparam(struct net_device *netdev, + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + +- new_tx_count = clamp_t(u32, ring->tx_pending, +- IAVF_MIN_TXD, +- IAVF_MAX_TXD); +- new_tx_count = ALIGN(new_tx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ if (ring->tx_pending > IAVF_MAX_TXD || ++ ring->tx_pending < IAVF_MIN_TXD || ++ ring->rx_pending > IAVF_MAX_RXD || ++ ring->rx_pending < IAVF_MIN_RXD) { ++ netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", ++ ring->tx_pending, ring->rx_pending, IAVF_MIN_TXD, ++ IAVF_MAX_RXD, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ return -EINVAL; ++ } ++ ++ new_tx_count = ALIGN(ring->tx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ if (new_tx_count != ring->tx_pending) ++ netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n", ++ new_tx_count); + +- new_rx_count = clamp_t(u32, ring->rx_pending, +- IAVF_MIN_RXD, +- IAVF_MAX_RXD); +- new_rx_count = ALIGN(new_rx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ new_rx_count = ALIGN(ring->rx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); ++ if (new_rx_count != ring->rx_pending) ++ netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n", ++ new_rx_count); + + /* if nothing to do return success */ + if ((new_tx_count == adapter->tx_desc_count) && +- (new_rx_count == adapter->rx_desc_count)) ++ (new_rx_count == adapter->rx_desc_count)) { ++ netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); + return 0; ++ } ++ ++ if (new_tx_count != adapter->tx_desc_count) { ++ netdev_dbg(netdev, "Changing Tx descriptor count from %d to %d\n", ++ adapter->tx_desc_count, new_tx_count); ++ adapter->tx_desc_count = new_tx_count; ++ } + +- adapter->tx_desc_count = new_tx_count; +- adapter->rx_desc_count = new_rx_count; ++ if (new_rx_count != adapter->rx_desc_count) { ++ netdev_dbg(netdev, "Changing Rx descriptor count from %d to %d\n", ++ adapter->rx_desc_count, new_rx_count); ++ adapter->rx_desc_count = new_rx_count; ++ } + + if (netif_running(netdev)) { + adapter->flags |= IAVF_FLAG_RESET_NEEDED; +@@ -723,12 +747,31 @@ static int iavf_get_per_queue_coalesce(struct net_device *netdev, u32 queue, + * + * Change the ITR settings for a specific queue. + **/ +-static void iavf_set_itr_per_queue(struct iavf_adapter *adapter, +- struct ethtool_coalesce *ec, int queue) ++static int iavf_set_itr_per_queue(struct iavf_adapter *adapter, ++ struct ethtool_coalesce *ec, int queue) + { + struct iavf_ring *rx_ring = &adapter->rx_rings[queue]; + struct iavf_ring *tx_ring = &adapter->tx_rings[queue]; + struct iavf_q_vector *q_vector; ++ u16 itr_setting; ++ ++ itr_setting = rx_ring->itr_setting & ~IAVF_ITR_DYNAMIC; ++ ++ if (ec->rx_coalesce_usecs != itr_setting && ++ ec->use_adaptive_rx_coalesce) { ++ netif_info(adapter, drv, adapter->netdev, ++ "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n"); ++ return -EINVAL; ++ } ++ ++ itr_setting = tx_ring->itr_setting & ~IAVF_ITR_DYNAMIC; ++ ++ if (ec->tx_coalesce_usecs != itr_setting && ++ ec->use_adaptive_tx_coalesce) { ++ netif_info(adapter, drv, adapter->netdev, ++ "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n"); ++ return -EINVAL; ++ } + + rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); + tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); +@@ -751,6 +794,7 @@ static void iavf_set_itr_per_queue(struct iavf_adapter *adapter, + * the Tx and Rx ITR values based on the values we have entered + * into the q_vector, no need to write the values now. + */ ++ return 0; + } + + /** +@@ -792,9 +836,11 @@ static int __iavf_set_coalesce(struct net_device *netdev, + */ + if (queue < 0) { + for (i = 0; i < adapter->num_active_queues; i++) +- iavf_set_itr_per_queue(adapter, ec, i); ++ if (iavf_set_itr_per_queue(adapter, ec, i)) ++ return -EINVAL; + } else if (queue < adapter->num_active_queues) { +- iavf_set_itr_per_queue(adapter, ec, queue); ++ if (iavf_set_itr_per_queue(adapter, ec, queue)) ++ return -EINVAL; + } else { + netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n", + adapter->num_active_queues - 1); +@@ -1776,6 +1822,7 @@ static int iavf_set_channels(struct net_device *netdev, + { + struct iavf_adapter *adapter = netdev_priv(netdev); + u32 num_req = ch->combined_count; ++ int i; + + if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) && + adapter->num_tc) { +@@ -1786,7 +1833,7 @@ static int iavf_set_channels(struct net_device *netdev, + /* All of these should have already been checked by ethtool before this + * even gets to us, but just to be sure. + */ +- if (num_req > adapter->vsi_res->num_queue_pairs) ++ if (num_req == 0 || num_req > adapter->vsi_res->num_queue_pairs) + return -EINVAL; + + if (num_req == adapter->num_active_queues) +@@ -1798,6 +1845,20 @@ static int iavf_set_channels(struct net_device *netdev, + adapter->num_req_queues = num_req; + adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED; + iavf_schedule_reset(adapter); ++ ++ /* wait for the reset is done */ ++ for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) { ++ msleep(IAVF_RESET_WAIT_MS); ++ if (adapter->flags & IAVF_FLAG_RESET_PENDING) ++ continue; ++ break; ++ } ++ if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { ++ adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED; ++ adapter->num_active_queues = num_req; ++ return -EOPNOTSUPP; ++ } ++ + return 0; + } + +@@ -1844,14 +1905,13 @@ static int iavf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; +- if (!indir) +- return 0; +- +- memcpy(key, adapter->rss_key, adapter->rss_key_size); ++ if (key) ++ memcpy(key, adapter->rss_key, adapter->rss_key_size); + +- /* Each 32 bits pointed by 'indir' is stored with a lut entry */ +- for (i = 0; i < adapter->rss_lut_size; i++) +- indir[i] = (u32)adapter->rss_lut[i]; ++ if (indir) ++ /* Each 32 bits pointed by 'indir' is stored with a lut entry */ ++ for (i = 0; i < adapter->rss_lut_size; i++) ++ indir[i] = (u32)adapter->rss_lut[i]; + + return 0; + } +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index cada4e0e40b48..711e8c7f62de7 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -14,7 +14,7 @@ + static int iavf_setup_all_tx_resources(struct iavf_adapter *adapter); + static int iavf_setup_all_rx_resources(struct iavf_adapter *adapter); + static int iavf_close(struct net_device *netdev); +-static int iavf_init_get_resources(struct iavf_adapter *adapter); ++static void iavf_init_get_resources(struct iavf_adapter *adapter); + static int iavf_check_reset_complete(struct iavf_hw *hw); + + char iavf_driver_name[] = "iavf"; +@@ -51,6 +51,15 @@ MODULE_LICENSE("GPL v2"); + static const struct net_device_ops iavf_netdev_ops; + struct workqueue_struct *iavf_wq; + ++/** ++ * iavf_pdev_to_adapter - go from pci_dev to adapter ++ * @pdev: pci_dev pointer ++ */ ++static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev) ++{ ++ return netdev_priv(pci_get_drvdata(pdev)); ++} ++ + /** + * iavf_allocate_dma_mem_d - OS specific memory alloc for shared code + * @hw: pointer to the HW structure +@@ -138,7 +147,7 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw, + * + * Returns 0 on success, negative on failure + **/ +-static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) ++int iavf_lock_timeout(struct mutex *lock, unsigned int msecs) + { + unsigned int wait, delay = 10; + +@@ -165,6 +174,19 @@ void iavf_schedule_reset(struct iavf_adapter *adapter) + } + } + ++/** ++ * iavf_schedule_request_stats - Set the flags and schedule statistics request ++ * @adapter: board private structure ++ * ++ * Sets IAVF_FLAG_AQ_REQUEST_STATS flag so iavf_watchdog_task() will explicitly ++ * request and refresh ethtool stats ++ **/ ++void iavf_schedule_request_stats(struct iavf_adapter *adapter) ++{ ++ adapter->aq_required |= IAVF_FLAG_AQ_REQUEST_STATS; ++ mod_delayed_work(iavf_wq, &adapter->watchdog_task, 0); ++} ++ + /** + * iavf_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure +@@ -280,8 +302,9 @@ static irqreturn_t iavf_msix_aq(int irq, void *data) + rd32(hw, IAVF_VFINT_ICR01); + rd32(hw, IAVF_VFINT_ICR0_ENA1); + +- /* schedule work on the private workqueue */ +- queue_work(iavf_wq, &adapter->adminq_task); ++ if (adapter->state != __IAVF_REMOVE) ++ /* schedule work on the private workqueue */ ++ queue_work(iavf_wq, &adapter->adminq_task); + + return IRQ_HANDLED; + } +@@ -687,6 +710,21 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, u16 vlan) + spin_unlock_bh(&adapter->mac_vlan_list_lock); + } + ++/** ++ * iavf_restore_filters ++ * @adapter: board private structure ++ * ++ * Restore existing non MAC filters when VF netdev comes back up ++ **/ ++static void iavf_restore_filters(struct iavf_adapter *adapter) ++{ ++ u16 vid; ++ ++ /* re-add all VLAN filters */ ++ for_each_set_bit(vid, adapter->vsi.active_vlans, VLAN_N_VID) ++ iavf_add_vlan(adapter, vid); ++} ++ + /** + * iavf_vlan_rx_add_vid - Add a VLAN filter to a device + * @netdev: network device struct +@@ -700,8 +738,11 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev, + + if (!VLAN_ALLOWED(adapter)) + return -EIO; ++ + if (iavf_add_vlan(adapter, vid) == NULL) + return -ENOMEM; ++ ++ set_bit(vid, adapter->vsi.active_vlans); + return 0; + } + +@@ -716,11 +757,10 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev, + { + struct iavf_adapter *adapter = netdev_priv(netdev); + +- if (VLAN_ALLOWED(adapter)) { +- iavf_del_vlan(adapter, vid); +- return 0; +- } +- return -EIO; ++ iavf_del_vlan(adapter, vid); ++ clear_bit(vid, adapter->vsi.active_vlans); ++ ++ return 0; + } + + /** +@@ -960,7 +1000,7 @@ static void iavf_configure(struct iavf_adapter *adapter) + **/ + static void iavf_up_complete(struct iavf_adapter *adapter) + { +- adapter->state = __IAVF_RUNNING; ++ iavf_change_state(adapter, __IAVF_RUNNING); + clear_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + + iavf_napi_enable_all(adapter); +@@ -1033,8 +1073,7 @@ void iavf_down(struct iavf_adapter *adapter) + rss->state = IAVF_ADV_RSS_DEL_REQUEST; + spin_unlock_bh(&adapter->adv_rss_lock); + +- if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) && +- adapter->state != __IAVF_RESETTING) { ++ if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)) { + /* cancel any current operation */ + adapter->current_op = VIRTCHNL_OP_UNKNOWN; + /* Schedule operations to close down the HW. Don't wait +@@ -1630,8 +1669,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) + iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC); + return 0; + } +- +- if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) && ++ if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) || + (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) { + iavf_set_promiscuous(adapter, 0); + return 0; +@@ -1679,6 +1717,11 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) + iavf_del_adv_rss_cfg(adapter); + return 0; + } ++ if (adapter->aq_required & IAVF_FLAG_AQ_REQUEST_STATS) { ++ iavf_request_stats(adapter); ++ return 0; ++ } ++ + return -EAGAIN; + } + +@@ -1688,9 +1731,9 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter) + * + * Function process __IAVF_STARTUP driver state. + * When success the state is changed to __IAVF_INIT_VERSION_CHECK +- * when fails it returns -EAGAIN ++ * when fails the state is changed to __IAVF_INIT_FAILED + **/ +-static int iavf_startup(struct iavf_adapter *adapter) ++static void iavf_startup(struct iavf_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct iavf_hw *hw = &adapter->hw; +@@ -1729,9 +1772,10 @@ static int iavf_startup(struct iavf_adapter *adapter) + iavf_shutdown_adminq(hw); + goto err; + } +- adapter->state = __IAVF_INIT_VERSION_CHECK; ++ iavf_change_state(adapter, __IAVF_INIT_VERSION_CHECK); ++ return; + err: +- return err; ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); + } + + /** +@@ -1740,9 +1784,9 @@ err: + * + * Function process __IAVF_INIT_VERSION_CHECK driver state. + * When success the state is changed to __IAVF_INIT_GET_RESOURCES +- * when fails it returns -EAGAIN ++ * when fails the state is changed to __IAVF_INIT_FAILED + **/ +-static int iavf_init_version_check(struct iavf_adapter *adapter) ++static void iavf_init_version_check(struct iavf_adapter *adapter) + { + struct pci_dev *pdev = adapter->pdev; + struct iavf_hw *hw = &adapter->hw; +@@ -1753,7 +1797,7 @@ static int iavf_init_version_check(struct iavf_adapter *adapter) + if (!iavf_asq_done(hw)) { + dev_err(&pdev->dev, "Admin queue command never completed\n"); + iavf_shutdown_adminq(hw); +- adapter->state = __IAVF_STARTUP; ++ iavf_change_state(adapter, __IAVF_STARTUP); + goto err; + } + +@@ -1776,10 +1820,10 @@ static int iavf_init_version_check(struct iavf_adapter *adapter) + err); + goto err; + } +- adapter->state = __IAVF_INIT_GET_RESOURCES; +- ++ iavf_change_state(adapter, __IAVF_INIT_GET_RESOURCES); ++ return; + err: +- return err; ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); + } + + /** +@@ -1789,9 +1833,9 @@ err: + * Function process __IAVF_INIT_GET_RESOURCES driver state and + * finishes driver initialization procedure. + * When success the state is changed to __IAVF_DOWN +- * when fails it returns -EAGAIN ++ * when fails the state is changed to __IAVF_INIT_FAILED + **/ +-static int iavf_init_get_resources(struct iavf_adapter *adapter) ++static void iavf_init_get_resources(struct iavf_adapter *adapter) + { + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; +@@ -1819,7 +1863,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + */ + iavf_shutdown_adminq(hw); + dev_err(&pdev->dev, "Unable to get VF config due to PF error condition, not retrying\n"); +- return 0; ++ return; + } + if (err) { + dev_err(&pdev->dev, "Unable to get VF config (%d)\n", err); +@@ -1893,7 +1937,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + if (netdev->features & NETIF_F_GRO) + dev_info(&pdev->dev, "GRO is enabled\n"); + +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + set_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + rtnl_unlock(); + +@@ -1911,7 +1955,7 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter) + else + iavf_init_rss(adapter); + +- return err; ++ return; + err_mem: + iavf_free_rss(adapter); + err_register: +@@ -1922,7 +1966,7 @@ err_alloc: + kfree(adapter->vf_res); + adapter->vf_res = NULL; + err: +- return err; ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); + } + + /** +@@ -1937,14 +1981,80 @@ static void iavf_watchdog_task(struct work_struct *work) + struct iavf_hw *hw = &adapter->hw; + u32 reg_val; + +- if (!mutex_trylock(&adapter->crit_lock)) ++ if (!mutex_trylock(&adapter->crit_lock)) { ++ if (adapter->state == __IAVF_REMOVE) ++ return; ++ + goto restart_watchdog; ++ } + + if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) +- adapter->state = __IAVF_COMM_FAILED; ++ iavf_change_state(adapter, __IAVF_COMM_FAILED); ++ ++ if (adapter->flags & IAVF_FLAG_RESET_NEEDED) { ++ adapter->aq_required = 0; ++ adapter->current_op = VIRTCHNL_OP_UNKNOWN; ++ mutex_unlock(&adapter->crit_lock); ++ queue_work(iavf_wq, &adapter->reset_task); ++ return; ++ } + + switch (adapter->state) { ++ case __IAVF_STARTUP: ++ iavf_startup(adapter); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, ++ msecs_to_jiffies(30)); ++ return; ++ case __IAVF_INIT_VERSION_CHECK: ++ iavf_init_version_check(adapter); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, ++ msecs_to_jiffies(30)); ++ return; ++ case __IAVF_INIT_GET_RESOURCES: ++ iavf_init_get_resources(adapter); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, ++ msecs_to_jiffies(1)); ++ return; ++ case __IAVF_INIT_FAILED: ++ if (test_bit(__IAVF_IN_REMOVE_TASK, ++ &adapter->crit_section)) { ++ /* Do not update the state and do not reschedule ++ * watchdog task, iavf_remove should handle this state ++ * as it can loop forever ++ */ ++ mutex_unlock(&adapter->crit_lock); ++ return; ++ } ++ if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) { ++ dev_err(&adapter->pdev->dev, ++ "Failed to communicate with PF; waiting before retry\n"); ++ adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED; ++ iavf_shutdown_adminq(hw); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, ++ &adapter->watchdog_task, (5 * HZ)); ++ return; ++ } ++ /* Try again from failed step*/ ++ iavf_change_state(adapter, adapter->last_state); ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ); ++ return; + case __IAVF_COMM_FAILED: ++ if (test_bit(__IAVF_IN_REMOVE_TASK, ++ &adapter->crit_section)) { ++ /* Set state to __IAVF_INIT_FAILED and perform remove ++ * steps. Remove IAVF_FLAG_PF_COMMS_FAILED so the task ++ * doesn't bring the state back to __IAVF_COMM_FAILED. ++ */ ++ iavf_change_state(adapter, __IAVF_INIT_FAILED); ++ adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED; ++ mutex_unlock(&adapter->crit_lock); ++ return; ++ } + reg_val = rd32(hw, IAVF_VFGEN_RSTAT) & + IAVF_VFGEN_RSTAT_VFR_STATE_MASK; + if (reg_val == VIRTCHNL_VFR_VFACTIVE || +@@ -1952,23 +2062,20 @@ static void iavf_watchdog_task(struct work_struct *work) + /* A chance for redemption! */ + dev_err(&adapter->pdev->dev, + "Hardware came out of reset. Attempting reinit.\n"); +- adapter->state = __IAVF_STARTUP; +- adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED; +- queue_delayed_work(iavf_wq, &adapter->init_task, 10); +- mutex_unlock(&adapter->crit_lock); +- /* Don't reschedule the watchdog, since we've restarted +- * the init task. When init_task contacts the PF and ++ /* When init task contacts the PF and + * gets everything set up again, it'll restart the + * watchdog for us. Down, boy. Sit. Stay. Woof. + */ +- return; ++ iavf_change_state(adapter, __IAVF_STARTUP); ++ adapter->flags &= ~IAVF_FLAG_PF_COMMS_FAILED; + } + adapter->aq_required = 0; + adapter->current_op = VIRTCHNL_OP_UNKNOWN; ++ mutex_unlock(&adapter->crit_lock); + queue_delayed_work(iavf_wq, + &adapter->watchdog_task, + msecs_to_jiffies(10)); +- goto watchdog_done; ++ return; + case __IAVF_RESETTING: + mutex_unlock(&adapter->crit_lock); + queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); +@@ -1991,15 +2098,16 @@ static void iavf_watchdog_task(struct work_struct *work) + adapter->state == __IAVF_RUNNING) + iavf_request_stats(adapter); + } ++ if (adapter->state == __IAVF_RUNNING) ++ iavf_detect_recover_hung(&adapter->vsi); + break; + case __IAVF_REMOVE: ++ default: + mutex_unlock(&adapter->crit_lock); + return; +- default: +- goto restart_watchdog; + } + +- /* check for hw reset */ ++ /* check for hw reset */ + reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK; + if (!reg_val) { + adapter->flags |= IAVF_FLAG_RESET_PENDING; +@@ -2007,22 +2115,22 @@ static void iavf_watchdog_task(struct work_struct *work) + adapter->current_op = VIRTCHNL_OP_UNKNOWN; + dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); + queue_work(iavf_wq, &adapter->reset_task); +- goto watchdog_done; ++ mutex_unlock(&adapter->crit_lock); ++ queue_delayed_work(iavf_wq, ++ &adapter->watchdog_task, HZ * 2); ++ return; + } + + schedule_delayed_work(&adapter->client_task, msecs_to_jiffies(5)); +-watchdog_done: +- if (adapter->state == __IAVF_RUNNING || +- adapter->state == __IAVF_COMM_FAILED) +- iavf_detect_recover_hung(&adapter->vsi); + mutex_unlock(&adapter->crit_lock); + restart_watchdog: ++ if (adapter->state >= __IAVF_DOWN) ++ queue_work(iavf_wq, &adapter->adminq_task); + if (adapter->aq_required) + queue_delayed_work(iavf_wq, &adapter->watchdog_task, + msecs_to_jiffies(20)); + else + queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2); +- queue_work(iavf_wq, &adapter->adminq_task); + } + + static void iavf_disable_vf(struct iavf_adapter *adapter) +@@ -2074,14 +2182,14 @@ static void iavf_disable_vf(struct iavf_adapter *adapter) + + iavf_free_misc_irq(adapter); + iavf_reset_interrupt_capability(adapter); +- iavf_free_queues(adapter); + iavf_free_q_vectors(adapter); ++ iavf_free_queues(adapter); + memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE); + iavf_shutdown_adminq(&adapter->hw); + adapter->netdev->flags &= ~IFF_UP; + mutex_unlock(&adapter->crit_lock); + adapter->flags &= ~IAVF_FLAG_RESET_PENDING; +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); + dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n"); + } +@@ -2103,7 +2211,6 @@ static void iavf_reset_task(struct work_struct *work) + struct net_device *netdev = adapter->netdev; + struct iavf_hw *hw = &adapter->hw; + struct iavf_mac_filter *f, *ftmp; +- struct iavf_vlan_filter *vlf; + struct iavf_cloud_filter *cf; + u32 reg_val; + int i = 0, err; +@@ -2112,13 +2219,13 @@ static void iavf_reset_task(struct work_struct *work) + /* When device is being removed it doesn't make sense to run the reset + * task, just return in such a case. + */ +- if (mutex_is_locked(&adapter->remove_lock)) +- return; ++ if (!mutex_trylock(&adapter->crit_lock)) { ++ if (adapter->state != __IAVF_REMOVE) ++ queue_work(iavf_wq, &adapter->reset_task); + +- if (iavf_lock_timeout(&adapter->crit_lock, 200)) { +- schedule_work(&adapter->reset_task); + return; + } ++ + while (!mutex_trylock(&adapter->client_lock)) + usleep_range(500, 1000); + if (CLIENT_ENABLED(adapter)) { +@@ -2166,12 +2273,14 @@ static void iavf_reset_task(struct work_struct *work) + } + + pci_set_master(adapter->pdev); ++ pci_restore_msi_state(adapter->pdev); + + if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { + dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", + reg_val); + iavf_disable_vf(adapter); + mutex_unlock(&adapter->client_lock); ++ mutex_unlock(&adapter->crit_lock); + return; /* Do not attempt to reinit. It's dead, Jim. */ + } + +@@ -2180,8 +2289,7 @@ continue_reset: + * ndo_open() returning, so we can't assume it means all our open + * tasks have finished, since we're not holding the rtnl_lock here. + */ +- running = ((adapter->state == __IAVF_RUNNING) || +- (adapter->state == __IAVF_RESETTING)); ++ running = adapter->state == __IAVF_RUNNING; + + if (running) { + netif_carrier_off(netdev); +@@ -2191,7 +2299,7 @@ continue_reset: + } + iavf_irq_disable(adapter); + +- adapter->state = __IAVF_RESETTING; ++ iavf_change_state(adapter, __IAVF_RESETTING); + adapter->flags &= ~IAVF_FLAG_RESET_PENDING; + + /* free the Tx/Rx rings and descriptors, might be better to just +@@ -2243,11 +2351,6 @@ continue_reset: + list_for_each_entry(f, &adapter->mac_filter_list, list) { + f->add = true; + } +- /* re-add all VLAN filters */ +- list_for_each_entry(vlf, &adapter->vlan_filter_list, list) { +- vlf->add = true; +- } +- + spin_unlock_bh(&adapter->mac_vlan_list_lock); + + /* check if TCs are running and re-add all cloud filters */ +@@ -2261,7 +2364,6 @@ continue_reset: + spin_unlock_bh(&adapter->cloud_filter_list_lock); + + adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; +- adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER; + adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER; + iavf_misc_irq_enable(adapter); + +@@ -2291,11 +2393,14 @@ continue_reset: + + iavf_configure(adapter); + ++ /* iavf_up_complete() will switch device back ++ * to __IAVF_RUNNING ++ */ + iavf_up_complete(adapter); + + iavf_irq_enable(adapter, true); + } else { +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); + } + mutex_unlock(&adapter->client_lock); +@@ -2305,6 +2410,8 @@ continue_reset: + reset_err: + mutex_unlock(&adapter->client_lock); + mutex_unlock(&adapter->crit_lock); ++ if (running) ++ iavf_change_state(adapter, __IAVF_RUNNING); + dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); + iavf_close(netdev); + } +@@ -2327,13 +2434,19 @@ static void iavf_adminq_task(struct work_struct *work) + if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) + goto out; + ++ if (!mutex_trylock(&adapter->crit_lock)) { ++ if (adapter->state == __IAVF_REMOVE) ++ return; ++ ++ queue_work(iavf_wq, &adapter->adminq_task); ++ goto out; ++ } ++ + event.buf_len = IAVF_MAX_AQ_BUF_SIZE; + event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL); + if (!event.msg_buf) + goto out; + +- if (iavf_lock_timeout(&adapter->crit_lock, 200)) +- goto freedom; + do { + ret = iavf_clean_arq_element(hw, &event, &pending); + v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high); +@@ -2349,6 +2462,18 @@ static void iavf_adminq_task(struct work_struct *work) + } while (pending); + mutex_unlock(&adapter->crit_lock); + ++ if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES)) { ++ if (adapter->netdev_registered || ++ !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) { ++ struct net_device *netdev = adapter->netdev; ++ ++ rtnl_lock(); ++ netdev_update_features(netdev); ++ rtnl_unlock(); ++ } ++ ++ adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES; ++ } + if ((adapter->flags & + (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) || + adapter->state == __IAVF_RESETTING) +@@ -2356,7 +2481,7 @@ static void iavf_adminq_task(struct work_struct *work) + + /* check for error indications */ + val = rd32(hw, hw->aq.arq.len); +- if (val == 0xdeadbeef) /* indicates device in reset */ ++ if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */ + goto freedom; + oldval = val; + if (val & IAVF_VF_ARQLEN1_ARQVFE_MASK) { +@@ -2624,8 +2749,11 @@ static int iavf_validate_ch_config(struct iavf_adapter *adapter, + total_max_rate += tx_rate; + num_qps += mqprio_qopt->qopt.count[i]; + } +- if (num_qps > IAVF_MAX_REQ_QUEUES) ++ if (num_qps > adapter->num_active_queues) { ++ dev_err(&adapter->pdev->dev, ++ "Cannot support requested number of queues\n"); + return -EINVAL; ++ } + + ret = iavf_validate_tx_bandwidth(adapter, total_max_rate); + return ret; +@@ -3041,8 +3169,10 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter, + return -ENOMEM; + + while (!mutex_trylock(&adapter->crit_lock)) { +- if (--count == 0) +- goto err; ++ if (--count == 0) { ++ kfree(filter); ++ return err; ++ } + udelay(1); + } + +@@ -3053,11 +3183,11 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter, + /* start out with flow type and eth type IPv4 to begin with */ + filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW; + err = iavf_parse_cls_flower(adapter, cls_flower, filter); +- if (err < 0) ++ if (err) + goto err; + + err = iavf_handle_tclass(adapter, tc, filter); +- if (err < 0) ++ if (err) + goto err; + + /* add filter to the list */ +@@ -3226,6 +3356,13 @@ static int iavf_open(struct net_device *netdev) + goto err_unlock; + } + ++ if (adapter->state == __IAVF_RUNNING && ++ !test_bit(__IAVF_VSI_DOWN, adapter->vsi.state)) { ++ dev_dbg(&adapter->pdev->dev, "VF is already open.\n"); ++ err = 0; ++ goto err_unlock; ++ } ++ + /* allocate transmit descriptors */ + err = iavf_setup_all_tx_resources(adapter); + if (err) +@@ -3247,6 +3384,9 @@ static int iavf_open(struct net_device *netdev) + + spin_unlock_bh(&adapter->mac_vlan_list_lock); + ++ /* Restore VLAN filters that were removed with IFF_DOWN */ ++ iavf_restore_filters(adapter); ++ + iavf_configure(adapter); + + iavf_up_complete(adapter); +@@ -3286,18 +3426,19 @@ static int iavf_close(struct net_device *netdev) + struct iavf_adapter *adapter = netdev_priv(netdev); + int status; + +- if (adapter->state <= __IAVF_DOWN_PENDING) +- return 0; ++ mutex_lock(&adapter->crit_lock); + +- while (!mutex_trylock(&adapter->crit_lock)) +- usleep_range(500, 1000); ++ if (adapter->state <= __IAVF_DOWN_PENDING) { ++ mutex_unlock(&adapter->crit_lock); ++ return 0; ++ } + + set_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + if (CLIENT_ENABLED(adapter)) + adapter->flags |= IAVF_FLAG_CLIENT_NEEDS_CLOSE; + + iavf_down(adapter); +- adapter->state = __IAVF_DOWN_PENDING; ++ iavf_change_state(adapter, __IAVF_DOWN_PENDING); + iavf_free_traffic_irqs(adapter); + + mutex_unlock(&adapter->crit_lock); +@@ -3337,8 +3478,11 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu) + iavf_notify_client_l2_params(&adapter->vsi); + adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED; + } +- adapter->flags |= IAVF_FLAG_RESET_NEEDED; +- queue_work(iavf_wq, &adapter->reset_task); ++ ++ if (netif_running(netdev)) { ++ adapter->flags |= IAVF_FLAG_RESET_NEEDED; ++ queue_work(iavf_wq, &adapter->reset_task); ++ } + + return 0; + } +@@ -3354,11 +3498,16 @@ static int iavf_set_features(struct net_device *netdev, + { + struct iavf_adapter *adapter = netdev_priv(netdev); + +- /* Don't allow changing VLAN_RX flag when adapter is not capable +- * of VLAN offload ++ /* Don't allow enabling VLAN features when adapter is not capable ++ * of VLAN offload/filtering + */ + if (!VLAN_ALLOWED(adapter)) { +- if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) ++ netdev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_RX | ++ NETIF_F_HW_VLAN_CTAG_TX | ++ NETIF_F_HW_VLAN_CTAG_FILTER); ++ if (features & (NETIF_F_HW_VLAN_CTAG_RX | ++ NETIF_F_HW_VLAN_CTAG_TX | ++ NETIF_F_HW_VLAN_CTAG_FILTER)) + return -EINVAL; + } else if ((netdev->features ^ features) & NETIF_F_HW_VLAN_CTAG_RX) { + if (features & NETIF_F_HW_VLAN_CTAG_RX) +@@ -3442,7 +3591,8 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev, + { + struct iavf_adapter *adapter = netdev_priv(netdev); + +- if (!(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) ++ if (adapter->vf_res && ++ !(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)) + features &= ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_FILTER); +@@ -3630,72 +3780,14 @@ int iavf_process_config(struct iavf_adapter *adapter) + return 0; + } + +-/** +- * iavf_init_task - worker thread to perform delayed initialization +- * @work: pointer to work_struct containing our data +- * +- * This task completes the work that was begun in probe. Due to the nature +- * of VF-PF communications, we may need to wait tens of milliseconds to get +- * responses back from the PF. Rather than busy-wait in probe and bog down the +- * whole system, we'll do it in a task so we can sleep. +- * This task only runs during driver init. Once we've established +- * communications with the PF driver and set up our netdev, the watchdog +- * takes over. +- **/ +-static void iavf_init_task(struct work_struct *work) +-{ +- struct iavf_adapter *adapter = container_of(work, +- struct iavf_adapter, +- init_task.work); +- struct iavf_hw *hw = &adapter->hw; +- +- if (iavf_lock_timeout(&adapter->crit_lock, 5000)) { +- dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__); +- return; +- } +- switch (adapter->state) { +- case __IAVF_STARTUP: +- if (iavf_startup(adapter) < 0) +- goto init_failed; +- break; +- case __IAVF_INIT_VERSION_CHECK: +- if (iavf_init_version_check(adapter) < 0) +- goto init_failed; +- break; +- case __IAVF_INIT_GET_RESOURCES: +- if (iavf_init_get_resources(adapter) < 0) +- goto init_failed; +- goto out; +- default: +- goto init_failed; +- } +- +- queue_delayed_work(iavf_wq, &adapter->init_task, +- msecs_to_jiffies(30)); +- goto out; +-init_failed: +- if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) { +- dev_err(&adapter->pdev->dev, +- "Failed to communicate with PF; waiting before retry\n"); +- adapter->flags |= IAVF_FLAG_PF_COMMS_FAILED; +- iavf_shutdown_adminq(hw); +- adapter->state = __IAVF_STARTUP; +- queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5); +- goto out; +- } +- queue_delayed_work(iavf_wq, &adapter->init_task, HZ); +-out: +- mutex_unlock(&adapter->crit_lock); +-} +- + /** + * iavf_shutdown - Shutdown the device in preparation for a reboot + * @pdev: pci device structure + **/ + static void iavf_shutdown(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iavf_adapter *adapter = netdev_priv(netdev); ++ struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev); ++ struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + +@@ -3705,7 +3797,7 @@ static void iavf_shutdown(struct pci_dev *pdev) + if (iavf_lock_timeout(&adapter->crit_lock, 5000)) + dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__); + /* Prevent the watchdog from running. */ +- adapter->state = __IAVF_REMOVE; ++ iavf_change_state(adapter, __IAVF_REMOVE); + adapter->aq_required = 0; + mutex_unlock(&adapter->crit_lock); + +@@ -3778,7 +3870,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + hw->back = adapter; + + adapter->msg_enable = BIT(DEFAULT_DEBUG_LEVEL_SHIFT) - 1; +- adapter->state = __IAVF_STARTUP; ++ iavf_change_state(adapter, __IAVF_STARTUP); + + /* Call save state here because it relies on the adapter struct. */ + pci_save_state(pdev); +@@ -3803,7 +3895,6 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + */ + mutex_init(&adapter->crit_lock); + mutex_init(&adapter->client_lock); +- mutex_init(&adapter->remove_lock); + mutex_init(&hw->aq.asq_mutex); + mutex_init(&hw->aq.arq_mutex); + +@@ -3822,8 +3913,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + INIT_WORK(&adapter->adminq_task, iavf_adminq_task); + INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task); + INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task); +- INIT_DELAYED_WORK(&adapter->init_task, iavf_init_task); +- queue_delayed_work(iavf_wq, &adapter->init_task, ++ queue_delayed_work(iavf_wq, &adapter->watchdog_task, + msecs_to_jiffies(5 * (pdev->devfn & 0x07))); + + /* Setup the wait queue for indicating transition to down status */ +@@ -3880,10 +3970,11 @@ static int __maybe_unused iavf_suspend(struct device *dev_d) + static int __maybe_unused iavf_resume(struct device *dev_d) + { + struct pci_dev *pdev = to_pci_dev(dev_d); +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iavf_adapter *adapter = netdev_priv(netdev); ++ struct iavf_adapter *adapter; + u32 err; + ++ adapter = iavf_pdev_to_adapter(pdev); ++ + pci_set_master(pdev); + + rtnl_lock(); +@@ -3902,7 +3993,7 @@ static int __maybe_unused iavf_resume(struct device *dev_d) + + queue_work(iavf_wq, &adapter->reset_task); + +- netif_device_attach(netdev); ++ netif_device_attach(adapter->netdev); + + return err; + } +@@ -3918,8 +4009,8 @@ static int __maybe_unused iavf_resume(struct device *dev_d) + **/ + static void iavf_remove(struct pci_dev *pdev) + { +- struct net_device *netdev = pci_get_drvdata(pdev); +- struct iavf_adapter *adapter = netdev_priv(netdev); ++ struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev); ++ struct net_device *netdev = adapter->netdev; + struct iavf_fdir_fltr *fdir, *fdirtmp; + struct iavf_vlan_filter *vlf, *vlftmp; + struct iavf_adv_rss *rss, *rsstmp; +@@ -3927,14 +4018,30 @@ static void iavf_remove(struct pci_dev *pdev) + struct iavf_cloud_filter *cf, *cftmp; + struct iavf_hw *hw = &adapter->hw; + int err; +- /* Indicate we are in remove and not to run reset_task */ +- mutex_lock(&adapter->remove_lock); +- cancel_delayed_work_sync(&adapter->init_task); +- cancel_work_sync(&adapter->reset_task); +- cancel_delayed_work_sync(&adapter->client_task); ++ ++ set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section); ++ /* Wait until port initialization is complete. ++ * There are flows where register/unregister netdev may race. ++ */ ++ while (1) { ++ mutex_lock(&adapter->crit_lock); ++ if (adapter->state == __IAVF_RUNNING || ++ adapter->state == __IAVF_DOWN || ++ adapter->state == __IAVF_INIT_FAILED) { ++ mutex_unlock(&adapter->crit_lock); ++ break; ++ } ++ ++ mutex_unlock(&adapter->crit_lock); ++ usleep_range(500, 1000); ++ } ++ cancel_delayed_work_sync(&adapter->watchdog_task); ++ + if (adapter->netdev_registered) { +- unregister_netdev(netdev); ++ rtnl_lock(); ++ unregister_netdevice(netdev); + adapter->netdev_registered = false; ++ rtnl_unlock(); + } + if (CLIENT_ALLOWED(adapter)) { + err = iavf_lan_del_device(adapter); +@@ -3943,6 +4050,10 @@ static void iavf_remove(struct pci_dev *pdev) + err); + } + ++ mutex_lock(&adapter->crit_lock); ++ dev_info(&adapter->pdev->dev, "Remove device\n"); ++ iavf_change_state(adapter, __IAVF_REMOVE); ++ + iavf_request_reset(adapter); + msleep(50); + /* If the FW isn't responding, kick it once, but only once. */ +@@ -3950,24 +4061,24 @@ static void iavf_remove(struct pci_dev *pdev) + iavf_request_reset(adapter); + msleep(50); + } +- if (iavf_lock_timeout(&adapter->crit_lock, 5000)) +- dev_warn(&adapter->pdev->dev, "failed to acquire crit_lock in %s\n", __FUNCTION__); + ++ iavf_misc_irq_disable(adapter); + /* Shut down all the garbage mashers on the detention level */ +- adapter->state = __IAVF_REMOVE; ++ cancel_work_sync(&adapter->reset_task); ++ cancel_delayed_work_sync(&adapter->watchdog_task); ++ cancel_work_sync(&adapter->adminq_task); ++ cancel_delayed_work_sync(&adapter->client_task); ++ + adapter->aq_required = 0; + adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED; ++ + iavf_free_all_tx_resources(adapter); + iavf_free_all_rx_resources(adapter); +- iavf_misc_irq_disable(adapter); + iavf_free_misc_irq(adapter); ++ + iavf_reset_interrupt_capability(adapter); + iavf_free_q_vectors(adapter); + +- cancel_delayed_work_sync(&adapter->watchdog_task); +- +- cancel_work_sync(&adapter->adminq_task); +- + iavf_free_rss(adapter); + + if (hw->aq.asq.count) +@@ -3979,8 +4090,6 @@ static void iavf_remove(struct pci_dev *pdev) + mutex_destroy(&adapter->client_lock); + mutex_unlock(&adapter->crit_lock); + mutex_destroy(&adapter->crit_lock); +- mutex_unlock(&adapter->remove_lock); +- mutex_destroy(&adapter->remove_lock); + + iounmap(hw->hw_addr); + pci_release_regions(pdev); +diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +index 3c735968e1b85..8a1c293b8c7ab 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +@@ -607,7 +607,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter) + if (f->add) + count++; + } +- if (!count) { ++ if (!count || !VLAN_ALLOWED(adapter)) { + adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_VLAN_FILTER; + spin_unlock_bh(&adapter->mac_vlan_list_lock); + return; +@@ -673,9 +673,19 @@ void iavf_del_vlans(struct iavf_adapter *adapter) + + spin_lock_bh(&adapter->mac_vlan_list_lock); + +- list_for_each_entry(f, &adapter->vlan_filter_list, list) { +- if (f->remove) ++ list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { ++ /* since VLAN capabilities are not allowed, we dont want to send ++ * a VLAN delete request because it will most likely fail and ++ * create unnecessary errors/noise, so just free the VLAN ++ * filters marked for removal to enable bailing out before ++ * sending a virtchnl message ++ */ ++ if (f->remove && !VLAN_ALLOWED(adapter)) { ++ list_del(&f->list); ++ kfree(f); ++ } else if (f->remove) { + count++; ++ } + } + if (!count) { + adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_VLAN_FILTER; +@@ -784,6 +794,8 @@ void iavf_request_stats(struct iavf_adapter *adapter) + /* no error message, this isn't crucial */ + return; + } ++ ++ adapter->aq_required &= ~IAVF_FLAG_AQ_REQUEST_STATS; + adapter->current_op = VIRTCHNL_OP_GET_STATS; + vqs.vsi_id = adapter->vsi_res->vsi_id; + /* queue maps are ignored for this message - only the vsi is used */ +@@ -1722,8 +1734,25 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, + } + spin_lock_bh(&adapter->mac_vlan_list_lock); + iavf_add_filter(adapter, adapter->hw.mac.addr); ++ ++ if (VLAN_ALLOWED(adapter)) { ++ if (!list_empty(&adapter->vlan_filter_list)) { ++ struct iavf_vlan_filter *vlf; ++ ++ /* re-add all VLAN filters over virtchnl */ ++ list_for_each_entry(vlf, ++ &adapter->vlan_filter_list, ++ list) ++ vlf->add = true; ++ ++ adapter->aq_required |= ++ IAVF_FLAG_AQ_ADD_VLAN_FILTER; ++ } ++ } ++ + spin_unlock_bh(&adapter->mac_vlan_list_lock); + iavf_process_config(adapter); ++ adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES; + } + break; + case VIRTCHNL_OP_ENABLE_QUEUES: +@@ -1735,7 +1764,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, + iavf_free_all_tx_resources(adapter); + iavf_free_all_rx_resources(adapter); + if (adapter->state == __IAVF_DOWN_PENDING) { +- adapter->state = __IAVF_DOWN; ++ iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); + } + break; +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 3c4f08d20414e..387322615e080 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -139,13 +139,10 @@ + #define ice_for_each_q_vector(vsi, i) \ + for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++) + +-#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \ +- ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX) ++#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_UCAST_RX) + + #define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \ +- ICE_PROMISC_MCAST_TX | \ + ICE_PROMISC_UCAST_RX | \ +- ICE_PROMISC_MCAST_RX | \ + ICE_PROMISC_VLAN_TX | \ + ICE_PROMISC_VLAN_RX) + +@@ -234,7 +231,6 @@ enum ice_pf_state { + ICE_VFLR_EVENT_PENDING, + ICE_FLTR_OVERFLOW_PROMISC, + ICE_VF_DIS, +- ICE_VF_DEINIT_IN_PROGRESS, + ICE_CFG_BUSY, + ICE_SERVICE_SCHED, + ICE_SERVICE_DIS, +@@ -306,10 +302,6 @@ struct ice_vsi { + spinlock_t arfs_lock; /* protects aRFS hash table and filter state */ + atomic_t *arfs_last_fltr_id; + +- /* devlink port data */ +- struct devlink_port devlink_port; +- bool devlink_port_registered; +- + u16 max_frame; + u16 rx_buf_len; + +@@ -405,6 +397,7 @@ enum ice_pf_flags { + ICE_FLAG_VF_TRUE_PROMISC_ENA, + ICE_FLAG_MDD_AUTO_RESET_VF, + ICE_FLAG_LINK_LENIENT_MODE_ENA, ++ ICE_FLAG_PLUG_AUX_DEV, + ICE_PF_FLAGS_NBITS /* must be last */ + }; + +@@ -421,6 +414,9 @@ struct ice_pf { + struct devlink_region *nvm_region; + struct devlink_region *devcaps_region; + ++ /* devlink port data */ ++ struct devlink_port devlink_port; ++ + /* OS reserved IRQ details */ + struct msix_entry *msix_entries; + struct ice_res_tracker *irq_tracker; +@@ -696,7 +692,7 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf) + if (pf->hw.func_caps.common_cap.rdma && pf->num_rdma_msix) { + set_bit(ICE_FLAG_RDMA_ENA, pf->flags); + set_bit(ICE_FLAG_AUX_ENA, pf->flags); +- ice_plug_aux_dev(pf); ++ set_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags); + } + } + +diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c +index c36057efc7ae3..f74610442bda7 100644 +--- a/drivers/net/ethernet/intel/ice/ice_base.c ++++ b/drivers/net/ethernet/intel/ice/ice_base.c +@@ -909,7 +909,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, + } else if (status == ICE_ERR_DOES_NOT_EXIST) { + dev_dbg(ice_pf_to_dev(vsi->back), "LAN Tx queues do not exist, nothing to disable\n"); + } else if (status) { +- dev_err(ice_pf_to_dev(vsi->back), "Failed to disable LAN Tx queues, error: %s\n", ++ dev_dbg(ice_pf_to_dev(vsi->back), "Failed to disable LAN Tx queues, error: %s\n", + ice_stat_str(status)); + return -ENODEV; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c +index df5ad4de1f00e..3de6f16f985ab 100644 +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -3270,9 +3270,10 @@ ice_cfg_phy_fec(struct ice_port_info *pi, struct ice_aqc_set_phy_cfg_data *cfg, + + if (fec == ICE_FEC_AUTO && ice_fw_supports_link_override(hw) && + !ice_fw_supports_report_dflt_cfg(hw)) { +- struct ice_link_default_override_tlv tlv; ++ struct ice_link_default_override_tlv tlv = { 0 }; + +- if (ice_get_link_default_override(&tlv, pi)) ++ status = ice_get_link_default_override(&tlv, pi); ++ if (status) + goto out; + + if (!(tlv.options & ICE_LINK_OVERRIDE_STRICT_MODE) && +diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c +index da7288bdc9a3f..2ec5d5cb72803 100644 +--- a/drivers/net/ethernet/intel/ice/ice_devlink.c ++++ b/drivers/net/ethernet/intel/ice/ice_devlink.c +@@ -526,60 +526,115 @@ void ice_devlink_unregister(struct ice_pf *pf) + } + + /** +- * ice_devlink_create_port - Create a devlink port for this VSI +- * @vsi: the VSI to create a port for ++ * ice_devlink_create_pf_port - Create a devlink port for this PF ++ * @pf: the PF to create a devlink port for + * +- * Create and register a devlink_port for this VSI. ++ * Create and register a devlink_port for this PF. + * + * Return: zero on success or an error code on failure. + */ +-int ice_devlink_create_port(struct ice_vsi *vsi) ++int ice_devlink_create_pf_port(struct ice_pf *pf) + { + struct devlink_port_attrs attrs = {}; +- struct ice_port_info *pi; ++ struct devlink_port *devlink_port; + struct devlink *devlink; ++ struct ice_vsi *vsi; + struct device *dev; +- struct ice_pf *pf; + int err; + +- /* Currently we only create devlink_port instances for PF VSIs */ +- if (vsi->type != ICE_VSI_PF) +- return -EINVAL; +- +- pf = vsi->back; +- devlink = priv_to_devlink(pf); + dev = ice_pf_to_dev(pf); +- pi = pf->hw.port_info; ++ ++ devlink_port = &pf->devlink_port; ++ ++ vsi = ice_get_main_vsi(pf); ++ if (!vsi) ++ return -EIO; + + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; +- attrs.phys.port_number = pi->lport; +- devlink_port_attrs_set(&vsi->devlink_port, &attrs); +- err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx); ++ attrs.phys.port_number = pf->hw.bus.func; ++ devlink_port_attrs_set(devlink_port, &attrs); ++ devlink = priv_to_devlink(pf); ++ ++ err = devlink_port_register(devlink, devlink_port, vsi->idx); + if (err) { +- dev_err(dev, "devlink_port_register failed: %d\n", err); ++ dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", ++ pf->hw.pf_id, err); + return err; + } + +- vsi->devlink_port_registered = true; ++ return 0; ++} ++ ++/** ++ * ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF ++ * @pf: the PF to cleanup ++ * ++ * Unregisters the devlink_port structure associated with this PF. ++ */ ++void ice_devlink_destroy_pf_port(struct ice_pf *pf) ++{ ++ struct devlink_port *devlink_port; ++ ++ devlink_port = &pf->devlink_port; ++ ++ devlink_port_type_clear(devlink_port); ++ devlink_port_unregister(devlink_port); ++} ++ ++/** ++ * ice_devlink_create_vf_port - Create a devlink port for this VF ++ * @vf: the VF to create a port for ++ * ++ * Create and register a devlink_port for this VF. ++ * ++ * Return: zero on success or an error code on failure. ++ */ ++int ice_devlink_create_vf_port(struct ice_vf *vf) ++{ ++ struct devlink_port_attrs attrs = {}; ++ struct devlink_port *devlink_port; ++ struct devlink *devlink; ++ struct ice_vsi *vsi; ++ struct device *dev; ++ struct ice_pf *pf; ++ int err; ++ ++ pf = vf->pf; ++ dev = ice_pf_to_dev(pf); ++ vsi = ice_get_vf_vsi(vf); ++ devlink_port = &vf->devlink_port; ++ ++ attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; ++ attrs.pci_vf.pf = pf->hw.bus.func; ++ attrs.pci_vf.vf = vf->vf_id; ++ ++ devlink_port_attrs_set(devlink_port, &attrs); ++ devlink = priv_to_devlink(pf); ++ ++ err = devlink_port_register(devlink, devlink_port, vsi->idx); ++ if (err) { ++ dev_err(dev, "Failed to create devlink port for VF %d, error %d\n", ++ vf->vf_id, err); ++ return err; ++ } + + return 0; + } + + /** +- * ice_devlink_destroy_port - Destroy the devlink_port for this VSI +- * @vsi: the VSI to cleanup ++ * ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF ++ * @vf: the VF to cleanup + * +- * Unregisters the devlink_port structure associated with this VSI. ++ * Unregisters the devlink_port structure associated with this VF. + */ +-void ice_devlink_destroy_port(struct ice_vsi *vsi) ++void ice_devlink_destroy_vf_port(struct ice_vf *vf) + { +- if (!vsi->devlink_port_registered) +- return; ++ struct devlink_port *devlink_port; + +- devlink_port_type_clear(&vsi->devlink_port); +- devlink_port_unregister(&vsi->devlink_port); ++ devlink_port = &vf->devlink_port; + +- vsi->devlink_port_registered = false; ++ devlink_port_type_clear(devlink_port); ++ devlink_port_unregister(devlink_port); + } + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.h b/drivers/net/ethernet/intel/ice/ice_devlink.h +index e07e74426bde8..e30284ccbed4c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_devlink.h ++++ b/drivers/net/ethernet/intel/ice/ice_devlink.h +@@ -8,8 +8,10 @@ struct ice_pf *ice_allocate_pf(struct device *dev); + + int ice_devlink_register(struct ice_pf *pf); + void ice_devlink_unregister(struct ice_pf *pf); +-int ice_devlink_create_port(struct ice_vsi *vsi); +-void ice_devlink_destroy_port(struct ice_vsi *vsi); ++int ice_devlink_create_pf_port(struct ice_pf *pf); ++void ice_devlink_destroy_pf_port(struct ice_pf *pf); ++int ice_devlink_create_vf_port(struct ice_vf *vf); ++void ice_devlink_destroy_vf_port(struct ice_vf *vf); + + void ice_devlink_init_regions(struct ice_pf *pf); + void ice_devlink_destroy_regions(struct ice_pf *pf); +diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c +index e375ac849aecd..4f954db01b929 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lag.c ++++ b/drivers/net/ethernet/intel/ice/ice_lag.c +@@ -204,17 +204,39 @@ ice_lag_unlink(struct ice_lag *lag, + lag->upper_netdev = NULL; + } + +- if (lag->peer_netdev) { +- dev_put(lag->peer_netdev); +- lag->peer_netdev = NULL; +- } +- ++ lag->peer_netdev = NULL; + ice_set_sriov_cap(pf); + ice_set_rdma_cap(pf); + lag->bonded = false; + lag->role = ICE_LAG_NONE; + } + ++/** ++ * ice_lag_unregister - handle netdev unregister events ++ * @lag: LAG info struct ++ * @netdev: netdev reporting the event ++ */ ++static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev) ++{ ++ struct ice_pf *pf = lag->pf; ++ ++ /* check to see if this event is for this netdev ++ * check that we are in an aggregate ++ */ ++ if (netdev != lag->netdev || !lag->bonded) ++ return; ++ ++ if (lag->upper_netdev) { ++ dev_put(lag->upper_netdev); ++ lag->upper_netdev = NULL; ++ ice_set_sriov_cap(pf); ++ ice_set_rdma_cap(pf); ++ } ++ /* perform some cleanup in case we come back */ ++ lag->bonded = false; ++ lag->role = ICE_LAG_NONE; ++} ++ + /** + * ice_lag_changeupper_event - handle LAG changeupper event + * @lag: LAG info struct +@@ -307,7 +329,7 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event, + ice_lag_info_event(lag, ptr); + break; + case NETDEV_UNREGISTER: +- ice_lag_unlink(lag, ptr); ++ ice_lag_unregister(lag, netdev); + break; + default: + break; +diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +index 80736e0ec0dca..3f635fdbfaff9 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h ++++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +@@ -528,6 +528,7 @@ struct ice_tx_ctx_desc { + (0x3FFFFULL << ICE_TXD_CTX_QW1_TSO_LEN_S) + + #define ICE_TXD_CTX_QW1_MSS_S 50 ++#define ICE_TXD_CTX_MIN_MSS 64 + + enum ice_tx_ctx_desc_cmd_bits { + ICE_TX_CTX_DESC_TSO = 0x01, +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index b718e196af2a4..8c08997dcef64 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -83,8 +83,13 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) + if (!vsi->rx_rings) + goto err_rings; + +- /* XDP will have vsi->alloc_txq Tx queues as well, so double the size */ +- vsi->txq_map = devm_kcalloc(dev, (2 * vsi->alloc_txq), ++ /* txq_map needs to have enough space to track both Tx (stack) rings ++ * and XDP rings; at this point vsi->num_xdp_txq might not be set, ++ * so use num_possible_cpus() as we want to always provide XDP ring ++ * per CPU, regardless of queue count settings from user that might ++ * have come from ethtool's set_channels() callback; ++ */ ++ vsi->txq_map = devm_kcalloc(dev, (vsi->alloc_txq + num_possible_cpus()), + sizeof(*vsi->txq_map), GFP_KERNEL); + + if (!vsi->txq_map) +@@ -1516,6 +1521,12 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) + if (status) + dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %s\n", + vsi_num, ice_stat_str(status)); ++ ++ status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_ESP_SPI, ++ ICE_FLOW_SEG_HDR_ESP); ++ if (status) ++ dev_dbg(dev, "ice_add_rss_cfg failed for esp/spi flow, vsi = %d, error = %d\n", ++ vsi_num, status); + } + + /** +@@ -2860,7 +2871,8 @@ int ice_vsi_release(struct ice_vsi *vsi) + clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state); + } + +- ice_devlink_destroy_port(vsi); ++ if (vsi->type == ICE_VSI_PF) ++ ice_devlink_destroy_pf_port(pf); + + if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) + ice_rss_clean(vsi); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 06fa93e597fbc..8a0c928853e6a 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -1679,7 +1679,9 @@ static void ice_handle_mdd_event(struct ice_pf *pf) + * reset, so print the event prior to reset. + */ + ice_print_vf_rx_mdd_event(vf); ++ mutex_lock(&pf->vf[i].cfg_lock); + ice_reset_vf(&pf->vf[i], false); ++ mutex_unlock(&pf->vf[i].cfg_lock); + } + } + } +@@ -2141,6 +2143,9 @@ static void ice_service_task(struct work_struct *work) + return; + } + ++ if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) ++ ice_plug_aux_dev(pf); ++ + ice_clean_adminq_subtask(pf); + ice_check_media_subtask(pf); + ice_check_for_hang_subtask(pf); +@@ -2497,7 +2502,18 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog) + ice_stat_str(status)); + goto clear_xdp_rings; + } +- ice_vsi_assign_bpf_prog(vsi, prog); ++ ++ /* assign the prog only when it's not already present on VSI; ++ * this flow is a subject of both ethtool -L and ndo_bpf flows; ++ * VSI rebuild that happens under ethtool -L can expose us to ++ * the bpf_prog refcount issues as we would be swapping same ++ * bpf_prog pointers from vsi->xdp_prog and calling bpf_prog_put ++ * on it as it would be treated as an 'old_prog'; for ndo_bpf ++ * this is not harmful as dev_xdp_install bumps the refcount ++ * before calling the op exposed by the driver; ++ */ ++ if (!ice_is_xdp_ena_vsi(vsi)) ++ ice_vsi_assign_bpf_prog(vsi, prog); + + return 0; + clear_xdp_rings: +@@ -2643,6 +2659,11 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog, + if (xdp_ring_err) + NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed"); + } else { ++ /* safe to call even when prog == vsi->xdp_prog as ++ * dev_xdp_install in net/core/dev.c incremented prog's ++ * refcount so corresponding bpf_prog_put won't cause ++ * underflow ++ */ + ice_vsi_assign_bpf_prog(vsi, prog); + } + +@@ -4170,11 +4191,11 @@ static int ice_register_netdev(struct ice_pf *pf) + set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state); + netif_carrier_off(vsi->netdev); + netif_tx_stop_all_queues(vsi->netdev); +- err = ice_devlink_create_port(vsi); ++ err = ice_devlink_create_pf_port(pf); + if (err) + goto err_devlink_create; + +- devlink_port_type_eth_set(&vsi->devlink_port, vsi->netdev); ++ devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev); + + return 0; + err_devlink_create: +@@ -4600,9 +4621,6 @@ static void ice_remove(struct pci_dev *pdev) + struct ice_pf *pf = pci_get_drvdata(pdev); + int i; + +- if (!pf) +- return; +- + for (i = 0; i < ICE_MAX_RESET_WAIT; i++) { + if (!ice_is_reset_in_progress(pf->state)) + break; +@@ -5608,6 +5626,9 @@ static int ice_up_complete(struct ice_vsi *vsi) + netif_carrier_on(vsi->netdev); + } + ++ /* clear this now, and the first stats read will be used as baseline */ ++ vsi->stat_offsets_loaded = false; ++ + ice_service_task_schedule(pf); + + return 0; +@@ -7190,6 +7211,7 @@ ice_features_check(struct sk_buff *skb, + struct net_device __always_unused *netdev, + netdev_features_t features) + { ++ bool gso = skb_is_gso(skb); + size_t len; + + /* No point in doing any of this if neither checksum nor GSO are +@@ -7202,24 +7224,32 @@ ice_features_check(struct sk_buff *skb, + /* We cannot support GSO if the MSS is going to be less than + * 64 bytes. If it is then we need to drop support for GSO. + */ +- if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64)) ++ if (gso && (skb_shinfo(skb)->gso_size < ICE_TXD_CTX_MIN_MSS)) + features &= ~NETIF_F_GSO_MASK; + +- len = skb_network_header(skb) - skb->data; ++ len = skb_network_offset(skb); + if (len > ICE_TXD_MACLEN_MAX || len & 0x1) + goto out_rm_features; + +- len = skb_transport_header(skb) - skb_network_header(skb); ++ len = skb_network_header_len(skb); + if (len > ICE_TXD_IPLEN_MAX || len & 0x1) + goto out_rm_features; + + if (skb->encapsulation) { +- len = skb_inner_network_header(skb) - skb_transport_header(skb); +- if (len > ICE_TXD_L4LEN_MAX || len & 0x1) +- goto out_rm_features; ++ /* this must work for VXLAN frames AND IPIP/SIT frames, and in ++ * the case of IPIP frames, the transport header pointer is ++ * after the inner header! So check to make sure that this ++ * is a GRE or UDP_TUNNEL frame before doing that math. ++ */ ++ if (gso && (skb_shinfo(skb)->gso_type & ++ (SKB_GSO_GRE | SKB_GSO_UDP_TUNNEL))) { ++ len = skb_inner_network_header(skb) - ++ skb_transport_header(skb); ++ if (len > ICE_TXD_L4LEN_MAX || len & 0x1) ++ goto out_rm_features; ++ } + +- len = skb_inner_transport_header(skb) - +- skb_inner_network_header(skb); ++ len = skb_inner_network_header_len(skb); + if (len > ICE_TXD_IPLEN_MAX || len & 0x1) + goto out_rm_features; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index d1ef3d48a4b03..eb91936825795 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -459,7 +459,7 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm) + scaled_ppm = -scaled_ppm; + } + +- while ((u64)scaled_ppm > div_u64(U64_MAX, incval)) { ++ while ((u64)scaled_ppm > div64_u64(U64_MAX, incval)) { + /* handle overflow by scaling down the scaled_ppm and + * the divisor, losing some precision + */ +@@ -846,9 +846,12 @@ exit: + static int ice_ptp_adjtime_nonatomic(struct ptp_clock_info *info, s64 delta) + { + struct timespec64 now, then; ++ int ret; + + then = ns_to_timespec64(delta); +- ice_ptp_gettimex64(info, &now, NULL); ++ ret = ice_ptp_gettimex64(info, &now, NULL); ++ if (ret) ++ return ret; + now = timespec64_add(now, then); + + return ice_ptp_settime64(info, (const struct timespec64 *)&now); +@@ -1182,19 +1185,16 @@ static void ice_ptp_tx_tstamp_work(struct kthread_work *work) + if (err) + continue; + +- /* Check if the timestamp is valid */ +- if (!(raw_tstamp & ICE_PTP_TS_VALID)) ++ /* Check if the timestamp is invalid or stale */ ++ if (!(raw_tstamp & ICE_PTP_TS_VALID) || ++ raw_tstamp == tx->tstamps[idx].cached_tstamp) + continue; + +- /* clear the timestamp register, so that it won't show valid +- * again when re-used. +- */ +- ice_clear_phy_tstamp(hw, tx->quad, phy_idx); +- + /* The timestamp is valid, so we'll go ahead and clear this + * index and then send the timestamp up to the stack. + */ + spin_lock(&tx->lock); ++ tx->tstamps[idx].cached_tstamp = raw_tstamp; + clear_bit(idx, tx->in_use); + skb = tx->tstamps[idx].skb; + tx->tstamps[idx].skb = NULL; +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h +index e1c787bd5b967..8cdd6f7046b73 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.h ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h +@@ -46,15 +46,21 @@ struct ice_perout_channel { + * struct ice_tx_tstamp - Tracking for a single Tx timestamp + * @skb: pointer to the SKB for this timestamp request + * @start: jiffies when the timestamp was first requested ++ * @cached_tstamp: last read timestamp + * + * This structure tracks a single timestamp request. The SKB pointer is + * provided when initiating a request. The start time is used to ensure that + * we discard old requests that were not fulfilled within a 2 second time + * window. ++ * Timestamp values in the PHY are read only and do not get cleared except at ++ * hardware reset or when a new timestamp value is captured. The cached_tstamp ++ * field is used to detect the case where a new timestamp has not yet been ++ * captured, ensuring that we avoid sending stale timestamp data to the stack. + */ + struct ice_tx_tstamp { + struct sk_buff *skb; + unsigned long start; ++ u64 cached_tstamp; + }; + + /** +diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h +index 1e46e80f3d6f8..7c2328529ff8e 100644 +--- a/drivers/net/ethernet/intel/ice/ice_txrx.h ++++ b/drivers/net/ethernet/intel/ice/ice_txrx.h +@@ -164,17 +164,10 @@ struct ice_tx_offload_params { + }; + + struct ice_rx_buf { +- union { +- struct { +- dma_addr_t dma; +- struct page *page; +- unsigned int page_offset; +- u16 pagecnt_bias; +- }; +- struct { +- struct xdp_buff *xdp; +- }; +- }; ++ dma_addr_t dma; ++ struct page *page; ++ unsigned int page_offset; ++ u16 pagecnt_bias; + }; + + struct ice_q_stats { +@@ -270,6 +263,7 @@ struct ice_ring { + union { + struct ice_tx_buf *tx_buf; + struct ice_rx_buf *rx_buf; ++ struct xdp_buff **xdp_buf; + }; + /* CL2 - 2nd cacheline starts here */ + u16 q_index; /* Queue number of ring */ +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +index e93430ab37f1e..4054adb5279c3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +@@ -251,7 +251,7 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list_comms[] = { + * ice_get_vf_vsi - get VF's VSI based on the stored index + * @vf: VF used to get VSI + */ +-static struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) ++struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) + { + return vf->pf->vsi[vf->lan_vsi_idx]; + } +@@ -615,8 +615,6 @@ void ice_free_vfs(struct ice_pf *pf) + struct ice_hw *hw = &pf->hw; + unsigned int tmp, i; + +- set_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state); +- + if (!pf->vf) + return; + +@@ -632,21 +630,26 @@ void ice_free_vfs(struct ice_pf *pf) + else + dev_warn(dev, "VFs are assigned - not disabling SR-IOV\n"); + +- /* Avoid wait time by stopping all VFs at the same time */ +- ice_for_each_vf(pf, i) +- if (test_bit(ICE_VF_STATE_QS_ENA, pf->vf[i].vf_states)) +- ice_dis_vf_qs(&pf->vf[i]); +- + tmp = pf->num_alloc_vfs; + pf->num_qps_per_vf = 0; + pf->num_alloc_vfs = 0; + for (i = 0; i < tmp; i++) { +- if (test_bit(ICE_VF_STATE_INIT, pf->vf[i].vf_states)) { ++ struct ice_vf *vf = &pf->vf[i]; ++ ++ mutex_lock(&vf->cfg_lock); ++ ++ ice_dis_vf_qs(vf); ++ ++ if (test_bit(ICE_VF_STATE_INIT, vf->vf_states)) { + /* disable VF qp mappings and set VF disable state */ +- ice_dis_vf_mappings(&pf->vf[i]); +- set_bit(ICE_VF_STATE_DIS, pf->vf[i].vf_states); +- ice_free_vf_res(&pf->vf[i]); ++ ice_dis_vf_mappings(vf); ++ set_bit(ICE_VF_STATE_DIS, vf->vf_states); ++ ice_free_vf_res(vf); + } ++ ++ mutex_unlock(&vf->cfg_lock); ++ ++ mutex_destroy(&vf->cfg_lock); + } + + if (ice_sriov_free_msix_res(pf)) +@@ -682,7 +685,6 @@ void ice_free_vfs(struct ice_pf *pf) + i); + + clear_bit(ICE_VF_DIS, pf->state); +- clear_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state); + clear_bit(ICE_FLAG_SRIOV_ENA, pf->flags); + } + +@@ -1566,10 +1568,13 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr) + ice_for_each_vf(pf, v) { + vf = &pf->vf[v]; + ++ mutex_lock(&vf->cfg_lock); ++ + vf->driver_caps = 0; + ice_vc_set_default_allowlist(vf); + + ice_vf_fdir_exit(vf); ++ ice_vf_fdir_init(vf); + /* clean VF control VSI when resetting VFs since it should be + * setup only when VF creates its first FDIR rule. + */ +@@ -1579,6 +1584,8 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr) + ice_vf_pre_vsi_rebuild(vf); + ice_vf_rebuild_vsi(vf); + ice_vf_post_vsi_rebuild(vf); ++ ++ mutex_unlock(&vf->cfg_lock); + } + + ice_flush(hw); +@@ -1625,6 +1632,8 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) + u32 reg; + int i; + ++ lockdep_assert_held(&vf->cfg_lock); ++ + dev = ice_pf_to_dev(pf); + + if (test_bit(ICE_VF_RESETS_DISABLED, pf->state)) { +@@ -1645,8 +1654,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) + + vsi = ice_get_vf_vsi(vf); + +- if (test_bit(ICE_VF_STATE_QS_ENA, vf->vf_states)) +- ice_dis_vf_qs(vf); ++ ice_dis_vf_qs(vf); + + /* Call Disable LAN Tx queue AQ whether or not queues are + * enabled. This is needed for successful completion of VFR. +@@ -1697,6 +1705,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) + } + + ice_vf_fdir_exit(vf); ++ ice_vf_fdir_init(vf); + /* clean VF control VSI when resetting VF since it should be setup + * only when VF creates its first FDIR rule. + */ +@@ -1894,6 +1903,8 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf) + */ + ice_vf_ctrl_invalidate_vsi(vf); + ice_vf_fdir_init(vf); ++ ++ mutex_init(&vf->cfg_lock); + } + } + +@@ -2109,9 +2120,12 @@ void ice_process_vflr_event(struct ice_pf *pf) + bit_idx = (hw->func_caps.vf_base_id + vf_id) % 32; + /* read GLGEN_VFLRSTAT register to find out the flr VFs */ + reg = rd32(hw, GLGEN_VFLRSTAT(reg_idx)); +- if (reg & BIT(bit_idx)) ++ if (reg & BIT(bit_idx)) { + /* GLGEN_VFLRSTAT bit will be cleared in ice_reset_vf */ ++ mutex_lock(&vf->cfg_lock); + ice_reset_vf(vf, true); ++ mutex_unlock(&vf->cfg_lock); ++ } + } + } + +@@ -2188,7 +2202,9 @@ ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event) + if (!vf) + return; + ++ mutex_lock(&vf->cfg_lock); + ice_vc_reset_vf(vf); ++ mutex_unlock(&vf->cfg_lock); + } + + /** +@@ -2954,6 +2970,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf) + static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) + { + enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; ++ enum ice_status mcast_status = 0, ucast_status = 0; + bool rm_promisc, alluni = false, allmulti = false; + struct virtchnl_promisc_info *info = + (struct virtchnl_promisc_info *)msg; +@@ -3043,52 +3060,51 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) + goto error_param; + } + } else { +- enum ice_status status; +- u8 promisc_m; +- +- if (alluni) { +- if (vf->port_vlan_info || vsi->num_vlan) +- promisc_m = ICE_UCAST_VLAN_PROMISC_BITS; +- else +- promisc_m = ICE_UCAST_PROMISC_BITS; +- } else if (allmulti) { +- if (vf->port_vlan_info || vsi->num_vlan) +- promisc_m = ICE_MCAST_VLAN_PROMISC_BITS; +- else +- promisc_m = ICE_MCAST_PROMISC_BITS; ++ u8 mcast_m, ucast_m; ++ ++ if (vf->port_vlan_info || vsi->num_vlan > 1) { ++ mcast_m = ICE_MCAST_VLAN_PROMISC_BITS; ++ ucast_m = ICE_UCAST_VLAN_PROMISC_BITS; + } else { +- if (vf->port_vlan_info || vsi->num_vlan) +- promisc_m = ICE_UCAST_VLAN_PROMISC_BITS; +- else +- promisc_m = ICE_UCAST_PROMISC_BITS; ++ mcast_m = ICE_MCAST_PROMISC_BITS; ++ ucast_m = ICE_UCAST_PROMISC_BITS; + } + +- /* Configure multicast/unicast with or without VLAN promiscuous +- * mode +- */ +- status = ice_vf_set_vsi_promisc(vf, vsi, promisc_m, rm_promisc); +- if (status) { +- dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed, error: %s\n", +- rm_promisc ? "dis" : "en", vf->vf_id, +- ice_stat_str(status)); +- v_ret = ice_err_to_virt_err(status); +- goto error_param; +- } else { +- dev_dbg(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d succeeded\n", +- rm_promisc ? "dis" : "en", vf->vf_id); ++ ucast_status = ice_vf_set_vsi_promisc(vf, vsi, ucast_m, ++ !alluni); ++ if (ucast_status) { ++ dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed\n", ++ alluni ? "en" : "dis", vf->vf_id); ++ v_ret = ice_err_to_virt_err(ucast_status); ++ } ++ ++ mcast_status = ice_vf_set_vsi_promisc(vf, vsi, mcast_m, ++ !allmulti); ++ if (mcast_status) { ++ dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed\n", ++ allmulti ? "en" : "dis", vf->vf_id); ++ v_ret = ice_err_to_virt_err(mcast_status); + } + } + +- if (allmulti && +- !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) +- dev_info(dev, "VF %u successfully set multicast promiscuous mode\n", vf->vf_id); +- else if (!allmulti && test_and_clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) +- dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n", vf->vf_id); ++ if (!mcast_status) { ++ if (allmulti && ++ !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) ++ dev_info(dev, "VF %u successfully set multicast promiscuous mode\n", ++ vf->vf_id); ++ else if (!allmulti && test_and_clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) ++ dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n", ++ vf->vf_id); ++ } + +- if (alluni && !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) +- dev_info(dev, "VF %u successfully set unicast promiscuous mode\n", vf->vf_id); +- else if (!alluni && test_and_clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) +- dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n", vf->vf_id); ++ if (!ucast_status) { ++ if (alluni && !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) ++ dev_info(dev, "VF %u successfully set unicast promiscuous mode\n", ++ vf->vf_id); ++ else if (!alluni && test_and_clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) ++ dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n", ++ vf->vf_id); ++ } + + error_param: + return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, +@@ -3762,6 +3778,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, + struct device *dev = ice_pf_to_dev(vf->pf); + u8 *mac_addr = vc_ether_addr->addr; + enum ice_status status; ++ int ret = 0; + + /* device MAC already added */ + if (ether_addr_equal(mac_addr, vf->dev_lan_addr.addr)) +@@ -3774,20 +3791,23 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, + + status = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI); + if (status == ICE_ERR_ALREADY_EXISTS) { +- dev_err(dev, "MAC %pM already exists for VF %d\n", mac_addr, ++ dev_dbg(dev, "MAC %pM already exists for VF %d\n", mac_addr, + vf->vf_id); +- return -EEXIST; ++ /* don't return since we might need to update ++ * the primary MAC in ice_vfhw_mac_add() below ++ */ ++ ret = -EEXIST; + } else if (status) { + dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %s\n", + mac_addr, vf->vf_id, ice_stat_str(status)); + return -EIO; ++ } else { ++ vf->num_mac++; + } + + ice_vfhw_mac_add(vf, vc_ether_addr); + +- vf->num_mac++; +- +- return 0; ++ return ret; + } + + /** +@@ -4078,6 +4098,8 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, + return 0; + } + ++ mutex_lock(&vf->cfg_lock); ++ + vf->port_vlan_info = vlanprio; + + if (vf->port_vlan_info) +@@ -4087,6 +4109,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, + dev_info(dev, "Clearing port VLAN on VF %d\n", vf_id); + + ice_vc_reset_vf(vf); ++ mutex_unlock(&vf->cfg_lock); + + return 0; + } +@@ -4418,10 +4441,6 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) + struct device *dev; + int err = 0; + +- /* if de-init is underway, don't process messages from VF */ +- if (test_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state)) +- return; +- + dev = ice_pf_to_dev(pf); + if (ice_validate_vf_id(pf, vf_id)) { + err = -EINVAL; +@@ -4461,6 +4480,15 @@ error_handler: + return; + } + ++ /* VF is being configured in another context that triggers a VFR, so no ++ * need to process this message ++ */ ++ if (!mutex_trylock(&vf->cfg_lock)) { ++ dev_info(dev, "VF %u is being configured in another context that will trigger a VFR, so there is no need to handle this message\n", ++ vf->vf_id); ++ return; ++ } ++ + switch (v_opcode) { + case VIRTCHNL_OP_VERSION: + err = ice_vc_get_ver_msg(vf, msg); +@@ -4549,6 +4577,8 @@ error_handler: + dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n", + vf_id, v_opcode, err); + } ++ ++ mutex_unlock(&vf->cfg_lock); + } + + /** +@@ -4664,6 +4694,8 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) + return -EINVAL; + } + ++ mutex_lock(&vf->cfg_lock); ++ + /* VF is notified of its new MAC via the PF's response to the + * VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset + */ +@@ -4682,6 +4714,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) + } + + ice_vc_reset_vf(vf); ++ mutex_unlock(&vf->cfg_lock); + return 0; + } + +@@ -4711,11 +4744,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted) + if (trusted == vf->trusted) + return 0; + ++ mutex_lock(&vf->cfg_lock); ++ + vf->trusted = trusted; + ice_vc_reset_vf(vf); + dev_info(ice_pf_to_dev(pf), "VF %u is now %strusted\n", + vf_id, trusted ? "" : "un"); + ++ mutex_unlock(&vf->cfg_lock); ++ + return 0; + } + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h +index 842cb077df861..a750e9a9d7125 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h +@@ -74,6 +74,11 @@ struct ice_mdd_vf_events { + struct ice_vf { + struct ice_pf *pf; + ++ /* Used during virtchnl message handling and NDO ops against the VF ++ * that will trigger a VFR ++ */ ++ struct mutex cfg_lock; ++ + u16 vf_id; /* VF ID in the PF space */ + u16 lan_vsi_idx; /* index into PF struct */ + u16 ctrl_vsi_idx; +@@ -111,9 +116,13 @@ struct ice_vf { + struct ice_mdd_vf_events mdd_rx_events; + struct ice_mdd_vf_events mdd_tx_events; + DECLARE_BITMAP(opcodes_allowlist, VIRTCHNL_OP_MAX); ++ ++ /* devlink port data */ ++ struct devlink_port devlink_port; + }; + + #ifdef CONFIG_PCI_IOV ++struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf); + void ice_process_vflr_event(struct ice_pf *pf); + int ice_sriov_configure(struct pci_dev *pdev, int num_vfs); + int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac); +@@ -171,6 +180,11 @@ static inline void ice_print_vfs_mdd_events(struct ice_pf *pf) { } + static inline void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { } + static inline void ice_restore_all_vfs_msi_state(struct pci_dev *pdev) { } + ++static inline struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf) ++{ ++ return NULL; ++} ++ + static inline bool + ice_is_malicious_vf(struct ice_pf __always_unused *pf, + struct ice_rq_event_info __always_unused *event, +diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c +index 5a9f61deeb38d..37c7dc6b44a9f 100644 +--- a/drivers/net/ethernet/intel/ice/ice_xsk.c ++++ b/drivers/net/ethernet/intel/ice/ice_xsk.c +@@ -364,7 +364,7 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count) + { + union ice_32b_rx_flex_desc *rx_desc; + u16 ntu = rx_ring->next_to_use; +- struct ice_rx_buf *rx_buf; ++ struct xdp_buff **xdp; + bool ok = true; + dma_addr_t dma; + +@@ -372,26 +372,26 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count) + return true; + + rx_desc = ICE_RX_DESC(rx_ring, ntu); +- rx_buf = &rx_ring->rx_buf[ntu]; ++ xdp = &rx_ring->xdp_buf[ntu]; + + do { +- rx_buf->xdp = xsk_buff_alloc(rx_ring->xsk_pool); +- if (!rx_buf->xdp) { ++ *xdp = xsk_buff_alloc(rx_ring->xsk_pool); ++ if (!xdp) { + ok = false; + break; + } + +- dma = xsk_buff_xdp_get_dma(rx_buf->xdp); ++ dma = xsk_buff_xdp_get_dma(*xdp); + rx_desc->read.pkt_addr = cpu_to_le64(dma); + rx_desc->wb.status_error0 = 0; + + rx_desc++; +- rx_buf++; ++ xdp++; + ntu++; + + if (unlikely(ntu == rx_ring->count)) { + rx_desc = ICE_RX_DESC(rx_ring, 0); +- rx_buf = rx_ring->rx_buf; ++ xdp = rx_ring->xdp_buf; + ntu = 0; + } + } while (--count); +@@ -421,19 +421,19 @@ static void ice_bump_ntc(struct ice_ring *rx_ring) + /** + * ice_construct_skb_zc - Create an sk_buff from zero-copy buffer + * @rx_ring: Rx ring +- * @rx_buf: zero-copy Rx buffer ++ * @xdp_arr: Pointer to the SW ring of xdp_buff pointers + * + * This function allocates a new skb from a zero-copy Rx buffer. + * + * Returns the skb on success, NULL on failure. + */ + static struct sk_buff * +-ice_construct_skb_zc(struct ice_ring *rx_ring, struct ice_rx_buf *rx_buf) ++ice_construct_skb_zc(struct ice_ring *rx_ring, struct xdp_buff **xdp_arr) + { +- unsigned int metasize = rx_buf->xdp->data - rx_buf->xdp->data_meta; +- unsigned int datasize = rx_buf->xdp->data_end - rx_buf->xdp->data; +- unsigned int datasize_hard = rx_buf->xdp->data_end - +- rx_buf->xdp->data_hard_start; ++ struct xdp_buff *xdp = *xdp_arr; ++ unsigned int metasize = xdp->data - xdp->data_meta; ++ unsigned int datasize = xdp->data_end - xdp->data; ++ unsigned int datasize_hard = xdp->data_end - xdp->data_hard_start; + struct sk_buff *skb; + + skb = __napi_alloc_skb(&rx_ring->q_vector->napi, datasize_hard, +@@ -441,13 +441,13 @@ ice_construct_skb_zc(struct ice_ring *rx_ring, struct ice_rx_buf *rx_buf) + if (unlikely(!skb)) + return NULL; + +- skb_reserve(skb, rx_buf->xdp->data - rx_buf->xdp->data_hard_start); +- memcpy(__skb_put(skb, datasize), rx_buf->xdp->data, datasize); ++ skb_reserve(skb, xdp->data - xdp->data_hard_start); ++ memcpy(__skb_put(skb, datasize), xdp->data, datasize); + if (metasize) + skb_metadata_set(skb, metasize); + +- xsk_buff_free(rx_buf->xdp); +- rx_buf->xdp = NULL; ++ xsk_buff_free(xdp); ++ *xdp_arr = NULL; + return skb; + } + +@@ -521,7 +521,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget) + while (likely(total_rx_packets < (unsigned int)budget)) { + union ice_32b_rx_flex_desc *rx_desc; + unsigned int size, xdp_res = 0; +- struct ice_rx_buf *rx_buf; ++ struct xdp_buff **xdp; + struct sk_buff *skb; + u16 stat_err_bits; + u16 vlan_tag = 0; +@@ -544,18 +544,18 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget) + if (!size) + break; + +- rx_buf = &rx_ring->rx_buf[rx_ring->next_to_clean]; +- rx_buf->xdp->data_end = rx_buf->xdp->data + size; +- xsk_buff_dma_sync_for_cpu(rx_buf->xdp, rx_ring->xsk_pool); ++ xdp = &rx_ring->xdp_buf[rx_ring->next_to_clean]; ++ (*xdp)->data_end = (*xdp)->data + size; ++ xsk_buff_dma_sync_for_cpu(*xdp, rx_ring->xsk_pool); + +- xdp_res = ice_run_xdp_zc(rx_ring, rx_buf->xdp); ++ xdp_res = ice_run_xdp_zc(rx_ring, *xdp); + if (xdp_res) { + if (xdp_res & (ICE_XDP_TX | ICE_XDP_REDIR)) + xdp_xmit |= xdp_res; + else +- xsk_buff_free(rx_buf->xdp); ++ xsk_buff_free(*xdp); + +- rx_buf->xdp = NULL; ++ *xdp = NULL; + total_rx_bytes += size; + total_rx_packets++; + cleaned_count++; +@@ -565,7 +565,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget) + } + + /* XDP_PASS path */ +- skb = ice_construct_skb_zc(rx_ring, rx_buf); ++ skb = ice_construct_skb_zc(rx_ring, xdp); + if (!skb) { + rx_ring->rx_stats.alloc_buf_failed++; + break; +@@ -810,15 +810,15 @@ bool ice_xsk_any_rx_ring_ena(struct ice_vsi *vsi) + */ + void ice_xsk_clean_rx_ring(struct ice_ring *rx_ring) + { +- u16 i; +- +- for (i = 0; i < rx_ring->count; i++) { +- struct ice_rx_buf *rx_buf = &rx_ring->rx_buf[i]; ++ u16 count_mask = rx_ring->count - 1; ++ u16 ntc = rx_ring->next_to_clean; ++ u16 ntu = rx_ring->next_to_use; + +- if (!rx_buf->xdp) +- continue; ++ for ( ; ntc != ntu; ntc = (ntc + 1) & count_mask) { ++ struct xdp_buff **xdp = &rx_ring->xdp_buf[ntc]; + +- rx_buf->xdp = NULL; ++ xsk_buff_free(*xdp); ++ *xdp = NULL; + } + } + +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index 751de06019a0e..82a712f77cb34 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -7641,6 +7641,20 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf, + struct vf_mac_filter *entry = NULL; + int ret = 0; + ++ if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && ++ !vf_data->trusted) { ++ dev_warn(&pdev->dev, ++ "VF %d requested MAC filter but is administratively denied\n", ++ vf); ++ return -EINVAL; ++ } ++ if (!is_valid_ether_addr(addr)) { ++ dev_warn(&pdev->dev, ++ "VF %d attempted to set invalid MAC filter\n", ++ vf); ++ return -EINVAL; ++ } ++ + switch (info) { + case E1000_VF_MAC_FILTER_CLR: + /* remove all unicast MAC filters related to the current VF */ +@@ -7654,20 +7668,6 @@ static int igb_set_vf_mac_filter(struct igb_adapter *adapter, const int vf, + } + break; + case E1000_VF_MAC_FILTER_ADD: +- if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) && +- !vf_data->trusted) { +- dev_warn(&pdev->dev, +- "VF %d requested MAC filter but is administratively denied\n", +- vf); +- return -EINVAL; +- } +- if (!is_valid_ether_addr(addr)) { +- dev_warn(&pdev->dev, +- "VF %d attempted to set invalid MAC filter\n", +- vf); +- return -EINVAL; +- } +- + /* try to find empty slot in the list */ + list_for_each(pos, &adapter->vf_macs.l) { + entry = list_entry(pos, struct vf_mac_filter, l); +@@ -8019,7 +8019,7 @@ static int igb_poll(struct napi_struct *napi, int budget) + if (likely(napi_complete_done(napi, work_done))) + igb_ring_irq_enable(q_vector); + +- return min(work_done, budget - 1); ++ return work_done; + } + + /** +@@ -9247,7 +9247,7 @@ static int __maybe_unused igb_suspend(struct device *dev) + return __igb_shutdown(to_pci_dev(dev), NULL, 0); + } + +-static int __maybe_unused igb_resume(struct device *dev) ++static int __maybe_unused __igb_resume(struct device *dev, bool rpm) + { + struct pci_dev *pdev = to_pci_dev(dev); + struct net_device *netdev = pci_get_drvdata(pdev); +@@ -9290,17 +9290,24 @@ static int __maybe_unused igb_resume(struct device *dev) + + wr32(E1000_WUS, ~0); + +- rtnl_lock(); ++ if (!rpm) ++ rtnl_lock(); + if (!err && netif_running(netdev)) + err = __igb_open(netdev, true); + + if (!err) + netif_device_attach(netdev); +- rtnl_unlock(); ++ if (!rpm) ++ rtnl_unlock(); + + return err; + } + ++static int __maybe_unused igb_resume(struct device *dev) ++{ ++ return __igb_resume(dev, false); ++} ++ + static int __maybe_unused igb_runtime_idle(struct device *dev) + { + struct net_device *netdev = dev_get_drvdata(dev); +@@ -9319,7 +9326,7 @@ static int __maybe_unused igb_runtime_suspend(struct device *dev) + + static int __maybe_unused igb_runtime_resume(struct device *dev) + { +- return igb_resume(dev); ++ return __igb_resume(dev, true); + } + + static void igb_shutdown(struct pci_dev *pdev) +@@ -9435,7 +9442,7 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, + * @pdev: Pointer to PCI device + * + * Restart the card from scratch, as if from a cold-boot. Implementation +- * resembles the first-half of the igb_resume routine. ++ * resembles the first-half of the __igb_resume routine. + **/ + static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) + { +@@ -9475,7 +9482,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) + * + * This callback is called when the error recovery driver tells us that + * its OK to resume normal operation. Implementation resembles the +- * second-half of the igb_resume routine. ++ * second-half of the __igb_resume routine. + */ + static void igb_io_resume(struct pci_dev *pdev) + { +diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c +index d32e72d953c8d..d051918dfdff9 100644 +--- a/drivers/net/ethernet/intel/igbvf/netdev.c ++++ b/drivers/net/ethernet/intel/igbvf/netdev.c +@@ -2861,6 +2861,7 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + return 0; + + err_hw_init: ++ netif_napi_del(&adapter->rx_ring->napi); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + err_sw_init: +diff --git a/drivers/net/ethernet/intel/igc/igc_i225.c b/drivers/net/ethernet/intel/igc/igc_i225.c +index b2ef9fde97b38..b6807e16eea93 100644 +--- a/drivers/net/ethernet/intel/igc/igc_i225.c ++++ b/drivers/net/ethernet/intel/igc/igc_i225.c +@@ -636,7 +636,7 @@ s32 igc_set_ltr_i225(struct igc_hw *hw, bool link) + ltrv = rd32(IGC_LTRMAXV); + if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) { + ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max | +- (scale_min << IGC_LTRMAXV_SCALE_SHIFT); ++ (scale_max << IGC_LTRMAXV_SCALE_SHIFT); + wr32(IGC_LTRMAXV, ltrv); + } + } +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 0e19b4d02e628..c7fa978cdf02e 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -2447,8 +2447,10 @@ static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring, + + skb_reserve(skb, xdp->data_meta - xdp->data_hard_start); + memcpy(__skb_put(skb, totalsize), xdp->data_meta, totalsize); +- if (metasize) ++ if (metasize) { + skb_metadata_set(skb, metasize); ++ __skb_pull(skb, metasize); ++ } + + return skb; + } +@@ -5466,6 +5468,9 @@ static irqreturn_t igc_intr_msi(int irq, void *data) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++ if (icr & IGC_ICR_TS) ++ igc_tsync_interrupt(adapter); ++ + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +@@ -5509,6 +5514,9 @@ static irqreturn_t igc_intr(int irq, void *data) + mod_timer(&adapter->watchdog_timer, jiffies + 1); + } + ++ if (icr & IGC_ICR_TS) ++ igc_tsync_interrupt(adapter); ++ + napi_schedule(&q_vector->napi); + + return IRQ_HANDLED; +diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c +index 5cad31c3c7b09..40dbf4b432345 100644 +--- a/drivers/net/ethernet/intel/igc/igc_phy.c ++++ b/drivers/net/ethernet/intel/igc/igc_phy.c +@@ -746,8 +746,6 @@ s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data) + if (ret_val) + return ret_val; + ret_val = igc_write_phy_reg_mdic(hw, offset, data); +- if (ret_val) +- return ret_val; + hw->phy.ops.release(hw); + } else { + ret_val = igc_write_xmdio_reg(hw, (u16)offset, dev_addr, +@@ -779,8 +777,6 @@ s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data) + if (ret_val) + return ret_val; + ret_val = igc_read_phy_reg_mdic(hw, offset, data); +- if (ret_val) +- return ret_val; + hw->phy.ops.release(hw); + } else { + ret_val = igc_read_xmdio_reg(hw, (u16)offset, dev_addr, +diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c +index 0f021909b430a..4f9245aa79a18 100644 +--- a/drivers/net/ethernet/intel/igc/igc_ptp.c ++++ b/drivers/net/ethernet/intel/igc/igc_ptp.c +@@ -768,12 +768,25 @@ int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) + */ + static bool igc_is_crosststamp_supported(struct igc_adapter *adapter) + { +- return IS_ENABLED(CONFIG_X86_TSC) ? pcie_ptm_enabled(adapter->pdev) : false; ++ if (!IS_ENABLED(CONFIG_X86_TSC)) ++ return false; ++ ++ /* FIXME: it was noticed that enabling support for PCIe PTM in ++ * some i225-V models could cause lockups when bringing the ++ * interface up/down. There should be no downsides to ++ * disabling crosstimestamping support for i225-V, as it ++ * doesn't have any PTP support. That way we gain some time ++ * while root causing the issue. ++ */ ++ if (adapter->pdev->device == IGC_DEV_ID_I225_V) ++ return false; ++ ++ return pcie_ptm_enabled(adapter->pdev); + } + + static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp) + { +-#if IS_ENABLED(CONFIG_X86_TSC) ++#if IS_ENABLED(CONFIG_X86_TSC) && !defined(CONFIG_UML) + return convert_art_ns_to_tsc(tstamp); + #else + return (struct system_counterval_t) { }; +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index 13c4782b920a7..750b02bb2fdc2 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -5526,6 +5526,10 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw) + if (!speed && hw->mac.ops.get_link_capabilities) { + ret = hw->mac.ops.get_link_capabilities(hw, &speed, + &autoneg); ++ /* remove NBASE-T speeds from default autonegotiation ++ * to accommodate broken network switches in the field ++ * which cannot cope with advertised NBASE-T speeds ++ */ + speed &= ~(IXGBE_LINK_SPEED_5GB_FULL | + IXGBE_LINK_SPEED_2_5GB_FULL); + } +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +index 9724ffb165189..e4b50c7781ffa 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +@@ -3405,6 +3405,9 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) + /* flush pending Tx transactions */ + ixgbe_clear_tx_pending(hw); + ++ /* set MDIO speed before talking to the PHY in case it's the 1st time */ ++ ixgbe_set_mdio_speed(hw); ++ + /* PHY ops must be identified and initialized prior to reset */ + status = hw->phy.ops.init(hw); + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED || +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c +index b1d22e4d5ec9c..e3bf024717ed3 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c +@@ -388,12 +388,14 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget) + u32 cmd_type; + + while (budget-- > 0) { +- if (unlikely(!ixgbe_desc_unused(xdp_ring)) || +- !netif_carrier_ok(xdp_ring->netdev)) { ++ if (unlikely(!ixgbe_desc_unused(xdp_ring))) { + work_done = false; + break; + } + ++ if (!netif_carrier_ok(xdp_ring->netdev)) ++ break; ++ + if (!xsk_tx_peek_desc(pool, &desc)) + break; + +diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +index c714e1ecd3089..7ef2e1241a76e 100644 +--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c ++++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +@@ -1984,14 +1984,15 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter, + if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) + return; + +- set_ring_build_skb_enabled(rx_ring); ++ if (PAGE_SIZE < 8192) ++ if (max_frame > IXGBEVF_MAX_FRAME_BUILD_SKB) ++ set_ring_uses_large_buffer(rx_ring); + +- if (PAGE_SIZE < 8192) { +- if (max_frame <= IXGBEVF_MAX_FRAME_BUILD_SKB) +- return; ++ /* 82599 can't rely on RXDCTL.RLPML to restrict the size of the frame */ ++ if (adapter->hw.mac.type == ixgbe_mac_82599_vf && !ring_uses_large_buffer(rx_ring)) ++ return; + +- set_ring_uses_large_buffer(rx_ring); +- } ++ set_ring_build_skb_enabled(rx_ring); + } + + /** +diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c +index fb78f17d734fe..b02f796b5422f 100644 +--- a/drivers/net/ethernet/lantiq_xrx200.c ++++ b/drivers/net/ethernet/lantiq_xrx200.c +@@ -209,7 +209,7 @@ static int xrx200_hw_receive(struct xrx200_chan *ch) + skb->protocol = eth_type_trans(skb, net_dev); + netif_receive_skb(skb); + net_dev->stats.rx_packets++; +- net_dev->stats.rx_bytes += len - ETH_FCS_LEN; ++ net_dev->stats.rx_bytes += len; + + return 0; + } +diff --git a/drivers/net/ethernet/litex/Kconfig b/drivers/net/ethernet/litex/Kconfig +index 63bf01d28f0cf..04345b929d8e5 100644 +--- a/drivers/net/ethernet/litex/Kconfig ++++ b/drivers/net/ethernet/litex/Kconfig +@@ -17,7 +17,7 @@ if NET_VENDOR_LITEX + + config LITEX_LITEETH + tristate "LiteX Ethernet support" +- depends on OF_NET ++ depends on OF && HAS_IOMEM + help + If you wish to compile a kernel for hardware with a LiteX LiteEth + device then you should answer Y to this. +diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c +index a9bdbf0dcfe1e..5bb1cc8a2ce13 100644 +--- a/drivers/net/ethernet/litex/litex_liteeth.c ++++ b/drivers/net/ethernet/litex/litex_liteeth.c +@@ -289,7 +289,6 @@ static int liteeth_remove(struct platform_device *pdev) + struct net_device *netdev = platform_get_drvdata(pdev); + + unregister_netdev(netdev); +- free_netdev(netdev); + + return 0; + } +diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c +index 28d5ad296646a..1b61fe2e9b4d5 100644 +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -2700,6 +2700,16 @@ MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids); + + static struct platform_device *port_platdev[3]; + ++static void mv643xx_eth_shared_of_remove(void) ++{ ++ int n; ++ ++ for (n = 0; n < 3; n++) { ++ platform_device_del(port_platdev[n]); ++ port_platdev[n] = NULL; ++ } ++} ++ + static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, + struct device_node *pnp) + { +@@ -2736,7 +2746,9 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, + return -EINVAL; + } + +- of_get_mac_address(pnp, ppd.mac_addr); ++ ret = of_get_mac_address(pnp, ppd.mac_addr); ++ if (ret) ++ return ret; + + mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size); + mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr); +@@ -2800,21 +2812,13 @@ static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) + ret = mv643xx_eth_shared_of_add_port(pdev, pnp); + if (ret) { + of_node_put(pnp); ++ mv643xx_eth_shared_of_remove(); + return ret; + } + } + return 0; + } + +-static void mv643xx_eth_shared_of_remove(void) +-{ +- int n; +- +- for (n = 0; n < 3; n++) { +- platform_device_del(port_platdev[n]); +- port_platdev[n] = NULL; +- } +-} + #else + static inline int mv643xx_eth_shared_of_probe(struct platform_device *pdev) + { +diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c +index 62a97c46fba05..ef878973b8597 100644 +--- a/drivers/net/ethernet/marvell/mvmdio.c ++++ b/drivers/net/ethernet/marvell/mvmdio.c +@@ -429,12 +429,14 @@ static const struct of_device_id orion_mdio_match[] = { + }; + MODULE_DEVICE_TABLE(of, orion_mdio_match); + ++#ifdef CONFIG_ACPI + static const struct acpi_device_id orion_mdio_acpi_match[] = { + { "MRVL0100", BUS_TYPE_SMI }, + { "MRVL0101", BUS_TYPE_XSMI }, + { }, + }; + MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match); ++#endif + + static struct platform_driver orion_mdio_driver = { + .probe = orion_mdio_probe, +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index d5c92e43f89e6..2baa909290b3b 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -1605,7 +1605,7 @@ static void mvpp22_gop_fca_set_periodic_timer(struct mvpp2_port *port) + mvpp22_gop_fca_enable_periodic(port, true); + } + +-static int mvpp22_gop_init(struct mvpp2_port *port) ++static int mvpp22_gop_init(struct mvpp2_port *port, phy_interface_t interface) + { + struct mvpp2 *priv = port->priv; + u32 val; +@@ -1613,7 +1613,7 @@ static int mvpp22_gop_init(struct mvpp2_port *port) + if (!priv->sysctrl_base) + return 0; + +- switch (port->phy_interface) { ++ switch (interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: +@@ -1743,15 +1743,15 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port) + * lanes by the physical layer. This is why configurations like + * "PPv2 (2500BaseX) - COMPHY (2500SGMII)" are valid. + */ +-static int mvpp22_comphy_init(struct mvpp2_port *port) ++static int mvpp22_comphy_init(struct mvpp2_port *port, ++ phy_interface_t interface) + { + int ret; + + if (!port->comphy) + return 0; + +- ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, +- port->phy_interface); ++ ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, interface); + if (ret) + return ret; + +@@ -2172,7 +2172,8 @@ static void mvpp22_pcs_reset_assert(struct mvpp2_port *port) + writel(val & ~MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0); + } + +-static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port) ++static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port, ++ phy_interface_t interface) + { + struct mvpp2 *priv = port->priv; + void __iomem *mpcs, *xpcs; +@@ -2184,7 +2185,7 @@ static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port) + mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id); + xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); + +- switch (port->phy_interface) { ++ switch (interface) { + case PHY_INTERFACE_MODE_10GBASER: + val = readl(mpcs + MVPP22_MPCS_CLK_RESET); + val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | +@@ -2959,11 +2960,11 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, + mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size); + + if (priv->percpu_pools) { +- err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->id, 0); ++ err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->logic_rxq, 0); + if (err < 0) + goto err_free_dma; + +- err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->id, 0); ++ err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->logic_rxq, 0); + if (err < 0) + goto err_unregister_rxq_short; + +@@ -4529,7 +4530,8 @@ static int mvpp2_poll(struct napi_struct *napi, int budget) + return rx_done; + } + +-static void mvpp22_mode_reconfigure(struct mvpp2_port *port) ++static void mvpp22_mode_reconfigure(struct mvpp2_port *port, ++ phy_interface_t interface) + { + u32 ctrl3; + +@@ -4540,18 +4542,18 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) + mvpp22_pcs_reset_assert(port); + + /* comphy reconfiguration */ +- mvpp22_comphy_init(port); ++ mvpp22_comphy_init(port, interface); + + /* gop reconfiguration */ +- mvpp22_gop_init(port); ++ mvpp22_gop_init(port, interface); + +- mvpp22_pcs_reset_deassert(port); ++ mvpp22_pcs_reset_deassert(port, interface); + + if (mvpp2_port_supports_xlg(port)) { + ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG); + ctrl3 &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK; + +- if (mvpp2_is_xlg(port->phy_interface)) ++ if (mvpp2_is_xlg(interface)) + ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_10G; + else + ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC; +@@ -4559,7 +4561,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) + writel(ctrl3, port->base + MVPP22_XLG_CTRL3_REG); + } + +- if (mvpp2_port_supports_xlg(port) && mvpp2_is_xlg(port->phy_interface)) ++ if (mvpp2_port_supports_xlg(port) && mvpp2_is_xlg(interface)) + mvpp2_xlg_max_rx_size_set(port); + else + mvpp2_gmac_max_rx_size_set(port); +@@ -4579,7 +4581,7 @@ static void mvpp2_start_dev(struct mvpp2_port *port) + mvpp2_interrupts_enable(port); + + if (port->priv->hw_version >= MVPP22) +- mvpp22_mode_reconfigure(port); ++ mvpp22_mode_reconfigure(port, port->phy_interface); + + if (port->phylink) { + phylink_start(port->phylink); +@@ -5015,11 +5017,13 @@ static int mvpp2_change_mtu(struct net_device *dev, int mtu) + mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8); + } + ++ if (port->xdp_prog && mtu > MVPP2_MAX_RX_BUF_SIZE) { ++ netdev_err(dev, "Illegal MTU value %d (> %d) for XDP mode\n", ++ mtu, (int)MVPP2_MAX_RX_BUF_SIZE); ++ return -EINVAL; ++ } ++ + if (MVPP2_RX_PKT_SIZE(mtu) > MVPP2_BM_LONG_PKT_SIZE) { +- if (port->xdp_prog) { +- netdev_err(dev, "Jumbo frames are not supported with XDP\n"); +- return -EINVAL; +- } + if (priv->percpu_pools) { + netdev_warn(dev, "mtu %d too high, switching to shared buffers", mtu); + mvpp2_bm_switch_buffers(priv, false); +@@ -5305,8 +5309,8 @@ static int mvpp2_xdp_setup(struct mvpp2_port *port, struct netdev_bpf *bpf) + bool running = netif_running(port->dev); + bool reset = !prog != !port->xdp_prog; + +- if (port->dev->mtu > ETH_DATA_LEN) { +- NL_SET_ERR_MSG_MOD(bpf->extack, "XDP is not supported with jumbo frames enabled"); ++ if (port->dev->mtu > MVPP2_MAX_RX_BUF_SIZE) { ++ NL_SET_ERR_MSG_MOD(bpf->extack, "MTU too large for XDP"); + return -EOPNOTSUPP; + } + +@@ -6477,6 +6481,9 @@ static int mvpp2__mac_prepare(struct phylink_config *config, unsigned int mode, + mvpp22_gop_mask_irq(port); + + phy_power_off(port->comphy); ++ ++ /* Reconfigure the serdes lanes */ ++ mvpp22_mode_reconfigure(port, interface); + } + } + +@@ -6531,9 +6538,6 @@ static int mvpp2_mac_finish(struct phylink_config *config, unsigned int mode, + port->phy_interface != interface) { + port->phy_interface = interface; + +- /* Reconfigure the serdes lanes */ +- mvpp22_mode_reconfigure(port); +- + /* Unmask interrupts */ + mvpp22_gop_unmask_irq(port); + } +@@ -6960,7 +6964,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, + * driver does this, we can remove this code. + */ + if (port->comphy) { +- err = mvpp22_comphy_init(port); ++ err = mvpp22_comphy_init(port, port->phy_interface); + if (err == 0) + phy_power_off(port->comphy); + } +@@ -7453,7 +7457,7 @@ static int mvpp2_probe(struct platform_device *pdev) + + shared = num_present_cpus() - priv->nthreads; + if (shared > 0) +- bitmap_fill(&priv->lock_map, ++ bitmap_set(&priv->lock_map, 0, + min_t(int, shared, MVPP2_MAX_THREADS)); + + for (i = 0; i < MVPP2_MAX_THREADS; i++) { +diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig +index 3f982ccf2c85f..639893d870550 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/Kconfig ++++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig +@@ -31,6 +31,7 @@ config NDC_DIS_DYNAMIC_CACHING + config OCTEONTX2_PF + tristate "Marvell OcteonTX2 NIC Physical Function driver" + select OCTEONTX2_MBOX ++ select NET_DEVLINK + depends on (64BIT && COMPILE_TEST) || ARM64 + depends on PCI + depends on PTP_1588_CLOCK_OPTIONAL +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index 34a089b71e554..6b335139abe7f 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -838,9 +838,6 @@ void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable) + if (!cgx) + return; + +- if (is_dev_rpm(cgx)) +- return; +- + if (enable) { + /* Enable inbound PTP timestamping */ + cfg = cgx_read(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL); +@@ -1545,9 +1542,11 @@ static int cgx_lmac_exit(struct cgx *cgx) + static void cgx_populate_features(struct cgx *cgx) + { + if (is_dev_rpm(cgx)) +- cgx->hw_features = (RVU_MAC_RPM | RVU_LMAC_FEAT_FC); ++ cgx->hw_features = (RVU_LMAC_FEAT_DMACF | RVU_MAC_RPM | ++ RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP); + else +- cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP); ++ cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_HIGIG2 | ++ RVU_LMAC_FEAT_PTP | RVU_LMAC_FEAT_DMACF); + } + + static struct mac_ops cgx_mac_ops = { +@@ -1571,6 +1570,9 @@ static struct mac_ops cgx_mac_ops = { + .mac_get_pause_frm_status = cgx_lmac_get_pause_frm_status, + .mac_enadis_pause_frm = cgx_lmac_enadis_pause_frm, + .mac_pause_frm_config = cgx_lmac_pause_frm_config, ++ .mac_enadis_ptp_config = cgx_lmac_ptp_config, ++ .mac_rx_tx_enable = cgx_lmac_rx_tx_enable, ++ .mac_tx_enable = cgx_lmac_tx_enable, + }; + + static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +index c38306b3384a7..b33e7d1d0851c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +@@ -102,6 +102,14 @@ struct mac_ops { + void (*mac_pause_frm_config)(void *cgxd, + int lmac_id, + bool enable); ++ ++ /* Enable/Disable Inbound PTP */ ++ void (*mac_enadis_ptp_config)(void *cgxd, ++ int lmac_id, ++ bool enable); ++ ++ int (*mac_rx_tx_enable)(void *cgxd, int lmac_id, bool enable); ++ int (*mac_tx_enable)(void *cgxd, int lmac_id, bool enable); + }; + + struct cgx { +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +index 154877706a0e1..c6643c7db1fc4 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +@@ -84,7 +84,7 @@ struct mbox_msghdr { + #define OTX2_MBOX_REQ_SIG (0xdead) + #define OTX2_MBOX_RSP_SIG (0xbeef) + u16 sig; /* Signature, for validating corrupted msgs */ +-#define OTX2_MBOX_VERSION (0x0009) ++#define OTX2_MBOX_VERSION (0x000a) + u16 ver; /* Version of msg's structure for this ID */ + u16 next_msgoff; /* Offset of next msg within mailbox region */ + int rc; /* Msg process'ed response code */ +@@ -154,23 +154,23 @@ M(CGX_PTP_RX_ENABLE, 0x20C, cgx_ptp_rx_enable, msg_req, msg_rsp) \ + M(CGX_PTP_RX_DISABLE, 0x20D, cgx_ptp_rx_disable, msg_req, msg_rsp) \ + M(CGX_CFG_PAUSE_FRM, 0x20E, cgx_cfg_pause_frm, cgx_pause_frm_cfg, \ + cgx_pause_frm_cfg) \ +-M(CGX_FEC_SET, 0x210, cgx_set_fec_param, fec_mode, fec_mode) \ +-M(CGX_FEC_STATS, 0x211, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \ +-M(CGX_GET_PHY_FEC_STATS, 0x212, cgx_get_phy_fec_stats, msg_req, msg_rsp) \ +-M(CGX_FW_DATA_GET, 0x213, cgx_get_aux_link_info, msg_req, cgx_fw_data) \ +-M(CGX_SET_LINK_MODE, 0x214, cgx_set_link_mode, cgx_set_link_mode_req,\ +- cgx_set_link_mode_rsp) \ +-M(CGX_FEATURES_GET, 0x215, cgx_features_get, msg_req, \ +- cgx_features_info_msg) \ +-M(RPM_STATS, 0x216, rpm_stats, msg_req, rpm_stats_rsp) \ +-M(CGX_MAC_ADDR_ADD, 0x217, cgx_mac_addr_add, cgx_mac_addr_add_req, \ +- cgx_mac_addr_add_rsp) \ +-M(CGX_MAC_ADDR_DEL, 0x218, cgx_mac_addr_del, cgx_mac_addr_del_req, \ ++M(CGX_FW_DATA_GET, 0x20F, cgx_get_aux_link_info, msg_req, cgx_fw_data) \ ++M(CGX_FEC_SET, 0x210, cgx_set_fec_param, fec_mode, fec_mode) \ ++M(CGX_MAC_ADDR_ADD, 0x211, cgx_mac_addr_add, cgx_mac_addr_add_req, \ ++ cgx_mac_addr_add_rsp) \ ++M(CGX_MAC_ADDR_DEL, 0x212, cgx_mac_addr_del, cgx_mac_addr_del_req, \ + msg_rsp) \ +-M(CGX_MAC_MAX_ENTRIES_GET, 0x219, cgx_mac_max_entries_get, msg_req, \ ++M(CGX_MAC_MAX_ENTRIES_GET, 0x213, cgx_mac_max_entries_get, msg_req, \ + cgx_max_dmac_entries_get_rsp) \ +-M(CGX_MAC_ADDR_RESET, 0x21A, cgx_mac_addr_reset, msg_req, msg_rsp) \ +-M(CGX_MAC_ADDR_UPDATE, 0x21B, cgx_mac_addr_update, cgx_mac_addr_update_req, \ ++M(CGX_FEC_STATS, 0x217, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \ ++M(CGX_SET_LINK_MODE, 0x218, cgx_set_link_mode, cgx_set_link_mode_req,\ ++ cgx_set_link_mode_rsp) \ ++M(CGX_GET_PHY_FEC_STATS, 0x219, cgx_get_phy_fec_stats, msg_req, msg_rsp) \ ++M(CGX_FEATURES_GET, 0x21B, cgx_features_get, msg_req, \ ++ cgx_features_info_msg) \ ++M(RPM_STATS, 0x21C, rpm_stats, msg_req, rpm_stats_rsp) \ ++M(CGX_MAC_ADDR_RESET, 0x21D, cgx_mac_addr_reset, msg_req, msg_rsp) \ ++M(CGX_MAC_ADDR_UPDATE, 0x21E, cgx_mac_addr_update, cgx_mac_addr_update_req, \ + msg_rsp) \ + /* NPA mbox IDs (range 0x400 - 0x5FF) */ \ + M(NPA_LF_ALLOC, 0x400, npa_lf_alloc, \ +@@ -229,6 +229,8 @@ M(NPC_DELETE_FLOW, 0x600e, npc_delete_flow, \ + M(NPC_MCAM_READ_ENTRY, 0x600f, npc_mcam_read_entry, \ + npc_mcam_read_entry_req, \ + npc_mcam_read_entry_rsp) \ ++M(NPC_SET_PKIND, 0x6010, npc_set_pkind, \ ++ npc_set_pkind, msg_rsp) \ + M(NPC_MCAM_READ_BASE_RULE, 0x6011, npc_read_base_steer_rule, \ + msg_req, npc_mcam_read_base_rule_rsp) \ + M(NPC_MCAM_GET_STATS, 0x6012, npc_mcam_entry_stats, \ +@@ -575,10 +577,13 @@ struct cgx_mac_addr_update_req { + }; + + #define RVU_LMAC_FEAT_FC BIT_ULL(0) /* pause frames */ +-#define RVU_LMAC_FEAT_PTP BIT_ULL(1) /* precision time protocol */ +-#define RVU_MAC_VERSION BIT_ULL(2) +-#define RVU_MAC_CGX BIT_ULL(3) +-#define RVU_MAC_RPM BIT_ULL(4) ++#define RVU_LMAC_FEAT_HIGIG2 BIT_ULL(1) ++ /* flow control from physical link higig2 messages */ ++#define RVU_LMAC_FEAT_PTP BIT_ULL(2) /* precison time protocol */ ++#define RVU_LMAC_FEAT_DMACF BIT_ULL(3) /* DMAC FILTER */ ++#define RVU_MAC_VERSION BIT_ULL(4) ++#define RVU_MAC_CGX BIT_ULL(5) ++#define RVU_MAC_RPM BIT_ULL(6) + + struct cgx_features_info_msg { + struct mbox_msghdr hdr; +@@ -593,6 +598,22 @@ struct rpm_stats_rsp { + u64 tx_stats[RPM_TX_STATS_COUNT]; + }; + ++struct npc_set_pkind { ++ struct mbox_msghdr hdr; ++#define OTX2_PRIV_FLAGS_DEFAULT BIT_ULL(0) ++#define OTX2_PRIV_FLAGS_CUSTOM BIT_ULL(63) ++ u64 mode; ++#define PKIND_TX BIT_ULL(0) ++#define PKIND_RX BIT_ULL(1) ++ u8 dir; ++ u8 pkind; /* valid only in case custom flag */ ++ u8 var_len_off; /* Offset of custom header length field. ++ * Valid only for pkind NPC_RX_CUSTOM_PRE_L2_PKIND ++ */ ++ u8 var_len_off_mask; /* Mask for length with in offset */ ++ u8 shift_dir; /* shift direction to get length of the header at var_len_off */ ++}; ++ + /* NPA mbox message formats */ + + /* NPA mailbox error codes +@@ -698,6 +719,9 @@ enum nix_af_status { + NIX_AF_ERR_INVALID_BANDPROF = -426, + NIX_AF_ERR_IPOLICER_NOTSUPP = -427, + NIX_AF_ERR_BANDPROF_INVAL_REQ = -428, ++ NIX_AF_ERR_CQ_CTX_WRITE_ERR = -429, ++ NIX_AF_ERR_AQ_CTX_RETRY_WRITE = -430, ++ NIX_AF_ERR_LINK_CREDITS = -431, + }; + + /* For NIX RX vtag action */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h +index 3a819b24accc6..6e1192f526089 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h +@@ -31,9 +31,9 @@ enum npc_kpu_la_ltype { + NPC_LT_LA_HIGIG2_ETHER, + NPC_LT_LA_IH_NIX_HIGIG2_ETHER, + NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_LT_LA_CH_LEN_90B_ETHER, + NPC_LT_LA_CPT_HDR, + NPC_LT_LA_CUSTOM_L2_24B_ETHER, ++ NPC_LT_LA_CUSTOM_PRE_L2_ETHER, + NPC_LT_LA_CUSTOM0 = 0xE, + NPC_LT_LA_CUSTOM1 = 0xF, + }; +@@ -148,10 +148,11 @@ enum npc_kpu_lh_ltype { + * Software assigns pkind for each incoming port such as CGX + * Ethernet interfaces, LBK interfaces, etc. + */ +-#define NPC_UNRESERVED_PKIND_COUNT NPC_RX_VLAN_EXDSA_PKIND ++#define NPC_UNRESERVED_PKIND_COUNT NPC_RX_CUSTOM_PRE_L2_PKIND + + enum npc_pkind_type { + NPC_RX_LBK_PKIND = 0ULL, ++ NPC_RX_CUSTOM_PRE_L2_PKIND = 55ULL, + NPC_RX_VLAN_EXDSA_PKIND = 56ULL, + NPC_RX_CHLEN24B_PKIND = 57ULL, + NPC_RX_CPT_HDR_PKIND, +@@ -162,6 +163,10 @@ enum npc_pkind_type { + NPC_TX_DEF_PKIND, /* NIX-TX PKIND */ + }; + ++enum npc_interface_type { ++ NPC_INTF_MODE_DEF, ++}; ++ + /* list of known and supported fields in packet header and + * fields present in key structure. + */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h +index 588822a0cf21e..695123e32ba85 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h +@@ -176,9 +176,8 @@ enum npc_kpu_parser_state { + NPC_S_KPU1_EXDSA, + NPC_S_KPU1_HIGIG2, + NPC_S_KPU1_IH_NIX_HIGIG2, +- NPC_S_KPU1_CUSTOM_L2_90B, ++ NPC_S_KPU1_CUSTOM_PRE_L2, + NPC_S_KPU1_CPT_HDR, +- NPC_S_KPU1_CUSTOM_L2_24B, + NPC_S_KPU1_VLAN_EXDSA, + NPC_S_KPU2_CTAG, + NPC_S_KPU2_CTAG2, +@@ -187,7 +186,8 @@ enum npc_kpu_parser_state { + NPC_S_KPU2_ETAG, + NPC_S_KPU2_PREHEADER, + NPC_S_KPU2_EXDSA, +- NPC_S_KPU2_NGIO, ++ NPC_S_KPU2_CPT_CTAG, ++ NPC_S_KPU2_CPT_QINQ, + NPC_S_KPU3_CTAG, + NPC_S_KPU3_STAG, + NPC_S_KPU3_QINQ, +@@ -212,6 +212,7 @@ enum npc_kpu_parser_state { + NPC_S_KPU5_NSH, + NPC_S_KPU5_CPT_IP, + NPC_S_KPU5_CPT_IP6, ++ NPC_S_KPU5_NGIO, + NPC_S_KPU6_IP6_EXT, + NPC_S_KPU6_IP6_HOP_DEST, + NPC_S_KPU6_IP6_ROUT, +@@ -979,8 +980,8 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = { + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 12, 16, 20, 0, 0, +- NPC_S_KPU1_ETHER, 0, 0, +- NPC_LID_LA, NPC_LT_NA, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0, 1, ++ NPC_LID_LA, NPC_LT_LA_CUSTOM_PRE_L2_ETHER, + 0, + 0, 0, 0, 0, + +@@ -996,27 +997,27 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = { + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, +- 36, 40, 44, 0, 0, +- NPC_S_KPU1_CUSTOM_L2_24B, 0, 0, +- NPC_LID_LA, NPC_LT_NA, ++ 12, 16, 20, 0, 0, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 24, 1, ++ NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, + 0, + 0, 0, 0, 0, + + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, +- 40, 54, 58, 0, 0, +- NPC_S_KPU1_CPT_HDR, 0, 0, ++ 12, 16, 20, 0, 0, ++ NPC_S_KPU1_CPT_HDR, 40, 0, + NPC_LID_LA, NPC_LT_NA, + 0, +- 0, 0, 0, 0, ++ 7, 7, 0, 0, + + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, +- 102, 106, 110, 0, 0, +- NPC_S_KPU1_CUSTOM_L2_90B, 0, 0, +- NPC_LID_LA, NPC_LT_NA, ++ 12, 16, 20, 0, 0, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 90, 1, ++ NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, + 0, + 0, 0, 0, 0, + +@@ -1116,15 +1117,6 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + 0x0000, + }, +- { +- NPC_S_KPU1_ETHER, 0xff, +- NPC_ETYPE_CTAG, +- 0xffff, +- NPC_ETYPE_NGIO, +- 0xffff, +- 0x0000, +- 0x0000, +- }, + { + NPC_S_KPU1_ETHER, 0xff, + NPC_ETYPE_CTAG, +@@ -1711,7 +1703,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_IP, + 0xffff, + 0x0000, +@@ -1720,7 +1712,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_IP6, + 0xffff, + 0x0000, +@@ -1729,7 +1721,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_ARP, + 0xffff, + 0x0000, +@@ -1738,7 +1730,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_RARP, + 0xffff, + 0x0000, +@@ -1747,7 +1739,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_PTP, + 0xffff, + 0x0000, +@@ -1756,7 +1748,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_FCOE, + 0xffff, + 0x0000, +@@ -1765,7 +1757,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_CTAG, + 0xffff, + NPC_ETYPE_CTAG, +@@ -1774,7 +1766,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_CTAG, + 0xffff, + 0x0000, +@@ -1783,7 +1775,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_SBTAG, + 0xffff, + 0x0000, +@@ -1792,7 +1784,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_QINQ, + 0xffff, + 0x0000, +@@ -1801,7 +1793,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_ETAG, + 0xffff, + 0x0000, +@@ -1810,7 +1802,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_MPLSU, + 0xffff, + 0x0000, +@@ -1819,7 +1811,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_MPLSM, + 0xffff, + 0x0000, +@@ -1828,7 +1820,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + NPC_ETYPE_NSH, + 0xffff, + 0x0000, +@@ -1837,7 +1829,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_90B, 0xff, ++ NPC_S_KPU1_CUSTOM_PRE_L2, 0xff, + 0x0000, + 0x0000, + 0x0000, +@@ -1847,150 +1839,24 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + }, + { + NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, + NPC_ETYPE_IP, + 0xffff, + 0x0000, + 0x0000, +- }, +- { +- NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, +- NPC_ETYPE_IP6, +- 0xffff, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, +- NPC_ETYPE_CTAG, +- 0xffff, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, +- NPC_ETYPE_QINQ, +- 0xffff, + 0x0000, + 0x0000, + }, + { + NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, +- 0x0000, +- 0x0000, +- NPC_ETYPE_IP, +- 0xffff, +- }, +- { +- NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, +- 0x0000, +- 0x0000, + NPC_ETYPE_IP6, + 0xffff, +- }, +- { +- NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0xffff, +- 0x0000, + 0x0000, +- NPC_ETYPE_CTAG, +- 0xffff, +- }, +- { +- NPC_S_KPU1_CPT_HDR, 0xff, + 0x0000, +- 0xffff, + 0x0000, + 0x0000, +- NPC_ETYPE_QINQ, +- 0xffff, + }, + { + NPC_S_KPU1_CPT_HDR, 0xff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_IP, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_IP6, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_ARP, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_RARP, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_PTP, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_FCOE, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_CTAG, +- 0xffff, +- NPC_ETYPE_CTAG, +- 0xffff, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, + NPC_ETYPE_CTAG, + 0xffff, + 0x0000, +@@ -1999,16 +1865,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_SBTAG, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, ++ NPC_S_KPU1_CPT_HDR, 0xff, + NPC_ETYPE_QINQ, + 0xffff, + 0x0000, +@@ -2016,51 +1873,6 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = { + 0x0000, + 0x0000, + }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_ETAG, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_MPLSU, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_MPLSM, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- NPC_ETYPE_NSH, +- 0xffff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, +- { +- NPC_S_KPU1_CUSTOM_L2_24B, 0xff, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- 0x0000, +- }, + { + NPC_S_KPU1_VLAN_EXDSA, 0xff, + NPC_ETYPE_CTAG, +@@ -2165,6 +1977,15 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = { + 0x0000, + 0x0000, + }, ++ { ++ NPC_S_KPU2_CTAG, 0xff, ++ NPC_ETYPE_NGIO, ++ 0xffff, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ }, + { + NPC_S_KPU2_CTAG, 0xff, + NPC_ETYPE_PPPOE, +@@ -3057,11 +2878,38 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = { + 0x0000, + }, + { +- NPC_S_KPU2_NGIO, 0xff, ++ NPC_S_KPU2_CPT_CTAG, 0xff, ++ NPC_ETYPE_IP, ++ 0xffff, + 0x0000, + 0x0000, + 0x0000, + 0x0000, ++ }, ++ { ++ NPC_S_KPU2_CPT_CTAG, 0xff, ++ NPC_ETYPE_IP6, ++ 0xffff, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ }, ++ { ++ NPC_S_KPU2_CPT_QINQ, 0xff, ++ NPC_ETYPE_CTAG, ++ 0xffff, ++ NPC_ETYPE_IP, ++ 0xffff, ++ 0x0000, ++ 0x0000, ++ }, ++ { ++ NPC_S_KPU2_CPT_QINQ, 0xff, ++ NPC_ETYPE_CTAG, ++ 0xffff, ++ NPC_ETYPE_IP6, ++ 0xffff, + 0x0000, + 0x0000, + }, +@@ -5348,6 +5196,15 @@ static struct npc_kpu_profile_cam kpu5_cam_entries[] = { + 0x0000, + 0x0000, + }, ++ { ++ NPC_S_KPU5_NGIO, 0xff, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ 0x0000, ++ }, + { + NPC_S_NA, 0X00, + 0x0000, +@@ -8642,14 +8499,6 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { + 0, + 0, 0, 0, 0, + }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 8, 12, 0, 0, 0, +- NPC_S_KPU2_NGIO, 12, 1, +- NPC_LID_LA, NPC_LT_LA_ETHER, +- 0, +- 0, 0, 0, 0, +- }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 8, 12, 0, 0, 0, +@@ -9192,159 +9041,127 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 8, 0, 6, 3, 0, +- NPC_S_KPU5_IP, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, ++ NPC_S_KPU5_IP, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 6, 0, 0, 3, 0, +- NPC_S_KPU5_IP6, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, ++ NPC_S_KPU5_IP6, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 0, 0, 0, 3, 0, +- NPC_S_KPU5_ARP, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, ++ NPC_S_KPU5_ARP, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 0, 0, 0, 3, 0, +- NPC_S_KPU5_RARP, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, ++ NPC_S_KPU5_RARP, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 0, 0, 0, 3, 0, +- NPC_S_KPU5_PTP, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, ++ NPC_S_KPU5_PTP, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 0, 0, 0, 3, 0, +- NPC_S_KPU5_FCOE, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, ++ NPC_S_KPU5_FCOE, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 8, 12, 0, 0, 0, +- NPC_S_KPU2_CTAG2, 102, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, ++ NPC_S_KPU2_CTAG2, 12, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 4, 8, 0, 0, 0, +- NPC_S_KPU2_CTAG, 102, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, ++ NPC_S_KPU2_CTAG, 12, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 4, 8, 22, 0, 0, +- NPC_S_KPU2_SBTAG, 102, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, ++ NPC_S_KPU2_SBTAG, 12, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 4, 8, 0, 0, 0, +- NPC_S_KPU2_QINQ, 102, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, ++ NPC_S_KPU2_QINQ, 12, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 8, 12, 26, 0, 0, +- NPC_S_KPU2_ETAG, 102, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_ETAG, ++ NPC_S_KPU2_ETAG, 12, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 2, 6, 10, 2, 0, +- NPC_S_KPU4_MPLS, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_L_WITH_MPLS, ++ NPC_S_KPU4_MPLS, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 2, 6, 10, 2, 0, +- NPC_S_KPU4_MPLS, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_L_WITH_MPLS, ++ NPC_S_KPU4_MPLS, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, ++ 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 2, 0, 0, 2, 0, +- NPC_S_KPU4_NSH, 104, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_L_WITH_NSH, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 0, 1, +- NPC_S_NA, 0, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER, +- NPC_F_LA_L_UNK_ETYPE, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 8, 0, 6, 3, 0, +- NPC_S_KPU5_CPT_IP, 56, 1, +- NPC_LID_LA, NPC_LT_LA_CPT_HDR, ++ NPC_S_KPU4_NSH, 14, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, +- 6, 0, 0, 3, 0, +- NPC_S_KPU5_CPT_IP6, 56, 1, +- NPC_LID_LA, NPC_LT_LA_CPT_HDR, ++ 0, 0, 0, 0, 1, ++ NPC_S_NA, 0, 0, ++ NPC_LID_LA, NPC_LT_NA, + 0, + 0, 0, 0, 0, + }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 4, 8, 0, 0, 0, +- NPC_S_KPU2_CTAG, 54, 1, +- NPC_LID_LA, NPC_LT_LA_CPT_HDR, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 4, 8, 0, 0, 0, +- NPC_S_KPU2_QINQ, 54, 1, +- NPC_LID_LA, NPC_LT_LA_CPT_HDR, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, +- 0, 0, 0, 0, +- }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 8, 0, 6, 3, 0, +- NPC_S_KPU5_CPT_IP, 60, 1, ++ NPC_S_KPU5_CPT_IP, 14, 1, + NPC_LID_LA, NPC_LT_LA_CPT_HDR, + 0, + 0, 0, 0, 0, +@@ -9352,7 +9169,7 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 6, 0, 0, 3, 0, +- NPC_S_KPU5_CPT_IP6, 60, 1, ++ NPC_S_KPU5_CPT_IP6, 14, 1, + NPC_LID_LA, NPC_LT_LA_CPT_HDR, + 0, + 0, 0, 0, 0, +@@ -9360,7 +9177,7 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 4, 8, 0, 0, 0, +- NPC_S_KPU2_CTAG, 58, 1, ++ NPC_S_KPU2_CPT_CTAG, 12, 1, + NPC_LID_LA, NPC_LT_LA_CPT_HDR, + NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, + 0, 0, 0, 0, +@@ -9368,139 +9185,11 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = { + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 4, 8, 0, 0, 0, +- NPC_S_KPU2_QINQ, 58, 1, ++ NPC_S_KPU2_CPT_QINQ, 12, 1, + NPC_LID_LA, NPC_LT_LA_CPT_HDR, + NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, + 0, 0, 0, 0, + }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 0, 1, +- NPC_S_NA, 0, 1, +- NPC_LID_LA, NPC_LT_LA_CPT_HDR, +- NPC_F_LA_L_UNK_ETYPE, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 8, 0, 6, 3, 0, +- NPC_S_KPU5_IP, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- 0, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 6, 0, 0, 3, 0, +- NPC_S_KPU5_IP6, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- 0, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 3, 0, +- NPC_S_KPU5_ARP, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- 0, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 3, 0, +- NPC_S_KPU5_RARP, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- 0, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 3, 0, +- NPC_S_KPU5_PTP, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- 0, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 3, 0, +- NPC_S_KPU5_FCOE, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- 0, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 8, 12, 0, 0, 0, +- NPC_S_KPU2_CTAG2, 36, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 4, 8, 0, 0, 0, +- NPC_S_KPU2_CTAG, 36, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 4, 8, 22, 0, 0, +- NPC_S_KPU2_SBTAG, 36, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 4, 8, 0, 0, 0, +- NPC_S_KPU2_QINQ, 36, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 8, 12, 26, 0, 0, +- NPC_S_KPU2_ETAG, 36, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_ETAG, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 2, 6, 10, 2, 0, +- NPC_S_KPU4_MPLS, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_L_WITH_MPLS, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 2, 6, 10, 2, 0, +- NPC_S_KPU4_MPLS, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_L_WITH_MPLS, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 2, 0, 0, 2, 0, +- NPC_S_KPU4_NSH, 38, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_L_WITH_NSH, +- 0, 0, 0, 0, +- }, +- { +- NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 0, 1, +- NPC_S_NA, 0, 1, +- NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER, +- NPC_F_LA_L_UNK_ETYPE, +- 0, 0, 0, 0, +- }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 12, 0, 0, 1, 0, +@@ -9594,6 +9283,14 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = { + 0, + 0, 0, 0, 0, + }, ++ { ++ NPC_ERRLEV_RE, NPC_EC_NOERR, ++ 0, 0, 0, 2, 0, ++ NPC_S_KPU5_NGIO, 6, 1, ++ NPC_LID_LB, NPC_LT_LB_CTAG, ++ 0, ++ 0, 0, 0, 0, ++ }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, + 8, 0, 6, 2, 0, +@@ -10388,12 +10085,36 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = { + }, + { + NPC_ERRLEV_RE, NPC_EC_NOERR, +- 0, 0, 0, 0, 1, +- NPC_S_NA, 0, 1, +- NPC_LID_LC, NPC_LT_LC_NGIO, ++ 8, 0, 6, 2, 0, ++ NPC_S_KPU5_CPT_IP, 6, 1, ++ NPC_LID_LB, NPC_LT_LB_CTAG, ++ 0, ++ 0, 0, 0, 0, ++ }, ++ { ++ NPC_ERRLEV_RE, NPC_EC_NOERR, ++ 6, 0, 0, 2, 0, ++ NPC_S_KPU5_CPT_IP6, 6, 1, ++ NPC_LID_LB, NPC_LT_LB_CTAG, + 0, + 0, 0, 0, 0, + }, ++ { ++ NPC_ERRLEV_RE, NPC_EC_NOERR, ++ 8, 0, 6, 2, 0, ++ NPC_S_KPU5_CPT_IP, 10, 1, ++ NPC_LID_LB, NPC_LT_LB_STAG_QINQ, ++ NPC_F_LB_U_MORE_TAG | NPC_F_LB_L_WITH_CTAG, ++ 0, 0, 0, 0, ++ }, ++ { ++ NPC_ERRLEV_RE, NPC_EC_NOERR, ++ 6, 0, 0, 2, 0, ++ NPC_S_KPU5_CPT_IP6, 10, 1, ++ NPC_LID_LB, NPC_LT_LB_STAG_QINQ, ++ NPC_F_LB_U_MORE_TAG | NPC_F_LB_L_WITH_CTAG, ++ 0, 0, 0, 0, ++ }, + { + NPC_ERRLEV_LB, NPC_EC_L2_K3, + 0, 0, 0, 0, 1, +@@ -12425,6 +12146,14 @@ static struct npc_kpu_profile_action kpu5_action_entries[] = { + 0, + 0, 0, 0, 0, + }, ++ { ++ NPC_ERRLEV_RE, NPC_EC_NOERR, ++ 0, 0, 0, 0, 1, ++ NPC_S_NA, 0, 1, ++ NPC_LID_LC, NPC_LT_LC_NGIO, ++ 0, ++ 0, 0, 0, 0, ++ }, + { + NPC_ERRLEV_LC, NPC_EC_UNK, + 0, 0, 0, 0, 1, +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +index 9b8e59f4c206d..77cb52b80c60f 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +@@ -85,6 +85,8 @@ struct ptp *ptp_get(void) + /* Check driver is bound to PTP block */ + if (!ptp) + ptp = ERR_PTR(-EPROBE_DEFER); ++ else ++ pci_dev_get(ptp->pdev); + + return ptp; + } +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +index 07b0eafccad87..9ea2f6ac38ec1 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +@@ -29,6 +29,9 @@ static struct mac_ops rpm_mac_ops = { + .mac_get_pause_frm_status = rpm_lmac_get_pause_frm_status, + .mac_enadis_pause_frm = rpm_lmac_enadis_pause_frm, + .mac_pause_frm_config = rpm_lmac_pause_frm_config, ++ .mac_enadis_ptp_config = rpm_lmac_ptp_config, ++ .mac_rx_tx_enable = rpm_lmac_rx_tx_enable, ++ .mac_tx_enable = rpm_lmac_tx_enable, + }; + + struct mac_ops *rpm_get_mac_ops(void) +@@ -53,6 +56,43 @@ int rpm_get_nr_lmacs(void *rpmd) + return hweight8(rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS) & 0xFULL); + } + ++int rpm_lmac_tx_enable(void *rpmd, int lmac_id, bool enable) ++{ ++ rpm_t *rpm = rpmd; ++ u64 cfg, last; ++ ++ if (!is_lmac_valid(rpm, lmac_id)) ++ return -ENODEV; ++ ++ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); ++ last = cfg; ++ if (enable) ++ cfg |= RPM_TX_EN; ++ else ++ cfg &= ~(RPM_TX_EN); ++ ++ if (cfg != last) ++ rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); ++ return !!(last & RPM_TX_EN); ++} ++ ++int rpm_lmac_rx_tx_enable(void *rpmd, int lmac_id, bool enable) ++{ ++ rpm_t *rpm = rpmd; ++ u64 cfg; ++ ++ if (!is_lmac_valid(rpm, lmac_id)) ++ return -ENODEV; ++ ++ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); ++ if (enable) ++ cfg |= RPM_RX_EN | RPM_TX_EN; ++ else ++ cfg &= ~(RPM_RX_EN | RPM_TX_EN); ++ rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); ++ return 0; ++} ++ + void rpm_lmac_enadis_rx_pause_fwding(void *rpmd, int lmac_id, bool enable) + { + rpm_t *rpm = rpmd; +@@ -251,22 +291,35 @@ int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable) + if (!rpm || lmac_id >= rpm->lmac_count) + return -ENODEV; + lmac_type = rpm->mac_ops->get_lmac_type(rpm, lmac_id); +- if (lmac_type == LMAC_MODE_100G_R) { +- cfg = rpm_read(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1); +- +- if (enable) +- cfg |= RPMX_MTI_PCS_LBK; +- else +- cfg &= ~RPMX_MTI_PCS_LBK; +- rpm_write(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1, cfg); +- } else { +- cfg = rpm_read(rpm, lmac_id, RPMX_MTI_LPCSX_CONTROL1); +- if (enable) +- cfg |= RPMX_MTI_PCS_LBK; +- else +- cfg &= ~RPMX_MTI_PCS_LBK; +- rpm_write(rpm, lmac_id, RPMX_MTI_LPCSX_CONTROL1, cfg); ++ ++ if (lmac_type == LMAC_MODE_QSGMII || lmac_type == LMAC_MODE_SGMII) { ++ dev_err(&rpm->pdev->dev, "loopback not supported for LPC mode\n"); ++ return 0; + } + ++ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1); ++ ++ if (enable) ++ cfg |= RPMX_MTI_PCS_LBK; ++ else ++ cfg &= ~RPMX_MTI_PCS_LBK; ++ rpm_write(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1, cfg); ++ + return 0; + } ++ ++void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable) ++{ ++ rpm_t *rpm = rpmd; ++ u64 cfg; ++ ++ if (!is_lmac_valid(rpm, lmac_id)) ++ return; ++ ++ cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_CFG); ++ if (enable) ++ cfg |= RPMX_RX_TS_PREPEND; ++ else ++ cfg &= ~RPMX_RX_TS_PREPEND; ++ rpm_write(rpm, lmac_id, RPMX_CMRX_CFG, cfg); ++} +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +index f0b069442dccb..ff580311edd03 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +@@ -14,6 +14,8 @@ + #define PCI_DEVID_CN10K_RPM 0xA060 + + /* Registers */ ++#define RPMX_CMRX_CFG 0x00 ++#define RPMX_RX_TS_PREPEND BIT_ULL(22) + #define RPMX_CMRX_SW_INT 0x180 + #define RPMX_CMRX_SW_INT_W1S 0x188 + #define RPMX_CMRX_SW_INT_ENA_W1S 0x198 +@@ -41,6 +43,8 @@ + #define RPMX_MTI_STAT_DATA_HI_CDC 0x10038 + + #define RPM_LMAC_FWI 0xa ++#define RPM_TX_EN BIT_ULL(0) ++#define RPM_RX_EN BIT_ULL(1) + + /* Function Declarations */ + int rpm_get_nr_lmacs(void *rpmd); +@@ -54,4 +58,7 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause, + u8 rx_pause); + int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat); + int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat); ++void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable); ++int rpm_lmac_rx_tx_enable(void *rpmd, int lmac_id, bool enable); ++int rpm_lmac_tx_enable(void *rpmd, int lmac_id, bool enable); + #endif /* RPM_H */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +index 35836903b7fbc..11ef46e72ddd9 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +@@ -520,8 +520,11 @@ static void rvu_block_reset(struct rvu *rvu, int blkaddr, u64 rst_reg) + + rvu_write64(rvu, blkaddr, rst_reg, BIT_ULL(0)); + err = rvu_poll_reg(rvu, blkaddr, rst_reg, BIT_ULL(63), true); +- if (err) +- dev_err(rvu->dev, "HW block:%d reset failed\n", blkaddr); ++ if (err) { ++ dev_err(rvu->dev, "HW block:%d reset timeout retrying again\n", blkaddr); ++ while (rvu_poll_reg(rvu, blkaddr, rst_reg, BIT_ULL(63), true) == -EBUSY) ++ ; ++ } + } + + static void rvu_reset_all_blocks(struct rvu *rvu) +@@ -2281,7 +2284,7 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw, + goto free_regions; + break; + default: +- return err; ++ goto free_regions; + } + + mw->mbox_wq = alloc_workqueue(name, +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +index 1d9411232f1da..a7213db38804b 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +@@ -220,6 +220,7 @@ struct rvu_pfvf { + u16 maxlen; + u16 minlen; + ++ bool hw_rx_tstamp_en; /* Is rx_tstamp enabled */ + u8 mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */ + u8 default_mac[ETH_ALEN]; /* MAC address from FWdata */ + +@@ -237,6 +238,7 @@ struct rvu_pfvf { + bool cgx_in_use; /* this PF/VF using CGX? */ + int cgx_users; /* number of cgx users - used only by PFs */ + ++ int intf_mode; + u8 nix_blkaddr; /* BLKADDR_NIX0/1 assigned to this PF */ + u8 nix_rx_intf; /* NIX0_RX/NIX1_RX interface to NPC */ + u8 nix_tx_intf; /* NIX0_TX/NIX1_TX interface to NPC */ +@@ -794,10 +796,12 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, + void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, u16 src, struct mcam_entry *entry, + u8 *intf, u8 *ena); ++bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc); + bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature); + u32 rvu_cgx_get_fifolen(struct rvu *rvu); + void *rvu_first_cgx_pdata(struct rvu *rvu); + int cgxlmac_to_pf(struct rvu *rvu, int cgx_id, int lmac_id); ++int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable); + + int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf, + int type); +@@ -827,4 +831,7 @@ void rvu_switch_enable(struct rvu *rvu); + void rvu_switch_disable(struct rvu *rvu); + void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc); + ++int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir, ++ u64 pkind, u8 var_len_off, u8 var_len_off_mask, ++ u8 shift_dir); + #endif /* RVU_H */ +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +index 81e8ea9ee30ea..28ff67819566c 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +@@ -411,7 +411,7 @@ int rvu_cgx_exit(struct rvu *rvu) + * VF's of mapped PF and other PFs are not allowed. This fn() checks + * whether a PFFUNC is permitted to do the config or not. + */ +-static bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc) ++inline bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc) + { + if ((pcifunc & RVU_PFVF_FUNC_MASK) || + !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) +@@ -442,16 +442,26 @@ void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable) + int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start) + { + int pf = rvu_get_pf(pcifunc); ++ struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; ++ void *cgxd; + + if (!is_cgx_config_permitted(rvu, pcifunc)) + return LMAC_AF_ERR_PERM_DENIED; + + rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); ++ cgxd = rvu_cgx_pdata(cgx_id, rvu); ++ mac_ops = get_mac_ops(cgxd); + +- cgx_lmac_rx_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, start); ++ return mac_ops->mac_rx_tx_enable(cgxd, lmac_id, start); ++} + +- return 0; ++int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable) ++{ ++ struct mac_ops *mac_ops; ++ ++ mac_ops = get_mac_ops(cgxd); ++ return mac_ops->mac_tx_enable(cgxd, lmac_id, enable); + } + + void rvu_cgx_disable_dmac_entries(struct rvu *rvu, u16 pcifunc) +@@ -694,7 +704,9 @@ int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req, + + static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) + { ++ struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + int pf = rvu_get_pf(pcifunc); ++ struct mac_ops *mac_ops; + u8 cgx_id, lmac_id; + void *cgxd; + +@@ -711,13 +723,16 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) + rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); + cgxd = rvu_cgx_pdata(cgx_id, rvu); + +- cgx_lmac_ptp_config(cgxd, lmac_id, enable); ++ mac_ops = get_mac_ops(cgxd); ++ mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true); + /* If PTP is enabled then inform NPC that packets to be + * parsed by this PF will have their data shifted by 8 bytes + * and if PTP is disabled then no shift is required + */ + if (npc_config_ts_kpuaction(rvu, pf, pcifunc, enable)) + return -EINVAL; ++ /* This flag is required to clean up CGX conf if app gets killed */ ++ pfvf->hw_rx_tstamp_en = enable; + + return 0; + } +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +index 49d822a98adab..f001579569a2b 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +@@ -1131,6 +1131,8 @@ static void print_nix_cn10k_sq_ctx(struct seq_file *m, + seq_printf(m, "W3: head_offset\t\t\t%d\nW3: smenq_next_sqb_vld\t\t%d\n\n", + sq_ctx->head_offset, sq_ctx->smenq_next_sqb_vld); + ++ seq_printf(m, "W3: smq_next_sq_vld\t\t%d\nW3: smq_pend\t\t\t%d\n", ++ sq_ctx->smq_next_sq_vld, sq_ctx->smq_pend); + seq_printf(m, "W4: next_sqb \t\t\t%llx\n\n", sq_ctx->next_sqb); + seq_printf(m, "W5: tail_sqb \t\t\t%llx\n\n", sq_ctx->tail_sqb); + seq_printf(m, "W6: smenq_sqb \t\t\t%llx\n\n", sq_ctx->smenq_sqb); +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +index 6970540dc4709..603361c94786a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +@@ -28,6 +28,7 @@ static int nix_verify_bandprof(struct nix_cn10k_aq_enq_req *req, + static int nix_free_all_bandprof(struct rvu *rvu, u16 pcifunc); + static void nix_clear_ratelimit_aggr(struct rvu *rvu, struct nix_hw *nix_hw, + u32 leaf_prof); ++static const char *nix_get_ctx_name(int ctype); + + enum mc_tbl_sz { + MC_TBL_SZ_256, +@@ -511,11 +512,11 @@ static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req, + cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST); + lmac_chan_cnt = cfg & 0xFF; + +- cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST1); +- sdp_chan_cnt = cfg & 0xFFF; +- + cgx_bpid_cnt = hw->cgx_links * lmac_chan_cnt; + lbk_bpid_cnt = hw->lbk_links * ((cfg >> 16) & 0xFF); ++ ++ cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST1); ++ sdp_chan_cnt = cfg & 0xFFF; + sdp_bpid_cnt = hw->sdp_links * sdp_chan_cnt; + + pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc); +@@ -1061,10 +1062,68 @@ static int rvu_nix_blk_aq_enq_inst(struct rvu *rvu, struct nix_hw *nix_hw, + return 0; + } + ++static int rvu_nix_verify_aq_ctx(struct rvu *rvu, struct nix_hw *nix_hw, ++ struct nix_aq_enq_req *req, u8 ctype) ++{ ++ struct nix_cn10k_aq_enq_req aq_req; ++ struct nix_cn10k_aq_enq_rsp aq_rsp; ++ int rc, word; ++ ++ if (req->ctype != NIX_AQ_CTYPE_CQ) ++ return 0; ++ ++ rc = nix_aq_context_read(rvu, nix_hw, &aq_req, &aq_rsp, ++ req->hdr.pcifunc, ctype, req->qidx); ++ if (rc) { ++ dev_err(rvu->dev, ++ "%s: Failed to fetch %s%d context of PFFUNC 0x%x\n", ++ __func__, nix_get_ctx_name(ctype), req->qidx, ++ req->hdr.pcifunc); ++ return rc; ++ } ++ ++ /* Make copy of original context & mask which are required ++ * for resubmission ++ */ ++ memcpy(&aq_req.cq_mask, &req->cq_mask, sizeof(struct nix_cq_ctx_s)); ++ memcpy(&aq_req.cq, &req->cq, sizeof(struct nix_cq_ctx_s)); ++ ++ /* exclude fields which HW can update */ ++ aq_req.cq_mask.cq_err = 0; ++ aq_req.cq_mask.wrptr = 0; ++ aq_req.cq_mask.tail = 0; ++ aq_req.cq_mask.head = 0; ++ aq_req.cq_mask.avg_level = 0; ++ aq_req.cq_mask.update_time = 0; ++ aq_req.cq_mask.substream = 0; ++ ++ /* Context mask (cq_mask) holds mask value of fields which ++ * are changed in AQ WRITE operation. ++ * for example cq.drop = 0xa; ++ * cq_mask.drop = 0xff; ++ * Below logic performs '&' between cq and cq_mask so that non ++ * updated fields are masked out for request and response ++ * comparison ++ */ ++ for (word = 0; word < sizeof(struct nix_cq_ctx_s) / sizeof(u64); ++ word++) { ++ *(u64 *)((u8 *)&aq_rsp.cq + word * 8) &= ++ (*(u64 *)((u8 *)&aq_req.cq_mask + word * 8)); ++ *(u64 *)((u8 *)&aq_req.cq + word * 8) &= ++ (*(u64 *)((u8 *)&aq_req.cq_mask + word * 8)); ++ } ++ ++ if (memcmp(&aq_req.cq, &aq_rsp.cq, sizeof(struct nix_cq_ctx_s))) ++ return NIX_AF_ERR_AQ_CTX_RETRY_WRITE; ++ ++ return 0; ++} ++ + static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req, + struct nix_aq_enq_rsp *rsp) + { + struct nix_hw *nix_hw; ++ int err, retries = 5; + int blkaddr; + + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, req->hdr.pcifunc); +@@ -1075,7 +1134,24 @@ static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req, + if (!nix_hw) + return NIX_AF_ERR_INVALID_NIXBLK; + +- return rvu_nix_blk_aq_enq_inst(rvu, nix_hw, req, rsp); ++retry: ++ err = rvu_nix_blk_aq_enq_inst(rvu, nix_hw, req, rsp); ++ ++ /* HW errata 'AQ Modification to CQ could be discarded on heavy traffic' ++ * As a work around perfrom CQ context read after each AQ write. If AQ ++ * read shows AQ write is not updated perform AQ write again. ++ */ ++ if (!err && req->op == NIX_AQ_INSTOP_WRITE) { ++ err = rvu_nix_verify_aq_ctx(rvu, nix_hw, req, NIX_AQ_CTYPE_CQ); ++ if (err == NIX_AF_ERR_AQ_CTX_RETRY_WRITE) { ++ if (retries--) ++ goto retry; ++ else ++ return NIX_AF_ERR_CQ_CTX_WRITE_ERR; ++ } ++ } ++ ++ return err; + } + + static const char *nix_get_ctx_name(int ctype) +@@ -1992,8 +2068,8 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, + /* enable cgx tx if disabled */ + if (is_pf_cgxmapped(rvu, pf)) { + rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); +- restore_tx_en = !cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu), +- lmac_id, true); ++ restore_tx_en = !rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), ++ lmac_id, true); + } + + cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq)); +@@ -2016,7 +2092,7 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, + rvu_cgx_enadis_rx_bp(rvu, pf, true); + /* restore cgx tx state */ + if (restore_tx_en) +- cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false); ++ rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false); + return err; + } + +@@ -3802,7 +3878,7 @@ nix_config_link_credits(struct rvu *rvu, int blkaddr, int link, + /* Enable cgx tx if disabled for credits to be back */ + if (is_pf_cgxmapped(rvu, pf)) { + rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); +- restore_tx_en = !cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu), ++ restore_tx_en = !rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), + lmac_id, true); + } + +@@ -3815,8 +3891,8 @@ nix_config_link_credits(struct rvu *rvu, int blkaddr, int link, + NIX_AF_TL1X_SW_XOFF(schq), BIT_ULL(0)); + } + +- rc = -EBUSY; +- poll_tmo = jiffies + usecs_to_jiffies(10000); ++ rc = NIX_AF_ERR_LINK_CREDITS; ++ poll_tmo = jiffies + usecs_to_jiffies(200000); + /* Wait for credits to return */ + do { + if (time_after(jiffies, poll_tmo)) +@@ -3842,7 +3918,7 @@ exit: + + /* Restore state of cgx tx */ + if (restore_tx_en) +- cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false); ++ rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false); + + mutex_unlock(&rvu->rsrc_lock); + return rc; +@@ -4443,6 +4519,10 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) + { + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + struct hwctx_disable_req ctx_req; ++ int pf = rvu_get_pf(pcifunc); ++ struct mac_ops *mac_ops; ++ u8 cgx_id, lmac_id; ++ void *cgxd; + int err; + + ctx_req.hdr.pcifunc = pcifunc; +@@ -4479,6 +4559,22 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) + dev_err(rvu->dev, "CQ ctx disable failed\n"); + } + ++ /* reset HW config done for Switch headers */ ++ rvu_npc_set_parse_mode(rvu, pcifunc, OTX2_PRIV_FLAGS_DEFAULT, ++ (PKIND_TX | PKIND_RX), 0, 0, 0, 0); ++ ++ /* Disabling CGX and NPC config done for PTP */ ++ if (pfvf->hw_rx_tstamp_en) { ++ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); ++ cgxd = rvu_cgx_pdata(cgx_id, rvu); ++ mac_ops = get_mac_ops(cgxd); ++ mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, false); ++ /* Undo NPC config done for PTP */ ++ if (npc_config_ts_kpuaction(rvu, pf, pcifunc, false)) ++ dev_err(rvu->dev, "NPC config for PTP failed\n"); ++ pfvf->hw_rx_tstamp_en = false; ++ } ++ + nix_ctx_free(rvu, pfvf); + + nix_free_all_bandprof(rvu, pcifunc); +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +index 5efb4174e82df..fbb573c40c1ac 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +@@ -402,6 +402,7 @@ static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index, struct mcam_entry *entry, + bool *enable) + { ++ struct rvu_npc_mcam_rule *rule; + u16 owner, target_func; + struct rvu_pfvf *pfvf; + u64 rx_action; +@@ -423,6 +424,12 @@ static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam, + test_bit(NIXLF_INITIALIZED, &pfvf->flags))) + *enable = false; + ++ /* fix up not needed for the rules added by user(ntuple filters) */ ++ list_for_each_entry(rule, &mcam->mcam_rules, list) { ++ if (rule->entry == index) ++ return; ++ } ++ + /* copy VF default entry action to the VF mcam entry */ + rx_action = npc_get_default_entry_action(rvu, mcam, blkaddr, + target_func); +@@ -489,8 +496,8 @@ static void npc_config_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, + } + + /* PF installing VF rule */ +- if (intf == NIX_INTF_RX && actindex < mcam->bmap_entries) +- npc_fixup_vf_rule(rvu, mcam, blkaddr, index, entry, &enable); ++ if (is_npc_intf_rx(intf) && actindex < mcam->bmap_entries) ++ npc_fixup_vf_rule(rvu, mcam, blkaddr, actindex, entry, &enable); + + /* Set 'action' */ + rvu_write64(rvu, blkaddr, +@@ -916,7 +923,8 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, u16 pcifunc, u64 rx_action) + { + int actindex, index, bank, entry; +- bool enable; ++ struct rvu_npc_mcam_rule *rule; ++ bool enable, update; + + if (!(pcifunc & RVU_PFVF_FUNC_MASK)) + return; +@@ -924,6 +932,14 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam, + mutex_lock(&mcam->lock); + for (index = 0; index < mcam->bmap_entries; index++) { + if (mcam->entry2target_pffunc[index] == pcifunc) { ++ update = true; ++ /* update not needed for the rules added via ntuple filters */ ++ list_for_each_entry(rule, &mcam->mcam_rules, list) { ++ if (rule->entry == index) ++ update = false; ++ } ++ if (!update) ++ continue; + bank = npc_get_bank(mcam, index); + actindex = index; + entry = index & (mcam->banksize - 1); +@@ -3167,6 +3183,102 @@ int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req, + return 0; + } + ++static int ++npc_set_var_len_offset_pkind(struct rvu *rvu, u16 pcifunc, u64 pkind, ++ u8 var_len_off, u8 var_len_off_mask, u8 shift_dir) ++{ ++ struct npc_kpu_action0 *act0; ++ u8 shift_count = 0; ++ int blkaddr; ++ u64 val; ++ ++ if (!var_len_off_mask) ++ return -EINVAL; ++ ++ if (var_len_off_mask != 0xff) { ++ if (shift_dir) ++ shift_count = __ffs(var_len_off_mask); ++ else ++ shift_count = (8 - __fls(var_len_off_mask)); ++ } ++ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, pcifunc); ++ if (blkaddr < 0) { ++ dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__); ++ return -EINVAL; ++ } ++ val = rvu_read64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind)); ++ act0 = (struct npc_kpu_action0 *)&val; ++ act0->var_len_shift = shift_count; ++ act0->var_len_right = shift_dir; ++ act0->var_len_mask = var_len_off_mask; ++ act0->var_len_offset = var_len_off; ++ rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind), val); ++ return 0; ++} ++ ++int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir, ++ u64 pkind, u8 var_len_off, u8 var_len_off_mask, ++ u8 shift_dir) ++ ++{ ++ struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); ++ int blkaddr, nixlf, rc, intf_mode; ++ int pf = rvu_get_pf(pcifunc); ++ u64 rxpkind, txpkind; ++ u8 cgx_id, lmac_id; ++ ++ /* use default pkind to disable edsa/higig */ ++ rxpkind = rvu_npc_get_pkind(rvu, pf); ++ txpkind = NPC_TX_DEF_PKIND; ++ intf_mode = NPC_INTF_MODE_DEF; ++ ++ if (mode & OTX2_PRIV_FLAGS_CUSTOM) { ++ if (pkind == NPC_RX_CUSTOM_PRE_L2_PKIND) { ++ rc = npc_set_var_len_offset_pkind(rvu, pcifunc, pkind, ++ var_len_off, ++ var_len_off_mask, ++ shift_dir); ++ if (rc) ++ return rc; ++ } ++ rxpkind = pkind; ++ txpkind = pkind; ++ } ++ ++ if (dir & PKIND_RX) { ++ /* rx pkind set req valid only for cgx mapped PFs */ ++ if (!is_cgx_config_permitted(rvu, pcifunc)) ++ return 0; ++ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); ++ ++ rc = cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id, ++ rxpkind); ++ if (rc) ++ return rc; ++ } ++ ++ if (dir & PKIND_TX) { ++ /* Tx pkind set request valid if PCIFUNC has NIXLF attached */ ++ rc = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr); ++ if (rc) ++ return rc; ++ ++ rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), ++ txpkind); ++ } ++ ++ pfvf->intf_mode = intf_mode; ++ return 0; ++} ++ ++int rvu_mbox_handler_npc_set_pkind(struct rvu *rvu, struct npc_set_pkind *req, ++ struct msg_rsp *rsp) ++{ ++ return rvu_npc_set_parse_mode(rvu, req->hdr.pcifunc, req->mode, ++ req->dir, req->pkind, req->var_len_off, ++ req->var_len_off_mask, req->shift_dir); ++} ++ + int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu, + struct msg_req *req, + struct npc_mcam_read_base_rule_rsp *rsp) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +index 51ddc7b81d0bd..ca404d51d9f56 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +@@ -1098,14 +1098,6 @@ find_rule: + write_req.cntr = rule->cntr; + } + +- err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, +- &write_rsp); +- if (err) { +- rvu_mcam_remove_counter_from_rule(rvu, owner, rule); +- if (new) +- kfree(rule); +- return err; +- } + /* update rule */ + memcpy(&rule->packet, &dummy.packet, sizeof(rule->packet)); + memcpy(&rule->mask, &dummy.mask, sizeof(rule->mask)); +@@ -1129,6 +1121,18 @@ find_rule: + if (req->default_rule) + pfvf->def_ucast_rule = rule; + ++ /* write to mcam entry registers */ ++ err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, ++ &write_rsp); ++ if (err) { ++ rvu_mcam_remove_counter_from_rule(rvu, owner, rule); ++ if (new) { ++ list_del(&rule->list); ++ kfree(rule); ++ } ++ return err; ++ } ++ + /* VF's MAC address is being changed via PF */ + if (pf_set_vfs_mac) { + ether_addr_copy(pfvf->default_mac, req->packet.dmac); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +index a51ecd771d075..637450de189c8 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +@@ -591,6 +591,7 @@ static inline void __cn10k_aura_freeptr(struct otx2_nic *pfvf, u64 aura, + size++; + tar_addr |= ((size - 1) & 0x7) << 4; + } ++ dma_wmb(); + memcpy((u64 *)lmt_info->lmt_addr, ptrs, sizeof(u64) * num_ptrs); + /* Perform LMTST flush */ + cn10k_lmt_flush(val, tar_addr); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +index 53df7fff92c40..b1894d4045b8d 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +@@ -386,7 +386,12 @@ static int otx2_forward_vf_mbox_msgs(struct otx2_nic *pf, + dst_mdev->msg_size = mbox_hdr->msg_size; + dst_mdev->num_msgs = num_msgs; + err = otx2_sync_mbox_msg(dst_mbox); +- if (err) { ++ /* Error code -EIO indicate there is a communication failure ++ * to the AF. Rest of the error codes indicate that AF processed ++ * VF messages and set the error codes in response messages ++ * (if any) so simply forward responses to VF. ++ */ ++ if (err == -EIO) { + dev_warn(pf->dev, + "AF not responding to VF%d messages\n", vf); + /* restore PF mbase and exit */ +@@ -1493,6 +1498,44 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) + mutex_unlock(&mbox->lock); + } + ++static void otx2_do_set_rx_mode(struct otx2_nic *pf) ++{ ++ struct net_device *netdev = pf->netdev; ++ struct nix_rx_mode *req; ++ bool promisc = false; ++ ++ if (!(netdev->flags & IFF_UP)) ++ return; ++ ++ if ((netdev->flags & IFF_PROMISC) || ++ (netdev_uc_count(netdev) > OTX2_MAX_UNICAST_FLOWS)) { ++ promisc = true; ++ } ++ ++ /* Write unicast address to mcam entries or del from mcam */ ++ if (!promisc && netdev->priv_flags & IFF_UNICAST_FLT) ++ __dev_uc_sync(netdev, otx2_add_macfilter, otx2_del_macfilter); ++ ++ mutex_lock(&pf->mbox.lock); ++ req = otx2_mbox_alloc_msg_nix_set_rx_mode(&pf->mbox); ++ if (!req) { ++ mutex_unlock(&pf->mbox.lock); ++ return; ++ } ++ ++ req->mode = NIX_RX_MODE_UCAST; ++ ++ if (promisc) ++ req->mode |= NIX_RX_MODE_PROMISC; ++ if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) ++ req->mode |= NIX_RX_MODE_ALLMULTI; ++ ++ req->mode |= NIX_RX_MODE_USE_MCE; ++ ++ otx2_sync_mbox_msg(&pf->mbox); ++ mutex_unlock(&pf->mbox.lock); ++} ++ + int otx2_open(struct net_device *netdev) + { + struct otx2_nic *pf = netdev_priv(netdev); +@@ -1646,6 +1689,8 @@ int otx2_open(struct net_device *netdev) + if (err) + goto err_tx_stop_queues; + ++ otx2_do_set_rx_mode(pf); ++ + return 0; + + err_tx_stop_queues: +@@ -1791,43 +1836,11 @@ static void otx2_set_rx_mode(struct net_device *netdev) + queue_work(pf->otx2_wq, &pf->rx_mode_work); + } + +-static void otx2_do_set_rx_mode(struct work_struct *work) ++static void otx2_rx_mode_wrk_handler(struct work_struct *work) + { + struct otx2_nic *pf = container_of(work, struct otx2_nic, rx_mode_work); +- struct net_device *netdev = pf->netdev; +- struct nix_rx_mode *req; +- bool promisc = false; +- +- if (!(netdev->flags & IFF_UP)) +- return; +- +- if ((netdev->flags & IFF_PROMISC) || +- (netdev_uc_count(netdev) > OTX2_MAX_UNICAST_FLOWS)) { +- promisc = true; +- } +- +- /* Write unicast address to mcam entries or del from mcam */ +- if (!promisc && netdev->priv_flags & IFF_UNICAST_FLT) +- __dev_uc_sync(netdev, otx2_add_macfilter, otx2_del_macfilter); + +- mutex_lock(&pf->mbox.lock); +- req = otx2_mbox_alloc_msg_nix_set_rx_mode(&pf->mbox); +- if (!req) { +- mutex_unlock(&pf->mbox.lock); +- return; +- } +- +- req->mode = NIX_RX_MODE_UCAST; +- +- if (promisc) +- req->mode |= NIX_RX_MODE_PROMISC; +- if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) +- req->mode |= NIX_RX_MODE_ALLMULTI; +- +- req->mode |= NIX_RX_MODE_USE_MCE; +- +- otx2_sync_mbox_msg(&pf->mbox); +- mutex_unlock(&pf->mbox.lock); ++ otx2_do_set_rx_mode(pf); + } + + static int otx2_set_features(struct net_device *netdev, +@@ -2358,7 +2371,7 @@ static int otx2_wq_init(struct otx2_nic *pf) + if (!pf->otx2_wq) + return -ENOMEM; + +- INIT_WORK(&pf->rx_mode_work, otx2_do_set_rx_mode); ++ INIT_WORK(&pf->rx_mode_work, otx2_rx_mode_wrk_handler); + INIT_WORK(&pf->reset_task, otx2_reset_task); + return 0; + } +diff --git a/drivers/net/ethernet/marvell/prestera/prestera_main.c b/drivers/net/ethernet/marvell/prestera/prestera_main.c +index 44c670807fb3c..aa543b29799ed 100644 +--- a/drivers/net/ethernet/marvell/prestera/prestera_main.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_main.c +@@ -54,12 +54,14 @@ int prestera_port_pvid_set(struct prestera_port *port, u16 vid) + struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw, + u32 dev_id, u32 hw_id) + { +- struct prestera_port *port = NULL; ++ struct prestera_port *port = NULL, *tmp; + + read_lock(&sw->port_list_lock); +- list_for_each_entry(port, &sw->port_list, list) { +- if (port->dev_id == dev_id && port->hw_id == hw_id) ++ list_for_each_entry(tmp, &sw->port_list, list) { ++ if (tmp->dev_id == dev_id && tmp->hw_id == hw_id) { ++ port = tmp; + break; ++ } + } + read_unlock(&sw->port_list_lock); + +@@ -68,12 +70,14 @@ struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw, + + struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id) + { +- struct prestera_port *port = NULL; ++ struct prestera_port *port = NULL, *tmp; + + read_lock(&sw->port_list_lock); +- list_for_each_entry(port, &sw->port_list, list) { +- if (port->id == id) ++ list_for_each_entry(tmp, &sw->port_list, list) { ++ if (tmp->id == id) { ++ port = tmp; + break; ++ } + } + read_unlock(&sw->port_list_lock); + +@@ -703,23 +707,27 @@ static int prestera_netdev_port_event(struct net_device *lower, + struct net_device *dev, + unsigned long event, void *ptr) + { +- struct netdev_notifier_changeupper_info *info = ptr; ++ struct netdev_notifier_info *info = ptr; ++ struct netdev_notifier_changeupper_info *cu_info; + struct prestera_port *port = netdev_priv(dev); + struct netlink_ext_ack *extack; + struct net_device *upper; + +- extack = netdev_notifier_info_to_extack(&info->info); +- upper = info->upper_dev; ++ extack = netdev_notifier_info_to_extack(info); ++ cu_info = container_of(info, ++ struct netdev_notifier_changeupper_info, ++ info); + + switch (event) { + case NETDEV_PRECHANGEUPPER: ++ upper = cu_info->upper_dev; + if (!netif_is_bridge_master(upper) && + !netif_is_lag_master(upper)) { + NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type"); + return -EINVAL; + } + +- if (!info->linking) ++ if (!cu_info->linking) + break; + + if (netdev_has_any_upper_dev(upper)) { +@@ -728,7 +736,7 @@ static int prestera_netdev_port_event(struct net_device *lower, + } + + if (netif_is_lag_master(upper) && +- !prestera_lag_master_check(upper, info->upper_info, extack)) ++ !prestera_lag_master_check(upper, cu_info->upper_info, extack)) + return -EOPNOTSUPP; + if (netif_is_lag_master(upper) && vlan_uses_dev(dev)) { + NL_SET_ERR_MSG_MOD(extack, +@@ -744,14 +752,15 @@ static int prestera_netdev_port_event(struct net_device *lower, + break; + + case NETDEV_CHANGEUPPER: ++ upper = cu_info->upper_dev; + if (netif_is_bridge_master(upper)) { +- if (info->linking) ++ if (cu_info->linking) + return prestera_bridge_port_join(upper, port, + extack); + else + prestera_bridge_port_leave(upper, port); + } else if (netif_is_lag_master(upper)) { +- if (info->linking) ++ if (cu_info->linking) + return prestera_lag_port_add(port, upper); + else + prestera_lag_port_del(port); +diff --git a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c +index 3ce6ccd0f5394..b4599fe4ca8da 100644 +--- a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c +@@ -497,8 +497,8 @@ int prestera_bridge_port_join(struct net_device *br_dev, + + br_port = prestera_bridge_port_add(bridge, port->dev); + if (IS_ERR(br_port)) { +- err = PTR_ERR(br_port); +- goto err_brport_create; ++ prestera_bridge_put(bridge); ++ return PTR_ERR(br_port); + } + + err = switchdev_bridge_port_offload(br_port->dev, port->dev, NULL, +@@ -519,8 +519,6 @@ err_port_join: + switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL); + err_switchdev_offload: + prestera_bridge_port_put(br_port); +-err_brport_create: +- prestera_bridge_put(bridge); + return err; + } + +@@ -1124,7 +1122,7 @@ static int prestera_switchdev_blk_event(struct notifier_block *unused, + prestera_port_obj_attr_set); + break; + default: +- err = -EOPNOTSUPP; ++ return NOTIFY_DONE; + } + + return notifier_from_errno(err); +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 398c23cec8151..ee1fd472e9252 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -91,46 +91,53 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth) + } + + dev_err(eth->dev, "mdio: MDIO timeout\n"); +- return -1; ++ return -ETIMEDOUT; + } + +-static u32 _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, +- u32 phy_register, u32 write_data) ++static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg, ++ u32 write_data) + { +- if (mtk_mdio_busy_wait(eth)) +- return -1; ++ int ret; + +- write_data &= 0xffff; ++ ret = mtk_mdio_busy_wait(eth); ++ if (ret < 0) ++ return ret; + +- mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_WRITE | +- (phy_register << PHY_IAC_REG_SHIFT) | +- (phy_addr << PHY_IAC_ADDR_SHIFT) | write_data, ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C22 | ++ PHY_IAC_CMD_WRITE | ++ PHY_IAC_REG(phy_reg) | ++ PHY_IAC_ADDR(phy_addr) | ++ PHY_IAC_DATA(write_data), + MTK_PHY_IAC); + +- if (mtk_mdio_busy_wait(eth)) +- return -1; ++ ret = mtk_mdio_busy_wait(eth); ++ if (ret < 0) ++ return ret; + + return 0; + } + +-static u32 _mtk_mdio_read(struct mtk_eth *eth, int phy_addr, int phy_reg) ++static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg) + { +- u32 d; ++ int ret; + +- if (mtk_mdio_busy_wait(eth)) +- return 0xffff; ++ ret = mtk_mdio_busy_wait(eth); ++ if (ret < 0) ++ return ret; + +- mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_READ | +- (phy_reg << PHY_IAC_REG_SHIFT) | +- (phy_addr << PHY_IAC_ADDR_SHIFT), ++ mtk_w32(eth, PHY_IAC_ACCESS | ++ PHY_IAC_START_C22 | ++ PHY_IAC_CMD_C22_READ | ++ PHY_IAC_REG(phy_reg) | ++ PHY_IAC_ADDR(phy_addr), + MTK_PHY_IAC); + +- if (mtk_mdio_busy_wait(eth)) +- return 0xffff; +- +- d = mtk_r32(eth, MTK_PHY_IAC) & 0xffff; ++ ret = mtk_mdio_busy_wait(eth); ++ if (ret < 0) ++ return ret; + +- return d; ++ return mtk_r32(eth, MTK_PHY_IAC) & PHY_IAC_DATA_MASK; + } + + static int mtk_mdio_write(struct mii_bus *bus, int phy_addr, +@@ -217,7 +224,7 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, + phylink_config); + struct mtk_eth *eth = mac->hw; + u32 mcr_cur, mcr_new, sid, i; +- int val, ge_mode, err; ++ int val, ge_mode, err = 0; + + /* MT76x8 has no hardware settings between for the MAC */ + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 5ef70dd8b49c6..f2d90639d7ed1 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -341,11 +341,17 @@ + /* PHY Indirect Access Control registers */ + #define MTK_PHY_IAC 0x10004 + #define PHY_IAC_ACCESS BIT(31) +-#define PHY_IAC_READ BIT(19) +-#define PHY_IAC_WRITE BIT(18) +-#define PHY_IAC_START BIT(16) +-#define PHY_IAC_ADDR_SHIFT 20 +-#define PHY_IAC_REG_SHIFT 25 ++#define PHY_IAC_REG_MASK GENMASK(29, 25) ++#define PHY_IAC_REG(x) FIELD_PREP(PHY_IAC_REG_MASK, (x)) ++#define PHY_IAC_ADDR_MASK GENMASK(24, 20) ++#define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x)) ++#define PHY_IAC_CMD_MASK GENMASK(19, 18) ++#define PHY_IAC_CMD_WRITE FIELD_PREP(PHY_IAC_CMD_MASK, 1) ++#define PHY_IAC_CMD_C22_READ FIELD_PREP(PHY_IAC_CMD_MASK, 2) ++#define PHY_IAC_START_MASK GENMASK(17, 16) ++#define PHY_IAC_START_C22 FIELD_PREP(PHY_IAC_START_MASK, 1) ++#define PHY_IAC_DATA_MASK GENMASK(15, 0) ++#define PHY_IAC_DATA(x) FIELD_PREP(PHY_IAC_DATA_MASK, (x)) + #define PHY_IAC_TIMEOUT HZ + + #define MTK_MAC_MISC 0x1000c +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +index ef518b1040f72..fde521b1eecad 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +@@ -663,7 +663,7 @@ void __init mlx4_en_init_ptys2ethtool_map(void) + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_T, SPEED_1000, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT); + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_CX_SGMII, SPEED_1000, +- ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); ++ ETHTOOL_LINK_MODE_1000baseX_Full_BIT); + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_KX, SPEED_1000, + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_T, SPEED_10000, +@@ -675,9 +675,9 @@ void __init mlx4_en_init_ptys2ethtool_map(void) + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KR, SPEED_10000, + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CR, SPEED_10000, +- ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); ++ ETHTOOL_LINK_MODE_10000baseCR_Full_BIT); + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_SR, SPEED_10000, +- ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); ++ ETHTOOL_LINK_MODE_10000baseSR_Full_BIT); + MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_20GBASE_KR2, SPEED_20000, + ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT, + ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +index 8af7f28273225..3bd3603873e32 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +@@ -2286,9 +2286,14 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, + bool carry_xdp_prog) + { + struct bpf_prog *xdp_prog; +- int i, t; ++ int i, t, ret; + +- mlx4_en_copy_priv(tmp, priv, prof); ++ ret = mlx4_en_copy_priv(tmp, priv, prof); ++ if (ret) { ++ en_warn(priv, "%s: mlx4_en_copy_priv() failed, return\n", ++ __func__); ++ return ret; ++ } + + if (mlx4_en_alloc_resources(tmp)) { + en_warn(priv, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index db5dfff585c99..00f63fbfe9b48 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -147,8 +147,12 @@ static void cmd_ent_put(struct mlx5_cmd_work_ent *ent) + if (!refcount_dec_and_test(&ent->refcnt)) + return; + +- if (ent->idx >= 0) +- cmd_free_index(ent->cmd, ent->idx); ++ if (ent->idx >= 0) { ++ struct mlx5_cmd *cmd = ent->cmd; ++ ++ cmd_free_index(cmd, ent->idx); ++ up(ent->page_queue ? &cmd->pages_sem : &cmd->sem); ++ } + + cmd_free_ent(ent); + } +@@ -334,6 +338,9 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, + case MLX5_CMD_OP_PAGE_FAULT_RESUME: + case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS: + case MLX5_CMD_OP_DEALLOC_SF: ++ case MLX5_CMD_OP_DESTROY_UCTX: ++ case MLX5_CMD_OP_DESTROY_UMEM: ++ case MLX5_CMD_OP_MODIFY_RQT: + return MLX5_CMD_STAT_OK; + + case MLX5_CMD_OP_QUERY_HCA_CAP: +@@ -439,7 +446,6 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, + case MLX5_CMD_OP_MODIFY_TIS: + case MLX5_CMD_OP_QUERY_TIS: + case MLX5_CMD_OP_CREATE_RQT: +- case MLX5_CMD_OP_MODIFY_RQT: + case MLX5_CMD_OP_QUERY_RQT: + + case MLX5_CMD_OP_CREATE_FLOW_TABLE: +@@ -459,9 +465,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, + case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT: + case MLX5_CMD_OP_QUERY_GENERAL_OBJECT: + case MLX5_CMD_OP_CREATE_UCTX: +- case MLX5_CMD_OP_DESTROY_UCTX: + case MLX5_CMD_OP_CREATE_UMEM: +- case MLX5_CMD_OP_DESTROY_UMEM: + case MLX5_CMD_OP_ALLOC_MEMIC: + case MLX5_CMD_OP_MODIFY_XRQ: + case MLX5_CMD_OP_RELEASE_XRQ_ERROR: +@@ -895,25 +899,6 @@ static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode) + return cmd->allowed_opcode == opcode; + } + +-static int cmd_alloc_index_retry(struct mlx5_cmd *cmd) +-{ +- unsigned long alloc_end = jiffies + msecs_to_jiffies(1000); +- int idx; +- +-retry: +- idx = cmd_alloc_index(cmd); +- if (idx < 0 && time_before(jiffies, alloc_end)) { +- /* Index allocation can fail on heavy load of commands. This is a temporary +- * situation as the current command already holds the semaphore, meaning that +- * another command completion is being handled and it is expected to release +- * the entry index soon. +- */ +- cpu_relax(); +- goto retry; +- } +- return idx; +-} +- + bool mlx5_cmd_is_down(struct mlx5_core_dev *dev) + { + return pci_channel_offline(dev->pdev) || +@@ -938,7 +923,7 @@ static void cmd_work_handler(struct work_struct *work) + sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; + down(sem); + if (!ent->page_queue) { +- alloc_ret = cmd_alloc_index_retry(cmd); ++ alloc_ret = cmd_alloc_index(cmd); + if (alloc_ret < 0) { + mlx5_core_err_rl(dev, "failed to allocate command entry\n"); + if (ent->callback) { +@@ -1594,8 +1579,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force + vector = vec & 0xffffffff; + for (i = 0; i < (1 << cmd->log_sz); i++) { + if (test_bit(i, &vector)) { +- struct semaphore *sem; +- + ent = cmd->ent_arr[i]; + + /* if we already completed the command, ignore it */ +@@ -1618,10 +1601,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force + dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) + cmd_ent_put(ent); + +- if (ent->page_queue) +- sem = &cmd->pages_sem; +- else +- sem = &cmd->sem; + ent->ts2 = ktime_get_ns(); + memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out)); + dump_command(dev, ent, 0); +@@ -1675,7 +1654,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force + */ + complete(&ent->done); + } +- up(sem); + } + } + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +index 02e77ffe5c3e4..5371ad0a12eb5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +@@ -164,13 +164,14 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) + MLX5_SET(destroy_cq_in, in, cqn, cq->cqn); + MLX5_SET(destroy_cq_in, in, uid, cq->uid); + err = mlx5_cmd_exec_in(dev, destroy_cq, in); ++ if (err) ++ return err; + + synchronize_irq(cq->irqn); +- + mlx5_cq_put(cq); + wait_for_completion(&cq->free); + +- return err; ++ return 0; + } + EXPORT_SYMBOL(mlx5_core_destroy_cq); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +index 07c8d9811bc81..10d195042ab55 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +@@ -507,6 +507,8 @@ void mlx5_debug_cq_remove(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) + if (!mlx5_debugfs_root) + return; + +- if (cq->dbg) ++ if (cq->dbg) { + rem_res_tree(cq->dbg); ++ cq->dbg = NULL; ++ } + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index dcf9f27ba2efd..d7576b6fa43b7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -625,7 +625,6 @@ static int mlx5_devlink_eth_param_register(struct devlink *devlink) + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, + value); +- devlink_param_publish(devlink, &enable_eth_param); + return 0; + } + +@@ -636,7 +635,6 @@ static void mlx5_devlink_eth_param_unregister(struct devlink *devlink) + if (!mlx5_eth_supported(dev)) + return; + +- devlink_param_unpublish(devlink, &enable_eth_param); + devlink_param_unregister(devlink, &enable_eth_param); + } + +@@ -672,7 +670,6 @@ static int mlx5_devlink_rdma_param_register(struct devlink *devlink) + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, + value); +- devlink_param_publish(devlink, &enable_rdma_param); + return 0; + } + +@@ -681,7 +678,6 @@ static void mlx5_devlink_rdma_param_unregister(struct devlink *devlink) + if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND)) + return; + +- devlink_param_unpublish(devlink, &enable_rdma_param); + devlink_param_unregister(devlink, &enable_rdma_param); + } + +@@ -706,7 +702,6 @@ static int mlx5_devlink_vnet_param_register(struct devlink *devlink) + devlink_param_driverinit_value_set(devlink, + DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, + value); +- devlink_param_publish(devlink, &enable_rdma_param); + return 0; + } + +@@ -717,7 +712,6 @@ static void mlx5_devlink_vnet_param_unregister(struct devlink *devlink) + if (!mlx5_vnet_supported(dev)) + return; + +- devlink_param_unpublish(devlink, &enable_vnet_param); + devlink_param_unregister(devlink, &enable_vnet_param); + } + +@@ -799,16 +793,12 @@ int mlx5_devlink_register(struct devlink *devlink) + { + int err; + +- err = devlink_register(devlink); +- if (err) +- return err; +- + err = devlink_params_register(devlink, mlx5_devlink_params, + ARRAY_SIZE(mlx5_devlink_params)); + if (err) +- goto params_reg_err; ++ return err; ++ + mlx5_devlink_set_params_init_values(devlink); +- devlink_params_publish(devlink); + + err = mlx5_devlink_auxdev_params_register(devlink); + if (err) +@@ -825,8 +815,6 @@ traps_reg_err: + auxdev_reg_err: + devlink_params_unregister(devlink, mlx5_devlink_params, + ARRAY_SIZE(mlx5_devlink_params)); +-params_reg_err: +- devlink_unregister(devlink); + return err; + } + +@@ -834,8 +822,6 @@ void mlx5_devlink_unregister(struct devlink *devlink) + { + mlx5_devlink_traps_unregister(devlink); + mlx5_devlink_auxdev_params_unregister(devlink); +- devlink_params_unpublish(devlink); + devlink_params_unregister(devlink, mlx5_devlink_params, + ARRAY_SIZE(mlx5_devlink_params)); +- devlink_unregister(devlink); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 03a7a4ce5cd5e..7204bc86e4741 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -244,6 +244,17 @@ enum mlx5e_priv_flag { + + #define MLX5E_GET_PFLAG(params, pflag) (!!((params)->pflags & (BIT(pflag)))) + ++enum packet_merge { ++ MLX5E_PACKET_MERGE_NONE, ++ MLX5E_PACKET_MERGE_LRO, ++ MLX5E_PACKET_MERGE_SHAMPO, ++}; ++ ++struct mlx5e_packet_merge_param { ++ enum packet_merge type; ++ u32 timeout; ++}; ++ + struct mlx5e_params { + u8 log_sq_size; + u8 rq_wq_type; +@@ -258,13 +269,12 @@ struct mlx5e_params { + bool tunneled_offload_en; + struct dim_cq_moder rx_cq_moderation; + struct dim_cq_moder tx_cq_moderation; +- bool lro_en; ++ struct mlx5e_packet_merge_param packet_merge; + u8 tx_min_inline_mode; + bool vlan_strip_disable; + bool scatter_fcs_en; + bool rx_dim_enabled; + bool tx_dim_enabled; +- u32 lro_timeout; + u32 pflags; + struct bpf_prog *xdp_prog; + struct mlx5e_xsk *xsk; +@@ -717,6 +727,8 @@ struct mlx5e_channel { + DECLARE_BITMAP(state, MLX5E_CHANNEL_NUM_STATES); + int ix; + int cpu; ++ /* Sync between icosq recovery and XSK enable/disable. */ ++ struct mutex icosq_recovery_lock; + }; + + struct mlx5e_ptp; +@@ -944,9 +956,6 @@ int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param); + void mlx5e_destroy_rq(struct mlx5e_rq *rq); + + struct mlx5e_sq_param; +-int mlx5e_open_icosq(struct mlx5e_channel *c, struct mlx5e_params *params, +- struct mlx5e_sq_param *param, struct mlx5e_icosq *sq); +-void mlx5e_close_icosq(struct mlx5e_icosq *sq); + int mlx5e_open_xdpsq(struct mlx5e_channel *c, struct mlx5e_params *params, + struct mlx5e_sq_param *param, struct xsk_buff_pool *xsk_pool, + struct mlx5e_xdpsq *sq, bool is_redirect); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/health.h b/drivers/net/ethernet/mellanox/mlx5/core/en/health.h +index 018262d0164b3..3aaf3c2752feb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/health.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/health.h +@@ -30,6 +30,8 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv); + void mlx5e_reporter_icosq_cqe_err(struct mlx5e_icosq *icosq); + void mlx5e_reporter_rq_cqe_err(struct mlx5e_rq *rq); + void mlx5e_reporter_rx_timeout(struct mlx5e_rq *rq); ++void mlx5e_reporter_icosq_suspend_recovery(struct mlx5e_channel *c); ++void mlx5e_reporter_icosq_resume_recovery(struct mlx5e_channel *c); + + #define MLX5E_REPORTER_PER_Q_MAX_LEN 256 + #define MLX5E_REPORTER_FLUSH_TIMEOUT_MSEC 2000 +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 3cbb596821e89..15f441a1b80c2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -87,7 +87,8 @@ bool mlx5e_rx_is_linear_skb(struct mlx5e_params *params, + u32 linear_frag_sz = max(mlx5e_rx_get_linear_frag_sz(params, xsk), + mlx5e_rx_get_linear_frag_sz(params, NULL)); + +- return !params->lro_en && linear_frag_sz <= PAGE_SIZE; ++ return params->packet_merge.type == MLX5E_PACKET_MERGE_NONE && ++ linear_frag_sz <= PAGE_SIZE; + } + + bool mlx5e_verify_rx_mpwqe_strides(struct mlx5_core_dev *mdev, +@@ -164,19 +165,8 @@ u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev, + mlx5e_rx_is_linear_skb(params, xsk) : + mlx5e_rx_mpwqe_is_linear_skb(mdev, params, xsk); + +- return is_linear_skb ? mlx5e_get_linear_rq_headroom(params, xsk) : 0; +-} +- +-struct mlx5e_lro_param mlx5e_get_lro_param(struct mlx5e_params *params) +-{ +- struct mlx5e_lro_param lro_param; +- +- lro_param = (struct mlx5e_lro_param) { +- .enabled = params->lro_en, +- .timeout = params->lro_timeout, +- }; +- +- return lro_param; ++ return is_linear_skb || params->packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO ? ++ mlx5e_get_linear_rq_headroom(params, xsk) : 0; + } + + u16 mlx5e_calc_sq_stop_room(struct mlx5_core_dev *mdev, struct mlx5e_params *params) +@@ -485,10 +475,11 @@ static void mlx5e_build_rx_cq_param(struct mlx5_core_dev *mdev, + + static u8 rq_end_pad_mode(struct mlx5_core_dev *mdev, struct mlx5e_params *params) + { ++ bool lro_en = params->packet_merge.type == MLX5E_PACKET_MERGE_LRO; + bool ro = pcie_relaxed_ordering_enabled(mdev->pdev) && + MLX5_CAP_GEN(mdev, relaxed_ordering_write); + +- return ro && params->lro_en ? ++ return ro && lro_en ? + MLX5_WQ_END_PAD_MODE_NONE : MLX5_WQ_END_PAD_MODE_ALIGN; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +index 879ad46d754e1..e9593f5f06610 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.h +@@ -11,11 +11,6 @@ struct mlx5e_xsk_param { + u16 chunk_size; + }; + +-struct mlx5e_lro_param { +- bool enabled; +- u32 timeout; +-}; +- + struct mlx5e_cq_param { + u32 cqc[MLX5_ST_SZ_DW(cqc)]; + struct mlx5_wq_param wq; +@@ -125,7 +120,6 @@ u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev, + u16 mlx5e_get_rq_headroom(struct mlx5_core_dev *mdev, + struct mlx5e_params *params, + struct mlx5e_xsk_param *xsk); +-struct mlx5e_lro_param mlx5e_get_lro_param(struct mlx5e_params *params); + + /* Build queue parameters */ + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +index e8a8d78e3e4d5..965838893432d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +@@ -553,7 +553,8 @@ static int mlx5e_htb_convert_rate(struct mlx5e_priv *priv, u64 rate, + + static void mlx5e_htb_convert_ceil(struct mlx5e_priv *priv, u64 ceil, u32 *max_average_bw) + { +- *max_average_bw = div_u64(ceil, BYTES_IN_MBIT); ++ /* Hardware treats 0 as "unlimited", set at least 1. */ ++ *max_average_bw = max_t(u32, div_u64(ceil, BYTES_IN_MBIT), 1); + + qos_dbg(priv->mdev, "Convert: ceil %llu -> max_average_bw %u\n", + ceil, *max_average_bw); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c +index 9c076aa20306a..b6f5c1bcdbcd4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c +@@ -183,18 +183,7 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw, + + static bool mlx5e_rep_is_lag_netdev(struct net_device *netdev) + { +- struct mlx5e_rep_priv *rpriv; +- struct mlx5e_priv *priv; +- +- /* A given netdev is not a representor or not a slave of LAG configuration */ +- if (!mlx5e_eswitch_rep(netdev) || !netif_is_lag_port(netdev)) +- return false; +- +- priv = netdev_priv(netdev); +- rpriv = priv->ppriv; +- +- /* Egress acl forward to vport is supported only non-uplink representor */ +- return rpriv->rep->vport != MLX5_VPORT_UPLINK; ++ return netif_is_lag_port(netdev) && mlx5e_eswitch_vf_rep(netdev); + } + + static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *ptr) +@@ -210,9 +199,6 @@ static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *pt + u16 fwd_vport_num; + int err; + +- if (!mlx5e_rep_is_lag_netdev(netdev)) +- return; +- + info = ptr; + lag_info = info->lower_state_info; + /* This is not an event of a representor becoming active slave */ +@@ -266,9 +252,6 @@ static void mlx5e_rep_changeupper_event(struct net_device *netdev, void *ptr) + struct net_device *lag_dev; + struct mlx5e_priv *priv; + +- if (!mlx5e_rep_is_lag_netdev(netdev)) +- return; +- + priv = netdev_priv(netdev); + rpriv = priv->ppriv; + lag_dev = info->upper_dev; +@@ -293,6 +276,19 @@ static int mlx5e_rep_esw_bond_netevent(struct notifier_block *nb, + unsigned long event, void *ptr) + { + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); ++ struct mlx5e_rep_priv *rpriv; ++ struct mlx5e_rep_bond *bond; ++ struct mlx5e_priv *priv; ++ ++ if (!mlx5e_rep_is_lag_netdev(netdev)) ++ return NOTIFY_DONE; ++ ++ bond = container_of(nb, struct mlx5e_rep_bond, nb); ++ priv = netdev_priv(netdev); ++ rpriv = mlx5_eswitch_get_uplink_priv(priv->mdev->priv.eswitch, REP_ETH); ++ /* Verify VF representor is on the same device of the bond handling the netevent. */ ++ if (rpriv->uplink_priv.bond != bond) ++ return NOTIFY_DONE; + + switch (event) { + case NETDEV_CHANGELOWERSTATE: +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +index c6d2f8c78db71..48dc121b2cb4c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c +@@ -491,7 +491,7 @@ void mlx5e_rep_bridge_init(struct mlx5e_priv *priv) + } + + br_offloads->netdev_nb.notifier_call = mlx5_esw_bridge_switchdev_port_event; +- err = register_netdevice_notifier(&br_offloads->netdev_nb); ++ err = register_netdevice_notifier_net(&init_net, &br_offloads->netdev_nb); + if (err) { + esw_warn(mdev, "Failed to register bridge offloads netdevice notifier (err=%d)\n", + err); +@@ -509,7 +509,9 @@ err_register_swdev_blk: + err_register_swdev: + destroy_workqueue(br_offloads->wq); + err_alloc_wq: ++ rtnl_lock(); + mlx5_esw_bridge_cleanup(esw); ++ rtnl_unlock(); + } + + void mlx5e_rep_bridge_cleanup(struct mlx5e_priv *priv) +@@ -524,7 +526,7 @@ void mlx5e_rep_bridge_cleanup(struct mlx5e_priv *priv) + return; + + cancel_delayed_work_sync(&br_offloads->update_work); +- unregister_netdevice_notifier(&br_offloads->netdev_nb); ++ unregister_netdevice_notifier_net(&init_net, &br_offloads->netdev_nb); + unregister_switchdev_blocking_notifier(&br_offloads->nb_blk); + unregister_switchdev_notifier(&br_offloads->nb); + destroy_workqueue(br_offloads->wq); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c +index de03684528bbf..8451940c16ab9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c +@@ -647,9 +647,7 @@ static void mlx5e_restore_skb_sample(struct mlx5e_priv *priv, struct sk_buff *sk + "Failed to restore tunnel info for sampled packet\n"); + return; + } +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) + mlx5e_tc_sample_skb(skb, mapped_obj); +-#endif /* CONFIG_MLX5_TC_SAMPLE */ + mlx5_rep_tc_post_napi_receive(tc_priv); + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c +index 0eb125316fe20..e329158fdc555 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c +@@ -59,6 +59,7 @@ static void mlx5e_reset_icosq_cc_pc(struct mlx5e_icosq *icosq) + + static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx) + { ++ struct mlx5e_rq *xskrq = NULL; + struct mlx5_core_dev *mdev; + struct mlx5e_icosq *icosq; + struct net_device *dev; +@@ -67,7 +68,13 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx) + int err; + + icosq = ctx; ++ ++ mutex_lock(&icosq->channel->icosq_recovery_lock); ++ ++ /* mlx5e_close_rq cancels this work before RQ and ICOSQ are killed. */ + rq = &icosq->channel->rq; ++ if (test_bit(MLX5E_RQ_STATE_ENABLED, &icosq->channel->xskrq.state)) ++ xskrq = &icosq->channel->xskrq; + mdev = icosq->channel->mdev; + dev = icosq->channel->netdev; + err = mlx5_core_query_sq_state(mdev, icosq->sqn, &state); +@@ -81,6 +88,9 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx) + goto out; + + mlx5e_deactivate_rq(rq); ++ if (xskrq) ++ mlx5e_deactivate_rq(xskrq); ++ + err = mlx5e_wait_for_icosq_flush(icosq); + if (err) + goto out; +@@ -94,15 +104,28 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx) + goto out; + + mlx5e_reset_icosq_cc_pc(icosq); ++ + mlx5e_free_rx_in_progress_descs(rq); ++ if (xskrq) ++ mlx5e_free_rx_in_progress_descs(xskrq); ++ + clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state); + mlx5e_activate_icosq(icosq); +- mlx5e_activate_rq(rq); + ++ mlx5e_activate_rq(rq); + rq->stats->recover++; ++ ++ if (xskrq) { ++ mlx5e_activate_rq(xskrq); ++ xskrq->stats->recover++; ++ } ++ ++ mutex_unlock(&icosq->channel->icosq_recovery_lock); ++ + return 0; + out: + clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state); ++ mutex_unlock(&icosq->channel->icosq_recovery_lock); + return err; + } + +@@ -703,6 +726,16 @@ void mlx5e_reporter_icosq_cqe_err(struct mlx5e_icosq *icosq) + mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx); + } + ++void mlx5e_reporter_icosq_suspend_recovery(struct mlx5e_channel *c) ++{ ++ mutex_lock(&c->icosq_recovery_lock); ++} ++ ++void mlx5e_reporter_icosq_resume_recovery(struct mlx5e_channel *c) ++{ ++ mutex_unlock(&c->icosq_recovery_lock); ++} ++ + static const struct devlink_health_reporter_ops mlx5_rx_reporter_ops = { + .name = "rx", + .recover = mlx5e_rx_reporter_recover, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +index bb682fd751c98..8024599994642 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +@@ -463,6 +463,14 @@ static int mlx5e_tx_reporter_dump_sq(struct mlx5e_priv *priv, struct devlink_fms + return mlx5e_health_fmsg_named_obj_nest_end(fmsg); + } + ++static int mlx5e_tx_reporter_timeout_dump(struct mlx5e_priv *priv, struct devlink_fmsg *fmsg, ++ void *ctx) ++{ ++ struct mlx5e_tx_timeout_ctx *to_ctx = ctx; ++ ++ return mlx5e_tx_reporter_dump_sq(priv, fmsg, to_ctx->sq); ++} ++ + static int mlx5e_tx_reporter_dump_all_sqs(struct mlx5e_priv *priv, + struct devlink_fmsg *fmsg) + { +@@ -558,7 +566,7 @@ int mlx5e_reporter_tx_timeout(struct mlx5e_txqsq *sq) + to_ctx.sq = sq; + err_ctx.ctx = &to_ctx; + err_ctx.recover = mlx5e_tx_reporter_timeout_recover; +- err_ctx.dump = mlx5e_tx_reporter_dump_sq; ++ err_ctx.dump = mlx5e_tx_reporter_timeout_dump; + snprintf(err_str, sizeof(err_str), + "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u", + sq->ch_ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c +index 625cd49ef96c5..7b55b14d47ef7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c +@@ -127,7 +127,7 @@ mlx5e_rss_get_tt_config(struct mlx5e_rss *rss, enum mlx5_traffic_types tt) + + static int mlx5e_rss_create_tir(struct mlx5e_rss *rss, + enum mlx5_traffic_types tt, +- const struct mlx5e_lro_param *init_lro_param, ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param, + bool inner) + { + struct mlx5e_rss_params_traffic_type rss_tt; +@@ -161,7 +161,7 @@ static int mlx5e_rss_create_tir(struct mlx5e_rss *rss, + rqtn = mlx5e_rqt_get_rqtn(&rss->rqt); + mlx5e_tir_builder_build_rqt(builder, rss->mdev->mlx5e_res.hw_objs.td.tdn, + rqtn, rss->inner_ft_support); +- mlx5e_tir_builder_build_lro(builder, init_lro_param); ++ mlx5e_tir_builder_build_packet_merge(builder, init_pkt_merge_param); + rss_tt = mlx5e_rss_get_tt_config(rss, tt); + mlx5e_tir_builder_build_rss(builder, &rss->hash, &rss_tt, inner); + +@@ -198,14 +198,14 @@ static void mlx5e_rss_destroy_tir(struct mlx5e_rss *rss, enum mlx5_traffic_types + } + + static int mlx5e_rss_create_tirs(struct mlx5e_rss *rss, +- const struct mlx5e_lro_param *init_lro_param, ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param, + bool inner) + { + enum mlx5_traffic_types tt, max_tt; + int err; + + for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { +- err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner); ++ err = mlx5e_rss_create_tir(rss, tt, init_pkt_merge_param, inner); + if (err) + goto err_destroy_tirs; + } +@@ -297,7 +297,7 @@ int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, + + int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, + bool inner_ft_support, u32 drop_rqn, +- const struct mlx5e_lro_param *init_lro_param) ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param) + { + int err; + +@@ -305,12 +305,12 @@ int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, + if (err) + goto err_out; + +- err = mlx5e_rss_create_tirs(rss, init_lro_param, false); ++ err = mlx5e_rss_create_tirs(rss, init_pkt_merge_param, false); + if (err) + goto err_destroy_rqt; + + if (inner_ft_support) { +- err = mlx5e_rss_create_tirs(rss, init_lro_param, true); ++ err = mlx5e_rss_create_tirs(rss, init_pkt_merge_param, true); + if (err) + goto err_destroy_tirs; + } +@@ -372,7 +372,7 @@ u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, + */ + int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss, + enum mlx5_traffic_types tt, +- const struct mlx5e_lro_param *init_lro_param, ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param, + bool inner, u32 *tirn) + { + struct mlx5e_tir *tir; +@@ -381,7 +381,7 @@ int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss, + if (!tir) { /* TIR doesn't exist, create one */ + int err; + +- err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner); ++ err = mlx5e_rss_create_tir(rss, tt, init_pkt_merge_param, inner); + if (err) + return err; + tir = rss_get_tir(rss, tt, inner); +@@ -418,7 +418,8 @@ void mlx5e_rss_disable(struct mlx5e_rss *rss) + mlx5e_rqt_get_rqtn(&rss->rqt), rss->drop_rqn, err); + } + +-int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_param) ++int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss, ++ struct mlx5e_packet_merge_param *pkt_merge_param) + { + struct mlx5e_tir_builder *builder; + enum mlx5_traffic_types tt; +@@ -428,7 +429,7 @@ int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_p + if (!builder) + return -ENOMEM; + +- mlx5e_tir_builder_build_lro(builder, lro_param); ++ mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param); + + final_err = 0; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h +index d522a10dadf33..c6b2164163440 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h +@@ -17,7 +17,7 @@ struct mlx5e_rss *mlx5e_rss_alloc(void); + void mlx5e_rss_free(struct mlx5e_rss *rss); + int mlx5e_rss_init(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, + bool inner_ft_support, u32 drop_rqn, +- const struct mlx5e_lro_param *init_lro_param); ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param); + int mlx5e_rss_init_no_tirs(struct mlx5e_rss *rss, struct mlx5_core_dev *mdev, + bool inner_ft_support, u32 drop_rqn); + int mlx5e_rss_cleanup(struct mlx5e_rss *rss); +@@ -30,13 +30,14 @@ u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, + bool inner); + int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss, + enum mlx5_traffic_types tt, +- const struct mlx5e_lro_param *init_lro_param, ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param, + bool inner, u32 *tirn); + + void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns); + void mlx5e_rss_disable(struct mlx5e_rss *rss); + +-int mlx5e_rss_lro_set_param(struct mlx5e_rss *rss, struct mlx5e_lro_param *lro_param); ++int mlx5e_rss_packet_merge_set_param(struct mlx5e_rss *rss, ++ struct mlx5e_packet_merge_param *pkt_merge_param); + int mlx5e_rss_get_rxfh(struct mlx5e_rss *rss, u32 *indir, u8 *key, u8 *hfunc); + int mlx5e_rss_set_rxfh(struct mlx5e_rss *rss, const u32 *indir, + const u8 *key, const u8 *hfunc, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c +index 13056cb9757d4..0015a81eb9a17 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c +@@ -13,6 +13,9 @@ struct mlx5e_rx_res { + unsigned int max_nch; + u32 drop_rqn; + ++ struct mlx5e_packet_merge_param pkt_merge_param; ++ struct rw_semaphore pkt_merge_param_sem; ++ + struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS]; + bool rss_active; + u32 rss_rqns[MLX5E_INDIR_RQT_SIZE]; +@@ -34,7 +37,7 @@ struct mlx5e_rx_res { + /* API for rx_res_rss_* */ + + static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res, +- const struct mlx5e_lro_param *init_lro_param, ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param, + unsigned int init_nch) + { + bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; +@@ -49,7 +52,7 @@ static int mlx5e_rx_res_rss_init_def(struct mlx5e_rx_res *res, + return -ENOMEM; + + err = mlx5e_rss_init(rss, res->mdev, inner_ft_support, res->drop_rqn, +- init_lro_param); ++ init_pkt_merge_param); + if (err) + goto err_rss_free; + +@@ -275,7 +278,7 @@ struct mlx5e_rx_res *mlx5e_rx_res_alloc(void) + } + + static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, +- const struct mlx5e_lro_param *init_lro_param) ++ const struct mlx5e_packet_merge_param *init_pkt_merge_param) + { + bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; + struct mlx5e_tir_builder *builder; +@@ -306,7 +309,7 @@ static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, + mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, + mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), + inner_ft_support); +- mlx5e_tir_builder_build_lro(builder, init_lro_param); ++ mlx5e_tir_builder_build_packet_merge(builder, init_pkt_merge_param); + mlx5e_tir_builder_build_direct(builder); + + err = mlx5e_tir_init(&res->channels[ix].direct_tir, builder, res->mdev, true); +@@ -336,7 +339,7 @@ static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, + mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, + mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), + inner_ft_support); +- mlx5e_tir_builder_build_lro(builder, init_lro_param); ++ mlx5e_tir_builder_build_packet_merge(builder, init_pkt_merge_param); + mlx5e_tir_builder_build_direct(builder); + + err = mlx5e_tir_init(&res->channels[ix].xsk_tir, builder, res->mdev, true); +@@ -392,6 +395,7 @@ static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res) + if (err) + goto out; + ++ /* Separated from the channels RQs, does not share pkt_merge state with them */ + mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, + mlx5e_rqt_get_rqtn(&res->ptp.rqt), + inner_ft_support); +@@ -437,7 +441,7 @@ static void mlx5e_rx_res_ptp_destroy(struct mlx5e_rx_res *res) + + int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, + enum mlx5e_rx_res_features features, unsigned int max_nch, +- u32 drop_rqn, const struct mlx5e_lro_param *init_lro_param, ++ u32 drop_rqn, const struct mlx5e_packet_merge_param *init_pkt_merge_param, + unsigned int init_nch) + { + int err; +@@ -447,11 +451,14 @@ int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, + res->max_nch = max_nch; + res->drop_rqn = drop_rqn; + +- err = mlx5e_rx_res_rss_init_def(res, init_lro_param, init_nch); ++ res->pkt_merge_param = *init_pkt_merge_param; ++ init_rwsem(&res->pkt_merge_param_sem); ++ ++ err = mlx5e_rx_res_rss_init_def(res, init_pkt_merge_param, init_nch); + if (err) + goto err_out; + +- err = mlx5e_rx_res_channels_init(res, init_lro_param); ++ err = mlx5e_rx_res_channels_init(res, init_pkt_merge_param); + if (err) + goto err_rss_destroy; + +@@ -513,7 +520,7 @@ u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res) + return mlx5e_tir_get_tirn(&res->ptp.tir); + } + +-u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) ++static u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) + { + return mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt); + } +@@ -645,7 +652,8 @@ int mlx5e_rx_res_xsk_deactivate(struct mlx5e_rx_res *res, unsigned int ix) + return err; + } + +-int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param *lro_param) ++int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, ++ struct mlx5e_packet_merge_param *pkt_merge_param) + { + struct mlx5e_tir_builder *builder; + int err, final_err; +@@ -655,7 +663,10 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param + if (!builder) + return -ENOMEM; + +- mlx5e_tir_builder_build_lro(builder, lro_param); ++ down_write(&res->pkt_merge_param_sem); ++ res->pkt_merge_param = *pkt_merge_param; ++ ++ mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param); + + final_err = 0; + +@@ -665,7 +676,7 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param + if (!rss) + continue; + +- err = mlx5e_rss_lro_set_param(rss, lro_param); ++ err = mlx5e_rss_packet_merge_set_param(rss, pkt_merge_param); + if (err) + final_err = final_err ? : err; + } +@@ -673,13 +684,14 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param + for (ix = 0; ix < res->max_nch; ix++) { + err = mlx5e_tir_modify(&res->channels[ix].direct_tir, builder); + if (err) { +- mlx5_core_warn(res->mdev, "Failed to update LRO state of direct TIR %#x for channel %u: err = %d\n", ++ mlx5_core_warn(res->mdev, "Failed to update packet merge state of direct TIR %#x for channel %u: err = %d\n", + mlx5e_tir_get_tirn(&res->channels[ix].direct_tir), ix, err); + if (!final_err) + final_err = err; + } + } + ++ up_write(&res->pkt_merge_param_sem); + mlx5e_tir_builder_free(builder); + return final_err; + } +@@ -688,3 +700,31 @@ struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res * + { + return mlx5e_rss_get_hash(res->rss[0]); + } ++ ++int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, ++ struct mlx5e_tir *tir) ++{ ++ bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; ++ struct mlx5e_tir_builder *builder; ++ u32 rqtn; ++ int err; ++ ++ builder = mlx5e_tir_builder_alloc(false); ++ if (!builder) ++ return -ENOMEM; ++ ++ rqtn = mlx5e_rx_res_get_rqtn_direct(res, rxq); ++ ++ mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, rqtn, ++ inner_ft_support); ++ mlx5e_tir_builder_build_direct(builder); ++ mlx5e_tir_builder_build_tls(builder); ++ down_read(&res->pkt_merge_param_sem); ++ mlx5e_tir_builder_build_packet_merge(builder, &res->pkt_merge_param); ++ err = mlx5e_tir_init(tir, builder, res->mdev, false); ++ up_read(&res->pkt_merge_param_sem); ++ ++ mlx5e_tir_builder_free(builder); ++ ++ return err; ++} +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h +index 4a15942d79f7d..b39b20a720e0f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h +@@ -25,7 +25,7 @@ enum mlx5e_rx_res_features { + struct mlx5e_rx_res *mlx5e_rx_res_alloc(void); + int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, + enum mlx5e_rx_res_features features, unsigned int max_nch, +- u32 drop_rqn, const struct mlx5e_lro_param *init_lro_param, ++ u32 drop_rqn, const struct mlx5e_packet_merge_param *init_pkt_merge_param, + unsigned int init_nch); + void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res); + void mlx5e_rx_res_free(struct mlx5e_rx_res *res); +@@ -37,9 +37,6 @@ u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5_traffic_types + u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt); + u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res); + +-/* RQTN getters for modules that create their own TIRs */ +-u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix); +- + /* Activate/deactivate API */ + void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs); + void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res); +@@ -57,7 +54,8 @@ int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, u32 rss_idx, + u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt); + int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt, + u8 rx_hash_fields); +-int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param *lro_param); ++int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, ++ struct mlx5e_packet_merge_param *pkt_merge_param); + + int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch); + int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx); +@@ -68,4 +66,7 @@ struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx); + /* Workaround for hairpin */ + struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res); + ++/* Accel TIRs */ ++int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, ++ struct mlx5e_tir *tir); + #endif /* __MLX5_EN_RX_RES_H__ */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.h +index db0146df9b303..9ef8a49d78014 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/sample.h +@@ -19,6 +19,8 @@ struct mlx5e_sample_attr { + struct mlx5e_sample_flow *sample_flow; + }; + ++#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) ++ + void mlx5e_tc_sample_skb(struct sk_buff *skb, struct mlx5_mapped_obj *mapped_obj); + + struct mlx5_flow_handle * +@@ -38,4 +40,29 @@ mlx5e_tc_sample_init(struct mlx5_eswitch *esw, struct mlx5e_post_act *post_act); + void + mlx5e_tc_sample_cleanup(struct mlx5e_tc_psample *tc_psample); + ++#else /* CONFIG_MLX5_TC_SAMPLE */ ++ ++static inline struct mlx5_flow_handle * ++mlx5e_tc_sample_offload(struct mlx5e_tc_psample *tc_psample, ++ struct mlx5_flow_spec *spec, ++ struct mlx5_flow_attr *attr, ++ u32 tunnel_id) ++{ return ERR_PTR(-EOPNOTSUPP); } ++ ++static inline void ++mlx5e_tc_sample_unoffload(struct mlx5e_tc_psample *tc_psample, ++ struct mlx5_flow_handle *rule, ++ struct mlx5_flow_attr *attr) {} ++ ++static inline struct mlx5e_tc_psample * ++mlx5e_tc_sample_init(struct mlx5_eswitch *esw, struct mlx5e_post_act *post_act) ++{ return ERR_PTR(-EOPNOTSUPP); } ++ ++static inline void ++mlx5e_tc_sample_cleanup(struct mlx5e_tc_psample *tc_psample) {} ++ ++static inline void ++mlx5e_tc_sample_skb(struct sk_buff *skb, struct mlx5_mapped_obj *mapped_obj) {} ++ ++#endif /* CONFIG_MLX5_TC_SAMPLE */ + #endif /* __MLX5_EN_TC_SAMPLE_H__ */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +index 6c949abcd2e14..bc65151321ec2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +@@ -1356,9 +1356,13 @@ mlx5_tc_ct_match_add(struct mlx5_tc_ct_priv *priv, + int + mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, + struct mlx5_flow_attr *attr, ++ struct mlx5e_tc_mod_hdr_acts *mod_acts, + const struct flow_action_entry *act, + struct netlink_ext_ack *extack) + { ++ bool clear_action = act->ct.action & TCA_CT_ACT_CLEAR; ++ int err; ++ + if (!priv) { + NL_SET_ERR_MSG_MOD(extack, + "offload of ct action isn't available"); +@@ -1369,6 +1373,17 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, + attr->ct_attr.ct_action = act->ct.action; + attr->ct_attr.nf_ft = act->ct.flow_table; + ++ if (!clear_action) ++ goto out; ++ ++ err = mlx5_tc_ct_entry_set_registers(priv, mod_acts, 0, 0, 0, 0); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(extack, "Failed to set registers for ct clear"); ++ return err; ++ } ++ attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; ++ ++out: + return 0; + } + +@@ -1898,23 +1913,16 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv, + + memcpy(pre_ct_attr, attr, attr_sz); + +- err = mlx5_tc_ct_entry_set_registers(ct_priv, mod_acts, 0, 0, 0, 0); +- if (err) { +- ct_dbg("Failed to set register for ct clear"); +- goto err_set_registers; +- } +- + mod_hdr = mlx5_modify_header_alloc(priv->mdev, ct_priv->ns_type, + mod_acts->num_actions, + mod_acts->actions); + if (IS_ERR(mod_hdr)) { + err = PTR_ERR(mod_hdr); + ct_dbg("Failed to add create ct clear mod hdr"); +- goto err_set_registers; ++ goto err_mod_hdr; + } + + pre_ct_attr->modify_hdr = mod_hdr; +- pre_ct_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; + + rule = mlx5_tc_rule_insert(priv, orig_spec, pre_ct_attr); + if (IS_ERR(rule)) { +@@ -1930,7 +1938,7 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv, + + err_insert: + mlx5_modify_header_dealloc(priv->mdev, mod_hdr); +-err_set_registers: ++err_mod_hdr: + netdev_warn(priv->netdev, + "Failed to offload ct clear flow, err %d\n", err); + kfree(pre_ct_attr); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h +index 363329f4aac61..99662af1e41a7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h +@@ -110,6 +110,7 @@ int mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec); + int + mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, + struct mlx5_flow_attr *attr, ++ struct mlx5e_tc_mod_hdr_acts *mod_acts, + const struct flow_action_entry *act, + struct netlink_ext_ack *extack); + +@@ -172,6 +173,7 @@ mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec) + static inline int + mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv, + struct mlx5_flow_attr *attr, ++ struct mlx5e_tc_mod_hdr_acts *mod_acts, + const struct flow_action_entry *act, + struct netlink_ext_ack *extack) + { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h +index d1599b7b944bf..c340bf90354a0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h +@@ -102,6 +102,7 @@ struct mlx5e_tc_flow { + refcount_t refcnt; + struct rcu_head rcu_head; + struct completion init_done; ++ struct completion del_hw_done; + int tunnel_id; /* the mapped tunnel id of this flow */ + struct mlx5_flow_attr *attr; + }; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +index 4a13ef561587d..cf03297c84710 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ + /* Copyright (c) 2018 Mellanox Technologies. */ + ++#include <net/inet_ecn.h> + #include <net/vxlan.h> + #include <net/gre.h> + #include <net/geneve.h> +@@ -229,7 +230,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv, + int err; + + /* add the IP fields */ +- attr.fl.fl4.flowi4_tos = tun_key->tos; ++ attr.fl.fl4.flowi4_tos = tun_key->tos & ~INET_ECN_MASK; + attr.fl.fl4.daddr = tun_key->u.ipv4.dst; + attr.fl.fl4.saddr = tun_key->u.ipv4.src; + attr.ttl = tun_key->ttl; +@@ -344,7 +345,7 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv, + int err; + + /* add the IP fields */ +- attr.fl.fl4.flowi4_tos = tun_key->tos; ++ attr.fl.fl4.flowi4_tos = tun_key->tos & ~INET_ECN_MASK; + attr.fl.fl4.daddr = tun_key->u.ipv4.dst; + attr.fl.fl4.saddr = tun_key->u.ipv4.src; + attr.ttl = tun_key->ttl; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +index 1c44c6c345f5d..700c463ea3679 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +@@ -221,8 +221,14 @@ static void mlx5e_take_tmp_flow(struct mlx5e_tc_flow *flow, + struct list_head *flow_list, + int index) + { +- if (IS_ERR(mlx5e_flow_get(flow))) ++ if (IS_ERR(mlx5e_flow_get(flow))) { ++ /* Flow is being deleted concurrently. Wait for it to be ++ * unoffloaded from hardware, otherwise deleting encap will ++ * fail. ++ */ ++ wait_for_completion(&flow->del_hw_done); + return; ++ } + wait_for_completion(&flow->init_done); + + flow->tmp_entry_index = index; +@@ -1538,6 +1544,8 @@ mlx5e_init_fib_work_ipv4(struct mlx5e_priv *priv, + struct net_device *fib_dev; + + fen_info = container_of(info, struct fib_entry_notifier_info, info); ++ if (fen_info->fi->nh) ++ return NULL; + fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev; + if (!fib_dev || fib_dev->netdev_ops != &mlx5e_netdev_ops || + fen_info->dst_len != 32) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c +index 60952b33b5688..d2333310b56fe 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c +@@ -60,37 +60,31 @@ static int parse_tunnel(struct mlx5e_priv *priv, + void *headers_v) + { + struct flow_rule *rule = flow_cls_offload_flow_rule(f); +- struct flow_match_enc_keyid enc_keyid; + struct flow_match_mpls match; + void *misc2_c; + void *misc2_v; + +- misc2_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, +- misc_parameters_2); +- misc2_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, +- misc_parameters_2); +- +- if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) +- return 0; +- +- if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) +- return 0; +- +- flow_rule_match_enc_keyid(rule, &enc_keyid); +- +- if (!enc_keyid.mask->keyid) +- return 0; +- + if (!MLX5_CAP_ETH(priv->mdev, tunnel_stateless_mpls_over_udp) && + !(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) & MLX5_FLEX_PROTO_CW_MPLS_UDP)) + return -EOPNOTSUPP; + ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) ++ return -EOPNOTSUPP; ++ ++ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) ++ return 0; ++ + flow_rule_match_mpls(rule, &match); + + /* Only support matching the first LSE */ + if (match.mask->used_lses != 1) + return -EOPNOTSUPP; + ++ misc2_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, ++ misc_parameters_2); ++ misc2_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, ++ misc_parameters_2); ++ + MLX5_SET(fte_match_set_misc2, misc2_c, + outer_first_mpls_over_udp.mpls_label, + match.mask->ls[0].mpls_label); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c +index de936dc4bc483..a1afb8585e37f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.c +@@ -70,24 +70,24 @@ void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn, + MLX5_SET(tirc, tirc, tunneled_offload_en, inner_ft_support); + } + +-void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder, +- const struct mlx5e_lro_param *lro_param) ++void mlx5e_tir_builder_build_packet_merge(struct mlx5e_tir_builder *builder, ++ const struct mlx5e_packet_merge_param *pkt_merge_param) + { + void *tirc = mlx5e_tir_builder_get_tirc(builder); + const unsigned int rough_max_l2_l3_hdr_sz = 256; + + if (builder->modify) +- MLX5_SET(modify_tir_in, builder->in, bitmask.lro, 1); ++ MLX5_SET(modify_tir_in, builder->in, bitmask.packet_merge, 1); + +- if (!lro_param->enabled) ++ if (pkt_merge_param->type == MLX5E_PACKET_MERGE_NONE) + return; + +- MLX5_SET(tirc, tirc, lro_enable_mask, +- MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO | +- MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO); ++ MLX5_SET(tirc, tirc, packet_merge_mask, ++ MLX5_TIRC_PACKET_MERGE_MASK_IPV4_LRO | ++ MLX5_TIRC_PACKET_MERGE_MASK_IPV6_LRO); + MLX5_SET(tirc, tirc, lro_max_ip_payload_size, + (MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - rough_max_l2_l3_hdr_sz) >> 8); +- MLX5_SET(tirc, tirc, lro_timeout_period_usecs, lro_param->timeout); ++ MLX5_SET(tirc, tirc, lro_timeout_period_usecs, pkt_merge_param->timeout); + } + + static int mlx5e_hfunc_to_hw(u8 hfunc) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h +index e45149a78ed9d..857a84bcd53af 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tir.h +@@ -18,7 +18,7 @@ struct mlx5e_rss_params_traffic_type { + }; + + struct mlx5e_tir_builder; +-struct mlx5e_lro_param; ++struct mlx5e_packet_merge_param; + + struct mlx5e_tir_builder *mlx5e_tir_builder_alloc(bool modify); + void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder); +@@ -27,8 +27,8 @@ void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder); + void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn); + void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn, + u32 rqtn, bool inner_ft_support); +-void mlx5e_tir_builder_build_lro(struct mlx5e_tir_builder *builder, +- const struct mlx5e_lro_param *lro_param); ++void mlx5e_tir_builder_build_packet_merge(struct mlx5e_tir_builder *builder, ++ const struct mlx5e_packet_merge_param *pkt_merge_param); + void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder, + const struct mlx5e_rss_params_hash *rss_hash, + const struct mlx5e_rss_params_traffic_type *rss_tt, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c +index 7b562d2c8a196..279cd8f4e79f7 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c +@@ -11,13 +11,13 @@ static int mlx5e_xsk_map_pool(struct mlx5e_priv *priv, + { + struct device *dev = mlx5_core_dma_dev(priv->mdev); + +- return xsk_pool_dma_map(pool, dev, 0); ++ return xsk_pool_dma_map(pool, dev, DMA_ATTR_SKIP_CPU_SYNC); + } + + static void mlx5e_xsk_unmap_pool(struct mlx5e_priv *priv, + struct xsk_buff_pool *pool) + { +- return xsk_pool_dma_unmap(pool, 0); ++ return xsk_pool_dma_unmap(pool, DMA_ATTR_SKIP_CPU_SYNC); + } + + static int mlx5e_xsk_get_pools(struct mlx5e_xsk *xsk) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +index 538bc2419bd83..8526a5fbbf0bf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c +@@ -4,6 +4,7 @@ + #include "setup.h" + #include "en/params.h" + #include "en/txrx.h" ++#include "en/health.h" + + /* It matches XDP_UMEM_MIN_CHUNK_SIZE, but as this constant is private and may + * change unexpectedly, and mlx5e has a minimum valid stride size for striding +@@ -170,7 +171,13 @@ void mlx5e_close_xsk(struct mlx5e_channel *c) + + void mlx5e_activate_xsk(struct mlx5e_channel *c) + { ++ /* ICOSQ recovery deactivates RQs. Suspend the recovery to avoid ++ * activating XSKRQ in the middle of recovery. ++ */ ++ mlx5e_reporter_icosq_suspend_recovery(c); + set_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state); ++ mlx5e_reporter_icosq_resume_recovery(c); ++ + /* TX queue is created active. */ + + spin_lock_bh(&c->async_icosq_lock); +@@ -180,6 +187,13 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c) + + void mlx5e_deactivate_xsk(struct mlx5e_channel *c) + { +- mlx5e_deactivate_rq(&c->xskrq); ++ /* ICOSQ recovery may reactivate XSKRQ if clear_bit is called in the ++ * middle of recovery. Suspend the recovery to avoid it. ++ */ ++ mlx5e_reporter_icosq_suspend_recovery(c); ++ clear_bit(MLX5E_RQ_STATE_ENABLED, &c->xskrq.state); ++ mlx5e_reporter_icosq_resume_recovery(c); ++ synchronize_net(); /* Sync with NAPI to prevent mlx5e_post_rx_wqes. */ ++ + /* TX queue is disabled on close. */ + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +index fb5397324aa4f..b56fea142c246 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +@@ -157,11 +157,20 @@ static void mlx5e_ipsec_set_swp(struct sk_buff *skb, + /* Tunnel mode */ + if (mode == XFRM_MODE_TUNNEL) { + eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2; +- eseg->swp_inner_l4_offset = skb_inner_transport_offset(skb) / 2; + if (xo->proto == IPPROTO_IPV6) + eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6; +- if (inner_ip_hdr(skb)->protocol == IPPROTO_UDP) ++ ++ switch (xo->inner_ipproto) { ++ case IPPROTO_UDP: + eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L4_UDP; ++ fallthrough; ++ case IPPROTO_TCP: ++ /* IP | ESP | IP | [TCP | UDP] */ ++ eseg->swp_inner_l4_offset = skb_inner_transport_offset(skb) / 2; ++ break; ++ default: ++ break; ++ } + return; + } + +@@ -191,7 +200,7 @@ static void mlx5e_ipsec_set_swp(struct sk_buff *skb, + eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2; + eseg->swp_inner_l4_offset = + (skb->csum_start + skb->head - skb->data) / 2; +- if (skb->protocol == htons(ETH_P_IPV6)) ++ if (inner_ip_hdr(skb)->version == 6) + eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6; + break; + default: +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h +index 5120a59361e6a..428881e0adcbe 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h +@@ -127,6 +127,28 @@ out_disable: + return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); + } + ++static inline bool ++mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, ++ struct mlx5_wqe_eth_seg *eseg) ++{ ++ u8 inner_ipproto; ++ ++ if (!mlx5e_ipsec_eseg_meta(eseg)) ++ return false; ++ ++ eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM; ++ inner_ipproto = xfrm_offload(skb)->inner_ipproto; ++ if (inner_ipproto) { ++ eseg->cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM; ++ if (inner_ipproto == IPPROTO_TCP || inner_ipproto == IPPROTO_UDP) ++ eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM; ++ } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM; ++ sq->stats->csum_partial_inner++; ++ } ++ ++ return true; ++} + #else + static inline + void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, +@@ -143,6 +165,13 @@ static inline bool mlx5_ipsec_is_rx_flow(struct mlx5_cqe64 *cqe) { return false; + static inline netdev_features_t + mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features) + { return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); } ++ ++static inline bool ++mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, ++ struct mlx5_wqe_eth_seg *eseg) ++{ ++ return false; ++} + #endif /* CONFIG_MLX5_EN_IPSEC */ + + #endif /* __MLX5E_IPSEC_RXTX_H__ */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +index 62abce008c7b8..15711814d2d28 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +@@ -55,6 +55,7 @@ struct mlx5e_ktls_offload_context_rx { + DECLARE_BITMAP(flags, MLX5E_NUM_PRIV_RX_FLAGS); + + /* resync */ ++ spinlock_t lock; /* protects resync fields */ + struct mlx5e_ktls_rx_resync_ctx resync; + struct list_head list; + }; +@@ -99,25 +100,6 @@ mlx5e_ktls_rx_resync_create_resp_list(void) + return resp_list; + } + +-static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 rqtn) +-{ +- struct mlx5e_tir_builder *builder; +- int err; +- +- builder = mlx5e_tir_builder_alloc(false); +- if (!builder) +- return -ENOMEM; +- +- mlx5e_tir_builder_build_rqt(builder, mdev->mlx5e_res.hw_objs.td.tdn, rqtn, false); +- mlx5e_tir_builder_build_direct(builder); +- mlx5e_tir_builder_build_tls(builder); +- err = mlx5e_tir_init(tir, builder, mdev, false); +- +- mlx5e_tir_builder_free(builder); +- +- return err; +-} +- + static void accel_rule_handle_work(struct work_struct *work) + { + struct mlx5e_ktls_offload_context_rx *priv_rx; +@@ -386,14 +368,18 @@ static void resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_r + struct mlx5e_icosq *sq; + bool trigger_poll; + +- memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq)); +- + sq = &c->async_icosq; + ktls_resync = sq->ktls_resync; ++ trigger_poll = false; + + spin_lock_bh(&ktls_resync->lock); +- list_add_tail(&priv_rx->list, &ktls_resync->list); +- trigger_poll = !test_and_set_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &sq->state); ++ spin_lock_bh(&priv_rx->lock); ++ memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq)); ++ if (list_empty(&priv_rx->list)) { ++ list_add_tail(&priv_rx->list, &ktls_resync->list); ++ trigger_poll = !test_and_set_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &sq->state); ++ } ++ spin_unlock_bh(&priv_rx->lock); + spin_unlock_bh(&ktls_resync->lock); + + if (!trigger_poll) +@@ -604,7 +590,6 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, + struct mlx5_core_dev *mdev; + struct mlx5e_priv *priv; + int rxq, err; +- u32 rqtn; + + tls_ctx = tls_get_ctx(sk); + priv = netdev_priv(netdev); +@@ -617,6 +602,8 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, + if (err) + goto err_create_key; + ++ INIT_LIST_HEAD(&priv_rx->list); ++ spin_lock_init(&priv_rx->lock); + priv_rx->crypto_info = + *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info; + +@@ -628,9 +615,7 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, + priv_rx->sw_stats = &priv->tls->sw_stats; + mlx5e_set_ktls_rx_priv_ctx(tls_ctx, priv_rx); + +- rqtn = mlx5e_rx_res_get_rqtn_direct(priv->rx_res, rxq); +- +- err = mlx5e_ktls_create_tir(mdev, &priv_rx->tir, rqtn); ++ err = mlx5e_rx_res_tls_tir_create(priv->rx_res, rxq, &priv_rx->tir); + if (err) + goto err_create_tir; + +@@ -730,10 +715,14 @@ bool mlx5e_ktls_rx_handle_resync_list(struct mlx5e_channel *c, int budget) + priv_rx = list_first_entry(&local_list, + struct mlx5e_ktls_offload_context_rx, + list); ++ spin_lock(&priv_rx->lock); + cseg = post_static_params(sq, priv_rx); +- if (IS_ERR(cseg)) ++ if (IS_ERR(cseg)) { ++ spin_unlock(&priv_rx->lock); + break; +- list_del(&priv_rx->list); ++ } ++ list_del_init(&priv_rx->list); ++ spin_unlock(&priv_rx->lock); + db_cseg = cseg; + } + if (db_cseg) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index 9d451b8ee467c..2d3cd237355a6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -1754,7 +1754,7 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev, + if (size_read < 0) { + netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n", + __func__, size_read); +- return 0; ++ return size_read; + } + + i += size_read; +@@ -1954,8 +1954,8 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable) + return -EOPNOTSUPP; + if (!mlx5e_striding_rq_possible(mdev, &priv->channels.params)) + return -EINVAL; +- } else if (priv->channels.params.lro_en) { +- netdev_warn(netdev, "Can't set legacy RQ with LRO, disable LRO first\n"); ++ } else if (priv->channels.params.packet_merge.type != MLX5E_PACKET_MERGE_NONE) { ++ netdev_warn(netdev, "Can't set legacy RQ with HW-GRO/LRO, disable them first\n"); + return -EINVAL; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +index 03693fa74a704..d32b70c62c949 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +@@ -411,7 +411,7 @@ static int flow_get_tirn(struct mlx5e_priv *priv, + u32 rss_context, u32 *tirn) + { + if (fs->flow_type & FLOW_RSS) { +- struct mlx5e_lro_param lro_param; ++ struct mlx5e_packet_merge_param pkt_merge_param; + struct mlx5e_rss *rss; + u32 flow_type; + int err; +@@ -426,8 +426,8 @@ static int flow_get_tirn(struct mlx5e_priv *priv, + if (tt < 0) + return -EINVAL; + +- lro_param = mlx5e_get_lro_param(&priv->channels.params); +- err = mlx5e_rss_obtain_tirn(rss, tt, &lro_param, false, tirn); ++ pkt_merge_param = priv->channels.params.packet_merge; ++ err = mlx5e_rss_obtain_tirn(rss, tt, &pkt_merge_param, false, tirn); + if (err) + return err; + eth_rule->rss = rss; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 41ef6eb70a585..f075bb8ccd00d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -911,8 +911,6 @@ void mlx5e_deactivate_rq(struct mlx5e_rq *rq) + void mlx5e_close_rq(struct mlx5e_rq *rq) + { + cancel_work_sync(&rq->dim.work); +- if (rq->icosq) +- cancel_work_sync(&rq->icosq->recover_work); + cancel_work_sync(&rq->recover_work); + mlx5e_destroy_rq(rq); + mlx5e_free_rx_descs(rq); +@@ -1038,9 +1036,20 @@ static void mlx5e_icosq_err_cqe_work(struct work_struct *recover_work) + mlx5e_reporter_icosq_cqe_err(sq); + } + ++static void mlx5e_async_icosq_err_cqe_work(struct work_struct *recover_work) ++{ ++ struct mlx5e_icosq *sq = container_of(recover_work, struct mlx5e_icosq, ++ recover_work); ++ ++ /* Not implemented yet. */ ++ ++ netdev_warn(sq->channel->netdev, "async_icosq recovery is not implemented\n"); ++} ++ + static int mlx5e_alloc_icosq(struct mlx5e_channel *c, + struct mlx5e_sq_param *param, +- struct mlx5e_icosq *sq) ++ struct mlx5e_icosq *sq, ++ work_func_t recover_work_func) + { + void *sqc_wq = MLX5_ADDR_OF(sqc, param->sqc, wq); + struct mlx5_core_dev *mdev = c->mdev; +@@ -1061,7 +1070,7 @@ static int mlx5e_alloc_icosq(struct mlx5e_channel *c, + if (err) + goto err_sq_wq_destroy; + +- INIT_WORK(&sq->recover_work, mlx5e_icosq_err_cqe_work); ++ INIT_WORK(&sq->recover_work, recover_work_func); + + return 0; + +@@ -1399,13 +1408,14 @@ void mlx5e_tx_err_cqe_work(struct work_struct *recover_work) + mlx5e_reporter_tx_err_cqe(sq); + } + +-int mlx5e_open_icosq(struct mlx5e_channel *c, struct mlx5e_params *params, +- struct mlx5e_sq_param *param, struct mlx5e_icosq *sq) ++static int mlx5e_open_icosq(struct mlx5e_channel *c, struct mlx5e_params *params, ++ struct mlx5e_sq_param *param, struct mlx5e_icosq *sq, ++ work_func_t recover_work_func) + { + struct mlx5e_create_sq_param csp = {}; + int err; + +- err = mlx5e_alloc_icosq(c, param, sq); ++ err = mlx5e_alloc_icosq(c, param, sq, recover_work_func); + if (err) + return err; + +@@ -1444,7 +1454,7 @@ void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq) + synchronize_net(); /* Sync with NAPI. */ + } + +-void mlx5e_close_icosq(struct mlx5e_icosq *sq) ++static void mlx5e_close_icosq(struct mlx5e_icosq *sq) + { + struct mlx5e_channel *c = sq->channel; + +@@ -1871,11 +1881,15 @@ static int mlx5e_open_queues(struct mlx5e_channel *c, + + spin_lock_init(&c->async_icosq_lock); + +- err = mlx5e_open_icosq(c, params, &cparam->async_icosq, &c->async_icosq); ++ err = mlx5e_open_icosq(c, params, &cparam->async_icosq, &c->async_icosq, ++ mlx5e_async_icosq_err_cqe_work); + if (err) + goto err_close_xdpsq_cq; + +- err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->icosq); ++ mutex_init(&c->icosq_recovery_lock); ++ ++ err = mlx5e_open_icosq(c, params, &cparam->icosq, &c->icosq, ++ mlx5e_icosq_err_cqe_work); + if (err) + goto err_close_async_icosq; + +@@ -1943,9 +1957,12 @@ static void mlx5e_close_queues(struct mlx5e_channel *c) + mlx5e_close_xdpsq(&c->xdpsq); + if (c->xdp) + mlx5e_close_xdpsq(&c->rq_xdpsq); ++ /* The same ICOSQ is used for UMRs for both RQ and XSKRQ. */ ++ cancel_work_sync(&c->icosq.recover_work); + mlx5e_close_rq(&c->rq); + mlx5e_close_sqs(c); + mlx5e_close_icosq(&c->icosq); ++ mutex_destroy(&c->icosq_recovery_lock); + mlx5e_close_icosq(&c->async_icosq); + if (c->xdp) + mlx5e_close_cq(&c->rq_xdpsq.cq); +@@ -2185,17 +2202,14 @@ void mlx5e_close_channels(struct mlx5e_channels *chs) + chs->num = 0; + } + +-static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv) ++static int mlx5e_modify_tirs_packet_merge(struct mlx5e_priv *priv) + { + struct mlx5e_rx_res *res = priv->rx_res; +- struct mlx5e_lro_param lro_param; + +- lro_param = mlx5e_get_lro_param(&priv->channels.params); +- +- return mlx5e_rx_res_lro_set_param(res, &lro_param); ++ return mlx5e_rx_res_packet_merge_set_param(res, &priv->channels.params.packet_merge); + } + +-static MLX5E_DEFINE_PREACTIVATE_WRAPPER_CTX(mlx5e_modify_tirs_lro); ++static MLX5E_DEFINE_PREACTIVATE_WRAPPER_CTX(mlx5e_modify_tirs_packet_merge); + + static int mlx5e_set_mtu(struct mlx5_core_dev *mdev, + struct mlx5e_params *params, u16 mtu) +@@ -3270,16 +3284,25 @@ static int set_feature_lro(struct net_device *netdev, bool enable) + } + + new_params = *cur_params; +- new_params.lro_en = enable; + +- if (cur_params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { +- if (mlx5e_rx_mpwqe_is_linear_skb(mdev, cur_params, NULL) == +- mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_params, NULL)) +- reset = false; ++ if (enable) ++ new_params.packet_merge.type = MLX5E_PACKET_MERGE_LRO; ++ else if (new_params.packet_merge.type == MLX5E_PACKET_MERGE_LRO) ++ new_params.packet_merge.type = MLX5E_PACKET_MERGE_NONE; ++ else ++ goto out; ++ ++ if (!(cur_params->packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO && ++ new_params.packet_merge.type == MLX5E_PACKET_MERGE_LRO)) { ++ if (cur_params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { ++ if (mlx5e_rx_mpwqe_is_linear_skb(mdev, cur_params, NULL) == ++ mlx5e_rx_mpwqe_is_linear_skb(mdev, &new_params, NULL)) ++ reset = false; ++ } + } + + err = mlx5e_safe_switch_params(priv, &new_params, +- mlx5e_modify_tirs_lro_ctx, NULL, reset); ++ mlx5e_modify_tirs_packet_merge_ctx, NULL, reset); + out: + mutex_unlock(&priv->state_lock); + return err; +@@ -3427,12 +3450,11 @@ static int set_feature_arfs(struct net_device *netdev, bool enable) + + static int mlx5e_handle_feature(struct net_device *netdev, + netdev_features_t *features, +- netdev_features_t wanted_features, + netdev_features_t feature, + mlx5e_feature_handler feature_handler) + { +- netdev_features_t changes = wanted_features ^ netdev->features; +- bool enable = !!(wanted_features & feature); ++ netdev_features_t changes = *features ^ netdev->features; ++ bool enable = !!(*features & feature); + int err; + + if (!(changes & feature)) +@@ -3440,22 +3462,22 @@ static int mlx5e_handle_feature(struct net_device *netdev, + + err = feature_handler(netdev, enable); + if (err) { ++ MLX5E_SET_FEATURE(features, feature, !enable); + netdev_err(netdev, "%s feature %pNF failed, err %d\n", + enable ? "Enable" : "Disable", &feature, err); + return err; + } + +- MLX5E_SET_FEATURE(features, feature, enable); + return 0; + } + + int mlx5e_set_features(struct net_device *netdev, netdev_features_t features) + { +- netdev_features_t oper_features = netdev->features; ++ netdev_features_t oper_features = features; + int err = 0; + + #define MLX5E_HANDLE_FEATURE(feature, handler) \ +- mlx5e_handle_feature(netdev, &oper_features, features, feature, handler) ++ mlx5e_handle_feature(netdev, &oper_features, feature, handler) + + err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro); + err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER, +@@ -3606,7 +3628,7 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu, + goto out; + } + +- if (params->lro_en) ++ if (params->packet_merge.type == MLX5E_PACKET_MERGE_LRO) + reset = false; + + if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { +@@ -4063,8 +4085,8 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog) + struct net_device *netdev = priv->netdev; + struct mlx5e_params new_params; + +- if (priv->channels.params.lro_en) { +- netdev_warn(netdev, "can't set XDP while LRO is on, disable LRO first\n"); ++ if (priv->channels.params.packet_merge.type != MLX5E_PACKET_MERGE_NONE) { ++ netdev_warn(netdev, "can't set XDP while HW-GRO/LRO is on, disable them first\n"); + return -EINVAL; + } + +@@ -4321,9 +4343,10 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 + params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { + /* No XSK params: checking the availability of striding RQ in general. */ + if (!mlx5e_rx_mpwqe_is_linear_skb(mdev, params, NULL)) +- params->lro_en = !slow_pci_heuristic(mdev); ++ params->packet_merge.type = slow_pci_heuristic(mdev) ? ++ MLX5E_PACKET_MERGE_NONE : MLX5E_PACKET_MERGE_LRO; + } +- params->lro_timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT); ++ params->packet_merge.timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT); + + /* CQ moderation params */ + rx_cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ? +@@ -4462,15 +4485,22 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) + } + + if (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev)) { +- netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; +- netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL; +- netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL; ++ netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM; ++ netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM; ++ netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM; ++ netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL | ++ NETIF_F_GSO_UDP_TUNNEL_CSUM; + } + + if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_GRE)) { +- netdev->hw_features |= NETIF_F_GSO_GRE; +- netdev->hw_enc_features |= NETIF_F_GSO_GRE; +- netdev->gso_partial_features |= NETIF_F_GSO_GRE; ++ netdev->hw_features |= NETIF_F_GSO_GRE | ++ NETIF_F_GSO_GRE_CSUM; ++ netdev->hw_enc_features |= NETIF_F_GSO_GRE | ++ NETIF_F_GSO_GRE_CSUM; ++ netdev->gso_partial_features |= NETIF_F_GSO_GRE | ++ NETIF_F_GSO_GRE_CSUM; + } + + if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_IPIP)) { +@@ -4608,7 +4638,6 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) + { + struct mlx5_core_dev *mdev = priv->mdev; + enum mlx5e_rx_res_features features; +- struct mlx5e_lro_param lro_param; + int err; + + priv->rx_res = mlx5e_rx_res_alloc(); +@@ -4626,9 +4655,9 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv) + features = MLX5E_RX_RES_FEATURE_XSK | MLX5E_RX_RES_FEATURE_PTP; + if (priv->channels.params.tunneled_offload_en) + features |= MLX5E_RX_RES_FEATURE_INNER_FT; +- lro_param = mlx5e_get_lro_param(&priv->channels.params); + err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, features, +- priv->max_nch, priv->drop_rq.rqn, &lro_param, ++ priv->max_nch, priv->drop_rq.rqn, ++ &priv->channels.params.packet_merge, + priv->channels.params.num_channels); + if (err) + goto err_close_drop_rq; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +index 0684ac6699b2d..161b60e1139b3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +@@ -50,6 +50,7 @@ + #include "fs_core.h" + #include "lib/mlx5.h" + #include "lib/devcom.h" ++#include "lib/vxlan.h" + #define CREATE_TRACE_POINTS + #include "diag/en_rep_tracepoint.h" + #include "en_accel/ipsec.h" +@@ -793,7 +794,6 @@ int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup) + static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) + { + struct mlx5_core_dev *mdev = priv->mdev; +- struct mlx5e_lro_param lro_param; + int err; + + priv->rx_res = mlx5e_rx_res_alloc(); +@@ -808,9 +808,9 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) + return err; + } + +- lro_param = mlx5e_get_lro_param(&priv->channels.params); + err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, +- priv->max_nch, priv->drop_rq.rqn, &lro_param, ++ priv->max_nch, priv->drop_rq.rqn, ++ &priv->channels.params.packet_merge, + priv->channels.params.num_channels); + if (err) + goto err_close_drop_rq; +@@ -1017,6 +1017,7 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) + rtnl_lock(); + if (netif_running(netdev)) + mlx5e_open(netdev); ++ udp_tunnel_nic_reset_ntf(priv->netdev); + netif_device_attach(netdev); + rtnl_unlock(); + } +@@ -1038,6 +1039,7 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) + mlx5_notifier_unregister(mdev, &priv->events_nb); + mlx5e_rep_tc_disable(priv); + mlx5_lag_remove_netdev(mdev, priv->netdev); ++ mlx5_vxlan_reset_to_default(mdev->vxlan); + } + + static MLX5E_DEFINE_STATS_GRP(sw_rep, 0); +@@ -1070,6 +1072,10 @@ static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = { + &MLX5E_STATS_GRP(pme), + &MLX5E_STATS_GRP(channels), + &MLX5E_STATS_GRP(per_port_buff_congest), ++#ifdef CONFIG_MLX5_EN_IPSEC ++ &MLX5E_STATS_GRP(ipsec_sw), ++ &MLX5E_STATS_GRP(ipsec_hw), ++#endif + }; + + static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +index 29a6586ef28dc..d2de1e6c514c1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +@@ -271,8 +271,8 @@ static inline int mlx5e_page_alloc_pool(struct mlx5e_rq *rq, + if (unlikely(!dma_info->page)) + return -ENOMEM; + +- dma_info->addr = dma_map_page(rq->pdev, dma_info->page, 0, +- PAGE_SIZE, rq->buff.map_dir); ++ dma_info->addr = dma_map_page_attrs(rq->pdev, dma_info->page, 0, PAGE_SIZE, ++ rq->buff.map_dir, DMA_ATTR_SKIP_CPU_SYNC); + if (unlikely(dma_mapping_error(rq->pdev, dma_info->addr))) { + page_pool_recycle_direct(rq->page_pool, dma_info->page); + dma_info->page = NULL; +@@ -293,7 +293,8 @@ static inline int mlx5e_page_alloc(struct mlx5e_rq *rq, + + void mlx5e_page_dma_unmap(struct mlx5e_rq *rq, struct mlx5e_dma_info *dma_info) + { +- dma_unmap_page(rq->pdev, dma_info->addr, PAGE_SIZE, rq->buff.map_dir); ++ dma_unmap_page_attrs(rq->pdev, dma_info->addr, PAGE_SIZE, rq->buff.map_dir, ++ DMA_ATTR_SKIP_CPU_SYNC); + } + + void mlx5e_page_release_dynamic(struct mlx5e_rq *rq, +@@ -986,7 +987,8 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, + } + + /* True when explicitly set via priv flag, or XDP prog is loaded */ +- if (test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state)) ++ if (test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state) || ++ get_cqe_tls_offload(cqe)) + goto csum_unnecessary; + + /* CQE csum doesn't cover padding octets in short ethernet +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +index 129ff7e0d65cc..8b041deb25e5f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +@@ -248,7 +248,6 @@ get_ct_priv(struct mlx5e_priv *priv) + return priv->fs.tc.ct; + } + +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) + static struct mlx5e_tc_psample * + get_sample_priv(struct mlx5e_priv *priv) + { +@@ -265,7 +264,6 @@ get_sample_priv(struct mlx5e_priv *priv) + + return NULL; + } +-#endif + + struct mlx5_flow_handle * + mlx5_tc_rule_insert(struct mlx5e_priv *priv, +@@ -1148,11 +1146,9 @@ mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw, + rule = mlx5_tc_ct_flow_offload(get_ct_priv(flow->priv), + flow, spec, attr, + mod_hdr_acts); +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) + } else if (flow_flag_test(flow, SAMPLE)) { + rule = mlx5e_tc_sample_offload(get_sample_priv(flow->priv), spec, attr, + mlx5e_tc_get_flow_tun_id(flow)); +-#endif + } else { + rule = mlx5_eswitch_add_offloaded_rule(esw, spec, attr); + } +@@ -1183,23 +1179,16 @@ void mlx5e_tc_unoffload_fdb_rules(struct mlx5_eswitch *esw, + if (attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) + goto offload_rule_0; + +- if (flow_flag_test(flow, CT)) { +- mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), flow, attr); +- return; +- } +- +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) +- if (flow_flag_test(flow, SAMPLE)) { +- mlx5e_tc_sample_unoffload(get_sample_priv(flow->priv), flow->rule[0], attr); +- return; +- } +-#endif +- + if (attr->esw_attr->split_count) + mlx5_eswitch_del_fwd_rule(esw, flow->rule[1], attr); + ++ if (flow_flag_test(flow, CT)) ++ mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), flow, attr); ++ else if (flow_flag_test(flow, SAMPLE)) ++ mlx5e_tc_sample_unoffload(get_sample_priv(flow->priv), flow->rule[0], attr); ++ else + offload_rule_0: +- mlx5_eswitch_del_offloaded_rule(esw, flow->rule[0], attr); ++ mlx5_eswitch_del_offloaded_rule(esw, flow->rule[0], attr); + } + + struct mlx5_flow_handle * +@@ -1544,6 +1533,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, + else + mlx5e_tc_unoffload_fdb_rules(esw, flow, attr); + } ++ complete_all(&flow->del_hw_done); + + if (mlx5_flow_has_geneve_opt(flow)) + mlx5_geneve_tlv_option_del(priv->mdev->geneve); +@@ -1884,6 +1874,111 @@ u8 mlx5e_tc_get_ip_version(struct mlx5_flow_spec *spec, bool outer) + return ip_version; + } + ++/* Tunnel device follows RFC 6040, see include/net/inet_ecn.h. ++ * And changes inner ip_ecn depending on inner and outer ip_ecn as follows: ++ * +---------+----------------------------------------+ ++ * |Arriving | Arriving Outer Header | ++ * | Inner +---------+---------+---------+----------+ ++ * | Header | Not-ECT | ECT(0) | ECT(1) | CE | ++ * +---------+---------+---------+---------+----------+ ++ * | Not-ECT | Not-ECT | Not-ECT | Not-ECT | <drop> | ++ * | ECT(0) | ECT(0) | ECT(0) | ECT(1) | CE* | ++ * | ECT(1) | ECT(1) | ECT(1) | ECT(1)* | CE* | ++ * | CE | CE | CE | CE | CE | ++ * +---------+---------+---------+---------+----------+ ++ * ++ * Tc matches on inner after decapsulation on tunnel device, but hw offload matches ++ * the inner ip_ecn value before hardware decap action. ++ * ++ * Cells marked are changed from original inner packet ip_ecn value during decap, and ++ * so matching those values on inner ip_ecn before decap will fail. ++ * ++ * The following helper allows offload when inner ip_ecn won't be changed by outer ip_ecn, ++ * except for the outer ip_ecn = CE, where in all cases inner ip_ecn will be changed to CE, ++ * and such we can drop the inner ip_ecn=CE match. ++ */ ++ ++static int mlx5e_tc_verify_tunnel_ecn(struct mlx5e_priv *priv, ++ struct flow_cls_offload *f, ++ bool *match_inner_ecn) ++{ ++ u8 outer_ecn_mask = 0, outer_ecn_key = 0, inner_ecn_mask = 0, inner_ecn_key = 0; ++ struct flow_rule *rule = flow_cls_offload_flow_rule(f); ++ struct netlink_ext_ack *extack = f->common.extack; ++ struct flow_match_ip match; ++ ++ *match_inner_ecn = true; ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { ++ flow_rule_match_enc_ip(rule, &match); ++ outer_ecn_key = match.key->tos & INET_ECN_MASK; ++ outer_ecn_mask = match.mask->tos & INET_ECN_MASK; ++ } ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { ++ flow_rule_match_ip(rule, &match); ++ inner_ecn_key = match.key->tos & INET_ECN_MASK; ++ inner_ecn_mask = match.mask->tos & INET_ECN_MASK; ++ } ++ ++ if (outer_ecn_mask != 0 && outer_ecn_mask != INET_ECN_MASK) { ++ NL_SET_ERR_MSG_MOD(extack, "Partial match on enc_tos ecn bits isn't supported"); ++ netdev_warn(priv->netdev, "Partial match on enc_tos ecn bits isn't supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (!outer_ecn_mask) { ++ if (!inner_ecn_mask) ++ return 0; ++ ++ NL_SET_ERR_MSG_MOD(extack, ++ "Matching on tos ecn bits without also matching enc_tos ecn bits isn't supported"); ++ netdev_warn(priv->netdev, ++ "Matching on tos ecn bits without also matching enc_tos ecn bits isn't supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (inner_ecn_mask && inner_ecn_mask != INET_ECN_MASK) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "Partial match on tos ecn bits with match on enc_tos ecn bits isn't supported"); ++ netdev_warn(priv->netdev, ++ "Partial match on tos ecn bits with match on enc_tos ecn bits isn't supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (!inner_ecn_mask) ++ return 0; ++ ++ /* Both inner and outer have full mask on ecn */ ++ ++ if (outer_ecn_key == INET_ECN_ECT_1) { ++ /* inner ecn might change by DECAP action */ ++ ++ NL_SET_ERR_MSG_MOD(extack, "Match on enc_tos ecn = ECT(1) isn't supported"); ++ netdev_warn(priv->netdev, "Match on enc_tos ecn = ECT(1) isn't supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (outer_ecn_key != INET_ECN_CE) ++ return 0; ++ ++ if (inner_ecn_key != INET_ECN_CE) { ++ /* Can't happen in software, as packet ecn will be changed to CE after decap */ ++ NL_SET_ERR_MSG_MOD(extack, ++ "Match on tos enc_tos ecn = CE while match on tos ecn != CE isn't supported"); ++ netdev_warn(priv->netdev, ++ "Match on tos enc_tos ecn = CE while match on tos ecn != CE isn't supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* outer ecn = CE, inner ecn = CE, as decap will change inner ecn to CE in anycase, ++ * drop match on inner ecn ++ */ ++ *match_inner_ecn = false; ++ ++ return 0; ++} ++ + static int parse_tunnel_attr(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow, + struct mlx5_flow_spec *spec, +@@ -2077,6 +2172,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, + struct flow_rule *rule = flow_cls_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; + enum fs_flow_table_type fs_type; ++ bool match_inner_ecn = true; + u16 addr_type = 0; + u8 ip_proto = 0; + u8 *match_level; +@@ -2130,6 +2226,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, + headers_c = get_match_inner_headers_criteria(spec); + headers_v = get_match_inner_headers_value(spec); + } ++ ++ err = mlx5e_tc_verify_tunnel_ecn(priv, f, &match_inner_ecn); ++ if (err) ++ return err; + } + + err = mlx5e_flower_parse_meta(filter_dev, f); +@@ -2351,10 +2451,12 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, + struct flow_match_ip match; + + flow_rule_match_ip(rule, &match); +- MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, +- match.mask->tos & 0x3); +- MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, +- match.key->tos & 0x3); ++ if (match_inner_ecn) { ++ MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, ++ match.mask->tos & 0x3); ++ MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, ++ match.key->tos & 0x3); ++ } + + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, + match.mask->tos >> 2); +@@ -3457,7 +3559,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, + attr->dest_chain = act->chain_index; + break; + case FLOW_ACTION_CT: +- err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, act, extack); ++ err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, ++ &parse_attr->mod_hdr_acts, ++ act, extack); + if (err) + return err; + +@@ -4008,7 +4112,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, + NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported"); + return -EOPNOTSUPP; + } +- err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, act, extack); ++ err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, ++ &parse_attr->mod_hdr_acts, ++ act, extack); + if (err) + return err; + +@@ -4222,6 +4328,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, + INIT_LIST_HEAD(&flow->l3_to_l2_reformat); + refcount_set(&flow->refcnt, 1); + init_completion(&flow->init_done); ++ init_completion(&flow->del_hw_done); + + *__flow = flow; + *__parse_attr = parse_attr; +@@ -5008,9 +5115,7 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht) + MLX5_FLOW_NAMESPACE_FDB, + uplink_priv->post_act); + +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) + uplink_priv->tc_psample = mlx5e_tc_sample_init(esw, uplink_priv->post_act); +-#endif + + mapping_id = mlx5_query_nic_system_image_guid(esw->dev); + +@@ -5054,9 +5159,7 @@ err_ht_init: + err_enc_opts_mapping: + mapping_destroy(uplink_priv->tunnel_mapping); + err_tun_mapping: +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) + mlx5e_tc_sample_cleanup(uplink_priv->tc_psample); +-#endif + mlx5_tc_ct_clean(uplink_priv->ct_priv); + netdev_warn(priv->netdev, + "Failed to initialize tc (eswitch), err: %d", err); +@@ -5076,9 +5179,7 @@ void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht) + mapping_destroy(uplink_priv->tunnel_enc_opts_mapping); + mapping_destroy(uplink_priv->tunnel_mapping); + +-#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE) + mlx5e_tc_sample_cleanup(uplink_priv->tc_psample); +-#endif + mlx5_tc_ct_clean(uplink_priv->ct_priv); + mlx5e_tc_post_act_destroy(uplink_priv->post_act); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +index 188994d091c54..7fd33b356cc8d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +@@ -38,6 +38,7 @@ + #include "en/txrx.h" + #include "ipoib/ipoib.h" + #include "en_accel/en_accel.h" ++#include "en_accel/ipsec_rxtx.h" + #include "en/ptp.h" + + static void mlx5e_dma_unmap_wqe_err(struct mlx5e_txqsq *sq, u8 num_dma) +@@ -213,30 +214,13 @@ static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs) + memcpy(&vhdr->h_vlan_encapsulated_proto, skb->data + cpy1_sz, cpy2_sz); + } + +-static void +-ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, +- struct mlx5_wqe_eth_seg *eseg) +-{ +- struct xfrm_offload *xo = xfrm_offload(skb); +- +- eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM; +- if (xo->inner_ipproto) { +- eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM | MLX5_ETH_WQE_L3_INNER_CSUM; +- } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { +- eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM; +- sq->stats->csum_partial_inner++; +- } +-} +- + static inline void + mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, + struct mlx5e_accel_tx_state *accel, + struct mlx5_wqe_eth_seg *eseg) + { +- if (unlikely(mlx5e_ipsec_eseg_meta(eseg))) { +- ipsec_txwqe_build_eseg_csum(sq, skb, eseg); ++ if (unlikely(mlx5e_ipsec_txwqe_build_eseg_csum(sq, skb, eseg))) + return; +- } + + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { + eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +index 7e221038df8d5..317d76b97c42a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +@@ -1385,6 +1385,8 @@ struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw) + { + struct mlx5_esw_bridge_offloads *br_offloads; + ++ ASSERT_RTNL(); ++ + br_offloads = kvzalloc(sizeof(*br_offloads), GFP_KERNEL); + if (!br_offloads) + return ERR_PTR(-ENOMEM); +@@ -1401,6 +1403,8 @@ void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw) + { + struct mlx5_esw_bridge_offloads *br_offloads = esw->br_offloads; + ++ ASSERT_RTNL(); ++ + if (!br_offloads) + return; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/bridge_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/bridge_tracepoint.h +index 3401188e0a602..51ac24e6ec3c3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/bridge_tracepoint.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/diag/bridge_tracepoint.h +@@ -21,7 +21,7 @@ DECLARE_EVENT_CLASS(mlx5_esw_bridge_fdb_template, + __field(unsigned int, used) + ), + TP_fast_assign( +- strncpy(__entry->dev_name, ++ strscpy(__entry->dev_name, + netdev_name(fdb->dev), + IFNAMSIZ); + memcpy(__entry->addr, fdb->key.addr, ETH_ALEN); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +index df277a6cddc0b..0c4c743ca31e1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +@@ -431,7 +431,7 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, + int err = 0; + + if (!mlx5_esw_allowed(esw)) +- return -EPERM; ++ return vlan ? -EPERM : 0; + + if (vlan || qos) + set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c +index c6cc67cb4f6ad..d377ddc70fc70 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c +@@ -130,7 +130,7 @@ static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw, + /* If vports min rate divider is 0 but their group has bw_share configured, then + * need to set bw_share for vports to minimal value. + */ +- if (!group_level && !max_guarantee && group->bw_share) ++ if (!group_level && !max_guarantee && group && group->bw_share) + return 1; + return 0; + } +@@ -423,7 +423,7 @@ static int esw_qos_vport_update_group(struct mlx5_eswitch *esw, + return err; + + /* Recalculate bw share weights of old and new groups */ +- if (vport->qos.bw_share) { ++ if (vport->qos.bw_share || new_group->bw_share) { + esw_qos_normalize_vports_min_rate(esw, curr_group, extack); + esw_qos_normalize_vports_min_rate(esw, new_group, extack); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +index ec136b4992045..51a8cecc4a7ce 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +@@ -1305,12 +1305,17 @@ abort: + */ + int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) + { ++ bool toggle_lag; + int ret; + + if (!mlx5_esw_allowed(esw)) + return 0; + +- mlx5_lag_disable_change(esw->dev); ++ toggle_lag = esw->mode == MLX5_ESWITCH_NONE; ++ ++ if (toggle_lag) ++ mlx5_lag_disable_change(esw->dev); ++ + down_write(&esw->mode_lock); + if (esw->mode == MLX5_ESWITCH_NONE) { + ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs); +@@ -1324,7 +1329,10 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) + esw->esw_funcs.num_vfs = num_vfs; + } + up_write(&esw->mode_lock); +- mlx5_lag_enable_change(esw->dev); ++ ++ if (toggle_lag) ++ mlx5_lag_enable_change(esw->dev); ++ + return ret; + } + +@@ -1572,6 +1580,11 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) + esw->enabled_vports = 0; + esw->mode = MLX5_ESWITCH_NONE; + esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; ++ if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) && ++ MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)) ++ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; ++ else ++ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; + + dev->priv.eswitch = esw; + BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); +@@ -1934,7 +1947,7 @@ free_out: + return err; + } + +-u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev) ++u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) + { + struct mlx5_eswitch *esw = dev->priv.eswitch; + +@@ -1948,7 +1961,7 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) + struct mlx5_eswitch *esw; + + esw = dev->priv.eswitch; +- return mlx5_esw_allowed(esw) ? esw->offloads.encap : ++ return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS) ? esw->offloads.encap : + DEVLINK_ESWITCH_ENCAP_MODE_NONE; + } + EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 0d461e38add37..3194cdcd2f630 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -2471,6 +2471,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, + struct mlx5_eswitch *esw = master->priv.eswitch; + struct mlx5_flow_table_attr ft_attr = { + .max_fte = 1, .prio = 0, .level = 0, ++ .flags = MLX5_FLOW_TABLE_OTHER_VPORT, + }; + struct mlx5_flow_namespace *egress_ns; + struct mlx5_flow_table *acl; +@@ -2783,10 +2784,6 @@ bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw) + if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source)) + return false; + +- if (mlx5_core_is_ecpf_esw_manager(esw->dev) || +- mlx5_ecpf_vport_exists(esw->dev)) +- return false; +- + return true; + } + +@@ -3141,12 +3138,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) + u64 mapping_id; + int err; + +- if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat) && +- MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, decap)) +- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; +- else +- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; +- + mutex_init(&esw->offloads.termtbl_mutex); + mlx5_rdma_enable_roce(esw->dev); + +@@ -3244,7 +3235,6 @@ void esw_offloads_disable(struct mlx5_eswitch *esw) + esw_offloads_metadata_uninit(esw); + mlx5_rdma_disable_roce(esw->dev); + mutex_destroy(&esw->offloads.termtbl_mutex); +- esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; + } + + static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode) +@@ -3588,7 +3578,7 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, + *encap = esw->offloads.encap; + unlock: + up_write(&esw->mode_lock); +- return 0; ++ return err; + } + + static bool +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index fe501ba88bea9..00834c914dc64 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -2041,6 +2041,8 @@ void mlx5_del_flow_rules(struct mlx5_flow_handle *handle) + fte->node.del_hw_func = NULL; + up_write_ref_node(&fte->node, false); + tree_put_node(&fte->node, false); ++ } else { ++ up_write_ref_node(&fte->node, false); + } + kfree(handle); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +index 106b50e42b464..a45c6f25add16 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +@@ -131,7 +131,7 @@ static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) + { + struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; + +- del_timer(&fw_reset->timer); ++ del_timer_sync(&fw_reset->timer); + } + + static void mlx5_sync_reset_clear_reset_requested(struct mlx5_core_dev *dev, bool poll_health) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +index 269ebb53eda67..cfde0a45b8b8a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +@@ -67,7 +67,7 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, + MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE : + MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE; + +- params->lro_en = false; ++ params->packet_merge.type = MLX5E_PACKET_MERGE_NONE; + params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; + params->tunneled_offload_en = false; + } +@@ -353,7 +353,6 @@ static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv) + static int mlx5i_init_rx(struct mlx5e_priv *priv) + { + struct mlx5_core_dev *mdev = priv->mdev; +- struct mlx5e_lro_param lro_param; + int err; + + priv->rx_res = mlx5e_rx_res_alloc(); +@@ -368,9 +367,9 @@ static int mlx5i_init_rx(struct mlx5e_priv *priv) + goto err_destroy_q_counters; + } + +- lro_param = mlx5e_get_lro_param(&priv->channels.params); + err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, +- priv->max_nch, priv->drop_rq.rqn, &lro_param, ++ priv->max_nch, priv->drop_rq.rqn, ++ &priv->channels.params.packet_merge, + priv->channels.params.num_channels); + if (err) + goto err_close_drop_rq; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c +index d2105c1635c34..c19d9327095b2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c +@@ -565,6 +565,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, + bool is_bonded, is_in_lag, mode_supported; + int bond_status = 0; + int num_slaves = 0; ++ int changed = 0; + int idx; + + if (!netif_is_lag_master(upper)) +@@ -601,27 +602,27 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, + */ + is_in_lag = num_slaves == MLX5_MAX_PORTS && bond_status == 0x3; + +- if (!mlx5_lag_is_ready(ldev) && is_in_lag) { +- NL_SET_ERR_MSG_MOD(info->info.extack, +- "Can't activate LAG offload, PF is configured with more than 64 VFs"); +- return 0; +- } +- + /* Lag mode must be activebackup or hash. */ + mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP || + tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH; + +- if (is_in_lag && !mode_supported) +- NL_SET_ERR_MSG_MOD(info->info.extack, +- "Can't activate LAG offload, TX type isn't supported"); +- + is_bonded = is_in_lag && mode_supported; + if (tracker->is_bonded != is_bonded) { + tracker->is_bonded = is_bonded; +- return 1; ++ changed = 1; + } + +- return 0; ++ if (!is_in_lag) ++ return changed; ++ ++ if (!mlx5_lag_is_ready(ldev)) ++ NL_SET_ERR_MSG_MOD(info->info.extack, ++ "Can't activate LAG offload, PF is configured with more than 64 VFs"); ++ else if (!mode_supported) ++ NL_SET_ERR_MSG_MOD(info->info.extack, ++ "Can't activate LAG offload, TX type isn't supported"); ++ ++ return changed; + } + + static int mlx5_handle_changelowerstate_event(struct mlx5_lag *ldev, +@@ -664,9 +665,6 @@ static int mlx5_lag_netdev_event(struct notifier_block *this, + + ldev = container_of(this, struct mlx5_lag, nb); + +- if (!mlx5_lag_is_ready(ldev) && event == NETDEV_CHANGELOWERSTATE) +- return NOTIFY_DONE; +- + tracker = ldev->tracker; + + switch (event) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c +index 21fdaf708f1fe..30282d86e6b96 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c +@@ -268,10 +268,8 @@ static int mlx5_lag_fib_event(struct notifier_block *nb, + fen_info = container_of(info, struct fib_entry_notifier_info, + info); + fi = fen_info->fi; +- if (fi->nh) { +- NL_SET_ERR_MSG_MOD(info->extack, "IPv4 route with nexthop objects is not supported"); +- return notifier_from_errno(-EINVAL); +- } ++ if (fi->nh) ++ return NOTIFY_DONE; + fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev; + if (fib_dev != ldev->pf[MLX5_LAG_P1].netdev && + fib_dev != ldev->pf[MLX5_LAG_P2].netdev) { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +index 97e5845b4cfdd..1e8ec4f236b28 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +@@ -121,9 +121,16 @@ u32 mlx5_chains_get_nf_ft_chain(struct mlx5_fs_chains *chains) + + u32 mlx5_chains_get_prio_range(struct mlx5_fs_chains *chains) + { ++ if (!mlx5_chains_prios_supported(chains)) ++ return 1; ++ + if (mlx5_chains_ignore_flow_level_supported(chains)) + return UINT_MAX; + ++ if (!chains->dev->priv.eswitch || ++ chains->dev->priv.eswitch->mode != MLX5_ESWITCH_OFFLOADS) ++ return 1; ++ + /* We should get here only for eswitch case */ + return FDB_TC_MAX_PRIO; + } +@@ -208,7 +215,7 @@ static int + create_chain_restore(struct fs_chain *chain) + { + struct mlx5_eswitch *esw = chain->chains->dev->priv.eswitch; +- char modact[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)]; ++ u8 modact[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; + struct mlx5_fs_chains *chains = chain->chains; + enum mlx5e_tc_attr_to_reg chain_to_reg; + struct mlx5_modify_hdr *mod_hdr; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 79482824c64ff..097ab6fe371ca 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -97,6 +97,8 @@ enum { + MLX5_ATOMIC_REQ_MODE_HOST_ENDIANNESS = 0x1, + }; + ++#define LOG_MAX_SUPPORTED_QPS 0xff ++ + static struct mlx5_profile profile[] = { + [0] = { + .mask = 0, +@@ -108,7 +110,7 @@ static struct mlx5_profile profile[] = { + [2] = { + .mask = MLX5_PROF_MASK_QP_SIZE | + MLX5_PROF_MASK_MR_CACHE, +- .log_max_qp = 18, ++ .log_max_qp = LOG_MAX_SUPPORTED_QPS, + .mr_cache[0] = { + .size = 500, + .limit = 250 +@@ -513,7 +515,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) + to_fw_pkey_sz(dev, 128)); + + /* Check log_max_qp from HCA caps to set in current profile */ +- if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < prof->log_max_qp) { ++ if (prof->log_max_qp == LOG_MAX_SUPPORTED_QPS) { ++ prof->log_max_qp = min_t(u8, 17, MLX5_CAP_GEN_MAX(dev, log_max_qp)); ++ } else if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < prof->log_max_qp) { + mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n", + prof->log_max_qp, + MLX5_CAP_GEN_MAX(dev, log_max_qp)); +@@ -1537,6 +1541,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id) + dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err); + + pci_save_state(pdev); ++ devlink_register(devlink); + if (!mlx5_core_is_mp_slave(dev)) + devlink_reload_enable(devlink); + return 0; +@@ -1559,6 +1564,7 @@ static void remove_one(struct pci_dev *pdev) + struct devlink *devlink = priv_to_devlink(dev); + + devlink_reload_disable(devlink); ++ devlink_unregister(devlink); + mlx5_crdump_disable(dev); + mlx5_drain_health_wq(dev); + mlx5_uninit_one(dev); +@@ -1756,10 +1762,12 @@ static const struct pci_device_id mlx5_core_pci_table[] = { + { PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */ + { PCI_VDEVICE(MELLANOX, 0x101f) }, /* ConnectX-6 LX */ + { PCI_VDEVICE(MELLANOX, 0x1021) }, /* ConnectX-7 */ ++ { PCI_VDEVICE(MELLANOX, 0x1023) }, /* ConnectX-8 */ + { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ + { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ + { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */ + { PCI_VDEVICE(MELLANOX, 0xa2dc) }, /* BlueField-3 integrated ConnectX-7 network controller */ ++ { PCI_VDEVICE(MELLANOX, 0xa2df) }, /* BlueField-4 integrated ConnectX-8 network controller */ + { 0, } + }; + +@@ -1773,12 +1781,13 @@ void mlx5_disable_device(struct mlx5_core_dev *dev) + + int mlx5_recover_device(struct mlx5_core_dev *dev) + { +- int ret = -EIO; ++ if (!mlx5_core_is_sf(dev)) { ++ mlx5_pci_disable_device(dev); ++ if (mlx5_pci_slot_reset(dev->pdev) != PCI_ERS_RESULT_RECOVERED) ++ return -EIO; ++ } + +- mlx5_pci_disable_device(dev); +- if (mlx5_pci_slot_reset(dev->pdev) == PCI_ERS_RESULT_RECOVERED) +- ret = mlx5_load_one(dev); +- return ret; ++ return mlx5_load_one(dev); + } + + static struct pci_driver mlx5_core_driver = { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +index 763c83a023809..11f3649fdaab1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +@@ -346,8 +346,8 @@ static struct mlx5_irq *irq_pool_request_affinity(struct mlx5_irq_pool *pool, + new_irq = irq_pool_create_irq(pool, affinity); + if (IS_ERR(new_irq)) { + if (!least_loaded_irq) { +- mlx5_core_err(pool->dev, "Didn't find IRQ for cpu = %u\n", +- cpumask_first(affinity)); ++ mlx5_core_err(pool->dev, "Didn't find a matching IRQ. err = %ld\n", ++ PTR_ERR(new_irq)); + mutex_unlock(&pool->lock); + return new_irq; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index 1ef2b6a848c10..7b16a1188aabb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -406,23 +406,24 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + + switch (module_id) { + case MLX5_MODULE_ID_SFP: +- mlx5_sfp_eeprom_params_set(&query.i2c_address, &query.page, &query.offset); ++ mlx5_sfp_eeprom_params_set(&query.i2c_address, &query.page, &offset); + break; + case MLX5_MODULE_ID_QSFP: + case MLX5_MODULE_ID_QSFP_PLUS: + case MLX5_MODULE_ID_QSFP28: +- mlx5_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &query.offset); ++ mlx5_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset); + break; + default: + mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id); + return -EINVAL; + } + +- if (query.offset + size > MLX5_EEPROM_PAGE_LENGTH) ++ if (offset + size > MLX5_EEPROM_PAGE_LENGTH) + /* Cross pages read, read until offset 256 in low page */ +- size -= offset + size - MLX5_EEPROM_PAGE_LENGTH; ++ size = MLX5_EEPROM_PAGE_LENGTH - offset; + + query.size = size; ++ query.offset = offset; + + return mlx5_query_mcia(dev, &query, data); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +index 871c2fbe18d39..64bbc18332d56 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c +@@ -28,10 +28,7 @@ bool mlx5_sf_dev_allocated(const struct mlx5_core_dev *dev) + { + struct mlx5_sf_dev_table *table = dev->priv.sf_dev_table; + +- if (!mlx5_sf_dev_supported(dev)) +- return false; +- +- return !xa_empty(&table->devices); ++ return table && !xa_empty(&table->devices); + } + + static ssize_t sfnum_show(struct device *dev, struct device_attribute *attr, char *buf) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +index 052f48068dc16..3cf272fa21646 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +@@ -46,6 +46,7 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia + mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err); + goto init_one_err; + } ++ devlink_register(devlink); + devlink_reload_enable(devlink); + return 0; + +@@ -65,6 +66,7 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev) + + devlink = priv_to_devlink(sf_dev->mdev); + devlink_reload_disable(devlink); ++ devlink_unregister(devlink); + mlx5_uninit_one(sf_dev->mdev); + iounmap(sf_dev->mdev->iseg); + mlx5_mdev_uninit(sf_dev->mdev); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c +index 0fe159809ba15..ea1b8ca5bf3aa 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c +@@ -2,6 +2,7 @@ + /* Copyright (c) 2019 Mellanox Technologies. */ + + #include <linux/mlx5/eswitch.h> ++#include <linux/err.h> + #include "dr_types.h" + + #define DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, dmn_type) \ +@@ -75,9 +76,9 @@ static int dr_domain_init_resources(struct mlx5dr_domain *dmn) + } + + dmn->uar = mlx5_get_uars_page(dmn->mdev); +- if (!dmn->uar) { ++ if (IS_ERR(dmn->uar)) { + mlx5dr_err(dmn, "Couldn't allocate UAR\n"); +- ret = -ENOMEM; ++ ret = PTR_ERR(dmn->uar); + goto clean_pd; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c +index 66c24767e3b00..8ad8d73e17f06 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c +@@ -4,7 +4,6 @@ + #include "dr_types.h" + + #define DR_ICM_MODIFY_HDR_ALIGN_BASE 64 +-#define DR_ICM_SYNC_THRESHOLD_POOL (64 * 1024 * 1024) + + struct mlx5dr_icm_pool { + enum mlx5dr_icm_type icm_type; +@@ -136,37 +135,35 @@ static void dr_icm_pool_mr_destroy(struct mlx5dr_icm_mr *icm_mr) + kvfree(icm_mr); + } + +-static int dr_icm_chunk_ste_init(struct mlx5dr_icm_chunk *chunk) ++static int dr_icm_buddy_get_ste_size(struct mlx5dr_icm_buddy_mem *buddy) + { +- chunk->ste_arr = kvzalloc(chunk->num_of_entries * +- sizeof(chunk->ste_arr[0]), GFP_KERNEL); +- if (!chunk->ste_arr) +- return -ENOMEM; +- +- chunk->hw_ste_arr = kvzalloc(chunk->num_of_entries * +- DR_STE_SIZE_REDUCED, GFP_KERNEL); +- if (!chunk->hw_ste_arr) +- goto out_free_ste_arr; +- +- chunk->miss_list = kvmalloc(chunk->num_of_entries * +- sizeof(chunk->miss_list[0]), GFP_KERNEL); +- if (!chunk->miss_list) +- goto out_free_hw_ste_arr; ++ /* We support only one type of STE size, both for ConnectX-5 and later ++ * devices. Once the support for match STE which has a larger tag is ++ * added (32B instead of 16B), the STE size for devices later than ++ * ConnectX-5 needs to account for that. ++ */ ++ return DR_STE_SIZE_REDUCED; ++} + +- return 0; ++static void dr_icm_chunk_ste_init(struct mlx5dr_icm_chunk *chunk, int offset) ++{ ++ struct mlx5dr_icm_buddy_mem *buddy = chunk->buddy_mem; ++ int index = offset / DR_STE_SIZE; + +-out_free_hw_ste_arr: +- kvfree(chunk->hw_ste_arr); +-out_free_ste_arr: +- kvfree(chunk->ste_arr); +- return -ENOMEM; ++ chunk->ste_arr = &buddy->ste_arr[index]; ++ chunk->miss_list = &buddy->miss_list[index]; ++ chunk->hw_ste_arr = buddy->hw_ste_arr + ++ index * dr_icm_buddy_get_ste_size(buddy); + } + + static void dr_icm_chunk_ste_cleanup(struct mlx5dr_icm_chunk *chunk) + { +- kvfree(chunk->miss_list); +- kvfree(chunk->hw_ste_arr); +- kvfree(chunk->ste_arr); ++ struct mlx5dr_icm_buddy_mem *buddy = chunk->buddy_mem; ++ ++ memset(chunk->hw_ste_arr, 0, ++ chunk->num_of_entries * dr_icm_buddy_get_ste_size(buddy)); ++ memset(chunk->ste_arr, 0, ++ chunk->num_of_entries * sizeof(chunk->ste_arr[0])); + } + + static enum mlx5dr_icm_type +@@ -189,6 +186,44 @@ static void dr_icm_chunk_destroy(struct mlx5dr_icm_chunk *chunk, + kvfree(chunk); + } + ++static int dr_icm_buddy_init_ste_cache(struct mlx5dr_icm_buddy_mem *buddy) ++{ ++ int num_of_entries = ++ mlx5dr_icm_pool_chunk_size_to_entries(buddy->pool->max_log_chunk_sz); ++ ++ buddy->ste_arr = kvcalloc(num_of_entries, ++ sizeof(struct mlx5dr_ste), GFP_KERNEL); ++ if (!buddy->ste_arr) ++ return -ENOMEM; ++ ++ /* Preallocate full STE size on non-ConnectX-5 devices since ++ * we need to support both full and reduced with the same cache. ++ */ ++ buddy->hw_ste_arr = kvcalloc(num_of_entries, ++ dr_icm_buddy_get_ste_size(buddy), GFP_KERNEL); ++ if (!buddy->hw_ste_arr) ++ goto free_ste_arr; ++ ++ buddy->miss_list = kvmalloc(num_of_entries * sizeof(struct list_head), GFP_KERNEL); ++ if (!buddy->miss_list) ++ goto free_hw_ste_arr; ++ ++ return 0; ++ ++free_hw_ste_arr: ++ kvfree(buddy->hw_ste_arr); ++free_ste_arr: ++ kvfree(buddy->ste_arr); ++ return -ENOMEM; ++} ++ ++static void dr_icm_buddy_cleanup_ste_cache(struct mlx5dr_icm_buddy_mem *buddy) ++{ ++ kvfree(buddy->ste_arr); ++ kvfree(buddy->hw_ste_arr); ++ kvfree(buddy->miss_list); ++} ++ + static int dr_icm_buddy_create(struct mlx5dr_icm_pool *pool) + { + struct mlx5dr_icm_buddy_mem *buddy; +@@ -208,11 +243,19 @@ static int dr_icm_buddy_create(struct mlx5dr_icm_pool *pool) + buddy->icm_mr = icm_mr; + buddy->pool = pool; + ++ if (pool->icm_type == DR_ICM_TYPE_STE) { ++ /* Reduce allocations by preallocating and reusing the STE structures */ ++ if (dr_icm_buddy_init_ste_cache(buddy)) ++ goto err_cleanup_buddy; ++ } ++ + /* add it to the -start- of the list in order to search in it first */ + list_add(&buddy->list_node, &pool->buddy_mem_list); + + return 0; + ++err_cleanup_buddy: ++ mlx5dr_buddy_cleanup(buddy); + err_free_buddy: + kvfree(buddy); + free_mr: +@@ -234,6 +277,9 @@ static void dr_icm_buddy_destroy(struct mlx5dr_icm_buddy_mem *buddy) + + mlx5dr_buddy_cleanup(buddy); + ++ if (buddy->pool->icm_type == DR_ICM_TYPE_STE) ++ dr_icm_buddy_cleanup_ste_cache(buddy); ++ + kvfree(buddy); + } + +@@ -261,34 +307,30 @@ dr_icm_chunk_create(struct mlx5dr_icm_pool *pool, + chunk->byte_size = + mlx5dr_icm_pool_chunk_size_to_byte(chunk_size, pool->icm_type); + chunk->seg = seg; ++ chunk->buddy_mem = buddy_mem_pool; + +- if (pool->icm_type == DR_ICM_TYPE_STE && dr_icm_chunk_ste_init(chunk)) { +- mlx5dr_err(pool->dmn, +- "Failed to init ste arrays (order: %d)\n", +- chunk_size); +- goto out_free_chunk; +- } ++ if (pool->icm_type == DR_ICM_TYPE_STE) ++ dr_icm_chunk_ste_init(chunk, offset); + + buddy_mem_pool->used_memory += chunk->byte_size; +- chunk->buddy_mem = buddy_mem_pool; + INIT_LIST_HEAD(&chunk->chunk_list); + + /* chunk now is part of the used_list */ + list_add_tail(&chunk->chunk_list, &buddy_mem_pool->used_list); + + return chunk; +- +-out_free_chunk: +- kvfree(chunk); +- return NULL; + } + + static bool dr_icm_pool_is_sync_required(struct mlx5dr_icm_pool *pool) + { +- if (pool->hot_memory_size > DR_ICM_SYNC_THRESHOLD_POOL) +- return true; ++ int allow_hot_size; ++ ++ /* sync when hot memory reaches half of the pool size */ ++ allow_hot_size = ++ mlx5dr_icm_pool_chunk_size_to_byte(pool->max_log_chunk_sz, ++ pool->icm_type) / 2; + +- return false; ++ return pool->hot_memory_size > allow_hot_size; + } + + static int dr_icm_pool_sync_all_buddy_pools(struct mlx5dr_icm_pool *pool) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c +index b5409cc021d33..a19e8157c1002 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c +@@ -13,18 +13,6 @@ static bool dr_mask_is_dmac_set(struct mlx5dr_match_spec *spec) + return (spec->dmac_47_16 || spec->dmac_15_0); + } + +-static bool dr_mask_is_src_addr_set(struct mlx5dr_match_spec *spec) +-{ +- return (spec->src_ip_127_96 || spec->src_ip_95_64 || +- spec->src_ip_63_32 || spec->src_ip_31_0); +-} +- +-static bool dr_mask_is_dst_addr_set(struct mlx5dr_match_spec *spec) +-{ +- return (spec->dst_ip_127_96 || spec->dst_ip_95_64 || +- spec->dst_ip_63_32 || spec->dst_ip_31_0); +-} +- + static bool dr_mask_is_l3_base_set(struct mlx5dr_match_spec *spec) + { + return (spec->ip_protocol || spec->frag || spec->tcp_flags || +@@ -480,11 +468,11 @@ static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher, + &mask, inner, rx); + + if (outer_ipv == DR_RULE_IPV6) { +- if (dr_mask_is_dst_addr_set(&mask.outer)) ++ if (DR_MASK_IS_DST_IP_SET(&mask.outer)) + mlx5dr_ste_build_eth_l3_ipv6_dst(ste_ctx, &sb[idx++], + &mask, inner, rx); + +- if (dr_mask_is_src_addr_set(&mask.outer)) ++ if (DR_MASK_IS_SRC_IP_SET(&mask.outer)) + mlx5dr_ste_build_eth_l3_ipv6_src(ste_ctx, &sb[idx++], + &mask, inner, rx); + +@@ -580,11 +568,11 @@ static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher, + &mask, inner, rx); + + if (inner_ipv == DR_RULE_IPV6) { +- if (dr_mask_is_dst_addr_set(&mask.inner)) ++ if (DR_MASK_IS_DST_IP_SET(&mask.inner)) + mlx5dr_ste_build_eth_l3_ipv6_dst(ste_ctx, &sb[idx++], + &mask, inner, rx); + +- if (dr_mask_is_src_addr_set(&mask.inner)) ++ if (DR_MASK_IS_SRC_IP_SET(&mask.inner)) + mlx5dr_ste_build_eth_l3_ipv6_src(ste_ctx, &sb[idx++], + &mask, inner, rx); + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c +index 1cdfe4fccc7a9..01246a1ae7d13 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c +@@ -602,12 +602,34 @@ int mlx5dr_ste_set_action_decap_l3_list(struct mlx5dr_ste_ctx *ste_ctx, + used_hw_action_num); + } + ++static int dr_ste_build_pre_check_spec(struct mlx5dr_domain *dmn, ++ struct mlx5dr_match_spec *spec) ++{ ++ if (spec->ip_version) { ++ if (spec->ip_version != 0xf) { ++ mlx5dr_err(dmn, ++ "Partial ip_version mask with src/dst IP is not supported\n"); ++ return -EINVAL; ++ } ++ } else if (spec->ethertype != 0xffff && ++ (DR_MASK_IS_SRC_IP_SET(spec) || DR_MASK_IS_DST_IP_SET(spec))) { ++ mlx5dr_err(dmn, ++ "Partial/no ethertype mask with src/dst IP is not supported\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + int mlx5dr_ste_build_pre_check(struct mlx5dr_domain *dmn, + u8 match_criteria, + struct mlx5dr_match_param *mask, + struct mlx5dr_match_param *value) + { +- if (!value && (match_criteria & DR_MATCHER_CRITERIA_MISC)) { ++ if (value) ++ return 0; ++ ++ if (match_criteria & DR_MATCHER_CRITERIA_MISC) { + if (mask->misc.source_port && mask->misc.source_port != 0xffff) { + mlx5dr_err(dmn, + "Partial mask source_port is not supported\n"); +@@ -621,6 +643,14 @@ int mlx5dr_ste_build_pre_check(struct mlx5dr_domain *dmn, + } + } + ++ if ((match_criteria & DR_MATCHER_CRITERIA_OUTER) && ++ dr_ste_build_pre_check_spec(dmn, &mask->outer)) ++ return -EINVAL; ++ ++ if ((match_criteria & DR_MATCHER_CRITERIA_INNER) && ++ dr_ste_build_pre_check_spec(dmn, &mask->inner)) ++ return -EINVAL; ++ + return 0; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h +index b20e8aabb861b..3d4e035698dd3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h +@@ -740,6 +740,16 @@ struct mlx5dr_match_param { + (_misc3)->icmpv4_code || \ + (_misc3)->icmpv4_header_data) + ++#define DR_MASK_IS_SRC_IP_SET(_spec) ((_spec)->src_ip_127_96 || \ ++ (_spec)->src_ip_95_64 || \ ++ (_spec)->src_ip_63_32 || \ ++ (_spec)->src_ip_31_0) ++ ++#define DR_MASK_IS_DST_IP_SET(_spec) ((_spec)->dst_ip_127_96 || \ ++ (_spec)->dst_ip_95_64 || \ ++ (_spec)->dst_ip_63_32 || \ ++ (_spec)->dst_ip_31_0) ++ + struct mlx5dr_esw_caps { + u64 drop_icm_address_rx; + u64 drop_icm_address_tx; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h +index c5a8b16019991..5ef1995434794 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h +@@ -160,6 +160,11 @@ struct mlx5dr_icm_buddy_mem { + * sync_ste command sets them free. + */ + struct list_head hot_list; ++ ++ /* Memory optimisation */ ++ struct mlx5dr_ste *ste_arr; ++ struct list_head *miss_list; ++ u8 *hw_ste_arr; + }; + + int mlx5dr_buddy_init(struct mlx5dr_icm_buddy_mem *buddy, +diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h +index 392ce3cb27f72..51b260d54237e 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h ++++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h +@@ -935,6 +935,18 @@ static inline int mlxsw_cmd_sw2hw_rdq(struct mlxsw_core *mlxsw_core, + */ + MLXSW_ITEM32(cmd_mbox, sw2hw_dq, cq, 0x00, 24, 8); + ++enum mlxsw_cmd_mbox_sw2hw_dq_sdq_lp { ++ MLXSW_CMD_MBOX_SW2HW_DQ_SDQ_LP_WQE, ++ MLXSW_CMD_MBOX_SW2HW_DQ_SDQ_LP_IGNORE_WQE, ++}; ++ ++/* cmd_mbox_sw2hw_dq_sdq_lp ++ * SDQ local Processing ++ * 0: local processing by wqe.lp ++ * 1: local processing (ignoring wqe.lp) ++ */ ++MLXSW_ITEM32(cmd_mbox, sw2hw_dq, sdq_lp, 0x00, 23, 1); ++ + /* cmd_mbox_sw2hw_dq_sdq_tclass + * SDQ: CPU Egress TClass + * RDQ: Reserved +diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c +index fcace73eae40f..d9f9cbba62465 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c +@@ -285,6 +285,7 @@ static int mlxsw_pci_sdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, + struct mlxsw_pci_queue *q) + { + int tclass; ++ int lp; + int i; + int err; + +@@ -292,9 +293,12 @@ static int mlxsw_pci_sdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, + q->consumer_counter = 0; + tclass = q->num == MLXSW_PCI_SDQ_EMAD_INDEX ? MLXSW_PCI_SDQ_EMAD_TC : + MLXSW_PCI_SDQ_CTL_TC; ++ lp = q->num == MLXSW_PCI_SDQ_EMAD_INDEX ? MLXSW_CMD_MBOX_SW2HW_DQ_SDQ_LP_IGNORE_WQE : ++ MLXSW_CMD_MBOX_SW2HW_DQ_SDQ_LP_WQE; + + /* Set CQ of same number of this SDQ. */ + mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, q->num); ++ mlxsw_cmd_mbox_sw2hw_dq_sdq_lp_set(mbox, lp); + mlxsw_cmd_mbox_sw2hw_dq_sdq_tclass_set(mbox, tclass); + mlxsw_cmd_mbox_sw2hw_dq_log2_dq_sz_set(mbox, 3); /* 8 pages */ + for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { +@@ -1678,7 +1682,7 @@ static int mlxsw_pci_skb_transmit(void *bus_priv, struct sk_buff *skb, + + wqe = elem_info->elem; + mlxsw_pci_wqe_c_set(wqe, 1); /* always report completion */ +- mlxsw_pci_wqe_lp_set(wqe, !!tx_info->is_emad); ++ mlxsw_pci_wqe_lp_set(wqe, 0); + mlxsw_pci_wqe_type_set(wqe, MLXSW_PCI_WQE_TYPE_ETHERNET); + + err = mlxsw_pci_wqe_frag_map(mlxsw_pci, wqe, 0, skb->data, +@@ -1973,6 +1977,7 @@ int mlxsw_pci_driver_register(struct pci_driver *pci_driver) + { + pci_driver->probe = mlxsw_pci_probe; + pci_driver->remove = mlxsw_pci_remove; ++ pci_driver->shutdown = mlxsw_pci_remove; + return pci_register_driver(pci_driver); + } + EXPORT_SYMBOL(mlxsw_pci_driver_register); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +index 250c5a24264dc..edfdd44de579c 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +@@ -2131,7 +2131,7 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, + max_ports = mlxsw_core_max_ports(mlxsw_sp->core); + local_port = mlxsw_reg_pude_local_port_get(pude_pl); + +- if (WARN_ON_ONCE(local_port >= max_ports)) ++ if (WARN_ON_ONCE(!local_port || local_port >= max_ports)) + return; + mlxsw_sp_port = mlxsw_sp->ports[local_port]; + if (!mlxsw_sp_port) +diff --git a/drivers/net/ethernet/micrel/ks8851_par.c b/drivers/net/ethernet/micrel/ks8851_par.c +index 2e8fcce50f9d1..c6f517c07bb9a 100644 +--- a/drivers/net/ethernet/micrel/ks8851_par.c ++++ b/drivers/net/ethernet/micrel/ks8851_par.c +@@ -321,6 +321,8 @@ static int ks8851_probe_par(struct platform_device *pdev) + return ret; + + netdev->irq = platform_get_irq(pdev, 0); ++ if (netdev->irq < 0) ++ return netdev->irq; + + return ks8851_probe_common(netdev, dev, msg_enable); + } +diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c +index 4d5a5d6595b3b..d64ce65a3c174 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -914,8 +914,7 @@ static int lan743x_phy_reset(struct lan743x_adapter *adapter) + } + + static void lan743x_phy_update_flowcontrol(struct lan743x_adapter *adapter, +- u8 duplex, u16 local_adv, +- u16 remote_adv) ++ u16 local_adv, u16 remote_adv) + { + struct lan743x_phy *phy = &adapter->phy; + u8 cap; +@@ -943,7 +942,6 @@ static void lan743x_phy_link_status_change(struct net_device *netdev) + + phy_print_status(phydev); + if (phydev->state == PHY_RUNNING) { +- struct ethtool_link_ksettings ksettings; + int remote_advertisement = 0; + int local_advertisement = 0; + +@@ -980,18 +978,14 @@ static void lan743x_phy_link_status_change(struct net_device *netdev) + } + lan743x_csr_write(adapter, MAC_CR, data); + +- memset(&ksettings, 0, sizeof(ksettings)); +- phy_ethtool_get_link_ksettings(netdev, &ksettings); + local_advertisement = + linkmode_adv_to_mii_adv_t(phydev->advertising); + remote_advertisement = + linkmode_adv_to_mii_adv_t(phydev->lp_advertising); + +- lan743x_phy_update_flowcontrol(adapter, +- ksettings.base.duplex, +- local_advertisement, ++ lan743x_phy_update_flowcontrol(adapter, local_advertisement, + remote_advertisement); +- lan743x_ptp_update_latency(adapter, ksettings.base.speed); ++ lan743x_ptp_update_latency(adapter, phydev->speed); + } + } + +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c +index 59783fc46a7b9..10b866e9f7266 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ethtool.c +@@ -1103,7 +1103,7 @@ void sparx5_get_stats64(struct net_device *ndev, + stats->tx_carrier_errors = portstats[spx5_stats_tx_csense_cnt]; + stats->tx_window_errors = portstats[spx5_stats_tx_late_coll_cnt]; + stats->rx_dropped = portstats[spx5_stats_ana_ac_port_stat_lsb_cnt]; +- for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx, ++stats) ++ for (idx = 0; idx < 2 * SPX5_PRIOS; ++idx) + stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop + + idx]; + stats->tx_dropped = portstats[spx5_stats_tx_local_drop]; +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c +index dc7e5ea6ec158..148d431fcde42 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c +@@ -145,9 +145,9 @@ static void sparx5_xtr_grp(struct sparx5 *sparx5, u8 grp, bool byte_swap) + skb_put(skb, byte_cnt - ETH_FCS_LEN); + eth_skb_pad(skb); + skb->protocol = eth_type_trans(skb, netdev); +- netif_rx(skb); + netdev->stats.rx_bytes += skb->len; + netdev->stats.rx_packets++; ++ netif_rx(skb); + } + + static int sparx5_inject(struct sparx5 *sparx5, +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c +index 4ce490a25f332..8e56ffa1c4f7a 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c +@@ -58,16 +58,6 @@ int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid, + struct sparx5 *sparx5 = port->sparx5; + int ret; + +- /* Make the port a member of the VLAN */ +- set_bit(port->portno, sparx5->vlan_mask[vid]); +- ret = sparx5_vlant_set_mask(sparx5, vid); +- if (ret) +- return ret; +- +- /* Default ingress vlan classification */ +- if (pvid) +- port->pvid = vid; +- + /* Untagged egress vlan classification */ + if (untagged && port->vid != vid) { + if (port->vid) { +@@ -79,6 +69,16 @@ int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid, + port->vid = vid; + } + ++ /* Make the port a member of the VLAN */ ++ set_bit(port->portno, sparx5->vlan_mask[vid]); ++ ret = sparx5_vlant_set_mask(sparx5, vid); ++ if (ret) ++ return ret; ++ ++ /* Default ingress vlan classification */ ++ if (pvid) ++ port->pvid = vid; ++ + sparx5_vlan_port_apply(sparx5, port); + + return 0; +diff --git a/drivers/net/ethernet/mscc/Kconfig b/drivers/net/ethernet/mscc/Kconfig +index b6a73d151dec1..8dd8c7f425d2c 100644 +--- a/drivers/net/ethernet/mscc/Kconfig ++++ b/drivers/net/ethernet/mscc/Kconfig +@@ -28,7 +28,7 @@ config MSCC_OCELOT_SWITCH + depends on BRIDGE || BRIDGE=n + depends on NET_SWITCHDEV + depends on HAS_IOMEM +- depends on OF_NET ++ depends on OF + select MSCC_OCELOT_SWITCH_LIB + select GENERIC_PHY + help +diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c +index a08e4f530c1c1..6aad0953e8fe5 100644 +--- a/drivers/net/ethernet/mscc/ocelot.c ++++ b/drivers/net/ethernet/mscc/ocelot.c +@@ -555,7 +555,10 @@ void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port, + + ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port); + +- ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, tx_pause); ++ /* Don't attempt to send PAUSE frames on the NPI port, it's broken */ ++ if (port != ocelot->npi) ++ ocelot_fields_write(ocelot, port, SYS_PAUSE_CFG_PAUSE_ENA, ++ tx_pause); + + /* Undo the effects of ocelot_phylink_mac_link_down: + * enable MAC module +@@ -1175,12 +1178,6 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) + switch (cfg.rx_filter) { + case HWTSTAMP_FILTER_NONE: + break; +- case HWTSTAMP_FILTER_ALL: +- case HWTSTAMP_FILTER_SOME: +- case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: +- case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: +- case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: +- case HWTSTAMP_FILTER_NTP_ALL: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: +@@ -1218,12 +1215,11 @@ void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) + } + EXPORT_SYMBOL(ocelot_get_strings); + ++/* Caller must hold &ocelot->stats_lock */ + static void ocelot_update_stats(struct ocelot *ocelot) + { + int i, j; + +- mutex_lock(&ocelot->stats_lock); +- + for (i = 0; i < ocelot->num_phys_ports; i++) { + /* Configure the port to read the stats from */ + ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(i), SYS_STAT_CFG); +@@ -1242,8 +1238,6 @@ static void ocelot_update_stats(struct ocelot *ocelot) + ~(u64)U32_MAX) + val; + } + } +- +- mutex_unlock(&ocelot->stats_lock); + } + + static void ocelot_check_stats_work(struct work_struct *work) +@@ -1252,7 +1246,9 @@ static void ocelot_check_stats_work(struct work_struct *work) + struct ocelot *ocelot = container_of(del_work, struct ocelot, + stats_work); + ++ mutex_lock(&ocelot->stats_lock); + ocelot_update_stats(ocelot); ++ mutex_unlock(&ocelot->stats_lock); + + queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, + OCELOT_STATS_CHECK_DELAY); +@@ -1262,12 +1258,16 @@ void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) + { + int i; + ++ mutex_lock(&ocelot->stats_lock); ++ + /* check and update now */ + ocelot_update_stats(ocelot); + + /* Copy all counters */ + for (i = 0; i < ocelot->num_stats; i++) + *data++ = ocelot->stats[port * ocelot->num_stats + i]; ++ ++ mutex_unlock(&ocelot->stats_lock); + } + EXPORT_SYMBOL(ocelot_get_ethtool_stats); + +@@ -1299,14 +1299,16 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port, + SOF_TIMESTAMPING_RAW_HARDWARE; + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) | + BIT(HWTSTAMP_TX_ONESTEP_SYNC); +- info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); ++ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | ++ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | ++ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | ++ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT); + + return 0; + } + EXPORT_SYMBOL(ocelot_get_ts_info); + +-static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond, +- bool only_active_ports) ++static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond) + { + u32 mask = 0; + int port; +@@ -1317,12 +1319,8 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond, + if (!ocelot_port) + continue; + +- if (ocelot_port->bond == bond) { +- if (only_active_ports && !ocelot_port->lag_tx_active) +- continue; +- ++ if (ocelot_port->bond == bond) + mask |= BIT(port); +- } + } + + return mask; +@@ -1409,10 +1407,8 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) + mask = ocelot_get_bridge_fwd_mask(ocelot, port, bridge); + mask |= cpu_fwd_mask; + mask &= ~BIT(port); +- if (bond) { +- mask &= ~ocelot_get_bond_mask(ocelot, bond, +- false); +- } ++ if (bond) ++ mask &= ~ocelot_get_bond_mask(ocelot, bond); + } else { + /* Standalone ports forward only to DSA tag_8021q CPU + * ports (if those exist), or to the hardware CPU port +@@ -1730,13 +1726,17 @@ static void ocelot_set_aggr_pgids(struct ocelot *ocelot) + if (!bond || (visited & BIT(lag))) + continue; + +- bond_mask = ocelot_get_bond_mask(ocelot, bond, true); ++ bond_mask = ocelot_get_bond_mask(ocelot, bond); + + for_each_set_bit(port, &bond_mask, ocelot->num_phys_ports) { ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; ++ + // Destination mask + ocelot_write_rix(ocelot, bond_mask, + ANA_PGID_PGID, port); +- aggr_idx[num_active_ports++] = port; ++ ++ if (ocelot_port->lag_tx_active) ++ aggr_idx[num_active_ports++] = port; + } + + for_each_aggr_pgid(ocelot, i) { +@@ -1785,8 +1785,7 @@ static void ocelot_setup_logical_port_ids(struct ocelot *ocelot) + + bond = ocelot_port->bond; + if (bond) { +- int lag = __ffs(ocelot_get_bond_mask(ocelot, bond, +- false)); ++ int lag = __ffs(ocelot_get_bond_mask(ocelot, bond)); + + ocelot_rmw_gix(ocelot, + ANA_PORT_PORT_CFG_PORTID_VAL(lag), +diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c +index 8b843d3c9189a..afa062c5f82d3 100644 +--- a/drivers/net/ethernet/mscc/ocelot_flower.c ++++ b/drivers/net/ethernet/mscc/ocelot_flower.c +@@ -467,13 +467,6 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, + return -EOPNOTSUPP; + } + +- if (filter->block_id == VCAP_IS1 && +- !is_zero_ether_addr(match.mask->dst)) { +- NL_SET_ERR_MSG_MOD(extack, +- "Key type S1_NORMAL cannot match on destination MAC"); +- return -EOPNOTSUPP; +- } +- + /* The hw support mac matches only for MAC_ETYPE key, + * therefore if other matches(port, tcp flags, etc) are added + * then just bail out +@@ -488,6 +481,14 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, + return -EOPNOTSUPP; + + flow_rule_match_eth_addrs(rule, &match); ++ ++ if (filter->block_id == VCAP_IS1 && ++ !is_zero_ether_addr(match.mask->dst)) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "Key type S1_NORMAL cannot match on destination MAC"); ++ return -EOPNOTSUPP; ++ } ++ + filter->key_type = OCELOT_VCAP_KEY_ETYPE; + ether_addr_copy(filter->key.etype.dmac.value, + match.key->dst); +diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c +index 2545727fd5b2f..c08c56e07b1d3 100644 +--- a/drivers/net/ethernet/mscc/ocelot_net.c ++++ b/drivers/net/ethernet/mscc/ocelot_net.c +@@ -1168,7 +1168,7 @@ static int ocelot_netdevice_bridge_join(struct net_device *dev, + ocelot_port_bridge_join(ocelot, port, bridge); + + err = switchdev_bridge_port_offload(brport_dev, dev, priv, +- &ocelot_netdevice_nb, ++ &ocelot_switchdev_nb, + &ocelot_switchdev_blocking_nb, + false, extack); + if (err) +@@ -1182,7 +1182,7 @@ static int ocelot_netdevice_bridge_join(struct net_device *dev, + + err_switchdev_sync: + switchdev_bridge_port_unoffload(brport_dev, priv, +- &ocelot_netdevice_nb, ++ &ocelot_switchdev_nb, + &ocelot_switchdev_blocking_nb); + err_switchdev_offload: + ocelot_port_bridge_leave(ocelot, port, bridge); +@@ -1195,7 +1195,7 @@ static void ocelot_netdevice_pre_bridge_leave(struct net_device *dev, + struct ocelot_port_private *priv = netdev_priv(dev); + + switchdev_bridge_port_unoffload(brport_dev, priv, +- &ocelot_netdevice_nb, ++ &ocelot_switchdev_nb, + &ocelot_switchdev_blocking_nb); + } + +diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c +index ca4686094701c..0a02d8bd0a3e5 100644 +--- a/drivers/net/ethernet/natsemi/xtsonic.c ++++ b/drivers/net/ethernet/natsemi/xtsonic.c +@@ -120,7 +120,7 @@ static const struct net_device_ops xtsonic_netdev_ops = { + .ndo_set_mac_address = eth_mac_addr, + }; + +-static int __init sonic_probe1(struct net_device *dev) ++static int sonic_probe1(struct net_device *dev) + { + unsigned int silicon_revision; + struct sonic_local *lp = netdev_priv(dev); +diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +index ab70179728f63..babd374333f34 100644 +--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c ++++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +@@ -922,8 +922,8 @@ nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev, + int port, bool mod) + { + struct nfp_flower_priv *priv = app->priv; +- int ida_idx = NFP_MAX_MAC_INDEX, err; + struct nfp_tun_offloaded_mac *entry; ++ int ida_idx = -1, err; + u16 nfp_mac_idx = 0; + + entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); +@@ -997,7 +997,7 @@ err_remove_hash: + err_free_entry: + kfree(entry); + err_free_ida: +- if (ida_idx != NFP_MAX_MAC_INDEX) ++ if (ida_idx != -1) + ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); + + return err; +@@ -1011,6 +1011,7 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, + struct nfp_flower_repr_priv *repr_priv; + struct nfp_tun_offloaded_mac *entry; + struct nfp_repr *repr; ++ u16 nfp_mac_idx; + int ida_idx; + + entry = nfp_tunnel_lookup_offloaded_macs(app, mac); +@@ -1029,8 +1030,6 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, + entry->bridge_count--; + + if (!entry->bridge_count && entry->ref_count) { +- u16 nfp_mac_idx; +- + nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; + if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, + false)) { +@@ -1046,7 +1045,6 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, + + /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ + if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { +- u16 nfp_mac_idx; + int port, err; + + repr_priv = list_first_entry(&entry->repr_list, +@@ -1074,8 +1072,14 @@ nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, + WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs, + &entry->ht_node, + offloaded_macs_params)); ++ ++ if (nfp_flower_is_supported_bridge(netdev)) ++ nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; ++ else ++ nfp_mac_idx = entry->index; ++ + /* If MAC has global ID then extract and free the ida entry. */ +- if (nfp_tunnel_is_mac_idx_global(entry->index)) { ++ if (nfp_tunnel_is_mac_idx_global(nfp_mac_idx)) { + ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); + ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); + } +diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h +index df203738511bf..0b1865e9f0b59 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h ++++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h +@@ -565,7 +565,6 @@ struct nfp_net_dp { + * @exn_name: Name for Exception interrupt + * @shared_handler: Handler for shared interrupts + * @shared_name: Name for shared interrupt +- * @me_freq_mhz: ME clock_freq (MHz) + * @reconfig_lock: Protects @reconfig_posted, @reconfig_timer_active, + * @reconfig_sync_present and HW reconfiguration request + * regs/machinery from async requests (sync must take +@@ -650,8 +649,6 @@ struct nfp_net { + irq_handler_t shared_handler; + char shared_name[IFNAMSIZ + 8]; + +- u32 me_freq_mhz; +- + bool link_up; + spinlock_t link_status_lock; + +diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +index 5bfa22accf2c9..850bfdf83d0a4 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c ++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +@@ -2067,7 +2067,7 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) + if (napi_complete_done(napi, pkts_polled)) + nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_entry); + +- if (r_vec->nfp_net->rx_coalesce_adapt_on) { ++ if (r_vec->nfp_net->rx_coalesce_adapt_on && r_vec->rx_ring) { + struct dim_sample dim_sample = {}; + unsigned int start; + u64 pkts, bytes; +@@ -2082,7 +2082,7 @@ static int nfp_net_poll(struct napi_struct *napi, int budget) + net_dim(&r_vec->rx_dim, dim_sample); + } + +- if (r_vec->nfp_net->tx_coalesce_adapt_on) { ++ if (r_vec->nfp_net->tx_coalesce_adapt_on && r_vec->tx_ring) { + struct dim_sample dim_sample = {}; + unsigned int start; + u64 pkts, bytes; +@@ -3016,10 +3016,8 @@ static void nfp_net_rx_dim_work(struct work_struct *work) + + /* copy RX interrupt coalesce parameters */ + value = (moder.pkts << 16) | (factor * moder.usec); +- rtnl_lock(); + nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(r_vec->rx_ring->idx), value); + (void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); +- rtnl_unlock(); + + dim->state = DIM_START_MEASURE; + } +@@ -3047,10 +3045,8 @@ static void nfp_net_tx_dim_work(struct work_struct *work) + + /* copy TX interrupt coalesce parameters */ + value = (moder.pkts << 16) | (factor * moder.usec); +- rtnl_lock(); + nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(r_vec->tx_ring->idx), value); + (void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); +- rtnl_unlock(); + + dim->state = DIM_START_MEASURE; + } +diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +index 0685ece1f155d..be1a358baadb9 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c ++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +@@ -1343,7 +1343,7 @@ static int nfp_net_set_coalesce(struct net_device *netdev, + * ME timestamp ticks. There are 16 ME clock cycles for each timestamp + * count. + */ +- factor = nn->me_freq_mhz / 16; ++ factor = nn->tlv_caps.me_freq_mhz / 16; + + /* Each pair of (usecs, max_frames) fields specifies that interrupts + * should be coalesced until +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c +index d7ac0307797fd..34c0d2ddf9ef6 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c +@@ -803,8 +803,10 @@ int nfp_cpp_area_cache_add(struct nfp_cpp *cpp, size_t size) + return -ENOMEM; + + cache = kzalloc(sizeof(*cache), GFP_KERNEL); +- if (!cache) ++ if (!cache) { ++ nfp_cpp_area_free(area); + return -ENOMEM; ++ } + + cache->id = 0; + cache->addr = 0; +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 7f3322ce044c7..6ac507ddf09af 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -3283,7 +3283,7 @@ int ionic_lif_init(struct ionic_lif *lif) + return -EINVAL; + } + +- lif->dbid_inuse = bitmap_alloc(lif->dbid_count, GFP_KERNEL); ++ lif->dbid_inuse = bitmap_zalloc(lif->dbid_count, GFP_KERNEL); + if (!lif->dbid_inuse) { + dev_err(dev, "Failed alloc doorbell id bitmap, aborting\n"); + return -ENOMEM; +diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c +index 065e9004598ee..999abcfe3310a 100644 +--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c ++++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c +@@ -1643,6 +1643,13 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev) + data_split = true; + } + } else { ++ if (unlikely(skb->len > ETH_TX_MAX_NON_LSO_PKT_LEN)) { ++ DP_ERR(edev, "Unexpected non LSO skb length = 0x%x\n", skb->len); ++ qede_free_failed_tx_pkt(txq, first_bd, 0, false); ++ qede_update_tx_producer(txq); ++ return NETDEV_TX_OK; ++ } ++ + val |= ((skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK) << + ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); + } +diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c +index 9837bdb89cd40..ee4c3bd28a934 100644 +--- a/drivers/net/ethernet/qlogic/qede/qede_main.c ++++ b/drivers/net/ethernet/qlogic/qede/qede_main.c +@@ -1176,19 +1176,17 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, + edev->devlink = qed_ops->common->devlink_register(cdev); + if (IS_ERR(edev->devlink)) { + DP_NOTICE(edev, "Cannot register devlink\n"); ++ rc = PTR_ERR(edev->devlink); + edev->devlink = NULL; +- /* Go on, we can live without devlink */ ++ goto err3; + } + } else { + struct net_device *ndev = pci_get_drvdata(pdev); ++ struct qed_devlink *qdl; + + edev = netdev_priv(ndev); +- +- if (edev->devlink) { +- struct qed_devlink *qdl = devlink_priv(edev->devlink); +- +- qdl->cdev = cdev; +- } ++ qdl = devlink_priv(edev->devlink); ++ qdl->cdev = cdev; + edev->cdev = cdev; + memset(&edev->stats, 0, sizeof(edev->stats)); + memcpy(&edev->dev_info, &dev_info, sizeof(dev_info)); +diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c +index c00ad57575eab..4eb9ea280474f 100644 +--- a/drivers/net/ethernet/qlogic/qla3xxx.c ++++ b/drivers/net/ethernet/qlogic/qla3xxx.c +@@ -3478,20 +3478,19 @@ static int ql_adapter_up(struct ql3_adapter *qdev) + + spin_lock_irqsave(&qdev->hw_lock, hw_flags); + +- err = ql_wait_for_drvr_lock(qdev); +- if (err) { +- err = ql_adapter_initialize(qdev); +- if (err) { +- netdev_err(ndev, "Unable to initialize adapter\n"); +- goto err_init; +- } +- netdev_err(ndev, "Releasing driver lock\n"); +- ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); +- } else { ++ if (!ql_wait_for_drvr_lock(qdev)) { + netdev_err(ndev, "Could not acquire driver lock\n"); ++ err = -ENODEV; + goto err_lock; + } + ++ err = ql_adapter_initialize(qdev); ++ if (err) { ++ netdev_err(ndev, "Unable to initialize adapter\n"); ++ goto err_init; ++ } ++ ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); ++ + spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + + set_bit(QL_ADAPTER_UP, &qdev->flags); +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +index d51bac7ba5afa..bd06076803295 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +@@ -1077,8 +1077,14 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter) + sds_mbx_size = sizeof(struct qlcnic_sds_mbx); + context_id = recv_ctx->context_id; + num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS; +- ahw->hw_ops->alloc_mbx_args(&cmd, adapter, +- QLCNIC_CMD_ADD_RCV_RINGS); ++ err = ahw->hw_ops->alloc_mbx_args(&cmd, adapter, ++ QLCNIC_CMD_ADD_RCV_RINGS); ++ if (err) { ++ dev_err(&adapter->pdev->dev, ++ "Failed to alloc mbx args %d\n", err); ++ return err; ++ } ++ + cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16); + + /* set up status rings, mbx 2-81 */ +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +index 7160b42f51ddd..d0111cb3b40e1 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +@@ -201,7 +201,7 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *, + struct qlcnic_info *, u16); + int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8); + void qlcnic_sriov_free_vlans(struct qlcnic_adapter *); +-void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *); ++int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *); + bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *); + void qlcnic_sriov_del_vlan_id(struct qlcnic_sriov *, + struct qlcnic_vf_info *, u16); +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +index dd03be3fc82a9..42a44c97572ae 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +@@ -432,7 +432,7 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, + struct qlcnic_cmd_args *cmd) + { + struct qlcnic_sriov *sriov = adapter->ahw->sriov; +- int i, num_vlans; ++ int i, num_vlans, ret; + u16 *vlans; + + if (sriov->allowed_vlans) +@@ -443,7 +443,9 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, + dev_info(&adapter->pdev->dev, "Number of allowed Guest VLANs = %d\n", + sriov->num_allowed_vlans); + +- qlcnic_sriov_alloc_vlans(adapter); ++ ret = qlcnic_sriov_alloc_vlans(adapter); ++ if (ret) ++ return ret; + + if (!sriov->any_vlan) + return 0; +@@ -2154,7 +2156,7 @@ static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) + return err; + } + +-void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter) ++int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter) + { + struct qlcnic_sriov *sriov = adapter->ahw->sriov; + struct qlcnic_vf_info *vf; +@@ -2164,7 +2166,11 @@ void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter) + vf = &sriov->vf_info[i]; + vf->sriov_vlans = kcalloc(sriov->num_allowed_vlans, + sizeof(*vf->sriov_vlans), GFP_KERNEL); ++ if (!vf->sriov_vlans) ++ return -ENOMEM; + } ++ ++ return 0; + } + + void qlcnic_sriov_free_vlans(struct qlcnic_adapter *adapter) +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +index 447720b93e5ab..e90fa97c0ae6c 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +@@ -597,7 +597,9 @@ static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, + if (err) + goto del_flr_queue; + +- qlcnic_sriov_alloc_vlans(adapter); ++ err = qlcnic_sriov_alloc_vlans(adapter); ++ if (err) ++ goto del_flr_queue; + + return err; + +diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c +index 0f85f2d97b18d..4e08b7219403c 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -30,8 +30,7 @@ + #include <linux/spinlock.h> + #include <linux/sys_soc.h> + #include <linux/reset.h> +- +-#include <asm/div64.h> ++#include <linux/math64.h> + + #include "ravb.h" + +@@ -2061,8 +2060,7 @@ static int ravb_set_gti(struct net_device *ndev) + if (!rate) + return -EINVAL; + +- inc = 1000000000ULL << 20; +- do_div(inc, rate); ++ inc = div64_ul(1000000000ULL << 20, rate); + + if (inc < GTI_TIV_MIN || inc > GTI_TIV_MAX) { + dev_err(dev, "gti.tiv increment 0x%llx is outside the range 0x%x - 0x%x\n", +diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c +index 3e1ca7a8d0295..bc70c6abd6a5b 100644 +--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c ++++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c +@@ -2783,7 +2783,8 @@ static void ofdpa_fib4_abort(struct rocker *rocker) + if (!ofdpa_port) + continue; + nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; +- ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE, ++ ofdpa_flow_tbl_del(ofdpa_port, ++ OFDPA_OP_FLAG_REMOVE | OFDPA_OP_FLAG_NOWAIT, + flow_entry); + } + spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, flags); +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index 6781aa636d588..1b415fe6f9b9f 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -2282,18 +2282,18 @@ static int __init sxgbe_cmdline_opt(char *str) + char *opt; + + if (!str || !*str) +- return -EINVAL; ++ return 1; + while ((opt = strsep(&str, ",")) != NULL) { + if (!strncmp(opt, "eee_timer:", 10)) { + if (kstrtoint(opt + 10, 0, &eee_timer)) + goto err; + } + } +- return 0; ++ return 1; + + err: + pr_err("%s: ERROR broken module parameter conversion\n", __func__); +- return -EINVAL; ++ return 1; + } + + __setup("sxgbeeth=", sxgbe_cmdline_opt); +diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c +index 518268ce20644..d35cafd422b1c 100644 +--- a/drivers/net/ethernet/sfc/ef100_nic.c ++++ b/drivers/net/ethernet/sfc/ef100_nic.c +@@ -609,6 +609,9 @@ static size_t ef100_update_stats(struct efx_nic *efx, + ef100_common_stat_mask(mask); + ef100_ethtool_stat_mask(mask); + ++ if (!mc_stats) ++ return 0; ++ + efx_nic_copy_stats(efx, mc_stats); + efx_nic_update_stats(ef100_stat_desc, EF100_STAT_COUNT, mask, + stats, mc_stats, false); +diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c +index bf1443539a1a4..bd552c7dffcb1 100644 +--- a/drivers/net/ethernet/sfc/ethtool_common.c ++++ b/drivers/net/ethernet/sfc/ethtool_common.c +@@ -563,20 +563,14 @@ int efx_ethtool_get_link_ksettings(struct net_device *net_dev, + { + struct efx_nic *efx = netdev_priv(net_dev); + struct efx_link_state *link_state = &efx->link_state; +- u32 supported; + + mutex_lock(&efx->mac_lock); + efx_mcdi_phy_get_link_ksettings(efx, cmd); + mutex_unlock(&efx->mac_lock); + + /* Both MACs support pause frames (bidirectional and respond-only) */ +- ethtool_convert_link_mode_to_legacy_u32(&supported, +- cmd->link_modes.supported); +- +- supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; +- +- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, +- supported); ++ ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); ++ ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); + + if (LOOPBACK_INTERNAL(efx)) { + cmd->base.speed = link_state->speed; +diff --git a/drivers/net/ethernet/sfc/falcon/rx.c b/drivers/net/ethernet/sfc/falcon/rx.c +index 966f13e7475dd..0c6cc21913693 100644 +--- a/drivers/net/ethernet/sfc/falcon/rx.c ++++ b/drivers/net/ethernet/sfc/falcon/rx.c +@@ -110,6 +110,8 @@ static struct page *ef4_reuse_page(struct ef4_rx_queue *rx_queue) + struct ef4_rx_page_state *state; + unsigned index; + ++ if (unlikely(!rx_queue->page_ring)) ++ return NULL; + index = rx_queue->page_remove & rx_queue->page_ptr_mask; + page = rx_queue->page_ring[index]; + if (page == NULL) +@@ -293,6 +295,9 @@ static void ef4_recycle_rx_pages(struct ef4_channel *channel, + { + struct ef4_rx_queue *rx_queue = ef4_channel_get_rx_queue(channel); + ++ if (unlikely(!rx_queue->page_ring)) ++ return; ++ + do { + ef4_recycle_rx_page(channel, rx_buf); + rx_buf = ef4_rx_buf_next(rx_queue, rx_buf); +@@ -728,7 +733,10 @@ static void ef4_init_rx_recycle_ring(struct ef4_nic *efx, + efx->rx_bufs_per_page); + rx_queue->page_ring = kcalloc(page_ring_size, + sizeof(*rx_queue->page_ring), GFP_KERNEL); +- rx_queue->page_ptr_mask = page_ring_size - 1; ++ if (!rx_queue->page_ring) ++ rx_queue->page_ptr_mask = 0; ++ else ++ rx_queue->page_ptr_mask = page_ring_size - 1; + } + + void ef4_init_rx_queue(struct ef4_rx_queue *rx_queue) +diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c +index 68fc7d317693b..633ca77a26fd1 100644 +--- a/drivers/net/ethernet/sfc/rx_common.c ++++ b/drivers/net/ethernet/sfc/rx_common.c +@@ -45,6 +45,8 @@ static struct page *efx_reuse_page(struct efx_rx_queue *rx_queue) + unsigned int index; + struct page *page; + ++ if (unlikely(!rx_queue->page_ring)) ++ return NULL; + index = rx_queue->page_remove & rx_queue->page_ptr_mask; + page = rx_queue->page_ring[index]; + if (page == NULL) +@@ -114,6 +116,9 @@ void efx_recycle_rx_pages(struct efx_channel *channel, + { + struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); + ++ if (unlikely(!rx_queue->page_ring)) ++ return; ++ + do { + efx_recycle_rx_page(channel, rx_buf); + rx_buf = efx_rx_buf_next(rx_queue, rx_buf); +@@ -150,7 +155,10 @@ static void efx_init_rx_recycle_ring(struct efx_rx_queue *rx_queue) + efx->rx_bufs_per_page); + rx_queue->page_ring = kcalloc(page_ring_size, + sizeof(*rx_queue->page_ring), GFP_KERNEL); +- rx_queue->page_ptr_mask = page_ring_size - 1; ++ if (!rx_queue->page_ring) ++ rx_queue->page_ptr_mask = 0; ++ else ++ rx_queue->page_ptr_mask = page_ring_size - 1; + } + + static void efx_fini_rx_recycle_ring(struct efx_rx_queue *rx_queue) +diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c +index b008b4e8a2a5a..0641a1d392b86 100644 +--- a/drivers/net/ethernet/smsc/smc911x.c ++++ b/drivers/net/ethernet/smsc/smc911x.c +@@ -2070,6 +2070,11 @@ static int smc911x_drv_probe(struct platform_device *pdev) + + ndev->dma = (unsigned char)-1; + ndev->irq = platform_get_irq(pdev, 0); ++ if (ndev->irq < 0) { ++ ret = ndev->irq; ++ goto release_both; ++ } ++ + lp = netdev_priv(ndev); + lp->netdev = ndev; + #ifdef SMC_DYNAMIC_BUS_CONFIG +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +index 5c74b6279d690..6b1d9e8879f46 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +@@ -113,8 +113,10 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos, + rgmii_writel(ethqos, temp, offset); + } + +-static void rgmii_dump(struct qcom_ethqos *ethqos) ++static void rgmii_dump(void *priv) + { ++ struct qcom_ethqos *ethqos = priv; ++ + dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n"); + dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n", + rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG)); +@@ -499,6 +501,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) + + plat_dat->bsp_priv = ethqos; + plat_dat->fix_mac_speed = ethqos_fix_mac_speed; ++ plat_dat->dump_debug_regs = rgmii_dump; + plat_dat->has_gmac4 = 1; + plat_dat->pmt = 1; + plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); +@@ -507,8 +510,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev) + if (ret) + goto err_clk; + +- rgmii_dump(ethqos); +- + return ret; + + err_clk: +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +index 6924a6aacbd53..c469abc91fa1b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +@@ -33,6 +33,7 @@ struct rk_gmac_ops { + void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); + void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); + void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); ++ bool regs_valid; + u32 regs[]; + }; + +@@ -1092,6 +1093,7 @@ static const struct rk_gmac_ops rk3568_ops = { + .set_to_rmii = rk3568_set_to_rmii, + .set_rgmii_speed = rk3568_set_gmac_speed, + .set_rmii_speed = rk3568_set_gmac_speed, ++ .regs_valid = true, + .regs = { + 0xfe2a0000, /* gmac0 */ + 0xfe010000, /* gmac1 */ +@@ -1383,7 +1385,7 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, + * to be distinguished. + */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (res) { ++ if (res && ops->regs_valid) { + int i = 0; + + while (ops->regs[i]) { +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +index 85208128f135c..b7c2579c963b6 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -485,8 +485,28 @@ static int socfpga_dwmac_resume(struct device *dev) + } + #endif /* CONFIG_PM_SLEEP */ + +-static SIMPLE_DEV_PM_OPS(socfpga_dwmac_pm_ops, stmmac_suspend, +- socfpga_dwmac_resume); ++static int __maybe_unused socfpga_dwmac_runtime_suspend(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ ++ stmmac_bus_clks_config(priv, false); ++ ++ return 0; ++} ++ ++static int __maybe_unused socfpga_dwmac_runtime_resume(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ ++ return stmmac_bus_clks_config(priv, true); ++} ++ ++static const struct dev_pm_ops socfpga_dwmac_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(stmmac_suspend, socfpga_dwmac_resume) ++ SET_RUNTIME_PM_OPS(socfpga_dwmac_runtime_suspend, socfpga_dwmac_runtime_resume, NULL) ++}; + + static const struct socfpga_dwmac_ops socfpga_gen5_ops = { + .set_phy_mode = socfpga_gen5_set_phy_mode, +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +index 4422baeed3d89..13fbb68158c66 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -756,7 +756,7 @@ static int sun8i_dwmac_reset(struct stmmac_priv *priv) + + if (err) { + dev_err(priv->device, "EMAC reset timeout\n"); +- return -EFAULT; ++ return err; + } + return 0; + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c +index d046e33b8a297..c27441c08dd6f 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c +@@ -22,21 +22,21 @@ + #define ETHER_CLK_SEL_RMII_CLK_EN BIT(2) + #define ETHER_CLK_SEL_RMII_CLK_RST BIT(3) + #define ETHER_CLK_SEL_DIV_SEL_2 BIT(4) +-#define ETHER_CLK_SEL_DIV_SEL_20 BIT(0) ++#define ETHER_CLK_SEL_DIV_SEL_20 0 + #define ETHER_CLK_SEL_FREQ_SEL_125M (BIT(9) | BIT(8)) + #define ETHER_CLK_SEL_FREQ_SEL_50M BIT(9) + #define ETHER_CLK_SEL_FREQ_SEL_25M BIT(8) +-#define ETHER_CLK_SEL_FREQ_SEL_2P5M BIT(0) +-#define ETHER_CLK_SEL_TX_CLK_EXT_SEL_IN BIT(0) ++#define ETHER_CLK_SEL_FREQ_SEL_2P5M 0 ++#define ETHER_CLK_SEL_TX_CLK_EXT_SEL_IN 0 + #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC BIT(10) + #define ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV BIT(11) +-#define ETHER_CLK_SEL_RX_CLK_EXT_SEL_IN BIT(0) ++#define ETHER_CLK_SEL_RX_CLK_EXT_SEL_IN 0 + #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC BIT(12) + #define ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV BIT(13) +-#define ETHER_CLK_SEL_TX_CLK_O_TX_I BIT(0) ++#define ETHER_CLK_SEL_TX_CLK_O_TX_I 0 + #define ETHER_CLK_SEL_TX_CLK_O_RMII_I BIT(14) + #define ETHER_CLK_SEL_TX_O_E_N_IN BIT(15) +-#define ETHER_CLK_SEL_RMII_CLK_SEL_IN BIT(0) ++#define ETHER_CLK_SEL_RMII_CLK_SEL_IN 0 + #define ETHER_CLK_SEL_RMII_CLK_SEL_RX_C BIT(16) + + #define ETHER_CLK_SEL_RX_TX_CLK_EN (ETHER_CLK_SEL_RX_CLK_EN | ETHER_CLK_SEL_TX_CLK_EN) +@@ -49,13 +49,15 @@ struct visconti_eth { + void __iomem *reg; + u32 phy_intf_sel; + struct clk *phy_ref_clk; ++ struct device *dev; + spinlock_t lock; /* lock to protect register update */ + }; + + static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed) + { + struct visconti_eth *dwmac = priv; +- unsigned int val, clk_sel_val; ++ struct net_device *netdev = dev_get_drvdata(dwmac->dev); ++ unsigned int val, clk_sel_val = 0; + unsigned long flags; + + spin_lock_irqsave(&dwmac->lock, flags); +@@ -85,7 +87,9 @@ static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed) + break; + default: + /* No bit control */ +- break; ++ netdev_err(netdev, "Unsupported speed request (%d)", speed); ++ spin_unlock_irqrestore(&dwmac->lock, flags); ++ return; + } + + writel(val, dwmac->reg + MAC_CTRL_REG); +@@ -96,31 +100,41 @@ static void visconti_eth_fix_mac_speed(void *priv, unsigned int speed) + val |= ETHER_CLK_SEL_TX_O_E_N_IN; + writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); + ++ /* Set Clock-Mux, Start clock, Set TX_O direction */ + switch (dwmac->phy_intf_sel) { + case ETHER_CONFIG_INTF_RGMII: + val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); ++ ++ val |= ETHER_CLK_SEL_RX_TX_CLK_EN; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); ++ ++ val &= ~ETHER_CLK_SEL_TX_O_E_N_IN; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); + break; + case ETHER_CONFIG_INTF_RMII: + val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV | +- ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC | ETHER_CLK_SEL_TX_O_E_N_IN | ++ ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV | ETHER_CLK_SEL_TX_O_E_N_IN | + ETHER_CLK_SEL_RMII_CLK_SEL_RX_C; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); ++ ++ val |= ETHER_CLK_SEL_RMII_CLK_RST; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); ++ ++ val |= ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); + break; + case ETHER_CONFIG_INTF_MII: + default: + val = clk_sel_val | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC | +- ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV | ETHER_CLK_SEL_TX_O_E_N_IN | +- ETHER_CLK_SEL_RMII_CLK_EN; ++ ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC | ETHER_CLK_SEL_TX_O_E_N_IN; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); ++ ++ val |= ETHER_CLK_SEL_RX_TX_CLK_EN; ++ writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); + break; + } + +- /* Start clock */ +- writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); +- val |= ETHER_CLK_SEL_RX_TX_CLK_EN; +- writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); +- +- val &= ~ETHER_CLK_SEL_TX_O_E_N_IN; +- writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL); +- + spin_unlock_irqrestore(&dwmac->lock, flags); + } + +@@ -220,6 +234,7 @@ static int visconti_eth_dwmac_probe(struct platform_device *pdev) + + spin_lock_init(&dwmac->lock); + dwmac->reg = stmmac_res.addr; ++ dwmac->dev = &pdev->dev; + plat_dat->bsp_priv = dwmac; + plat_dat->fix_mac_speed = visconti_eth_fix_mac_speed; + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +index 1914ad698cab2..acd70b9a3173c 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +@@ -150,6 +150,7 @@ + + #define NUM_DWMAC100_DMA_REGS 9 + #define NUM_DWMAC1000_DMA_REGS 23 ++#define NUM_DWMAC4_DMA_REGS 27 + + void dwmac_enable_dma_transmission(void __iomem *ioaddr); + void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 43eead726886a..05b5371ca036b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -172,6 +172,19 @@ struct stmmac_flow_entry { + int is_l4; + }; + ++/* Rx Frame Steering */ ++enum stmmac_rfs_type { ++ STMMAC_RFS_T_VLAN, ++ STMMAC_RFS_T_MAX, ++}; ++ ++struct stmmac_rfs_entry { ++ unsigned long cookie; ++ int in_use; ++ int type; ++ int tc; ++}; ++ + struct stmmac_priv { + /* Frequently used values are kept adjacent for cache effect */ + u32 tx_coal_frames[MTL_MAX_TX_QUEUES]; +@@ -289,6 +302,10 @@ struct stmmac_priv { + struct stmmac_tc_entry *tc_entries; + unsigned int flow_entries_max; + struct stmmac_flow_entry *flow_entries; ++ unsigned int rfs_entries_max[STMMAC_RFS_T_MAX]; ++ unsigned int rfs_entries_cnt[STMMAC_RFS_T_MAX]; ++ unsigned int rfs_entries_total; ++ struct stmmac_rfs_entry *rfs_entries; + + /* Pulse Per Second output */ + struct stmmac_pps_cfg pps[STMMAC_PPS_MAX]; +@@ -314,10 +331,11 @@ int stmmac_mdio_reset(struct mii_bus *mii); + int stmmac_xpcs_setup(struct mii_bus *mii); + void stmmac_set_ethtool_ops(struct net_device *netdev); + ++int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags); + void stmmac_ptp_register(struct stmmac_priv *priv); + void stmmac_ptp_unregister(struct stmmac_priv *priv); +-int stmmac_open(struct net_device *dev); +-int stmmac_release(struct net_device *dev); ++int stmmac_xdp_open(struct net_device *dev); ++void stmmac_xdp_release(struct net_device *dev); + int stmmac_resume(struct device *dev); + int stmmac_suspend(struct device *dev); + int stmmac_dvr_remove(struct device *dev); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +index d89455803beda..8f563b446d5ca 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +@@ -21,10 +21,18 @@ + #include "dwxgmac2.h" + + #define REG_SPACE_SIZE 0x1060 ++#define GMAC4_REG_SPACE_SIZE 0x116C + #define MAC100_ETHTOOL_NAME "st_mac100" + #define GMAC_ETHTOOL_NAME "st_gmac" + #define XGMAC_ETHTOOL_NAME "st_xgmac" + ++/* Same as DMA_CHAN_BASE_ADDR defined in dwmac4_dma.h ++ * ++ * It is here because dwmac_dma.h and dwmac4_dam.h can not be included at the ++ * same time due to the conflicting macro names. ++ */ ++#define GMAC4_DMA_CHAN_BASE_ADDR 0x00001100 ++ + #define ETHTOOL_DMA_OFFSET 55 + + struct stmmac_stats { +@@ -435,6 +443,8 @@ static int stmmac_ethtool_get_regs_len(struct net_device *dev) + + if (priv->plat->has_xgmac) + return XGMAC_REGSIZE * 4; ++ else if (priv->plat->has_gmac4) ++ return GMAC4_REG_SPACE_SIZE; + return REG_SPACE_SIZE; + } + +@@ -447,8 +457,13 @@ static void stmmac_ethtool_gregs(struct net_device *dev, + stmmac_dump_mac_regs(priv, priv->hw, reg_space); + stmmac_dump_dma_regs(priv, priv->ioaddr, reg_space); + +- if (!priv->plat->has_xgmac) { +- /* Copy DMA registers to where ethtool expects them */ ++ /* Copy DMA registers to where ethtool expects them */ ++ if (priv->plat->has_gmac4) { ++ /* GMAC4 dumps its DMA registers at its DMA_CHAN_BASE_ADDR */ ++ memcpy(®_space[ETHTOOL_DMA_OFFSET], ++ ®_space[GMAC4_DMA_CHAN_BASE_ADDR / 4], ++ NUM_DWMAC4_DMA_REGS * 4); ++ } else if (!priv->plat->has_xgmac) { + memcpy(®_space[ETHTOOL_DMA_OFFSET], + ®_space[DMA_BUS_MODE / 4], + NUM_DWMAC1000_DMA_REGS * 4); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +index 074e2cdfb0fa6..a7ec9f4d46ced 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +@@ -145,15 +145,20 @@ static int adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec, + + static void get_systime(void __iomem *ioaddr, u64 *systime) + { +- u64 ns; +- +- /* Get the TSSS value */ +- ns = readl(ioaddr + PTP_STNSR); +- /* Get the TSS and convert sec time value to nanosecond */ +- ns += readl(ioaddr + PTP_STSR) * 1000000000ULL; ++ u64 ns, sec0, sec1; ++ ++ /* Get the TSS value */ ++ sec1 = readl_relaxed(ioaddr + PTP_STSR); ++ do { ++ sec0 = sec1; ++ /* Get the TSSS value */ ++ ns = readl_relaxed(ioaddr + PTP_STNSR); ++ /* Get the TSS value */ ++ sec1 = readl_relaxed(ioaddr + PTP_STSR); ++ } while (sec0 != sec1); + + if (systime) +- *systime = ns; ++ *systime = ns + (sec1 * 1000000000ULL); + } + + static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time) +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 3d67d1fa36906..9376c4e286268 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -50,6 +50,13 @@ + #include "dwxgmac2.h" + #include "hwif.h" + ++/* As long as the interface is active, we keep the timestamping counter enabled ++ * with fine resolution and binary rollover. This avoid non-monotonic behavior ++ * (clock jumps) when changing timestamping settings at runtime. ++ */ ++#define STMMAC_HWTS_ACTIVE (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | \ ++ PTP_TCR_TSCTRLSSR) ++ + #define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16) + #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) + +@@ -393,7 +400,7 @@ static void stmmac_lpi_entry_timer_config(struct stmmac_priv *priv, bool en) + * Description: this function is to verify and enter in LPI mode in case of + * EEE. + */ +-static void stmmac_enable_eee_mode(struct stmmac_priv *priv) ++static int stmmac_enable_eee_mode(struct stmmac_priv *priv) + { + u32 tx_cnt = priv->plat->tx_queues_to_use; + u32 queue; +@@ -403,13 +410,14 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv) + struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; + + if (tx_q->dirty_tx != tx_q->cur_tx) +- return; /* still unfinished work */ ++ return -EBUSY; /* still unfinished work */ + } + + /* Check and enter in LPI mode */ + if (!priv->tx_path_in_lpi_mode) + stmmac_set_eee_mode(priv, priv->hw, + priv->plat->en_tx_lpi_clockgating); ++ return 0; + } + + /** +@@ -441,8 +449,8 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t) + { + struct stmmac_priv *priv = from_timer(priv, t, eee_ctrl_timer); + +- stmmac_enable_eee_mode(priv); +- mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer)); ++ if (stmmac_enable_eee_mode(priv)) ++ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer)); + } + + /** +@@ -511,6 +519,14 @@ bool stmmac_eee_init(struct stmmac_priv *priv) + return true; + } + ++static inline u32 stmmac_cdc_adjust(struct stmmac_priv *priv) ++{ ++ /* Correct the clk domain crossing(CDC) error */ ++ if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) ++ return (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate; ++ return 0; ++} ++ + /* stmmac_get_tx_hwtstamp - get HW TX timestamps + * @priv: driver private structure + * @p : descriptor pointer +@@ -524,7 +540,6 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, + { + struct skb_shared_hwtstamps shhwtstamp; + bool found = false; +- s64 adjust = 0; + u64 ns = 0; + + if (!priv->hwts_tx_en) +@@ -543,12 +558,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, + } + + if (found) { +- /* Correct the clk domain crossing(CDC) error */ +- if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) { +- adjust += -(2 * (NSEC_PER_SEC / +- priv->plat->clk_ptp_rate)); +- ns += adjust; +- } ++ ns -= stmmac_cdc_adjust(priv); + + memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); + shhwtstamp.hwtstamp = ns_to_ktime(ns); +@@ -573,7 +583,6 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, + { + struct skb_shared_hwtstamps *shhwtstamp = NULL; + struct dma_desc *desc = p; +- u64 adjust = 0; + u64 ns = 0; + + if (!priv->hwts_rx_en) +@@ -586,11 +595,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, + if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) { + stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns); + +- /* Correct the clk domain crossing(CDC) error */ +- if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) { +- adjust += 2 * (NSEC_PER_SEC / priv->plat->clk_ptp_rate); +- ns -= adjust; +- } ++ ns -= stmmac_cdc_adjust(priv); + + netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns); + shhwtstamp = skb_hwtstamps(skb); +@@ -616,8 +621,6 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) + { + struct stmmac_priv *priv = netdev_priv(dev); + struct hwtstamp_config config; +- struct timespec64 now; +- u64 temp = 0; + u32 ptp_v2 = 0; + u32 tstamp_all = 0; + u32 ptp_over_ipv4_udp = 0; +@@ -626,11 +629,6 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) + u32 snap_type_sel = 0; + u32 ts_master_en = 0; + u32 ts_event_en = 0; +- u32 sec_inc = 0; +- u32 value = 0; +- bool xmac; +- +- xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; + + if (!(priv->dma_cap.time_stamp || priv->adv_ts)) { + netdev_alert(priv->dev, "No support for HW time stamping\n"); +@@ -792,42 +790,17 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) + priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1); + priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON; + +- if (!priv->hwts_tx_en && !priv->hwts_rx_en) +- stmmac_config_hw_tstamping(priv, priv->ptpaddr, 0); +- else { +- value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR | +- tstamp_all | ptp_v2 | ptp_over_ethernet | +- ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en | +- ts_master_en | snap_type_sel); +- stmmac_config_hw_tstamping(priv, priv->ptpaddr, value); +- +- /* program Sub Second Increment reg */ +- stmmac_config_sub_second_increment(priv, +- priv->ptpaddr, priv->plat->clk_ptp_rate, +- xmac, &sec_inc); +- temp = div_u64(1000000000ULL, sec_inc); +- +- /* Store sub second increment and flags for later use */ +- priv->sub_second_inc = sec_inc; +- priv->systime_flags = value; +- +- /* calculate default added value: +- * formula is : +- * addend = (2^32)/freq_div_ratio; +- * where, freq_div_ratio = 1e9ns/sec_inc +- */ +- temp = (u64)(temp << 32); +- priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); +- stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend); +- +- /* initialize system time */ +- ktime_get_real_ts64(&now); ++ priv->systime_flags = STMMAC_HWTS_ACTIVE; + +- /* lower 32 bits of tv_sec are safe until y2106 */ +- stmmac_init_systime(priv, priv->ptpaddr, +- (u32)now.tv_sec, now.tv_nsec); ++ if (priv->hwts_tx_en || priv->hwts_rx_en) { ++ priv->systime_flags |= tstamp_all | ptp_v2 | ++ ptp_over_ethernet | ptp_over_ipv6_udp | ++ ptp_over_ipv4_udp | ts_event_en | ++ ts_master_en | snap_type_sel; + } + ++ stmmac_config_hw_tstamping(priv, priv->ptpaddr, priv->systime_flags); ++ + memcpy(&priv->tstamp_config, &config, sizeof(config)); + + return copy_to_user(ifr->ifr_data, &config, +@@ -855,6 +828,66 @@ static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) + sizeof(*config)) ? -EFAULT : 0; + } + ++/** ++ * stmmac_init_tstamp_counter - init hardware timestamping counter ++ * @priv: driver private structure ++ * @systime_flags: timestamping flags ++ * Description: ++ * Initialize hardware counter for packet timestamping. ++ * This is valid as long as the interface is open and not suspended. ++ * Will be rerun after resuming from suspend, case in which the timestamping ++ * flags updated by stmmac_hwtstamp_set() also need to be restored. ++ */ ++int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags) ++{ ++ bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; ++ struct timespec64 now; ++ u32 sec_inc = 0; ++ u64 temp = 0; ++ int ret; ++ ++ if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) ++ return -EOPNOTSUPP; ++ ++ ret = clk_prepare_enable(priv->plat->clk_ptp_ref); ++ if (ret < 0) { ++ netdev_warn(priv->dev, ++ "failed to enable PTP reference clock: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ ++ stmmac_config_hw_tstamping(priv, priv->ptpaddr, systime_flags); ++ priv->systime_flags = systime_flags; ++ ++ /* program Sub Second Increment reg */ ++ stmmac_config_sub_second_increment(priv, priv->ptpaddr, ++ priv->plat->clk_ptp_rate, ++ xmac, &sec_inc); ++ temp = div_u64(1000000000ULL, sec_inc); ++ ++ /* Store sub second increment for later use */ ++ priv->sub_second_inc = sec_inc; ++ ++ /* calculate default added value: ++ * formula is : ++ * addend = (2^32)/freq_div_ratio; ++ * where, freq_div_ratio = 1e9ns/sec_inc ++ */ ++ temp = (u64)(temp << 32); ++ priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); ++ stmmac_config_addend(priv, priv->ptpaddr, priv->default_addend); ++ ++ /* initialize system time */ ++ ktime_get_real_ts64(&now); ++ ++ /* lower 32 bits of tv_sec are safe until y2106 */ ++ stmmac_init_systime(priv, priv->ptpaddr, (u32)now.tv_sec, now.tv_nsec); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(stmmac_init_tstamp_counter); ++ + /** + * stmmac_init_ptp - init PTP + * @priv: driver private structure +@@ -865,9 +898,14 @@ static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) + static int stmmac_init_ptp(struct stmmac_priv *priv) + { + bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac; ++ int ret; + +- if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) +- return -EOPNOTSUPP; ++ if (priv->plat->ptp_clk_freq_config) ++ priv->plat->ptp_clk_freq_config(priv); ++ ++ ret = stmmac_init_tstamp_counter(priv, STMMAC_HWTS_ACTIVE); ++ if (ret) ++ return ret; + + priv->adv_ts = 0; + /* Check if adv_ts can be enabled for dwmac 4.x / xgmac core */ +@@ -887,8 +925,6 @@ static int stmmac_init_ptp(struct stmmac_priv *priv) + priv->hwts_tx_en = 0; + priv->hwts_rx_en = 0; + +- stmmac_ptp_register(priv); +- + return 0; + } + +@@ -2232,6 +2268,23 @@ static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan) + stmmac_stop_tx(priv, priv->ioaddr, chan); + } + ++static void stmmac_enable_all_dma_irq(struct stmmac_priv *priv) ++{ ++ u32 rx_channels_count = priv->plat->rx_queues_to_use; ++ u32 tx_channels_count = priv->plat->tx_queues_to_use; ++ u32 dma_csr_ch = max(rx_channels_count, tx_channels_count); ++ u32 chan; ++ ++ for (chan = 0; chan < dma_csr_ch; chan++) { ++ struct stmmac_channel *ch = &priv->channel[chan]; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ch->lock, flags); ++ stmmac_enable_dma_irq(priv, priv->ioaddr, chan, 1, 1); ++ spin_unlock_irqrestore(&ch->lock, flags); ++ } ++} ++ + /** + * stmmac_start_all_dma - start all RX and TX DMA channels + * @priv: driver private structure +@@ -2602,8 +2655,8 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) + + if (priv->eee_enabled && !priv->tx_path_in_lpi_mode && + priv->eee_sw_timer_en) { +- stmmac_enable_eee_mode(priv); +- mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer)); ++ if (stmmac_enable_eee_mode(priv)) ++ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer)); + } + + /* We still have pending packets, let's call for a new scheduling */ +@@ -2867,8 +2920,10 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv) + stmmac_axi(priv, priv->ioaddr, priv->plat->axi); + + /* DMA CSR Channel configuration */ +- for (chan = 0; chan < dma_csr_ch; chan++) ++ for (chan = 0; chan < dma_csr_ch; chan++) { + stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan); ++ stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1); ++ } + + /* DMA RX Channel Configuration */ + for (chan = 0; chan < rx_channels_count; chan++) { +@@ -3203,7 +3258,7 @@ static int stmmac_fpe_start_wq(struct stmmac_priv *priv) + /** + * stmmac_hw_setup - setup mac in a usable state. + * @dev : pointer to the device structure. +- * @init_ptp: initialize PTP if set ++ * @ptp_register: register PTP if set + * Description: + * this is the main function to setup the HW in a usable state because the + * dma engine is reset, the core registers are configured (e.g. AXI, +@@ -3213,7 +3268,7 @@ static int stmmac_fpe_start_wq(struct stmmac_priv *priv) + * 0 on success and an appropriate (-)ve integer as defined in errno.h + * file on failure. + */ +-static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) ++static int stmmac_hw_setup(struct net_device *dev, bool ptp_register) + { + struct stmmac_priv *priv = netdev_priv(dev); + u32 rx_cnt = priv->plat->rx_queues_to_use; +@@ -3270,17 +3325,13 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) + + stmmac_mmc_setup(priv); + +- if (init_ptp) { +- ret = clk_prepare_enable(priv->plat->clk_ptp_ref); +- if (ret < 0) +- netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret); +- +- ret = stmmac_init_ptp(priv); +- if (ret == -EOPNOTSUPP) +- netdev_warn(priv->dev, "PTP not supported by HW\n"); +- else if (ret) +- netdev_warn(priv->dev, "PTP init failed\n"); +- } ++ ret = stmmac_init_ptp(priv); ++ if (ret == -EOPNOTSUPP) ++ netdev_warn(priv->dev, "PTP not supported by HW\n"); ++ else if (ret) ++ netdev_warn(priv->dev, "PTP init failed\n"); ++ else if (ptp_register) ++ stmmac_ptp_register(priv); + + priv->eee_tw_timer = STMMAC_DEFAULT_TWT_LS; + +@@ -3635,7 +3686,7 @@ static int stmmac_request_irq(struct net_device *dev) + * 0 on success and an appropriate (-)ve integer as defined in errno.h + * file on failure. + */ +-int stmmac_open(struct net_device *dev) ++static int stmmac_open(struct net_device *dev) + { + struct stmmac_priv *priv = netdev_priv(dev); + int mode = priv->plat->phy_interface; +@@ -3724,6 +3775,7 @@ int stmmac_open(struct net_device *dev) + + stmmac_enable_all_queues(priv); + netif_tx_start_all_queues(priv->dev); ++ stmmac_enable_all_dma_irq(priv); + + return 0; + +@@ -3759,11 +3811,13 @@ static void stmmac_fpe_stop_wq(struct stmmac_priv *priv) + * Description: + * This is the stop entry point of the driver. + */ +-int stmmac_release(struct net_device *dev) ++static int stmmac_release(struct net_device *dev) + { + struct stmmac_priv *priv = netdev_priv(dev); + u32 chan; + ++ netif_tx_disable(dev); ++ + if (device_may_wakeup(priv->device)) + phylink_speed_down(priv->phylink, false); + /* Stop and disconnect the PHY */ +@@ -5499,8 +5553,6 @@ static int stmmac_set_features(struct net_device *netdev, + netdev_features_t features) + { + struct stmmac_priv *priv = netdev_priv(netdev); +- bool sph_en; +- u32 chan; + + /* Keep the COE Type in case of csum is supporting */ + if (features & NETIF_F_RXCSUM) +@@ -5512,10 +5564,13 @@ static int stmmac_set_features(struct net_device *netdev, + */ + stmmac_rx_ipc(priv, priv->hw); + +- sph_en = (priv->hw->rx_csum > 0) && priv->sph; ++ if (priv->sph_cap) { ++ bool sph_en = (priv->hw->rx_csum > 0) && priv->sph; ++ u32 chan; + +- for (chan = 0; chan < priv->plat->rx_queues_to_use; chan++) +- stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); ++ for (chan = 0; chan < priv->plat->rx_queues_to_use; chan++) ++ stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); ++ } + + return 0; + } +@@ -6421,6 +6476,143 @@ void stmmac_enable_tx_queue(struct stmmac_priv *priv, u32 queue) + spin_unlock_irqrestore(&ch->lock, flags); + } + ++void stmmac_xdp_release(struct net_device *dev) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ u32 chan; ++ ++ /* Disable NAPI process */ ++ stmmac_disable_all_queues(priv); ++ ++ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) ++ hrtimer_cancel(&priv->tx_queue[chan].txtimer); ++ ++ /* Free the IRQ lines */ ++ stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0); ++ ++ /* Stop TX/RX DMA channels */ ++ stmmac_stop_all_dma(priv); ++ ++ /* Release and free the Rx/Tx resources */ ++ free_dma_desc_resources(priv); ++ ++ /* Disable the MAC Rx/Tx */ ++ stmmac_mac_set(priv, priv->ioaddr, false); ++ ++ /* set trans_start so we don't get spurious ++ * watchdogs during reset ++ */ ++ netif_trans_update(dev); ++ netif_carrier_off(dev); ++} ++ ++int stmmac_xdp_open(struct net_device *dev) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ u32 rx_cnt = priv->plat->rx_queues_to_use; ++ u32 tx_cnt = priv->plat->tx_queues_to_use; ++ u32 dma_csr_ch = max(rx_cnt, tx_cnt); ++ struct stmmac_rx_queue *rx_q; ++ struct stmmac_tx_queue *tx_q; ++ u32 buf_size; ++ bool sph_en; ++ u32 chan; ++ int ret; ++ ++ ret = alloc_dma_desc_resources(priv); ++ if (ret < 0) { ++ netdev_err(dev, "%s: DMA descriptors allocation failed\n", ++ __func__); ++ goto dma_desc_error; ++ } ++ ++ ret = init_dma_desc_rings(dev, GFP_KERNEL); ++ if (ret < 0) { ++ netdev_err(dev, "%s: DMA descriptors initialization failed\n", ++ __func__); ++ goto init_error; ++ } ++ ++ /* DMA CSR Channel configuration */ ++ for (chan = 0; chan < dma_csr_ch; chan++) { ++ stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan); ++ stmmac_disable_dma_irq(priv, priv->ioaddr, chan, 1, 1); ++ } ++ ++ /* Adjust Split header */ ++ sph_en = (priv->hw->rx_csum > 0) && priv->sph; ++ ++ /* DMA RX Channel Configuration */ ++ for (chan = 0; chan < rx_cnt; chan++) { ++ rx_q = &priv->rx_queue[chan]; ++ ++ stmmac_init_rx_chan(priv, priv->ioaddr, priv->plat->dma_cfg, ++ rx_q->dma_rx_phy, chan); ++ ++ rx_q->rx_tail_addr = rx_q->dma_rx_phy + ++ (rx_q->buf_alloc_num * ++ sizeof(struct dma_desc)); ++ stmmac_set_rx_tail_ptr(priv, priv->ioaddr, ++ rx_q->rx_tail_addr, chan); ++ ++ if (rx_q->xsk_pool && rx_q->buf_alloc_num) { ++ buf_size = xsk_pool_get_rx_frame_size(rx_q->xsk_pool); ++ stmmac_set_dma_bfsize(priv, priv->ioaddr, ++ buf_size, ++ rx_q->queue_index); ++ } else { ++ stmmac_set_dma_bfsize(priv, priv->ioaddr, ++ priv->dma_buf_sz, ++ rx_q->queue_index); ++ } ++ ++ stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); ++ } ++ ++ /* DMA TX Channel Configuration */ ++ for (chan = 0; chan < tx_cnt; chan++) { ++ tx_q = &priv->tx_queue[chan]; ++ ++ stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg, ++ tx_q->dma_tx_phy, chan); ++ ++ tx_q->tx_tail_addr = tx_q->dma_tx_phy; ++ stmmac_set_tx_tail_ptr(priv, priv->ioaddr, ++ tx_q->tx_tail_addr, chan); ++ ++ hrtimer_init(&tx_q->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ tx_q->txtimer.function = stmmac_tx_timer; ++ } ++ ++ /* Enable the MAC Rx/Tx */ ++ stmmac_mac_set(priv, priv->ioaddr, true); ++ ++ /* Start Rx & Tx DMA Channels */ ++ stmmac_start_all_dma(priv); ++ ++ ret = stmmac_request_irq(dev); ++ if (ret) ++ goto irq_error; ++ ++ /* Enable NAPI process*/ ++ stmmac_enable_all_queues(priv); ++ netif_carrier_on(dev); ++ netif_tx_start_all_queues(dev); ++ stmmac_enable_all_dma_irq(priv); ++ ++ return 0; ++ ++irq_error: ++ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) ++ hrtimer_cancel(&priv->tx_queue[chan].txtimer); ++ ++ stmmac_hw_teardown(dev); ++init_error: ++ free_dma_desc_resources(priv); ++dma_desc_error: ++ return ret; ++} ++ + int stmmac_xsk_wakeup(struct net_device *dev, u32 queue, u32 flags) + { + struct stmmac_priv *priv = netdev_priv(dev); +@@ -7044,6 +7236,9 @@ int stmmac_dvr_probe(struct device *device, + stmmac_init_fs(ndev); + #endif + ++ if (priv->plat->dump_debug_regs) ++ priv->plat->dump_debug_regs(priv->plat->bsp_priv); ++ + /* Let pm_runtime_put() disable the clocks. + * If CONFIG_PM is not enabled, the clocks will stay powered. + */ +@@ -7083,6 +7278,10 @@ int stmmac_dvr_remove(struct device *dev) + + netdev_info(priv->dev, "%s: removing driver", __func__); + ++ pm_runtime_get_sync(dev); ++ pm_runtime_disable(dev); ++ pm_runtime_put_noidle(dev); ++ + stmmac_stop_all_dma(priv); + stmmac_mac_set(priv, priv->ioaddr, false); + netif_carrier_off(ndev); +@@ -7101,8 +7300,6 @@ int stmmac_dvr_remove(struct device *dev) + if (priv->plat->stmmac_rst) + reset_control_assert(priv->plat->stmmac_rst); + reset_control_assert(priv->plat->stmmac_ahb_rst); +- pm_runtime_put(dev); +- pm_runtime_disable(dev); + if (priv->hw->pcs != STMMAC_PCS_TBI && + priv->hw->pcs != STMMAC_PCS_RTBI) + stmmac_mdio_unregister(ndev); +@@ -7280,6 +7477,7 @@ int stmmac_resume(struct device *dev) + stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw); + + stmmac_enable_all_queues(priv); ++ stmmac_enable_all_dma_irq(priv); + + mutex_unlock(&priv->lock); + rtnl_unlock(); +@@ -7296,7 +7494,7 @@ static int __init stmmac_cmdline_opt(char *str) + char *opt; + + if (!str || !*str) +- return -EINVAL; ++ return 1; + while ((opt = strsep(&str, ",")) != NULL) { + if (!strncmp(opt, "debug:", 6)) { + if (kstrtoint(opt + 6, 0, &debug)) +@@ -7327,11 +7525,11 @@ static int __init stmmac_cmdline_opt(char *str) + goto err; + } + } +- return 0; ++ return 1; + + err: + pr_err("%s: ERROR broken module parameter conversion", __func__); +- return -EINVAL; ++ return 1; + } + + __setup("stmmaceth=", stmmac_cmdline_opt); +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 232ac98943cd0..5d29f336315b7 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -816,7 +816,7 @@ static int __maybe_unused stmmac_pltfr_noirq_resume(struct device *dev) + if (ret) + return ret; + +- clk_prepare_enable(priv->plat->clk_ptp_ref); ++ stmmac_init_tstamp_counter(priv, priv->systime_flags); + } + + return 0; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +index 580cc035536bd..ac8bc1c8614d3 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +@@ -102,7 +102,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta) + time.tv_nsec = priv->plat->est->btr_reserve[0]; + time.tv_sec = priv->plat->est->btr_reserve[1]; + basetime = timespec64_to_ktime(time); +- cycle_time = priv->plat->est->ctr[1] * NSEC_PER_SEC + ++ cycle_time = (u64)priv->plat->est->ctr[1] * NSEC_PER_SEC + + priv->plat->est->ctr[0]; + time = stmmac_calc_tas_basetime(basetime, + current_time_ns, +@@ -297,9 +297,6 @@ void stmmac_ptp_register(struct stmmac_priv *priv) + { + int i; + +- if (priv->plat->ptp_clk_freq_config) +- priv->plat->ptp_clk_freq_config(priv); +- + for (i = 0; i < priv->dma_cap.pps_out_num; i++) { + if (i >= STMMAC_PPS_MAX) + break; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 8160087ee92f2..d0a2b289f4603 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -232,11 +232,33 @@ static int tc_setup_cls_u32(struct stmmac_priv *priv, + } + } + ++static int tc_rfs_init(struct stmmac_priv *priv) ++{ ++ int i; ++ ++ priv->rfs_entries_max[STMMAC_RFS_T_VLAN] = 8; ++ ++ for (i = 0; i < STMMAC_RFS_T_MAX; i++) ++ priv->rfs_entries_total += priv->rfs_entries_max[i]; ++ ++ priv->rfs_entries = devm_kcalloc(priv->device, ++ priv->rfs_entries_total, ++ sizeof(*priv->rfs_entries), ++ GFP_KERNEL); ++ if (!priv->rfs_entries) ++ return -ENOMEM; ++ ++ dev_info(priv->device, "Enabled RFS Flow TC (entries=%d)\n", ++ priv->rfs_entries_total); ++ ++ return 0; ++} ++ + static int tc_init(struct stmmac_priv *priv) + { + struct dma_features *dma_cap = &priv->dma_cap; + unsigned int count; +- int i; ++ int ret, i; + + if (dma_cap->l3l4fnum) { + priv->flow_entries_max = dma_cap->l3l4fnum; +@@ -250,10 +272,14 @@ static int tc_init(struct stmmac_priv *priv) + for (i = 0; i < priv->flow_entries_max; i++) + priv->flow_entries[i].idx = i; + +- dev_info(priv->device, "Enabled Flow TC (entries=%d)\n", ++ dev_info(priv->device, "Enabled L3L4 Flow TC (entries=%d)\n", + priv->flow_entries_max); + } + ++ ret = tc_rfs_init(priv); ++ if (ret) ++ return -ENOMEM; ++ + if (!priv->plat->fpe_cfg) { + priv->plat->fpe_cfg = devm_kzalloc(priv->device, + sizeof(*priv->plat->fpe_cfg), +@@ -607,16 +633,45 @@ static int tc_del_flow(struct stmmac_priv *priv, + return ret; + } + ++static struct stmmac_rfs_entry *tc_find_rfs(struct stmmac_priv *priv, ++ struct flow_cls_offload *cls, ++ bool get_free) ++{ ++ int i; ++ ++ for (i = 0; i < priv->rfs_entries_total; i++) { ++ struct stmmac_rfs_entry *entry = &priv->rfs_entries[i]; ++ ++ if (entry->cookie == cls->cookie) ++ return entry; ++ if (get_free && entry->in_use == false) ++ return entry; ++ } ++ ++ return NULL; ++} ++ + #define VLAN_PRIO_FULL_MASK (0x07) + + static int tc_add_vlan_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls) + { ++ struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false); + struct flow_rule *rule = flow_cls_offload_flow_rule(cls); + struct flow_dissector *dissector = rule->match.dissector; + int tc = tc_classid_to_hwtc(priv->dev, cls->classid); + struct flow_match_vlan match; + ++ if (!entry) { ++ entry = tc_find_rfs(priv, cls, true); ++ if (!entry) ++ return -ENOENT; ++ } ++ ++ if (priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN] >= ++ priv->rfs_entries_max[STMMAC_RFS_T_VLAN]) ++ return -ENOENT; ++ + /* Nothing to do here */ + if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN)) + return -EINVAL; +@@ -638,6 +693,12 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv, + + prio = BIT(match.key->vlan_priority); + stmmac_rx_queue_prio(priv, priv->hw, prio, tc); ++ ++ entry->in_use = true; ++ entry->cookie = cls->cookie; ++ entry->tc = tc; ++ entry->type = STMMAC_RFS_T_VLAN; ++ priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]++; + } + + return 0; +@@ -646,20 +707,19 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv, + static int tc_del_vlan_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls) + { +- struct flow_rule *rule = flow_cls_offload_flow_rule(cls); +- struct flow_dissector *dissector = rule->match.dissector; +- int tc = tc_classid_to_hwtc(priv->dev, cls->classid); ++ struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false); + +- /* Nothing to do here */ +- if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN)) +- return -EINVAL; ++ if (!entry || !entry->in_use || entry->type != STMMAC_RFS_T_VLAN) ++ return -ENOENT; + +- if (tc < 0) { +- netdev_err(priv->dev, "Invalid traffic class\n"); +- return -EINVAL; +- } ++ stmmac_rx_queue_prio(priv, priv->hw, 0, entry->tc); ++ ++ entry->in_use = false; ++ entry->cookie = 0; ++ entry->tc = 0; ++ entry->type = 0; + +- stmmac_rx_queue_prio(priv, priv->hw, 0, tc); ++ priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]--; + + return 0; + } +@@ -786,8 +846,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv, + goto disable; + if (qopt->num_entries >= dep) + return -EINVAL; +- if (!qopt->base_time) +- return -ERANGE; + if (!qopt->cycle_time) + return -ERANGE; + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c +index 2a616c6f7cd0e..9d4d8c3dad0a3 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c +@@ -119,7 +119,7 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog, + + need_update = !!priv->xdp_prog != !!prog; + if (if_running && need_update) +- stmmac_release(dev); ++ stmmac_xdp_release(dev); + + old_prog = xchg(&priv->xdp_prog, prog); + if (old_prog) +@@ -129,7 +129,7 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog, + priv->sph = priv->sph_cap && !stmmac_xdp_is_enabled(priv); + + if (if_running && need_update) +- stmmac_open(dev); ++ stmmac_xdp_open(dev); + + return 0; + } +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 66f7ddd9b1f99..e226ecd95a2cc 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -349,7 +349,7 @@ static void cpsw_rx_handler(void *token, int len, int status) + struct cpsw_common *cpsw = ndev_to_cpsw(xmeta->ndev); + int pkt_size = cpsw->rx_packet_max; + int ret = 0, port, ch = xmeta->ch; +- int headroom = CPSW_HEADROOM; ++ int headroom = CPSW_HEADROOM_NA; + struct net_device *ndev = xmeta->ndev; + struct cpsw_priv *priv; + struct page_pool *pool; +@@ -392,7 +392,7 @@ static void cpsw_rx_handler(void *token, int len, int status) + } + + if (priv->xdp_prog) { +- int headroom = CPSW_HEADROOM, size = len; ++ int size = len; + + xdp_init_buff(&xdp, PAGE_SIZE, &priv->xdp_rxq[ch]); + if (status & CPDMA_RX_VLAN_ENCAP) { +@@ -442,7 +442,7 @@ requeue: + xmeta->ndev = ndev; + xmeta->ch = ch; + +- dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM; ++ dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM_NA; + ret = cpdma_chan_submit_mapped(cpsw->rxv[ch].ch, new_page, dma, + pkt_size, 0); + if (ret < 0) { +diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c +index 0c75e0576ee1f..1ef0aaef5c61c 100644 +--- a/drivers/net/ethernet/ti/cpsw_ale.c ++++ b/drivers/net/ethernet/ti/cpsw_ale.c +@@ -1299,10 +1299,8 @@ struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params) + if (!ale) + return ERR_PTR(-ENOMEM); + +- ale->p0_untag_vid_mask = +- devm_kmalloc_array(params->dev, BITS_TO_LONGS(VLAN_N_VID), +- sizeof(unsigned long), +- GFP_KERNEL); ++ ale->p0_untag_vid_mask = devm_bitmap_zalloc(params->dev, VLAN_N_VID, ++ GFP_KERNEL); + if (!ale->p0_untag_vid_mask) + return ERR_PTR(-ENOMEM); + +diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c +index 7968f24d99c85..9e16afbdbdc1d 100644 +--- a/drivers/net/ethernet/ti/cpsw_new.c ++++ b/drivers/net/ethernet/ti/cpsw_new.c +@@ -283,7 +283,7 @@ static void cpsw_rx_handler(void *token, int len, int status) + { + struct page *new_page, *page = token; + void *pa = page_address(page); +- int headroom = CPSW_HEADROOM; ++ int headroom = CPSW_HEADROOM_NA; + struct cpsw_meta_xdp *xmeta; + struct cpsw_common *cpsw; + struct net_device *ndev; +@@ -336,7 +336,7 @@ static void cpsw_rx_handler(void *token, int len, int status) + } + + if (priv->xdp_prog) { +- int headroom = CPSW_HEADROOM, size = len; ++ int size = len; + + xdp_init_buff(&xdp, PAGE_SIZE, &priv->xdp_rxq[ch]); + if (status & CPDMA_RX_VLAN_ENCAP) { +@@ -386,7 +386,7 @@ requeue: + xmeta->ndev = ndev; + xmeta->ch = ch; + +- dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM; ++ dma = page_pool_get_dma_addr(new_page) + CPSW_HEADROOM_NA; + ret = cpdma_chan_submit_mapped(cpsw->rxv[ch].ch, new_page, dma, + pkt_size, 0); + if (ret < 0) { +diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c +index ecc2a6b7e28f2..f8e591d69d2cb 100644 +--- a/drivers/net/ethernet/ti/cpsw_priv.c ++++ b/drivers/net/ethernet/ti/cpsw_priv.c +@@ -1120,7 +1120,7 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv) + xmeta->ndev = priv->ndev; + xmeta->ch = ch; + +- dma = page_pool_get_dma_addr(page) + CPSW_HEADROOM; ++ dma = page_pool_get_dma_addr(page) + CPSW_HEADROOM_NA; + ret = cpdma_chan_idle_submit_mapped(cpsw->rxv[ch].ch, + page, dma, + cpsw->rx_packet_max, +@@ -1144,7 +1144,7 @@ int cpsw_fill_rx_channels(struct cpsw_priv *priv) + static struct page_pool *cpsw_create_page_pool(struct cpsw_common *cpsw, + int size) + { +- struct page_pool_params pp_params; ++ struct page_pool_params pp_params = {}; + struct page_pool *pool; + + pp_params.order = 0; +diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c +index e8291d8488391..d243ca5dfde00 100644 +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -420,8 +420,20 @@ static int emac_set_coalesce(struct net_device *ndev, + u32 int_ctrl, num_interrupts = 0; + u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0; + +- if (!coal->rx_coalesce_usecs) +- return -EINVAL; ++ if (!coal->rx_coalesce_usecs) { ++ priv->coal_intvl = 0; ++ ++ switch (priv->version) { ++ case EMAC_VERSION_2: ++ emac_ctrl_write(EMAC_DM646X_CMINTCTRL, 0); ++ break; ++ default: ++ emac_ctrl_write(EMAC_CTRL_EWINTTCNT, 0); ++ break; ++ } ++ ++ return 0; ++ } + + coal_intvl = coal->rx_coalesce_usecs; + +diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c +index 463094ced104a..2ab29efa6b6e4 100644 +--- a/drivers/net/ethernet/xilinx/ll_temac_main.c ++++ b/drivers/net/ethernet/xilinx/ll_temac_main.c +@@ -1427,6 +1427,8 @@ static int temac_probe(struct platform_device *pdev) + lp->indirect_lock = devm_kmalloc(&pdev->dev, + sizeof(*lp->indirect_lock), + GFP_KERNEL); ++ if (!lp->indirect_lock) ++ return -ENOMEM; + spin_lock_init(lp->indirect_lock); + } + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 871b5ec3183d6..2169417210c2b 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -41,8 +41,9 @@ + #include "xilinx_axienet.h" + + /* Descriptors defines for Tx and Rx DMA */ +-#define TX_BD_NUM_DEFAULT 64 ++#define TX_BD_NUM_DEFAULT 128 + #define RX_BD_NUM_DEFAULT 1024 ++#define TX_BD_NUM_MIN (MAX_SKB_FRAGS + 1) + #define TX_BD_NUM_MAX 4096 + #define RX_BD_NUM_MAX 4096 + +@@ -496,7 +497,8 @@ static void axienet_setoptions(struct net_device *ndev, u32 options) + + static int __axienet_device_reset(struct axienet_local *lp) + { +- u32 timeout; ++ u32 value; ++ int ret; + + /* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset + * process of Axi DMA takes a while to complete as all pending +@@ -506,15 +508,23 @@ static int __axienet_device_reset(struct axienet_local *lp) + * they both reset the entire DMA core, so only one needs to be used. + */ + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, XAXIDMA_CR_RESET_MASK); +- timeout = DELAY_OF_ONE_MILLISEC; +- while (axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET) & +- XAXIDMA_CR_RESET_MASK) { +- udelay(1); +- if (--timeout == 0) { +- netdev_err(lp->ndev, "%s: DMA reset timeout!\n", +- __func__); +- return -ETIMEDOUT; +- } ++ ret = read_poll_timeout(axienet_dma_in32, value, ++ !(value & XAXIDMA_CR_RESET_MASK), ++ DELAY_OF_ONE_MILLISEC, 50000, false, lp, ++ XAXIDMA_TX_CR_OFFSET); ++ if (ret) { ++ dev_err(lp->dev, "%s: DMA reset timeout!\n", __func__); ++ return ret; ++ } ++ ++ /* Wait for PhyRstCmplt bit to be set, indicating the PHY reset has finished */ ++ ret = read_poll_timeout(axienet_ior, value, ++ value & XAE_INT_PHYRSTCMPLT_MASK, ++ DELAY_OF_ONE_MILLISEC, 50000, false, lp, ++ XAE_IS_OFFSET); ++ if (ret) { ++ dev_err(lp->dev, "%s: timeout waiting for PhyRstCmplt\n", __func__); ++ return ret; + } + + return 0; +@@ -623,6 +633,8 @@ static int axienet_free_tx_chain(struct net_device *ndev, u32 first_bd, + if (nr_bds == -1 && !(status & XAXIDMA_BD_STS_COMPLETE_MASK)) + break; + ++ /* Ensure we see complete descriptor update */ ++ dma_rmb(); + phys = desc_get_phys_addr(lp, cur_p); + dma_unmap_single(ndev->dev.parent, phys, + (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), +@@ -631,13 +643,15 @@ static int axienet_free_tx_chain(struct net_device *ndev, u32 first_bd, + if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) + dev_consume_skb_irq(cur_p->skb); + +- cur_p->cntrl = 0; + cur_p->app0 = 0; + cur_p->app1 = 0; + cur_p->app2 = 0; + cur_p->app4 = 0; +- cur_p->status = 0; + cur_p->skb = NULL; ++ /* ensure our transmit path and device don't prematurely see status cleared */ ++ wmb(); ++ cur_p->cntrl = 0; ++ cur_p->status = 0; + + if (sizep) + *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; +@@ -646,6 +660,32 @@ static int axienet_free_tx_chain(struct net_device *ndev, u32 first_bd, + return i; + } + ++/** ++ * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy ++ * @lp: Pointer to the axienet_local structure ++ * @num_frag: The number of BDs to check for ++ * ++ * Return: 0, on success ++ * NETDEV_TX_BUSY, if any of the descriptors are not free ++ * ++ * This function is invoked before BDs are allocated and transmission starts. ++ * This function returns 0 if a BD or group of BDs can be allocated for ++ * transmission. If the BD or any of the BDs are not free the function ++ * returns a busy status. This is invoked from axienet_start_xmit. ++ */ ++static inline int axienet_check_tx_bd_space(struct axienet_local *lp, ++ int num_frag) ++{ ++ struct axidma_bd *cur_p; ++ ++ /* Ensure we see all descriptor updates from device or TX IRQ path */ ++ rmb(); ++ cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % lp->tx_bd_num]; ++ if (cur_p->cntrl) ++ return NETDEV_TX_BUSY; ++ return 0; ++} ++ + /** + * axienet_start_xmit_done - Invoked once a transmit is completed by the + * Axi DMA Tx channel. +@@ -675,30 +715,8 @@ static void axienet_start_xmit_done(struct net_device *ndev) + /* Matches barrier in axienet_start_xmit */ + smp_mb(); + +- netif_wake_queue(ndev); +-} +- +-/** +- * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy +- * @lp: Pointer to the axienet_local structure +- * @num_frag: The number of BDs to check for +- * +- * Return: 0, on success +- * NETDEV_TX_BUSY, if any of the descriptors are not free +- * +- * This function is invoked before BDs are allocated and transmission starts. +- * This function returns 0 if a BD or group of BDs can be allocated for +- * transmission. If the BD or any of the BDs are not free the function +- * returns a busy status. This is invoked from axienet_start_xmit. +- */ +-static inline int axienet_check_tx_bd_space(struct axienet_local *lp, +- int num_frag) +-{ +- struct axidma_bd *cur_p; +- cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % lp->tx_bd_num]; +- if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK) +- return NETDEV_TX_BUSY; +- return 0; ++ if (!axienet_check_tx_bd_space(lp, MAX_SKB_FRAGS + 1)) ++ netif_wake_queue(ndev); + } + + /** +@@ -730,20 +748,15 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) + num_frag = skb_shinfo(skb)->nr_frags; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + +- if (axienet_check_tx_bd_space(lp, num_frag)) { +- if (netif_queue_stopped(ndev)) +- return NETDEV_TX_BUSY; +- ++ if (axienet_check_tx_bd_space(lp, num_frag + 1)) { ++ /* Should not happen as last start_xmit call should have ++ * checked for sufficient space and queue should only be ++ * woken when sufficient space is available. ++ */ + netif_stop_queue(ndev); +- +- /* Matches barrier in axienet_start_xmit_done */ +- smp_mb(); +- +- /* Space might have just been freed - check again */ +- if (axienet_check_tx_bd_space(lp, num_frag)) +- return NETDEV_TX_BUSY; +- +- netif_wake_queue(ndev); ++ if (net_ratelimit()) ++ netdev_warn(ndev, "TX ring unexpectedly full\n"); ++ return NETDEV_TX_BUSY; + } + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +@@ -804,6 +817,18 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev) + if (++lp->tx_bd_tail >= lp->tx_bd_num) + lp->tx_bd_tail = 0; + ++ /* Stop queue if next transmit may not have space */ ++ if (axienet_check_tx_bd_space(lp, MAX_SKB_FRAGS + 1)) { ++ netif_stop_queue(ndev); ++ ++ /* Matches barrier in axienet_start_xmit_done */ ++ smp_mb(); ++ ++ /* Space might have just been freed - check again */ ++ if (!axienet_check_tx_bd_space(lp, MAX_SKB_FRAGS + 1)) ++ netif_wake_queue(ndev); ++ } ++ + return NETDEV_TX_OK; + } + +@@ -834,6 +859,8 @@ static void axienet_recv(struct net_device *ndev) + + tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; + ++ /* Ensure we see complete descriptor update */ ++ dma_rmb(); + phys = desc_get_phys_addr(lp, cur_p); + dma_unmap_single(ndev->dev.parent, phys, lp->max_frm_size, + DMA_FROM_DEVICE); +@@ -1346,7 +1373,8 @@ static int axienet_ethtools_set_ringparam(struct net_device *ndev, + if (ering->rx_pending > RX_BD_NUM_MAX || + ering->rx_mini_pending || + ering->rx_jumbo_pending || +- ering->rx_pending > TX_BD_NUM_MAX) ++ ering->tx_pending < TX_BD_NUM_MIN || ++ ering->tx_pending > TX_BD_NUM_MAX) + return -EINVAL; + + if (netif_running(ndev)) +@@ -2082,6 +2110,11 @@ static int axienet_probe(struct platform_device *pdev) + lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; + lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; + ++ /* Reset core now that clocks are enabled, prior to accessing MDIO */ ++ ret = __axienet_device_reset(lp); ++ if (ret) ++ goto cleanup_clk; ++ + lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); + if (lp->phy_node) { + ret = axienet_mdio_setup(lp); +diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c +index 185c8a3986816..1d1808afd5295 100644 +--- a/drivers/net/fjes/fjes_main.c ++++ b/drivers/net/fjes/fjes_main.c +@@ -1261,6 +1261,11 @@ static int fjes_probe(struct platform_device *plat_dev) + hw->hw_res.start = res->start; + hw->hw_res.size = resource_size(res); + hw->hw_res.irq = platform_get_irq(plat_dev, 0); ++ if (hw->hw_res.irq < 0) { ++ err = hw->hw_res.irq; ++ goto err_free_control_wq; ++ } ++ + err = fjes_hw_init(&adapter->hw); + if (err) + goto err_free_control_wq; +diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c +index 8666110bec555..763d435a9564c 100644 +--- a/drivers/net/hamradio/mkiss.c ++++ b/drivers/net/hamradio/mkiss.c +@@ -31,6 +31,8 @@ + + #define AX_MTU 236 + ++/* some arch define END as assembly function ending, just undef it */ ++#undef END + /* SLIP/KISS protocol characters. */ + #define END 0300 /* indicates end of frame */ + #define ESC 0333 /* indicates byte stuffing */ +@@ -792,13 +794,14 @@ static void mkiss_close(struct tty_struct *tty) + */ + netif_stop_queue(ax->dev); + +- /* Free all AX25 frame buffers. */ ++ unregister_netdev(ax->dev); ++ ++ /* Free all AX25 frame buffers after unreg. */ + kfree(ax->rbuff); + kfree(ax->xbuff); + + ax->tty = NULL; + +- unregister_netdev(ax->dev); + free_netdev(ax->dev); + } + +diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c +index 6ddacbdb224ba..528d57a435394 100644 +--- a/drivers/net/hamradio/yam.c ++++ b/drivers/net/hamradio/yam.c +@@ -950,9 +950,7 @@ static int yam_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __ + ym = memdup_user(data, sizeof(struct yamdrv_ioctl_mcs)); + if (IS_ERR(ym)) + return PTR_ERR(ym); +- if (ym->cmd != SIOCYAMSMCS) +- return -EINVAL; +- if (ym->bitrate > YAM_MAXBITRATE) { ++ if (ym->cmd != SIOCYAMSMCS || ym->bitrate > YAM_MAXBITRATE) { + kfree(ym); + return -EINVAL; + } +diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c +index 7d67f41387f55..4f5ef8a9a9a87 100644 +--- a/drivers/net/ieee802154/at86rf230.c ++++ b/drivers/net/ieee802154/at86rf230.c +@@ -100,6 +100,7 @@ struct at86rf230_local { + unsigned long cal_timeout; + bool is_tx; + bool is_tx_from_off; ++ bool was_tx; + u8 tx_retry; + struct sk_buff *tx_skb; + struct at86rf230_state_change tx; +@@ -343,7 +344,11 @@ at86rf230_async_error_recover_complete(void *context) + if (ctx->free) + kfree(ctx); + +- ieee802154_wake_queue(lp->hw); ++ if (lp->was_tx) { ++ lp->was_tx = 0; ++ dev_kfree_skb_any(lp->tx_skb); ++ ieee802154_wake_queue(lp->hw); ++ } + } + + static void +@@ -352,7 +357,11 @@ at86rf230_async_error_recover(void *context) + struct at86rf230_state_change *ctx = context; + struct at86rf230_local *lp = ctx->lp; + +- lp->is_tx = 0; ++ if (lp->is_tx) { ++ lp->was_tx = 1; ++ lp->is_tx = 0; ++ } ++ + at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, + at86rf230_async_error_recover_complete); + } +diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c +index 23ee0b14cbfa1..2f5e7b31032aa 100644 +--- a/drivers/net/ieee802154/atusb.c ++++ b/drivers/net/ieee802154/atusb.c +@@ -93,7 +93,9 @@ static int atusb_control_msg(struct atusb *atusb, unsigned int pipe, + + ret = usb_control_msg(usb_dev, pipe, request, requesttype, + value, index, data, size, timeout); +- if (ret < 0) { ++ if (ret < size) { ++ ret = ret < 0 ? ret : -ENODATA; ++ + atusb->err = ret; + dev_err(&usb_dev->dev, + "%s: req 0x%02x val 0x%x idx 0x%x, error %d\n", +@@ -861,9 +863,9 @@ static int atusb_get_and_show_build(struct atusb *atusb) + if (!build) + return -ENOMEM; + +- ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), +- ATUSB_BUILD, ATUSB_REQ_FROM_DEV, 0, 0, +- build, ATUSB_BUILD_SIZE, 1000); ++ /* We cannot call atusb_control_msg() here, since this request may read various length data */ ++ ret = usb_control_msg(atusb->usb_dev, usb_rcvctrlpipe(usb_dev, 0), ATUSB_BUILD, ++ ATUSB_REQ_FROM_DEV, 0, 0, build, ATUSB_BUILD_SIZE, 1000); + if (ret >= 0) { + build[ret] = 0; + dev_info(&usb_dev->dev, "Firmware: build %s\n", build); +diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c +index 3a2824f24caa8..96592a20c61ff 100644 +--- a/drivers/net/ieee802154/ca8210.c ++++ b/drivers/net/ieee802154/ca8210.c +@@ -1771,6 +1771,7 @@ static int ca8210_async_xmit_complete( + status + ); + if (status != MAC_TRANSACTION_OVERFLOW) { ++ dev_kfree_skb_any(priv->tx_skb); + ieee802154_wake_queue(priv->hw); + return 0; + } +@@ -2976,8 +2977,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw) + ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND; + ca8210_hw->phy->cca_ed_level = -9800; + ca8210_hw->phy->symbol_duration = 16; +- ca8210_hw->phy->lifs_period = 40; +- ca8210_hw->phy->sifs_period = 12; ++ ca8210_hw->phy->lifs_period = 40 * ca8210_hw->phy->symbol_duration; ++ ca8210_hw->phy->sifs_period = 12 * ca8210_hw->phy->symbol_duration; + ca8210_hw->flags = + IEEE802154_HW_AFILT | + IEEE802154_HW_OMIT_CKSUM | +diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c +index 8caa61ec718f5..36f1c5aa98fc6 100644 +--- a/drivers/net/ieee802154/mac802154_hwsim.c ++++ b/drivers/net/ieee802154/mac802154_hwsim.c +@@ -786,6 +786,7 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev, + goto err_pib; + } + ++ pib->channel = 13; + rcu_assign_pointer(phy->pib, pib); + phy->idx = idx; + INIT_LIST_HEAD(&phy->edges); +diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c +index 8dc04e2590b18..383231b854642 100644 +--- a/drivers/net/ieee802154/mcr20a.c ++++ b/drivers/net/ieee802154/mcr20a.c +@@ -976,8 +976,8 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) + dev_dbg(printdev(lp), "%s\n", __func__); + + phy->symbol_duration = 16; +- phy->lifs_period = 40; +- phy->sifs_period = 12; ++ phy->lifs_period = 40 * phy->symbol_duration; ++ phy->sifs_period = 12 * phy->symbol_duration; + + hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | + IEEE802154_HW_AFILT | +diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c +index e9258a9f3702c..31bc02421dd4e 100644 +--- a/drivers/net/ifb.c ++++ b/drivers/net/ifb.c +@@ -76,7 +76,9 @@ static void ifb_ri_tasklet(struct tasklet_struct *t) + + while ((skb = __skb_dequeue(&txp->tq)) != NULL) { + skb->redirected = 0; ++#ifdef CONFIG_NET_CLS_ACT + skb->tc_skip_classify = 1; ++#endif + + u64_stats_update_begin(&txp->tsync); + txp->tx_packets++; +diff --git a/drivers/net/ipa/Kconfig b/drivers/net/ipa/Kconfig +index d037682fb7adb..3e0da1e764718 100644 +--- a/drivers/net/ipa/Kconfig ++++ b/drivers/net/ipa/Kconfig +@@ -2,6 +2,7 @@ config QCOM_IPA + tristate "Qualcomm IPA support" + depends on NET && QCOM_SMEM + depends on ARCH_QCOM || COMPILE_TEST ++ depends on INTERCONNECT + depends on QCOM_RPROC_COMMON || (QCOM_RPROC_COMMON=n && COMPILE_TEST) + select QCOM_MDT_LOADER if ARCH_QCOM + select QCOM_SCM +diff --git a/drivers/net/ipa/ipa_cmd.c b/drivers/net/ipa/ipa_cmd.c +index cff51731195aa..d57472ea077f2 100644 +--- a/drivers/net/ipa/ipa_cmd.c ++++ b/drivers/net/ipa/ipa_cmd.c +@@ -661,22 +661,6 @@ void ipa_cmd_pipeline_clear_wait(struct ipa *ipa) + wait_for_completion(&ipa->completion); + } + +-void ipa_cmd_pipeline_clear(struct ipa *ipa) +-{ +- u32 count = ipa_cmd_pipeline_clear_count(); +- struct gsi_trans *trans; +- +- trans = ipa_cmd_trans_alloc(ipa, count); +- if (trans) { +- ipa_cmd_pipeline_clear_add(trans); +- gsi_trans_commit_wait(trans); +- ipa_cmd_pipeline_clear_wait(ipa); +- } else { +- dev_err(&ipa->pdev->dev, +- "error allocating %u entry tag transaction\n", count); +- } +-} +- + static struct ipa_cmd_info * + ipa_cmd_info_alloc(struct ipa_endpoint *endpoint, u32 tre_count) + { +diff --git a/drivers/net/ipa/ipa_cmd.h b/drivers/net/ipa/ipa_cmd.h +index 69cd085d427db..05ed7e42e1842 100644 +--- a/drivers/net/ipa/ipa_cmd.h ++++ b/drivers/net/ipa/ipa_cmd.h +@@ -163,12 +163,6 @@ u32 ipa_cmd_pipeline_clear_count(void); + */ + void ipa_cmd_pipeline_clear_wait(struct ipa *ipa); + +-/** +- * ipa_cmd_pipeline_clear() - Clear the hardware pipeline +- * @ipa: - IPA pointer +- */ +-void ipa_cmd_pipeline_clear(struct ipa *ipa); +- + /** + * ipa_cmd_trans_alloc() - Allocate a transaction for the command TX endpoint + * @ipa: IPA pointer +diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c +index 5528d97110d56..87e42db1b61e6 100644 +--- a/drivers/net/ipa/ipa_endpoint.c ++++ b/drivers/net/ipa/ipa_endpoint.c +@@ -853,6 +853,7 @@ static void ipa_endpoint_init_hol_block_timer(struct ipa_endpoint *endpoint, + u32 offset; + u32 val; + ++ /* This should only be changed when HOL_BLOCK_EN is disabled */ + offset = IPA_REG_ENDP_INIT_HOL_BLOCK_TIMER_N_OFFSET(endpoint_id); + val = hol_block_timer_val(ipa, microseconds); + iowrite32(val, ipa->reg_virt + offset); +@@ -868,6 +869,9 @@ ipa_endpoint_init_hol_block_enable(struct ipa_endpoint *endpoint, bool enable) + val = enable ? HOL_BLOCK_EN_FMASK : 0; + offset = IPA_REG_ENDP_INIT_HOL_BLOCK_EN_N_OFFSET(endpoint_id); + iowrite32(val, endpoint->ipa->reg_virt + offset); ++ /* When enabling, the register must be written twice for IPA v4.5+ */ ++ if (enable && endpoint->ipa->version >= IPA_VERSION_4_5) ++ iowrite32(val, endpoint->ipa->reg_virt + offset); + } + + void ipa_endpoint_modem_hol_block_clear_all(struct ipa *ipa) +@@ -880,6 +884,7 @@ void ipa_endpoint_modem_hol_block_clear_all(struct ipa *ipa) + if (endpoint->toward_ipa || endpoint->ee_id != GSI_EE_MODEM) + continue; + ++ ipa_endpoint_init_hol_block_enable(endpoint, false); + ipa_endpoint_init_hol_block_timer(endpoint, 0); + ipa_endpoint_init_hol_block_enable(endpoint, true); + } +@@ -1062,27 +1067,38 @@ static void ipa_endpoint_replenish(struct ipa_endpoint *endpoint, bool add_one) + { + struct gsi *gsi; + u32 backlog; ++ int delta; + +- if (!endpoint->replenish_enabled) { ++ if (!test_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags)) { + if (add_one) + atomic_inc(&endpoint->replenish_saved); + return; + } + ++ /* If already active, just update the backlog */ ++ if (test_and_set_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags)) { ++ if (add_one) ++ atomic_inc(&endpoint->replenish_backlog); ++ return; ++ } ++ + while (atomic_dec_not_zero(&endpoint->replenish_backlog)) + if (ipa_endpoint_replenish_one(endpoint)) + goto try_again_later; ++ ++ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags); ++ + if (add_one) + atomic_inc(&endpoint->replenish_backlog); + + return; + + try_again_later: +- /* The last one didn't succeed, so fix the backlog */ +- backlog = atomic_inc_return(&endpoint->replenish_backlog); ++ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags); + +- if (add_one) +- atomic_inc(&endpoint->replenish_backlog); ++ /* The last one didn't succeed, so fix the backlog */ ++ delta = add_one ? 2 : 1; ++ backlog = atomic_add_return(delta, &endpoint->replenish_backlog); + + /* Whenever a receive buffer transaction completes we'll try to + * replenish again. It's unlikely, but if we fail to supply even +@@ -1102,7 +1118,7 @@ static void ipa_endpoint_replenish_enable(struct ipa_endpoint *endpoint) + u32 max_backlog; + u32 saved; + +- endpoint->replenish_enabled = true; ++ set_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags); + while ((saved = atomic_xchg(&endpoint->replenish_saved, 0))) + atomic_add(saved, &endpoint->replenish_backlog); + +@@ -1116,7 +1132,7 @@ static void ipa_endpoint_replenish_disable(struct ipa_endpoint *endpoint) + { + u32 backlog; + +- endpoint->replenish_enabled = false; ++ clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags); + while ((backlog = atomic_xchg(&endpoint->replenish_backlog, 0))) + atomic_add(backlog, &endpoint->replenish_saved); + } +@@ -1631,8 +1647,6 @@ void ipa_endpoint_suspend(struct ipa *ipa) + if (ipa->modem_netdev) + ipa_modem_suspend(ipa->modem_netdev); + +- ipa_cmd_pipeline_clear(ipa); +- + ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_LAN_RX]); + ipa_endpoint_suspend_one(ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]); + } +@@ -1663,7 +1677,8 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *endpoint) + /* RX transactions require a single TRE, so the maximum + * backlog is the same as the maximum outstanding TREs. + */ +- endpoint->replenish_enabled = false; ++ clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags); ++ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags); + atomic_set(&endpoint->replenish_saved, + gsi_channel_tre_max(gsi, endpoint->channel_id)); + atomic_set(&endpoint->replenish_backlog, 0); +diff --git a/drivers/net/ipa/ipa_endpoint.h b/drivers/net/ipa/ipa_endpoint.h +index 0a859d10312dc..0313cdc607de3 100644 +--- a/drivers/net/ipa/ipa_endpoint.h ++++ b/drivers/net/ipa/ipa_endpoint.h +@@ -40,6 +40,19 @@ enum ipa_endpoint_name { + + #define IPA_ENDPOINT_MAX 32 /* Max supported by driver */ + ++/** ++ * enum ipa_replenish_flag: RX buffer replenish flags ++ * ++ * @IPA_REPLENISH_ENABLED: Whether receive buffer replenishing is enabled ++ * @IPA_REPLENISH_ACTIVE: Whether replenishing is underway ++ * @IPA_REPLENISH_COUNT: Number of defined replenish flags ++ */ ++enum ipa_replenish_flag { ++ IPA_REPLENISH_ENABLED, ++ IPA_REPLENISH_ACTIVE, ++ IPA_REPLENISH_COUNT, /* Number of flags (must be last) */ ++}; ++ + /** + * struct ipa_endpoint - IPA endpoint information + * @ipa: IPA pointer +@@ -51,7 +64,7 @@ enum ipa_endpoint_name { + * @trans_tre_max: Maximum number of TRE descriptors per transaction + * @evt_ring_id: GSI event ring used by the endpoint + * @netdev: Network device pointer, if endpoint uses one +- * @replenish_enabled: Whether receive buffer replenishing is enabled ++ * @replenish_flags: Replenishing state flags + * @replenish_ready: Number of replenish transactions without doorbell + * @replenish_saved: Replenish requests held while disabled + * @replenish_backlog: Number of buffers needed to fill hardware queue +@@ -72,7 +85,7 @@ struct ipa_endpoint { + struct net_device *netdev; + + /* Receive buffer replenishing for RX endpoints */ +- bool replenish_enabled; ++ DECLARE_BITMAP(replenish_flags, IPA_REPLENISH_COUNT); + u32 replenish_ready; + atomic_t replenish_saved; + atomic_t replenish_backlog; +diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c +index cdfa98a76e1f4..a448ec198bee1 100644 +--- a/drivers/net/ipa/ipa_main.c ++++ b/drivers/net/ipa/ipa_main.c +@@ -28,6 +28,7 @@ + #include "ipa_reg.h" + #include "ipa_mem.h" + #include "ipa_table.h" ++#include "ipa_smp2p.h" + #include "ipa_modem.h" + #include "ipa_uc.h" + #include "ipa_interrupt.h" +@@ -801,6 +802,11 @@ static int ipa_remove(struct platform_device *pdev) + struct device *dev = &pdev->dev; + int ret; + ++ /* Prevent the modem from triggering a call to ipa_setup(). This ++ * also ensures a modem-initiated setup that's underway completes. ++ */ ++ ipa_smp2p_irq_disable_setup(ipa); ++ + ret = pm_runtime_get_sync(dev); + if (WARN_ON(ret < 0)) + goto out_power_put; +diff --git a/drivers/net/ipa/ipa_modem.c b/drivers/net/ipa/ipa_modem.c +index ad116bcc0580e..d0ab4d70c303b 100644 +--- a/drivers/net/ipa/ipa_modem.c ++++ b/drivers/net/ipa/ipa_modem.c +@@ -339,9 +339,6 @@ int ipa_modem_stop(struct ipa *ipa) + if (state != IPA_MODEM_STATE_RUNNING) + return -EBUSY; + +- /* Prevent the modem from triggering a call to ipa_setup() */ +- ipa_smp2p_disable(ipa); +- + /* Clean up the netdev and endpoints if it was started */ + if (netdev) { + struct ipa_priv *priv = netdev_priv(netdev); +@@ -369,6 +366,9 @@ static void ipa_modem_crashed(struct ipa *ipa) + struct device *dev = &ipa->pdev->dev; + int ret; + ++ /* Prevent the modem from triggering a call to ipa_setup() */ ++ ipa_smp2p_irq_disable_setup(ipa); ++ + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "error %d getting power to handle crash\n", ret); +diff --git a/drivers/net/ipa/ipa_resource.c b/drivers/net/ipa/ipa_resource.c +index e3da95d694099..06cec71993823 100644 +--- a/drivers/net/ipa/ipa_resource.c ++++ b/drivers/net/ipa/ipa_resource.c +@@ -52,7 +52,7 @@ static bool ipa_resource_limits_valid(struct ipa *ipa, + return false; + } + +- group_count = data->rsrc_group_src_count; ++ group_count = data->rsrc_group_dst_count; + if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX) + return false; + +diff --git a/drivers/net/ipa/ipa_smp2p.c b/drivers/net/ipa/ipa_smp2p.c +index df7639c39d716..2112336120391 100644 +--- a/drivers/net/ipa/ipa_smp2p.c ++++ b/drivers/net/ipa/ipa_smp2p.c +@@ -53,7 +53,7 @@ + * @setup_ready_irq: IPA interrupt triggered by modem to signal GSI ready + * @power_on: Whether IPA power is on + * @notified: Whether modem has been notified of power state +- * @disabled: Whether setup ready interrupt handling is disabled ++ * @setup_disabled: Whether setup ready interrupt handler is disabled + * @mutex: Mutex protecting ready-interrupt/shutdown interlock + * @panic_notifier: Panic notifier structure + */ +@@ -67,7 +67,7 @@ struct ipa_smp2p { + u32 setup_ready_irq; + bool power_on; + bool notified; +- bool disabled; ++ bool setup_disabled; + struct mutex mutex; + struct notifier_block panic_notifier; + }; +@@ -155,11 +155,9 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id) + struct device *dev; + int ret; + +- mutex_lock(&smp2p->mutex); +- +- if (smp2p->disabled) +- goto out_mutex_unlock; +- smp2p->disabled = true; /* If any others arrive, ignore them */ ++ /* Ignore any (spurious) interrupts received after the first */ ++ if (smp2p->ipa->setup_complete) ++ return IRQ_HANDLED; + + /* Power needs to be active for setup */ + dev = &smp2p->ipa->pdev->dev; +@@ -176,8 +174,6 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id) + out_power_put: + pm_runtime_mark_last_busy(dev); + (void)pm_runtime_put_autosuspend(dev); +-out_mutex_unlock: +- mutex_unlock(&smp2p->mutex); + + return IRQ_HANDLED; + } +@@ -313,7 +309,7 @@ void ipa_smp2p_exit(struct ipa *ipa) + kfree(smp2p); + } + +-void ipa_smp2p_disable(struct ipa *ipa) ++void ipa_smp2p_irq_disable_setup(struct ipa *ipa) + { + struct ipa_smp2p *smp2p = ipa->smp2p; + +@@ -322,7 +318,10 @@ void ipa_smp2p_disable(struct ipa *ipa) + + mutex_lock(&smp2p->mutex); + +- smp2p->disabled = true; ++ if (!smp2p->setup_disabled) { ++ disable_irq(smp2p->setup_ready_irq); ++ smp2p->setup_disabled = true; ++ } + + mutex_unlock(&smp2p->mutex); + } +diff --git a/drivers/net/ipa/ipa_smp2p.h b/drivers/net/ipa/ipa_smp2p.h +index 99a9567896388..59cee31a73836 100644 +--- a/drivers/net/ipa/ipa_smp2p.h ++++ b/drivers/net/ipa/ipa_smp2p.h +@@ -27,13 +27,12 @@ int ipa_smp2p_init(struct ipa *ipa, bool modem_init); + void ipa_smp2p_exit(struct ipa *ipa); + + /** +- * ipa_smp2p_disable() - Prevent "ipa-setup-ready" interrupt handling ++ * ipa_smp2p_irq_disable_setup() - Disable the "setup ready" interrupt + * @ipa: IPA pointer + * +- * Prevent handling of the "setup ready" interrupt from the modem. +- * This is used before initiating shutdown of the driver. ++ * Disable the "ipa-setup-ready" interrupt from the modem. + */ +-void ipa_smp2p_disable(struct ipa *ipa); ++void ipa_smp2p_irq_disable_setup(struct ipa *ipa); + + /** + * ipa_smp2p_notify_reset() - Reset modem notification state +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index 93dc48b9b4f24..e53b40359fd10 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -3870,6 +3870,18 @@ static void macsec_common_dellink(struct net_device *dev, struct list_head *head + struct macsec_dev *macsec = macsec_priv(dev); + struct net_device *real_dev = macsec->real_dev; + ++ /* If h/w offloading is available, propagate to the device */ ++ if (macsec_is_offloaded(macsec)) { ++ const struct macsec_ops *ops; ++ struct macsec_context ctx; ++ ++ ops = macsec_get_ops(netdev_priv(dev), &ctx); ++ if (ops) { ++ ctx.secy = &macsec->secy; ++ macsec_offload(ops->mdo_del_secy, &ctx); ++ } ++ } ++ + unregister_netdevice_queue(dev, head); + list_del_rcu(&macsec->secys); + macsec_del_dev(macsec); +@@ -3884,18 +3896,6 @@ static void macsec_dellink(struct net_device *dev, struct list_head *head) + struct net_device *real_dev = macsec->real_dev; + struct macsec_rxh_data *rxd = macsec_data_rtnl(real_dev); + +- /* If h/w offloading is available, propagate to the device */ +- if (macsec_is_offloaded(macsec)) { +- const struct macsec_ops *ops; +- struct macsec_context ctx; +- +- ops = macsec_get_ops(netdev_priv(dev), &ctx); +- if (ops) { +- ctx.secy = &macsec->secy; +- macsec_offload(ops->mdo_del_secy, &ctx); +- } +- } +- + macsec_common_dellink(dev, head); + + if (list_empty(&rxd->secys)) { +@@ -4018,6 +4018,15 @@ static int macsec_newlink(struct net *net, struct net_device *dev, + !macsec_check_offload(macsec->offload, macsec)) + return -EOPNOTSUPP; + ++ /* send_sci must be set to true when transmit sci explicitly is set */ ++ if ((data && data[IFLA_MACSEC_SCI]) && ++ (data && data[IFLA_MACSEC_INC_SCI])) { ++ u8 send_sci = !!nla_get_u8(data[IFLA_MACSEC_INC_SCI]); ++ ++ if (!send_sci) ++ return -EINVAL; ++ } ++ + if (data && data[IFLA_MACSEC_ICV_LEN]) + icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]); + mtu = real_dev->mtu - icv_len - macsec_extra_len(true); +diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c +index cad820568f751..e2273588c75b6 100644 +--- a/drivers/net/mdio/mdio-aspeed.c ++++ b/drivers/net/mdio/mdio-aspeed.c +@@ -61,6 +61,13 @@ static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum) + + iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL); + ++ rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl, ++ !(ctrl & ASPEED_MDIO_CTRL_FIRE), ++ ASPEED_MDIO_INTERVAL_US, ++ ASPEED_MDIO_TIMEOUT_US); ++ if (rc < 0) ++ return rc; ++ + rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_DATA, data, + data & ASPEED_MDIO_DATA_IDLE, + ASPEED_MDIO_INTERVAL_US, +@@ -141,6 +148,7 @@ static const struct of_device_id aspeed_mdio_of_match[] = { + { .compatible = "aspeed,ast2600-mdio", }, + { }, + }; ++MODULE_DEVICE_TABLE(of, aspeed_mdio_of_match); + + static struct platform_driver aspeed_mdio_driver = { + .driver = { +diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c +index 5f4cd24a0241d..4eba5a91075c0 100644 +--- a/drivers/net/mdio/mdio-ipq4019.c ++++ b/drivers/net/mdio/mdio-ipq4019.c +@@ -200,7 +200,11 @@ static int ipq_mdio_reset(struct mii_bus *bus) + if (ret) + return ret; + +- return clk_prepare_enable(priv->mdio_clk); ++ ret = clk_prepare_enable(priv->mdio_clk); ++ if (ret == 0) ++ mdelay(10); ++ ++ return ret; + } + + static int ipq4019_mdio_probe(struct platform_device *pdev) +diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c +index 90aafb56f1409..a438202129323 100644 +--- a/drivers/net/netdevsim/bpf.c ++++ b/drivers/net/netdevsim/bpf.c +@@ -514,6 +514,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap) + goto err_free; + key = nmap->entry[i].key; + *key = i; ++ memset(nmap->entry[i].value, 0, offmap->map.value_size); + } + } + +diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c +index b03a0513eb7e7..2e7c1cc16cb93 100644 +--- a/drivers/net/netdevsim/ethtool.c ++++ b/drivers/net/netdevsim/ethtool.c +@@ -77,7 +77,10 @@ static int nsim_set_ringparam(struct net_device *dev, + { + struct netdevsim *ns = netdev_priv(dev); + +- memcpy(&ns->ethtool.ring, ring, sizeof(ns->ethtool.ring)); ++ ns->ethtool.ring.rx_pending = ring->rx_pending; ++ ns->ethtool.ring.rx_jumbo_pending = ring->rx_jumbo_pending; ++ ns->ethtool.ring.rx_mini_pending = ring->rx_mini_pending; ++ ns->ethtool.ring.tx_pending = ring->tx_pending; + return 0; + } + +diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c +index 4300261e2f9e7..378ee779061c3 100644 +--- a/drivers/net/netdevsim/fib.c ++++ b/drivers/net/netdevsim/fib.c +@@ -623,14 +623,14 @@ static int nsim_fib6_rt_append(struct nsim_fib_data *data, + if (err) + goto err_fib6_rt_nh_del; + +- fib6_event->rt_arr[i]->trap = true; ++ WRITE_ONCE(fib6_event->rt_arr[i]->trap, true); + } + + return 0; + + err_fib6_rt_nh_del: + for (i--; i >= 0; i--) { +- fib6_event->rt_arr[i]->trap = false; ++ WRITE_ONCE(fib6_event->rt_arr[i]->trap, false); + nsim_fib6_rt_nh_del(fib6_rt, fib6_event->rt_arr[i]); + } + return err; +diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c +index 83aea5c5cd03c..db26ff8ce7dbb 100644 +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -768,6 +768,7 @@ static struct phy_driver broadcom_drivers[] = { + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM54616S", + /* PHY_GBIT_FEATURES */ ++ .soft_reset = genphy_soft_reset, + .config_init = bcm54xx_config_init, + .config_aneg = bcm54616s_config_aneg, + .config_intr = bcm_phy_config_intr, +diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c +index 4fcfca4e17021..cfda625dbea57 100644 +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -189,6 +189,8 @@ + #define MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII 0x4 + #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */ + ++#define MII_88E1510_MSCR_2 0x15 ++ + #define MII_VCT5_TX_RX_MDI0_COUPLING 0x10 + #define MII_VCT5_TX_RX_MDI1_COUPLING 0x11 + #define MII_VCT5_TX_RX_MDI2_COUPLING 0x12 +@@ -551,9 +553,9 @@ static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev) + else + mscr = 0; + +- return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE, +- MII_88E1121_PHY_MSCR_REG, +- MII_88E1121_PHY_MSCR_DELAY_MASK, mscr); ++ return phy_modify_paged_changed(phydev, MII_MARVELL_MSCR_PAGE, ++ MII_88E1121_PHY_MSCR_REG, ++ MII_88E1121_PHY_MSCR_DELAY_MASK, mscr); + } + + static int m88e1121_config_aneg(struct phy_device *phydev) +@@ -567,11 +569,13 @@ static int m88e1121_config_aneg(struct phy_device *phydev) + return err; + } + ++ changed = err; ++ + err = marvell_set_polarity(phydev, phydev->mdix_ctrl); + if (err < 0) + return err; + +- changed = err; ++ changed |= err; + + err = genphy_config_aneg(phydev); + if (err < 0) +@@ -1211,16 +1215,15 @@ static int m88e1118_config_aneg(struct phy_device *phydev) + { + int err; + +- err = genphy_soft_reset(phydev); ++ err = marvell_set_polarity(phydev, phydev->mdix_ctrl); + if (err < 0) + return err; + +- err = marvell_set_polarity(phydev, phydev->mdix_ctrl); ++ err = genphy_config_aneg(phydev); + if (err < 0) + return err; + +- err = genphy_config_aneg(phydev); +- return 0; ++ return genphy_soft_reset(phydev); + } + + static int m88e1118_config_init(struct phy_device *phydev) +@@ -1242,6 +1245,12 @@ static int m88e1118_config_init(struct phy_device *phydev) + if (err < 0) + return err; + ++ if (phy_interface_is_rgmii(phydev)) { ++ err = m88e1121_config_aneg_rgmii_delays(phydev); ++ if (err < 0) ++ return err; ++ } ++ + /* Adjust LED Control */ + if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS) + err = phy_write(phydev, 0x10, 0x1100); +@@ -1932,6 +1941,58 @@ static void marvell_get_stats(struct phy_device *phydev, + data[i] = marvell_get_stat(phydev, i); + } + ++static int m88e1510_loopback(struct phy_device *phydev, bool enable) ++{ ++ int err; ++ ++ if (enable) { ++ u16 bmcr_ctl = 0, mscr2_ctl = 0; ++ ++ if (phydev->speed == SPEED_1000) ++ bmcr_ctl = BMCR_SPEED1000; ++ else if (phydev->speed == SPEED_100) ++ bmcr_ctl = BMCR_SPEED100; ++ ++ if (phydev->duplex == DUPLEX_FULL) ++ bmcr_ctl |= BMCR_FULLDPLX; ++ ++ err = phy_write(phydev, MII_BMCR, bmcr_ctl); ++ if (err < 0) ++ return err; ++ ++ if (phydev->speed == SPEED_1000) ++ mscr2_ctl = BMCR_SPEED1000; ++ else if (phydev->speed == SPEED_100) ++ mscr2_ctl = BMCR_SPEED100; ++ ++ err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE, ++ MII_88E1510_MSCR_2, BMCR_SPEED1000 | ++ BMCR_SPEED100, mscr2_ctl); ++ if (err < 0) ++ return err; ++ ++ /* Need soft reset to have speed configuration takes effect */ ++ err = genphy_soft_reset(phydev); ++ if (err < 0) ++ return err; ++ ++ /* FIXME: Based on trial and error test, it seem 1G need to have ++ * delay between soft reset and loopback enablement. ++ */ ++ if (phydev->speed == SPEED_1000) ++ msleep(1000); ++ ++ return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, ++ BMCR_LOOPBACK); ++ } else { ++ err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0); ++ if (err < 0) ++ return err; ++ ++ return phy_config_aneg(phydev); ++ } ++} ++ + static int marvell_vct5_wait_complete(struct phy_device *phydev) + { + int i; +@@ -3078,7 +3139,7 @@ static struct phy_driver marvell_drivers[] = { + .get_sset_count = marvell_get_sset_count, + .get_strings = marvell_get_strings, + .get_stats = marvell_get_stats, +- .set_loopback = genphy_loopback, ++ .set_loopback = m88e1510_loopback, + .get_tunable = m88e1011_get_tunable, + .set_tunable = m88e1011_set_tunable, + .cable_test_start = marvell_vct7_cable_test_start, +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 6865d9319197f..8dc6e6269c65e 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -591,7 +591,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) + mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device); + + bus->state = MDIOBUS_REGISTERED; +- pr_info("%s: probed\n", bus->name); ++ dev_dbg(&bus->dev, "probed\n"); + return 0; + + error: +diff --git a/drivers/net/phy/mediatek-ge.c b/drivers/net/phy/mediatek-ge.c +index b7a5ae20edd53..68ee434f9dea3 100644 +--- a/drivers/net/phy/mediatek-ge.c ++++ b/drivers/net/phy/mediatek-ge.c +@@ -55,9 +55,6 @@ static int mt7530_phy_config_init(struct phy_device *phydev) + + static int mt7531_phy_config_init(struct phy_device *phydev) + { +- if (phydev->interface != PHY_INTERFACE_MODE_INTERNAL) +- return -EINVAL; +- + mtk_gephy_config_init(phydev); + + /* PHY link down power saving enable */ +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 5c928f827173c..e2ac61f44c945 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -863,9 +863,9 @@ static int ksz9031_config_init(struct phy_device *phydev) + MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4, + tx_data_skews, 4, &update); + +- if (update && phydev->interface != PHY_INTERFACE_MODE_RGMII) ++ if (update && !phy_interface_is_rgmii(phydev)) + phydev_warn(phydev, +- "*-skew-ps values should be used only with phy-mode = \"rgmii\"\n"); ++ "*-skew-ps values should be used only with RGMII PHY modes\n"); + + /* Silicon Errata Sheet (DS80000691D or DS80000692D): + * When the device links in the 1000BASE-T slave mode only, +@@ -1547,8 +1547,8 @@ static struct phy_driver ksphy_driver[] = { + .config_init = kszphy_config_init, + .config_intr = kszphy_config_intr, + .handle_interrupt = kszphy_handle_interrupt, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ8021, + .phy_id_mask = 0x00ffffff, +@@ -1562,8 +1562,8 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ8031, + .phy_id_mask = 0x00ffffff, +@@ -1577,8 +1577,8 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ8041, + .phy_id_mask = MICREL_PHY_ID_MASK, +@@ -1593,8 +1593,9 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ /* No suspend/resume callbacks because of errata DS80000700A, ++ * receiver error following software power down. ++ */ + }, { + .phy_id = PHY_ID_KSZ8041RNLI, + .phy_id_mask = MICREL_PHY_ID_MASK, +@@ -1608,8 +1609,8 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .name = "Micrel KSZ8051", + /* PHY_BASIC_FEATURES */ +@@ -1622,8 +1623,8 @@ static struct phy_driver ksphy_driver[] = { + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, + .match_phy_device = ksz8051_match_phy_device, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ8001, + .name = "Micrel KSZ8001 or KS8721", +@@ -1637,8 +1638,8 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ8081, + .name = "Micrel KSZ8081 or KSZ8091", +@@ -1668,8 +1669,8 @@ static struct phy_driver ksphy_driver[] = { + .config_init = ksz8061_config_init, + .config_intr = kszphy_config_intr, + .handle_interrupt = kszphy_handle_interrupt, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ9021, + .phy_id_mask = 0x000ffffe, +@@ -1684,8 +1685,8 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, +- .resume = genphy_resume, ++ .suspend = kszphy_suspend, ++ .resume = kszphy_resume, + .read_mmd = genphy_read_mmd_unsupported, + .write_mmd = genphy_write_mmd_unsupported, + }, { +@@ -1703,7 +1704,7 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, ++ .suspend = kszphy_suspend, + .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_LAN8814, +@@ -1731,7 +1732,7 @@ static struct phy_driver ksphy_driver[] = { + .get_sset_count = kszphy_get_sset_count, + .get_strings = kszphy_get_strings, + .get_stats = kszphy_get_stats, +- .suspend = genphy_suspend, ++ .suspend = kszphy_suspend, + .resume = kszphy_resume, + }, { + .phy_id = PHY_ID_KSZ8873MLL, +diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c +index 2870c33b8975d..271fc01f7f7fd 100644 +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -162,11 +162,11 @@ static const struct phy_setting settings[] = { + PHY_SETTING( 2500, FULL, 2500baseT_Full ), + PHY_SETTING( 2500, FULL, 2500baseX_Full ), + /* 1G */ +- PHY_SETTING( 1000, FULL, 1000baseKX_Full ), + PHY_SETTING( 1000, FULL, 1000baseT_Full ), + PHY_SETTING( 1000, HALF, 1000baseT_Half ), + PHY_SETTING( 1000, FULL, 1000baseT1_Full ), + PHY_SETTING( 1000, FULL, 1000baseX_Full ), ++ PHY_SETTING( 1000, FULL, 1000baseKX_Full ), + /* 100M */ + PHY_SETTING( 100, FULL, 100baseT_Full ), + PHY_SETTING( 100, FULL, 100baseT1_Full ), +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index a3bfb156c83d7..beb2b66da1324 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -815,7 +815,12 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev, + phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl; + + /* Restart the PHY */ +- _phy_start_aneg(phydev); ++ if (phy_is_started(phydev)) { ++ phydev->state = PHY_UP; ++ phy_trigger_machine(phydev); ++ } else { ++ _phy_start_aneg(phydev); ++ } + + mutex_unlock(&phydev->lock); + return 0; +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 4f9990b47a377..28f4a383aba72 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1746,6 +1746,9 @@ void phy_detach(struct phy_device *phydev) + phy_driver_is_genphy_10g(phydev)) + device_release_driver(&phydev->mdio.dev); + ++ /* Assert the reset signal */ ++ phy_device_reset(phydev, 1); ++ + /* + * The phydev might go away on the put_device() below, so avoid + * a use-after-free bug by reading the underlying bus first. +@@ -1757,9 +1760,6 @@ void phy_detach(struct phy_device *phydev) + ndev_owner = dev->dev.parent->driver->owner; + if (ndev_owner != bus->owner) + module_put(bus->owner); +- +- /* Assert the reset signal */ +- phy_device_reset(phydev, 1); + } + EXPORT_SYMBOL(phy_detach); + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index 0a0abe8e4be0b..fef1416dcee4c 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -657,6 +657,7 @@ static void phylink_resolve(struct work_struct *w) + struct phylink_link_state link_state; + struct net_device *ndev = pl->netdev; + bool mac_config = false; ++ bool retrigger = false; + bool cur_link_state; + + mutex_lock(&pl->state_mutex); +@@ -670,6 +671,7 @@ static void phylink_resolve(struct work_struct *w) + link_state.link = false; + } else if (pl->mac_link_dropped) { + link_state.link = false; ++ retrigger = true; + } else { + switch (pl->cur_link_an_mode) { + case MLO_AN_PHY: +@@ -686,6 +688,19 @@ static void phylink_resolve(struct work_struct *w) + case MLO_AN_INBAND: + phylink_mac_pcs_get_state(pl, &link_state); + ++ /* The PCS may have a latching link-fail indicator. ++ * If the link was up, bring the link down and ++ * re-trigger the resolve. Otherwise, re-read the ++ * PCS state to get the current status of the link. ++ */ ++ if (!link_state.link) { ++ if (cur_link_state) ++ retrigger = true; ++ else ++ phylink_mac_pcs_get_state(pl, ++ &link_state); ++ } ++ + /* If we have a phy, the "up" state is the union of + * both the PHY and the MAC + */ +@@ -694,6 +709,15 @@ static void phylink_resolve(struct work_struct *w) + + /* Only update if the PHY link is up */ + if (pl->phydev && pl->phy_state.link) { ++ /* If the interface has changed, force a ++ * link down event if the link isn't already ++ * down, and re-resolve. ++ */ ++ if (link_state.interface != ++ pl->phy_state.interface) { ++ retrigger = true; ++ link_state.link = false; ++ } + link_state.interface = pl->phy_state.interface; + + /* If we have a PHY, we need to update with +@@ -736,7 +760,7 @@ static void phylink_resolve(struct work_struct *w) + else + phylink_link_up(pl, link_state); + } +- if (!link_state.link && pl->mac_link_dropped) { ++ if (!link_state.link && retrigger) { + pl->mac_link_dropped = false; + queue_work(system_power_efficient_wq, &pl->resolve); + } +@@ -1333,7 +1357,10 @@ void phylink_suspend(struct phylink *pl, bool mac_wol) + * but one would hope all packets have been sent. This + * also means phylink_resolve() will do nothing. + */ +- netif_carrier_off(pl->netdev); ++ if (pl->netdev) ++ netif_carrier_off(pl->netdev); ++ else ++ pl->old_link_state = false; + + /* We do not call mac_link_down() here as we want the + * link to remain up to receive the WoL packets. +@@ -1724,7 +1751,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl, + return -EOPNOTSUPP; + + if (!phylink_test(pl->supported, Asym_Pause) && +- !pause->autoneg && pause->rx_pause != pause->tx_pause) ++ pause->rx_pause != pause->tx_pause) + return -EINVAL; + + pause_state = 0; +diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c +index 7362f8c3271c9..ef2c6a09eb0f3 100644 +--- a/drivers/net/phy/sfp-bus.c ++++ b/drivers/net/phy/sfp-bus.c +@@ -651,6 +651,11 @@ struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode) + else if (ret < 0) + return ERR_PTR(ret); + ++ if (!fwnode_device_is_available(ref.fwnode)) { ++ fwnode_handle_put(ref.fwnode); ++ return NULL; ++ } ++ + bus = sfp_bus_get(ref.fwnode); + fwnode_handle_put(ref.fwnode); + if (!bus) +diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c +index ab77a9f439ef9..4720b24ca51b5 100644 +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -1641,17 +1641,20 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp) + static int sfp_module_parse_power(struct sfp *sfp) + { + u32 power_mW = 1000; ++ bool supports_a2; + + if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_POWER_DECL)) + power_mW = 1500; + if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL)) + power_mW = 2000; + ++ supports_a2 = sfp->id.ext.sff8472_compliance != ++ SFP_SFF8472_COMPLIANCE_NONE || ++ sfp->id.ext.diagmon & SFP_DIAGMON_DDM; ++ + if (power_mW > sfp->max_power_mW) { + /* Module power specification exceeds the allowed maximum. */ +- if (sfp->id.ext.sff8472_compliance == +- SFP_SFF8472_COMPLIANCE_NONE && +- !(sfp->id.ext.diagmon & SFP_DIAGMON_DDM)) { ++ if (!supports_a2) { + /* The module appears not to implement bus address + * 0xa2, so assume that the module powers up in the + * indicated mode. +@@ -1668,11 +1671,25 @@ static int sfp_module_parse_power(struct sfp *sfp) + } + } + ++ if (power_mW <= 1000) { ++ /* Modules below 1W do not require a power change sequence */ ++ sfp->module_power_mW = power_mW; ++ return 0; ++ } ++ ++ if (!supports_a2) { ++ /* The module power level is below the host maximum and the ++ * module appears not to implement bus address 0xa2, so assume ++ * that the module powers up in the indicated mode. ++ */ ++ return 0; ++ } ++ + /* If the module requires a higher power mode, but also requires + * an address change sequence, warn the user that the module may + * not be functional. + */ +- if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE && power_mW > 1000) { ++ if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE) { + dev_warn(sfp->dev, + "Address Change Sequence not supported but module requires %u.%uW, module may not be functional\n", + power_mW / 1000, (power_mW / 100) % 10); +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index fb52cd175b45d..829d6ada1704c 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -69,6 +69,8 @@ + #define MPHDRLEN 6 /* multilink protocol header length */ + #define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ + ++#define PPP_PROTO_LEN 2 ++ + /* + * An instance of /dev/ppp can be associated with either a ppp + * interface unit or a ppp channel. In both cases, file->private_data +@@ -497,6 +499,9 @@ static ssize_t ppp_write(struct file *file, const char __user *buf, + + if (!pf) + return -ENXIO; ++ /* All PPP packets should start with the 2-byte protocol */ ++ if (count < PPP_PROTO_LEN) ++ return -EINVAL; + ret = -ENOMEM; + skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL); + if (!skb) +@@ -1764,7 +1769,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + } + + ++ppp->stats64.tx_packets; +- ppp->stats64.tx_bytes += skb->len - 2; ++ ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN; + + switch (proto) { + case PPP_IP: +diff --git a/drivers/net/slip/slip.h b/drivers/net/slip/slip.h +index c420e59485221..3d7f88b330c1e 100644 +--- a/drivers/net/slip/slip.h ++++ b/drivers/net/slip/slip.h +@@ -40,6 +40,8 @@ + insmod -oslip_maxdev=nnn */ + #define SL_MTU 296 /* 296; I am used to 600- FvK */ + ++/* some arch define END as assembly function ending, just undef it */ ++#undef END + /* SLIP protocol characters. */ + #define END 0300 /* indicates end of frame */ + #define ESC 0333 /* indicates byte stuffing */ +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index fecc9a1d293ae..45a67e72a02c6 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -209,6 +209,9 @@ struct tun_struct { + struct tun_prog __rcu *steering_prog; + struct tun_prog __rcu *filter_prog; + struct ethtool_link_ksettings link_ksettings; ++ /* init args */ ++ struct file *file; ++ struct ifreq *ifr; + }; + + struct veth { +@@ -216,6 +219,9 @@ struct veth { + __be16 h_vlan_TCI; + }; + ++static void tun_flow_init(struct tun_struct *tun); ++static void tun_flow_uninit(struct tun_struct *tun); ++ + static int tun_napi_receive(struct napi_struct *napi, int budget) + { + struct tun_file *tfile = container_of(napi, struct tun_file, napi); +@@ -953,6 +959,49 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) + + static const struct ethtool_ops tun_ethtool_ops; + ++static int tun_net_init(struct net_device *dev) ++{ ++ struct tun_struct *tun = netdev_priv(dev); ++ struct ifreq *ifr = tun->ifr; ++ int err; ++ ++ dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); ++ if (!dev->tstats) ++ return -ENOMEM; ++ ++ spin_lock_init(&tun->lock); ++ ++ err = security_tun_dev_alloc_security(&tun->security); ++ if (err < 0) { ++ free_percpu(dev->tstats); ++ return err; ++ } ++ ++ tun_flow_init(tun); ++ ++ dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | ++ TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | ++ NETIF_F_HW_VLAN_STAG_TX; ++ dev->features = dev->hw_features | NETIF_F_LLTX; ++ dev->vlan_features = dev->features & ++ ~(NETIF_F_HW_VLAN_CTAG_TX | ++ NETIF_F_HW_VLAN_STAG_TX); ++ ++ tun->flags = (tun->flags & ~TUN_FEATURES) | ++ (ifr->ifr_flags & TUN_FEATURES); ++ ++ INIT_LIST_HEAD(&tun->disabled); ++ err = tun_attach(tun, tun->file, false, ifr->ifr_flags & IFF_NAPI, ++ ifr->ifr_flags & IFF_NAPI_FRAGS, false); ++ if (err < 0) { ++ tun_flow_uninit(tun); ++ security_tun_dev_free_security(tun->security); ++ free_percpu(dev->tstats); ++ return err; ++ } ++ return 0; ++} ++ + /* Net device detach from fd. */ + static void tun_net_uninit(struct net_device *dev) + { +@@ -1010,6 +1059,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct tun_struct *tun = netdev_priv(dev); + int txq = skb->queue_mapping; ++ struct netdev_queue *queue; + struct tun_file *tfile; + int len = skb->len; + +@@ -1054,6 +1104,10 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) + if (ptr_ring_produce(&tfile->tx_ring, skb)) + goto drop; + ++ /* NETIF_F_LLTX requires to do our own update of trans_start */ ++ queue = netdev_get_tx_queue(dev, txq); ++ queue->trans_start = jiffies; ++ + /* Notify and wake up reader process */ + if (tfile->flags & TUN_FASYNC) + kill_fasync(&tfile->fasync, SIGIO, POLL_IN); +@@ -1164,6 +1218,7 @@ static int tun_net_change_carrier(struct net_device *dev, bool new_carrier) + } + + static const struct net_device_ops tun_netdev_ops = { ++ .ndo_init = tun_net_init, + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, +@@ -1247,6 +1302,7 @@ static int tun_xdp_tx(struct net_device *dev, struct xdp_buff *xdp) + } + + static const struct net_device_ops tap_netdev_ops = { ++ .ndo_init = tun_net_init, + .ndo_uninit = tun_net_uninit, + .ndo_open = tun_net_open, + .ndo_stop = tun_net_close, +@@ -1287,7 +1343,7 @@ static void tun_flow_uninit(struct tun_struct *tun) + #define MAX_MTU 65535 + + /* Initialize net device. */ +-static void tun_net_init(struct net_device *dev) ++static void tun_net_initialize(struct net_device *dev) + { + struct tun_struct *tun = netdev_priv(dev); + +@@ -2201,11 +2257,6 @@ static void tun_free_netdev(struct net_device *dev) + BUG_ON(!(list_empty(&tun->disabled))); + + free_percpu(dev->tstats); +- /* We clear tstats so that tun_set_iff() can tell if +- * tun_free_netdev() has been called from register_netdevice(). +- */ +- dev->tstats = NULL; +- + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); + __tun_set_ebpf(tun, &tun->steering_prog, NULL); +@@ -2711,41 +2762,16 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + tun->rx_batched = 0; + RCU_INIT_POINTER(tun->steering_prog, NULL); + +- dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); +- if (!dev->tstats) { +- err = -ENOMEM; +- goto err_free_dev; +- } ++ tun->ifr = ifr; ++ tun->file = file; + +- spin_lock_init(&tun->lock); +- +- err = security_tun_dev_alloc_security(&tun->security); +- if (err < 0) +- goto err_free_stat; +- +- tun_net_init(dev); +- tun_flow_init(tun); +- +- dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | +- TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | +- NETIF_F_HW_VLAN_STAG_TX; +- dev->features = dev->hw_features | NETIF_F_LLTX; +- dev->vlan_features = dev->features & +- ~(NETIF_F_HW_VLAN_CTAG_TX | +- NETIF_F_HW_VLAN_STAG_TX); +- +- tun->flags = (tun->flags & ~TUN_FEATURES) | +- (ifr->ifr_flags & TUN_FEATURES); +- +- INIT_LIST_HEAD(&tun->disabled); +- err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI, +- ifr->ifr_flags & IFF_NAPI_FRAGS, false); +- if (err < 0) +- goto err_free_flow; ++ tun_net_initialize(dev); + + err = register_netdevice(tun->dev); +- if (err < 0) +- goto err_detach; ++ if (err < 0) { ++ free_netdev(dev); ++ return err; ++ } + /* free_netdev() won't check refcnt, to avoid race + * with dev_put() we need publish tun after registration. + */ +@@ -2762,24 +2788,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + + strcpy(ifr->ifr_name, tun->dev->name); + return 0; +- +-err_detach: +- tun_detach_all(dev); +- /* We are here because register_netdevice() has failed. +- * If register_netdevice() already called tun_free_netdev() +- * while dealing with the error, dev->stats has been cleared. +- */ +- if (!dev->tstats) +- goto err_free_dev; +- +-err_free_flow: +- tun_flow_uninit(tun); +- security_tun_dev_free_security(tun->security); +-err_free_stat: +- free_percpu(dev->tstats); +-err_free_dev: +- free_netdev(dev); +- return err; + } + + static void tun_get_iff(struct tun_struct *tun, struct ifreq *ifr) +diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c +index 38cda590895cc..9aa92076500af 100644 +--- a/drivers/net/usb/asix_common.c ++++ b/drivers/net/usb/asix_common.c +@@ -9,6 +9,8 @@ + + #include "asix.h" + ++#define AX_HOST_EN_RETRIES 30 ++ + int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, + u16 size, void *data, int in_pm) + { +@@ -68,7 +70,7 @@ static int asix_check_host_enable(struct usbnet *dev, int in_pm) + int i, ret; + u8 smsr; + +- for (i = 0; i < 30; ++i) { ++ for (i = 0; i < AX_HOST_EN_RETRIES; ++i) { + ret = asix_set_sw_mii(dev, in_pm); + if (ret == -ENODEV || ret == -ETIMEDOUT) + break; +@@ -77,13 +79,13 @@ static int asix_check_host_enable(struct usbnet *dev, int in_pm) + 0, 0, 1, &smsr, in_pm); + if (ret == -ENODEV) + break; +- else if (ret < 0) ++ else if (ret < sizeof(smsr)) + continue; + else if (smsr & AX_HOST_EN) + break; + } + +- return ret; ++ return i >= AX_HOST_EN_RETRIES ? -ETIMEDOUT : ret; + } + + static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx) +diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c +index f25448a088707..d5ce642200e8e 100644 +--- a/drivers/net/usb/ax88179_178a.c ++++ b/drivers/net/usb/ax88179_178a.c +@@ -1467,58 +1467,68 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + u16 hdr_off; + u32 *pkt_hdr; + +- /* This check is no longer done by usbnet */ +- if (skb->len < dev->net->hard_header_len) ++ /* At the end of the SKB, there's a header telling us how many packets ++ * are bundled into this buffer and where we can find an array of ++ * per-packet metadata (which contains elements encoded into u16). ++ */ ++ if (skb->len < 4) + return 0; +- + skb_trim(skb, skb->len - 4); + rx_hdr = get_unaligned_le32(skb_tail_pointer(skb)); +- + pkt_cnt = (u16)rx_hdr; + hdr_off = (u16)(rx_hdr >> 16); ++ ++ if (pkt_cnt == 0) ++ return 0; ++ ++ /* Make sure that the bounds of the metadata array are inside the SKB ++ * (and in front of the counter at the end). ++ */ ++ if (pkt_cnt * 2 + hdr_off > skb->len) ++ return 0; + pkt_hdr = (u32 *)(skb->data + hdr_off); + +- while (pkt_cnt--) { ++ /* Packets must not overlap the metadata array */ ++ skb_trim(skb, hdr_off); ++ ++ for (; ; pkt_cnt--, pkt_hdr++) { + u16 pkt_len; + + le32_to_cpus(pkt_hdr); + pkt_len = (*pkt_hdr >> 16) & 0x1fff; + +- /* Check CRC or runt packet */ +- if ((*pkt_hdr & AX_RXHDR_CRC_ERR) || +- (*pkt_hdr & AX_RXHDR_DROP_ERR)) { +- skb_pull(skb, (pkt_len + 7) & 0xFFF8); +- pkt_hdr++; +- continue; +- } +- +- if (pkt_cnt == 0) { +- skb->len = pkt_len; +- /* Skip IP alignment pseudo header */ +- skb_pull(skb, 2); +- skb_set_tail_pointer(skb, skb->len); +- skb->truesize = pkt_len + sizeof(struct sk_buff); +- ax88179_rx_checksum(skb, pkt_hdr); +- return 1; +- } ++ if (pkt_len > skb->len) ++ return 0; + +- ax_skb = skb_clone(skb, GFP_ATOMIC); +- if (ax_skb) { ++ /* Check CRC or runt packet */ ++ if (((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) == 0) && ++ pkt_len >= 2 + ETH_HLEN) { ++ bool last = (pkt_cnt == 0); ++ ++ if (last) { ++ ax_skb = skb; ++ } else { ++ ax_skb = skb_clone(skb, GFP_ATOMIC); ++ if (!ax_skb) ++ return 0; ++ } + ax_skb->len = pkt_len; + /* Skip IP alignment pseudo header */ + skb_pull(ax_skb, 2); + skb_set_tail_pointer(ax_skb, ax_skb->len); + ax_skb->truesize = pkt_len + sizeof(struct sk_buff); + ax88179_rx_checksum(ax_skb, pkt_hdr); ++ ++ if (last) ++ return 1; ++ + usbnet_skb_return(dev, ax_skb); +- } else { +- return 0; + } + +- skb_pull(skb, (pkt_len + 7) & 0xFFF8); +- pkt_hdr++; ++ /* Trim this packet away from the SKB */ ++ if (!skb_pull(skb, (pkt_len + 7) & 0xFFF8)) ++ return 0; + } +- return 1; + } + + static struct sk_buff * +diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c +index eb3817d70f2b8..9b4dfa3001d6e 100644 +--- a/drivers/net/usb/cdc_ether.c ++++ b/drivers/net/usb/cdc_ether.c +@@ -583,6 +583,11 @@ static const struct usb_device_id products[] = { + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ + .bInterfaceProtocol = USB_CDC_PROTO_NONE + ++#define ZAURUS_FAKE_INTERFACE \ ++ .bInterfaceClass = USB_CLASS_COMM, \ ++ .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, \ ++ .bInterfaceProtocol = USB_CDC_PROTO_NONE ++ + /* SA-1100 based Sharp Zaurus ("collie"), or compatible; + * wire-incompatible with true CDC Ethernet implementations. + * (And, it seems, needlessly so...) +@@ -636,6 +641,13 @@ static const struct usb_device_id products[] = { + .idProduct = 0x9032, /* SL-6000 */ + ZAURUS_MASTER_INTERFACE, + .driver_info = 0, ++}, { ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO ++ | USB_DEVICE_ID_MATCH_DEVICE, ++ .idVendor = 0x04DD, ++ .idProduct = 0x9032, /* SL-6000 */ ++ ZAURUS_FAKE_INTERFACE, ++ .driver_info = 0, + }, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, +diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c +index 82bb5ed94c485..c0b8b4aa78f37 100644 +--- a/drivers/net/usb/cdc_mbim.c ++++ b/drivers/net/usb/cdc_mbim.c +@@ -659,6 +659,11 @@ static const struct usb_device_id mbim_devs[] = { + .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, + }, + ++ /* Telit FN990 */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1071, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), ++ .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle, ++ }, ++ + /* default entry */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&cdc_mbim_info_zlp, +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index 24753a4da7e60..15f91d691bba3 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -181,6 +181,8 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx) + min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32); + + max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)); ++ if (max == 0) ++ max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */ + + /* some devices set dwNtbOutMaxSize too low for the above default */ + min = min(min, max); +@@ -1713,10 +1715,10 @@ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) + { + struct sk_buff *skb; + struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; +- int len; ++ unsigned int len; + int nframes; + int x; +- int offset; ++ unsigned int offset; + union { + struct usb_cdc_ncm_ndp16 *ndp16; + struct usb_cdc_ncm_ndp32 *ndp32; +@@ -1788,8 +1790,8 @@ next_ndp: + break; + } + +- /* sanity checking */ +- if (((offset + len) > skb_in->len) || ++ /* sanity checking - watch out for integer wrap*/ ++ if ((offset > skb_in->len) || (len > skb_in->len - offset) || + (len > ctx->rx_max) || (len < ETH_HLEN)) { + netif_dbg(dev, rx_err, dev->net, + "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n", +diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c +index 06e2181e58108..d56e276e4d805 100644 +--- a/drivers/net/usb/ipheth.c ++++ b/drivers/net/usb/ipheth.c +@@ -121,7 +121,7 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) + if (tx_buf == NULL) + goto free_rx_urb; + +- rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, ++ rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + GFP_KERNEL, &rx_urb->transfer_dma); + if (rx_buf == NULL) + goto free_tx_buf; +@@ -146,7 +146,7 @@ error_nomem: + + static void ipheth_free_urbs(struct ipheth_device *iphone) + { +- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf, ++ usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf, + iphone->rx_urb->transfer_dma); + usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, + iphone->tx_urb->transfer_dma); +@@ -317,7 +317,7 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) + + usb_fill_bulk_urb(dev->rx_urb, udev, + usb_rcvbulkpipe(udev, dev->bulk_in), +- dev->rx_buf, IPHETH_BUF_SIZE, ++ dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + ipheth_rcvbulk_callback, + dev); + dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 63cd72c5f580c..3e1a83a22fdd6 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -76,6 +76,8 @@ + #define LAN7801_USB_PRODUCT_ID (0x7801) + #define LAN78XX_EEPROM_MAGIC (0x78A5) + #define LAN78XX_OTP_MAGIC (0x78F3) ++#define AT29M2AF_USB_VENDOR_ID (0x07C9) ++#define AT29M2AF_USB_PRODUCT_ID (0x0012) + + #define MII_READ 1 + #define MII_WRITE 0 +@@ -2228,7 +2230,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) + if (dev->domain_data.phyirq > 0) + phydev->irq = dev->domain_data.phyirq; + else +- phydev->irq = 0; ++ phydev->irq = PHY_POLL; + netdev_dbg(dev->net, "phydev->irq = %d\n", phydev->irq); + + /* set to AUTOMDIX */ +@@ -4734,6 +4736,10 @@ static const struct usb_device_id products[] = { + /* LAN7801 USB Gigabit Ethernet Device */ + USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7801_USB_PRODUCT_ID), + }, ++ { ++ /* ATM2-AF USB Gigabit Ethernet Device */ ++ USB_DEVICE(AT29M2AF_USB_VENDOR_ID, AT29M2AF_USB_PRODUCT_ID), ++ }, + {}, + }; + MODULE_DEVICE_TABLE(usb, products); +diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c +index 66866bef25df7..a31a3b9cbd58d 100644 +--- a/drivers/net/usb/mcs7830.c ++++ b/drivers/net/usb/mcs7830.c +@@ -108,8 +108,16 @@ static const char driver_name[] = "MOSCHIP usb-ethernet driver"; + + static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data) + { +- return usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ, +- 0x0000, index, data, size); ++ int ret; ++ ++ ret = usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ, ++ 0x0000, index, data, size); ++ if (ret < 0) ++ return ret; ++ else if (ret < size) ++ return -ENODATA; ++ ++ return ret; + } + + static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data) +diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c +index 6a92a3fef75e5..cd063f45785b7 100644 +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -493,11 +493,11 @@ static void read_bulk_callback(struct urb *urb) + goto goon; + + rx_status = buf[count - 2]; +- if (rx_status & 0x1e) { ++ if (rx_status & 0x1c) { + netif_dbg(pegasus, rx_err, net, + "RX packet error %x\n", rx_status); + net->stats.rx_errors++; +- if (rx_status & 0x06) /* long or runt */ ++ if (rx_status & 0x04) /* runt */ + net->stats.rx_length_errors++; + if (rx_status & 0x08) + net->stats.rx_crc_errors++; +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 33ada2c59952e..0c7f02ca6822b 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -1395,6 +1395,8 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81d7, 0)}, /* Dell Wireless 5821e */ + {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e preproduction config */ + {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/ ++ {QMI_FIXED_INTF(0x413c, 0x81e4, 0)}, /* Dell Wireless 5829e with eSIM support*/ ++ {QMI_FIXED_INTF(0x413c, 0x81e6, 0)}, /* Dell Wireless 5829e */ + {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ + {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ + {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index f329e39100a7d..d467a9f3bb44d 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -32,7 +32,7 @@ + #define NETNEXT_VERSION "12" + + /* Information for net */ +-#define NET_VERSION "11" ++#define NET_VERSION "12" + + #define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION + #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" +@@ -4016,6 +4016,11 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type) + ocp_write_word(tp, type, PLA_BP_BA, 0); + } + ++static inline void rtl_reset_ocp_base(struct r8152 *tp) ++{ ++ tp->ocp_base = -1; ++} ++ + static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) + { + u16 data, check; +@@ -4087,8 +4092,6 @@ static int rtl_post_ram_code(struct r8152 *tp, u16 key_addr, bool wait) + + rtl_phy_patch_request(tp, false, wait); + +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); +- + return 0; + } + +@@ -4800,6 +4803,8 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, + u32 len; + u8 *data; + ++ rtl_reset_ocp_base(tp); ++ + if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) { + dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); + return; +@@ -4845,7 +4850,8 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, + } + } + +- ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base); ++ rtl_reset_ocp_base(tp); ++ + rtl_phy_patch_request(tp, false, wait); + + if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version)) +@@ -4861,6 +4867,8 @@ static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver) + ver_addr = __le16_to_cpu(phy_ver->ver.addr); + ver = __le16_to_cpu(phy_ver->ver.data); + ++ rtl_reset_ocp_base(tp); ++ + if (sram_read(tp, ver_addr) >= ver) { + dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); + return 0; +@@ -4877,6 +4885,8 @@ static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix) + { + u16 addr, data; + ++ rtl_reset_ocp_base(tp); ++ + addr = __le16_to_cpu(fix->setting.addr); + data = ocp_reg_read(tp, addr); + +@@ -4908,6 +4918,8 @@ static void rtl8152_fw_phy_union_apply(struct r8152 *tp, struct fw_phy_union *ph + u32 length; + int i, num; + ++ rtl_reset_ocp_base(tp); ++ + num = phy->pre_num; + for (i = 0; i < num; i++) + sram_write(tp, __le16_to_cpu(phy->pre_set[i].addr), +@@ -4938,6 +4950,8 @@ static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy) + u32 length, i, num; + __le16 *data; + ++ rtl_reset_ocp_base(tp); ++ + mode_reg = __le16_to_cpu(phy->mode_reg); + sram_write(tp, mode_reg, __le16_to_cpu(phy->mode_pre)); + sram_write(tp, __le16_to_cpu(phy->ba_reg), +@@ -5107,6 +5121,7 @@ post_fw: + if (rtl_fw->post_fw) + rtl_fw->post_fw(tp); + ++ rtl_reset_ocp_base(tp); + strscpy(rtl_fw->version, fw_hdr->version, RTL_VER_SIZE); + dev_info(&tp->intf->dev, "load %s successfully\n", rtl_fw->version); + } +@@ -6584,6 +6599,21 @@ static bool rtl8153_in_nway(struct r8152 *tp) + return true; + } + ++static void r8156_mdio_force_mode(struct r8152 *tp) ++{ ++ u16 data; ++ ++ /* Select force mode through 0xa5b4 bit 15 ++ * 0: MDIO force mode ++ * 1: MMD force mode ++ */ ++ data = ocp_reg_read(tp, 0xa5b4); ++ if (data & BIT(15)) { ++ data &= ~BIT(15); ++ ocp_reg_write(tp, 0xa5b4, data); ++ } ++} ++ + static void set_carrier(struct r8152 *tp) + { + struct net_device *netdev = tp->netdev; +@@ -8016,6 +8046,7 @@ static void r8156_init(struct r8152 *tp) + ocp_data |= ACT_ODMA; + ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_CONFIG, ocp_data); + ++ r8156_mdio_force_mode(tp); + rtl_tally_reset(tp); + + tp->coalesce = 15000; /* 15 us */ +@@ -8145,6 +8176,7 @@ static void r8156b_init(struct r8152 *tp) + ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); + ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); + ++ r8156_mdio_force_mode(tp); + rtl_tally_reset(tp); + + tp->coalesce = 15000; /* 15 us */ +@@ -8467,6 +8499,8 @@ static int rtl8152_resume(struct usb_interface *intf) + + mutex_lock(&tp->control); + ++ rtl_reset_ocp_base(tp); ++ + if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) + ret = rtl8152_runtime_resume(tp); + else +@@ -8482,6 +8516,7 @@ static int rtl8152_reset_resume(struct usb_interface *intf) + struct r8152 *tp = usb_get_intfdata(intf); + + clear_bit(SELECTIVE_SUSPEND, &tp->flags); ++ rtl_reset_ocp_base(tp); + tp->rtl_ops.init(tp); + queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0); + set_ethernet_addr(tp, true); +diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c +index 85a8b96e39a65..bedd36ab5cf01 100644 +--- a/drivers/net/usb/rndis_host.c ++++ b/drivers/net/usb/rndis_host.c +@@ -608,6 +608,11 @@ static const struct usb_device_id products [] = { + USB_DEVICE_AND_INTERFACE_INFO(0x1630, 0x0042, + USB_CLASS_COMM, 2 /* ACM */, 0x0ff), + .driver_info = (unsigned long) &rndis_poll_status_info, ++}, { ++ /* Hytera Communications DMR radios' "Radio to PC Network" */ ++ USB_VENDOR_AND_INTERFACE_INFO(0x238b, ++ USB_CLASS_COMM, 2 /* ACM */, 0x0ff), ++ .driver_info = (unsigned long)&rndis_info, + }, { + /* RNDIS is MSFT's un-official variant of CDC ACM */ + USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 26b1bd8e845b4..026e7487c45b5 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -1049,6 +1049,14 @@ static const struct net_device_ops smsc95xx_netdev_ops = { + .ndo_set_features = smsc95xx_set_features, + }; + ++static void smsc95xx_handle_link_change(struct net_device *net) ++{ ++ struct usbnet *dev = netdev_priv(net); ++ ++ phy_print_status(net->phydev); ++ usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); ++} ++ + static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) + { + struct smsc95xx_priv *pdata; +@@ -1153,6 +1161,17 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) + dev->net->min_mtu = ETH_MIN_MTU; + dev->net->max_mtu = ETH_DATA_LEN; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; ++ ++ ret = phy_connect_direct(dev->net, pdata->phydev, ++ &smsc95xx_handle_link_change, ++ PHY_INTERFACE_MODE_MII); ++ if (ret) { ++ netdev_err(dev->net, "can't attach PHY to %s\n", pdata->mdiobus->id); ++ goto unregister_mdio; ++ } ++ ++ phy_attached_info(dev->net->phydev); ++ + return 0; + + unregister_mdio: +@@ -1170,47 +1189,25 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) + { + struct smsc95xx_priv *pdata = dev->driver_priv; + ++ phy_disconnect(dev->net->phydev); + mdiobus_unregister(pdata->mdiobus); + mdiobus_free(pdata->mdiobus); + netif_dbg(dev, ifdown, dev->net, "free pdata\n"); + kfree(pdata); + } + +-static void smsc95xx_handle_link_change(struct net_device *net) +-{ +- struct usbnet *dev = netdev_priv(net); +- +- phy_print_status(net->phydev); +- usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); +-} +- + static int smsc95xx_start_phy(struct usbnet *dev) + { +- struct smsc95xx_priv *pdata = dev->driver_priv; +- struct net_device *net = dev->net; +- int ret; ++ phy_start(dev->net->phydev); + +- ret = smsc95xx_reset(dev); +- if (ret < 0) +- return ret; +- +- ret = phy_connect_direct(net, pdata->phydev, +- &smsc95xx_handle_link_change, +- PHY_INTERFACE_MODE_MII); +- if (ret) { +- netdev_err(net, "can't attach PHY to %s\n", pdata->mdiobus->id); +- return ret; +- } +- +- phy_attached_info(net->phydev); +- phy_start(net->phydev); + return 0; + } + +-static int smsc95xx_disconnect_phy(struct usbnet *dev) ++static int smsc95xx_stop(struct usbnet *dev) + { +- phy_stop(dev->net->phydev); +- phy_disconnect(dev->net->phydev); ++ if (dev->net->phydev) ++ phy_stop(dev->net->phydev); ++ + return 0; + } + +@@ -1964,8 +1961,9 @@ static const struct driver_info smsc95xx_info = { + .bind = smsc95xx_bind, + .unbind = smsc95xx_unbind, + .link_reset = smsc95xx_link_reset, +- .reset = smsc95xx_start_phy, +- .stop = smsc95xx_disconnect_phy, ++ .reset = smsc95xx_reset, ++ .check_connect = smsc95xx_start_phy, ++ .stop = smsc95xx_stop, + .rx_fixup = smsc95xx_rx_fixup, + .tx_fixup = smsc95xx_tx_fixup, + .status = smsc95xx_status, +diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c +index 6516a37893e27..0c50f24671da3 100644 +--- a/drivers/net/usb/sr9700.c ++++ b/drivers/net/usb/sr9700.c +@@ -410,7 +410,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + /* ignore the CRC length */ + len = (skb->data[1] | (skb->data[2] << 8)) - 4; + +- if (len > ETH_FRAME_LEN) ++ if (len > ETH_FRAME_LEN || len > skb->len) + return 0; + + /* the last packet of current skb */ +diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c +index 8e717a0b559b3..7984f2157d222 100644 +--- a/drivers/net/usb/zaurus.c ++++ b/drivers/net/usb/zaurus.c +@@ -256,6 +256,11 @@ static const struct usb_device_id products [] = { + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ + .bInterfaceProtocol = USB_CDC_PROTO_NONE + ++#define ZAURUS_FAKE_INTERFACE \ ++ .bInterfaceClass = USB_CLASS_COMM, \ ++ .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, \ ++ .bInterfaceProtocol = USB_CDC_PROTO_NONE ++ + /* SA-1100 based Sharp Zaurus ("collie"), or compatible. */ + { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO +@@ -313,6 +318,13 @@ static const struct usb_device_id products [] = { + .idProduct = 0x9032, /* SL-6000 */ + ZAURUS_MASTER_INTERFACE, + .driver_info = ZAURUS_PXA_INFO, ++}, { ++ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO ++ | USB_DEVICE_ID_MATCH_DEVICE, ++ .idVendor = 0x04DD, ++ .idProduct = 0x9032, /* SL-6000 */ ++ ZAURUS_FAKE_INTERFACE, ++ .driver_info = (unsigned long)&bogus_mdlm_info, + }, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 50eb43e5bf459..f478fe7e2b820 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -272,9 +272,10 @@ static void __veth_xdp_flush(struct veth_rq *rq) + { + /* Write ptr_ring before reading rx_notify_masked */ + smp_mb(); +- if (!rq->rx_notify_masked) { +- rq->rx_notify_masked = true; +- napi_schedule(&rq->xdp_napi); ++ if (!READ_ONCE(rq->rx_notify_masked) && ++ napi_schedule_prep(&rq->xdp_napi)) { ++ WRITE_ONCE(rq->rx_notify_masked, true); ++ __napi_schedule(&rq->xdp_napi); + } + } + +@@ -342,7 +343,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) + */ + use_napi = rcu_access_pointer(rq->napi) && + veth_skb_is_eligible_for_gro(dev, rcv, skb); +- skb_record_rx_queue(skb, rxq); + } + + skb_tx_timestamp(skb); +@@ -879,8 +879,12 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + + stats->xdp_bytes += skb->len; + skb = veth_xdp_rcv_skb(rq, skb, bq, stats); +- if (skb) +- napi_gro_receive(&rq->xdp_napi, skb); ++ if (skb) { ++ if (skb_shared(skb) || skb_unclone(skb, GFP_ATOMIC)) ++ netif_receive_skb(skb); ++ else ++ napi_gro_receive(&rq->xdp_napi, skb); ++ } + } + done++; + } +@@ -916,8 +920,10 @@ static int veth_poll(struct napi_struct *napi, int budget) + /* Write rx_notify_masked before reading ptr_ring */ + smp_store_mb(rq->rx_notify_masked, false); + if (unlikely(!__ptr_ring_empty(&rq->xdp_ring))) { +- rq->rx_notify_masked = true; +- napi_schedule(&rq->xdp_napi); ++ if (napi_schedule_prep(&rq->xdp_napi)) { ++ WRITE_ONCE(rq->rx_notify_masked, true); ++ __napi_schedule(&rq->xdp_napi); ++ } + } + } + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 8799854bacb29..5b0215b7c1761 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -3261,7 +3261,7 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) + + #ifdef CONFIG_PCI_MSI + if (adapter->intr.type == VMXNET3_IT_MSIX) { +- int i, nvec; ++ int i, nvec, nvec_allocated; + + nvec = adapter->share_intr == VMXNET3_INTR_TXSHARE ? + 1 : adapter->num_tx_queues; +@@ -3274,14 +3274,15 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) + for (i = 0; i < nvec; i++) + adapter->intr.msix_entries[i].entry = i; + +- nvec = vmxnet3_acquire_msix_vectors(adapter, nvec); +- if (nvec < 0) ++ nvec_allocated = vmxnet3_acquire_msix_vectors(adapter, nvec); ++ if (nvec_allocated < 0) + goto msix_err; + + /* If we cannot allocate one MSIx vector per queue + * then limit the number of rx queues to 1 + */ +- if (nvec == VMXNET3_LINUX_MIN_MSIX_VECT) { ++ if (nvec_allocated == VMXNET3_LINUX_MIN_MSIX_VECT && ++ nvec != VMXNET3_LINUX_MIN_MSIX_VECT) { + if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE + || adapter->num_rx_queues != 1) { + adapter->share_intr = VMXNET3_INTR_TXSHARE; +@@ -3291,14 +3292,14 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) + } + } + +- adapter->intr.num_intrs = nvec; ++ adapter->intr.num_intrs = nvec_allocated; + return; + + msix_err: + /* If we cannot allocate MSIx vectors use only one rx queue */ + dev_info(&adapter->pdev->dev, + "Failed to enable MSI-X, error %d. " +- "Limiting #rx queues to 1, try MSI.\n", nvec); ++ "Limiting #rx queues to 1, try MSI.\n", nvec_allocated); + + adapter->intr.type = VMXNET3_IT_MSI; + } +diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c +index 662e261173539..b2242a082431c 100644 +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -35,6 +35,7 @@ + #include <net/l3mdev.h> + #include <net/fib_rules.h> + #include <net/netns/generic.h> ++#include <net/netfilter/nf_conntrack.h> + + #define DRV_NAME "vrf" + #define DRV_VERSION "1.1" +@@ -424,12 +425,26 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev, + return NETDEV_TX_OK; + } + ++static void vrf_nf_set_untracked(struct sk_buff *skb) ++{ ++ if (skb_get_nfct(skb) == 0) ++ nf_ct_set(skb, NULL, IP_CT_UNTRACKED); ++} ++ ++static void vrf_nf_reset_ct(struct sk_buff *skb) ++{ ++ if (skb_get_nfct(skb) == IP_CT_UNTRACKED) ++ nf_reset_ct(skb); ++} ++ + #if IS_ENABLED(CONFIG_IPV6) + static int vrf_ip6_local_out(struct net *net, struct sock *sk, + struct sk_buff *skb) + { + int err; + ++ vrf_nf_reset_ct(skb); ++ + err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, + sk, skb, NULL, skb_dst(skb)->dev, dst_output); + +@@ -482,6 +497,7 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, + /* strip the ethernet header added for pass through VRF device */ + __skb_pull(skb, skb_network_offset(skb)); + ++ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + ret = vrf_ip6_local_out(net, skb->sk, skb); + if (unlikely(net_xmit_eval(ret))) + dev->stats.tx_errors++; +@@ -508,6 +524,8 @@ static int vrf_ip_local_out(struct net *net, struct sock *sk, + { + int err; + ++ vrf_nf_reset_ct(skb); ++ + err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, + skb, NULL, skb_dst(skb)->dev, dst_output); + if (likely(err == 1)) +@@ -562,6 +580,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, + RT_SCOPE_LINK); + } + ++ memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + ret = vrf_ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb); + if (unlikely(net_xmit_eval(ret))) + vrf_dev->stats.tx_errors++; +@@ -626,8 +645,7 @@ static void vrf_finish_direct(struct sk_buff *skb) + skb_pull(skb, ETH_HLEN); + } + +- /* reset skb device */ +- nf_reset_ct(skb); ++ vrf_nf_reset_ct(skb); + } + + #if IS_ENABLED(CONFIG_IPV6) +@@ -641,7 +659,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk, + struct neighbour *neigh; + int ret; + +- nf_reset_ct(skb); ++ vrf_nf_reset_ct(skb); + + skb->protocol = htons(ETH_P_IPV6); + skb->dev = dev; +@@ -772,6 +790,8 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev, + if (rt6_need_strict(&ipv6_hdr(skb)->daddr)) + return skb; + ++ vrf_nf_set_untracked(skb); ++ + if (qdisc_tx_is_default(vrf_dev) || + IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) + return vrf_ip6_out_direct(vrf_dev, sk, skb); +@@ -858,7 +878,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s + struct neighbour *neigh; + bool is_v6gw = false; + +- nf_reset_ct(skb); ++ vrf_nf_reset_ct(skb); + + /* Be paranoid, rather than too clever. */ + if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) { +@@ -1001,6 +1021,8 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev, + ipv4_is_lbcast(ip_hdr(skb)->daddr)) + return skb; + ++ vrf_nf_set_untracked(skb); ++ + if (qdisc_tx_is_default(vrf_dev) || + IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) + return vrf_ip_out_direct(vrf_dev, sk, skb); +diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c +index b7197e80f2264..9a4c8ff32d9dd 100644 +--- a/drivers/net/wireguard/allowedips.c ++++ b/drivers/net/wireguard/allowedips.c +@@ -163,7 +163,7 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key, + return exact; + } + +-static inline void connect_node(struct allowedips_node **parent, u8 bit, struct allowedips_node *node) ++static inline void connect_node(struct allowedips_node __rcu **parent, u8 bit, struct allowedips_node *node) + { + node->parent_bit_packed = (unsigned long)parent | bit; + rcu_assign_pointer(*parent, node); +diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c +index 551ddaaaf5400..a46067c38bf5d 100644 +--- a/drivers/net/wireguard/device.c ++++ b/drivers/net/wireguard/device.c +@@ -98,6 +98,7 @@ static int wg_stop(struct net_device *dev) + { + struct wg_device *wg = netdev_priv(dev); + struct wg_peer *peer; ++ struct sk_buff *skb; + + mutex_lock(&wg->device_update_lock); + list_for_each_entry(peer, &wg->peer_list, peer_list) { +@@ -108,7 +109,9 @@ static int wg_stop(struct net_device *dev) + wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake); + } + mutex_unlock(&wg->device_update_lock); +- skb_queue_purge(&wg->incoming_handshakes); ++ while ((skb = ptr_ring_consume(&wg->handshake_queue.ring)) != NULL) ++ kfree_skb(skb); ++ atomic_set(&wg->handshake_queue_len, 0); + wg_socket_reinit(wg, NULL, NULL); + return 0; + } +@@ -235,14 +238,13 @@ static void wg_destruct(struct net_device *dev) + destroy_workqueue(wg->handshake_receive_wq); + destroy_workqueue(wg->handshake_send_wq); + destroy_workqueue(wg->packet_crypt_wq); +- wg_packet_queue_free(&wg->decrypt_queue); +- wg_packet_queue_free(&wg->encrypt_queue); ++ wg_packet_queue_free(&wg->handshake_queue, true); ++ wg_packet_queue_free(&wg->decrypt_queue, false); ++ wg_packet_queue_free(&wg->encrypt_queue, false); + rcu_barrier(); /* Wait for all the peers to be actually freed. */ + wg_ratelimiter_uninit(); + memzero_explicit(&wg->static_identity, sizeof(wg->static_identity)); +- skb_queue_purge(&wg->incoming_handshakes); + free_percpu(dev->tstats); +- free_percpu(wg->incoming_handshakes_worker); + kvfree(wg->index_hashtable); + kvfree(wg->peer_hashtable); + mutex_unlock(&wg->device_update_lock); +@@ -298,7 +300,6 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, + init_rwsem(&wg->static_identity.lock); + mutex_init(&wg->socket_update_lock); + mutex_init(&wg->device_update_lock); +- skb_queue_head_init(&wg->incoming_handshakes); + wg_allowedips_init(&wg->peer_allowedips); + wg_cookie_checker_init(&wg->cookie_checker, wg); + INIT_LIST_HEAD(&wg->peer_list); +@@ -316,16 +317,10 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, + if (!dev->tstats) + goto err_free_index_hashtable; + +- wg->incoming_handshakes_worker = +- wg_packet_percpu_multicore_worker_alloc( +- wg_packet_handshake_receive_worker, wg); +- if (!wg->incoming_handshakes_worker) +- goto err_free_tstats; +- + wg->handshake_receive_wq = alloc_workqueue("wg-kex-%s", + WQ_CPU_INTENSIVE | WQ_FREEZABLE, 0, dev->name); + if (!wg->handshake_receive_wq) +- goto err_free_incoming_handshakes; ++ goto err_free_tstats; + + wg->handshake_send_wq = alloc_workqueue("wg-kex-%s", + WQ_UNBOUND | WQ_FREEZABLE, 0, dev->name); +@@ -347,10 +342,15 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, + if (ret < 0) + goto err_free_encrypt_queue; + +- ret = wg_ratelimiter_init(); ++ ret = wg_packet_queue_init(&wg->handshake_queue, wg_packet_handshake_receive_worker, ++ MAX_QUEUED_INCOMING_HANDSHAKES); + if (ret < 0) + goto err_free_decrypt_queue; + ++ ret = wg_ratelimiter_init(); ++ if (ret < 0) ++ goto err_free_handshake_queue; ++ + ret = register_netdevice(dev); + if (ret < 0) + goto err_uninit_ratelimiter; +@@ -367,18 +367,18 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, + + err_uninit_ratelimiter: + wg_ratelimiter_uninit(); ++err_free_handshake_queue: ++ wg_packet_queue_free(&wg->handshake_queue, false); + err_free_decrypt_queue: +- wg_packet_queue_free(&wg->decrypt_queue); ++ wg_packet_queue_free(&wg->decrypt_queue, false); + err_free_encrypt_queue: +- wg_packet_queue_free(&wg->encrypt_queue); ++ wg_packet_queue_free(&wg->encrypt_queue, false); + err_destroy_packet_crypt: + destroy_workqueue(wg->packet_crypt_wq); + err_destroy_handshake_send: + destroy_workqueue(wg->handshake_send_wq); + err_destroy_handshake_receive: + destroy_workqueue(wg->handshake_receive_wq); +-err_free_incoming_handshakes: +- free_percpu(wg->incoming_handshakes_worker); + err_free_tstats: + free_percpu(dev->tstats); + err_free_index_hashtable: +@@ -398,6 +398,7 @@ static struct rtnl_link_ops link_ops __read_mostly = { + static void wg_netns_pre_exit(struct net *net) + { + struct wg_device *wg; ++ struct wg_peer *peer; + + rtnl_lock(); + list_for_each_entry(wg, &device_list, device_list) { +@@ -407,6 +408,8 @@ static void wg_netns_pre_exit(struct net *net) + mutex_lock(&wg->device_update_lock); + rcu_assign_pointer(wg->creating_net, NULL); + wg_socket_reinit(wg, NULL, NULL); ++ list_for_each_entry(peer, &wg->peer_list, peer_list) ++ wg_socket_clear_peer_endpoint_src(peer); + mutex_unlock(&wg->device_update_lock); + } + } +diff --git a/drivers/net/wireguard/device.h b/drivers/net/wireguard/device.h +index 854bc3d97150e..43c7cebbf50b0 100644 +--- a/drivers/net/wireguard/device.h ++++ b/drivers/net/wireguard/device.h +@@ -39,21 +39,18 @@ struct prev_queue { + + struct wg_device { + struct net_device *dev; +- struct crypt_queue encrypt_queue, decrypt_queue; ++ struct crypt_queue encrypt_queue, decrypt_queue, handshake_queue; + struct sock __rcu *sock4, *sock6; + struct net __rcu *creating_net; + struct noise_static_identity static_identity; +- struct workqueue_struct *handshake_receive_wq, *handshake_send_wq; +- struct workqueue_struct *packet_crypt_wq; +- struct sk_buff_head incoming_handshakes; +- int incoming_handshake_cpu; +- struct multicore_worker __percpu *incoming_handshakes_worker; ++ struct workqueue_struct *packet_crypt_wq,*handshake_receive_wq, *handshake_send_wq; + struct cookie_checker cookie_checker; + struct pubkey_hashtable *peer_hashtable; + struct index_hashtable *index_hashtable; + struct allowedips peer_allowedips; + struct mutex device_update_lock, socket_update_lock; + struct list_head device_list, peer_list; ++ atomic_t handshake_queue_len; + unsigned int num_peers, device_update_gen; + u32 fwmark; + u16 incoming_port; +diff --git a/drivers/net/wireguard/queueing.c b/drivers/net/wireguard/queueing.c +index 48e7b982a3073..1de413b19e342 100644 +--- a/drivers/net/wireguard/queueing.c ++++ b/drivers/net/wireguard/queueing.c +@@ -38,11 +38,11 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, + return 0; + } + +-void wg_packet_queue_free(struct crypt_queue *queue) ++void wg_packet_queue_free(struct crypt_queue *queue, bool purge) + { + free_percpu(queue->worker); +- WARN_ON(!__ptr_ring_empty(&queue->ring)); +- ptr_ring_cleanup(&queue->ring, NULL); ++ WARN_ON(!purge && !__ptr_ring_empty(&queue->ring)); ++ ptr_ring_cleanup(&queue->ring, purge ? (void(*)(void*))kfree_skb : NULL); + } + + #define NEXT(skb) ((skb)->prev) +diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h +index 4ef2944a68bc9..e2388107f7fdc 100644 +--- a/drivers/net/wireguard/queueing.h ++++ b/drivers/net/wireguard/queueing.h +@@ -23,7 +23,7 @@ struct sk_buff; + /* queueing.c APIs: */ + int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, + unsigned int len); +-void wg_packet_queue_free(struct crypt_queue *queue); ++void wg_packet_queue_free(struct crypt_queue *queue, bool purge); + struct multicore_worker __percpu * + wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr); + +diff --git a/drivers/net/wireguard/ratelimiter.c b/drivers/net/wireguard/ratelimiter.c +index 3fedd1d21f5ee..dd55e5c26f468 100644 +--- a/drivers/net/wireguard/ratelimiter.c ++++ b/drivers/net/wireguard/ratelimiter.c +@@ -176,12 +176,12 @@ int wg_ratelimiter_init(void) + (1U << 14) / sizeof(struct hlist_head))); + max_entries = table_size * 8; + +- table_v4 = kvzalloc(table_size * sizeof(*table_v4), GFP_KERNEL); ++ table_v4 = kvcalloc(table_size, sizeof(*table_v4), GFP_KERNEL); + if (unlikely(!table_v4)) + goto err_kmemcache; + + #if IS_ENABLED(CONFIG_IPV6) +- table_v6 = kvzalloc(table_size * sizeof(*table_v6), GFP_KERNEL); ++ table_v6 = kvcalloc(table_size, sizeof(*table_v6), GFP_KERNEL); + if (unlikely(!table_v6)) { + kvfree(table_v4); + goto err_kmemcache; +diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c +index 7dc84bcca2613..7b8df406c7737 100644 +--- a/drivers/net/wireguard/receive.c ++++ b/drivers/net/wireguard/receive.c +@@ -116,8 +116,8 @@ static void wg_receive_handshake_packet(struct wg_device *wg, + return; + } + +- under_load = skb_queue_len(&wg->incoming_handshakes) >= +- MAX_QUEUED_INCOMING_HANDSHAKES / 8; ++ under_load = atomic_read(&wg->handshake_queue_len) >= ++ MAX_QUEUED_INCOMING_HANDSHAKES / 8; + if (under_load) { + last_under_load = ktime_get_coarse_boottime_ns(); + } else if (last_under_load) { +@@ -212,13 +212,14 @@ static void wg_receive_handshake_packet(struct wg_device *wg, + + void wg_packet_handshake_receive_worker(struct work_struct *work) + { +- struct wg_device *wg = container_of(work, struct multicore_worker, +- work)->ptr; ++ struct crypt_queue *queue = container_of(work, struct multicore_worker, work)->ptr; ++ struct wg_device *wg = container_of(queue, struct wg_device, handshake_queue); + struct sk_buff *skb; + +- while ((skb = skb_dequeue(&wg->incoming_handshakes)) != NULL) { ++ while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) { + wg_receive_handshake_packet(wg, skb); + dev_kfree_skb(skb); ++ atomic_dec(&wg->handshake_queue_len); + cond_resched(); + } + } +@@ -553,22 +554,28 @@ void wg_packet_receive(struct wg_device *wg, struct sk_buff *skb) + case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION): + case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): + case cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE): { +- int cpu; +- +- if (skb_queue_len(&wg->incoming_handshakes) > +- MAX_QUEUED_INCOMING_HANDSHAKES || +- unlikely(!rng_is_initialized())) { ++ int cpu, ret = -EBUSY; ++ ++ if (unlikely(!rng_is_initialized())) ++ goto drop; ++ if (atomic_read(&wg->handshake_queue_len) > MAX_QUEUED_INCOMING_HANDSHAKES / 2) { ++ if (spin_trylock_bh(&wg->handshake_queue.ring.producer_lock)) { ++ ret = __ptr_ring_produce(&wg->handshake_queue.ring, skb); ++ spin_unlock_bh(&wg->handshake_queue.ring.producer_lock); ++ } ++ } else ++ ret = ptr_ring_produce_bh(&wg->handshake_queue.ring, skb); ++ if (ret) { ++ drop: + net_dbg_skb_ratelimited("%s: Dropping handshake packet from %pISpfsc\n", + wg->dev->name, skb); + goto err; + } +- skb_queue_tail(&wg->incoming_handshakes, skb); +- /* Queues up a call to packet_process_queued_handshake_ +- * packets(skb): +- */ +- cpu = wg_cpumask_next_online(&wg->incoming_handshake_cpu); ++ atomic_inc(&wg->handshake_queue_len); ++ cpu = wg_cpumask_next_online(&wg->handshake_queue.last_cpu); ++ /* Queues up a call to packet_process_queued_handshake_packets(skb): */ + queue_work_on(cpu, wg->handshake_receive_wq, +- &per_cpu_ptr(wg->incoming_handshakes_worker, cpu)->work); ++ &per_cpu_ptr(wg->handshake_queue.worker, cpu)->work); + break; + } + case cpu_to_le32(MESSAGE_DATA): +diff --git a/drivers/net/wireguard/socket.c b/drivers/net/wireguard/socket.c +index 8c496b7471082..6f07b949cb81d 100644 +--- a/drivers/net/wireguard/socket.c ++++ b/drivers/net/wireguard/socket.c +@@ -308,7 +308,7 @@ void wg_socket_clear_peer_endpoint_src(struct wg_peer *peer) + { + write_lock_bh(&peer->endpoint_lock); + memset(&peer->endpoint.src6, 0, sizeof(peer->endpoint.src6)); +- dst_cache_reset(&peer->endpoint_cache); ++ dst_cache_reset_now(&peer->endpoint_cache); + write_unlock_bh(&peer->endpoint_lock); + } + +diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c +index 49cc4b7ed5163..1baec4b412c8d 100644 +--- a/drivers/net/wireless/ath/ar5523/ar5523.c ++++ b/drivers/net/wireless/ath/ar5523/ar5523.c +@@ -153,6 +153,10 @@ static void ar5523_cmd_rx_cb(struct urb *urb) + ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START"); + return; + } ++ if (!cmd->odata) { ++ ar5523_err(ar, "Unexpected WDCMSG_TARGET_START reply"); ++ return; ++ } + memcpy(cmd->odata, hdr + 1, sizeof(u32)); + cmd->olen = sizeof(u32); + cmd->res = 0; +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index 2f9be182fbfbb..58e86e662ab83 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -89,6 +89,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = true, + .dynamic_sar_support = false, + }, +@@ -124,6 +125,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = true, + .dynamic_sar_support = false, + }, +@@ -160,6 +162,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -190,6 +193,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .num_wds_entries = 0x20, + .uart_pin_workaround = true, + .tx_stats_over_pktlog = false, ++ .credit_size_workaround = false, + .bmi_large_size_download = true, + .supports_peer_stats_info = true, + .dynamic_sar_support = true, +@@ -226,6 +230,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -261,6 +266,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -296,6 +302,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -334,6 +341,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = true, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .supports_peer_stats_info = true, + .dynamic_sar_support = true, +@@ -376,6 +384,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -424,6 +433,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -469,6 +479,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -504,6 +515,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -541,6 +553,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = true, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -570,6 +583,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, + .uart_pin_workaround = true, ++ .credit_size_workaround = true, + .dynamic_sar_support = false, + }, + { +@@ -611,6 +625,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = false, + .hw_filter_reset_required = true, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + }, +@@ -639,6 +654,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .rri_on_ddr = true, + .hw_filter_reset_required = false, + .fw_diag_ce_download = false, ++ .credit_size_workaround = false, + .tx_stats_over_pktlog = false, + .dynamic_sar_support = true, + }, +@@ -714,6 +730,7 @@ static void ath10k_send_suspend_complete(struct ath10k *ar) + + static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode) + { ++ bool mtu_workaround = ar->hw_params.credit_size_workaround; + int ret; + u32 param = 0; + +@@ -731,7 +748,7 @@ static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode) + + param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET; + +- if (mode == ATH10K_FIRMWARE_MODE_NORMAL) ++ if (mode == ATH10K_FIRMWARE_MODE_NORMAL && !mtu_workaround) + param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; + else + param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; +@@ -2690,9 +2707,16 @@ static int ath10k_core_copy_target_iram(struct ath10k *ar) + int i, ret; + u32 len, remaining_len; + +- hw_mem = ath10k_coredump_get_mem_layout(ar); ++ /* copy target iram feature must work also when ++ * ATH10K_FW_CRASH_DUMP_RAM_DATA is disabled, so ++ * _ath10k_coredump_get_mem_layout() to accomplist that ++ */ ++ hw_mem = _ath10k_coredump_get_mem_layout(ar); + if (!hw_mem) +- return -ENOMEM; ++ /* if CONFIG_DEV_COREDUMP is disabled we get NULL, then ++ * just silently disable the feature by doing nothing ++ */ ++ return 0; + + for (i = 0; i < hw_mem->region_table.size; i++) { + tmp = &hw_mem->region_table.regions[i]; +diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c +index 7eb72290a925c..55e7e11d06d94 100644 +--- a/drivers/net/wireless/ath/ath10k/coredump.c ++++ b/drivers/net/wireless/ath/ath10k/coredump.c +@@ -1447,11 +1447,17 @@ static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar) + + const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar) + { +- int i; +- + if (!test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) + return NULL; + ++ return _ath10k_coredump_get_mem_layout(ar); ++} ++EXPORT_SYMBOL(ath10k_coredump_get_mem_layout); ++ ++const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar) ++{ ++ int i; ++ + if (WARN_ON(ar->target_version == 0)) + return NULL; + +@@ -1464,7 +1470,6 @@ const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k + + return NULL; + } +-EXPORT_SYMBOL(ath10k_coredump_get_mem_layout); + + struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar) + { +diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h +index 42404e246e0e9..240d705150888 100644 +--- a/drivers/net/wireless/ath/ath10k/coredump.h ++++ b/drivers/net/wireless/ath/ath10k/coredump.h +@@ -176,6 +176,7 @@ int ath10k_coredump_register(struct ath10k *ar); + void ath10k_coredump_unregister(struct ath10k *ar); + void ath10k_coredump_destroy(struct ath10k *ar); + ++const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar); + const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar); + + #else /* CONFIG_DEV_COREDUMP */ +@@ -214,6 +215,12 @@ ath10k_coredump_get_mem_layout(struct ath10k *ar) + return NULL; + } + ++static inline const struct ath10k_hw_mem_layout * ++_ath10k_coredump_get_mem_layout(struct ath10k *ar) ++{ ++ return NULL; ++} ++ + #endif /* CONFIG_DEV_COREDUMP */ + + #endif /* _COREDUMP_H_ */ +diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c +index d6b8bdcef4160..b793eac2cfac8 100644 +--- a/drivers/net/wireless/ath/ath10k/htt_tx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c +@@ -147,6 +147,9 @@ void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) + htt->num_pending_tx--; + if (htt->num_pending_tx == htt->max_num_pending_tx - 1) + ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); ++ ++ if (htt->num_pending_tx == 0) ++ wake_up(&htt->empty_tx_wq); + } + + int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) +diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h +index 6b03c7787e36a..591ef7416b613 100644 +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -618,6 +618,9 @@ struct ath10k_hw_params { + */ + bool uart_pin_workaround; + ++ /* Workaround for the credit size calculation */ ++ bool credit_size_workaround; ++ + /* tx stats support over pktlog */ + bool tx_stats_over_pktlog; + +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index c272b290fa73d..1f73fbfee0c06 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -993,8 +993,12 @@ static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif) + ath10k_mac_vif_beacon_free(arvif); + + if (arvif->beacon_buf) { +- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, +- arvif->beacon_buf, arvif->beacon_paddr); ++ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) ++ kfree(arvif->beacon_buf); ++ else ++ dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, ++ arvif->beacon_buf, ++ arvif->beacon_paddr); + arvif->beacon_buf = NULL; + } + } +@@ -1048,7 +1052,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) + arg.channel.min_power = 0; + arg.channel.max_power = channel->max_power * 2; + arg.channel.max_reg_power = channel->max_reg_power * 2; +- arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; ++ arg.channel.max_antenna_gain = channel->max_antenna_gain; + + reinit_completion(&ar->vdev_setup_done); + reinit_completion(&ar->vdev_delete_done); +@@ -1494,7 +1498,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, + arg.channel.min_power = 0; + arg.channel.max_power = chandef->chan->max_power * 2; + arg.channel.max_reg_power = chandef->chan->max_reg_power * 2; +- arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2; ++ arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain; + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; +@@ -3422,7 +3426,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) + ch->min_power = 0; + ch->max_power = channel->max_power * 2; + ch->max_reg_power = channel->max_reg_power * 2; +- ch->max_antenna_gain = channel->max_antenna_gain * 2; ++ ch->max_antenna_gain = channel->max_antenna_gain; + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any +@@ -5576,10 +5580,25 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, + if (vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT || + vif->type == NL80211_IFTYPE_AP) { +- arvif->beacon_buf = dma_alloc_coherent(ar->dev, +- IEEE80211_MAX_FRAME_LEN, +- &arvif->beacon_paddr, +- GFP_ATOMIC); ++ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) { ++ arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN, ++ GFP_KERNEL); ++ ++ /* Using a kernel pointer in place of a dma_addr_t ++ * token can lead to undefined behavior if that ++ * makes it into cache management functions. Use a ++ * known-invalid address token instead, which ++ * avoids the warning and makes it easier to catch ++ * bugs if it does end up getting used. ++ */ ++ arvif->beacon_paddr = DMA_MAPPING_ERROR; ++ } else { ++ arvif->beacon_buf = ++ dma_alloc_coherent(ar->dev, ++ IEEE80211_MAX_FRAME_LEN, ++ &arvif->beacon_paddr, ++ GFP_ATOMIC); ++ } + if (!arvif->beacon_buf) { + ret = -ENOMEM; + ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", +@@ -5794,8 +5813,12 @@ err_vdev_delete: + + err: + if (arvif->beacon_buf) { +- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, +- arvif->beacon_buf, arvif->beacon_paddr); ++ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) ++ kfree(arvif->beacon_buf); ++ else ++ dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, ++ arvif->beacon_buf, ++ arvif->beacon_paddr); + arvif->beacon_buf = NULL; + } + +diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c +index 07e478f9a808c..80fcb917fe4e1 100644 +--- a/drivers/net/wireless/ath/ath10k/qmi.c ++++ b/drivers/net/wireless/ath/ath10k/qmi.c +@@ -864,7 +864,8 @@ static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi) + + ath10k_qmi_remove_msa_permission(qmi); + ath10k_core_free_board_files(ar); +- if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags)) ++ if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags) && ++ !test_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags)) + ath10k_snoc_fw_crashed_dump(ar); + + ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND); +diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c +index b746052737e0b..eb705214f3f0a 100644 +--- a/drivers/net/wireless/ath/ath10k/sdio.c ++++ b/drivers/net/wireless/ath/ath10k/sdio.c +@@ -1363,8 +1363,11 @@ static void ath10k_rx_indication_async_work(struct work_struct *work) + ep->ep_ops.ep_rx_complete(ar, skb); + } + +- if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) ++ if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) { ++ local_bh_disable(); + napi_schedule(&ar->napi); ++ local_bh_enable(); ++ } + } + + static int ath10k_sdio_read_rtc_state(struct ath10k_sdio *ar_sdio, unsigned char *state) +diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c +index ea00fbb156015..9513ab696fff1 100644 +--- a/drivers/net/wireless/ath/ath10k/snoc.c ++++ b/drivers/net/wireless/ath/ath10k/snoc.c +@@ -12,6 +12,7 @@ + #include <linux/platform_device.h> + #include <linux/property.h> + #include <linux/regulator/consumer.h> ++#include <linux/remoteproc/qcom_rproc.h> + #include <linux/of_address.h> + #include <linux/iommu.h> + +@@ -1477,6 +1478,74 @@ void ath10k_snoc_fw_crashed_dump(struct ath10k *ar) + mutex_unlock(&ar->dump_mutex); + } + ++static int ath10k_snoc_modem_notify(struct notifier_block *nb, unsigned long action, ++ void *data) ++{ ++ struct ath10k_snoc *ar_snoc = container_of(nb, struct ath10k_snoc, nb); ++ struct ath10k *ar = ar_snoc->ar; ++ struct qcom_ssr_notify_data *notify_data = data; ++ ++ switch (action) { ++ case QCOM_SSR_BEFORE_POWERUP: ++ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem starting event\n"); ++ clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags); ++ break; ++ ++ case QCOM_SSR_AFTER_POWERUP: ++ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem running event\n"); ++ break; ++ ++ case QCOM_SSR_BEFORE_SHUTDOWN: ++ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem %s event\n", ++ notify_data->crashed ? "crashed" : "stopping"); ++ if (!notify_data->crashed) ++ set_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags); ++ else ++ clear_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags); ++ break; ++ ++ case QCOM_SSR_AFTER_SHUTDOWN: ++ ath10k_dbg(ar, ATH10K_DBG_SNOC, "received modem offline event\n"); ++ break; ++ ++ default: ++ ath10k_err(ar, "received unrecognized event %lu\n", action); ++ break; ++ } ++ ++ return NOTIFY_OK; ++} ++ ++static int ath10k_modem_init(struct ath10k *ar) ++{ ++ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); ++ void *notifier; ++ int ret; ++ ++ ar_snoc->nb.notifier_call = ath10k_snoc_modem_notify; ++ ++ notifier = qcom_register_ssr_notifier("mpss", &ar_snoc->nb); ++ if (IS_ERR(notifier)) { ++ ret = PTR_ERR(notifier); ++ ath10k_err(ar, "failed to initialize modem notifier: %d\n", ret); ++ return ret; ++ } ++ ++ ar_snoc->notifier = notifier; ++ ++ return 0; ++} ++ ++static void ath10k_modem_deinit(struct ath10k *ar) ++{ ++ int ret; ++ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); ++ ++ ret = qcom_unregister_ssr_notifier(ar_snoc->notifier, &ar_snoc->nb); ++ if (ret) ++ ath10k_err(ar, "error %d unregistering notifier\n", ret); ++} ++ + static int ath10k_setup_msa_resources(struct ath10k *ar, u32 msa_size) + { + struct device *dev = ar->dev; +@@ -1740,10 +1809,17 @@ static int ath10k_snoc_probe(struct platform_device *pdev) + goto err_fw_deinit; + } + ++ ret = ath10k_modem_init(ar); ++ if (ret) ++ goto err_qmi_deinit; ++ + ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n"); + + return 0; + ++err_qmi_deinit: ++ ath10k_qmi_deinit(ar); ++ + err_fw_deinit: + ath10k_fw_deinit(ar); + +@@ -1771,6 +1847,7 @@ static int ath10k_snoc_free_resources(struct ath10k *ar) + ath10k_fw_deinit(ar); + ath10k_snoc_free_irq(ar); + ath10k_snoc_release_resource(ar); ++ ath10k_modem_deinit(ar); + ath10k_qmi_deinit(ar); + ath10k_core_destroy(ar); + +diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h +index 5095d1893681b..d4bce17076960 100644 +--- a/drivers/net/wireless/ath/ath10k/snoc.h ++++ b/drivers/net/wireless/ath/ath10k/snoc.h +@@ -6,6 +6,8 @@ + #ifndef _SNOC_H_ + #define _SNOC_H_ + ++#include <linux/notifier.h> ++ + #include "hw.h" + #include "ce.h" + #include "qmi.h" +@@ -45,6 +47,7 @@ struct ath10k_snoc_ce_irq { + enum ath10k_snoc_flags { + ATH10K_SNOC_FLAG_REGISTERED, + ATH10K_SNOC_FLAG_UNREGISTERING, ++ ATH10K_SNOC_FLAG_MODEM_STOPPED, + ATH10K_SNOC_FLAG_RECOVERY, + ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, + }; +@@ -75,6 +78,8 @@ struct ath10k_snoc { + struct clk_bulk_data *clks; + size_t num_clks; + struct ath10k_qmi *qmi; ++ struct notifier_block nb; ++ void *notifier; + unsigned long flags; + bool xo_cal_supported; + u32 xo_cal_data; +diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c +index 7c9ea0c073d8b..6f8b642188941 100644 +--- a/drivers/net/wireless/ath/ath10k/txrx.c ++++ b/drivers/net/wireless/ath/ath10k/txrx.c +@@ -82,8 +82,6 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, + flags = skb_cb->flags; + ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); + ath10k_htt_tx_dec_pending(htt); +- if (htt->num_pending_tx == 0) +- wake_up(&htt->empty_tx_wq); + spin_unlock_bh(&htt->tx_lock); + + rcu_read_lock(); +diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c +index 19b9c27e30e20..3d98f19c6ec8a 100644 +--- a/drivers/net/wireless/ath/ath10k/usb.c ++++ b/drivers/net/wireless/ath/ath10k/usb.c +@@ -525,7 +525,7 @@ static int ath10k_usb_submit_ctrl_in(struct ath10k *ar, + req, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, +- size, 2 * HZ); ++ size, 2000); + + if (ret < 0) { + ath10k_warn(ar, "Failed to read usb control message: %d\n", +@@ -853,6 +853,11 @@ static int ath10k_usb_setup_pipe_resources(struct ath10k *ar, + le16_to_cpu(endpoint->wMaxPacketSize), + endpoint->bInterval); + } ++ ++ /* Ignore broken descriptors. */ ++ if (usb_endpoint_maxp(endpoint) == 0) ++ continue; ++ + urbcount = 0; + + pipe_num = +diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c +index b8a4bbfe10b87..7c1c2658cb5f8 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -2610,6 +2610,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) + if (ieee80211_is_beacon(hdr->frame_control)) + ath10k_mac_handle_beacon(ar, skb); + ++ if (ieee80211_is_beacon(hdr->frame_control) || ++ ieee80211_is_probe_resp(hdr->frame_control)) ++ status->boottime_ns = ktime_get_boottime_ns(); ++ + ath10k_dbg(ar, ATH10K_DBG_MGMT, + "event mgmt rx skb %pK len %d ftype %02x stype %02x\n", + skb, skb->len, +diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h +index 41c1a3d339c25..01bfd09a9d88c 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h +@@ -2066,7 +2066,9 @@ struct wmi_channel { + union { + __le32 reginfo1; + struct { ++ /* note: power unit is 1 dBm */ + u8 antenna_max; ++ /* note: power unit is 0.5 dBm */ + u8 max_tx_power; + } __packed; + } __packed; +@@ -2086,6 +2088,7 @@ struct wmi_channel_arg { + u32 min_power; + u32 max_power; + u32 max_reg_power; ++ /* note: power unit is 1 dBm */ + u32 max_antenna_gain; + u32 reg_class_id; + enum wmi_phy_mode mode; +diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c +index 8c9c781afc3e5..3fb0aa0008259 100644 +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -175,8 +175,11 @@ static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) + + ath11k_ahb_ext_grp_disable(irq_grp); + +- napi_synchronize(&irq_grp->napi); +- napi_disable(&irq_grp->napi); ++ if (irq_grp->napi_enabled) { ++ napi_synchronize(&irq_grp->napi); ++ napi_disable(&irq_grp->napi); ++ irq_grp->napi_enabled = false; ++ } + } + } + +@@ -206,13 +209,13 @@ static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset) + + static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) + { +- const struct ce_pipe_config *ce_config; ++ const struct ce_attr *ce_attr; + +- ce_config = &ab->hw_params.target_ce_config[ce_id]; +- if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT) ++ ce_attr = &ab->hw_params.host_ce_config[ce_id]; ++ if (ce_attr->src_nentries) + ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS); + +- if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) { ++ if (ce_attr->dest_nentries) { + ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); + ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, + CE_HOST_IE_3_ADDRESS); +@@ -221,13 +224,13 @@ static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) + + static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) + { +- const struct ce_pipe_config *ce_config; ++ const struct ce_attr *ce_attr; + +- ce_config = &ab->hw_params.target_ce_config[ce_id]; +- if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT) ++ ce_attr = &ab->hw_params.host_ce_config[ce_id]; ++ if (ce_attr->src_nentries) + ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS); + +- if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) { ++ if (ce_attr->dest_nentries) { + ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); + ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, + CE_HOST_IE_3_ADDRESS); +@@ -300,7 +303,10 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + +- napi_enable(&irq_grp->napi); ++ if (!irq_grp->napi_enabled) { ++ napi_enable(&irq_grp->napi); ++ irq_grp->napi_enabled = true; ++ } + ath11k_ahb_ext_grp_enable(irq_grp); + } + } +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index 969bf1a590d99..7dcf6b13f7949 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -347,11 +347,26 @@ static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + scnprintf(variant, sizeof(variant), ",variant=%s", + ab->qmi.target.bdf_ext); + +- scnprintf(name, name_len, +- "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", +- ath11k_bus_str(ab->hif.bus), +- ab->qmi.target.chip_id, +- ab->qmi.target.board_id, variant); ++ switch (ab->id.bdf_search) { ++ case ATH11K_BDF_SEARCH_BUS_AND_BOARD: ++ scnprintf(name, name_len, ++ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s", ++ ath11k_bus_str(ab->hif.bus), ++ ab->id.vendor, ab->id.device, ++ ab->id.subsystem_vendor, ++ ab->id.subsystem_device, ++ ab->qmi.target.chip_id, ++ ab->qmi.target.board_id, ++ variant); ++ break; ++ default: ++ scnprintf(name, name_len, ++ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s", ++ ath11k_bus_str(ab->hif.bus), ++ ab->qmi.target.chip_id, ++ ab->qmi.target.board_id, variant); ++ break; ++ } + + ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name); + +@@ -588,7 +603,7 @@ static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, + return 0; + } + +-#define BOARD_NAME_SIZE 100 ++#define BOARD_NAME_SIZE 200 + int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) + { + char boardname[BOARD_NAME_SIZE]; +diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h +index 018fb2385f2a3..caa8f6eba0097 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -47,6 +47,11 @@ enum ath11k_supported_bw { + ATH11K_BW_160 = 3, + }; + ++enum ath11k_bdf_search { ++ ATH11K_BDF_SEARCH_DEFAULT, ++ ATH11K_BDF_SEARCH_BUS_AND_BOARD, ++}; ++ + enum wme_ac { + WME_AC_BE, + WME_AC_BK, +@@ -132,6 +137,7 @@ struct ath11k_ext_irq_grp { + u32 num_irq; + u32 grp_id; + u64 timestamp; ++ bool napi_enabled; + struct napi_struct napi; + struct net_device napi_ndev; + }; +@@ -701,7 +707,6 @@ struct ath11k_base { + u32 wlan_init_status; + int irq_num[ATH11K_IRQ_NUM_MAX]; + struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX]; +- struct napi_struct *napi; + struct ath11k_targ_cap target_caps; + u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE]; + bool pdevs_macaddr_valid; +@@ -747,6 +752,14 @@ struct ath11k_base { + + struct completion htc_suspend; + ++ struct { ++ enum ath11k_bdf_search bdf_search; ++ u32 vendor; ++ u32 device; ++ u32 subsystem_vendor; ++ u32 subsystem_device; ++ } id; ++ + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); + }; +diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireless/ath/ath11k/dbring.c +index 5e1f5437b4185..fd98ba5b1130b 100644 +--- a/drivers/net/wireless/ath/ath11k/dbring.c ++++ b/drivers/net/wireless/ath/ath11k/dbring.c +@@ -8,8 +8,7 @@ + + static int ath11k_dbring_bufs_replenish(struct ath11k *ar, + struct ath11k_dbring *ring, +- struct ath11k_dbring_element *buff, +- gfp_t gfp) ++ struct ath11k_dbring_element *buff) + { + struct ath11k_base *ab = ar->ab; + struct hal_srng *srng; +@@ -35,7 +34,7 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar, + goto err; + + spin_lock_bh(&ring->idr_lock); +- buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, gfp); ++ buf_id = idr_alloc(&ring->bufs_idr, buff, 0, ring->bufs_max, GFP_ATOMIC); + spin_unlock_bh(&ring->idr_lock); + if (buf_id < 0) { + ret = -ENOBUFS; +@@ -72,8 +71,7 @@ err: + } + + static int ath11k_dbring_fill_bufs(struct ath11k *ar, +- struct ath11k_dbring *ring, +- gfp_t gfp) ++ struct ath11k_dbring *ring) + { + struct ath11k_dbring_element *buff; + struct hal_srng *srng; +@@ -92,11 +90,11 @@ static int ath11k_dbring_fill_bufs(struct ath11k *ar, + size = sizeof(*buff) + ring->buf_sz + align - 1; + + while (num_remain > 0) { +- buff = kzalloc(size, gfp); ++ buff = kzalloc(size, GFP_ATOMIC); + if (!buff) + break; + +- ret = ath11k_dbring_bufs_replenish(ar, ring, buff, gfp); ++ ret = ath11k_dbring_bufs_replenish(ar, ring, buff); + if (ret) { + ath11k_warn(ar->ab, "failed to replenish db ring num_remain %d req_ent %d\n", + num_remain, req_entries); +@@ -176,7 +174,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar, + ring->hp_addr = ath11k_hal_srng_get_hp_addr(ar->ab, srng); + ring->tp_addr = ath11k_hal_srng_get_tp_addr(ar->ab, srng); + +- ret = ath11k_dbring_fill_bufs(ar, ring, GFP_KERNEL); ++ ret = ath11k_dbring_fill_bufs(ar, ring); + + return ret; + } +@@ -322,7 +320,7 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab, + } + + memset(buff, 0, size); +- ath11k_dbring_bufs_replenish(ar, ring, buff, GFP_ATOMIC); ++ ath11k_dbring_bufs_replenish(ar, ring, buff); + } + + spin_unlock_bh(&srng->lock); +diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h +index ee768ccce46e1..d3e50e34f23dd 100644 +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -515,7 +515,8 @@ struct htt_ppdu_stats_cfg_cmd { + } __packed; + + #define HTT_PPDU_STATS_CFG_MSG_TYPE GENMASK(7, 0) +-#define HTT_PPDU_STATS_CFG_PDEV_ID GENMASK(15, 8) ++#define HTT_PPDU_STATS_CFG_SOC_STATS BIT(8) ++#define HTT_PPDU_STATS_CFG_PDEV_ID GENMASK(15, 9) + #define HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK GENMASK(31, 16) + + enum htt_ppdu_stats_tag_type { +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 9a224817630ae..0ae6bebff801d 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -2337,8 +2337,10 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, + channel_num = meta_data; + center_freq = meta_data >> 16; + +- if (center_freq >= 5935 && center_freq <= 7105) { ++ if (center_freq >= ATH11K_MIN_6G_FREQ && ++ center_freq <= ATH11K_MAX_6G_FREQ) { + rx_status->band = NL80211_BAND_6GHZ; ++ rx_status->freq = center_freq; + } else if (channel_num >= 1 && channel_num <= 14) { + rx_status->band = NL80211_BAND_2GHZ; + } else if (channel_num >= 36 && channel_num <= 173) { +@@ -2356,8 +2358,9 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, + rx_desc, sizeof(struct hal_rx_desc)); + } + +- rx_status->freq = ieee80211_channel_to_frequency(channel_num, +- rx_status->band); ++ if (rx_status->band != NL80211_BAND_6GHZ) ++ rx_status->freq = ieee80211_channel_to_frequency(channel_num, ++ rx_status->band); + + ath11k_dp_rx_h_rate(ar, rx_desc, rx_status); + } +@@ -3310,7 +3313,7 @@ static int ath11k_dp_rx_h_defrag_reo_reinject(struct ath11k *ar, struct dp_rx_ti + + paddr = dma_map_single(ab->dev, defrag_skb->data, + defrag_skb->len + skb_tailroom(defrag_skb), +- DMA_FROM_DEVICE); ++ DMA_TO_DEVICE); + if (dma_mapping_error(ab->dev, paddr)) + return -ENOMEM; + +@@ -3375,7 +3378,7 @@ err_free_idr: + spin_unlock_bh(&rx_refill_ring->idr_lock); + err_unmap_dma: + dma_unmap_single(ab->dev, paddr, defrag_skb->len + skb_tailroom(defrag_skb), +- DMA_FROM_DEVICE); ++ DMA_TO_DEVICE); + return ret; + } + +diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c +index 8bba5234f81fc..bb8744ccfa00c 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -895,7 +895,7 @@ int ath11k_dp_tx_htt_h2t_ppdu_stats_req(struct ath11k *ar, u32 mask) + cmd->msg = FIELD_PREP(HTT_PPDU_STATS_CFG_MSG_TYPE, + HTT_H2T_MSG_TYPE_PPDU_STATS_CFG); + +- pdev_mask = 1 << (i + 1); ++ pdev_mask = 1 << (ar->pdev_idx + i); + cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_PDEV_ID, pdev_mask); + cmd->msg |= FIELD_PREP(HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK, mask); + +diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c +index eaa0edca55761..5dbf5596c9e8e 100644 +--- a/drivers/net/wireless/ath/ath11k/hal.c ++++ b/drivers/net/wireless/ath/ath11k/hal.c +@@ -947,6 +947,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, + srng->msi_data = params->msi_data; + srng->initialized = 1; + spin_lock_init(&srng->lock); ++ lockdep_set_class(&srng->lock, hal->srng_key + ring_id); + + for (i = 0; i < HAL_SRNG_NUM_REG_GRP; i++) { + srng->hwreg_base[i] = srng_config->reg_start[i] + +@@ -1233,6 +1234,24 @@ static int ath11k_hal_srng_create_config(struct ath11k_base *ab) + return 0; + } + ++static void ath11k_hal_register_srng_key(struct ath11k_base *ab) ++{ ++ struct ath11k_hal *hal = &ab->hal; ++ u32 ring_id; ++ ++ for (ring_id = 0; ring_id < HAL_SRNG_RING_ID_MAX; ring_id++) ++ lockdep_register_key(hal->srng_key + ring_id); ++} ++ ++static void ath11k_hal_unregister_srng_key(struct ath11k_base *ab) ++{ ++ struct ath11k_hal *hal = &ab->hal; ++ u32 ring_id; ++ ++ for (ring_id = 0; ring_id < HAL_SRNG_RING_ID_MAX; ring_id++) ++ lockdep_unregister_key(hal->srng_key + ring_id); ++} ++ + int ath11k_hal_srng_init(struct ath11k_base *ab) + { + struct ath11k_hal *hal = &ab->hal; +@@ -1252,6 +1271,8 @@ int ath11k_hal_srng_init(struct ath11k_base *ab) + if (ret) + goto err_free_cont_rdp; + ++ ath11k_hal_register_srng_key(ab); ++ + return 0; + + err_free_cont_rdp: +@@ -1266,6 +1287,7 @@ void ath11k_hal_srng_deinit(struct ath11k_base *ab) + { + struct ath11k_hal *hal = &ab->hal; + ++ ath11k_hal_unregister_srng_key(ab); + ath11k_hal_free_cont_rdp(ab); + ath11k_hal_free_cont_wrp(ab); + kfree(hal->srng_config); +diff --git a/drivers/net/wireless/ath/ath11k/hal.h b/drivers/net/wireless/ath/ath11k/hal.h +index 35ed3a14e200a..7fdcd8bbf7e98 100644 +--- a/drivers/net/wireless/ath/ath11k/hal.h ++++ b/drivers/net/wireless/ath/ath11k/hal.h +@@ -901,6 +901,8 @@ struct ath11k_hal { + /* shadow register configuration */ + u32 shadow_reg_addr[HAL_SHADOW_NUM_REGS]; + int num_shadow_reg_configured; ++ ++ struct lock_class_key srng_key[HAL_SRNG_RING_ID_MAX]; + }; + + u32 ath11k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid); +diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c +index d9596903b0a58..3e92cc7cfe4c9 100644 +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -1015,8 +1015,6 @@ const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074 = { + const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390 = { + .tx = { + ATH11K_TX_RING_MASK_0, +- ATH11K_TX_RING_MASK_1, +- ATH11K_TX_RING_MASK_2, + }, + .rx_mon_status = { + 0, 0, 0, 0, +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index e9b3689331ec2..3834be1587057 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: BSD-3-Clause-Clear + /* + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + */ + + #include <net/mac80211.h> +@@ -767,11 +768,15 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) + + if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) + arvif->rsnie_present = true; ++ else ++ arvif->rsnie_present = false; + + if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + ies, (skb_tail_pointer(bcn) - ies))) + arvif->wpaie_present = true; ++ else ++ arvif->wpaie_present = false; + + ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); + +@@ -2576,9 +2581,12 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, + arg.scan_id = ATH11K_SCAN_ID; + + if (req->ie_len) { ++ arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL); ++ if (!arg.extraie.ptr) { ++ ret = -ENOMEM; ++ goto exit; ++ } + arg.extraie.len = req->ie_len; +- arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL); +- memcpy(arg.extraie.ptr, req->ie, req->ie_len); + } + + if (req->n_ssids) { +@@ -2655,9 +2663,7 @@ static int ath11k_install_key(struct ath11k_vif *arvif, + return 0; + + if (cmd == DISABLE_KEY) { +- /* TODO: Check if FW expects value other than NONE for del */ +- /* arg.key_cipher = WMI_CIPHER_NONE; */ +- arg.key_len = 0; ++ arg.key_cipher = WMI_CIPHER_NONE; + arg.key_data = NULL; + goto install; + } +@@ -2789,7 +2795,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + /* flush the fragments cache during key (re)install to + * ensure all frags in the new frag list belong to the same key. + */ +- if (peer && cmd == SET_KEY) ++ if (peer && sta && cmd == SET_KEY) + ath11k_peer_frags_flush(ar, peer); + spin_unlock_bh(&ab->base_lock); + +@@ -4131,23 +4137,32 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant) + return 0; + } + +-int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) ++static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id) + { +- struct sk_buff *msdu = skb; ++ struct sk_buff *msdu; + struct ieee80211_tx_info *info; +- struct ath11k *ar = ctx; +- struct ath11k_base *ab = ar->ab; + + spin_lock_bh(&ar->txmgmt_idr_lock); +- idr_remove(&ar->txmgmt_idr, buf_id); ++ msdu = idr_remove(&ar->txmgmt_idr, buf_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); +- dma_unmap_single(ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len, ++ ++ if (!msdu) ++ return; ++ ++ dma_unmap_single(ar->ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len, + DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); + memset(&info->status, 0, sizeof(info->status)); + + ieee80211_free_txskb(ar->hw, msdu); ++} ++ ++int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) ++{ ++ struct ath11k *ar = ctx; ++ ++ ath11k_mac_tx_mgmt_free(ar, buf_id); + + return 0; + } +@@ -4156,17 +4171,10 @@ static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx) + { + struct ieee80211_vif *vif = ctx; + struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb); +- struct sk_buff *msdu = skb; + struct ath11k *ar = skb_cb->ar; +- struct ath11k_base *ab = ar->ab; + +- if (skb_cb->vif == vif) { +- spin_lock_bh(&ar->txmgmt_idr_lock); +- idr_remove(&ar->txmgmt_idr, buf_id); +- spin_unlock_bh(&ar->txmgmt_idr_lock); +- dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, +- DMA_TO_DEVICE); +- } ++ if (skb_cb->vif == vif) ++ ath11k_mac_tx_mgmt_free(ar, buf_id); + + return 0; + } +@@ -4181,6 +4189,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif, + int buf_id; + int ret; + ++ ATH11K_SKB_CB(skb)->ar = ar; ++ + spin_lock_bh(&ar->txmgmt_idr_lock); + buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0, + ATH11K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC); +@@ -6590,7 +6600,7 @@ static int __ath11k_mac_register(struct ath11k *ar) + ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR); + + /* Apply the regd received during initialization */ +- ret = ath11k_regd_update(ar, true); ++ ret = ath11k_regd_update(ar); + if (ret) { + ath11k_err(ar->ab, "ath11k regd update failed: %d\n", ret); + goto err_unregister_hw; +diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c +index 26c7ae242db67..49c0b1ad40a02 100644 +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -533,7 +533,11 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, + ret = mhi_pm_suspend(ab_pci->mhi_ctrl); + break; + case ATH11K_MHI_RESUME: +- ret = mhi_pm_resume(ab_pci->mhi_ctrl); ++ /* Do force MHI resume as some devices like QCA6390, WCN6855 ++ * are not in M3 state but they are functional. So just ignore ++ * the MHI state while resuming. ++ */ ++ ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); + break; + case ATH11K_MHI_TRIGGER_RDDM: + ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index 5abb38cc3b55f..54ce08f1c6e0c 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -632,8 +632,11 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc) + + ath11k_pci_ext_grp_disable(irq_grp); + +- napi_synchronize(&irq_grp->napi); +- napi_disable(&irq_grp->napi); ++ if (irq_grp->napi_enabled) { ++ napi_synchronize(&irq_grp->napi); ++ napi_disable(&irq_grp->napi); ++ irq_grp->napi_enabled = false; ++ } + } + } + +@@ -652,7 +655,10 @@ static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab) + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + +- napi_enable(&irq_grp->napi); ++ if (!irq_grp->napi_enabled) { ++ napi_enable(&irq_grp->napi); ++ irq_grp->napi_enabled = true; ++ } + ath11k_pci_ext_grp_enable(irq_grp); + } + } +@@ -1218,6 +1224,15 @@ static int ath11k_pci_probe(struct pci_dev *pdev, + goto err_free_core; + } + ++ ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n", ++ pdev->vendor, pdev->device, ++ pdev->subsystem_vendor, pdev->subsystem_device); ++ ++ ab->id.vendor = pdev->vendor; ++ ab->id.device = pdev->device; ++ ab->id.subsystem_vendor = pdev->subsystem_vendor; ++ ab->id.subsystem_device = pdev->subsystem_device; ++ + switch (pci_dev->device) { + case QCA6390_DEVICE_ID: + ath11k_pci_read_hw_version(ab, &soc_hw_version_major, +@@ -1240,6 +1255,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev, + ab->hw_rev = ATH11K_HW_QCN9074_HW10; + break; + case WCN6855_DEVICE_ID: ++ ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD; + ath11k_pci_read_hw_version(ab, &soc_hw_version_major, + &soc_hw_version_minor); + switch (soc_hw_version_major) { +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index b5e34d670715e..e4a65513a1bfd 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -1770,7 +1770,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) + chunk->vaddr = dma_alloc_coherent(ab->dev, + chunk->size, + &chunk->paddr, +- GFP_KERNEL); ++ GFP_KERNEL | __GFP_NOWARN); + if (!chunk->vaddr) { + if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) { + ath11k_dbg(ab, ATH11K_DBG_QMI, +@@ -2707,8 +2707,10 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + list_del(&event->list); + spin_unlock(&qmi->event_lock); + +- if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)) ++ if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)) { ++ kfree(event); + return; ++ } + + switch (event->type) { + case ATH11K_QMI_EVENT_SERVER_ARRIVE: +diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c +index e1a1df169034b..f793324ad0b73 100644 +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -198,7 +198,7 @@ static void ath11k_copy_regd(struct ieee80211_regdomain *regd_orig, + sizeof(struct ieee80211_reg_rule)); + } + +-int ath11k_regd_update(struct ath11k *ar, bool init) ++int ath11k_regd_update(struct ath11k *ar) + { + struct ieee80211_regdomain *regd, *regd_copy = NULL; + int ret, regd_len, pdev_id; +@@ -209,7 +209,10 @@ int ath11k_regd_update(struct ath11k *ar, bool init) + + spin_lock_bh(&ab->base_lock); + +- if (init) { ++ /* Prefer the latest regd update over default if it's available */ ++ if (ab->new_regd[pdev_id]) { ++ regd = ab->new_regd[pdev_id]; ++ } else { + /* Apply the regd received during init through + * WMI_REG_CHAN_LIST_CC event. In case of failure to + * receive the regd, initialize with a default world +@@ -222,8 +225,6 @@ int ath11k_regd_update(struct ath11k *ar, bool init) + "failed to receive default regd during init\n"); + regd = (struct ieee80211_regdomain *)&ath11k_world_regd; + } +- } else { +- regd = ab->new_regd[pdev_id]; + } + + if (!regd) { +@@ -458,6 +459,9 @@ ath11k_reg_adjust_bw(u16 start_freq, u16 end_freq, u16 max_bw) + { + u16 bw; + ++ if (end_freq <= start_freq) ++ return 0; ++ + bw = end_freq - start_freq; + bw = min_t(u16, bw, max_bw); + +@@ -465,8 +469,10 @@ ath11k_reg_adjust_bw(u16 start_freq, u16 end_freq, u16 max_bw) + bw = 80; + else if (bw >= 40 && bw < 80) + bw = 40; +- else if (bw < 40) ++ else if (bw >= 20 && bw < 40) + bw = 20; ++ else ++ bw = 0; + + return bw; + } +@@ -490,73 +496,77 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab, + struct cur_reg_rule *reg_rule, + u8 *rule_idx, u32 flags, u16 max_bw) + { ++ u32 start_freq; + u32 end_freq; + u16 bw; + u8 i; + + i = *rule_idx; + ++ /* there might be situations when even the input rule must be dropped */ ++ i--; ++ ++ /* frequencies below weather radar */ + bw = ath11k_reg_adjust_bw(reg_rule->start_freq, + ETSI_WEATHER_RADAR_BAND_LOW, max_bw); ++ if (bw > 0) { ++ i++; + +- ath11k_reg_update_rule(regd->reg_rules + i, reg_rule->start_freq, +- ETSI_WEATHER_RADAR_BAND_LOW, bw, +- reg_rule->ant_gain, reg_rule->reg_power, +- flags); ++ ath11k_reg_update_rule(regd->reg_rules + i, ++ reg_rule->start_freq, ++ ETSI_WEATHER_RADAR_BAND_LOW, bw, ++ reg_rule->ant_gain, reg_rule->reg_power, ++ flags); + +- ath11k_dbg(ab, ATH11K_DBG_REG, +- "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", +- i + 1, reg_rule->start_freq, ETSI_WEATHER_RADAR_BAND_LOW, +- bw, reg_rule->ant_gain, reg_rule->reg_power, +- regd->reg_rules[i].dfs_cac_ms, +- flags); +- +- if (reg_rule->end_freq > ETSI_WEATHER_RADAR_BAND_HIGH) +- end_freq = ETSI_WEATHER_RADAR_BAND_HIGH; +- else +- end_freq = reg_rule->end_freq; ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", ++ i + 1, reg_rule->start_freq, ++ ETSI_WEATHER_RADAR_BAND_LOW, bw, reg_rule->ant_gain, ++ reg_rule->reg_power, regd->reg_rules[i].dfs_cac_ms, ++ flags); ++ } + +- bw = ath11k_reg_adjust_bw(ETSI_WEATHER_RADAR_BAND_LOW, end_freq, +- max_bw); ++ /* weather radar frequencies */ ++ start_freq = max_t(u32, reg_rule->start_freq, ++ ETSI_WEATHER_RADAR_BAND_LOW); ++ end_freq = min_t(u32, reg_rule->end_freq, ETSI_WEATHER_RADAR_BAND_HIGH); + +- i++; ++ bw = ath11k_reg_adjust_bw(start_freq, end_freq, max_bw); ++ if (bw > 0) { ++ i++; + +- ath11k_reg_update_rule(regd->reg_rules + i, +- ETSI_WEATHER_RADAR_BAND_LOW, end_freq, bw, +- reg_rule->ant_gain, reg_rule->reg_power, +- flags); ++ ath11k_reg_update_rule(regd->reg_rules + i, start_freq, ++ end_freq, bw, reg_rule->ant_gain, ++ reg_rule->reg_power, flags); + +- regd->reg_rules[i].dfs_cac_ms = ETSI_WEATHER_RADAR_BAND_CAC_TIMEOUT; ++ regd->reg_rules[i].dfs_cac_ms = ETSI_WEATHER_RADAR_BAND_CAC_TIMEOUT; + +- ath11k_dbg(ab, ATH11K_DBG_REG, +- "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", +- i + 1, ETSI_WEATHER_RADAR_BAND_LOW, end_freq, +- bw, reg_rule->ant_gain, reg_rule->reg_power, +- regd->reg_rules[i].dfs_cac_ms, +- flags); +- +- if (end_freq == reg_rule->end_freq) { +- regd->n_reg_rules--; +- *rule_idx = i; +- return; ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", ++ i + 1, start_freq, end_freq, bw, ++ reg_rule->ant_gain, reg_rule->reg_power, ++ regd->reg_rules[i].dfs_cac_ms, flags); + } + ++ /* frequencies above weather radar */ + bw = ath11k_reg_adjust_bw(ETSI_WEATHER_RADAR_BAND_HIGH, + reg_rule->end_freq, max_bw); ++ if (bw > 0) { ++ i++; + +- i++; +- +- ath11k_reg_update_rule(regd->reg_rules + i, ETSI_WEATHER_RADAR_BAND_HIGH, +- reg_rule->end_freq, bw, +- reg_rule->ant_gain, reg_rule->reg_power, +- flags); ++ ath11k_reg_update_rule(regd->reg_rules + i, ++ ETSI_WEATHER_RADAR_BAND_HIGH, ++ reg_rule->end_freq, bw, ++ reg_rule->ant_gain, reg_rule->reg_power, ++ flags); + +- ath11k_dbg(ab, ATH11K_DBG_REG, +- "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", +- i + 1, ETSI_WEATHER_RADAR_BAND_HIGH, reg_rule->end_freq, +- bw, reg_rule->ant_gain, reg_rule->reg_power, +- regd->reg_rules[i].dfs_cac_ms, +- flags); ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", ++ i + 1, ETSI_WEATHER_RADAR_BAND_HIGH, ++ reg_rule->end_freq, bw, reg_rule->ant_gain, ++ reg_rule->reg_power, regd->reg_rules[i].dfs_cac_ms, ++ flags); ++ } + + *rule_idx = i; + } +@@ -683,7 +693,7 @@ void ath11k_regd_update_work(struct work_struct *work) + regd_update_work); + int ret; + +- ret = ath11k_regd_update(ar, false); ++ ret = ath11k_regd_update(ar); + if (ret) { + /* Firmware has already moved to the new regd. We need + * to maintain channel consistency across FW, Host driver +diff --git a/drivers/net/wireless/ath/ath11k/reg.h b/drivers/net/wireless/ath/ath11k/reg.h +index 65d56d44796f6..5fb9dc03a74e8 100644 +--- a/drivers/net/wireless/ath/ath11k/reg.h ++++ b/drivers/net/wireless/ath/ath11k/reg.h +@@ -31,6 +31,6 @@ void ath11k_regd_update_work(struct work_struct *work); + struct ieee80211_regdomain * + ath11k_reg_build_regd(struct ath11k_base *ab, + struct cur_regulatory_info *reg_info, bool intersect); +-int ath11k_regd_update(struct ath11k *ar, bool init); ++int ath11k_regd_update(struct ath11k *ar); + int ath11k_reg_update_chan_list(struct ath11k *ar); + #endif +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 6c253eae9d069..b11070cf159cc 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -1339,6 +1339,7 @@ int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar, + WMI_TAG_PDEV_BSS_CHAN_INFO_REQUEST) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + cmd->req_type = type; ++ cmd->pdev_id = ar->pdev->pdev_id; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "WMI bss chan info req type %d\n", type); +@@ -1670,7 +1671,8 @@ int ath11k_wmi_vdev_install_key(struct ath11k *ar, + tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | + FIELD_PREP(WMI_TLV_LEN, key_len_aligned); +- memcpy(tlv->value, (u8 *)arg->key_data, key_len_aligned); ++ if (arg->key_data) ++ memcpy(tlv->value, (u8 *)arg->key_data, key_len_aligned); + + ret = ath11k_wmi_cmd_send(wmi, skb, WMI_VDEV_INSTALL_KEY_CMDID); + if (ret) { +@@ -2050,7 +2052,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, + void *ptr; + int i, ret, len; + u32 *tmp_ptr; +- u8 extraie_len_with_pad = 0; ++ u16 extraie_len_with_pad = 0; + struct hint_short_ssid *s_ssid = NULL; + struct hint_bssid *hint_bssid = NULL; + +@@ -2069,7 +2071,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, + len += sizeof(*bssid) * params->num_bssid; + + len += TLV_HDR_SIZE; +- if (params->extraie.len) ++ if (params->extraie.len && params->extraie.len <= 0xFFFF) + extraie_len_with_pad = + roundup(params->extraie.len, sizeof(u32)); + len += extraie_len_with_pad; +@@ -2176,7 +2178,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, + FIELD_PREP(WMI_TLV_LEN, len); + ptr += TLV_HDR_SIZE; + +- if (params->extraie.len) ++ if (extraie_len_with_pad) + memcpy(ptr, params->extraie.ptr, + params->extraie.len); + +@@ -5792,6 +5794,17 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk + + pdev_idx = reg_info->phy_id; + ++ /* Avoid default reg rule updates sent during FW recovery if ++ * it is already available ++ */ ++ spin_lock(&ab->base_lock); ++ if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) && ++ ab->default_regd[pdev_idx]) { ++ spin_unlock(&ab->base_lock); ++ goto mem_free; ++ } ++ spin_unlock(&ab->base_lock); ++ + if (pdev_idx >= ab->num_radios) { + /* Process the event for phy0 only if single_pdev_only + * is true. If pdev_idx is valid but not 0, discard the +@@ -5829,10 +5842,10 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk + } + + spin_lock(&ab->base_lock); +- if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { +- /* Once mac is registered, ar is valid and all CC events from +- * fw is considered to be received due to user requests +- * currently. ++ if (ab->default_regd[pdev_idx]) { ++ /* The initial rules from FW after WMI Init is to build ++ * the default regd. From then on, any rules updated for ++ * the pdev could be due to user reg changes. + * Free previously built regd before assigning the newly + * generated regd to ar. NULL pointer handling will be + * taken care by kfree itself. +@@ -5840,15 +5853,11 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk + ar = ab->pdevs[pdev_idx].ar; + kfree(ab->new_regd[pdev_idx]); + ab->new_regd[pdev_idx] = regd; +- ieee80211_queue_work(ar->hw, &ar->regd_update_work); ++ queue_work(ab->workqueue, &ar->regd_update_work); + } else { +- /* Multiple events for the same *ar is not expected. But we +- * can still clear any previously stored default_regd if we +- * are receiving this event for the same radio by mistake. +- * NULL pointer handling will be taken care by kfree itself. ++ /* This regd would be applied during mac registration and is ++ * held constant throughout for regd intersection purpose + */ +- kfree(ab->default_regd[pdev_idx]); +- /* This regd would be applied during mac registration */ + ab->default_regd[pdev_idx] = regd; + } + ab->dfs_region = reg_info->dfs_region; +@@ -6119,8 +6128,10 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) + if (rx_ev.status & WMI_RX_STATUS_ERR_MIC) + status->flag |= RX_FLAG_MMIC_ERROR; + +- if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ) { ++ if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ && ++ rx_ev.chan_freq <= ATH11K_MAX_6G_FREQ) { + status->band = NL80211_BAND_6GHZ; ++ status->freq = rx_ev.chan_freq; + } else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) { + status->band = NL80211_BAND_2GHZ; + } else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH11K_MAX_5G_CHAN) { +@@ -6141,8 +6152,10 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb) + + sband = &ar->mac.sbands[status->band]; + +- status->freq = ieee80211_channel_to_frequency(rx_ev.channel, +- status->band); ++ if (status->band != NL80211_BAND_6GHZ) ++ status->freq = ieee80211_channel_to_frequency(rx_ev.channel, ++ status->band); ++ + status->signal = rx_ev.snr + ATH11K_DEFAULT_NOISE_FLOOR; + status->rate_idx = ath11k_mac_bitrate_to_idx(sband, rx_ev.rate / 100); + +@@ -6301,6 +6314,8 @@ static void ath11k_scan_event(struct ath11k_base *ab, struct sk_buff *skb) + ath11k_wmi_event_scan_start_failed(ar); + break; + case WMI_SCAN_EVENT_DEQUEUED: ++ __ath11k_mac_scan_finish(ar); ++ break; + case WMI_SCAN_EVENT_PREEMPTED: + case WMI_SCAN_EVENT_RESTARTED: + case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT: +diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h +index d35c47e0b19d4..0b7d337b36930 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2960,6 +2960,7 @@ struct wmi_pdev_bss_chan_info_req_cmd { + u32 tlv_header; + /* ref wmi_bss_chan_info_req_type */ + u32 req_type; ++ u32 pdev_id; + } __packed; + + struct wmi_ap_ps_peer_cmd { +@@ -4056,7 +4057,6 @@ struct wmi_vdev_stopped_event { + } __packed; + + struct wmi_pdev_bss_chan_info_event { +- u32 pdev_id; + u32 freq; /* Units in MHz */ + u32 noise_floor; /* units are dBm */ + /* rx clear - how often the channel was unused */ +@@ -4074,6 +4074,7 @@ struct wmi_pdev_bss_chan_info_event { + /*rx_cycle cnt for my bss in 64bits format */ + u32 rx_bss_cycle_count_low; + u32 rx_bss_cycle_count_high; ++ u32 pdev_id; + } __packed; + + #define WMI_VDEV_INSTALL_KEY_COMPL_STATUS_SUCCESS 0 +diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c +index 5372e948e761d..aba70f35e574b 100644 +--- a/drivers/net/wireless/ath/ath6kl/usb.c ++++ b/drivers/net/wireless/ath/ath6kl/usb.c +@@ -340,6 +340,11 @@ static int ath6kl_usb_setup_pipe_resources(struct ath6kl_usb *ar_usb) + le16_to_cpu(endpoint->wMaxPacketSize), + endpoint->bInterval); + } ++ ++ /* Ignore broken descriptors. */ ++ if (usb_endpoint_maxp(endpoint) == 0) ++ continue; ++ + urbcount = 0; + + pipe_num = +@@ -907,7 +912,7 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, + req, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, +- size, 2 * HZ); ++ size, 2000); + + if (ret < 0) { + ath6kl_warn("Failed to read usb control message: %d\n", ret); +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 860da13bfb6ac..f06eec99de688 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -590,6 +590,13 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, + return; + } + ++ if (pkt_len > 2 * MAX_RX_BUF_SIZE) { ++ dev_err(&hif_dev->udev->dev, ++ "ath9k_htc: invalid pkt_len (%x)\n", pkt_len); ++ RX_STAT_INC(skb_dropped); ++ return; ++ } ++ + pad_len = 4 - (pkt_len & 0x3); + if (pad_len == 4) + pad_len = 0; +diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h +index 0a1634238e673..6b45e63fae4ba 100644 +--- a/drivers/net/wireless/ath/ath9k/htc.h ++++ b/drivers/net/wireless/ath/ath9k/htc.h +@@ -281,6 +281,7 @@ struct ath9k_htc_rxbuf { + struct ath9k_htc_rx { + struct list_head rxbuf; + spinlock_t rxbuflock; ++ bool initialized; + }; + + #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ +@@ -305,6 +306,7 @@ struct ath9k_htc_tx { + DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); + struct timer_list cleanup_timer; + spinlock_t tx_lock; ++ bool initialized; + }; + + struct ath9k_htc_tx_ctl { +diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +index 8e69e8989f6d3..6a850a0bfa8ad 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c ++++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +@@ -813,6 +813,11 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv) + skb_queue_head_init(&priv->tx.data_vi_queue); + skb_queue_head_init(&priv->tx.data_vo_queue); + skb_queue_head_init(&priv->tx.tx_failed); ++ ++ /* Allow ath9k_wmi_event_tasklet(WMI_TXSTATUS_EVENTID) to operate. */ ++ smp_wmb(); ++ priv->tx.initialized = true; ++ + return 0; + } + +@@ -1130,6 +1135,10 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, + struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; + unsigned long flags; + ++ /* Check if ath9k_rx_init() completed. */ ++ if (!data_race(priv->rx.initialized)) ++ goto err; ++ + spin_lock_irqsave(&priv->rx.rxbuflock, flags); + list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { + if (!tmp_buf->in_process) { +@@ -1185,6 +1194,10 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv) + list_add_tail(&rxbuf->list, &priv->rx.rxbuf); + } + ++ /* Allow ath9k_htc_rxep() to operate. */ ++ smp_wmb(); ++ priv->rx.initialized = true; ++ + return 0; + + err: +diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c +index 139831539da37..98090e40e1cf4 100644 +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -533,8 +533,10 @@ irqreturn_t ath_isr(int irq, void *dev) + ath9k_debug_sync_cause(sc, sync_cause); + status &= ah->imask; /* discard unasked-for bits */ + +- if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) ++ if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) { ++ ath9k_hw_kill_interrupts(sc->sc_ah); + return IRQ_HANDLED; ++ } + + /* + * If there are no status bits set, then this interrupt was not +diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c +index fe29ad4b9023c..f315c54bd3ac0 100644 +--- a/drivers/net/wireless/ath/ath9k/wmi.c ++++ b/drivers/net/wireless/ath/ath9k/wmi.c +@@ -169,6 +169,10 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t) + &wmi->drv_priv->fatal_work); + break; + case WMI_TXSTATUS_EVENTID: ++ /* Check if ath9k_tx_init() completed. */ ++ if (!data_race(priv->tx.initialized)) ++ break; ++ + spin_lock_bh(&priv->tx.tx_lock); + if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { + spin_unlock_bh(&priv->tx.tx_lock); +diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c +index 80390495ea250..75cb53a3ec15e 100644 +--- a/drivers/net/wireless/ath/dfs_pattern_detector.c ++++ b/drivers/net/wireless/ath/dfs_pattern_detector.c +@@ -183,10 +183,12 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd, + if (cd == NULL) + return; + list_del(&cd->head); +- for (i = 0; i < dpd->num_radar_types; i++) { +- struct pri_detector *de = cd->detectors[i]; +- if (de != NULL) +- de->exit(de); ++ if (cd->detectors) { ++ for (i = 0; i < dpd->num_radar_types; i++) { ++ struct pri_detector *de = cd->detectors[i]; ++ if (de != NULL) ++ de->exit(de); ++ } + } + kfree(cd->detectors); + kfree(cd); +diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c +index 8e1dbfda65386..e1a35c2eadb6c 100644 +--- a/drivers/net/wireless/ath/wcn36xx/dxe.c ++++ b/drivers/net/wireless/ath/wcn36xx/dxe.c +@@ -272,6 +272,21 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) + return 0; + } + ++static void wcn36xx_dxe_disable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) ++{ ++ int reg_data = 0; ++ ++ wcn36xx_dxe_read_register(wcn, ++ WCN36XX_DXE_INT_MASK_REG, ++ ®_data); ++ ++ reg_data &= ~wcn_ch; ++ ++ wcn36xx_dxe_write_register(wcn, ++ WCN36XX_DXE_INT_MASK_REG, ++ (int)reg_data); ++} ++ + static int wcn36xx_dxe_fill_skb(struct device *dev, + struct wcn36xx_dxe_ctl *ctl, + gfp_t gfp) +@@ -403,8 +418,21 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) + dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, + ctl->skb->len, DMA_TO_DEVICE); + info = IEEE80211_SKB_CB(ctl->skb); +- if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { +- /* Keep frame until TX status comes */ ++ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { ++ if (info->flags & IEEE80211_TX_CTL_NO_ACK) { ++ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ++ ieee80211_tx_status_irqsafe(wcn->hw, ctl->skb); ++ } else { ++ /* Wait for the TX ack indication or timeout... */ ++ spin_lock(&wcn->dxe_lock); ++ if (WARN_ON(wcn->tx_ack_skb)) ++ ieee80211_free_txskb(wcn->hw, wcn->tx_ack_skb); ++ wcn->tx_ack_skb = ctl->skb; /* Tracking ref */ ++ mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10); ++ spin_unlock(&wcn->dxe_lock); ++ } ++ /* do not free, ownership transferred to mac80211 status cb */ ++ } else { + ieee80211_free_txskb(wcn->hw, ctl->skb); + } + +@@ -426,7 +454,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) + { + struct wcn36xx *wcn = (struct wcn36xx *)dev; + int int_src, int_reason; +- bool transmitted = false; + + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); + +@@ -466,7 +493,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) + if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | + WCN36XX_CH_STAT_INT_ED_MASK)) { + reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); +- transmitted = true; + } + } + +@@ -479,7 +505,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) + WCN36XX_DXE_0_INT_CLR, + WCN36XX_INT_MASK_CHAN_TX_L); + +- + if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ERR_CLR, +@@ -507,25 +532,8 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) + if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | + WCN36XX_CH_STAT_INT_ED_MASK)) { + reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); +- transmitted = true; +- } +- } +- +- spin_lock(&wcn->dxe_lock); +- if (wcn->tx_ack_skb && transmitted) { +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(wcn->tx_ack_skb); +- +- /* TX complete, no need to wait for 802.11 ack indication */ +- if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS && +- info->flags & IEEE80211_TX_CTL_NO_ACK) { +- info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; +- del_timer(&wcn->tx_ack_timer); +- ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); +- wcn->tx_ack_skb = NULL; +- ieee80211_wake_queues(wcn->hw); + } + } +- spin_unlock(&wcn->dxe_lock); + + return IRQ_HANDLED; + } +@@ -613,6 +621,10 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, + dxe = ctl->desc; + + while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) { ++ /* do not read until we own DMA descriptor */ ++ dma_rmb(); ++ ++ /* read/modify DMA descriptor */ + skb = ctl->skb; + dma_addr = dxe->dst_addr_l; + ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl, GFP_ATOMIC); +@@ -623,9 +635,15 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, + dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE, + DMA_FROM_DEVICE); + wcn36xx_rx_skb(wcn, skb); +- } /* else keep old skb not submitted and use it for rx DMA */ ++ } ++ /* else keep old skb not submitted and reuse it for rx DMA ++ * (dropping the packet that it contained) ++ */ + ++ /* flush descriptor changes before re-marking as valid */ ++ dma_wmb(); + dxe->ctrl = ctrl; ++ + ctl = ctl->next; + dxe = ctl->desc; + } +@@ -866,7 +884,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) + WCN36XX_DXE_WQ_TX_L); + + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); +- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); + + /***************************************/ + /* Init descriptors for TX HIGH channel */ +@@ -890,9 +907,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) + + wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); + +- /* Enable channel interrupts */ +- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); +- + /***************************************/ + /* Init descriptors for RX LOW channel */ + /***************************************/ +@@ -902,7 +916,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) + goto out_err_rxl_ch; + } + +- + /* For RX we need to preallocated buffers */ + wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); + +@@ -925,9 +938,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) + WCN36XX_DXE_REG_CTL_RX_L, + WCN36XX_DXE_CH_DEFAULT_CTL_RX_L); + +- /* Enable channel interrupts */ +- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); +- + /***************************************/ + /* Init descriptors for RX HIGH channel */ + /***************************************/ +@@ -959,15 +969,18 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) + WCN36XX_DXE_REG_CTL_RX_H, + WCN36XX_DXE_CH_DEFAULT_CTL_RX_H); + +- /* Enable channel interrupts */ +- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); +- + ret = wcn36xx_dxe_request_irqs(wcn); + if (ret < 0) + goto out_err_irq; + + timer_setup(&wcn->tx_ack_timer, wcn36xx_dxe_tx_timer, 0); + ++ /* Enable channel interrupts */ ++ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); ++ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); ++ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); ++ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); ++ + return 0; + + out_err_irq: +@@ -984,6 +997,14 @@ out_err_txh_ch: + + void wcn36xx_dxe_deinit(struct wcn36xx *wcn) + { ++ int reg_data = 0; ++ ++ /* Disable channel interrupts */ ++ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); ++ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); ++ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); ++ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); ++ + free_irq(wcn->tx_irq, wcn); + free_irq(wcn->rx_irq, wcn); + del_timer(&wcn->tx_ack_timer); +@@ -993,6 +1014,15 @@ void wcn36xx_dxe_deinit(struct wcn36xx *wcn) + wcn->tx_ack_skb = NULL; + } + ++ /* Put the DXE block into reset before freeing memory */ ++ reg_data = WCN36XX_DXE_REG_RESET; ++ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data); ++ + wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch); + wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch); ++ ++ wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_l_ch); ++ wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_h_ch); ++ wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_l_ch); ++ wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_h_ch); + } +diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h +index 455143c4164ee..de3bca043c2b3 100644 +--- a/drivers/net/wireless/ath/wcn36xx/hal.h ++++ b/drivers/net/wireless/ath/wcn36xx/hal.h +@@ -359,6 +359,8 @@ enum wcn36xx_hal_host_msg_type { + WCN36XX_HAL_START_SCAN_OFFLOAD_RSP = 205, + WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ = 206, + WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP = 207, ++ WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ = 208, ++ WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP = 209, + WCN36XX_HAL_SCAN_OFFLOAD_IND = 210, + + WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233, +@@ -1353,6 +1355,36 @@ struct wcn36xx_hal_stop_scan_offload_rsp_msg { + u32 status; + } __packed; + ++#define WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK 0x000000ff ++#define WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK 0x0000ff00 ++#define WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK 0x00ff0000 ++#define WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK 0xff000000 ++#define WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK 0x000000ff ++#define WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE BIT(7) ++#define WCN36XX_HAL_CHAN_INFO_FLAG_DFS BIT(10) ++#define WCN36XX_HAL_CHAN_INFO_FLAG_HT BIT(11) ++#define WCN36XX_HAL_CHAN_INFO_FLAG_VHT BIT(12) ++#define WCN36XX_HAL_CHAN_INFO_PHY_11A 0 ++#define WCN36XX_HAL_CHAN_INFO_PHY_11BG 1 ++#define WCN36XX_HAL_DEFAULT_ANT_GAIN 6 ++#define WCN36XX_HAL_DEFAULT_MIN_POWER 6 ++ ++struct wcn36xx_hal_channel_param { ++ u32 mhz; ++ u32 band_center_freq1; ++ u32 band_center_freq2; ++ u32 channel_info; ++ u32 reg_info_1; ++ u32 reg_info_2; ++} __packed; ++ ++struct wcn36xx_hal_update_channel_list_req_msg { ++ struct wcn36xx_hal_msg_header header; ++ ++ u8 num_channel; ++ struct wcn36xx_hal_channel_param channels[80]; ++} __packed; ++ + enum wcn36xx_hal_rate_index { + HW_RATE_INDEX_1MBPS = 0x82, + HW_RATE_INDEX_2MBPS = 0x84, +diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c +index ec913ec991f3f..cf9e1396bd046 100644 +--- a/drivers/net/wireless/ath/wcn36xx/main.c ++++ b/drivers/net/wireless/ath/wcn36xx/main.c +@@ -135,7 +135,9 @@ static struct ieee80211_supported_band wcn_band_2ghz = { + .cap = IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40 | +- IEEE80211_HT_CAP_LSIG_TXOP_PROT, ++ IEEE80211_HT_CAP_LSIG_TXOP_PROT | ++ IEEE80211_HT_CAP_SGI_40 | ++ IEEE80211_HT_CAP_SUP_WIDTH_20_40, + .ht_supported = true, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, +@@ -398,6 +400,7 @@ static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch) + static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) + { + struct wcn36xx *wcn = hw->priv; ++ int ret; + + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); + +@@ -413,17 +416,31 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) + * want to receive/transmit regular data packets, then + * simply stop the scan session and exit PS mode. + */ +- wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, +- wcn->sw_scan_vif); +- wcn->sw_scan_channel = 0; ++ if (wcn->sw_scan_channel) ++ wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel); ++ if (wcn->sw_scan_init) { ++ wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, ++ wcn->sw_scan_vif); ++ } + } else if (wcn->sw_scan) { + /* A scan is ongoing, do not change the operating + * channel, but start a scan session on the channel. + */ +- wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN, +- wcn->sw_scan_vif); ++ if (wcn->sw_scan_channel) ++ wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel); ++ if (!wcn->sw_scan_init) { ++ /* This can fail if we are unable to notify the ++ * operating channel. ++ */ ++ ret = wcn36xx_smd_init_scan(wcn, ++ HAL_SYS_MODE_SCAN, ++ wcn->sw_scan_vif); ++ if (ret) { ++ mutex_unlock(&wcn->conf_mutex); ++ return -EIO; ++ } ++ } + wcn36xx_smd_start_scan(wcn, ch); +- wcn->sw_scan_channel = ch; + } else { + wcn36xx_change_opchannel(wcn, ch); + } +@@ -569,12 +586,14 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { + sta_priv->is_data_encrypted = true; + /* Reconfigure bss with encrypt_type */ +- if (NL80211_IFTYPE_STATION == vif->type) ++ if (NL80211_IFTYPE_STATION == vif->type) { + wcn36xx_smd_config_bss(wcn, + vif, + sta, + sta->addr, + true); ++ wcn36xx_smd_config_sta(wcn, vif, sta); ++ } + + wcn36xx_smd_set_stakey(wcn, + vif_priv->encrypt_type, +@@ -604,15 +623,6 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + } + } + } +- /* FIXME: Only enable bmps support when encryption is enabled. +- * For any reasons, when connected to open/no-security BSS, +- * the wcn36xx controller in bmps mode does not forward +- * 'wake-up' beacons despite AP sends DTIM with station AID. +- * It could be due to a firmware issue or to the way driver +- * configure the station. +- */ +- if (vif->type == NL80211_IFTYPE_STATION) +- vif_priv->allow_bmps = true; + break; + case DISABLE_KEY: + if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) { +@@ -676,6 +686,7 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw, + + mutex_unlock(&wcn->scan_lock); + ++ wcn36xx_smd_update_channel_list(wcn, &hw_req->req); + return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req); + } + +@@ -717,7 +728,12 @@ static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, + struct wcn36xx *wcn = hw->priv; + + /* ensure that any scan session is finished */ +- wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, wcn->sw_scan_vif); ++ if (wcn->sw_scan_channel) ++ wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel); ++ if (wcn->sw_scan_init) { ++ wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, ++ wcn->sw_scan_vif); ++ } + wcn->sw_scan = false; + wcn->sw_scan_opchannel = 0; + } +@@ -913,7 +929,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, + vif->addr, + bss_conf->aid); + vif_priv->sta_assoc = false; +- vif_priv->allow_bmps = false; + wcn36xx_smd_set_link_st(wcn, + bss_conf->bssid, + vif->addr, +@@ -1123,6 +1138,13 @@ static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) + goto out; + ret = wcn36xx_smd_wlan_host_suspend_ind(wcn); + } ++ ++ /* Disable IRQ, we don't want to handle any packet before mac80211 is ++ * resumed and ready to receive packets. ++ */ ++ disable_irq(wcn->tx_irq); ++ disable_irq(wcn->rx_irq); ++ + out: + mutex_unlock(&wcn->conf_mutex); + return ret; +@@ -1145,6 +1167,10 @@ static int wcn36xx_resume(struct ieee80211_hw *hw) + wcn36xx_smd_ipv6_ns_offload(wcn, vif, false); + wcn36xx_smd_arp_offload(wcn, vif, false); + } ++ ++ enable_irq(wcn->tx_irq); ++ enable_irq(wcn->rx_irq); ++ + mutex_unlock(&wcn->conf_mutex); + + return 0; +@@ -1338,7 +1364,6 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) + ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); + ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS); + ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS); +- ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR); + + wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | +diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c +index 2d0780fefd477..2936aaf532738 100644 +--- a/drivers/net/wireless/ath/wcn36xx/pmc.c ++++ b/drivers/net/wireless/ath/wcn36xx/pmc.c +@@ -23,10 +23,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn, + { + int ret = 0; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); +- +- if (!vif_priv->allow_bmps) +- return -ENOTSUPP; +- ++ /* TODO: Make sure the TX chain clean */ + ret = wcn36xx_smd_enter_bmps(wcn, vif); + if (!ret) { + wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n"); +diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c +index 57fa857b290b7..c056fae1d6418 100644 +--- a/drivers/net/wireless/ath/wcn36xx/smd.c ++++ b/drivers/net/wireless/ath/wcn36xx/smd.c +@@ -16,6 +16,7 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + ++#include <linux/bitfield.h> + #include <linux/etherdevice.h> + #include <linux/firmware.h> + #include <linux/bitops.h> +@@ -720,6 +721,7 @@ int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode, + wcn36xx_err("hal_init_scan response failed err=%d\n", ret); + goto out; + } ++ wcn->sw_scan_init = true; + out: + mutex_unlock(&wcn->hal_mutex); + return ret; +@@ -750,6 +752,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel) + wcn36xx_err("hal_start_scan response failed err=%d\n", ret); + goto out; + } ++ wcn->sw_scan_channel = scan_channel; + out: + mutex_unlock(&wcn->hal_mutex); + return ret; +@@ -780,6 +783,7 @@ int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel) + wcn36xx_err("hal_end_scan response failed err=%d\n", ret); + goto out; + } ++ wcn->sw_scan_channel = 0; + out: + mutex_unlock(&wcn->hal_mutex); + return ret; +@@ -821,6 +825,7 @@ int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, + wcn36xx_err("hal_finish_scan response failed err=%d\n", ret); + goto out; + } ++ wcn->sw_scan_init = false; + out: + mutex_unlock(&wcn->hal_mutex); + return ret; +@@ -927,6 +932,86 @@ out: + return ret; + } + ++int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req) ++{ ++ struct wcn36xx_hal_update_channel_list_req_msg *msg_body; ++ int ret, i; ++ ++ msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL); ++ if (!msg_body) ++ return -ENOMEM; ++ ++ INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ); ++ ++ msg_body->num_channel = min_t(u8, req->n_channels, ARRAY_SIZE(msg_body->channels)); ++ for (i = 0; i < msg_body->num_channel; i++) { ++ struct wcn36xx_hal_channel_param *param = &msg_body->channels[i]; ++ u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER; ++ u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN; ++ ++ param->mhz = req->channels[i]->center_freq; ++ param->band_center_freq1 = req->channels[i]->center_freq; ++ param->band_center_freq2 = 0; ++ ++ if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) ++ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE; ++ ++ if (req->channels[i]->flags & IEEE80211_CHAN_RADAR) ++ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS; ++ ++ if (req->channels[i]->band == NL80211_BAND_5GHZ) { ++ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT; ++ param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT; ++ param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A; ++ } else { ++ param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG; ++ } ++ ++ if (min_power > req->channels[i]->max_power) ++ min_power = req->channels[i]->max_power; ++ ++ if (req->channels[i]->max_antenna_gain) ++ ant_gain = req->channels[i]->max_antenna_gain; ++ ++ u32p_replace_bits(¶m->reg_info_1, min_power, ++ WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK); ++ u32p_replace_bits(¶m->reg_info_1, req->channels[i]->max_power, ++ WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK); ++ u32p_replace_bits(¶m->reg_info_1, req->channels[i]->max_reg_power, ++ WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK); ++ u32p_replace_bits(¶m->reg_info_1, 0, ++ WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK); ++ u32p_replace_bits(¶m->reg_info_2, ant_gain, ++ WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK); ++ ++ wcn36xx_dbg(WCN36XX_DBG_HAL, ++ "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n", ++ __func__, param->mhz, param->channel_info, param->reg_info_1, ++ param->reg_info_2); ++ } ++ ++ mutex_lock(&wcn->hal_mutex); ++ ++ PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body)); ++ ++ ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len); ++ if (ret) { ++ wcn36xx_err("Sending hal_update_channel_list failed\n"); ++ goto out; ++ } ++ ++ ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); ++ if (ret) { ++ wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret); ++ goto out; ++ } ++ ++out: ++ kfree(msg_body); ++ mutex_unlock(&wcn->hal_mutex); ++ return ret; ++} ++ + static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len) + { + struct wcn36xx_hal_switch_channel_rsp_msg *rsp; +@@ -2594,7 +2679,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, + wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", + tmp->bss_index); + vif = wcn36xx_priv_to_vif(tmp); +- ieee80211_connection_loss(vif); ++ ieee80211_beacon_loss(vif); + } + return 0; + } +@@ -2609,7 +2694,7 @@ static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn, + wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n", + rsp->bss_index); + vif = wcn36xx_priv_to_vif(tmp); +- ieee80211_connection_loss(vif); ++ ieee80211_beacon_loss(vif); + return 0; + } + } +@@ -2623,30 +2708,52 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, + size_t len) + { + struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf; +- struct wcn36xx_vif *tmp; ++ struct wcn36xx_vif *vif_priv; ++ struct ieee80211_vif *vif; ++ struct ieee80211_bss_conf *bss_conf; + struct ieee80211_sta *sta; ++ bool found = false; + + if (len != sizeof(*rsp)) { + wcn36xx_warn("Corrupted delete sta indication\n"); + return -EIO; + } + +- wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n", +- rsp->addr2, rsp->sta_id); ++ wcn36xx_dbg(WCN36XX_DBG_HAL, ++ "delete station indication %pM index %d reason %d\n", ++ rsp->addr2, rsp->sta_id, rsp->reason_code); + +- list_for_each_entry(tmp, &wcn->vif_list, list) { ++ list_for_each_entry(vif_priv, &wcn->vif_list, list) { + rcu_read_lock(); +- sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2); +- if (sta) +- ieee80211_report_low_ack(sta, 0); ++ vif = wcn36xx_priv_to_vif(vif_priv); ++ ++ if (vif->type == NL80211_IFTYPE_STATION) { ++ /* We could call ieee80211_find_sta too, but checking ++ * bss_conf is clearer. ++ */ ++ bss_conf = &vif->bss_conf; ++ if (vif_priv->sta_assoc && ++ !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) { ++ found = true; ++ wcn36xx_dbg(WCN36XX_DBG_HAL, ++ "connection loss bss_index %d\n", ++ vif_priv->bss_index); ++ ieee80211_connection_loss(vif); ++ } ++ } else { ++ sta = ieee80211_find_sta(vif, rsp->addr2); ++ if (sta) { ++ found = true; ++ ieee80211_report_low_ack(sta, 0); ++ } ++ } ++ + rcu_read_unlock(); +- if (sta) ++ if (found) + return 0; + } + +- wcn36xx_warn("STA with addr %pM and index %d not found\n", +- rsp->addr2, +- rsp->sta_id); ++ wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2); + return -ENOENT; + } + +@@ -3060,6 +3167,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, + case WCN36XX_HAL_GTK_OFFLOAD_RSP: + case WCN36XX_HAL_GTK_OFFLOAD_GETINFO_RSP: + case WCN36XX_HAL_HOST_RESUME_RSP: ++ case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP: + memcpy(wcn->hal_buf, buf, len); + wcn->hal_rsp_len = len; + complete(&wcn->hal_rsp_compl); +diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h +index d8bded03945d4..d3774568d885e 100644 +--- a/drivers/net/wireless/ath/wcn36xx/smd.h ++++ b/drivers/net/wireless/ath/wcn36xx/smd.h +@@ -70,6 +70,7 @@ int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t cha + int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif, + struct cfg80211_scan_request *req); + int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn); ++int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req); + int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif); + int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr); + int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index); +diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c +index cab196bb38cd4..f33e7228a1010 100644 +--- a/drivers/net/wireless/ath/wcn36xx/txrx.c ++++ b/drivers/net/wireless/ath/wcn36xx/txrx.c +@@ -31,6 +31,13 @@ struct wcn36xx_rate { + enum rate_info_bw bw; + }; + ++/* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used ++ * for 11A Channels. ++ */ ++static const u8 ab_rx_ch_map[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, ++ 108, 112, 116, 120, 124, 128, 132, 136, 140, ++ 149, 153, 157, 161, 165, 144 }; ++ + static const struct wcn36xx_rate wcn36xx_rate_table[] = { + /* 11b rates */ + { 10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 }, +@@ -230,7 +237,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) + const struct wcn36xx_rate *rate; + struct ieee80211_hdr *hdr; + struct wcn36xx_rx_bd *bd; +- struct ieee80211_supported_band *sband; + u16 fc, sn; + + /* +@@ -252,8 +258,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) + fc = __le16_to_cpu(hdr->frame_control); + sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); + +- status.freq = WCN36XX_CENTER_FREQ(wcn); +- status.band = WCN36XX_BAND(wcn); + status.mactime = 10; + status.signal = -get_rssi0(bd); + status.antenna = 1; +@@ -265,18 +269,36 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) + + wcn36xx_dbg(WCN36XX_DBG_RX, "status.flags=%x\n", status.flag); + ++ if (bd->scan_learn) { ++ /* If packet originate from hardware scanning, extract the ++ * band/channel from bd descriptor. ++ */ ++ u8 hwch = (bd->reserved0 << 4) + bd->rx_ch; ++ ++ if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) { ++ status.band = NL80211_BAND_5GHZ; ++ status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1], ++ status.band); ++ } else { ++ status.band = NL80211_BAND_2GHZ; ++ status.freq = ieee80211_channel_to_frequency(hwch, status.band); ++ } ++ } else { ++ status.band = WCN36XX_BAND(wcn); ++ status.freq = WCN36XX_CENTER_FREQ(wcn); ++ } ++ + if (bd->rate_id < ARRAY_SIZE(wcn36xx_rate_table)) { + rate = &wcn36xx_rate_table[bd->rate_id]; + status.encoding = rate->encoding; + status.enc_flags = rate->encoding_flags; + status.bw = rate->bw; + status.rate_idx = rate->mcs_or_legacy_index; +- sband = wcn->hw->wiphy->bands[status.band]; + status.nss = 1; + + if (status.band == NL80211_BAND_5GHZ && + status.encoding == RX_ENC_LEGACY && +- status.rate_idx >= sband->n_bitrates) { ++ status.rate_idx >= 4) { + /* no dsss rates in 5Ghz rates table */ + status.rate_idx -= 4; + } +@@ -321,8 +343,6 @@ static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd, + bd->pdu.mpdu_header_off; + bd->pdu.mpdu_len = len; + bd->pdu.tid = tid; +- /* Use seq number generated by mac80211 */ +- bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST; + } + + static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn, +@@ -419,6 +439,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, + tid = ieee80211_get_tid(hdr); + /* TID->QID is one-to-one mapping */ + bd->queue_id = tid; ++ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS; ++ } else { ++ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS; + } + + if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT || +@@ -429,6 +452,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd, + if (ieee80211_is_any_nullfunc(hdr->frame_control)) { + /* Don't use a regular queue for null packet (no ampdu) */ + bd->queue_id = WCN36XX_TX_U_WQ_ID; ++ bd->bd_rate = WCN36XX_BD_RATE_CTRL; ++ if (ieee80211_is_qos_nullfunc(hdr->frame_control)) ++ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST; + } + + if (bcast) { +@@ -488,6 +514,8 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd, + bd->queue_id = WCN36XX_TX_U_WQ_ID; + *vif_priv = __vif_priv; + ++ bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS; ++ + wcn36xx_set_tx_pdu(bd, + ieee80211_is_data_qos(hdr->frame_control) ? + sizeof(struct ieee80211_qos_hdr) : +@@ -502,10 +530,11 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct wcn36xx_vif *vif_priv = NULL; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +- unsigned long flags; + bool is_low = ieee80211_is_data(hdr->frame_control); + bool bcast = is_broadcast_ether_addr(hdr->addr1) || + is_multicast_ether_addr(hdr->addr1); ++ bool ack_ind = (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) && ++ !(info->flags & IEEE80211_TX_CTL_NO_ACK); + struct wcn36xx_tx_bd bd; + int ret; + +@@ -521,30 +550,16 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, + + bd.dpu_rf = WCN36XX_BMU_WQ_TX; + +- if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { ++ if (unlikely(ack_ind)) { + wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n"); + +- spin_lock_irqsave(&wcn->dxe_lock, flags); +- if (wcn->tx_ack_skb) { +- spin_unlock_irqrestore(&wcn->dxe_lock, flags); +- wcn36xx_warn("tx_ack_skb already set\n"); +- return -EINVAL; +- } +- +- wcn->tx_ack_skb = skb; +- spin_unlock_irqrestore(&wcn->dxe_lock, flags); +- + /* Only one at a time is supported by fw. Stop the TX queues + * until the ack status gets back. + */ + ieee80211_stop_queues(wcn->hw); + +- /* TX watchdog if no TX irq or ack indication received */ +- mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10); +- + /* Request ack indication from the firmware */ +- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) +- bd.tx_comp = 1; ++ bd.tx_comp = 1; + } + + /* Data frames served first*/ +@@ -558,14 +573,8 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, + bd.tx_bd_sign = 0xbdbdbdbd; + + ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low); +- if (ret && (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { +- /* If the skb has not been transmitted, +- * don't keep a reference to it. +- */ +- spin_lock_irqsave(&wcn->dxe_lock, flags); +- wcn->tx_ack_skb = NULL; +- spin_unlock_irqrestore(&wcn->dxe_lock, flags); +- ++ if (unlikely(ret && ack_ind)) { ++ /* If the skb has not been transmitted, resume TX queue */ + ieee80211_wake_queues(wcn->hw); + } + +diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h +index 032216e82b2be..b54311ffde9c5 100644 +--- a/drivers/net/wireless/ath/wcn36xx/txrx.h ++++ b/drivers/net/wireless/ath/wcn36xx/txrx.h +@@ -110,7 +110,8 @@ struct wcn36xx_rx_bd { + /* 0x44 */ + u32 exp_seq_num:12; + u32 cur_seq_num:12; +- u32 fr_type_subtype:8; ++ u32 rf_band:2; ++ u32 fr_type_subtype:6; + + /* 0x48 */ + u32 msdu_size:16; +diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +index add6e527e8330..428546a6047f0 100644 +--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h ++++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +@@ -128,7 +128,6 @@ struct wcn36xx_vif { + enum wcn36xx_hal_bss_type bss_type; + + /* Power management */ +- bool allow_bmps; + enum wcn36xx_power_state pw_state; + + u8 bss_index; +@@ -247,6 +246,7 @@ struct wcn36xx { + struct cfg80211_scan_request *scan_req; + bool sw_scan; + u8 sw_scan_opchannel; ++ bool sw_scan_init; + u8 sw_scan_channel; + struct ieee80211_vif *sw_scan_vif; + struct mutex scan_lock; +diff --git a/drivers/net/wireless/broadcom/b43/phy_g.c b/drivers/net/wireless/broadcom/b43/phy_g.c +index d5a1a5c582366..ac72ca39e409b 100644 +--- a/drivers/net/wireless/broadcom/b43/phy_g.c ++++ b/drivers/net/wireless/broadcom/b43/phy_g.c +@@ -2297,7 +2297,7 @@ static u8 b43_gphy_aci_scan(struct b43_wldev *dev) + b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF); + b43_set_all_gains(dev, 3, 8, 1); + +- start = (channel - 5 > 0) ? channel - 5 : 1; ++ start = (channel > 5) ? channel - 5 : 1; + end = (channel + 5 < 14) ? channel + 5 : 13; + + for (i = start; i <= end; i++) { +diff --git a/drivers/net/wireless/broadcom/b43legacy/radio.c b/drivers/net/wireless/broadcom/b43legacy/radio.c +index 06891b4f837b9..fdf78c10a05c2 100644 +--- a/drivers/net/wireless/broadcom/b43legacy/radio.c ++++ b/drivers/net/wireless/broadcom/b43legacy/radio.c +@@ -283,7 +283,7 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev) + & 0x7FFF); + b43legacy_set_all_gains(dev, 3, 8, 1); + +- start = (channel - 5 > 0) ? channel - 5 : 1; ++ start = (channel > 5) ? channel - 5 : 1; + end = (channel + 5 < 14) ? channel + 5 : 13; + + for (i = start; i <= end; i++) { +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c +index 6d5188b78f2de..0af452dca7664 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c +@@ -75,6 +75,16 @@ static const struct dmi_system_id dmi_platform_data[] = { + }, + .driver_data = (void *)&acepc_t8_data, + }, ++ { ++ /* Cyberbook T116 rugged tablet */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"), ++ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "20170531"), ++ }, ++ /* The factory image nvram file is identical to the ACEPC T8 one */ ++ .driver_data = (void *)&acepc_t8_data, ++ }, + { + /* Match for the GPDwin which unfortunately uses somewhat + * generic dmi strings, which is why we test for 4 strings. +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index 0eb13e5df5177..d99140960a820 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -693,7 +693,7 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, + { + struct brcmf_fw_item *first = &req->items[0]; + struct brcmf_fw *fwctx; +- char *alt_path; ++ char *alt_path = NULL; + int ret; + + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); +@@ -712,7 +712,9 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, + fwctx->done = fw_cb; + + /* First try alternative board-specific path if any */ +- alt_path = brcm_alt_fw_path(first->path, fwctx->req->board_type); ++ if (fwctx->req->board_type) ++ alt_path = brcm_alt_fw_path(first->path, ++ fwctx->req->board_type); + if (alt_path) { + ret = request_firmware_nowait(THIS_MODULE, true, alt_path, + fwctx->dev, GFP_KERNEL, fwctx, +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +index 1efac0b2a94d7..9e00d1d7e1468 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* + * Copyright (C) 2017 Intel Deutschland GmbH +- * Copyright (C) 2019-2021 Intel Corporation ++ * Copyright (C) 2019-2022 Intel Corporation + */ + #include <linux/uuid.h> + #include "iwl-drv.h" +@@ -814,10 +814,11 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) + * only one using version 36, so skip this version entirely. + */ + return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 || +- IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 || +- (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 && +- ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == +- CSR_HW_REV_TYPE_7265D)); ++ (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 && ++ fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) || ++ (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 && ++ ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == ++ CSR_HW_REV_TYPE_7265D)); + } + IWL_EXPORT_SYMBOL(iwl_sar_geo_support); + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +index dde22bdc87039..069fcbc46d2ba 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +@@ -284,16 +284,19 @@ int iwl_pnvm_load(struct iwl_trans *trans, + /* First attempt to get the PNVM from BIOS */ + package = iwl_uefi_get_pnvm(trans, &len); + if (!IS_ERR_OR_NULL(package)) { +- data = kmemdup(package->data, len, GFP_KERNEL); ++ if (len >= sizeof(*package)) { ++ /* we need only the data */ ++ len -= sizeof(*package); ++ data = kmemdup(package->data, len, GFP_KERNEL); ++ } else { ++ data = NULL; ++ } + + /* free package regardless of whether kmemdup succeeded */ + kfree(package); + +- if (data) { +- /* we need only the data size */ +- len -= sizeof(*package); ++ if (data) + goto parse; +- } + } + + /* If it's not available, try from the filesystem */ +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +index c875bf35533ce..009dd4be597b0 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +@@ -86,6 +86,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, + if (len < tlv_len) { + IWL_ERR(trans, "invalid TLV len: %zd/%u\n", + len, tlv_len); ++ kfree(reduce_power_data); + reduce_power_data = ERR_PTR(-EINVAL); + goto out; + } +@@ -105,6 +106,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, + IWL_DEBUG_FW(trans, + "Couldn't allocate (more) reduce_power_data\n"); + ++ kfree(reduce_power_data); + reduce_power_data = ERR_PTR(-ENOMEM); + goto out; + } +@@ -134,6 +136,10 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, + done: + if (!size) { + IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); ++ /* Better safe than sorry, but 'reduce_power_data' should ++ * always be NULL if !size. ++ */ ++ kfree(reduce_power_data); + reduce_power_data = ERR_PTR(-ENOENT); + goto out; + } +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +index cf796403c45c0..c8dff76ac03c1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ + /* +- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation ++ * Copyright (C) 2005-2014, 2018-2022 Intel Corporation + * Copyright (C) 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2016 Intel Deutschland GmbH + */ +@@ -104,9 +104,10 @@ + /* GIO Chicken Bits (PCI Express bus link power management) */ + #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) + +-/* Doorbell NMI (since Bz) */ ++/* Doorbell - since Bz ++ * connected to UREG_DOORBELL_TO_ISR6 (lower 16 bits only) ++ */ + #define CSR_DOORBELL_VECTOR (CSR_BASE + 0x130) +-#define CSR_DOORBELL_VECTOR_NMI BIT(1) + + /* host chicken bits */ + #define CSR_HOST_CHICKEN (CSR_BASE + 0x204) +@@ -318,6 +319,7 @@ enum { + #define CSR_HW_REV_TYPE_2x00 (0x0000100) + #define CSR_HW_REV_TYPE_105 (0x0000110) + #define CSR_HW_REV_TYPE_135 (0x0000120) ++#define CSR_HW_REV_TYPE_3160 (0x0000164) + #define CSR_HW_REV_TYPE_7265D (0x0000210) + #define CSR_HW_REV_TYPE_NONE (0x00001F0) + #define CSR_HW_REV_TYPE_QNJ (0x0000360) +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +index 77124b8b235ee..524b0ad873578 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +@@ -131,6 +131,9 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) + + for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) + iwl_free_fw_img(drv, drv->fw.img + i); ++ ++ /* clear the data for the aborted load case */ ++ memset(&drv->fw, 0, sizeof(drv->fw)); + } + + static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, +@@ -1271,23 +1274,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) + const struct iwl_op_mode_ops *ops = op->ops; + struct dentry *dbgfs_dir = NULL; + struct iwl_op_mode *op_mode = NULL; ++ int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY; ++ ++ for (retry = 0; retry <= max_retry; retry++) { + + #ifdef CONFIG_IWLWIFI_DEBUGFS +- drv->dbgfs_op_mode = debugfs_create_dir(op->name, +- drv->dbgfs_drv); +- dbgfs_dir = drv->dbgfs_op_mode; ++ drv->dbgfs_op_mode = debugfs_create_dir(op->name, ++ drv->dbgfs_drv); ++ dbgfs_dir = drv->dbgfs_op_mode; + #endif + +- op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir); ++ op_mode = ops->start(drv->trans, drv->trans->cfg, ++ &drv->fw, dbgfs_dir); ++ ++ if (op_mode) ++ return op_mode; ++ ++ IWL_ERR(drv, "retry init count %d\n", retry); + + #ifdef CONFIG_IWLWIFI_DEBUGFS +- if (!op_mode) { + debugfs_remove_recursive(drv->dbgfs_op_mode); + drv->dbgfs_op_mode = NULL; +- } + #endif ++ } + +- return op_mode; ++ return NULL; + } + + static void _iwl_op_mode_stop(struct iwl_drv *drv) +@@ -1325,6 +1336,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) + int i; + bool load_module = false; + bool usniffer_images = false; ++ bool failure = true; + + fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; + fw->ucode_capa.standard_phy_calibration_size = +@@ -1585,15 +1597,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) + * else from proceeding if the module fails to load + * or hangs loading. + */ +- if (load_module) { ++ if (load_module) + request_module("%s", op->name); +-#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR +- if (err) +- IWL_ERR(drv, +- "failed to load module %s (error %d), is dynamic loading enabled?\n", +- op->name, err); +-#endif +- } ++ failure = false; + goto free; + + try_again: +@@ -1608,7 +1614,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) + out_unbind: + complete(&drv->request_firmware_complete); + device_release_driver(drv->trans->dev); ++ /* drv has just been freed by the release */ ++ failure = false; + free: ++ if (failure) ++ iwl_dealloc_ucode(drv); ++ + if (pieces) { + for (i = 0; i < ARRAY_SIZE(pieces->img); i++) + kfree(pieces->img[i].sec); +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +index b6442df0c6439..56f2fd3b94906 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +@@ -90,4 +90,7 @@ void iwl_drv_stop(struct iwl_drv *drv); + #define IWL_EXPORT_SYMBOL(sym) + #endif + ++/* max retry for init flow */ ++#define IWL_MAX_INIT_RETRY 2 ++ + #endif /* __iwl_drv_h__ */ +diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c +index 2517c4ae07ab3..5e76ab6c8ad0a 100644 +--- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c +@@ -218,7 +218,7 @@ void iwl_force_nmi(struct iwl_trans *trans) + UREG_DOORBELL_TO_ISR6_NMI_BIT); + else + iwl_write32(trans, CSR_DOORBELL_VECTOR, +- CSR_DOORBELL_VECTOR_NMI); ++ UREG_DOORBELL_TO_ISR6_NMI_BIT); + } + IWL_EXPORT_SYMBOL(iwl_force_nmi); + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index 9f706fffb5922..d3013a51a5096 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -2336,7 +2336,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) + iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, + false, 0); + ret = 1; +- mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; + goto err; + } + +@@ -2385,6 +2384,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) + } + } + ++ /* after the successful handshake, we're out of D3 */ + mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; + + /* +@@ -2455,6 +2455,9 @@ out: + */ + set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); + ++ /* regardless of what happened, we're now out of D3 */ ++ mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; ++ + return 1; + } + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +index 5dc39fbb74d67..d398a06b26567 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +@@ -5,6 +5,7 @@ + * Copyright (C) 2016-2017 Intel Deutschland GmbH + */ + #include <linux/vmalloc.h> ++#include <linux/err.h> + #include <linux/ieee80211.h> + #include <linux/netdevice.h> + +@@ -2044,7 +2045,6 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, + void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) + { + struct dentry *bcast_dir __maybe_unused; +- char buf[100]; + + spin_lock_init(&mvm->drv_stats_lock); + +@@ -2140,6 +2140,11 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) + * Create a symlink with mac80211. It will be removed when mac80211 + * exists (before the opmode exists which removes the target.) + */ +- snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent); +- debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf); ++ if (!IS_ERR(mvm->debugfs_dir)) { ++ char buf[100]; ++ ++ snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent); ++ debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, ++ buf); ++ } + } +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +index 03e5bf5cb9094..bb5fff8174435 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +@@ -499,7 +499,7 @@ iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + rcu_read_lock(); + + sta = rcu_dereference(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id]); +- if (sta->mfp) ++ if (sta->mfp && (peer->ftm.trigger_based || peer->ftm.non_trigger_based)) + FTM_PUT_FLAG(PMF); + + rcu_read_unlock(); +@@ -1054,7 +1054,7 @@ static void iwl_mvm_ftm_rtt_smoothing(struct iwl_mvm *mvm, + overshoot = IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT; + alpha = IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA; + +- rtt_avg = (alpha * rtt + (100 - alpha) * resp->rtt_avg) / 100; ++ rtt_avg = div_s64(alpha * rtt + (100 - alpha) * resp->rtt_avg, 100); + + IWL_DEBUG_INFO(mvm, + "%pM: prev rtt_avg=%lld, new rtt_avg=%lld, rtt=%lld\n", +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index 74404c96063bc..bcc032c815dcb 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -1572,7 +1572,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) + ret = iwl_mvm_sar_init(mvm); + if (ret == 0) + ret = iwl_mvm_sar_geo_init(mvm); +- else if (ret < 0) ++ if (ret < 0) + goto error; + + iwl_mvm_tas_init(mvm); +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index 3a4585222d6d4..750217393f480 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -16,6 +16,7 @@ + #include <net/ieee80211_radiotap.h> + #include <net/tcp.h> + ++#include "iwl-drv.h" + #include "iwl-op-mode.h" + #include "iwl-io.h" + #include "mvm.h" +@@ -1116,9 +1117,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) + { + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + int ret; ++ int retry, max_retry = 0; + + mutex_lock(&mvm->mutex); +- ret = __iwl_mvm_mac_start(mvm); ++ ++ /* we are starting the mac not in error flow, and restart is enabled */ ++ if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) && ++ iwlwifi_mod_params.fw_restart) { ++ max_retry = IWL_MAX_INIT_RETRY; ++ /* ++ * This will prevent mac80211 recovery flows to trigger during ++ * init failures ++ */ ++ set_bit(IWL_MVM_STATUS_STARTING, &mvm->status); ++ } ++ ++ for (retry = 0; retry <= max_retry; retry++) { ++ ret = __iwl_mvm_mac_start(mvm); ++ if (!ret) ++ break; ++ ++ IWL_ERR(mvm, "mac start retry %d\n", retry); ++ } ++ clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status); ++ + mutex_unlock(&mvm->mutex); + + return ret; +@@ -1665,6 +1687,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) + struct iwl_mvm_mc_iter_data iter_data = { + .mvm = mvm, + }; ++ int ret; + + lockdep_assert_held(&mvm->mutex); + +@@ -1674,6 +1697,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_mc_iface_iterator, &iter_data); ++ ++ /* ++ * Send a (synchronous) ech command so that we wait for the ++ * multiple asynchronous MCAST_FILTER_CMD commands sent by ++ * the interface iterator. Otherwise, we might get here over ++ * and over again (by userspace just sending a lot of these) ++ * and the CPU can send them faster than the firmware can ++ * process them. ++ * Note that the CPU is still faster - but with this we'll ++ * actually send fewer commands overall because the CPU will ++ * not schedule the work in mac80211 as frequently if it's ++ * still running when rescheduled (possibly multiple times). ++ */ ++ ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); ++ if (ret) ++ IWL_ERR(mvm, "Failed to synchronize multicast groups update\n"); + } + + static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw, +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +index f877d86b038e3..46af8dd2dc930 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -1121,6 +1121,8 @@ struct iwl_mvm { + * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running + * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA + * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) ++ * @IWL_MVM_STATUS_STARTING: starting mac, ++ * used to disable restart flow while in STARTING state + */ + enum iwl_mvm_status { + IWL_MVM_STATUS_HW_RFKILL, +@@ -1132,6 +1134,7 @@ enum iwl_mvm_status { + IWL_MVM_STATUS_FIRMWARE_RUNNING, + IWL_MVM_STATUS_NEED_FLUSH_P2P, + IWL_MVM_STATUS_IN_D3, ++ IWL_MVM_STATUS_STARTING, + }; + + /* Keep track of completed init configuration */ +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +index 77ea2d0a30916..49c32a8132a0f 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +@@ -687,6 +687,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) + int ret; + + rtnl_lock(); ++ wiphy_lock(mvm->hw->wiphy); + mutex_lock(&mvm->mutex); + + ret = iwl_run_init_mvm_ucode(mvm); +@@ -702,6 +703,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) + iwl_mvm_stop_device(mvm); + + mutex_unlock(&mvm->mutex); ++ wiphy_unlock(mvm->hw->wiphy); + rtnl_unlock(); + + if (ret < 0) +@@ -1424,6 +1426,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) + */ + if (!mvm->fw_restart && fw_error) { + iwl_fw_error_collect(&mvm->fwrt, false); ++ } else if (test_bit(IWL_MVM_STATUS_STARTING, ++ &mvm->status)) { ++ IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n"); + } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { + struct iwl_mvm_reprobe *reprobe; + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +index c12f303cf652c..efccdd3f33773 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +@@ -121,12 +121,39 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb, + struct iwl_rx_mpdu_desc *desc = (void *)pkt->data; + unsigned int headlen, fraglen, pad_len = 0; + unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ u8 mic_crc_len = u8_get_bits(desc->mac_flags1, ++ IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK) << 1; + + if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) { + len -= 2; + pad_len = 2; + } + ++ /* ++ * For non monitor interface strip the bytes the RADA might not have ++ * removed. As monitor interface cannot exist with other interfaces ++ * this removal is safe. ++ */ ++ if (mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS)) { ++ u32 pkt_flags = le32_to_cpu(pkt->len_n_flags); ++ ++ /* ++ * If RADA was not enabled then decryption was not performed so ++ * the MIC cannot be removed. ++ */ ++ if (!(pkt_flags & FH_RSCSR_RADA_EN)) { ++ if (WARN_ON(crypt_len > mic_crc_len)) ++ return -EINVAL; ++ ++ mic_crc_len -= crypt_len; ++ } ++ ++ if (WARN_ON(mic_crc_len > len)) ++ return -EINVAL; ++ ++ len -= mic_crc_len; ++ } ++ + /* If frame is small enough to fit in skb->head, pull it completely. + * If not, only pull ieee80211_hdr (including crypto if present, and + * an additional 8 bytes for SNAP/ethertype, see below) so that +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +index d78e436fa8b53..5461bf3999593 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +@@ -1924,22 +1924,19 @@ static void iwl_mvm_scan_6ghz_passive_scan(struct iwl_mvm *mvm, + } + + /* +- * 6GHz passive scan is allowed while associated in a defined time +- * interval following HW reset or resume flow ++ * 6GHz passive scan is allowed in a defined time interval following HW ++ * reset or resume flow, or while not associated and a large interval ++ * has passed since the last 6GHz passive scan. + */ +- if (vif->bss_conf.assoc && ++ if ((vif->bss_conf.assoc || ++ time_after(mvm->last_6ghz_passive_scan_jiffies + ++ (IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT * HZ), jiffies)) && + (time_before(mvm->last_reset_or_resume_time_jiffies + + (IWL_MVM_6GHZ_PASSIVE_SCAN_ASSOC_TIMEOUT * HZ), + jiffies))) { +- IWL_DEBUG_SCAN(mvm, "6GHz passive scan: associated\n"); +- return; +- } +- +- /* No need for 6GHz passive scan if not enough time elapsed */ +- if (time_after(mvm->last_6ghz_passive_scan_jiffies + +- (IWL_MVM_6GHZ_PASSIVE_SCAN_TIMEOUT * HZ), jiffies)) { +- IWL_DEBUG_SCAN(mvm, +- "6GHz passive scan: timeout did not expire\n"); ++ IWL_DEBUG_SCAN(mvm, "6GHz passive scan: %s\n", ++ vif->bss_conf.assoc ? "associated" : ++ "timeout did not expire"); + return; + } + +@@ -2490,7 +2487,7 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) + return -EIO; + } + +-#define SCAN_TIMEOUT 20000 ++#define SCAN_TIMEOUT 30000 + + void iwl_mvm_scan_timeout_wk(struct work_struct *work) + { +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +index e91f8e889df70..ab06dcda1462a 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +@@ -49,14 +49,13 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) + struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk); + + /* +- * Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit. ++ * Clear the ROC_RUNNING status bit. + * This will cause the TX path to drop offchannel transmissions. + * That would also be done by mac80211, but it is racy, in particular + * in the case that the time event actually completed in the firmware + * (which is handled in iwl_mvm_te_handle_notif). + */ + clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); +- clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); + + synchronize_net(); + +@@ -82,9 +81,19 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) + mvmvif = iwl_mvm_vif_from_mac80211(mvm->p2p_device_vif); + iwl_mvm_flush_sta(mvm, &mvmvif->bcast_sta, true); + } +- } else { ++ } ++ ++ /* ++ * Clear the ROC_AUX_RUNNING status bit. ++ * This will cause the TX path to drop offchannel transmissions. ++ * That would also be done by mac80211, but it is racy, in particular ++ * in the case that the time event actually completed in the firmware ++ * (which is handled in iwl_mvm_te_handle_notif). ++ */ ++ if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) { + /* do the same in case of hot spot 2.0 */ + iwl_mvm_flush_sta(mvm, &mvm->aux_sta, true); ++ + /* 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 */ +@@ -687,11 +696,14 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm, + iwl_mvm_te_clear_data(mvm, te_data); + spin_unlock_bh(&mvm->time_event_lock); + +- /* When session protection is supported, the te_data->id field ++ /* When session protection is used, the te_data->id field + * is reused to save session protection's configuration. ++ * For AUX ROC, HOT_SPOT_CMD is used and the te_data->id field is set ++ * to HOT_SPOT_CMD. + */ + if (fw_has_capa(&mvm->fw->ucode_capa, +- IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD)) { ++ IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD) && ++ id != HOT_SPOT_CMD) { + if (mvmvif && id < SESSION_PROTECT_CONF_MAX_ID) { + /* Session protection is still ongoing. Cancel it */ + iwl_mvm_cancel_session_protection(mvm, mvmvif, id); +@@ -1027,7 +1039,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) + iwl_mvm_p2p_roc_finished(mvm); + } else { + iwl_mvm_remove_aux_roc_te(mvm, mvmvif, +- &mvmvif->time_event_data); ++ &mvmvif->hs_time_event_data); + iwl_mvm_roc_finished(mvm); + } + +@@ -1158,15 +1170,10 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm, + cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, + mvmvif->color)), + .action = cpu_to_le32(FW_CTXT_ACTION_ADD), ++ .conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC), + .duration_tu = cpu_to_le32(MSEC_TO_TU(duration)), + }; + +- /* The time_event_data.id field is reused to save session +- * protection's configuration. +- */ +- mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC; +- cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id); +- + lockdep_assert_held(&mvm->mutex); + + spin_lock_bh(&mvm->time_event_lock); +@@ -1180,6 +1187,11 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm, + } + + iwl_mvm_te_clear_data(mvm, te_data); ++ /* ++ * The time_event_data.id field is reused to save session ++ * protection's configuration. ++ */ ++ te_data->id = le32_to_cpu(cmd.conf_id); + te_data->duration = le32_to_cpu(cmd.duration_tu); + te_data->vif = vif; + spin_unlock_bh(&mvm->time_event_lock); +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +index 0a13c2bda2eed..06fbd9ab37dfe 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +@@ -268,17 +268,18 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, + int rate_idx = -1; + u8 rate_plcp; + u32 rate_flags = 0; +- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + + /* info->control is only relevant for non HW rate control */ + if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) { ++ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); ++ + /* HT rate doesn't make sense for a non data frame */ + WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS && + !ieee80211_is_data(fc), + "Got a HT rate (flags:0x%x/mcs:%d/fc:0x%x/state:%d) for a non data frame\n", + info->control.rates[0].flags, + info->control.rates[0].idx, +- le16_to_cpu(fc), mvmsta->sta_state); ++ le16_to_cpu(fc), sta ? mvmsta->sta_state : -1); + + rate_idx = info->control.rates[0].idx; + } +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +index 4a3d2971a98b7..ec8a223f90e85 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +@@ -405,6 +405,9 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm, + + lockdep_assert_held(&mvm->mutex); + ++ if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) ++ return false; ++ + if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1) + return false; + +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +index e3996ff99bad5..3b974388d834d 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +@@ -931,9 +931,9 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { + IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_qu_b0_hr1_b0, iwl_ax101_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, +- IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, ++ IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, + IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, +- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, ++ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_qu_b0_hr_b0, iwl_ax203_name), + + /* Qu C step */ +@@ -945,7 +945,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, + IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, +- IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB, ++ IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_qu_c0_hr_b0, iwl_ax203_name), + + /* QuZ */ +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +index 8e45eb38304b2..fea89330f692c 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +@@ -2261,7 +2261,12 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) + } + } + +- if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) { ++ /* ++ * In some rare cases when the HW is in a bad state, we may ++ * get this interrupt too early, when prph_info is still NULL. ++ * So make sure that it's not NULL to prevent crashing. ++ */ ++ if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP && trans_pcie->prph_info) { + u32 sleep_notif = + le32_to_cpu(trans_pcie->prph_info->sleep_notif); + if (sleep_notif == IWL_D3_SLEEP_STATUS_SUSPEND || +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +index bf0c32a74ca47..a9c19be29e92e 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +@@ -408,8 +408,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, + /* This may fail if AMT took ownership of the device */ + if (iwl_pcie_prepare_card_hw(trans)) { + IWL_WARN(trans, "Exit HW not ready\n"); +- ret = -EIO; +- goto out; ++ return -EIO; + } + + iwl_enable_rfkill_int(trans); +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +index f252680f18e88..02da9cc8646cf 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +@@ -1273,8 +1273,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, + /* This may fail if AMT took ownership of the device */ + if (iwl_pcie_prepare_card_hw(trans)) { + IWL_WARN(trans, "Exit HW not ready\n"); +- ret = -EIO; +- goto out; ++ return -EIO; + } + + iwl_enable_rfkill_int(trans); +diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c +index 451b060693501..0f3526b0c5b00 100644 +--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c +@@ -1072,6 +1072,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, + return 0; + err_free_tfds: + dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr); ++ txq->tfds = NULL; + error: + if (txq->entries && cmd_queue) + for (i = 0; i < slots_num; i++) +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 0adae76eb8df1..0aeb1e1ec93ff 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -2336,6 +2336,15 @@ static void hw_scan_work(struct work_struct *work) + if (req->ie_len) + skb_put_data(probe, req->ie, req->ie_len); + ++ if (!ieee80211_tx_prepare_skb(hwsim->hw, ++ hwsim->hw_scan_vif, ++ probe, ++ hwsim->tmp_chan->band, ++ NULL)) { ++ kfree_skb(probe); ++ continue; ++ } ++ + local_bh_disable(); + mac80211_hwsim_tx_frame(hwsim->hw, probe, + hwsim->tmp_chan); +@@ -3641,6 +3650,10 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, + } + txi->flags |= IEEE80211_TX_STAT_ACK; + } ++ ++ if (hwsim_flags & HWSIM_TX_CTL_NO_ACK) ++ txi->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ++ + ieee80211_tx_status_irqsafe(data2->hw, skb); + return 0; + out: +diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c +index 20436a289d5cd..5d6dc1dd050d4 100644 +--- a/drivers/net/wireless/marvell/libertas/if_usb.c ++++ b/drivers/net/wireless/marvell/libertas/if_usb.c +@@ -292,6 +292,7 @@ err_add_card: + if_usb_reset_device(cardp); + dealloc: + if_usb_free(cardp); ++ kfree(cardp); + + error: + return r; +@@ -316,6 +317,7 @@ static void if_usb_disconnect(struct usb_interface *intf) + + /* Unlink and free urb */ + if_usb_free(cardp); ++ kfree(cardp); + + usb_set_intfdata(intf, NULL); + usb_put_dev(interface_to_usbdev(intf)); +diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c +index fe0a69e804d8c..75b5319d033f3 100644 +--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c ++++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c +@@ -230,6 +230,7 @@ static int if_usb_probe(struct usb_interface *intf, + + dealloc: + if_usb_free(cardp); ++ kfree(cardp); + error: + lbtf_deb_leave(LBTF_DEB_MAIN); + return -ENOMEM; +@@ -254,6 +255,7 @@ static void if_usb_disconnect(struct usb_interface *intf) + + /* Unlink and free urb */ + if_usb_free(cardp); ++ kfree(cardp); + + usb_set_intfdata(intf, NULL); + usb_put_dev(interface_to_usbdev(intf)); +diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c +index 6696bce561786..cf08a4af84d6d 100644 +--- a/drivers/net/wireless/marvell/mwifiex/11n.c ++++ b/drivers/net/wireless/marvell/mwifiex/11n.c +@@ -657,14 +657,15 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, + uint16_t del_ba_param_set; + + memset(&delba, 0, sizeof(delba)); +- delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); + +- del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); ++ del_ba_param_set = tid << DELBA_TID_POS; ++ + if (initiator) + del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; + else + del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; + ++ delba.del_ba_param_set = cpu_to_le16(del_ba_param_set); + memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); + + /* We don't wait for the response of this command */ +diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c +index 0961f4a5e415c..97f0f39364d67 100644 +--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c ++++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c +@@ -908,16 +908,20 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, + switch (type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: +- priv->bss_role = MWIFIEX_BSS_ROLE_STA; ++ priv->bss_role = MWIFIEX_BSS_ROLE_STA; ++ priv->bss_type = MWIFIEX_BSS_TYPE_STA; + break; + case NL80211_IFTYPE_P2P_CLIENT: +- priv->bss_role = MWIFIEX_BSS_ROLE_STA; ++ priv->bss_role = MWIFIEX_BSS_ROLE_STA; ++ priv->bss_type = MWIFIEX_BSS_TYPE_P2P; + break; + case NL80211_IFTYPE_P2P_GO: +- priv->bss_role = MWIFIEX_BSS_ROLE_UAP; ++ priv->bss_role = MWIFIEX_BSS_ROLE_UAP; ++ priv->bss_type = MWIFIEX_BSS_TYPE_P2P; + break; + case NL80211_IFTYPE_AP: + priv->bss_role = MWIFIEX_BSS_ROLE_UAP; ++ priv->bss_type = MWIFIEX_BSS_TYPE_UAP; + break; + default: + mwifiex_dbg(adapter, ERROR, +@@ -1229,29 +1233,15 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: ++ if (mwifiex_cfg80211_deinit_p2p(priv)) ++ return -EFAULT; ++ + switch (type) { +- case NL80211_IFTYPE_STATION: +- if (mwifiex_cfg80211_deinit_p2p(priv)) +- return -EFAULT; +- priv->adapter->curr_iface_comb.p2p_intf--; +- priv->adapter->curr_iface_comb.sta_intf++; +- dev->ieee80211_ptr->iftype = type; +- if (mwifiex_deinit_priv_params(priv)) +- return -1; +- if (mwifiex_init_new_priv_params(priv, dev, type)) +- return -1; +- if (mwifiex_sta_init_cmd(priv, false, false)) +- return -1; +- break; + case NL80211_IFTYPE_ADHOC: +- if (mwifiex_cfg80211_deinit_p2p(priv)) +- return -EFAULT; ++ case NL80211_IFTYPE_STATION: + return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, + type, params); +- break; + case NL80211_IFTYPE_AP: +- if (mwifiex_cfg80211_deinit_p2p(priv)) +- return -EFAULT; + return mwifiex_change_vif_to_ap(dev, curr_iftype, type, + params); + case NL80211_IFTYPE_UNSPECIFIED: +diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c +index c6ccce426b496..c3f5583ea70df 100644 +--- a/drivers/net/wireless/marvell/mwifiex/pcie.c ++++ b/drivers/net/wireless/marvell/mwifiex/pcie.c +@@ -17,6 +17,7 @@ + * this warranty disclaimer. + */ + ++#include <linux/iopoll.h> + #include <linux/firmware.h> + + #include "decl.h" +@@ -647,11 +648,15 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, + "max count reached while accessing sleep cookie\n"); + } + ++#define N_WAKEUP_TRIES_SHORT_INTERVAL 15 ++#define N_WAKEUP_TRIES_LONG_INTERVAL 35 ++ + /* This function wakes up the card by reading fw_status register. */ + static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) + { + struct pcie_service_card *card = adapter->card; + const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; ++ int retval; + + mwifiex_dbg(adapter, EVENT, + "event: Wakeup device...\n"); +@@ -659,11 +664,24 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) + if (reg->sleep_cookie) + mwifiex_pcie_dev_wakeup_delay(adapter); + +- /* Accessing fw_status register will wakeup device */ +- if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { +- mwifiex_dbg(adapter, ERROR, +- "Writing fw_status register failed\n"); +- return -1; ++ /* The 88W8897 PCIe+USB firmware (latest version 15.68.19.p21) sometimes ++ * appears to ignore or miss our wakeup request, so we continue trying ++ * until we receive an interrupt from the card. ++ */ ++ if (read_poll_timeout(mwifiex_write_reg, retval, ++ READ_ONCE(adapter->int_status) != 0, ++ 500, 500 * N_WAKEUP_TRIES_SHORT_INTERVAL, ++ false, ++ adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { ++ if (read_poll_timeout(mwifiex_write_reg, retval, ++ READ_ONCE(adapter->int_status) != 0, ++ 10000, 10000 * N_WAKEUP_TRIES_LONG_INTERVAL, ++ false, ++ adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { ++ mwifiex_dbg(adapter, ERROR, ++ "Firmware didn't wake up\n"); ++ return -EIO; ++ } + } + + if (reg->sleep_cookie) { +@@ -1490,6 +1508,14 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, + ret = -1; + goto done_unmap; + } ++ ++ /* The firmware (latest version 15.68.19.p21) of the 88W8897 PCIe+USB card ++ * seems to crash randomly after setting the TX ring write pointer when ++ * ASPM powersaving is enabled. A workaround seems to be keeping the bus ++ * busy by reading a random register afterwards. ++ */ ++ mwifiex_read_reg(adapter, PCI_VENDOR_ID, &rx_val); ++ + if ((mwifiex_pcie_txbd_not_full(card)) && + tx_param->next_pkt_len) { + /* have more packets and TxBD still can hold more */ +diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c +index 68c63268e2e6b..2b2e6e0166e14 100644 +--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c +@@ -365,10 +365,12 @@ static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv, + sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac); + if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) { + sta_ptr->tx_pause = tp->tx_pause; ++ spin_unlock_bh(&priv->sta_list_spinlock); + mwifiex_update_ralist_tx_pause(priv, tp->peermac, + tp->tx_pause); ++ } else { ++ spin_unlock_bh(&priv->sta_list_spinlock); + } +- spin_unlock_bh(&priv->sta_list_spinlock); + } + } + +@@ -400,11 +402,13 @@ static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv, + sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac); + if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) { + sta_ptr->tx_pause = tp->tx_pause; ++ spin_unlock_bh(&priv->sta_list_spinlock); + mwifiex_update_ralist_tx_pause(priv, + tp->peermac, + tp->tx_pause); ++ } else { ++ spin_unlock_bh(&priv->sta_list_spinlock); + } +- spin_unlock_bh(&priv->sta_list_spinlock); + } + } + } +diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c +index 426e39d4ccf0f..8f01fcbe93961 100644 +--- a/drivers/net/wireless/marvell/mwifiex/usb.c ++++ b/drivers/net/wireless/marvell/mwifiex/usb.c +@@ -130,7 +130,8 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter, + default: + mwifiex_dbg(adapter, ERROR, + "unknown recv_type %#x\n", recv_type); +- return -1; ++ ret = -1; ++ goto exit_restore_skb; + } + break; + case MWIFIEX_USB_EP_DATA: +@@ -505,6 +506,22 @@ static int mwifiex_usb_probe(struct usb_interface *intf, + } + } + ++ switch (card->usb_boot_state) { ++ case USB8XXX_FW_DNLD: ++ /* Reject broken descriptors. */ ++ if (!card->rx_cmd_ep || !card->tx_cmd_ep) ++ return -ENODEV; ++ if (card->bulk_out_maxpktsize == 0) ++ return -ENODEV; ++ break; ++ case USB8XXX_FW_READY: ++ /* Assume the driver can handle missing endpoints for now. */ ++ break; ++ default: ++ WARN_ON(1); ++ return -ENODEV; ++ } ++ + usb_set_intfdata(intf, card); + + ret = mwifiex_add_card(card, &card->fw_done, &usb_ops, +diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c +index 3bf6571f41490..529e325498cdb 100644 +--- a/drivers/net/wireless/marvell/mwl8k.c ++++ b/drivers/net/wireless/marvell/mwl8k.c +@@ -5800,8 +5800,8 @@ static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) + fail: + priv->fw_state = FW_STATE_ERROR; + complete(&priv->firmware_loading_complete); +- device_release_driver(&priv->pdev->dev); + mwl8k_release_firmware(priv); ++ device_release_driver(&priv->pdev->dev); + } + + #define MAX_RESTART_ATTEMPTS 1 +diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c +index fa48cc3a7a8f7..ad97308c78534 100644 +--- a/drivers/net/wireless/mediatek/mt76/debugfs.c ++++ b/drivers/net/wireless/mediatek/mt76/debugfs.c +@@ -116,8 +116,11 @@ static int mt76_read_rate_txpower(struct seq_file *s, void *data) + return 0; + } + +-struct dentry *mt76_register_debugfs(struct mt76_dev *dev) ++struct dentry * ++mt76_register_debugfs_fops(struct mt76_dev *dev, ++ const struct file_operations *ops) + { ++ const struct file_operations *fops = ops ? ops : &fops_regval; + struct dentry *dir; + + dir = debugfs_create_dir("mt76", dev->hw->wiphy->debugfsdir); +@@ -126,8 +129,7 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev) + + debugfs_create_u8("led_pin", 0600, dir, &dev->led_pin); + debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg); +- debugfs_create_file_unsafe("regval", 0600, dir, dev, +- &fops_regval); ++ debugfs_create_file_unsafe("regval", 0600, dir, dev, fops); + debugfs_create_file_unsafe("napi_threaded", 0600, dir, dev, + &fops_napi_threaded); + debugfs_create_blob("eeprom", 0400, dir, &dev->eeprom); +@@ -140,4 +142,4 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev) + + return dir; + } +-EXPORT_SYMBOL_GPL(mt76_register_debugfs); ++EXPORT_SYMBOL_GPL(mt76_register_debugfs_fops); +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index 25c5ceef52577..4d01fd85283df 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -869,7 +869,13 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, + int mt76_register_phy(struct mt76_phy *phy, bool vht, + struct ieee80211_rate *rates, int n_rates); + +-struct dentry *mt76_register_debugfs(struct mt76_dev *dev); ++struct dentry *mt76_register_debugfs_fops(struct mt76_dev *dev, ++ const struct file_operations *ops); ++static inline struct dentry *mt76_register_debugfs(struct mt76_dev *dev) ++{ ++ return mt76_register_debugfs_fops(dev, NULL); ++} ++ + int mt76_queues_read(struct seq_file *s, void *data); + void mt76_seq_puts_array(struct seq_file *file, const char *str, + s8 *val, int len); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +index 3972c56136a20..65f1f2bb80835 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +@@ -525,6 +525,10 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) + if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR) + status->flag |= RX_FLAG_MMIC_ERROR; + ++ /* ICV error or CCMP/BIP/WPI MIC error */ ++ if (rxd2 & MT_RXD2_NORMAL_ICV_ERR) ++ status->flag |= RX_FLAG_ONLY_MONITOR; ++ + if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && + !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) { + status->flag |= RX_FLAG_DECRYPTED; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +index cb4659771fd97..bda22ca0bd714 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +@@ -2,6 +2,33 @@ + + #include "mt7615.h" + ++static int ++mt7615_reg_set(void *data, u64 val) ++{ ++ struct mt7615_dev *dev = data; ++ ++ mt7615_mutex_acquire(dev); ++ mt76_wr(dev, dev->mt76.debugfs_reg, val); ++ mt7615_mutex_release(dev); ++ ++ return 0; ++} ++ ++static int ++mt7615_reg_get(void *data, u64 *val) ++{ ++ struct mt7615_dev *dev = data; ++ ++ mt7615_mutex_acquire(dev); ++ *val = mt76_rr(dev, dev->mt76.debugfs_reg); ++ mt7615_mutex_release(dev); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7615_reg_get, mt7615_reg_set, ++ "0x%08llx\n"); ++ + static int + mt7615_radar_pattern_set(void *data, u64 val) + { +@@ -506,7 +533,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) + { + struct dentry *dir; + +- dir = mt76_register_debugfs(&dev->mt76); ++ dir = mt76_register_debugfs_fops(&dev->mt76, &fops_regval); + if (!dir) + return -ENOMEM; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c +index 2f1ac644e018e..47f23ac905a3c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c +@@ -49,12 +49,14 @@ int mt7615_thermal_init(struct mt7615_dev *dev) + { + struct wiphy *wiphy = mt76_hw(dev)->wiphy; + struct device *hwmon; ++ const char *name; + + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + +- hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, +- wiphy_name(wiphy), dev, ++ name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7615_%s", ++ wiphy_name(wiphy)); ++ hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev, + mt7615_hwmon_groups); + if (IS_ERR(hwmon)) + return PTR_ERR(hwmon); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +index ff3f85e4087c9..f2704149834a0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +@@ -286,9 +286,16 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + ++ hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS; ++ if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_CM)) ++ return -EINVAL; ++ ++ /* ICV error or CCMP/BIP/WPI MIC error */ ++ if (rxd2 & MT_RXD2_NORMAL_ICV_ERR) ++ status->flag |= RX_FLAG_ONLY_MONITOR; ++ + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; + idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); +- hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS; + status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); + + if (status->wcid) { +@@ -755,12 +762,15 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK); + +- txwi[7] = FIELD_PREP(MT_TXD7_TYPE, fc_type) | +- FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) | +- FIELD_PREP(MT_TXD7_SPE_IDX, 0x18); +- if (!is_mmio) +- txwi[8] = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) | +- FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype); ++ val = FIELD_PREP(MT_TXD7_TYPE, fc_type) | ++ FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) | ++ FIELD_PREP(MT_TXD7_SPE_IDX, 0x18); ++ txwi[7] = cpu_to_le32(val); ++ if (!is_mmio) { ++ val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) | ++ FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype); ++ txwi[8] = cpu_to_le32(val); ++ } + + return 0; + } +@@ -1494,32 +1504,41 @@ out: + } + + static void +-mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) ++mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi) + { + struct mt76_dev *mdev = &dev->mt76; +- struct mt76_txwi_cache *txwi; + __le32 *txwi_data; + u32 val; + u8 wcid; + +- trace_mac_tx_free(dev, token); +- txwi = mt76_token_put(mdev, token); +- if (!txwi) +- return; ++ mt7615_txp_skb_unmap(mdev, txwi); ++ if (!txwi->skb) ++ goto out; + + txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi); + val = le32_to_cpu(txwi_data[1]); + wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val); ++ mt76_tx_complete_skb(mdev, wcid, txwi->skb); + +- mt7615_txp_skb_unmap(mdev, txwi); +- if (txwi->skb) { +- mt76_tx_complete_skb(mdev, wcid, txwi->skb); +- txwi->skb = NULL; +- } +- ++out: ++ txwi->skb = NULL; + mt76_put_txwi(mdev, txwi); + } + ++static void ++mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) ++{ ++ struct mt76_dev *mdev = &dev->mt76; ++ struct mt76_txwi_cache *txwi; ++ ++ trace_mac_tx_free(dev, token); ++ txwi = mt76_token_put(mdev, token); ++ if (!txwi) ++ return; ++ ++ mt7615_txwi_free(dev, txwi); ++} ++ + static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) + { + struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; +@@ -2026,16 +2045,8 @@ void mt7615_tx_token_put(struct mt7615_dev *dev) + int id; + + spin_lock_bh(&dev->mt76.token_lock); +- idr_for_each_entry(&dev->mt76.token, txwi, id) { +- mt7615_txp_skb_unmap(&dev->mt76, txwi); +- if (txwi->skb) { +- struct ieee80211_hw *hw; +- +- hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb); +- ieee80211_free_txskb(hw, txwi->skb); +- } +- mt76_put_txwi(&dev->mt76, txwi); +- } ++ idr_for_each_entry(&dev->mt76.token, txwi, id) ++ mt7615_txwi_free(dev, txwi); + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); + } +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +index dada43d6d879e..fc266da54fe7b 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +@@ -135,8 +135,6 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) + int i; + + switch (type) { +- case NL80211_IFTYPE_MESH_POINT: +- case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + /* prefer hw bssid slot 1-3 */ + i = get_free_idx(mask, HW_BSSID_1, HW_BSSID_3); +@@ -160,6 +158,8 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask) + return HW_BSSID_0; + + break; ++ case NL80211_IFTYPE_ADHOC: ++ case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_AP: + /* ap uses hw bssid 0 and ext bssid */ +@@ -211,11 +211,9 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, + mvif->mt76.omac_idx = idx; + + mvif->mt76.band_idx = ext_phy; +- if (mt7615_ext_phy(dev)) +- mvif->mt76.wmm_idx = ext_phy * (MT7615_MAX_WMM_SETS / 2) + +- mvif->mt76.idx % (MT7615_MAX_WMM_SETS / 2); +- else +- mvif->mt76.wmm_idx = mvif->mt76.idx % MT7615_MAX_WMM_SETS; ++ mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP; ++ if (ext_phy) ++ mvif->mt76.wmm_idx += 2; + + dev->mt76.vif_mask |= BIT(mvif->mt76.idx); + dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +index f8a09692d3e4c..4fed3afad67cc 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +@@ -808,7 +808,8 @@ mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) + + static int + mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, bool enable) ++ struct ieee80211_sta *sta, struct mt7615_phy *phy, ++ bool enable) + { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA; +@@ -821,6 +822,7 @@ mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_MONITOR: + break; + case NL80211_IFTYPE_STATION: + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ +@@ -840,14 +842,19 @@ mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + } + + bss = (struct bss_info_basic *)tlv; +- memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); +- bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + bss->network_type = cpu_to_le32(type); +- bss->dtim_period = vif->bss_conf.dtim_period; + bss->bmc_tx_wlan_idx = wlan_idx; + bss->wmm_idx = mvif->mt76.wmm_idx; + bss->active = enable; + ++ if (vif->type != NL80211_IFTYPE_MONITOR) { ++ memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); ++ bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); ++ bss->dtim_period = vif->bss_conf.dtim_period; ++ } else { ++ memcpy(bss->bssid, phy->mt76->macaddr, ETH_ALEN); ++ } ++ + return 0; + } + +@@ -863,6 +870,7 @@ mt7615_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); + + switch (vif->type) { ++ case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + if (vif->p2p) +@@ -929,7 +937,7 @@ mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif, + if (enable) + mt7615_mcu_bss_omac_tlv(skb, vif); + +- mt7615_mcu_bss_basic_tlv(skb, vif, sta, enable); ++ mt7615_mcu_bss_basic_tlv(skb, vif, sta, phy, enable); + + if (enable && mvif->mt76.omac_idx >= EXT_BSSID_START && + mvif->mt76.omac_idx < REPEATER_BSSID_START) +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +index a2465b49ecd0c..87b4aa52ee0f9 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +@@ -28,8 +28,6 @@ static void mt7615_pci_init_work(struct work_struct *work) + return; + + mt7615_init_work(dev); +- if (dev->dbdc_support) +- mt7615_register_ext_phy(dev); + } + + static int mt7615_init_hardware(struct mt7615_dev *dev) +@@ -160,6 +158,12 @@ int mt7615_register_device(struct mt7615_dev *dev) + mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); + ++ if (dev->dbdc_support) { ++ ret = mt7615_register_ext_phy(dev); ++ if (ret) ++ return ret; ++ } ++ + return mt7615_init_debugfs(dev); + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 5c3a81e5f559d..d25b50e769328 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -689,7 +689,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, + if (ht_cap->ht_supported) + mode |= PHY_TYPE_BIT_HT; + +- if (he_cap->has_he) ++ if (he_cap && he_cap->has_he) + mode |= PHY_TYPE_BIT_HE; + } else if (band == NL80211_BAND_5GHZ) { + mode |= PHY_TYPE_BIT_OFDM; +@@ -700,7 +700,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif, + if (vht_cap->vht_supported) + mode |= PHY_TYPE_BIT_VHT; + +- if (he_cap->has_he) ++ if (he_cap && he_cap->has_he) + mode |= PHY_TYPE_BIT_HE; + } + +@@ -719,6 +719,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, + struct sta_rec_state *state; + struct sta_rec_phy *phy; + struct tlv *tlv; ++ u16 supp_rates; + + /* starec ht */ + if (sta->ht_cap.ht_supported) { +@@ -767,7 +768,15 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb, + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info)); + ra_info = (struct sta_rec_ra_info *)tlv; +- ra_info->legacy = cpu_to_le16((u16)sta->supp_rates[band]); ++ ++ supp_rates = sta->supp_rates[band]; ++ if (band == NL80211_BAND_2GHZ) ++ supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) | ++ FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf); ++ else ++ supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates); ++ ++ ra_info->legacy = cpu_to_le16(supp_rates); + + if (sta->ht_cap.ht_supported) + memcpy(ra_info->rx_mcs_bitmask, sta->ht_cap.mcs.rx_mask, +@@ -1929,19 +1938,22 @@ mt76_connac_mcu_key_iter(struct ieee80211_hw *hw, + key->cipher != WLAN_CIPHER_SUITE_TKIP) + return; + +- if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { +- gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1); ++ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) + cipher = BIT(3); +- } else { +- gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2); ++ else + cipher = BIT(4); +- } + + /* we are assuming here to have a single pairwise key */ + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { ++ if (key->cipher == WLAN_CIPHER_SUITE_TKIP) ++ gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1); ++ else ++ gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2); ++ + gtk_tlv->pairwise_cipher = cpu_to_le32(cipher); +- gtk_tlv->group_cipher = cpu_to_le32(cipher); + gtk_tlv->keyid = key->keyidx; ++ } else { ++ gtk_tlv->group_cipher = cpu_to_le32(cipher); + } + } + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +index 1c73beb226771..77d4435e4581e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +@@ -124,6 +124,8 @@ struct sta_rec_state { + u8 rsv[1]; + } __packed; + ++#define RA_LEGACY_OFDM GENMASK(13, 6) ++#define RA_LEGACY_CCK GENMASK(3, 0) + #define HT_MCS_MASK_NUM 10 + struct sta_rec_ra_info { + __le16 tag; +@@ -844,14 +846,14 @@ struct mt76_connac_gtk_rekey_tlv { + * 2: rekey update + */ + u8 keyid; +- u8 pad[2]; ++ u8 option; /* 1: rekey data update without enabling offload */ ++ u8 pad[1]; + __le32 proto; /* WPA-RSN-WAPI-OPSN */ + __le32 pairwise_cipher; + __le32 group_cipher; + __le32 key_mgmt; /* NONE-PSK-IEEE802.1X */ + __le32 mgmt_group_cipher; +- u8 option; /* 1: rekey data update without enabling offload */ +- u8 reserverd[3]; ++ u8 reserverd[4]; + } __packed; + + #define MT76_CONNAC_WOW_MASK_MAX_LEN 16 +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +index c32e6dc687739..07b21b2085823 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +@@ -176,7 +176,7 @@ void mt76x02_mac_wcid_set_drop(struct mt76x02_dev *dev, u8 idx, bool drop) + mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop)); + } + +-static __le16 ++static u16 + mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, + const struct ieee80211_tx_rate *rate, u8 *nss_val) + { +@@ -222,14 +222,14 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, + rateval |= MT_RXWI_RATE_SGI; + + *nss_val = nss; +- return cpu_to_le16(rateval); ++ return rateval; + } + + void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid, + const struct ieee80211_tx_rate *rate) + { + s8 max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); +- __le16 rateval; ++ u16 rateval; + u32 tx_info; + s8 nss; + +@@ -342,7 +342,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, + struct ieee80211_key_conf *key = info->control.hw_key; + u32 wcid_tx_info; + u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2)); +- u16 txwi_flags = 0; ++ u16 txwi_flags = 0, rateval; + u8 nss; + s8 txpwr_adj, max_txpwr_adj; + u8 ccmp_pn[8], nstreams = dev->mphy.chainmask & 0xf; +@@ -380,14 +380,15 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, + + if (wcid && (rate->idx < 0 || !rate->count)) { + wcid_tx_info = wcid->tx_info; +- txwi->rate = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info); ++ rateval = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info); + max_txpwr_adj = FIELD_GET(MT_WCID_TX_INFO_TXPWR_ADJ, + wcid_tx_info); + nss = FIELD_GET(MT_WCID_TX_INFO_NSS, wcid_tx_info); + } else { +- txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss); ++ rateval = mt76x02_mac_tx_rate_val(dev, rate, &nss); + max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); + } ++ txwi->rate = cpu_to_le16(rateval); + + txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf, + max_txpwr_adj); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +index 4798d6344305d..b171027e0cfa8 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +@@ -130,9 +130,12 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) + struct wiphy *wiphy = phy->mt76->hw->wiphy; + struct thermal_cooling_device *cdev; + struct device *hwmon; ++ const char *name; + +- cdev = thermal_cooling_device_register(wiphy_name(wiphy), phy, +- &mt7915_thermal_ops); ++ name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7915_%s", ++ wiphy_name(wiphy)); ++ ++ cdev = thermal_cooling_device_register(name, phy, &mt7915_thermal_ops); + if (!IS_ERR(cdev)) { + if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj, + "cooling_device") < 0) +@@ -144,8 +147,7 @@ static int mt7915_thermal_init(struct mt7915_phy *phy) + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + +- hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, +- wiphy_name(wiphy), phy, ++ hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, + mt7915_hwmon_groups); + if (IS_ERR(hwmon)) + return PTR_ERR(hwmon); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +index 2462704094b0a..ff613d7056119 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +@@ -349,9 +349,16 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + ++ hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; ++ if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) ++ return -EINVAL; ++ ++ /* ICV error or CCMP/BIP/WPI MIC error */ ++ if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) ++ status->flag |= RX_FLAG_ONLY_MONITOR; ++ + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; + idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); +- hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; + status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); + + if (status->wcid) { +@@ -1232,7 +1239,7 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid, + goto out; + + info = IEEE80211_SKB_CB(skb); +- if (!(txs_data[0] & le32_to_cpu(MT_TXS0_ACK_ERROR_MASK))) ++ if (!(txs_data[0] & cpu_to_le32(MT_TXS0_ACK_ERROR_MASK))) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.ampdu_len = 1; +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +index eb1885f4bd8eb..fee7741b5d421 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +@@ -272,7 +272,8 @@ enum tx_mcu_port_q_idx { + #define MT_TX_RATE_MODE GENMASK(9, 6) + #define MT_TX_RATE_SU_EXT_TONE BIT(5) + #define MT_TX_RATE_DCM BIT(4) +-#define MT_TX_RATE_IDX GENMASK(3, 0) ++/* VHT/HE only use bits 0-3 */ ++#define MT_TX_RATE_IDX GENMASK(5, 0) + + #define MT_TXP_MAX_BUF_NUM 6 + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 43960770a9af2..7440f2b443eca 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) + if (ht_cap->ht_supported) + mode |= PHY_MODE_GN; + +- if (he_cap->has_he) ++ if (he_cap && he_cap->has_he) + mode |= PHY_MODE_AX_24G; + } else if (band == NL80211_BAND_5GHZ) { + mode |= PHY_MODE_A; +@@ -187,7 +187,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) + if (vht_cap->vht_supported) + mode |= PHY_MODE_AC; + +- if (he_cap->has_he) ++ if (he_cap && he_cap->has_he) + mode |= PHY_MODE_AX_5G; + } + +@@ -721,7 +721,7 @@ mt7915_mcu_alloc_sta_req(struct mt7915_dev *dev, struct mt7915_vif *mvif, + .bss_idx = mvif->idx, + .wlan_idx_lo = msta ? to_wcid_lo(msta->wcid.idx) : 0, + .wlan_idx_hi = msta ? to_wcid_hi(msta->wcid.idx) : 0, +- .muar_idx = msta ? mvif->omac_idx : 0, ++ .muar_idx = msta && msta->wcid.sta ? mvif->omac_idx : 0xe, + .is_tlv_append = 1, + }; + struct sk_buff *skb; +@@ -757,7 +757,7 @@ mt7915_mcu_alloc_wtbl_req(struct mt7915_dev *dev, struct mt7915_sta *msta, + } + + if (sta_hdr) +- sta_hdr->len = cpu_to_le16(sizeof(hdr)); ++ le16_add_cpu(&sta_hdr->len, sizeof(hdr)); + + return skb_put_data(nskb, &hdr, sizeof(hdr)); + } +@@ -925,7 +925,7 @@ static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, + + elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY); + +- if (!elem || elem->datalen < 10 || ++ if (!elem || elem->datalen <= 10 || + !(elem->data[10] & + WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) + data->tolerated = false; +@@ -1201,7 +1201,7 @@ mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb, + u8 cipher; + + cipher = mt7915_mcu_get_cipher(key->cipher); +- if (cipher == MT_CIPHER_NONE) ++ if (cipher == MCU_CIPHER_NONE) + return -EOPNOTSUPP; + + sec_key = &sec->key[0]; +@@ -2790,7 +2790,7 @@ out: + default: + ret = -EAGAIN; + dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); +- goto out; ++ break; + } + release_firmware(fw); + +@@ -3391,20 +3391,20 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd) + + static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) + { +-#define TOTAL_PAGE_MASK GENMASK(7, 5) ++#define MAX_PAGE_IDX_MASK GENMASK(7, 5) + #define PAGE_IDX_MASK GENMASK(4, 2) + #define PER_PAGE_SIZE 0x400 + struct mt7915_mcu_eeprom req = { .buffer_mode = EE_MODE_BUFFER }; +- u8 total = MT7915_EEPROM_SIZE / PER_PAGE_SIZE; ++ u8 total = DIV_ROUND_UP(MT7915_EEPROM_SIZE, PER_PAGE_SIZE); + u8 *eep = (u8 *)dev->mt76.eeprom.data; + int eep_len; + int i; + +- for (i = 0; i <= total; i++, eep += eep_len) { ++ for (i = 0; i < total; i++, eep += eep_len) { + struct sk_buff *skb; + int ret; + +- if (i == total) ++ if (i == total - 1 && !!(MT7915_EEPROM_SIZE % PER_PAGE_SIZE)) + eep_len = MT7915_EEPROM_SIZE % PER_PAGE_SIZE; + else + eep_len = PER_PAGE_SIZE; +@@ -3414,7 +3414,7 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev) + if (!skb) + return -ENOMEM; + +- req.format = FIELD_PREP(TOTAL_PAGE_MASK, total) | ++ req.format = FIELD_PREP(MAX_PAGE_IDX_MASK, total - 1) | + FIELD_PREP(PAGE_IDX_MASK, i) | EE_FORMAT_WHOLE; + req.len = cpu_to_le16(eep_len); + +@@ -3481,7 +3481,7 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx, + u8 idx; + u8 rsv[4]; + __le32 len; +- } req; ++ } req = {}; + struct sk_buff *skb; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req) + len); +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +index 77468bdae460b..30f3b3085c786 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +@@ -4,6 +4,32 @@ + #include "mt7921.h" + #include "eeprom.h" + ++static int ++mt7921_reg_set(void *data, u64 val) ++{ ++ struct mt7921_dev *dev = data; ++ ++ mt7921_mutex_acquire(dev); ++ mt76_wr(dev, dev->mt76.debugfs_reg, val); ++ mt7921_mutex_release(dev); ++ ++ return 0; ++} ++ ++static int ++mt7921_reg_get(void *data, u64 *val) ++{ ++ struct mt7921_dev *dev = data; ++ ++ mt7921_mutex_acquire(dev); ++ *val = mt76_rr(dev, dev->mt76.debugfs_reg); ++ mt7921_mutex_release(dev); ++ ++ return 0; ++} ++ ++DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set, ++ "0x%08llx\n"); + static int + mt7921_fw_debug_set(void *data, u64 val) + { +@@ -69,6 +95,8 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) + struct mt7921_dev *dev = file->private; + int stat[8], i, n; + ++ mt7921_mutex_acquire(dev); ++ + mt7921_ampdu_stat_read_phy(&dev->phy, file); + + /* Tx amsdu info */ +@@ -78,6 +106,8 @@ mt7921_tx_stats_show(struct seq_file *file, void *data) + n += stat[i]; + } + ++ mt7921_mutex_release(dev); ++ + for (i = 0; i < ARRAY_SIZE(stat); i++) { + seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ", + i + 1, stat[i]); +@@ -98,6 +128,8 @@ mt7921_queues_acq(struct seq_file *s, void *data) + struct mt7921_dev *dev = dev_get_drvdata(s->private); + int i; + ++ mt7921_mutex_acquire(dev); ++ + for (i = 0; i < 16; i++) { + int j, acs = i / 4, index = i % 4; + u32 ctrl, val, qlen = 0; +@@ -117,6 +149,8 @@ mt7921_queues_acq(struct seq_file *s, void *data) + seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); + } + ++ mt7921_mutex_release(dev); ++ + return 0; + } + +@@ -373,7 +407,7 @@ int mt7921_init_debugfs(struct mt7921_dev *dev) + { + struct dentry *dir; + +- dir = mt76_register_debugfs(&dev->mt76); ++ dir = mt76_register_debugfs_fops(&dev->mt76, &fops_regval); + if (!dir) + return -ENOMEM; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +index a9ce10b988273..78a00028137bd 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c +@@ -106,6 +106,10 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + ++ /* enable MIB tx-rx time reporting */ ++ mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN); ++ mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN); ++ + mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); + /* disable rx rate report by default due to hw issues */ + mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); +@@ -247,8 +251,17 @@ int mt7921_register_device(struct mt7921_dev *dev) + + void mt7921_unregister_device(struct mt7921_dev *dev) + { ++ int i; ++ struct mt76_connac_pm *pm = &dev->pm; ++ + mt76_unregister_device(&dev->mt76); ++ mt76_for_each_q_rx(&dev->mt76, i) ++ napi_disable(&dev->mt76.napi[i]); ++ cancel_delayed_work_sync(&pm->ps_work); ++ cancel_work_sync(&pm->wake_work); ++ + mt7921_tx_token_put(dev); ++ mt7921_mcu_drv_pmctrl(dev); + mt7921_dma_cleanup(dev); + mt7921_mcu_exit(dev); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +index 7fe2e3a50428f..04a288029c98e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +@@ -180,12 +180,56 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); + } + ++static void ++mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, ++ struct mt76_rx_status *status, ++ __le32 *rxv) ++{ ++ static const struct ieee80211_radiotap_he_mu mu_known = { ++ .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | ++ HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | ++ HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | ++ HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN) | ++ HE_BITS(MU_FLAGS1_SIG_B_COMP_KNOWN), ++ .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN) | ++ HE_BITS(MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN), ++ }; ++ struct ieee80211_radiotap_he_mu *he_mu = NULL; ++ ++ he_mu = skb_push(skb, sizeof(mu_known)); ++ memcpy(he_mu, &mu_known, sizeof(mu_known)); ++ ++#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) ++ ++ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); ++ if (status->he_dcm) ++ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); ++ ++ he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | ++ MU_PREP(FLAGS2_SIG_B_SYMS_USERS, ++ le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER)); ++ ++ he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, cpu_to_le32(rxv[3])); ++ ++ if (status->bw >= RATE_INFO_BW_40) { ++ he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); ++ he_mu->ru_ch2[0] = ++ FIELD_GET(MT_CRXV_HE_RU1, cpu_to_le32(rxv[3])); ++ } ++ ++ if (status->bw >= RATE_INFO_BW_80) { ++ he_mu->ru_ch1[1] = ++ FIELD_GET(MT_CRXV_HE_RU2, cpu_to_le32(rxv[3])); ++ he_mu->ru_ch2[1] = ++ FIELD_GET(MT_CRXV_HE_RU3, cpu_to_le32(rxv[3])); ++ } ++} ++ + static void + mt7921_mac_decode_he_radiotap(struct sk_buff *skb, + struct mt76_rx_status *status, + __le32 *rxv, u32 phy) + { +- /* TODO: struct ieee80211_radiotap_he_mu */ + static const struct ieee80211_radiotap_he known = { + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | + HE_BITS(DATA1_DATA_DCM_KNOWN) | +@@ -193,6 +237,7 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, + HE_BITS(DATA1_CODING_KNOWN) | + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | ++ HE_BITS(DATA1_SPTL_REUSE_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN), + .data2 = HE_BITS(DATA2_GI_KNOWN) | + HE_BITS(DATA2_TXBF_KNOWN) | +@@ -207,9 +252,12 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, + + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) | + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]); ++ he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) | + le16_encode_bits(ltf_size, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); ++ if (cpu_to_le32(rxv[0]) & MT_PRXV_TXBF) ++ he->data5 |= HE_BITS(DATA5_TXBF); + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) | + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]); + +@@ -217,8 +265,7 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, + case MT_PHY_TYPE_HE_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | +- HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | +- HE_BITS(DATA1_SPTL_REUSE_KNOWN); ++ HE_BITS(DATA1_BEAM_CHANGE_KNOWN); + + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) | + HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); +@@ -232,17 +279,15 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, + break; + case MT_PHY_TYPE_HE_MU: + he->data1 |= HE_BITS(DATA1_FORMAT_MU) | +- HE_BITS(DATA1_UL_DL_KNOWN) | +- HE_BITS(DATA1_SPTL_REUSE_KNOWN); ++ HE_BITS(DATA1_UL_DL_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]); +- he->data4 |= HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]); ++ he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]); + + mt7921_mac_decode_he_radiotap_ru(status, he, rxv); + break; + case MT_PHY_TYPE_HE_TB: + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | +- HE_BITS(DATA1_SPTL_REUSE_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE4_KNOWN); +@@ -338,10 +383,17 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + ++ hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; ++ if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM)) ++ return -EINVAL; ++ ++ /* ICV error or CCMP/BIP/WPI MIC error */ ++ if (rxd1 & MT_RXD1_NORMAL_ICV_ERR) ++ status->flag |= RX_FLAG_ONLY_MONITOR; ++ + chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3); + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; + idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); +- hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; + status->wcid = mt7921_rx_get_wcid(dev, idx, unicast); + + if (status->wcid) { +@@ -606,9 +658,13 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) + + mt7921_mac_assoc_rssi(dev, skb); + +- if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) ++ if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) { + mt7921_mac_decode_he_radiotap(skb, status, rxv, mode); + ++ if (status->flag & RX_FLAG_RADIOTAP_HE_MU) ++ mt7921_mac_decode_he_mu_radiotap(skb, status, rxv); ++ } ++ + if (!status->wcid || !ieee80211_is_data_qos(fc)) + return 0; + +@@ -735,8 +791,9 @@ mt7921_mac_write_txwi_80211(struct mt7921_dev *dev, __le32 *txwi, + static void mt7921_update_txs(struct mt76_wcid *wcid, __le32 *txwi) + { + struct mt7921_sta *msta = container_of(wcid, struct mt7921_sta, wcid); +- u32 pid, frame_type = FIELD_GET(MT_TXD2_FRAME_TYPE, txwi[2]); ++ u32 pid, frame_type; + ++ frame_type = FIELD_GET(MT_TXD2_FRAME_TYPE, le32_to_cpu(txwi[2])); + if (!(frame_type & (IEEE80211_FTYPE_DATA >> 2))) + return; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h +index 3af67fac213df..f0194c8780372 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.h +@@ -116,6 +116,7 @@ enum rx_pkt_type { + #define MT_PRXV_TX_DCM BIT(4) + #define MT_PRXV_TX_ER_SU_106T BIT(5) + #define MT_PRXV_NSTS GENMASK(9, 7) ++#define MT_PRXV_TXBF BIT(10) + #define MT_PRXV_HT_AD_CODE BIT(11) + #define MT_PRXV_FRAME_MODE GENMASK(14, 12) + #define MT_PRXV_SGI GENMASK(16, 15) +@@ -138,8 +139,15 @@ enum rx_pkt_type { + #define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17) + #define MT_CRXV_HE_LDPC_EXT_SYM BIT(20) + #define MT_CRXV_HE_PE_DISAMBIG BIT(23) ++#define MT_CRXV_HE_NUM_USER GENMASK(30, 24) + #define MT_CRXV_HE_UPLINK BIT(31) + ++#define MT_CRXV_HE_RU0 GENMASK(7, 0) ++#define MT_CRXV_HE_RU1 GENMASK(15, 8) ++#define MT_CRXV_HE_RU2 GENMASK(23, 16) ++#define MT_CRXV_HE_RU3 GENMASK(31, 24) ++#define MT_CRXV_HE_MU_AID GENMASK(30, 20) ++ + #define MT_CRXV_HE_SR_MASK GENMASK(11, 8) + #define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) + #define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +index 63ec140c9c372..9eb90e6f01031 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -285,12 +285,6 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, + mtxq->wcid = &mvif->sta.wcid; + } + +- if (vif->type != NL80211_IFTYPE_AP && +- (!mvif->mt76.omac_idx || mvif->mt76.omac_idx > 3)) +- vif->offload_flags = 0; +- +- vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; +- + out: + mt7921_mutex_release(dev); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +index 9fbaacc67cfad..506a1909ce6d5 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +@@ -157,6 +157,7 @@ mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, + struct sk_buff *skb, int seq) + { + struct mt7921_mcu_rxd *rxd; ++ int mcu_cmd = cmd & MCU_CMD_MASK; + int ret = 0; + + if (!skb) { +@@ -194,6 +195,9 @@ mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, + skb_pull(skb, sizeof(*rxd)); + event = (struct mt7921_mcu_uni_event *)skb->data; + ret = le32_to_cpu(event->status); ++ /* skip invalid event */ ++ if (mcu_cmd != event->cid) ++ ret = -EAGAIN; + break; + } + case MCU_CMD_REG_READ: { +@@ -316,11 +320,13 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy, + struct rate_info *rate, u16 r) + { + struct ieee80211_supported_band *sband; +- u16 flags = 0; ++ u16 flags = 0, rate_idx; + u8 txmode = FIELD_GET(MT_WTBL_RATE_TX_MODE, r); + u8 gi = 0; + u8 bw = 0; ++ bool cck = false; + ++ memset(rate, 0, sizeof(*rate)); + rate->mcs = FIELD_GET(MT_WTBL_RATE_MCS, r); + rate->nss = FIELD_GET(MT_WTBL_RATE_NSS, r) + 1; + +@@ -345,13 +351,18 @@ mt7921_mcu_tx_rate_parse(struct mt76_phy *mphy, + + switch (txmode) { + case MT_PHY_TYPE_CCK: ++ cck = true; ++ fallthrough; + case MT_PHY_TYPE_OFDM: + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + +- rate->legacy = sband->bitrates[rate->mcs].bitrate; ++ rate_idx = FIELD_GET(MT_TX_RATE_IDX, r); ++ rate_idx = mt76_get_rate(mphy->dev, sband, rate_idx, ++ cck); ++ rate->legacy = sband->bitrates[rate_idx].bitrate; + break; + case MT_PHY_TYPE_HT: + case MT_PHY_TYPE_HT_GF: +@@ -532,7 +543,8 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) + peer.g8 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); + peer.g16 = !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); + mt7921_mcu_tx_rate_parse(mphy->mt76, &peer, +- &msta->stats.tx_rate, event->tx_rate); ++ &msta->stats.tx_rate, ++ le16_to_cpu(event->tx_rate)); + + spin_lock_bh(&dev->sta_poll_lock); + break; +@@ -619,7 +631,7 @@ mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb, + u8 cipher; + + cipher = mt7921_mcu_get_cipher(key->cipher); +- if (cipher == MT_CIPHER_NONE) ++ if (cipher == MCU_CIPHER_NONE) + return -EOPNOTSUPP; + + sec_key = &sec->key[0]; +@@ -815,7 +827,7 @@ out: + default: + ret = -EAGAIN; + dev_err(dev->mt76.dev, "Failed to release patch semaphore\n"); +- goto out; ++ break; + } + release_firmware(fw); + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +index de3c091f67368..42e7271848956 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +@@ -296,11 +296,11 @@ struct mt7921_txpwr_event { + struct mt7921_mcu_tx_done_event { + u8 pid; + u8 status; +- u16 seq; ++ __le16 seq; + + u8 wlan_idx; + u8 tx_cnt; +- u16 tx_rate; ++ __le16 tx_rate; + + u8 flag; + u8 tid; +@@ -312,9 +312,9 @@ struct mt7921_mcu_tx_done_event { + u8 reason; + u8 rsv0[1]; + +- u32 delay; +- u32 timestamp; +- u32 applied_flag; ++ __le32 delay; ++ __le32 timestamp; ++ __le32 applied_flag; + + u8 txs[28]; + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +index b6944c867a573..26fb118237626 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +@@ -96,6 +96,10 @@ + #define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800) + #define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) + ++#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004) ++#define MT_MIB_TXDUR_EN BIT(8) ++#define MT_MIB_RXDUR_EN BIT(9) ++ + #define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) + #define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) + +@@ -108,9 +112,9 @@ + #define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) + #define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) + +-#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x098) ++#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054) + #define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) +-#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x09c) ++#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058) + #define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) + + #define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) +diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c +index 96973ec7bd9ac..87c14969c75fa 100644 +--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c ++++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c +@@ -129,8 +129,7 @@ static void cfg_scan_result(enum scan_event scan_event, + info->frame_len, + (s32)info->rssi * 100, + GFP_KERNEL); +- if (!bss) +- cfg80211_put_bss(wiphy, bss); ++ cfg80211_put_bss(wiphy, bss); + } else if (scan_event == SCAN_EVENT_DONE) { + mutex_lock(&priv->scan_req_lock); + +diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c +index 7e4d9235251cb..9dfb1a285e6a4 100644 +--- a/drivers/net/wireless/microchip/wilc1000/netdev.c ++++ b/drivers/net/wireless/microchip/wilc1000/netdev.c +@@ -901,7 +901,6 @@ void wilc_netdev_cleanup(struct wilc *wilc) + + wilc_wlan_cfg_deinit(wilc); + wlan_deinit_locks(wilc); +- kfree(wilc->bus_data); + wiphy_unregister(wilc->wiphy); + wiphy_free(wilc->wiphy); + } +diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c +index 42e03a701ae16..8b3b735231085 100644 +--- a/drivers/net/wireless/microchip/wilc1000/sdio.c ++++ b/drivers/net/wireless/microchip/wilc1000/sdio.c +@@ -167,9 +167,11 @@ free: + static void wilc_sdio_remove(struct sdio_func *func) + { + struct wilc *wilc = sdio_get_drvdata(func); ++ struct wilc_sdio *sdio_priv = wilc->bus_data; + + clk_disable_unprepare(wilc->rtc_clk); + wilc_netdev_cleanup(wilc); ++ kfree(sdio_priv); + } + + static int wilc_sdio_reset(struct wilc *wilc) +diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c +index dd481dc0b5ce0..c98c0999a6b67 100644 +--- a/drivers/net/wireless/microchip/wilc1000/spi.c ++++ b/drivers/net/wireless/microchip/wilc1000/spi.c +@@ -182,9 +182,11 @@ free: + static int wilc_bus_remove(struct spi_device *spi) + { + struct wilc *wilc = spi_get_drvdata(spi); ++ struct wilc_spi *spi_priv = wilc->bus_data; + + clk_disable_unprepare(wilc->rtc_clk); + wilc_netdev_cleanup(wilc); ++ kfree(spi_priv); + + return 0; + } +diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +index e4473a5512415..74c3d8cb31002 100644 +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +@@ -25,6 +25,9 @@ static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status) + if (status == -ENODEV || status == -ENOENT) + return true; + ++ if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) ++ return false; ++ + if (status == -EPROTO || status == -ETIMEDOUT) + rt2x00dev->num_proto_errs++; + else +diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c +index 585784258c665..4efab907a3ac6 100644 +--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c ++++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c +@@ -28,7 +28,7 @@ u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, idx & 0x03, +- &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); ++ &priv->io_dmabuf->bits8, sizeof(val), 500); + + val = priv->io_dmabuf->bits8; + mutex_unlock(&priv->io_mutex); +@@ -45,7 +45,7 @@ u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, idx & 0x03, +- &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); ++ &priv->io_dmabuf->bits16, sizeof(val), 500); + + val = priv->io_dmabuf->bits16; + mutex_unlock(&priv->io_mutex); +@@ -62,7 +62,7 @@ u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, idx & 0x03, +- &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); ++ &priv->io_dmabuf->bits32, sizeof(val), 500); + + val = priv->io_dmabuf->bits32; + mutex_unlock(&priv->io_mutex); +@@ -79,7 +79,7 @@ void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, idx & 0x03, +- &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); ++ &priv->io_dmabuf->bits8, sizeof(val), 500); + + mutex_unlock(&priv->io_mutex); + } +@@ -93,7 +93,7 @@ void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, idx & 0x03, +- &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); ++ &priv->io_dmabuf->bits16, sizeof(val), 500); + + mutex_unlock(&priv->io_mutex); + } +@@ -107,7 +107,7 @@ void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, idx & 0x03, +- &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); ++ &priv->io_dmabuf->bits32, sizeof(val), 500); + + mutex_unlock(&priv->io_mutex); + } +@@ -183,7 +183,7 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data) + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data), +- HZ / 2); ++ 500); + + mutex_unlock(&priv->io_mutex); + +diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +index 6312fddd9c00a..eaba661133280 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +@@ -1000,6 +1000,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) + _initpabias(hw); + rtl92c_dm_init(hw); + exit: ++ local_irq_disable(); + local_irq_restore(flags); + return err; + } +diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c +index e6399519584bd..a384fc3a4f2b0 100644 +--- a/drivers/net/wireless/realtek/rtw88/fw.c ++++ b/drivers/net/wireless/realtek/rtw88/fw.c +@@ -1556,12 +1556,10 @@ static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, + u32 i; + u16 idx = 0; + u16 ctl; +- u8 rcr; + +- rcr = rtw_read8(rtwdev, REG_RCR + 2); + ctl = rtw_read16(rtwdev, REG_PKTBUF_DBG_CTRL) & 0xf000; + /* disable rx clock gate */ +- rtw_write8(rtwdev, REG_RCR, rcr | BIT(3)); ++ rtw_write32_set(rtwdev, REG_RCR, BIT_DISGCLK); + + do { + rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, start_pg | ctl); +@@ -1580,7 +1578,8 @@ static void rtw_fw_read_fifo_page(struct rtw_dev *rtwdev, u32 offset, u32 size, + + out: + rtw_write16(rtwdev, REG_PKTBUF_DBG_CTRL, ctl); +- rtw_write8(rtwdev, REG_RCR + 2, rcr); ++ /* restore rx clock gate */ ++ rtw_write32_clr(rtwdev, REG_RCR, BIT_DISGCLK); + } + + static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel, +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 6bb55e663fc36..69512856bb462 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -1859,7 +1859,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) + + /* default rx filter setting */ + rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV | +- BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | ++ BIT_PKTCTL_DLEN | BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | + BIT_AB | BIT_AM | BIT_APM; + + ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW); +diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c +index a7a6ebfaa203c..08cf66141889b 100644 +--- a/drivers/net/wireless/realtek/rtw88/pci.c ++++ b/drivers/net/wireless/realtek/rtw88/pci.c +@@ -2,7 +2,6 @@ + /* Copyright(c) 2018-2019 Realtek Corporation + */ + +-#include <linux/dmi.h> + #include <linux/module.h> + #include <linux/pci.h> + #include "main.h" +@@ -1409,7 +1408,11 @@ static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter) + * throughput. This is probably because the ASPM behavior slightly + * varies from different SOC. + */ +- if (rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1) ++ if (!(rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1)) ++ return; ++ ++ if ((enter && atomic_dec_if_positive(&rtwpci->link_usage) == 0) || ++ (!enter && atomic_inc_return(&rtwpci->link_usage) == 1)) + rtw_pci_aspm_set(rtwdev, enter); + } + +@@ -1658,6 +1661,9 @@ static int rtw_pci_napi_poll(struct napi_struct *napi, int budget) + priv); + int work_done = 0; + ++ if (rtwpci->rx_no_aspm) ++ rtw_pci_link_ps(rtwdev, false); ++ + while (work_done < budget) { + u32 work_done_once; + +@@ -1681,6 +1687,8 @@ static int rtw_pci_napi_poll(struct napi_struct *napi, int budget) + if (rtw_pci_get_hw_rx_ring_nr(rtwdev, rtwpci)) + napi_schedule(napi); + } ++ if (rtwpci->rx_no_aspm) ++ rtw_pci_link_ps(rtwdev, true); + + return work_done; + } +@@ -1702,50 +1710,13 @@ static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev) + netif_napi_del(&rtwpci->napi); + } + +-enum rtw88_quirk_dis_pci_caps { +- QUIRK_DIS_PCI_CAP_MSI, +- QUIRK_DIS_PCI_CAP_ASPM, +-}; +- +-static int disable_pci_caps(const struct dmi_system_id *dmi) +-{ +- uintptr_t dis_caps = (uintptr_t)dmi->driver_data; +- +- if (dis_caps & BIT(QUIRK_DIS_PCI_CAP_MSI)) +- rtw_disable_msi = true; +- if (dis_caps & BIT(QUIRK_DIS_PCI_CAP_ASPM)) +- rtw_pci_disable_aspm = true; +- +- return 1; +-} +- +-static const struct dmi_system_id rtw88_pci_quirks[] = { +- { +- .callback = disable_pci_caps, +- .ident = "Protempo Ltd L116HTN6SPW", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Protempo Ltd"), +- DMI_MATCH(DMI_PRODUCT_NAME, "L116HTN6SPW"), +- }, +- .driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM), +- }, +- { +- .callback = disable_pci_caps, +- .ident = "HP HP Pavilion Laptop 14-ce0xxx", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "HP"), +- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Laptop 14-ce0xxx"), +- }, +- .driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM), +- }, +- {} +-}; +- + int rtw_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) + { ++ struct pci_dev *bridge = pci_upstream_bridge(pdev); + struct ieee80211_hw *hw; + struct rtw_dev *rtwdev; ++ struct rtw_pci *rtwpci; + int drv_data_size; + int ret; + +@@ -1763,6 +1734,9 @@ int rtw_pci_probe(struct pci_dev *pdev, + rtwdev->hci.ops = &rtw_pci_ops; + rtwdev->hci.type = RTW_HCI_TYPE_PCIE; + ++ rtwpci = (struct rtw_pci *)rtwdev->priv; ++ atomic_set(&rtwpci->link_usage, 1); ++ + ret = rtw_core_init(rtwdev); + if (ret) + goto err_release_hw; +@@ -1791,7 +1765,10 @@ int rtw_pci_probe(struct pci_dev *pdev, + goto err_destroy_pci; + } + +- dmi_check_system(rtw88_pci_quirks); ++ /* Disable PCIe ASPM L1 while doing NAPI poll for 8821CE */ ++ if (pdev->device == 0xc821 && bridge->vendor == PCI_VENDOR_ID_INTEL) ++ rtwpci->rx_no_aspm = true; ++ + rtw_pci_phy_cfg(rtwdev); + + ret = rtw_register_hw(rtwdev, hw); +diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h +index 66f78eb7757c5..0c37efd8c66fa 100644 +--- a/drivers/net/wireless/realtek/rtw88/pci.h ++++ b/drivers/net/wireless/realtek/rtw88/pci.h +@@ -223,6 +223,8 @@ struct rtw_pci { + struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM]; + struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM]; + u16 link_ctrl; ++ atomic_t link_usage; ++ bool rx_no_aspm; + DECLARE_BITMAP(flags, NUM_OF_RTW_PCI_FLAGS); + + void __iomem *mmap; +diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h +index f5ce75095e904..c0fb1e446245f 100644 +--- a/drivers/net/wireless/realtek/rtw88/reg.h ++++ b/drivers/net/wireless/realtek/rtw88/reg.h +@@ -406,6 +406,7 @@ + #define BIT_MFBEN BIT(22) + #define BIT_DISCHKPPDLLEN BIT(21) + #define BIT_PKTCTL_DLEN BIT(20) ++#define BIT_DISGCLK BIT(19) + #define BIT_TIM_PARSER_EN BIT(18) + #define BIT_BC_MD_EN BIT(17) + #define BIT_UC_MD_EN BIT(16) +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h +index 112faa60f653e..d9fbddd7b0f35 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h +@@ -131,7 +131,7 @@ _rtw_write32s_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) + #define WLAN_TX_FUNC_CFG2 0x30 + #define WLAN_MAC_OPT_NORM_FUNC1 0x98 + #define WLAN_MAC_OPT_LB_FUNC1 0x80 +-#define WLAN_MAC_OPT_FUNC2 0x30810041 ++#define WLAN_MAC_OPT_FUNC2 0xb0810041 + + #define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \ + (WLAN_SIFS_OFDM_CONT_TX << BIT_SHIFT_SIFS_OFDM_CTX) | \ +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +index f1789155e9016..247f26e3e8192 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c +@@ -204,7 +204,7 @@ static void rtw8822b_phy_set_param(struct rtw_dev *rtwdev) + #define WLAN_TX_FUNC_CFG2 0x30 + #define WLAN_MAC_OPT_NORM_FUNC1 0x98 + #define WLAN_MAC_OPT_LB_FUNC1 0x80 +-#define WLAN_MAC_OPT_FUNC2 0x30810041 ++#define WLAN_MAC_OPT_FUNC2 0xb0810041 + + #define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \ + (WLAN_SIFS_OFDM_CONT_TX << BIT_SHIFT_SIFS_OFDM_CTX) | \ +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +index f3ad079967a68..bc87e3cb9cdce 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c +@@ -1962,7 +1962,7 @@ static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev) + #define WLAN_TX_FUNC_CFG2 0x30 + #define WLAN_MAC_OPT_NORM_FUNC1 0x98 + #define WLAN_MAC_OPT_LB_FUNC1 0x80 +-#define WLAN_MAC_OPT_FUNC2 0x30810041 ++#define WLAN_MAC_OPT_FUNC2 0xb0810041 + #define WLAN_MAC_INT_MIG_CFG 0x33330000 + + #define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \ +diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c +index a48e616e0fb91..6bfaab48b507d 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_core.c ++++ b/drivers/net/wireless/rsi/rsi_91x_core.c +@@ -399,6 +399,8 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) + + info = IEEE80211_SKB_CB(skb); + tx_params = (struct skb_info *)info->driver_data; ++ /* info->driver_data and info->control part of union so make copy */ ++ tx_params->have_key = !!info->control.hw_key; + wh = (struct ieee80211_hdr *)&skb->data[0]; + tx_params->sta_id = 0; + +diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c +index f4a26f16f00f4..dca81a4bbdd7f 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_hal.c ++++ b/drivers/net/wireless/rsi/rsi_91x_hal.c +@@ -203,7 +203,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + wh->frame_control |= cpu_to_le16(RSI_SET_PS_ENABLE); + + if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) && +- info->control.hw_key) { ++ tx_params->have_key) { + if (rsi_is_cipher_wep(common)) + ieee80211_size += 4; + else +@@ -214,15 +214,17 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + RSI_WIFI_DATA_Q); + data_desc->header_len = ieee80211_size; + +- if (common->min_rate != RSI_RATE_AUTO) { ++ if (common->rate_config[common->band].fixed_enabled) { + /* Send fixed rate */ ++ u16 fixed_rate = common->rate_config[common->band].fixed_hw_rate; ++ + data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE); +- data_desc->rate_info = cpu_to_le16(common->min_rate); ++ data_desc->rate_info = cpu_to_le16(fixed_rate); + + if (conf_is_ht40(&common->priv->hw->conf)) + data_desc->bbp_info = cpu_to_le16(FULL40M_ENABLE); + +- if ((common->vif_info[0].sgi) && (common->min_rate & 0x100)) { ++ if (common->vif_info[0].sgi && (fixed_rate & 0x100)) { + /* Only MCS rates */ + data_desc->rate_info |= + cpu_to_le16(ENABLE_SHORTGI_RATE); +diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c +index b66975f545675..e70c1c7fdf595 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c ++++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c +@@ -510,7 +510,6 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw, + if ((vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_P2P_GO)) { + rsi_send_rx_filter_frame(common, DISALLOW_BEACONS); +- common->min_rate = RSI_RATE_AUTO; + for (i = 0; i < common->max_stations; i++) + common->stations[i].sta = NULL; + } +@@ -1228,20 +1227,32 @@ static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask) + { ++ const unsigned int mcs_offset = ARRAY_SIZE(rsi_rates); + struct rsi_hw *adapter = hw->priv; + struct rsi_common *common = adapter->priv; +- enum nl80211_band band = hw->conf.chandef.chan->band; ++ int i; + + mutex_lock(&common->mutex); +- common->fixedrate_mask[band] = 0; + +- if (mask->control[band].legacy == 0xfff) { +- common->fixedrate_mask[band] = +- (mask->control[band].ht_mcs[0] << 12); +- } else { +- common->fixedrate_mask[band] = +- mask->control[band].legacy; ++ for (i = 0; i < ARRAY_SIZE(common->rate_config); i++) { ++ struct rsi_rate_config *cfg = &common->rate_config[i]; ++ u32 bm; ++ ++ bm = mask->control[i].legacy | (mask->control[i].ht_mcs[0] << mcs_offset); ++ if (hweight32(bm) == 1) { /* single rate */ ++ int rate_index = ffs(bm) - 1; ++ ++ if (rate_index < mcs_offset) ++ cfg->fixed_hw_rate = rsi_rates[rate_index].hw_value; ++ else ++ cfg->fixed_hw_rate = rsi_mcsrates[rate_index - mcs_offset]; ++ cfg->fixed_enabled = true; ++ } else { ++ cfg->configured_mask = bm; ++ cfg->fixed_enabled = false; ++ } + } ++ + mutex_unlock(&common->mutex); + + return 0; +@@ -1378,46 +1389,6 @@ void rsi_indicate_pkt_to_os(struct rsi_common *common, + ieee80211_rx_irqsafe(hw, skb); + } + +-static void rsi_set_min_rate(struct ieee80211_hw *hw, +- struct ieee80211_sta *sta, +- struct rsi_common *common) +-{ +- u8 band = hw->conf.chandef.chan->band; +- u8 ii; +- u32 rate_bitmap; +- bool matched = false; +- +- common->bitrate_mask[band] = sta->supp_rates[band]; +- +- rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]); +- +- if (rate_bitmap & 0xfff) { +- /* Find out the min rate */ +- for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) { +- if (rate_bitmap & BIT(ii)) { +- common->min_rate = rsi_rates[ii].hw_value; +- matched = true; +- break; +- } +- } +- } +- +- common->vif_info[0].is_ht = sta->ht_cap.ht_supported; +- +- if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) { +- for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) { +- if ((rate_bitmap >> 12) & BIT(ii)) { +- common->min_rate = rsi_mcsrates[ii]; +- matched = true; +- break; +- } +- } +- } +- +- if (!matched) +- common->min_rate = 0xffff; +-} +- + /** + * rsi_mac80211_sta_add() - This function notifies driver about a peer getting + * connected. +@@ -1516,9 +1487,9 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw, + + if ((vif->type == NL80211_IFTYPE_STATION) || + (vif->type == NL80211_IFTYPE_P2P_CLIENT)) { +- rsi_set_min_rate(hw, sta, common); ++ common->bitrate_mask[common->band] = sta->supp_rates[common->band]; ++ common->vif_info[0].is_ht = sta->ht_cap.ht_supported; + if (sta->ht_cap.ht_supported) { +- common->vif_info[0].is_ht = true; + common->bitrate_mask[NL80211_BAND_2GHZ] = + sta->supp_rates[NL80211_BAND_2GHZ]; + if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) || +@@ -1592,7 +1563,6 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw, + bss->qos = sta->wme; + common->bitrate_mask[NL80211_BAND_2GHZ] = 0; + common->bitrate_mask[NL80211_BAND_5GHZ] = 0; +- common->min_rate = 0xffff; + common->vif_info[0].is_ht = false; + common->vif_info[0].sgi = false; + common->vif_info[0].seq_start = 0; +diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c +index d98483298555c..5d1490fc32db4 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_main.c ++++ b/drivers/net/wireless/rsi/rsi_91x_main.c +@@ -23,6 +23,7 @@ + #include "rsi_common.h" + #include "rsi_coex.h" + #include "rsi_hal.h" ++#include "rsi_usb.h" + + u32 rsi_zone_enabled = /* INFO_ZONE | + INIT_ZONE | +@@ -168,6 +169,9 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len) + frame_desc = &rx_pkt[index]; + actual_length = *(u16 *)&frame_desc[0]; + offset = *(u16 *)&frame_desc[2]; ++ if (!rcv_pkt_len && offset > ++ RSI_MAX_RX_USB_PKT_SIZE - FRAME_DESC_SZ) ++ goto fail; + + queueno = rsi_get_queueno(frame_desc, offset); + length = rsi_get_length(frame_desc, offset); +@@ -211,9 +215,10 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len) + bt_pkt_type = frame_desc[offset + BT_RX_PKT_TYPE_OFST]; + if (bt_pkt_type == BT_CARD_READY_IND) { + rsi_dbg(INFO_ZONE, "BT Card ready recvd\n"); +- if (rsi_bt_ops.attach(common, &g_proto_ops)) +- rsi_dbg(ERR_ZONE, +- "Failed to attach BT module\n"); ++ if (common->fsm_state == FSM_MAC_INIT_DONE) ++ rsi_attach_bt(common); ++ else ++ common->bt_defer_attach = true; + } else { + if (common->bt_adapter) + rsi_bt_ops.recv_pkt(common->bt_adapter, +@@ -278,6 +283,15 @@ void rsi_set_bt_context(void *priv, void *bt_context) + } + #endif + ++void rsi_attach_bt(struct rsi_common *common) ++{ ++#ifdef CONFIG_RSI_COEX ++ if (rsi_bt_ops.attach(common, &g_proto_ops)) ++ rsi_dbg(ERR_ZONE, ++ "Failed to attach BT module\n"); ++#endif ++} ++ + /** + * rsi_91x_init() - This function initializes os interface operations. + * @oper_mode: One of DEV_OPMODE_*. +@@ -359,6 +373,7 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode) + if (common->coex_mode > 1) { + if (rsi_coex_attach(common)) { + rsi_dbg(ERR_ZONE, "Failed to init coex module\n"); ++ rsi_kill_thread(&common->tx_thread); + goto err; + } + } +diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c +index 891fd5f0fa765..0848f7a7e76c6 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c ++++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c +@@ -276,7 +276,7 @@ static void rsi_set_default_parameters(struct rsi_common *common) + common->channel_width = BW_20MHZ; + common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; + common->channel = 1; +- common->min_rate = 0xffff; ++ memset(&common->rate_config, 0, sizeof(common->rate_config)); + common->fsm_state = FSM_CARD_NOT_READY; + common->iface_down = true; + common->endpoint = EP_2GHZ_20MHZ; +@@ -1314,7 +1314,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common, + u8 band = hw->conf.chandef.chan->band; + u8 num_supported_rates = 0; + u8 rate_table_offset, rate_offset = 0; +- u32 rate_bitmap; ++ u32 rate_bitmap, configured_rates; + u16 *selected_rates, min_rate; + bool is_ht = false, is_sgi = false; + u16 frame_len = sizeof(struct rsi_auto_rate); +@@ -1364,6 +1364,10 @@ static int rsi_send_auto_rate_request(struct rsi_common *common, + is_sgi = true; + } + ++ /* Limit to any rates administratively configured by cfg80211 */ ++ configured_rates = common->rate_config[band].configured_mask ?: 0xffffffff; ++ rate_bitmap &= configured_rates; ++ + if (band == NL80211_BAND_2GHZ) { + if ((rate_bitmap == 0) && (is_ht)) + min_rate = RSI_RATE_MCS0; +@@ -1389,10 +1393,13 @@ static int rsi_send_auto_rate_request(struct rsi_common *common, + num_supported_rates = jj; + + if (is_ht) { +- for (ii = 0; ii < ARRAY_SIZE(mcs); ii++) +- selected_rates[jj++] = mcs[ii]; +- num_supported_rates += ARRAY_SIZE(mcs); +- rate_offset += ARRAY_SIZE(mcs); ++ for (ii = 0; ii < ARRAY_SIZE(mcs); ii++) { ++ if (configured_rates & BIT(ii + ARRAY_SIZE(rsi_rates))) { ++ selected_rates[jj++] = mcs[ii]; ++ num_supported_rates++; ++ rate_offset++; ++ } ++ } + } + + sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL); +@@ -1482,7 +1489,7 @@ void rsi_inform_bss_status(struct rsi_common *common, + qos_enable, + aid, sta_id, + vif); +- if (common->min_rate == 0xffff) ++ if (!common->rate_config[common->band].fixed_enabled) + rsi_send_auto_rate_request(common, sta, sta_id, vif); + if (opmode == RSI_OPMODE_STA && + !(assoc_cap & WLAN_CAPABILITY_PRIVACY) && +@@ -2071,6 +2078,9 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, + if (common->reinit_hw) { + complete(&common->wlan_init_completion); + } else { ++ if (common->bt_defer_attach) ++ rsi_attach_bt(common); ++ + return rsi_mac80211_attach(common); + } + } +diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c +index e0c502bc42707..9f16128e4ffab 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c ++++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c +@@ -24,10 +24,7 @@ + /* Default operating mode is wlan STA + BT */ + static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL; + module_param(dev_oper_mode, ushort, 0444); +-MODULE_PARM_DESC(dev_oper_mode, +- "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n" +- "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n" +- "6[AP + BT classic], 14[AP + BT classic + BT LE]"); ++MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC); + + /** + * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg. +diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c +index 416976f098882..66fe386ec9cc6 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_usb.c ++++ b/drivers/net/wireless/rsi/rsi_91x_usb.c +@@ -25,10 +25,7 @@ + /* Default operating mode is wlan STA + BT */ + static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL; + module_param(dev_oper_mode, ushort, 0444); +-MODULE_PARM_DESC(dev_oper_mode, +- "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n" +- "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n" +- "6[AP + BT classic], 14[AP + BT classic + BT LE]"); ++MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC); + + static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t flags); + +@@ -61,7 +58,7 @@ static int rsi_usb_card_write(struct rsi_hw *adapter, + (void *)seg, + (int)len, + &transfer, +- HZ * 5); ++ USB_CTRL_SET_TIMEOUT); + + if (status < 0) { + rsi_dbg(ERR_ZONE, +@@ -272,8 +269,12 @@ static void rsi_rx_done_handler(struct urb *urb) + struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data; + int status = -EINVAL; + ++ if (!rx_cb->rx_skb) ++ return; ++ + if (urb->status) { + dev_kfree_skb(rx_cb->rx_skb); ++ rx_cb->rx_skb = NULL; + return; + } + +@@ -297,8 +298,10 @@ out: + if (rsi_rx_urb_submit(dev->priv, rx_cb->ep_num, GFP_ATOMIC)) + rsi_dbg(ERR_ZONE, "%s: Failed in urb submission", __func__); + +- if (status) ++ if (status) { + dev_kfree_skb(rx_cb->rx_skb); ++ rx_cb->rx_skb = NULL; ++ } + } + + static void rsi_rx_urb_kill(struct rsi_hw *adapter, u8 ep_num) +@@ -327,7 +330,6 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t mem_flags) + struct sk_buff *skb; + u8 dword_align_bytes = 0; + +-#define RSI_MAX_RX_USB_PKT_SIZE 3000 + skb = dev_alloc_skb(RSI_MAX_RX_USB_PKT_SIZE); + if (!skb) + return -ENOMEM; +diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h +index d044a440fa080..5b07262a97408 100644 +--- a/drivers/net/wireless/rsi/rsi_hal.h ++++ b/drivers/net/wireless/rsi/rsi_hal.h +@@ -28,6 +28,17 @@ + #define DEV_OPMODE_AP_BT 6 + #define DEV_OPMODE_AP_BT_DUAL 14 + ++#define DEV_OPMODE_PARAM_DESC \ ++ __stringify(DEV_OPMODE_WIFI_ALONE) "[Wi-Fi alone], " \ ++ __stringify(DEV_OPMODE_BT_ALONE) "[BT classic alone], " \ ++ __stringify(DEV_OPMODE_BT_LE_ALONE) "[BT LE alone], " \ ++ __stringify(DEV_OPMODE_BT_DUAL) "[BT classic + BT LE alone], " \ ++ __stringify(DEV_OPMODE_STA_BT) "[Wi-Fi STA + BT classic], " \ ++ __stringify(DEV_OPMODE_STA_BT_LE) "[Wi-Fi STA + BT LE], " \ ++ __stringify(DEV_OPMODE_STA_BT_DUAL) "[Wi-Fi STA + BT classic + BT LE], " \ ++ __stringify(DEV_OPMODE_AP_BT) "[Wi-Fi AP + BT classic], " \ ++ __stringify(DEV_OPMODE_AP_BT_DUAL) "[Wi-Fi AP + BT classic + BT LE]" ++ + #define FLASH_WRITE_CHUNK_SIZE (4 * 1024) + #define FLASH_SECTOR_SIZE (4 * 1024) + +diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h +index 0f535850a3836..dcf8fb40698b7 100644 +--- a/drivers/net/wireless/rsi/rsi_main.h ++++ b/drivers/net/wireless/rsi/rsi_main.h +@@ -61,6 +61,7 @@ enum RSI_FSM_STATES { + extern u32 rsi_zone_enabled; + extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...); + ++#define RSI_MAX_BANDS 2 + #define RSI_MAX_VIFS 3 + #define NUM_EDCA_QUEUES 4 + #define IEEE80211_ADDR_LEN 6 +@@ -139,6 +140,7 @@ struct skb_info { + u8 internal_hdr_size; + struct ieee80211_vif *vif; + u8 vap_id; ++ bool have_key; + }; + + enum edca_queue { +@@ -229,6 +231,12 @@ struct rsi_9116_features { + u32 ps_options; + }; + ++struct rsi_rate_config { ++ u32 configured_mask; /* configured by mac80211 bits 0-11=legacy 12+ mcs */ ++ u16 fixed_hw_rate; ++ bool fixed_enabled; ++}; ++ + struct rsi_common { + struct rsi_hw *priv; + struct vif_priv vif_info[RSI_MAX_VIFS]; +@@ -254,8 +262,8 @@ struct rsi_common { + u8 channel_width; + + u16 rts_threshold; +- u16 bitrate_mask[2]; +- u32 fixedrate_mask[2]; ++ u32 bitrate_mask[RSI_MAX_BANDS]; ++ struct rsi_rate_config rate_config[RSI_MAX_BANDS]; + + u8 rf_reset; + struct transmit_q_stats tx_stats; +@@ -276,7 +284,6 @@ struct rsi_common { + u8 mac_id; + u8 radio_id; + u16 rate_pwr[20]; +- u16 min_rate; + + /* WMM algo related */ + u8 selected_qnum; +@@ -320,6 +327,7 @@ struct rsi_common { + struct ieee80211_vif *roc_vif; + + bool eapol4_confirm; ++ bool bt_defer_attach; + void *bt_adapter; + + struct cfg80211_scan_request *hwscan; +@@ -401,5 +409,6 @@ struct rsi_host_intf_ops { + + enum rsi_host_intf rsi_get_host_intf(void *priv); + void rsi_set_bt_context(void *priv, void *bt_context); ++void rsi_attach_bt(struct rsi_common *common); + + #endif +diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h +index 254d19b664123..961851748bc4c 100644 +--- a/drivers/net/wireless/rsi/rsi_usb.h ++++ b/drivers/net/wireless/rsi/rsi_usb.h +@@ -44,6 +44,8 @@ + #define RSI_USB_BUF_SIZE 4096 + #define RSI_USB_CTRL_BUF_SIZE 0x04 + ++#define RSI_MAX_RX_USB_PKT_SIZE 3000 ++ + struct rx_usb_ctrl_block { + u8 *data; + struct urb *rx_urb; +diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c +index 71bf9b4f769f5..6872782e8dd89 100644 +--- a/drivers/net/wwan/mhi_wwan_mbim.c ++++ b/drivers/net/wwan/mhi_wwan_mbim.c +@@ -385,13 +385,13 @@ static void mhi_net_rx_refill_work(struct work_struct *work) + int err; + + while (!mhi_queue_is_full(mdev, DMA_FROM_DEVICE)) { +- struct sk_buff *skb = alloc_skb(MHI_DEFAULT_MRU, GFP_KERNEL); ++ struct sk_buff *skb = alloc_skb(mbim->mru, GFP_KERNEL); + + if (unlikely(!skb)) + break; + + err = mhi_queue_skb(mdev, DMA_FROM_DEVICE, skb, +- MHI_DEFAULT_MRU, MHI_EOT); ++ mbim->mru, MHI_EOT); + if (unlikely(err)) { + kfree_skb(skb); + break; +diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h +index 4a16d6e33c093..d9dea4829c86e 100644 +--- a/drivers/net/xen-netback/common.h ++++ b/drivers/net/xen-netback/common.h +@@ -203,6 +203,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */ + unsigned int rx_queue_max; + unsigned int rx_queue_len; + unsigned long last_rx_time; ++ unsigned int rx_slots_needed; + bool stalled; + + struct xenvif_copy_state rx_copy; +diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c +index accc991d153f7..dbac4c03d21a1 100644 +--- a/drivers/net/xen-netback/rx.c ++++ b/drivers/net/xen-netback/rx.c +@@ -33,28 +33,36 @@ + #include <xen/xen.h> + #include <xen/events.h> + +-static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) ++/* ++ * Update the needed ring page slots for the first SKB queued. ++ * Note that any call sequence outside the RX thread calling this function ++ * needs to wake up the RX thread via a call of xenvif_kick_thread() ++ * afterwards in order to avoid a race with putting the thread to sleep. ++ */ ++static void xenvif_update_needed_slots(struct xenvif_queue *queue, ++ const struct sk_buff *skb) + { +- RING_IDX prod, cons; +- struct sk_buff *skb; +- int needed; +- unsigned long flags; +- +- spin_lock_irqsave(&queue->rx_queue.lock, flags); ++ unsigned int needed = 0; + +- skb = skb_peek(&queue->rx_queue); +- if (!skb) { +- spin_unlock_irqrestore(&queue->rx_queue.lock, flags); +- return false; ++ if (skb) { ++ needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); ++ if (skb_is_gso(skb)) ++ needed++; ++ if (skb->sw_hash) ++ needed++; + } + +- needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); +- if (skb_is_gso(skb)) +- needed++; +- if (skb->sw_hash) +- needed++; ++ WRITE_ONCE(queue->rx_slots_needed, needed); ++} + +- spin_unlock_irqrestore(&queue->rx_queue.lock, flags); ++static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) ++{ ++ RING_IDX prod, cons; ++ unsigned int needed; ++ ++ needed = READ_ONCE(queue->rx_slots_needed); ++ if (!needed) ++ return false; + + do { + prod = queue->rx.sring->req_prod; +@@ -80,13 +88,19 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb) + + spin_lock_irqsave(&queue->rx_queue.lock, flags); + +- __skb_queue_tail(&queue->rx_queue, skb); +- +- queue->rx_queue_len += skb->len; +- if (queue->rx_queue_len > queue->rx_queue_max) { ++ if (queue->rx_queue_len >= queue->rx_queue_max) { + struct net_device *dev = queue->vif->dev; + + netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id)); ++ kfree_skb(skb); ++ queue->vif->dev->stats.rx_dropped++; ++ } else { ++ if (skb_queue_empty(&queue->rx_queue)) ++ xenvif_update_needed_slots(queue, skb); ++ ++ __skb_queue_tail(&queue->rx_queue, skb); ++ ++ queue->rx_queue_len += skb->len; + } + + spin_unlock_irqrestore(&queue->rx_queue.lock, flags); +@@ -100,6 +114,8 @@ static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue) + + skb = __skb_dequeue(&queue->rx_queue); + if (skb) { ++ xenvif_update_needed_slots(queue, skb_peek(&queue->rx_queue)); ++ + queue->rx_queue_len -= skb->len; + if (queue->rx_queue_len < queue->rx_queue_max) { + struct netdev_queue *txq; +@@ -134,6 +150,7 @@ static void xenvif_rx_queue_drop_expired(struct xenvif_queue *queue) + break; + xenvif_rx_dequeue(queue); + kfree_skb(skb); ++ queue->vif->dev->stats.rx_dropped++; + } + } + +@@ -487,27 +504,31 @@ void xenvif_rx_action(struct xenvif_queue *queue) + xenvif_rx_copy_flush(queue); + } + +-static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue) ++static RING_IDX xenvif_rx_queue_slots(const struct xenvif_queue *queue) + { + RING_IDX prod, cons; + + prod = queue->rx.sring->req_prod; + cons = queue->rx.req_cons; + ++ return prod - cons; ++} ++ ++static bool xenvif_rx_queue_stalled(const struct xenvif_queue *queue) ++{ ++ unsigned int needed = READ_ONCE(queue->rx_slots_needed); ++ + return !queue->stalled && +- prod - cons < 1 && ++ xenvif_rx_queue_slots(queue) < needed && + time_after(jiffies, + queue->last_rx_time + queue->vif->stall_timeout); + } + + static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) + { +- RING_IDX prod, cons; +- +- prod = queue->rx.sring->req_prod; +- cons = queue->rx.req_cons; ++ unsigned int needed = READ_ONCE(queue->rx_slots_needed); + +- return queue->stalled && prod - cons >= 1; ++ return queue->stalled && xenvif_rx_queue_slots(queue) >= needed; + } + + bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread) +diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c +index fc41ba95f81d0..2492a27467b46 100644 +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -148,6 +148,9 @@ struct netfront_queue { + grant_ref_t gref_rx_head; + grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; + ++ unsigned int rx_rsp_unconsumed; ++ spinlock_t rx_cons_lock; ++ + struct page_pool *page_pool; + struct xdp_rxq_info xdp_rxq; + }; +@@ -376,12 +379,13 @@ static int xennet_open(struct net_device *dev) + return 0; + } + +-static void xennet_tx_buf_gc(struct netfront_queue *queue) ++static bool xennet_tx_buf_gc(struct netfront_queue *queue) + { + RING_IDX cons, prod; + unsigned short id; + struct sk_buff *skb; + bool more_to_do; ++ bool work_done = false; + const struct device *dev = &queue->info->netdev->dev; + + BUG_ON(!netif_carrier_ok(queue->info->netdev)); +@@ -398,6 +402,8 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) + for (cons = queue->tx.rsp_cons; cons != prod; cons++) { + struct xen_netif_tx_response txrsp; + ++ work_done = true; ++ + RING_COPY_RESPONSE(&queue->tx, cons, &txrsp); + if (txrsp.status == XEN_NETIF_RSP_NULL) + continue; +@@ -418,14 +424,12 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) + queue->tx_link[id] = TX_LINK_NONE; + skb = queue->tx_skbs[id]; + queue->tx_skbs[id] = NULL; +- if (unlikely(gnttab_query_foreign_access( +- queue->grant_tx_ref[id]) != 0)) { ++ if (unlikely(!gnttab_end_foreign_access_ref( ++ queue->grant_tx_ref[id], GNTMAP_readonly))) { + dev_alert(dev, + "Grant still in use by backend domain\n"); + goto err; + } +- gnttab_end_foreign_access_ref( +- queue->grant_tx_ref[id], GNTMAP_readonly); + gnttab_release_grant_reference( + &queue->gref_tx_head, queue->grant_tx_ref[id]); + queue->grant_tx_ref[id] = GRANT_INVALID_REF; +@@ -441,11 +445,13 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) + + xennet_maybe_wake_tx(queue); + +- return; ++ return work_done; + + err: + queue->info->broken = true; + dev_alert(dev, "Disabled for further use\n"); ++ ++ return work_done; + } + + struct xennet_gnttab_make_txreq { +@@ -834,6 +840,38 @@ static int xennet_close(struct net_device *dev) + return 0; + } + ++static void xennet_destroy_queues(struct netfront_info *info) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < info->netdev->real_num_tx_queues; i++) { ++ struct netfront_queue *queue = &info->queues[i]; ++ ++ if (netif_running(info->netdev)) ++ napi_disable(&queue->napi); ++ netif_napi_del(&queue->napi); ++ } ++ ++ kfree(info->queues); ++ info->queues = NULL; ++} ++ ++static void xennet_uninit(struct net_device *dev) ++{ ++ struct netfront_info *np = netdev_priv(dev); ++ xennet_destroy_queues(np); ++} ++ ++static void xennet_set_rx_rsp_cons(struct netfront_queue *queue, RING_IDX val) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&queue->rx_cons_lock, flags); ++ queue->rx.rsp_cons = val; ++ queue->rx_rsp_unconsumed = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx); ++ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); ++} ++ + static void xennet_move_rx_slot(struct netfront_queue *queue, struct sk_buff *skb, + grant_ref_t ref) + { +@@ -885,7 +923,7 @@ static int xennet_get_extras(struct netfront_queue *queue, + xennet_move_rx_slot(queue, skb, ref); + } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); + +- queue->rx.rsp_cons = cons; ++ xennet_set_rx_rsp_cons(queue, cons); + return err; + } + +@@ -950,7 +988,6 @@ static int xennet_get_responses(struct netfront_queue *queue, + struct device *dev = &queue->info->netdev->dev; + struct bpf_prog *xdp_prog; + struct xdp_buff xdp; +- unsigned long ret; + int slots = 1; + int err = 0; + u32 verdict; +@@ -992,8 +1029,13 @@ static int xennet_get_responses(struct netfront_queue *queue, + goto next; + } + +- ret = gnttab_end_foreign_access_ref(ref, 0); +- BUG_ON(!ret); ++ if (!gnttab_end_foreign_access_ref(ref, 0)) { ++ dev_alert(dev, ++ "Grant still in use by backend domain\n"); ++ queue->info->broken = true; ++ dev_alert(dev, "Disabled for further use\n"); ++ return -EINVAL; ++ } + + gnttab_release_grant_reference(&queue->gref_rx_head, ref); + +@@ -1039,7 +1081,7 @@ next: + } + + if (unlikely(err)) +- queue->rx.rsp_cons = cons + slots; ++ xennet_set_rx_rsp_cons(queue, cons + slots); + + return err; + } +@@ -1093,7 +1135,8 @@ static int xennet_fill_frags(struct netfront_queue *queue, + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); + } + if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) { +- queue->rx.rsp_cons = ++cons + skb_queue_len(list); ++ xennet_set_rx_rsp_cons(queue, ++ ++cons + skb_queue_len(list)); + kfree_skb(nskb); + return -ENOENT; + } +@@ -1106,7 +1149,7 @@ static int xennet_fill_frags(struct netfront_queue *queue, + kfree_skb(nskb); + } + +- queue->rx.rsp_cons = cons; ++ xennet_set_rx_rsp_cons(queue, cons); + + return 0; + } +@@ -1213,6 +1256,10 @@ static int xennet_poll(struct napi_struct *napi, int budget) + &need_xdp_flush); + + if (unlikely(err)) { ++ if (queue->info->broken) { ++ spin_unlock(&queue->rx_lock); ++ return 0; ++ } + err: + while ((skb = __skb_dequeue(&tmpq))) + __skb_queue_tail(&errq, skb); +@@ -1229,7 +1276,9 @@ err: + + if (unlikely(xennet_set_skb_gso(skb, gso))) { + __skb_queue_head(&tmpq, skb); +- queue->rx.rsp_cons += skb_queue_len(&tmpq); ++ xennet_set_rx_rsp_cons(queue, ++ queue->rx.rsp_cons + ++ skb_queue_len(&tmpq)); + goto err; + } + } +@@ -1253,7 +1302,8 @@ err: + + __skb_queue_tail(&rxq, skb); + +- i = ++queue->rx.rsp_cons; ++ i = queue->rx.rsp_cons + 1; ++ xennet_set_rx_rsp_cons(queue, i); + work_done++; + } + if (need_xdp_flush) +@@ -1417,40 +1467,79 @@ static int xennet_set_features(struct net_device *dev, + return 0; + } + +-static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) ++static bool xennet_handle_tx(struct netfront_queue *queue, unsigned int *eoi) + { +- struct netfront_queue *queue = dev_id; + unsigned long flags; + +- if (queue->info->broken) +- return IRQ_HANDLED; ++ if (unlikely(queue->info->broken)) ++ return false; + + spin_lock_irqsave(&queue->tx_lock, flags); +- xennet_tx_buf_gc(queue); ++ if (xennet_tx_buf_gc(queue)) ++ *eoi = 0; + spin_unlock_irqrestore(&queue->tx_lock, flags); + ++ return true; ++} ++ ++static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) ++{ ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ ++ if (likely(xennet_handle_tx(dev_id, &eoiflag))) ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + } + +-static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) ++static bool xennet_handle_rx(struct netfront_queue *queue, unsigned int *eoi) + { +- struct netfront_queue *queue = dev_id; +- struct net_device *dev = queue->info->netdev; ++ unsigned int work_queued; ++ unsigned long flags; ++ ++ if (unlikely(queue->info->broken)) ++ return false; + +- if (queue->info->broken) +- return IRQ_HANDLED; ++ spin_lock_irqsave(&queue->rx_cons_lock, flags); ++ work_queued = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx); ++ if (work_queued > queue->rx_rsp_unconsumed) { ++ queue->rx_rsp_unconsumed = work_queued; ++ *eoi = 0; ++ } else if (unlikely(work_queued < queue->rx_rsp_unconsumed)) { ++ const struct device *dev = &queue->info->netdev->dev; ++ ++ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); ++ dev_alert(dev, "RX producer index going backwards\n"); ++ dev_alert(dev, "Disabled for further use\n"); ++ queue->info->broken = true; ++ return false; ++ } ++ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); + +- if (likely(netif_carrier_ok(dev) && +- RING_HAS_UNCONSUMED_RESPONSES(&queue->rx))) ++ if (likely(netif_carrier_ok(queue->info->netdev) && work_queued)) + napi_schedule(&queue->napi); + ++ return true; ++} ++ ++static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) ++{ ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ ++ if (likely(xennet_handle_rx(dev_id, &eoiflag))) ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + } + + static irqreturn_t xennet_interrupt(int irq, void *dev_id) + { +- xennet_tx_interrupt(irq, dev_id); +- xennet_rx_interrupt(irq, dev_id); ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ ++ if (xennet_handle_tx(dev_id, &eoiflag) && ++ xennet_handle_rx(dev_id, &eoiflag)) ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + } + +@@ -1550,6 +1639,7 @@ static int xennet_xdp(struct net_device *dev, struct netdev_bpf *xdp) + } + + static const struct net_device_ops xennet_netdev_ops = { ++ .ndo_uninit = xennet_uninit, + .ndo_open = xennet_open, + .ndo_stop = xennet_close, + .ndo_start_xmit = xennet_start_xmit, +@@ -1768,9 +1858,10 @@ static int setup_netfront_single(struct netfront_queue *queue) + if (err < 0) + goto fail; + +- err = bind_evtchn_to_irqhandler(queue->tx_evtchn, +- xennet_interrupt, +- 0, queue->info->netdev->name, queue); ++ err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn, ++ xennet_interrupt, 0, ++ queue->info->netdev->name, ++ queue); + if (err < 0) + goto bind_fail; + queue->rx_evtchn = queue->tx_evtchn; +@@ -1798,18 +1889,18 @@ static int setup_netfront_split(struct netfront_queue *queue) + + snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), + "%s-tx", queue->name); +- err = bind_evtchn_to_irqhandler(queue->tx_evtchn, +- xennet_tx_interrupt, +- 0, queue->tx_irq_name, queue); ++ err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn, ++ xennet_tx_interrupt, 0, ++ queue->tx_irq_name, queue); + if (err < 0) + goto bind_tx_fail; + queue->tx_irq = err; + + snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), + "%s-rx", queue->name); +- err = bind_evtchn_to_irqhandler(queue->rx_evtchn, +- xennet_rx_interrupt, +- 0, queue->rx_irq_name, queue); ++ err = bind_evtchn_to_irqhandler_lateeoi(queue->rx_evtchn, ++ xennet_rx_interrupt, 0, ++ queue->rx_irq_name, queue); + if (err < 0) + goto bind_rx_fail; + queue->rx_irq = err; +@@ -1833,7 +1924,7 @@ static int setup_netfront(struct xenbus_device *dev, + struct netfront_queue *queue, unsigned int feature_split_evtchn) + { + struct xen_netif_tx_sring *txs; +- struct xen_netif_rx_sring *rxs; ++ struct xen_netif_rx_sring *rxs = NULL; + grant_ref_t gref; + int err; + +@@ -1853,21 +1944,21 @@ static int setup_netfront(struct xenbus_device *dev, + + err = xenbus_grant_ring(dev, txs, 1, &gref); + if (err < 0) +- goto grant_tx_ring_fail; ++ goto fail; + queue->tx_ring_ref = gref; + + rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH); + if (!rxs) { + err = -ENOMEM; + xenbus_dev_fatal(dev, err, "allocating rx ring page"); +- goto alloc_rx_ring_fail; ++ goto fail; + } + SHARED_RING_INIT(rxs); + FRONT_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE); + + err = xenbus_grant_ring(dev, rxs, 1, &gref); + if (err < 0) +- goto grant_rx_ring_fail; ++ goto fail; + queue->rx_ring_ref = gref; + + if (feature_split_evtchn) +@@ -1880,22 +1971,28 @@ static int setup_netfront(struct xenbus_device *dev, + err = setup_netfront_single(queue); + + if (err) +- goto alloc_evtchn_fail; ++ goto fail; + + return 0; + + /* If we fail to setup netfront, it is safe to just revoke access to + * granted pages because backend is not accessing it at this point. + */ +-alloc_evtchn_fail: +- gnttab_end_foreign_access_ref(queue->rx_ring_ref, 0); +-grant_rx_ring_fail: +- free_page((unsigned long)rxs); +-alloc_rx_ring_fail: +- gnttab_end_foreign_access_ref(queue->tx_ring_ref, 0); +-grant_tx_ring_fail: +- free_page((unsigned long)txs); +-fail: ++ fail: ++ if (queue->rx_ring_ref != GRANT_INVALID_REF) { ++ gnttab_end_foreign_access(queue->rx_ring_ref, 0, ++ (unsigned long)rxs); ++ queue->rx_ring_ref = GRANT_INVALID_REF; ++ } else { ++ free_page((unsigned long)rxs); ++ } ++ if (queue->tx_ring_ref != GRANT_INVALID_REF) { ++ gnttab_end_foreign_access(queue->tx_ring_ref, 0, ++ (unsigned long)txs); ++ queue->tx_ring_ref = GRANT_INVALID_REF; ++ } else { ++ free_page((unsigned long)txs); ++ } + return err; + } + +@@ -1911,6 +2008,7 @@ static int xennet_init_queue(struct netfront_queue *queue) + + spin_lock_init(&queue->tx_lock); + spin_lock_init(&queue->rx_lock); ++ spin_lock_init(&queue->rx_cons_lock); + + timer_setup(&queue->rx_refill_timer, rx_refill_timeout, 0); + +@@ -2040,22 +2138,6 @@ error: + return err; + } + +-static void xennet_destroy_queues(struct netfront_info *info) +-{ +- unsigned int i; +- +- for (i = 0; i < info->netdev->real_num_tx_queues; i++) { +- struct netfront_queue *queue = &info->queues[i]; +- +- if (netif_running(info->netdev)) +- napi_disable(&queue->napi); +- netif_napi_del(&queue->napi); +- } +- +- kfree(info->queues); +- info->queues = NULL; +-} +- + + + static int xennet_create_page_pool(struct netfront_queue *queue) +diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c +index 2f3f3fe9a0baa..d32aec0c334fe 100644 +--- a/drivers/nfc/pn533/pn533.c ++++ b/drivers/nfc/pn533/pn533.c +@@ -2218,7 +2218,7 @@ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) + frag = pn533_alloc_skb(dev, frag_size); + if (!frag) { + skb_queue_purge(&dev->fragment_skb); +- break; ++ return -ENOMEM; + } + + if (!dev->tgt_mode) { +@@ -2287,7 +2287,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, + /* jumbo frame ? */ + if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { + rc = pn533_fill_fragment_skbs(dev, skb); +- if (rc <= 0) ++ if (rc < 0) + goto error; + + skb = skb_dequeue(&dev->fragment_skb); +@@ -2355,7 +2355,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) + /* let's split in multiple chunks if size's too big */ + if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { + rc = pn533_fill_fragment_skbs(dev, skb); +- if (rc <= 0) ++ if (rc < 0) + goto error; + + /* get the first skb */ +diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c +index 279d88128b2e4..d56bc24709b5c 100644 +--- a/drivers/nfc/st21nfca/i2c.c ++++ b/drivers/nfc/st21nfca/i2c.c +@@ -528,7 +528,8 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, + phy->gpiod_ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_ena)) { + nfc_err(dev, "Unable to get ENABLE GPIO\n"); +- return PTR_ERR(phy->gpiod_ena); ++ r = PTR_ERR(phy->gpiod_ena); ++ goto out_free; + } + + phy->se_status.is_ese_present = +@@ -539,7 +540,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, + r = st21nfca_hci_platform_init(phy); + if (r < 0) { + nfc_err(&client->dev, "Unable to reboot st21nfca\n"); +- return r; ++ goto out_free; + } + + r = devm_request_threaded_irq(&client->dev, client->irq, NULL, +@@ -548,15 +549,23 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, + ST21NFCA_HCI_DRIVER_NAME, phy); + if (r < 0) { + nfc_err(&client->dev, "Unable to register IRQ handler\n"); +- return r; ++ goto out_free; + } + +- return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, +- ST21NFCA_FRAME_HEADROOM, +- ST21NFCA_FRAME_TAILROOM, +- ST21NFCA_HCI_LLC_MAX_PAYLOAD, +- &phy->hdev, +- &phy->se_status); ++ r = st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, ++ ST21NFCA_FRAME_HEADROOM, ++ ST21NFCA_FRAME_TAILROOM, ++ ST21NFCA_HCI_LLC_MAX_PAYLOAD, ++ &phy->hdev, ++ &phy->se_status); ++ if (r) ++ goto out_free; ++ ++ return 0; ++ ++out_free: ++ kfree_skb(phy->pending_skb); ++ return r; + } + + static int st21nfca_hci_i2c_remove(struct i2c_client *client) +@@ -567,6 +576,8 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client) + + if (phy->powered) + st21nfca_hci_i2c_disable(phy); ++ if (phy->pending_skb) ++ kfree_skb(phy->pending_skb); + + return 0; + } +diff --git a/drivers/ntb/hw/intel/ntb_hw_gen4.c b/drivers/ntb/hw/intel/ntb_hw_gen4.c +index fede05151f698..4081fc538ff45 100644 +--- a/drivers/ntb/hw/intel/ntb_hw_gen4.c ++++ b/drivers/ntb/hw/intel/ntb_hw_gen4.c +@@ -168,6 +168,18 @@ static enum ntb_topo gen4_ppd_topo(struct intel_ntb_dev *ndev, u32 ppd) + return NTB_TOPO_NONE; + } + ++static enum ntb_topo spr_ppd_topo(struct intel_ntb_dev *ndev, u32 ppd) ++{ ++ switch (ppd & SPR_PPD_TOPO_MASK) { ++ case SPR_PPD_TOPO_B2B_USD: ++ return NTB_TOPO_B2B_USD; ++ case SPR_PPD_TOPO_B2B_DSD: ++ return NTB_TOPO_B2B_DSD; ++ } ++ ++ return NTB_TOPO_NONE; ++} ++ + int gen4_init_dev(struct intel_ntb_dev *ndev) + { + struct pci_dev *pdev = ndev->ntb.pdev; +@@ -183,7 +195,10 @@ int gen4_init_dev(struct intel_ntb_dev *ndev) + } + + ppd1 = ioread32(ndev->self_mmio + GEN4_PPD1_OFFSET); +- ndev->ntb.topo = gen4_ppd_topo(ndev, ppd1); ++ if (pdev_is_ICX(pdev)) ++ ndev->ntb.topo = gen4_ppd_topo(ndev, ppd1); ++ else if (pdev_is_SPR(pdev)) ++ ndev->ntb.topo = spr_ppd_topo(ndev, ppd1); + dev_dbg(&pdev->dev, "ppd %#x topo %s\n", ppd1, + ntb_topo_string(ndev->ntb.topo)); + if (ndev->ntb.topo == NTB_TOPO_NONE) +diff --git a/drivers/ntb/hw/intel/ntb_hw_gen4.h b/drivers/ntb/hw/intel/ntb_hw_gen4.h +index 3fcd3fdce9edf..f91323eaf5ce4 100644 +--- a/drivers/ntb/hw/intel/ntb_hw_gen4.h ++++ b/drivers/ntb/hw/intel/ntb_hw_gen4.h +@@ -49,10 +49,14 @@ + #define GEN4_PPD_CLEAR_TRN 0x0001 + #define GEN4_PPD_LINKTRN 0x0008 + #define GEN4_PPD_CONN_MASK 0x0300 ++#define SPR_PPD_CONN_MASK 0x0700 + #define GEN4_PPD_CONN_B2B 0x0200 + #define GEN4_PPD_DEV_MASK 0x1000 + #define GEN4_PPD_DEV_DSD 0x1000 + #define GEN4_PPD_DEV_USD 0x0000 ++#define SPR_PPD_DEV_MASK 0x4000 ++#define SPR_PPD_DEV_DSD 0x4000 ++#define SPR_PPD_DEV_USD 0x0000 + #define GEN4_LINK_CTRL_LINK_DISABLE 0x0010 + + #define GEN4_SLOTSTS 0xb05a +@@ -62,6 +66,10 @@ + #define GEN4_PPD_TOPO_B2B_USD (GEN4_PPD_CONN_B2B | GEN4_PPD_DEV_USD) + #define GEN4_PPD_TOPO_B2B_DSD (GEN4_PPD_CONN_B2B | GEN4_PPD_DEV_DSD) + ++#define SPR_PPD_TOPO_MASK (SPR_PPD_CONN_MASK | SPR_PPD_DEV_MASK) ++#define SPR_PPD_TOPO_B2B_USD (GEN4_PPD_CONN_B2B | SPR_PPD_DEV_USD) ++#define SPR_PPD_TOPO_B2B_DSD (GEN4_PPD_CONN_B2B | SPR_PPD_DEV_DSD) ++ + #define GEN4_DB_COUNT 32 + #define GEN4_DB_LINK 32 + #define GEN4_DB_LINK_BIT BIT_ULL(GEN4_DB_LINK) +@@ -112,4 +120,12 @@ static inline int pdev_is_ICX(struct pci_dev *pdev) + return 0; + } + ++static inline int pdev_is_SPR(struct pci_dev *pdev) ++{ ++ if (pdev_is_gen4(pdev) && ++ pdev->revision > PCI_DEVICE_REVISION_ICX_MAX) ++ return 1; ++ return 0; ++} ++ + #endif +diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +index 4c6eb61a6ac62..ec9cb6c81edae 100644 +--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c ++++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c +@@ -419,8 +419,8 @@ static void switchtec_ntb_part_link_speed(struct switchtec_ntb *sndev, + enum ntb_width *width) + { + struct switchtec_dev *stdev = sndev->stdev; +- +- u32 pff = ioread32(&stdev->mmio_part_cfg[partition].vep_pff_inst_id); ++ u32 pff = ++ ioread32(&stdev->mmio_part_cfg_all[partition].vep_pff_inst_id); + u32 linksta = ioread32(&stdev->mmio_pff_csr[pff].pci_cap_region[13]); + + if (speed) +@@ -840,7 +840,6 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev) + u64 tpart_vec; + int self; + u64 part_map; +- int bit; + + sndev->ntb.pdev = sndev->stdev->pdev; + sndev->ntb.topo = NTB_TOPO_SWITCH; +@@ -861,29 +860,28 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev) + part_map = ioread64(&sndev->mmio_ntb->ep_map); + part_map &= ~(1 << sndev->self_partition); + +- if (!ffs(tpart_vec)) { ++ if (!tpart_vec) { + if (sndev->stdev->partition_count != 2) { + dev_err(&sndev->stdev->dev, + "ntb target partition not defined\n"); + return -ENODEV; + } + +- bit = ffs(part_map); +- if (!bit) { ++ if (!part_map) { + dev_err(&sndev->stdev->dev, + "peer partition is not NT partition\n"); + return -ENODEV; + } + +- sndev->peer_partition = bit - 1; ++ sndev->peer_partition = __ffs64(part_map); + } else { +- if (ffs(tpart_vec) != fls(tpart_vec)) { ++ if (__ffs64(tpart_vec) != (fls64(tpart_vec) - 1)) { + dev_err(&sndev->stdev->dev, + "ntb driver only supports 1 pair of 1-1 ntb mapping\n"); + return -ENODEV; + } + +- sndev->peer_partition = ffs(tpart_vec) - 1; ++ sndev->peer_partition = __ffs64(tpart_vec); + if (!(part_map & (1ULL << sndev->peer_partition))) { + dev_err(&sndev->stdev->dev, + "ntb target partition is not NT partition\n"); +diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c +index 92dec49522972..3fd1bdb9fc05b 100644 +--- a/drivers/nvdimm/btt.c ++++ b/drivers/nvdimm/btt.c +@@ -1538,7 +1538,6 @@ static int btt_blk_init(struct btt *btt) + int rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt)); + + if (rc) { +- del_gendisk(btt->btt_disk); + blk_cleanup_disk(btt->btt_disk); + return rc; + } +diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c +index 054154c22899a..2721dd2ead0a7 100644 +--- a/drivers/nvdimm/pmem.c ++++ b/drivers/nvdimm/pmem.c +@@ -429,8 +429,10 @@ static int pmem_attach_disk(struct device *dev, + bb_range.end = res->end; + } + +- if (IS_ERR(addr)) +- return PTR_ERR(addr); ++ if (IS_ERR(addr)) { ++ rc = PTR_ERR(addr); ++ goto out; ++ } + pmem->virt_addr = addr; + + blk_queue_write_cache(q, true, fua); +@@ -455,7 +457,8 @@ static int pmem_attach_disk(struct device *dev, + flags = DAXDEV_F_SYNC; + dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags); + if (IS_ERR(dax_dev)) { +- return PTR_ERR(dax_dev); ++ rc = PTR_ERR(dax_dev); ++ goto out; + } + dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); + pmem->dax_dev = dax_dev; +@@ -470,8 +473,10 @@ static int pmem_attach_disk(struct device *dev, + "badblocks"); + if (!pmem->bb_state) + dev_warn(dev, "'badblocks' notification disabled\n"); +- + return 0; ++out: ++ blk_cleanup_disk(pmem->disk); ++ return rc; + } + + static int nd_pmem_probe(struct device *dev) +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index f8dd664b2eda5..d5d5d035d6775 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -131,7 +131,7 @@ static void nvme_set_queue_dying(struct nvme_ns *ns) + if (test_and_set_bit(NVME_NS_DEAD, &ns->flags)) + return; + +- blk_set_queue_dying(ns->queue); ++ blk_mark_disk_dead(ns->disk); + blk_mq_unquiesce_queue(ns->queue); + + set_capacity_and_notify(ns->disk, 0); +@@ -1914,7 +1914,7 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id) + if (blk_queue_is_zoned(ns->queue)) { + ret = nvme_revalidate_zones(ns); + if (ret && !nvme_first_scan(ns->disk)) +- goto out; ++ return ret; + } + + if (nvme_ns_head_multipath(ns->head)) { +@@ -1929,16 +1929,16 @@ static int nvme_update_ns_info(struct nvme_ns *ns, struct nvme_id_ns *id) + return 0; + + out_unfreeze: +- blk_mq_unfreeze_queue(ns->disk->queue); +-out: + /* + * If probing fails due an unsupported feature, hide the block device, + * but still allow other access. + */ + if (ret == -ENODEV) { + ns->disk->flags |= GENHD_FL_HIDDEN; ++ set_bit(NVME_NS_READY, &ns->flags); + ret = 0; + } ++ blk_mq_unfreeze_queue(ns->disk->queue); + return ret; + } + +@@ -4187,7 +4187,14 @@ static void nvme_async_event_work(struct work_struct *work) + container_of(work, struct nvme_ctrl, async_event_work); + + nvme_aen_uevent(ctrl); +- ctrl->ops->submit_async_event(ctrl); ++ ++ /* ++ * The transport drivers must guarantee AER submission here is safe by ++ * flushing ctrl async_event_work after changing the controller state ++ * from LIVE and before freeing the admin queue. ++ */ ++ if (ctrl->state == NVME_CTRL_LIVE) ++ ctrl->ops->submit_async_event(ctrl); + } + + static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl) +diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h +index a146cb903869c..561c2abd3892b 100644 +--- a/drivers/nvme/host/fabrics.h ++++ b/drivers/nvme/host/fabrics.h +@@ -169,6 +169,7 @@ nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl, + struct nvmf_ctrl_options *opts) + { + if (ctrl->state == NVME_CTRL_DELETING || ++ ctrl->state == NVME_CTRL_DELETING_NOIO || + ctrl->state == NVME_CTRL_DEAD || + strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || + strcmp(opts->host->nqn, ctrl->opts->host->nqn) || +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index fba06618c6c23..727520c397109 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -138,13 +138,12 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl) + { + struct nvme_ns *ns; + +- mutex_lock(&ctrl->scan_lock); + down_read(&ctrl->namespaces_rwsem); +- list_for_each_entry(ns, &ctrl->namespaces, list) +- if (nvme_mpath_clear_current_path(ns)) +- kblockd_schedule_work(&ns->head->requeue_work); ++ list_for_each_entry(ns, &ctrl->namespaces, list) { ++ nvme_mpath_clear_current_path(ns); ++ kblockd_schedule_work(&ns->head->requeue_work); ++ } + up_read(&ctrl->namespaces_rwsem); +- mutex_unlock(&ctrl->scan_lock); + } + + void nvme_mpath_revalidate_paths(struct nvme_ns *ns) +@@ -793,7 +792,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head) + { + if (!head->disk) + return; +- blk_set_queue_dying(head->disk->queue); ++ blk_mark_disk_dead(head->disk); + /* make sure all pending bios are cleaned up */ + kblockd_schedule_work(&head->requeue_work); + flush_work(&head->requeue_work); +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index 149ecf73df384..b925a5f4afc3a 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -3300,7 +3300,8 @@ static const struct pci_device_id nvme_id_table[] = { + NVME_QUIRK_DEALLOCATE_ZEROES, }, + { PCI_VDEVICE(INTEL, 0x0a54), /* Intel P4500/P4600 */ + .driver_data = NVME_QUIRK_STRIPE_SIZE | +- NVME_QUIRK_DEALLOCATE_ZEROES, }, ++ NVME_QUIRK_DEALLOCATE_ZEROES | ++ NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */ + .driver_data = NVME_QUIRK_STRIPE_SIZE | + NVME_QUIRK_DEALLOCATE_ZEROES, }, +diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c +index 042c594bc57e2..d51f52e296f50 100644 +--- a/drivers/nvme/host/rdma.c ++++ b/drivers/nvme/host/rdma.c +@@ -1095,11 +1095,13 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new) + return ret; + + if (ctrl->ctrl.icdoff) { ++ ret = -EOPNOTSUPP; + dev_err(ctrl->ctrl.device, "icdoff is not supported!\n"); + goto destroy_admin; + } + + if (!(ctrl->ctrl.sgls & (1 << 2))) { ++ ret = -EOPNOTSUPP; + dev_err(ctrl->ctrl.device, + "Mandatory keyed sgls are not supported!\n"); + goto destroy_admin; +@@ -1190,6 +1192,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work) + struct nvme_rdma_ctrl, err_work); + + nvme_stop_keep_alive(&ctrl->ctrl); ++ flush_work(&ctrl->ctrl.async_event_work); + nvme_rdma_teardown_io_queues(ctrl, false); + nvme_start_queues(&ctrl->ctrl); + nvme_rdma_teardown_admin_queue(ctrl, false); +diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c +index 4ae562d30d2b9..ef65d24639c44 100644 +--- a/drivers/nvme/host/tcp.c ++++ b/drivers/nvme/host/tcp.c +@@ -920,7 +920,15 @@ static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue) + + static void nvme_tcp_fail_request(struct nvme_tcp_request *req) + { +- nvme_tcp_end_request(blk_mq_rq_from_pdu(req), NVME_SC_HOST_PATH_ERROR); ++ if (nvme_tcp_async_req(req)) { ++ union nvme_result res = {}; ++ ++ nvme_complete_async_event(&req->queue->ctrl->ctrl, ++ cpu_to_le16(NVME_SC_HOST_PATH_ERROR), &res); ++ } else { ++ nvme_tcp_end_request(blk_mq_rq_from_pdu(req), ++ NVME_SC_HOST_PATH_ERROR); ++ } + } + + static int nvme_tcp_try_send_data(struct nvme_tcp_request *req) +@@ -2097,6 +2105,7 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work) + struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl; + + nvme_stop_keep_alive(ctrl); ++ flush_work(&ctrl->async_event_work); + nvme_tcp_teardown_io_queues(ctrl, false); + /* unquiesce to fail fast pending requests */ + nvme_start_queues(ctrl); +diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c +index be5d82421e3a4..496d775c67707 100644 +--- a/drivers/nvme/target/configfs.c ++++ b/drivers/nvme/target/configfs.c +@@ -1553,6 +1553,8 @@ static void nvmet_port_release(struct config_item *item) + { + struct nvmet_port *port = to_nvmet_port(item); + ++ /* Let inflight controllers teardown complete */ ++ flush_scheduled_work(); + list_del(&port->global_entry); + + kfree(port->ana_state); +diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c +index 1dd1a0fe2e819..df7e033dd2732 100644 +--- a/drivers/nvme/target/io-cmd-file.c ++++ b/drivers/nvme/target/io-cmd-file.c +@@ -8,6 +8,7 @@ + #include <linux/uio.h> + #include <linux/falloc.h> + #include <linux/file.h> ++#include <linux/fs.h> + #include "nvmet.h" + + #define NVMET_MAX_MPOOL_BVEC 16 +@@ -266,7 +267,8 @@ static void nvmet_file_execute_rw(struct nvmet_req *req) + + if (req->ns->buffered_io) { + if (likely(!req->f.mpool_alloc) && +- nvmet_file_execute_io(req, IOCB_NOWAIT)) ++ (req->ns->file->f_mode & FMODE_NOWAIT) && ++ nvmet_file_execute_io(req, IOCB_NOWAIT)) + return; + nvmet_file_submit_buffered_io(req); + } else +diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c +index 891174ccd44bb..f1eedbf493d5b 100644 +--- a/drivers/nvme/target/rdma.c ++++ b/drivers/nvme/target/rdma.c +@@ -1818,12 +1818,36 @@ restart: + mutex_unlock(&nvmet_rdma_queue_mutex); + } + ++static void nvmet_rdma_destroy_port_queues(struct nvmet_rdma_port *port) ++{ ++ struct nvmet_rdma_queue *queue, *tmp; ++ struct nvmet_port *nport = port->nport; ++ ++ mutex_lock(&nvmet_rdma_queue_mutex); ++ list_for_each_entry_safe(queue, tmp, &nvmet_rdma_queue_list, ++ queue_list) { ++ if (queue->port != nport) ++ continue; ++ ++ list_del_init(&queue->queue_list); ++ __nvmet_rdma_queue_disconnect(queue); ++ } ++ mutex_unlock(&nvmet_rdma_queue_mutex); ++} ++ + static void nvmet_rdma_disable_port(struct nvmet_rdma_port *port) + { + struct rdma_cm_id *cm_id = xchg(&port->cm_id, NULL); + + if (cm_id) + rdma_destroy_id(cm_id); ++ ++ /* ++ * Destroy the remaining queues, which are not belong to any ++ * controller yet. Do it here after the RDMA-CM was destroyed ++ * guarantees that no new queue will be created. ++ */ ++ nvmet_rdma_destroy_port_queues(port); + } + + static int nvmet_rdma_enable_port(struct nvmet_rdma_port *port) +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index 46c3b3be7e033..2b8bab28417b8 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -700,10 +700,11 @@ static int nvmet_try_send_r2t(struct nvmet_tcp_cmd *cmd, bool last_in_batch) + static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch) + { + struct nvmet_tcp_queue *queue = cmd->queue; ++ int left = NVME_TCP_DIGEST_LENGTH - cmd->offset; + struct msghdr msg = { .msg_flags = MSG_DONTWAIT }; + struct kvec iov = { + .iov_base = (u8 *)&cmd->exp_ddgst + cmd->offset, +- .iov_len = NVME_TCP_DIGEST_LENGTH - cmd->offset ++ .iov_len = left + }; + int ret; + +@@ -717,6 +718,10 @@ static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd, bool last_in_batch) + return ret; + + cmd->offset += ret; ++ left -= ret; ++ ++ if (left) ++ return -EAGAIN; + + if (queue->nvme_sq.sqhd_disabled) { + cmd->queue->snd_cmd = NULL; +@@ -1740,6 +1745,17 @@ err_port: + return ret; + } + ++static void nvmet_tcp_destroy_port_queues(struct nvmet_tcp_port *port) ++{ ++ struct nvmet_tcp_queue *queue; ++ ++ mutex_lock(&nvmet_tcp_queue_mutex); ++ list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list) ++ if (queue->port == port) ++ kernel_sock_shutdown(queue->sock, SHUT_RDWR); ++ mutex_unlock(&nvmet_tcp_queue_mutex); ++} ++ + static void nvmet_tcp_remove_port(struct nvmet_port *nport) + { + struct nvmet_tcp_port *port = nport->priv; +@@ -1749,6 +1765,11 @@ static void nvmet_tcp_remove_port(struct nvmet_port *nport) + port->sock->sk->sk_user_data = NULL; + write_unlock_bh(&port->sock->sk->sk_callback_lock); + cancel_work_sync(&port->accept_work); ++ /* ++ * Destroy the remaining queues, which are not belong to any ++ * controller yet. ++ */ ++ nvmet_tcp_destroy_port_queues(port); + + sock_release(port->sock); + kfree(port); +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index 8976da38b375a..fb7840c73765a 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -307,6 +307,8 @@ static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj, + struct device *dev = kobj_to_dev(kobj); + struct nvmem_device *nvmem = to_nvmem_device(dev); + ++ attr->size = nvmem->size; ++ + return nvmem_bin_attr_get_umode(nvmem); + } + +@@ -766,7 +768,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) + + if (config->wp_gpio) + nvmem->wp_gpio = config->wp_gpio; +- else ++ else if (!config->ignore_wp) + nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp", + GPIOD_OUT_HIGH); + if (IS_ERR(nvmem->wp_gpio)) { +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index 3dfeae8912dfc..80b5fd44ab1c7 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -70,10 +70,6 @@ config OF_IRQ + def_bool y + depends on !SPARC && IRQ_DOMAIN + +-config OF_NET +- depends on NETDEVICES +- def_bool y +- + config OF_RESERVED_MEM + def_bool OF_EARLY_FLATTREE + +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index c13b982084a3a..e0360a44306e2 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -7,7 +7,6 @@ obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o + obj-$(CONFIG_OF_PROMTREE) += pdt.o + obj-$(CONFIG_OF_ADDRESS) += address.o + obj-$(CONFIG_OF_IRQ) += irq.o +-obj-$(CONFIG_OF_NET) += of_net.o + obj-$(CONFIG_OF_UNITTEST) += unittest.o + obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o + obj-$(CONFIG_OF_RESOLVE) += resolver.o +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 0ac17256258d5..54719f8156ed1 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -1327,9 +1327,14 @@ int of_phandle_iterator_next(struct of_phandle_iterator *it) + * property data length + */ + if (it->cur + count > it->list_end) { +- pr_err("%pOF: %s = %d found %d\n", +- it->parent, it->cells_name, +- count, it->cell_count); ++ if (it->cells_name) ++ pr_err("%pOF: %s = %d found %td\n", ++ it->parent, it->cells_name, ++ count, it->list_end - it->cur); ++ else ++ pr_err("%pOF: phandle %s needs %d, found %td\n", ++ it->parent, of_node_full_name(it->node), ++ count, it->list_end - it->cur); + goto err; + } + } +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 4546572af24bb..59a7a9ee58ef7 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -482,9 +482,11 @@ static int __init early_init_dt_reserve_memory_arch(phys_addr_t base, + if (nomap) { + /* + * If the memory is already reserved (by another region), we +- * should not allow it to be marked nomap. ++ * should not allow it to be marked nomap, but don't worry ++ * if the region isn't memory as it won't be mapped. + */ +- if (memblock_is_region_reserved(base, size)) ++ if (memblock_overlaps_region(&memblock.memory, base, size) && ++ memblock_is_region_reserved(base, size)) + return -EBUSY; + + return memblock_mark_nomap(base, size); +@@ -969,18 +971,22 @@ static void __init early_init_dt_check_for_elfcorehdr(unsigned long node) + elfcorehdr_addr, elfcorehdr_size); + } + +-static phys_addr_t cap_mem_addr; +-static phys_addr_t cap_mem_size; ++static unsigned long chosen_node_offset = -FDT_ERR_NOTFOUND; + + /** + * early_init_dt_check_for_usable_mem_range - Decode usable memory range + * location from flat tree +- * @node: reference to node containing usable memory range location ('chosen') + */ +-static void __init early_init_dt_check_for_usable_mem_range(unsigned long node) ++void __init early_init_dt_check_for_usable_mem_range(void) + { + const __be32 *prop; + int len; ++ phys_addr_t cap_mem_addr; ++ phys_addr_t cap_mem_size; ++ unsigned long node = chosen_node_offset; ++ ++ if ((long)node < 0) ++ return; + + pr_debug("Looking for usable-memory-range property... "); + +@@ -993,6 +999,8 @@ static void __init early_init_dt_check_for_usable_mem_range(unsigned long node) + + pr_debug("cap_mem_start=%pa cap_mem_size=%pa\n", &cap_mem_addr, + &cap_mem_size); ++ ++ memblock_cap_memory_range(cap_mem_addr, cap_mem_size); + } + + #ifdef CONFIG_SERIAL_EARLYCON +@@ -1141,9 +1149,10 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, + (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) + return 0; + ++ chosen_node_offset = node; ++ + early_init_dt_check_for_initrd(node); + early_init_dt_check_for_elfcorehdr(node); +- early_init_dt_check_for_usable_mem_range(node); + + /* Retrieve command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); +@@ -1279,7 +1288,7 @@ void __init early_init_dt_scan_nodes(void) + of_scan_flat_dt(early_init_dt_scan_memory, NULL); + + /* Handle linux,usable-memory-range property */ +- memblock_cap_memory_range(cap_mem_addr, cap_mem_size); ++ early_init_dt_check_for_usable_mem_range(); + } + + bool __init early_init_dt_scan(void *params) +diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c +deleted file mode 100644 +index dbac3a172a11e..0000000000000 +--- a/drivers/of/of_net.c ++++ /dev/null +@@ -1,145 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * OF helpers for network devices. +- * +- * Initially copied out of arch/powerpc/kernel/prom_parse.c +- */ +-#include <linux/etherdevice.h> +-#include <linux/kernel.h> +-#include <linux/of_net.h> +-#include <linux/of_platform.h> +-#include <linux/phy.h> +-#include <linux/export.h> +-#include <linux/device.h> +-#include <linux/nvmem-consumer.h> +- +-/** +- * of_get_phy_mode - Get phy mode for given device_node +- * @np: Pointer to the given device_node +- * @interface: Pointer to the result +- * +- * The function gets phy interface string from property 'phy-mode' or +- * 'phy-connection-type'. The index in phy_modes table is set in +- * interface and 0 returned. In case of error interface is set to +- * PHY_INTERFACE_MODE_NA and an errno is returned, e.g. -ENODEV. +- */ +-int of_get_phy_mode(struct device_node *np, phy_interface_t *interface) +-{ +- const char *pm; +- int err, i; +- +- *interface = PHY_INTERFACE_MODE_NA; +- +- err = of_property_read_string(np, "phy-mode", &pm); +- if (err < 0) +- err = of_property_read_string(np, "phy-connection-type", &pm); +- if (err < 0) +- return err; +- +- for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) +- if (!strcasecmp(pm, phy_modes(i))) { +- *interface = i; +- return 0; +- } +- +- return -ENODEV; +-} +-EXPORT_SYMBOL_GPL(of_get_phy_mode); +- +-static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) +-{ +- struct property *pp = of_find_property(np, name, NULL); +- +- if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) { +- memcpy(addr, pp->value, ETH_ALEN); +- return 0; +- } +- return -ENODEV; +-} +- +-static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) +-{ +- struct platform_device *pdev = of_find_device_by_node(np); +- struct nvmem_cell *cell; +- const void *mac; +- size_t len; +- int ret; +- +- /* Try lookup by device first, there might be a nvmem_cell_lookup +- * associated with a given device. +- */ +- if (pdev) { +- ret = nvmem_get_mac_address(&pdev->dev, addr); +- put_device(&pdev->dev); +- return ret; +- } +- +- cell = of_nvmem_cell_get(np, "mac-address"); +- if (IS_ERR(cell)) +- return PTR_ERR(cell); +- +- mac = nvmem_cell_read(cell, &len); +- nvmem_cell_put(cell); +- +- if (IS_ERR(mac)) +- return PTR_ERR(mac); +- +- if (len != ETH_ALEN || !is_valid_ether_addr(mac)) { +- kfree(mac); +- return -EINVAL; +- } +- +- memcpy(addr, mac, ETH_ALEN); +- kfree(mac); +- +- return 0; +-} +- +-/** +- * of_get_mac_address() +- * @np: Caller's Device Node +- * @addr: Pointer to a six-byte array for the result +- * +- * Search the device tree for the best MAC address to use. 'mac-address' is +- * checked first, because that is supposed to contain to "most recent" MAC +- * address. If that isn't set, then 'local-mac-address' is checked next, +- * because that is the default address. If that isn't set, then the obsolete +- * 'address' is checked, just in case we're using an old device tree. If any +- * of the above isn't set, then try to get MAC address from nvmem cell named +- * 'mac-address'. +- * +- * Note that the 'address' property is supposed to contain a virtual address of +- * the register set, but some DTS files have redefined that property to be the +- * MAC address. +- * +- * All-zero MAC addresses are rejected, because those could be properties that +- * exist in the device tree, but were not set by U-Boot. For example, the +- * DTS could define 'mac-address' and 'local-mac-address', with zero MAC +- * addresses. Some older U-Boots only initialized 'local-mac-address'. In +- * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists +- * but is all zeros. +- * +- * Return: 0 on success and errno in case of error. +-*/ +-int of_get_mac_address(struct device_node *np, u8 *addr) +-{ +- int ret; +- +- if (!np) +- return -ENODEV; +- +- ret = of_get_mac_addr(np, "mac-address", addr); +- if (!ret) +- return 0; +- +- ret = of_get_mac_addr(np, "local-mac-address", addr); +- if (!ret) +- return 0; +- +- ret = of_get_mac_addr(np, "address", addr); +- if (!ret) +- return 0; +- +- return of_get_mac_addr_nvmem(np, addr); +-} +-EXPORT_SYMBOL(of_get_mac_address); +diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c +index 8c056972a6ddc..2bee1d992408f 100644 +--- a/drivers/of/unittest.c ++++ b/drivers/of/unittest.c +@@ -911,11 +911,18 @@ static void __init of_unittest_dma_ranges_one(const char *path, + if (!rc) { + phys_addr_t paddr; + dma_addr_t dma_addr; +- struct device dev_bogus; ++ struct device *dev_bogus; + +- dev_bogus.dma_range_map = map; +- paddr = dma_to_phys(&dev_bogus, expect_dma_addr); +- dma_addr = phys_to_dma(&dev_bogus, expect_paddr); ++ dev_bogus = kzalloc(sizeof(struct device), GFP_KERNEL); ++ if (!dev_bogus) { ++ unittest(0, "kzalloc() failed\n"); ++ kfree(map); ++ return; ++ } ++ ++ dev_bogus->dma_range_map = map; ++ paddr = dma_to_phys(dev_bogus, expect_dma_addr); ++ dma_addr = phys_to_dma(dev_bogus, expect_paddr); + + unittest(paddr == expect_paddr, + "of_dma_get_range: wrong phys addr %pap (expecting %llx) on node %pOF\n", +@@ -925,6 +932,7 @@ static void __init of_unittest_dma_ranges_one(const char *path, + &dma_addr, expect_dma_addr, np); + + kfree(map); ++ kfree(dev_bogus); + } + of_node_put(np); + #endif +@@ -934,8 +942,9 @@ static void __init of_unittest_parse_dma_ranges(void) + { + of_unittest_dma_ranges_one("/testcase-data/address-tests/device@70000000", + 0x0, 0x20000000); +- of_unittest_dma_ranges_one("/testcase-data/address-tests/bus@80000000/device@1000", +- 0x100000000, 0x20000000); ++ if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT)) ++ of_unittest_dma_ranges_one("/testcase-data/address-tests/bus@80000000/device@1000", ++ 0x100000000, 0x20000000); + of_unittest_dma_ranges_one("/testcase-data/address-tests/pci@90000000", + 0x80000000, 0x20000000); + } +@@ -1688,19 +1697,19 @@ static void __init of_unittest_overlay_gpio(void) + */ + + EXPECT_BEGIN(KERN_INFO, +- "GPIO line <<int>> (line-B-input) hogged as input\n"); ++ "gpio-<<int>> (line-B-input): hogged as input\n"); + + EXPECT_BEGIN(KERN_INFO, +- "GPIO line <<int>> (line-A-input) hogged as input\n"); ++ "gpio-<<int>> (line-A-input): hogged as input\n"); + + ret = platform_driver_register(&unittest_gpio_driver); + if (unittest(ret == 0, "could not register unittest gpio driver\n")) + return; + + EXPECT_END(KERN_INFO, +- "GPIO line <<int>> (line-A-input) hogged as input\n"); ++ "gpio-<<int>> (line-A-input): hogged as input\n"); + EXPECT_END(KERN_INFO, +- "GPIO line <<int>> (line-B-input) hogged as input\n"); ++ "gpio-<<int>> (line-B-input): hogged as input\n"); + + unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); +@@ -1727,7 +1736,7 @@ static void __init of_unittest_overlay_gpio(void) + chip_request_count = unittest_gpio_chip_request_count; + + EXPECT_BEGIN(KERN_INFO, +- "GPIO line <<int>> (line-D-input) hogged as input\n"); ++ "gpio-<<int>> (line-D-input): hogged as input\n"); + + /* overlay_gpio_03 contains gpio node and child gpio hog node */ + +@@ -1735,7 +1744,7 @@ static void __init of_unittest_overlay_gpio(void) + "Adding overlay 'overlay_gpio_03' failed\n"); + + EXPECT_END(KERN_INFO, +- "GPIO line <<int>> (line-D-input) hogged as input\n"); ++ "gpio-<<int>> (line-D-input): hogged as input\n"); + + unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count, + "unittest_gpio_probe() failed or not called\n"); +@@ -1774,7 +1783,7 @@ static void __init of_unittest_overlay_gpio(void) + */ + + EXPECT_BEGIN(KERN_INFO, +- "GPIO line <<int>> (line-C-input) hogged as input\n"); ++ "gpio-<<int>> (line-C-input): hogged as input\n"); + + /* overlay_gpio_04b contains child gpio hog node */ + +@@ -1782,7 +1791,7 @@ static void __init of_unittest_overlay_gpio(void) + "Adding overlay 'overlay_gpio_04b' failed\n"); + + EXPECT_END(KERN_INFO, +- "GPIO line <<int>> (line-C-input) hogged as input\n"); ++ "gpio-<<int>> (line-C-input): hogged as input\n"); + + unittest(chip_request_count + 1 == unittest_gpio_chip_request_count, + "unittest_gpio_chip_request() called %d times (expected 1 time)\n", +diff --git a/drivers/opp/of.c b/drivers/opp/of.c +index 2a97c6535c4c6..c32ae7497392b 100644 +--- a/drivers/opp/of.c ++++ b/drivers/opp/of.c +@@ -921,7 +921,7 @@ free_required_opps: + free_opp: + _opp_free(new_opp); + +- return ERR_PTR(ret); ++ return ret ? ERR_PTR(ret) : NULL; + } + + /* Initializes OPP tables based on new bindings */ +diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c +index 059566f544291..9be007c9420f9 100644 +--- a/drivers/parisc/ccio-dma.c ++++ b/drivers/parisc/ccio-dma.c +@@ -1003,7 +1003,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, + ioc->usg_calls++; + #endif + +- while(sg_dma_len(sglist) && nents--) { ++ while (nents && sg_dma_len(sglist)) { + + #ifdef CCIO_COLLECT_STATS + ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT; +@@ -1011,6 +1011,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, + ccio_unmap_page(dev, sg_dma_address(sglist), + sg_dma_len(sglist), direction, 0); + ++sglist; ++ nents--; + } + + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); +diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c +index e090978518f1a..4760f82def6ec 100644 +--- a/drivers/parisc/pdc_stable.c ++++ b/drivers/parisc/pdc_stable.c +@@ -979,8 +979,10 @@ pdcs_register_pathentries(void) + entry->kobj.kset = paths_kset; + err = kobject_init_and_add(&entry->kobj, &ktype_pdcspath, NULL, + "%s", entry->name); +- if (err) ++ if (err) { ++ kobject_put(&entry->kobj); + return err; ++ } + + /* kobject is now registered */ + write_lock(&entry->rw_lock); +diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c +index e60690d38d677..374b9199878d4 100644 +--- a/drivers/parisc/sba_iommu.c ++++ b/drivers/parisc/sba_iommu.c +@@ -1047,7 +1047,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, + spin_unlock_irqrestore(&ioc->res_lock, flags); + #endif + +- while (sg_dma_len(sglist) && nents--) { ++ while (nents && sg_dma_len(sglist)) { + + sba_unmap_page(dev, sg_dma_address(sglist), sg_dma_len(sglist), + direction, 0); +@@ -1056,6 +1056,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, + ioc->usingle_calls--; /* kluge since call is unmap_sg() */ + #endif + ++sglist; ++ nents--; + } + + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); +diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c +index ffb176d288cd9..918e11082e6a7 100644 +--- a/drivers/pci/controller/cadence/pci-j721e.c ++++ b/drivers/pci/controller/cadence/pci-j721e.c +@@ -474,7 +474,7 @@ static int j721e_pcie_probe(struct platform_device *pdev) + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(dev, "failed to enable pcie_refclk\n"); +- goto err_get_sync; ++ goto err_pcie_setup; + } + pcie->refclk = clk; + +diff --git a/drivers/pci/controller/cadence/pcie-cadence-plat.c b/drivers/pci/controller/cadence/pcie-cadence-plat.c +index 5fee0f89ab594..a224afadbcc00 100644 +--- a/drivers/pci/controller/cadence/pcie-cadence-plat.c ++++ b/drivers/pci/controller/cadence/pcie-cadence-plat.c +@@ -127,6 +127,8 @@ static int cdns_plat_pcie_probe(struct platform_device *pdev) + goto err_init; + } + ++ return 0; ++ + err_init: + err_get_sync: + pm_runtime_put_sync(dev); +diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c +index a945f0c0e73dc..3254f60d1713f 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.c ++++ b/drivers/pci/controller/dwc/pcie-designware.c +@@ -671,10 +671,11 @@ void dw_pcie_iatu_detect(struct dw_pcie *pci) + if (!pci->atu_base) { + struct resource *res = + platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu"); +- if (res) ++ if (res) { + pci->atu_size = resource_size(res); +- pci->atu_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(pci->atu_base)) ++ pci->atu_base = devm_ioremap_resource(dev, res); ++ } ++ if (!pci->atu_base || IS_ERR(pci->atu_base)) + pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; + } + +diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c +index d842fd0181299..d05be942956e2 100644 +--- a/drivers/pci/controller/dwc/pcie-uniphier.c ++++ b/drivers/pci/controller/dwc/pcie-uniphier.c +@@ -168,30 +168,21 @@ static void uniphier_pcie_irq_enable(struct uniphier_pcie_priv *priv) + writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX); + } + +-static void uniphier_pcie_irq_ack(struct irq_data *d) +-{ +- struct pcie_port *pp = irq_data_get_irq_chip_data(d); +- struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +- struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); +- u32 val; +- +- val = readl(priv->base + PCL_RCV_INTX); +- val &= ~PCL_RCV_INTX_ALL_STATUS; +- val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_STATUS_SHIFT); +- writel(val, priv->base + PCL_RCV_INTX); +-} +- + static void uniphier_pcie_irq_mask(struct irq_data *d) + { + struct pcie_port *pp = irq_data_get_irq_chip_data(d); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); ++ unsigned long flags; + u32 val; + ++ raw_spin_lock_irqsave(&pp->lock, flags); ++ + val = readl(priv->base + PCL_RCV_INTX); +- val &= ~PCL_RCV_INTX_ALL_MASK; + val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT); + writel(val, priv->base + PCL_RCV_INTX); ++ ++ raw_spin_unlock_irqrestore(&pp->lock, flags); + } + + static void uniphier_pcie_irq_unmask(struct irq_data *d) +@@ -199,17 +190,20 @@ static void uniphier_pcie_irq_unmask(struct irq_data *d) + struct pcie_port *pp = irq_data_get_irq_chip_data(d); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); ++ unsigned long flags; + u32 val; + ++ raw_spin_lock_irqsave(&pp->lock, flags); ++ + val = readl(priv->base + PCL_RCV_INTX); +- val &= ~PCL_RCV_INTX_ALL_MASK; + val &= ~BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT); + writel(val, priv->base + PCL_RCV_INTX); ++ ++ raw_spin_unlock_irqrestore(&pp->lock, flags); + } + + static struct irq_chip uniphier_pcie_irq_chip = { + .name = "PCI", +- .irq_ack = uniphier_pcie_irq_ack, + .irq_mask = uniphier_pcie_irq_mask, + .irq_unmask = uniphier_pcie_irq_unmask, + }; +diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c +index 596ebcfcc82dc..b2217e2b3efde 100644 +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -31,9 +31,6 @@ + /* PCIe core registers */ + #define PCIE_CORE_DEV_ID_REG 0x0 + #define PCIE_CORE_CMD_STATUS_REG 0x4 +-#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0) +-#define PCIE_CORE_CMD_MEM_ACCESS_EN BIT(1) +-#define PCIE_CORE_CMD_MEM_IO_REQ_EN BIT(2) + #define PCIE_CORE_DEV_REV_REG 0x8 + #define PCIE_CORE_PCIEXP_CAP 0xc0 + #define PCIE_CORE_ERR_CAPCTL_REG 0x118 +@@ -99,6 +96,7 @@ + #define PCIE_CORE_CTRL2_MSI_ENABLE BIT(10) + #define PCIE_CORE_REF_CLK_REG (CONTROL_BASE_ADDR + 0x14) + #define PCIE_CORE_REF_CLK_TX_ENABLE BIT(1) ++#define PCIE_CORE_REF_CLK_RX_ENABLE BIT(2) + #define PCIE_MSG_LOG_REG (CONTROL_BASE_ADDR + 0x30) + #define PCIE_ISR0_REG (CONTROL_BASE_ADDR + 0x40) + #define PCIE_MSG_PM_PME_MASK BIT(7) +@@ -106,18 +104,19 @@ + #define PCIE_ISR0_MSI_INT_PENDING BIT(24) + #define PCIE_ISR0_INTX_ASSERT(val) BIT(16 + (val)) + #define PCIE_ISR0_INTX_DEASSERT(val) BIT(20 + (val)) +-#define PCIE_ISR0_ALL_MASK GENMASK(26, 0) ++#define PCIE_ISR0_ALL_MASK GENMASK(31, 0) + #define PCIE_ISR1_REG (CONTROL_BASE_ADDR + 0x48) + #define PCIE_ISR1_MASK_REG (CONTROL_BASE_ADDR + 0x4C) + #define PCIE_ISR1_POWER_STATE_CHANGE BIT(4) + #define PCIE_ISR1_FLUSH BIT(5) + #define PCIE_ISR1_INTX_ASSERT(val) BIT(8 + (val)) +-#define PCIE_ISR1_ALL_MASK GENMASK(11, 4) ++#define PCIE_ISR1_ALL_MASK GENMASK(31, 0) + #define PCIE_MSI_ADDR_LOW_REG (CONTROL_BASE_ADDR + 0x50) + #define PCIE_MSI_ADDR_HIGH_REG (CONTROL_BASE_ADDR + 0x54) + #define PCIE_MSI_STATUS_REG (CONTROL_BASE_ADDR + 0x58) + #define PCIE_MSI_MASK_REG (CONTROL_BASE_ADDR + 0x5C) + #define PCIE_MSI_PAYLOAD_REG (CONTROL_BASE_ADDR + 0x9C) ++#define PCIE_MSI_DATA_MASK GENMASK(15, 0) + + /* PCIe window configuration */ + #define OB_WIN_BASE_ADDR 0x4c00 +@@ -164,8 +163,50 @@ + #define CFG_REG (LMI_BASE_ADDR + 0x0) + #define LTSSM_SHIFT 24 + #define LTSSM_MASK 0x3f +-#define LTSSM_L0 0x10 + #define RC_BAR_CONFIG 0x300 ++ ++/* LTSSM values in CFG_REG */ ++enum { ++ LTSSM_DETECT_QUIET = 0x0, ++ LTSSM_DETECT_ACTIVE = 0x1, ++ LTSSM_POLLING_ACTIVE = 0x2, ++ LTSSM_POLLING_COMPLIANCE = 0x3, ++ LTSSM_POLLING_CONFIGURATION = 0x4, ++ LTSSM_CONFIG_LINKWIDTH_START = 0x5, ++ LTSSM_CONFIG_LINKWIDTH_ACCEPT = 0x6, ++ LTSSM_CONFIG_LANENUM_ACCEPT = 0x7, ++ LTSSM_CONFIG_LANENUM_WAIT = 0x8, ++ LTSSM_CONFIG_COMPLETE = 0x9, ++ LTSSM_CONFIG_IDLE = 0xa, ++ LTSSM_RECOVERY_RCVR_LOCK = 0xb, ++ LTSSM_RECOVERY_SPEED = 0xc, ++ LTSSM_RECOVERY_RCVR_CFG = 0xd, ++ LTSSM_RECOVERY_IDLE = 0xe, ++ LTSSM_L0 = 0x10, ++ LTSSM_RX_L0S_ENTRY = 0x11, ++ LTSSM_RX_L0S_IDLE = 0x12, ++ LTSSM_RX_L0S_FTS = 0x13, ++ LTSSM_TX_L0S_ENTRY = 0x14, ++ LTSSM_TX_L0S_IDLE = 0x15, ++ LTSSM_TX_L0S_FTS = 0x16, ++ LTSSM_L1_ENTRY = 0x17, ++ LTSSM_L1_IDLE = 0x18, ++ LTSSM_L2_IDLE = 0x19, ++ LTSSM_L2_TRANSMIT_WAKE = 0x1a, ++ LTSSM_DISABLED = 0x20, ++ LTSSM_LOOPBACK_ENTRY_MASTER = 0x21, ++ LTSSM_LOOPBACK_ACTIVE_MASTER = 0x22, ++ LTSSM_LOOPBACK_EXIT_MASTER = 0x23, ++ LTSSM_LOOPBACK_ENTRY_SLAVE = 0x24, ++ LTSSM_LOOPBACK_ACTIVE_SLAVE = 0x25, ++ LTSSM_LOOPBACK_EXIT_SLAVE = 0x26, ++ LTSSM_HOT_RESET = 0x27, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE0 = 0x28, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE1 = 0x29, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE2 = 0x2a, ++ LTSSM_RECOVERY_EQUALIZATION_PHASE3 = 0x2b, ++}; ++ + #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) + + /* PCIe core controller registers */ +@@ -198,7 +239,7 @@ + #define PCIE_IRQ_MSI_INT2_DET BIT(21) + #define PCIE_IRQ_RC_DBELL_DET BIT(22) + #define PCIE_IRQ_EP_STATUS BIT(23) +-#define PCIE_IRQ_ALL_MASK 0xfff0fb ++#define PCIE_IRQ_ALL_MASK GENMASK(31, 0) + #define PCIE_IRQ_ENABLE_INTS_MASK PCIE_IRQ_CORE_INT + + /* Transaction types */ +@@ -257,18 +298,49 @@ static inline u32 advk_readl(struct advk_pcie *pcie, u64 reg) + return readl(pcie->base + reg); + } + +-static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg) ++static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie) + { +- return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8); ++ u32 val; ++ u8 ltssm_state; ++ ++ val = advk_readl(pcie, CFG_REG); ++ ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; ++ return ltssm_state; + } + +-static int advk_pcie_link_up(struct advk_pcie *pcie) ++static inline bool advk_pcie_link_up(struct advk_pcie *pcie) + { +- u32 val, ltssm_state; ++ /* check if LTSSM is in normal operation - some L* state */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; ++} + +- val = advk_readl(pcie, CFG_REG); +- ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; +- return ltssm_state >= LTSSM_L0; ++static inline bool advk_pcie_link_active(struct advk_pcie *pcie) ++{ ++ /* ++ * According to PCIe Base specification 3.0, Table 4-14: Link ++ * Status Mapped to the LTSSM, and 4.2.6.3.6 Configuration.Idle ++ * is Link Up mapped to LTSSM Configuration.Idle, Recovery, L0, ++ * L0s, L1 and L2 states. And according to 3.2.1. Data Link ++ * Control and Management State Machine Rules is DL Up status ++ * reported in DL Active state. ++ */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ltssm_state >= LTSSM_CONFIG_IDLE && ltssm_state < LTSSM_DISABLED; ++} ++ ++static inline bool advk_pcie_link_training(struct advk_pcie *pcie) ++{ ++ /* ++ * According to PCIe Base specification 3.0, Table 4-14: Link ++ * Status Mapped to the LTSSM is Link Training mapped to LTSSM ++ * Configuration and Recovery states. ++ */ ++ u8 ltssm_state = advk_pcie_ltssm_state(pcie); ++ return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START && ++ ltssm_state < LTSSM_L0) || ++ (ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 && ++ ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3)); + } + + static int advk_pcie_wait_for_link(struct advk_pcie *pcie) +@@ -291,7 +363,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie) + size_t retries; + + for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) { +- if (!advk_pcie_link_up(pcie)) ++ if (advk_pcie_link_training(pcie)) + break; + udelay(RETRAIN_WAIT_USLEEP_US); + } +@@ -299,23 +371,9 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie) + + static void advk_pcie_issue_perst(struct advk_pcie *pcie) + { +- u32 reg; +- + if (!pcie->reset_gpio) + return; + +- /* +- * As required by PCI Express spec (PCI Express Base Specification, REV. +- * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay +- * for at least 100ms after de-asserting PERST# signal is needed before +- * link training is enabled. So ensure that link training is disabled +- * prior de-asserting PERST# signal to fulfill that PCI Express spec +- * requirement. +- */ +- reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +- reg &= ~LINK_TRAINING_EN; +- advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); +- + /* 10ms delay is needed for some cards */ + dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); + gpiod_set_value_cansleep(pcie->reset_gpio, 1); +@@ -323,53 +381,46 @@ static void advk_pcie_issue_perst(struct advk_pcie *pcie) + gpiod_set_value_cansleep(pcie->reset_gpio, 0); + } + +-static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen) ++static void advk_pcie_train_link(struct advk_pcie *pcie) + { +- int ret, neg_gen; ++ struct device *dev = &pcie->pdev->dev; + u32 reg; ++ int ret; + +- /* Setup link speed */ ++ /* ++ * Setup PCIe rev / gen compliance based on device tree property ++ * 'max-link-speed' which also forces maximal link speed. ++ */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg &= ~PCIE_GEN_SEL_MSK; +- if (gen == 3) ++ if (pcie->link_gen == 3) + reg |= SPEED_GEN_3; +- else if (gen == 2) ++ else if (pcie->link_gen == 2) + reg |= SPEED_GEN_2; + else + reg |= SPEED_GEN_1; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + + /* +- * Enable link training. This is not needed in every call to this +- * function, just once suffices, but it does not break anything either. ++ * Set maximal link speed value also into PCIe Link Control 2 register. ++ * Armada 3700 Functional Specification says that default value is based ++ * on SPEED_GEN but tests showed that default value is always 8.0 GT/s. + */ ++ reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); ++ reg &= ~PCI_EXP_LNKCTL2_TLS; ++ if (pcie->link_gen == 3) ++ reg |= PCI_EXP_LNKCTL2_TLS_8_0GT; ++ else if (pcie->link_gen == 2) ++ reg |= PCI_EXP_LNKCTL2_TLS_5_0GT; ++ else ++ reg |= PCI_EXP_LNKCTL2_TLS_2_5GT; ++ advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); ++ ++ /* Enable link training after selecting PCIe generation */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg |= LINK_TRAINING_EN; + advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + +- /* +- * Start link training immediately after enabling it. +- * This solves problems for some buggy cards. +- */ +- reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); +- reg |= PCI_EXP_LNKCTL_RL; +- advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); +- +- ret = advk_pcie_wait_for_link(pcie); +- if (ret) +- return ret; +- +- reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA); +- neg_gen = reg & PCI_EXP_LNKSTA_CLS; +- +- return neg_gen; +-} +- +-static void advk_pcie_train_link(struct advk_pcie *pcie) +-{ +- struct device *dev = &pcie->pdev->dev; +- int neg_gen = -1, gen; +- + /* + * Reset PCIe card via PERST# signal. Some cards are not detected + * during link training when they are in some non-initial state. +@@ -380,41 +431,18 @@ static void advk_pcie_train_link(struct advk_pcie *pcie) + * PERST# signal could have been asserted by pinctrl subsystem before + * probe() callback has been called or issued explicitly by reset gpio + * function advk_pcie_issue_perst(), making the endpoint going into +- * fundamental reset. As required by PCI Express spec a delay for at +- * least 100ms after such a reset before link training is needed. +- */ +- msleep(PCI_PM_D3COLD_WAIT); +- +- /* +- * Try link training at link gen specified by device tree property +- * 'max-link-speed'. If this fails, iteratively train at lower gen. ++ * fundamental reset. As required by PCI Express spec (PCI Express ++ * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1 ++ * Conventional Reset) a delay for at least 100ms after such a reset ++ * before sending a Configuration Request to the device is needed. ++ * So wait until PCIe link is up. Function advk_pcie_wait_for_link() ++ * waits for link at least 900ms. + */ +- for (gen = pcie->link_gen; gen > 0; --gen) { +- neg_gen = advk_pcie_train_at_gen(pcie, gen); +- if (neg_gen > 0) +- break; +- } +- +- if (neg_gen < 0) +- goto err; +- +- /* +- * After successful training if negotiated gen is lower than requested, +- * train again on negotiated gen. This solves some stability issues for +- * some buggy gen1 cards. +- */ +- if (neg_gen < gen) { +- gen = neg_gen; +- neg_gen = advk_pcie_train_at_gen(pcie, gen); +- } +- +- if (neg_gen == gen) { +- dev_info(dev, "link up at gen %i\n", gen); +- return; +- } +- +-err: +- dev_err(dev, "link never came up\n"); ++ ret = advk_pcie_wait_for_link(pcie); ++ if (ret < 0) ++ dev_err(dev, "link never came up\n"); ++ else ++ dev_info(dev, "link up\n"); + } + + /* +@@ -451,9 +479,15 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) + u32 reg; + int i; + +- /* Enable TX */ ++ /* ++ * Configure PCIe Reference clock. Direction is from the PCIe ++ * controller to the endpoint card, so enable transmitting of ++ * Reference clock differential signal off-chip and disable ++ * receiving off-chip differential signal. ++ */ + reg = advk_readl(pcie, PCIE_CORE_REF_CLK_REG); + reg |= PCIE_CORE_REF_CLK_TX_ENABLE; ++ reg &= ~PCIE_CORE_REF_CLK_RX_ENABLE; + advk_writel(pcie, reg, PCIE_CORE_REF_CLK_REG); + + /* Set to Direct mode */ +@@ -477,6 +511,31 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) + reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL; + advk_writel(pcie, reg, VENDOR_ID_REG); + ++ /* ++ * Change Class Code of PCI Bridge device to PCI Bridge (0x600400), ++ * because the default value is Mass storage controller (0x010400). ++ * ++ * Note that this Aardvark PCI Bridge does not have compliant Type 1 ++ * Configuration Space and it even cannot be accessed via Aardvark's ++ * PCI config space access method. Something like config space is ++ * available in internal Aardvark registers starting at offset 0x0 ++ * and is reported as Type 0. In range 0x10 - 0x34 it has totally ++ * different registers. ++ * ++ * Therefore driver uses emulation of PCI Bridge which emulates ++ * access to configuration space via internal Aardvark registers or ++ * emulated configuration buffer. ++ */ ++ reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG); ++ reg &= ~0xffffff00; ++ reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8; ++ advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG); ++ ++ /* Disable Root Bridge I/O space, memory space and bus mastering */ ++ reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); ++ reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); ++ advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); ++ + /* Set Advanced Error Capabilities and Control PF0 register */ + reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX | + PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN | +@@ -488,8 +547,9 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) + reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); + reg &= ~PCI_EXP_DEVCTL_RELAX_EN; + reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; ++ reg &= ~PCI_EXP_DEVCTL_PAYLOAD; + reg &= ~PCI_EXP_DEVCTL_READRQ; +- reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */ ++ reg |= PCI_EXP_DEVCTL_PAYLOAD_512B; + reg |= PCI_EXP_DEVCTL_READRQ_512B; + advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); + +@@ -574,19 +634,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) + advk_pcie_disable_ob_win(pcie, i); + + advk_pcie_train_link(pcie); +- +- /* +- * FIXME: The following register update is suspicious. This register is +- * applicable only when the PCI controller is configured for Endpoint +- * mode, not as a Root Complex. But apparently when this code is +- * removed, some cards stop working. This should be investigated and +- * a comment explaining this should be put here. +- */ +- reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); +- reg |= PCIE_CORE_CMD_MEM_ACCESS_EN | +- PCIE_CORE_CMD_IO_ACCESS_EN | +- PCIE_CORE_CMD_MEM_IO_REQ_EN; +- advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); + } + + static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val) +@@ -595,6 +642,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 + u32 reg; + unsigned int status; + char *strcomp_status, *str_posted; ++ int ret; + + reg = advk_readl(pcie, PIO_STAT); + status = (reg & PIO_COMPLETION_STATUS_MASK) >> +@@ -619,6 +667,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 + case PIO_COMPLETION_STATUS_OK: + if (reg & PIO_ERR_STATUS) { + strcomp_status = "COMP_ERR"; ++ ret = -EFAULT; + break; + } + /* Get the read result */ +@@ -626,9 +675,11 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 + *val = advk_readl(pcie, PIO_RD_DATA); + /* No error */ + strcomp_status = NULL; ++ ret = 0; + break; + case PIO_COMPLETION_STATUS_UR: + strcomp_status = "UR"; ++ ret = -EOPNOTSUPP; + break; + case PIO_COMPLETION_STATUS_CRS: + if (allow_crs && val) { +@@ -646,6 +697,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 + */ + *val = CFG_RD_CRS_VAL; + strcomp_status = NULL; ++ ret = 0; + break; + } + /* PCIe r4.0, sec 2.3.2, says: +@@ -661,31 +713,34 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3 + * Request and taking appropriate action, e.g., complete the + * Request to the host as a failed transaction. + * +- * To simplify implementation do not re-issue the Configuration +- * Request and complete the Request as a failed transaction. ++ * So return -EAGAIN and caller (pci-aardvark.c driver) will ++ * re-issue request again up to the PIO_RETRY_CNT retries. + */ + strcomp_status = "CRS"; ++ ret = -EAGAIN; + break; + case PIO_COMPLETION_STATUS_CA: + strcomp_status = "CA"; ++ ret = -ECANCELED; + break; + default: + strcomp_status = "Unknown"; ++ ret = -EINVAL; + break; + } + + if (!strcomp_status) +- return 0; ++ return ret; + + if (reg & PIO_NON_POSTED_REQ) + str_posted = "Non-posted"; + else + str_posted = "Posted"; + +- dev_err(dev, "%s PIO Response Status: %s, %#x @ %#x\n", ++ dev_dbg(dev, "%s PIO Response Status: %s, %#x @ %#x\n", + str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS)); + +- return -EFAULT; ++ return ret; + } + + static int advk_pcie_wait_pio(struct advk_pcie *pcie) +@@ -693,13 +748,13 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie) + struct device *dev = &pcie->pdev->dev; + int i; + +- for (i = 0; i < PIO_RETRY_CNT; i++) { ++ for (i = 1; i <= PIO_RETRY_CNT; i++) { + u32 start, isr; + + start = advk_readl(pcie, PIO_START); + isr = advk_readl(pcie, PIO_ISR); + if (!start && isr) +- return 0; ++ return i; + udelay(PIO_RETRY_DELAY); + } + +@@ -707,6 +762,64 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie) + return -ETIMEDOUT; + } + ++static pci_bridge_emul_read_status_t ++advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, ++ int reg, u32 *value) ++{ ++ struct advk_pcie *pcie = bridge->data; ++ ++ switch (reg) { ++ case PCI_COMMAND: ++ *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); ++ return PCI_BRIDGE_EMUL_HANDLED; ++ ++ case PCI_INTERRUPT_LINE: { ++ /* ++ * From the whole 32bit register we support reading from HW only ++ * one bit: PCI_BRIDGE_CTL_BUS_RESET. ++ * Other bits are retrieved only from emulated config buffer. ++ */ ++ __le32 *cfgspace = (__le32 *)&bridge->conf; ++ u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]); ++ if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN) ++ val |= PCI_BRIDGE_CTL_BUS_RESET << 16; ++ else ++ val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16); ++ *value = val; ++ return PCI_BRIDGE_EMUL_HANDLED; ++ } ++ ++ default: ++ return PCI_BRIDGE_EMUL_NOT_HANDLED; ++ } ++} ++ ++static void ++advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, ++ int reg, u32 old, u32 new, u32 mask) ++{ ++ struct advk_pcie *pcie = bridge->data; ++ ++ switch (reg) { ++ case PCI_COMMAND: ++ advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG); ++ break; ++ ++ case PCI_INTERRUPT_LINE: ++ if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { ++ u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); ++ if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) ++ val |= HOT_RESET_GEN; ++ else ++ val &= ~HOT_RESET_GEN; ++ advk_writel(pcie, val, PCIE_CORE_CTRL1_REG); ++ } ++ break; ++ ++ default: ++ break; ++ } ++} + + static pci_bridge_emul_read_status_t + advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, +@@ -723,6 +836,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, + case PCI_EXP_RTCTL: { + u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); + *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; ++ *value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE; + *value |= PCI_EXP_RTCAP_CRSVIS << 16; + return PCI_BRIDGE_EMUL_HANDLED; + } +@@ -734,20 +848,32 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, + return PCI_BRIDGE_EMUL_HANDLED; + } + ++ case PCI_EXP_LNKCAP: { ++ u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); ++ /* ++ * PCI_EXP_LNKCAP_DLLLARC bit is hardwired in aardvark HW to 0. ++ * But support for PCI_EXP_LNKSTA_DLLLA is emulated via ltssm ++ * state so explicitly enable PCI_EXP_LNKCAP_DLLLARC flag. ++ */ ++ val |= PCI_EXP_LNKCAP_DLLLARC; ++ *value = val; ++ return PCI_BRIDGE_EMUL_HANDLED; ++ } ++ + case PCI_EXP_LNKCTL: { + /* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */ + u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) & + ~(PCI_EXP_LNKSTA_LT << 16); +- if (!advk_pcie_link_up(pcie)) ++ if (advk_pcie_link_training(pcie)) + val |= (PCI_EXP_LNKSTA_LT << 16); ++ if (advk_pcie_link_active(pcie)) ++ val |= (PCI_EXP_LNKSTA_DLLLA << 16); + *value = val; + return PCI_BRIDGE_EMUL_HANDLED; + } + +- case PCI_CAP_LIST_ID: + case PCI_EXP_DEVCAP: + case PCI_EXP_DEVCTL: +- case PCI_EXP_LNKCAP: + *value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); + return PCI_BRIDGE_EMUL_HANDLED; + default: +@@ -794,6 +920,8 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, + } + + static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = { ++ .read_base = advk_pci_bridge_emul_base_conf_read, ++ .write_base = advk_pci_bridge_emul_base_conf_write, + .read_pcie = advk_pci_bridge_emul_pcie_conf_read, + .write_pcie = advk_pci_bridge_emul_pcie_conf_write, + }; +@@ -805,7 +933,6 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = { + static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) + { + struct pci_bridge_emul *bridge = &pcie->bridge; +- int ret; + + bridge->conf.vendor = + cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff); +@@ -825,19 +952,17 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) + /* Support interrupt A for MSI feature */ + bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE; + +- bridge->has_pcie = true; +- bridge->data = pcie; +- bridge->ops = &advk_pci_bridge_emul_ops; +- +- /* PCIe config space can be initialized after pci_bridge_emul_init() */ +- ret = pci_bridge_emul_init(bridge, 0); +- if (ret < 0) +- return ret; ++ /* Aardvark HW provides PCIe Capability structure in version 2 */ ++ bridge->pcie_conf.cap = cpu_to_le16(2); + + /* Indicates supports for Completion Retry Status */ + bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS); + +- return 0; ++ bridge->has_pcie = true; ++ bridge->data = pcie; ++ bridge->ops = &advk_pci_bridge_emul_ops; ++ ++ return pci_bridge_emul_init(bridge, 0); + } + + static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, +@@ -889,6 +1014,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 *val) + { + struct advk_pcie *pcie = bus->sysdata; ++ int retry_count; + bool allow_crs; + u32 reg; + int ret; +@@ -911,18 +1037,8 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, + (le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & + PCI_EXP_RTCTL_CRSSVE); + +- if (advk_pcie_pio_is_running(pcie)) { +- /* +- * If it is possible return Completion Retry Status so caller +- * tries to issue the request again instead of failing. +- */ +- if (allow_crs) { +- *val = CFG_RD_CRS_VAL; +- return PCIBIOS_SUCCESSFUL; +- } +- *val = 0xffffffff; +- return PCIBIOS_SET_FAILED; +- } ++ if (advk_pcie_pio_is_running(pcie)) ++ goto try_crs; + + /* Program the control register */ + reg = advk_readl(pcie, PIO_CTRL); +@@ -941,30 +1057,24 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, + /* Program the data strobe */ + advk_writel(pcie, 0xf, PIO_WR_DATA_STRB); + +- /* Clear PIO DONE ISR and start the transfer */ +- advk_writel(pcie, 1, PIO_ISR); +- advk_writel(pcie, 1, PIO_START); ++ retry_count = 0; ++ do { ++ /* Clear PIO DONE ISR and start the transfer */ ++ advk_writel(pcie, 1, PIO_ISR); ++ advk_writel(pcie, 1, PIO_START); + +- ret = advk_pcie_wait_pio(pcie); +- if (ret < 0) { +- /* +- * If it is possible return Completion Retry Status so caller +- * tries to issue the request again instead of failing. +- */ +- if (allow_crs) { +- *val = CFG_RD_CRS_VAL; +- return PCIBIOS_SUCCESSFUL; +- } +- *val = 0xffffffff; +- return PCIBIOS_SET_FAILED; +- } ++ ret = advk_pcie_wait_pio(pcie); ++ if (ret < 0) ++ goto try_crs; + +- /* Check PIO status and get the read result */ +- ret = advk_pcie_check_pio_status(pcie, allow_crs, val); +- if (ret < 0) { +- *val = 0xffffffff; +- return PCIBIOS_SET_FAILED; +- } ++ retry_count += ret; ++ ++ /* Check PIO status and get the read result */ ++ ret = advk_pcie_check_pio_status(pcie, allow_crs, val); ++ } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT); ++ ++ if (ret < 0) ++ goto fail; + + if (size == 1) + *val = (*val >> (8 * (where & 3))) & 0xff; +@@ -972,6 +1082,20 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn, + *val = (*val >> (8 * (where & 3))) & 0xffff; + + return PCIBIOS_SUCCESSFUL; ++ ++try_crs: ++ /* ++ * If it is possible, return Completion Retry Status so that caller ++ * tries to issue the request again instead of failing. ++ */ ++ if (allow_crs) { ++ *val = CFG_RD_CRS_VAL; ++ return PCIBIOS_SUCCESSFUL; ++ } ++ ++fail: ++ *val = 0xffffffff; ++ return PCIBIOS_SET_FAILED; + } + + static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, +@@ -980,6 +1104,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, + struct advk_pcie *pcie = bus->sysdata; + u32 reg; + u32 data_strobe = 0x0; ++ int retry_count; + int offset; + int ret; + +@@ -1021,19 +1146,22 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, + /* Program the data strobe */ + advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB); + +- /* Clear PIO DONE ISR and start the transfer */ +- advk_writel(pcie, 1, PIO_ISR); +- advk_writel(pcie, 1, PIO_START); ++ retry_count = 0; ++ do { ++ /* Clear PIO DONE ISR and start the transfer */ ++ advk_writel(pcie, 1, PIO_ISR); ++ advk_writel(pcie, 1, PIO_START); + +- ret = advk_pcie_wait_pio(pcie); +- if (ret < 0) +- return PCIBIOS_SET_FAILED; ++ ret = advk_pcie_wait_pio(pcie); ++ if (ret < 0) ++ return PCIBIOS_SET_FAILED; + +- ret = advk_pcie_check_pio_status(pcie, false, NULL); +- if (ret < 0) +- return PCIBIOS_SET_FAILED; ++ retry_count += ret; + +- return PCIBIOS_SUCCESSFUL; ++ ret = advk_pcie_check_pio_status(pcie, false, NULL); ++ } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT); ++ ++ return ret < 0 ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL; + } + + static struct pci_ops advk_pcie_ops = { +@@ -1082,7 +1210,7 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain, + domain->host_data, handle_simple_irq, + NULL, NULL); + +- return hwirq; ++ return 0; + } + + static void advk_msi_irq_domain_free(struct irq_domain *domain, +@@ -1263,8 +1391,12 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie) + if (!(BIT(msi_idx) & msi_status)) + continue; + ++ /* ++ * msi_idx contains bits [4:0] of the msi_data and msi_data ++ * contains 16bit MSI interrupt number ++ */ + advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG); +- msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & 0xFF; ++ msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK; + generic_handle_irq(msi_data); + } + +@@ -1286,12 +1418,6 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie) + isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG); + isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); + +- if (!isr0_status && !isr1_status) { +- advk_writel(pcie, isr0_val, PCIE_ISR0_REG); +- advk_writel(pcie, isr1_val, PCIE_ISR1_REG); +- return; +- } +- + /* Process MSI interrupts */ + if (isr0_status & PCIE_ISR0_MSI_INT_PENDING) + advk_pcie_handle_msi(pcie); +@@ -1411,8 +1537,7 @@ static int advk_pcie_probe(struct platform_device *pdev) + * only PIO for issuing configuration transfers which does + * not use PCIe window configuration. + */ +- if (type != IORESOURCE_MEM && type != IORESOURCE_MEM_64 && +- type != IORESOURCE_IO) ++ if (type != IORESOURCE_MEM && type != IORESOURCE_IO) + continue; + + /* +@@ -1420,8 +1545,7 @@ static int advk_pcie_probe(struct platform_device *pdev) + * configuration is set to transparent memory access so it + * does not need window configuration. + */ +- if ((type == IORESOURCE_MEM || type == IORESOURCE_MEM_64) && +- entry->offset == 0) ++ if (type == IORESOURCE_MEM && entry->offset == 0) + continue; + + /* +diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c +index 67c46e52c0dc3..9dd4502d32a41 100644 +--- a/drivers/pci/controller/pci-hyperv.c ++++ b/drivers/pci/controller/pci-hyperv.c +@@ -1899,8 +1899,17 @@ static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus) + if (!hv_dev) + continue; + +- if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY) +- set_dev_node(&dev->dev, hv_dev->desc.virtual_numa_node); ++ if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY && ++ hv_dev->desc.virtual_numa_node < num_possible_nodes()) ++ /* ++ * The kernel may boot with some NUMA nodes offline ++ * (e.g. in a KDUMP kernel) or with NUMA disabled via ++ * "numa=off". In those cases, adjust the host provided ++ * NUMA node to a valid NUMA node used by the kernel. ++ */ ++ set_dev_node(&dev->dev, ++ numa_map_to_online_node( ++ hv_dev->desc.virtual_numa_node)); + + put_pcichild(hv_dev); + } +diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c +index ed13e81cd691d..2a3bf82aa4e26 100644 +--- a/drivers/pci/controller/pci-mvebu.c ++++ b/drivers/pci/controller/pci-mvebu.c +@@ -51,10 +51,14 @@ + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \ + PCIE_CONF_ADDR_EN) + #define PCIE_CONF_DATA_OFF 0x18fc ++#define PCIE_INT_CAUSE_OFF 0x1900 ++#define PCIE_INT_PM_PME BIT(28) + #define PCIE_MASK_OFF 0x1910 + #define PCIE_MASK_ENABLE_INTS 0x0f000000 + #define PCIE_CTRL_OFF 0x1a00 + #define PCIE_CTRL_X1_MODE 0x0001 ++#define PCIE_CTRL_RC_MODE BIT(1) ++#define PCIE_CTRL_MASTER_HOT_RESET BIT(24) + #define PCIE_STAT_OFF 0x1a04 + #define PCIE_STAT_BUS 0xff00 + #define PCIE_STAT_DEV 0x1f0000 +@@ -125,6 +129,11 @@ static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) + return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); + } + ++static u8 mvebu_pcie_get_local_bus_nr(struct mvebu_pcie_port *port) ++{ ++ return (mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_BUS) >> 8; ++} ++ + static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr) + { + u32 stat; +@@ -213,18 +222,21 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) + + static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) + { +- u32 cmd, mask; ++ u32 ctrl, cmd, mask; + +- /* Point PCIe unit MBUS decode windows to DRAM space. */ +- mvebu_pcie_setup_wins(port); ++ /* Setup PCIe controller to Root Complex mode. */ ++ ctrl = mvebu_readl(port, PCIE_CTRL_OFF); ++ ctrl |= PCIE_CTRL_RC_MODE; ++ mvebu_writel(port, ctrl, PCIE_CTRL_OFF); + +- /* Master + slave enable. */ ++ /* Disable Root Bridge I/O space, memory space and bus mastering. */ + cmd = mvebu_readl(port, PCIE_CMD_OFF); +- cmd |= PCI_COMMAND_IO; +- cmd |= PCI_COMMAND_MEMORY; +- cmd |= PCI_COMMAND_MASTER; ++ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + mvebu_writel(port, cmd, PCIE_CMD_OFF); + ++ /* Point PCIe unit MBUS decode windows to DRAM space. */ ++ mvebu_pcie_setup_wins(port); ++ + /* Enable interrupt lines A-D. */ + mask = mvebu_readl(port, PCIE_MASK_OFF); + mask |= PCIE_MASK_ENABLE_INTS; +@@ -371,8 +383,7 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) + + /* Are the new iobase/iolimit values invalid? */ + if (conf->iolimit < conf->iobase || +- conf->iolimitupper < conf->iobaseupper || +- !(conf->command & PCI_COMMAND_IO)) { ++ conf->iolimitupper < conf->iobaseupper) { + mvebu_pcie_set_window(port, port->io_target, port->io_attr, + &desired, &port->iowin); + return; +@@ -409,8 +420,7 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) + struct pci_bridge_emul_conf *conf = &port->bridge.conf; + + /* Are the new membase/memlimit values invalid? */ +- if (conf->memlimit < conf->membase || +- !(conf->command & PCI_COMMAND_MEMORY)) { ++ if (conf->memlimit < conf->membase) { + mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, + &desired, &port->memwin); + return; +@@ -430,6 +440,54 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) + &port->memwin); + } + ++static pci_bridge_emul_read_status_t ++mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, ++ int reg, u32 *value) ++{ ++ struct mvebu_pcie_port *port = bridge->data; ++ ++ switch (reg) { ++ case PCI_COMMAND: ++ *value = mvebu_readl(port, PCIE_CMD_OFF); ++ break; ++ ++ case PCI_PRIMARY_BUS: { ++ /* ++ * From the whole 32bit register we support reading from HW only ++ * secondary bus number which is mvebu local bus number. ++ * Other bits are retrieved only from emulated config buffer. ++ */ ++ __le32 *cfgspace = (__le32 *)&bridge->conf; ++ u32 val = le32_to_cpu(cfgspace[PCI_PRIMARY_BUS / 4]); ++ val &= ~0xff00; ++ val |= mvebu_pcie_get_local_bus_nr(port) << 8; ++ *value = val; ++ break; ++ } ++ ++ case PCI_INTERRUPT_LINE: { ++ /* ++ * From the whole 32bit register we support reading from HW only ++ * one bit: PCI_BRIDGE_CTL_BUS_RESET. ++ * Other bits are retrieved only from emulated config buffer. ++ */ ++ __le32 *cfgspace = (__le32 *)&bridge->conf; ++ u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]); ++ if (mvebu_readl(port, PCIE_CTRL_OFF) & PCIE_CTRL_MASTER_HOT_RESET) ++ val |= PCI_BRIDGE_CTL_BUS_RESET << 16; ++ else ++ val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16); ++ *value = val; ++ break; ++ } ++ ++ default: ++ return PCI_BRIDGE_EMUL_NOT_HANDLED; ++ } ++ ++ return PCI_BRIDGE_EMUL_HANDLED; ++} ++ + static pci_bridge_emul_read_status_t + mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, + int reg, u32 *value) +@@ -442,9 +500,7 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, + break; + + case PCI_EXP_DEVCTL: +- *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL) & +- ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE | +- PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE); ++ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL); + break; + + case PCI_EXP_LNKCAP: +@@ -468,6 +524,18 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, + *value = mvebu_readl(port, PCIE_RC_RTSTA); + break; + ++ case PCI_EXP_DEVCAP2: ++ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCAP2); ++ break; ++ ++ case PCI_EXP_DEVCTL2: ++ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL2); ++ break; ++ ++ case PCI_EXP_LNKCTL2: ++ *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL2); ++ break; ++ + default: + return PCI_BRIDGE_EMUL_NOT_HANDLED; + } +@@ -484,26 +552,16 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, + + switch (reg) { + case PCI_COMMAND: +- { +- if (!mvebu_has_ioport(port)) +- conf->command &= ~PCI_COMMAND_IO; +- +- if ((old ^ new) & PCI_COMMAND_IO) +- mvebu_pcie_handle_iobase_change(port); +- if ((old ^ new) & PCI_COMMAND_MEMORY) +- mvebu_pcie_handle_membase_change(port); ++ if (!mvebu_has_ioport(port)) { ++ conf->command = cpu_to_le16( ++ le16_to_cpu(conf->command) & ~PCI_COMMAND_IO); ++ new &= ~PCI_COMMAND_IO; ++ } + ++ mvebu_writel(port, new, PCIE_CMD_OFF); + break; +- } + + case PCI_IO_BASE: +- /* +- * We keep bit 1 set, it is a read-only bit that +- * indicates we support 32 bits addressing for the +- * I/O +- */ +- conf->iobase |= PCI_IO_RANGE_TYPE_32; +- conf->iolimit |= PCI_IO_RANGE_TYPE_32; + mvebu_pcie_handle_iobase_change(port); + break; + +@@ -516,7 +574,19 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, + break; + + case PCI_PRIMARY_BUS: +- mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus); ++ if (mask & 0xff00) ++ mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus); ++ break; ++ ++ case PCI_INTERRUPT_LINE: ++ if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { ++ u32 ctrl = mvebu_readl(port, PCIE_CTRL_OFF); ++ if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) ++ ctrl |= PCIE_CTRL_MASTER_HOT_RESET; ++ else ++ ctrl &= ~PCIE_CTRL_MASTER_HOT_RESET; ++ mvebu_writel(port, ctrl, PCIE_CTRL_OFF); ++ } + break; + + default: +@@ -532,13 +602,6 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, + + switch (reg) { + case PCI_EXP_DEVCTL: +- /* +- * Armada370 data says these bits must always +- * be zero when in root complex mode. +- */ +- new &= ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE | +- PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE); +- + mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL); + break; + +@@ -555,12 +618,31 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge, + break; + + case PCI_EXP_RTSTA: +- mvebu_writel(port, new, PCIE_RC_RTSTA); ++ /* ++ * PME Status bit in Root Status Register (PCIE_RC_RTSTA) ++ * is read-only and can be cleared only by writing 0b to the ++ * Interrupt Cause RW0C register (PCIE_INT_CAUSE_OFF). So ++ * clear PME via Interrupt Cause. ++ */ ++ if (new & PCI_EXP_RTSTA_PME) ++ mvebu_writel(port, ~PCIE_INT_PM_PME, PCIE_INT_CAUSE_OFF); ++ break; ++ ++ case PCI_EXP_DEVCTL2: ++ mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL2); ++ break; ++ ++ case PCI_EXP_LNKCTL2: ++ mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL2); ++ break; ++ ++ default: + break; + } + } + + static struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = { ++ .read_base = mvebu_pci_bridge_emul_base_conf_read, + .write_base = mvebu_pci_bridge_emul_base_conf_write, + .read_pcie = mvebu_pci_bridge_emul_pcie_conf_read, + .write_pcie = mvebu_pci_bridge_emul_pcie_conf_write, +@@ -570,9 +652,11 @@ static struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = { + * Initialize the configuration space of the PCI-to-PCI bridge + * associated with the given PCIe interface. + */ +-static void mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) ++static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) + { + struct pci_bridge_emul *bridge = &port->bridge; ++ u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP); ++ u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS); + + bridge->conf.vendor = PCI_VENDOR_ID_MARVELL; + bridge->conf.device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16; +@@ -585,11 +669,17 @@ static void mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) + bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32; + } + ++ /* ++ * Older mvebu hardware provides PCIe Capability structure only in ++ * version 1. New hardware provides it in version 2. ++ */ ++ bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver); ++ + bridge->has_pcie = true; + bridge->data = port; + bridge->ops = &mvebu_pci_bridge_emul_ops; + +- pci_bridge_emul_init(bridge, PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR); ++ return pci_bridge_emul_init(bridge, PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR); + } + + static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys) +@@ -1112,9 +1202,94 @@ static int mvebu_pcie_probe(struct platform_device *pdev) + continue; + } + ++ ret = mvebu_pci_bridge_emul_init(port); ++ if (ret < 0) { ++ dev_err(dev, "%s: cannot init emulated bridge\n", ++ port->name); ++ devm_iounmap(dev, port->base); ++ port->base = NULL; ++ mvebu_pcie_powerdown(port); ++ continue; ++ } ++ ++ /* ++ * PCIe topology exported by mvebu hw is quite complicated. In ++ * reality has something like N fully independent host bridges ++ * where each host bridge has one PCIe Root Port (which acts as ++ * PCI Bridge device). Each host bridge has its own independent ++ * internal registers, independent access to PCI config space, ++ * independent interrupt lines, independent window and memory ++ * access configuration. But additionally there is some kind of ++ * peer-to-peer support between PCIe devices behind different ++ * host bridges limited just to forwarding of memory and I/O ++ * transactions (forwarding of error messages and config cycles ++ * is not supported). So we could say there are N independent ++ * PCIe Root Complexes. ++ * ++ * For this kind of setup DT should have been structured into ++ * N independent PCIe controllers / host bridges. But instead ++ * structure in past was defined to put PCIe Root Ports of all ++ * host bridges into one bus zero, like in classic multi-port ++ * Root Complex setup with just one host bridge. ++ * ++ * This means that pci-mvebu.c driver provides "virtual" bus 0 ++ * on which registers all PCIe Root Ports (PCI Bridge devices) ++ * specified in DT by their BDF addresses and virtually routes ++ * PCI config access of each PCI bridge device to specific PCIe ++ * host bridge. ++ * ++ * Normally PCI Bridge should choose between Type 0 and Type 1 ++ * config requests based on primary and secondary bus numbers ++ * configured on the bridge itself. But because mvebu PCI Bridge ++ * does not have registers for primary and secondary bus numbers ++ * in its config space, it determinates type of config requests ++ * via its own custom way. ++ * ++ * There are two options how mvebu determinate type of config ++ * request. ++ * ++ * 1. If Secondary Bus Number Enable bit is not set or is not ++ * available (applies for pre-XP PCIe controllers) then Type 0 ++ * is used if target bus number equals Local Bus Number (bits ++ * [15:8] in register 0x1a04) and target device number differs ++ * from Local Device Number (bits [20:16] in register 0x1a04). ++ * Type 1 is used if target bus number differs from Local Bus ++ * Number. And when target bus number equals Local Bus Number ++ * and target device equals Local Device Number then request is ++ * routed to Local PCI Bridge (PCIe Root Port). ++ * ++ * 2. If Secondary Bus Number Enable bit is set (bit 7 in ++ * register 0x1a2c) then mvebu hw determinate type of config ++ * request like compliant PCI Bridge based on primary bus number ++ * which is configured via Local Bus Number (bits [15:8] in ++ * register 0x1a04) and secondary bus number which is configured ++ * via Secondary Bus Number (bits [7:0] in register 0x1a2c). ++ * Local PCI Bridge (PCIe Root Port) is available on primary bus ++ * as device with Local Device Number (bits [20:16] in register ++ * 0x1a04). ++ * ++ * Secondary Bus Number Enable bit is disabled by default and ++ * option 2. is not available on pre-XP PCIe controllers. Hence ++ * this driver always use option 1. ++ * ++ * Basically it means that primary and secondary buses shares ++ * one virtual number configured via Local Bus Number bits and ++ * Local Device Number bits determinates if accessing primary ++ * or secondary bus. Set Local Device Number to 1 and redirect ++ * all writes of PCI Bridge Secondary Bus Number register to ++ * Local Bus Number (bits [15:8] in register 0x1a04). ++ * ++ * So when accessing devices on buses behind secondary bus ++ * number it would work correctly. And also when accessing ++ * device 0 at secondary bus number via config space would be ++ * correctly routed to secondary bus. Due to issues described ++ * in mvebu_pcie_setup_hw(), PCI Bridges at primary bus (zero) ++ * are not accessed directly via PCI config space but rarher ++ * indirectly via kernel emulated PCI bridge driver. ++ */ + mvebu_pcie_setup_hw(port); + mvebu_pcie_set_local_dev_nr(port, 1); +- mvebu_pci_bridge_emul_init(port); ++ mvebu_pcie_set_local_bus_nr(port, 0); + } + + pcie->nports = i; +diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c +index e64536047b651..7d7d8970fdc25 100644 +--- a/drivers/pci/controller/pci-xgene.c ++++ b/drivers/pci/controller/pci-xgene.c +@@ -466,7 +466,7 @@ static int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size) + return 1; + } + +- if ((size > SZ_1K) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 0))) { ++ if ((size > SZ_1K) && (size < SZ_4G) && !(*ib_reg_mask & (1 << 0))) { + *ib_reg_mask |= (1 << 0); + return 0; + } +diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c +index 17c59b0d6978b..21207df680ccf 100644 +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -79,6 +79,9 @@ + #define PCIE_ICMD_PM_REG 0x198 + #define PCIE_TURN_OFF_LINK BIT(4) + ++#define PCIE_MISC_CTRL_REG 0x348 ++#define PCIE_DISABLE_DVFSRC_VLT_REQ BIT(1) ++ + #define PCIE_TRANS_TABLE_BASE_REG 0x800 + #define PCIE_ATR_SRC_ADDR_MSB_OFFSET 0x4 + #define PCIE_ATR_TRSL_ADDR_LSB_OFFSET 0x8 +@@ -297,6 +300,11 @@ static int mtk_pcie_startup_port(struct mtk_pcie_port *port) + val &= ~PCIE_INTX_ENABLE; + writel_relaxed(val, port->base + PCIE_INT_ENABLE_REG); + ++ /* Disable DVFSRC voltage request */ ++ val = readl_relaxed(port->base + PCIE_MISC_CTRL_REG); ++ val |= PCIE_DISABLE_DVFSRC_VLT_REQ; ++ writel_relaxed(val, port->base + PCIE_MISC_CTRL_REG); ++ + /* Assert all reset signals */ + val = readl_relaxed(port->base + PCIE_RST_CTRL_REG); + val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB; +diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c +index 8f3131844e777..bfb13f358d073 100644 +--- a/drivers/pci/controller/pcie-rcar-host.c ++++ b/drivers/pci/controller/pcie-rcar-host.c +@@ -52,10 +52,10 @@ struct rcar_msi { + */ + static void __iomem *pcie_base; + /* +- * Static copy of bus clock pointer, so we can check whether the clock +- * is enabled or not. ++ * Static copy of PCIe device pointer, so we can check whether the ++ * device is runtime suspended or not. + */ +-static struct clk *pcie_bus_clk; ++static struct device *pcie_dev; + #endif + + /* Structure representing the PCIe interface */ +@@ -794,7 +794,7 @@ static int rcar_pcie_get_resources(struct rcar_pcie_host *host) + #ifdef CONFIG_ARM + /* Cache static copy for L1 link state fixup hook on aarch32 */ + pcie_base = pcie->base; +- pcie_bus_clk = host->bus_clk; ++ pcie_dev = pcie->dev; + #endif + + return 0; +@@ -1064,7 +1064,7 @@ static int rcar_pcie_aarch32_abort_handler(unsigned long addr, + + spin_lock_irqsave(&pmsr_lock, flags); + +- if (!pcie_base || !__clk_is_enabled(pcie_bus_clk)) { ++ if (!pcie_base || pm_runtime_suspended(pcie_dev)) { + ret = 1; + goto unlock_exit; + } +diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h +index 69fd401691be6..10d7e7e1b5530 100644 +--- a/drivers/pci/hotplug/pciehp.h ++++ b/drivers/pci/hotplug/pciehp.h +@@ -75,6 +75,8 @@ extern int pciehp_poll_time; + * @reset_lock: prevents access to the Data Link Layer Link Active bit in the + * Link Status register and to the Presence Detect State bit in the Slot + * Status register during a slot reset which may cause them to flap ++ * @depth: Number of additional hotplug ports in the path to the root bus, ++ * used as lock subclass for @reset_lock + * @ist_running: flag to keep user request waiting while IRQ thread is running + * @request_result: result of last user request submitted to the IRQ thread + * @requester: wait queue to wake up on completion of user request, +@@ -106,6 +108,7 @@ struct controller { + + struct hotplug_slot hotplug_slot; /* hotplug core interface */ + struct rw_semaphore reset_lock; ++ unsigned int depth; + unsigned int ist_running; + int request_result; + wait_queue_head_t requester; +diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c +index ad3393930ecb4..e7fe4b42f0394 100644 +--- a/drivers/pci/hotplug/pciehp_core.c ++++ b/drivers/pci/hotplug/pciehp_core.c +@@ -166,7 +166,7 @@ static void pciehp_check_presence(struct controller *ctrl) + { + int occupied; + +- down_read(&ctrl->reset_lock); ++ down_read_nested(&ctrl->reset_lock, ctrl->depth); + mutex_lock(&ctrl->state_lock); + + occupied = pciehp_card_present_or_link_active(ctrl); +diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c +index 3024d7e85e6a7..b0692f33b03ae 100644 +--- a/drivers/pci/hotplug/pciehp_hpc.c ++++ b/drivers/pci/hotplug/pciehp_hpc.c +@@ -583,7 +583,7 @@ static void pciehp_ignore_dpc_link_change(struct controller *ctrl, + * the corresponding link change may have been ignored above. + * Synthesize it to ensure that it is acted on. + */ +- down_read(&ctrl->reset_lock); ++ down_read_nested(&ctrl->reset_lock, ctrl->depth); + if (!pciehp_check_link_active(ctrl)) + pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); + up_read(&ctrl->reset_lock); +@@ -642,6 +642,8 @@ read_status: + */ + if (ctrl->power_fault_detected) + status &= ~PCI_EXP_SLTSTA_PFD; ++ else if (status & PCI_EXP_SLTSTA_PFD) ++ ctrl->power_fault_detected = true; + + events |= status; + if (!events) { +@@ -651,7 +653,7 @@ read_status: + } + + if (status) { +- pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events); ++ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status); + + /* + * In MSI mode, all event bits must be zero before the port +@@ -725,8 +727,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) + } + + /* Check Power Fault Detected */ +- if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { +- ctrl->power_fault_detected = 1; ++ if (events & PCI_EXP_SLTSTA_PFD) { + ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl)); + pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, + PCI_EXP_SLTCTL_ATTN_IND_ON); +@@ -746,7 +747,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) + * Disable requests have higher priority than Presence Detect Changed + * or Data Link Layer State Changed events. + */ +- down_read(&ctrl->reset_lock); ++ down_read_nested(&ctrl->reset_lock, ctrl->depth); + if (events & DISABLE_SLOT) + pciehp_handle_disable_request(ctrl); + else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC)) +@@ -880,7 +881,7 @@ int pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe) + if (probe) + return 0; + +- down_write(&ctrl->reset_lock); ++ down_write_nested(&ctrl->reset_lock, ctrl->depth); + + if (!ATTN_BUTTN(ctrl)) { + ctrl_mask |= PCI_EXP_SLTCTL_PDCE; +@@ -936,6 +937,20 @@ static inline void dbg_ctrl(struct controller *ctrl) + + #define FLAG(x, y) (((x) & (y)) ? '+' : '-') + ++static inline int pcie_hotplug_depth(struct pci_dev *dev) ++{ ++ struct pci_bus *bus = dev->bus; ++ int depth = 0; ++ ++ while (bus->parent) { ++ bus = bus->parent; ++ if (bus->self && bus->self->is_hotplug_bridge) ++ depth++; ++ } ++ ++ return depth; ++} ++ + struct controller *pcie_init(struct pcie_device *dev) + { + struct controller *ctrl; +@@ -949,6 +964,7 @@ struct controller *pcie_init(struct pcie_device *dev) + return NULL; + + ctrl->pcie = dev; ++ ctrl->depth = pcie_hotplug_depth(dev->port); + pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); + + if (pdev->hotplug_user_indicators) +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 4b4792940e869..cc4c2b8a5efd7 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -148,6 +148,9 @@ static noinline void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 s + raw_spinlock_t *lock = &desc->dev->msi_lock; + unsigned long flags; + ++ if (!desc->msi_attrib.can_mask) ++ return; ++ + raw_spin_lock_irqsave(lock, flags); + desc->msi_mask &= ~clear; + desc->msi_mask |= set; +@@ -181,7 +184,8 @@ static void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl) + { + void __iomem *desc_addr = pci_msix_desc_addr(desc); + +- writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); ++ if (desc->msi_attrib.can_mask) ++ writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); + } + + static inline void pci_msix_mask(struct msi_desc *desc) +@@ -200,23 +204,17 @@ static inline void pci_msix_unmask(struct msi_desc *desc) + + static void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask) + { +- if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual) +- return; +- + if (desc->msi_attrib.is_msix) + pci_msix_mask(desc); +- else if (desc->msi_attrib.maskbit) ++ else + pci_msi_mask(desc, mask); + } + + static void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask) + { +- if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual) +- return; +- + if (desc->msi_attrib.is_msix) + pci_msix_unmask(desc); +- else if (desc->msi_attrib.maskbit) ++ else + pci_msi_unmask(desc, mask); + } + +@@ -370,6 +368,11 @@ static void free_msi_irqs(struct pci_dev *dev) + for (i = 0; i < entry->nvec_used; i++) + BUG_ON(irq_has_action(entry->irq + i)); + ++ if (dev->msi_irq_groups) { ++ msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups); ++ dev->msi_irq_groups = NULL; ++ } ++ + pci_msi_teardown_msi_irqs(dev); + + list_for_each_entry_safe(entry, tmp, msi_list, list) { +@@ -381,11 +384,6 @@ static void free_msi_irqs(struct pci_dev *dev) + list_del(&entry->list); + free_msi_entry(entry); + } +- +- if (dev->msi_irq_groups) { +- msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups); +- dev->msi_irq_groups = NULL; +- } + } + + static void pci_intx_for_msi(struct pci_dev *dev, int enable) +@@ -479,12 +477,16 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) + goto out; + + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); ++ /* Lies, damned lies, and MSIs */ ++ if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING) ++ control |= PCI_MSI_FLAGS_MASKBIT; + + entry->msi_attrib.is_msix = 0; + entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT); + entry->msi_attrib.is_virtual = 0; + entry->msi_attrib.entry_nr = 0; +- entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT); ++ entry->msi_attrib.can_mask = !pci_msi_ignore_mask && ++ !!(control & PCI_MSI_FLAGS_MASKBIT); + entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ + entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1; + entry->msi_attrib.multiple = ilog2(__roundup_pow_of_two(nvec)); +@@ -495,7 +497,7 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) + entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32; + + /* Save the initial mask status */ +- if (entry->msi_attrib.maskbit) ++ if (entry->msi_attrib.can_mask) + pci_read_config_dword(dev, entry->mask_pos, &entry->msi_mask); + + out: +@@ -638,10 +640,13 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, + entry->msi_attrib.is_virtual = + entry->msi_attrib.entry_nr >= vec_count; + ++ entry->msi_attrib.can_mask = !pci_msi_ignore_mask && ++ !entry->msi_attrib.is_virtual; ++ + entry->msi_attrib.default_irq = dev->irq; + entry->mask_base = base; + +- if (!entry->msi_attrib.is_virtual) { ++ if (entry->msi_attrib.can_mask) { + addr = pci_msix_desc_addr(entry); + entry->msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); + } +@@ -716,9 +721,6 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, + goto out_disable; + } + +- /* Ensure that all table entries are masked. */ +- msix_mask_all(base, tsize); +- + ret = msix_setup_entries(dev, base, entries, nvec, affd); + if (ret) + goto out_disable; +@@ -745,6 +747,16 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, + /* Set MSI-X enabled bits and unmask the function */ + pci_intx_for_msi(dev, 0); + dev->msix_enabled = 1; ++ ++ /* ++ * Ensure that all table entries are masked to prevent ++ * stale entries from firing in a crash kernel. ++ * ++ * Done late to deal with a broken Marvell NVME device ++ * which takes the MSI-X mask bits into account even ++ * when MSI-X is disabled, which prevents MSI delivery. ++ */ ++ msix_mask_all(base, tsize); + pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); + + pcibios_free_irq(dev); +@@ -771,7 +783,7 @@ out_free: + free_msi_irqs(dev); + + out_disable: +- pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); ++ pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); + + return ret; + } +@@ -1181,19 +1193,24 @@ EXPORT_SYMBOL(pci_free_irq_vectors); + + /** + * pci_irq_vector - return Linux IRQ number of a device vector +- * @dev: PCI device to operate on +- * @nr: device-relative interrupt vector index (0-based). ++ * @dev: PCI device to operate on ++ * @nr: Interrupt vector index (0-based) ++ * ++ * @nr has the following meanings depending on the interrupt mode: ++ * MSI-X: The index in the MSI-X vector table ++ * MSI: The index of the enabled MSI vectors ++ * INTx: Must be 0 ++ * ++ * Return: The Linux interrupt number or -EINVAl if @nr is out of range. + */ + int pci_irq_vector(struct pci_dev *dev, unsigned int nr) + { + if (dev->msix_enabled) { + struct msi_desc *entry; +- int i = 0; + + for_each_pci_msi_entry(entry, dev) { +- if (i == nr) ++ if (entry->msi_attrib.entry_nr == nr) + return entry->irq; +- i++; + } + WARN_ON_ONCE(1); + return -EINVAL; +@@ -1217,17 +1234,22 @@ EXPORT_SYMBOL(pci_irq_vector); + * pci_irq_get_affinity - return the affinity of a particular MSI vector + * @dev: PCI device to operate on + * @nr: device-relative interrupt vector index (0-based). ++ * ++ * @nr has the following meanings depending on the interrupt mode: ++ * MSI-X: The index in the MSI-X vector table ++ * MSI: The index of the enabled MSI vectors ++ * INTx: Must be 0 ++ * ++ * Return: A cpumask pointer or NULL if @nr is out of range + */ + const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr) + { + if (dev->msix_enabled) { + struct msi_desc *entry; +- int i = 0; + + for_each_pci_msi_entry(entry, dev) { +- if (i == nr) ++ if (entry->msi_attrib.entry_nr == nr) + return &entry->affinity->mask; +- i++; + } + WARN_ON_ONCE(1); + return NULL; +diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c +index fdaf86a888b73..37504c2cce9b8 100644 +--- a/drivers/pci/pci-bridge-emul.c ++++ b/drivers/pci/pci-bridge-emul.c +@@ -139,8 +139,13 @@ struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = { + .ro = GENMASK(7, 0), + }, + ++ /* ++ * If expansion ROM is unsupported then ROM Base Address register must ++ * be implemented as read-only register that return 0 when read, same ++ * as for unused Base Address registers. ++ */ + [PCI_ROM_ADDRESS1 / 4] = { +- .rw = GENMASK(31, 11) | BIT(0), ++ .ro = ~0, + }, + + /* +@@ -171,41 +176,55 @@ struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] = + [PCI_CAP_LIST_ID / 4] = { + /* + * Capability ID, Next Capability Pointer and +- * Capabilities register are all read-only. ++ * bits [14:0] of Capabilities register are all read-only. ++ * Bit 15 of Capabilities register is reserved. + */ +- .ro = ~0, ++ .ro = GENMASK(30, 0), + }, + + [PCI_EXP_DEVCAP / 4] = { +- .ro = ~0, ++ /* ++ * Bits [31:29] and [17:16] are reserved. ++ * Bits [27:18] are reserved for non-upstream ports. ++ * Bits 28 and [14:6] are reserved for non-endpoint devices. ++ * Other bits are read-only. ++ */ ++ .ro = BIT(15) | GENMASK(5, 0), + }, + + [PCI_EXP_DEVCTL / 4] = { +- /* Device control register is RW */ +- .rw = GENMASK(15, 0), ++ /* ++ * Device control register is RW, except bit 15 which is ++ * reserved for non-endpoints or non-PCIe-to-PCI/X bridges. ++ */ ++ .rw = GENMASK(14, 0), + + /* + * Device status register has bits 6 and [3:0] W1C, [5:4] RO, +- * the rest is reserved ++ * the rest is reserved. Also bit 6 is reserved for non-upstream ++ * ports. + */ +- .w1c = (BIT(6) | GENMASK(3, 0)) << 16, ++ .w1c = GENMASK(3, 0) << 16, + .ro = GENMASK(5, 4) << 16, + }, + + [PCI_EXP_LNKCAP / 4] = { +- /* All bits are RO, except bit 23 which is reserved */ +- .ro = lower_32_bits(~BIT(23)), ++ /* ++ * All bits are RO, except bit 23 which is reserved and ++ * bit 18 which is reserved for non-upstream ports. ++ */ ++ .ro = lower_32_bits(~(BIT(23) | PCI_EXP_LNKCAP_CLKPM)), + }, + + [PCI_EXP_LNKCTL / 4] = { + /* + * Link control has bits [15:14], [11:3] and [1:0] RW, the +- * rest is reserved. ++ * rest is reserved. Bit 8 is reserved for non-upstream ports. + * + * Link status has bits [13:0] RO, and bits [15:14] + * W1C. + */ +- .rw = GENMASK(15, 14) | GENMASK(11, 3) | GENMASK(1, 0), ++ .rw = GENMASK(15, 14) | GENMASK(11, 9) | GENMASK(7, 3) | GENMASK(1, 0), + .ro = GENMASK(13, 0) << 16, + .w1c = GENMASK(15, 14) << 16, + }, +@@ -277,11 +296,9 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge, + + if (bridge->has_pcie) { + bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START; ++ bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST); + bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP; +- /* Set PCIe v2, root port, slot support */ +- bridge->pcie_conf.cap = +- cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4 | 2 | +- PCI_EXP_FLAGS_SLOT); ++ bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4); + bridge->pcie_cap_regs_behavior = + kmemdup(pcie_cap_regs_behavior, + sizeof(pcie_cap_regs_behavior), +@@ -290,6 +307,27 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge, + kfree(bridge->pci_regs_behavior); + return -ENOMEM; + } ++ /* These bits are applicable only for PCI and reserved on PCIe */ ++ bridge->pci_regs_behavior[PCI_CACHE_LINE_SIZE / 4].ro &= ++ ~GENMASK(15, 8); ++ bridge->pci_regs_behavior[PCI_COMMAND / 4].ro &= ++ ~((PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE | ++ PCI_COMMAND_VGA_PALETTE | PCI_COMMAND_WAIT | ++ PCI_COMMAND_FAST_BACK) | ++ (PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK | ++ PCI_STATUS_DEVSEL_MASK) << 16); ++ bridge->pci_regs_behavior[PCI_PRIMARY_BUS / 4].ro &= ++ ~GENMASK(31, 24); ++ bridge->pci_regs_behavior[PCI_IO_BASE / 4].ro &= ++ ~((PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK | ++ PCI_STATUS_DEVSEL_MASK) << 16); ++ bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].rw &= ++ ~((PCI_BRIDGE_CTL_MASTER_ABORT | ++ BIT(8) | BIT(9) | BIT(11)) << 16); ++ bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].ro &= ++ ~((PCI_BRIDGE_CTL_FAST_BACK) << 16); ++ bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].w1c &= ++ ~(BIT(10) << 16); + } + + if (flags & PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR) { +@@ -431,8 +469,21 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, + /* Clear the W1C bits */ + new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); + ++ /* Save the new value with the cleared W1C bits into the cfgspace */ + cfgspace[reg / 4] = cpu_to_le32(new); + ++ /* ++ * Clear the W1C bits not specified by the write mask, so that the ++ * write_op() does not clear them. ++ */ ++ new &= ~(behavior[reg / 4].w1c & ~mask); ++ ++ /* ++ * Set the W1C bits specified by the write mask, so that write_op() ++ * knows about that they are to be cleared. ++ */ ++ new |= (value << shift) & (behavior[reg / 4].w1c & mask); ++ + if (write_op) + write_op(bridge, reg, old, new, mask); + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index ce2ab62b64cfa..a101faf3e88a9 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -3719,6 +3719,14 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) + struct pci_dev *bridge; + u32 cap, ctl2; + ++ /* ++ * Per PCIe r5.0, sec 9.3.5.10, the AtomicOp Requester Enable bit ++ * in Device Control 2 is reserved in VFs and the PF value applies ++ * to all associated VFs. ++ */ ++ if (dev->is_virtfn) ++ return -EINVAL; ++ + if (!pci_is_pcie(dev)) + return -EINVAL; + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 4537d1ea14fdc..0663762ea69db 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3612,6 +3612,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset); + + /* + * Root port on some Cavium CN8xxx chips do not successfully complete a bus +@@ -4102,6 +4103,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9120, + quirk_dma_func1_alias); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9123, + quirk_dma_func1_alias); ++/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c136 */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9125, ++ quirk_dma_func1_alias); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9128, + quirk_dma_func1_alias); + /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c14 */ +@@ -5795,3 +5799,9 @@ static void apex_pci_fixup_class(struct pci_dev *pdev) + } + DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a, + PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class); ++ ++static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) ++{ ++ pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING; ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup); +diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c +index e211e2619680c..f70197154a362 100644 +--- a/drivers/pcmcia/cs.c ++++ b/drivers/pcmcia/cs.c +@@ -666,18 +666,16 @@ static int pccardd(void *__skt) + if (events || sysfs_events) + continue; + ++ set_current_state(TASK_INTERRUPTIBLE); + if (kthread_should_stop()) + break; + +- set_current_state(TASK_INTERRUPTIBLE); +- + schedule(); + +- /* make sure we are running */ +- __set_current_state(TASK_RUNNING); +- + try_to_freeze(); + } ++ /* make sure we are running before we exit */ ++ __set_current_state(TASK_RUNNING); + + /* shut down socket, if a device is still present */ + if (skt->state & SOCKET_PRESENT) { +diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c +index bb15a8bdbaab5..1cac528707111 100644 +--- a/drivers/pcmcia/rsrc_nonstatic.c ++++ b/drivers/pcmcia/rsrc_nonstatic.c +@@ -690,6 +690,9 @@ static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s, + unsigned long min = base; + int ret; + ++ if (!res) ++ return NULL; ++ + data.mask = align - 1; + data.offset = base & data.mask; + data.map = &s_data->io_db; +@@ -809,6 +812,9 @@ static struct resource *nonstatic_find_mem_region(u_long base, u_long num, + unsigned long min, max; + int ret, i, j; + ++ if (!res) ++ return NULL; ++ + low = low || !(s->features & SS_CAP_PAGE_REGS); + + data.mask = align - 1; +diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c +index bc3cba5f8c5dc..400eb7f579dce 100644 +--- a/drivers/perf/arm-cmn.c ++++ b/drivers/perf/arm-cmn.c +@@ -1561,7 +1561,8 @@ static int arm_cmn_probe(struct platform_device *pdev) + + err = perf_pmu_register(&cmn->pmu, name, -1); + if (err) +- cpuhp_state_remove_instance(arm_cmn_hp_state, &cmn->cpuhp_node); ++ cpuhp_state_remove_instance_nocalls(arm_cmn_hp_state, &cmn->cpuhp_node); ++ + return err; + } + +@@ -1572,7 +1573,7 @@ static int arm_cmn_remove(struct platform_device *pdev) + writel_relaxed(0, cmn->dtc[0].base + CMN_DT_DTC_CTL); + + perf_pmu_unregister(&cmn->pmu); +- cpuhp_state_remove_instance(arm_cmn_hp_state, &cmn->cpuhp_node); ++ cpuhp_state_remove_instance_nocalls(arm_cmn_hp_state, &cmn->cpuhp_node); + return 0; + } + +diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c +index cd2332bf0e31a..fdbd64c03e12b 100644 +--- a/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c ++++ b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c +@@ -9,6 +9,7 @@ + + #include <linux/bitfield.h> + #include <linux/bitops.h> ++#include <linux/bits.h> + #include <linux/clk.h> + #include <linux/delay.h> + #include <linux/io.h> +@@ -250,7 +251,7 @@ static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy) + (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) | + (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24)); + regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1, +- DIV_ROUND_UP(priv->config.clk_pre, temp)); ++ DIV_ROUND_UP(priv->config.clk_pre, BITS_PER_BYTE)); + + regmap_write(priv->regmap, MIPI_DSI_HS_TIM, + DIV_ROUND_UP(priv->config.hs_exit, temp) | +diff --git a/drivers/phy/broadcom/Kconfig b/drivers/phy/broadcom/Kconfig +index fd92b73b71095..1dcfa3bd1442d 100644 +--- a/drivers/phy/broadcom/Kconfig ++++ b/drivers/phy/broadcom/Kconfig +@@ -95,8 +95,7 @@ config PHY_BRCM_USB + depends on OF + select GENERIC_PHY + select SOC_BRCMSTB if ARCH_BRCMSTB +- default ARCH_BCM4908 +- default ARCH_BRCMSTB ++ default ARCH_BCM4908 || ARCH_BRCMSTB + help + Enable this to support the Broadcom STB USB PHY. + This driver is required by the USB XHCI, EHCI and OHCI +diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c +index 116fb23aebd99..0f1deb6e0eabf 100644 +--- a/drivers/phy/broadcom/phy-brcm-usb.c ++++ b/drivers/phy/broadcom/phy-brcm-usb.c +@@ -18,6 +18,7 @@ + #include <linux/soc/brcmstb/brcmstb.h> + #include <dt-bindings/phy/phy.h> + #include <linux/mfd/syscon.h> ++#include <linux/suspend.h> + + #include "phy-brcm-usb-init.h" + +@@ -70,12 +71,35 @@ struct brcm_usb_phy_data { + int init_count; + int wake_irq; + struct brcm_usb_phy phys[BRCM_USB_PHY_ID_MAX]; ++ struct notifier_block pm_notifier; ++ bool pm_active; + }; + + static s8 *node_reg_names[BRCM_REGS_MAX] = { + "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec" + }; + ++static int brcm_pm_notifier(struct notifier_block *notifier, ++ unsigned long pm_event, ++ void *unused) ++{ ++ struct brcm_usb_phy_data *priv = ++ container_of(notifier, struct brcm_usb_phy_data, pm_notifier); ++ ++ switch (pm_event) { ++ case PM_HIBERNATION_PREPARE: ++ case PM_SUSPEND_PREPARE: ++ priv->pm_active = true; ++ break; ++ case PM_POST_RESTORE: ++ case PM_POST_HIBERNATION: ++ case PM_POST_SUSPEND: ++ priv->pm_active = false; ++ break; ++ } ++ return NOTIFY_DONE; ++} ++ + static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id) + { + struct phy *gphy = dev_id; +@@ -91,6 +115,9 @@ static int brcm_usb_phy_init(struct phy *gphy) + struct brcm_usb_phy_data *priv = + container_of(phy, struct brcm_usb_phy_data, phys[phy->id]); + ++ if (priv->pm_active) ++ return 0; ++ + /* + * Use a lock to make sure a second caller waits until + * the base phy is inited before using it. +@@ -120,6 +147,9 @@ static int brcm_usb_phy_exit(struct phy *gphy) + struct brcm_usb_phy_data *priv = + container_of(phy, struct brcm_usb_phy_data, phys[phy->id]); + ++ if (priv->pm_active) ++ return 0; ++ + dev_dbg(&gphy->dev, "EXIT\n"); + if (phy->id == BRCM_USB_PHY_2_0) + brcm_usb_uninit_eohci(&priv->ini); +@@ -488,6 +518,9 @@ static int brcm_usb_phy_probe(struct platform_device *pdev) + if (err) + return err; + ++ priv->pm_notifier.notifier_call = brcm_pm_notifier; ++ register_pm_notifier(&priv->pm_notifier); ++ + mutex_init(&priv->mutex); + + /* make sure invert settings are correct */ +@@ -528,7 +561,10 @@ static int brcm_usb_phy_probe(struct platform_device *pdev) + + static int brcm_usb_phy_remove(struct platform_device *pdev) + { ++ struct brcm_usb_phy_data *priv = dev_get_drvdata(&pdev->dev); ++ + sysfs_remove_group(&pdev->dev.kobj, &brcm_usb_phy_group); ++ unregister_pm_notifier(&priv->pm_notifier); + + return 0; + } +@@ -539,6 +575,7 @@ static int brcm_usb_phy_suspend(struct device *dev) + struct brcm_usb_phy_data *priv = dev_get_drvdata(dev); + + if (priv->init_count) { ++ dev_dbg(dev, "SUSPEND\n"); + priv->ini.wake_enabled = device_may_wakeup(dev); + if (priv->phys[BRCM_USB_PHY_3_0].inited) + brcm_usb_uninit_xhci(&priv->ini); +@@ -578,6 +615,7 @@ static int brcm_usb_phy_resume(struct device *dev) + * Uninitialize anything that wasn't previously initialized. + */ + if (priv->init_count) { ++ dev_dbg(dev, "RESUME\n"); + if (priv->wake_irq >= 0) + disable_irq_wake(priv->wake_irq); + brcm_usb_init_common(&priv->ini); +diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c +index e93818e3991fd..3e2d096d54fd7 100644 +--- a/drivers/phy/cadence/phy-cadence-sierra.c ++++ b/drivers/phy/cadence/phy-cadence-sierra.c +@@ -215,7 +215,10 @@ static const int pll_mux_parent_index[][SIERRA_NUM_CMN_PLLC_PARENTS] = { + [CMN_PLLLC1] = { PLL1_REFCLK, PLL0_REFCLK }, + }; + +-static u32 cdns_sierra_pll_mux_table[] = { 0, 1 }; ++static u32 cdns_sierra_pll_mux_table[][SIERRA_NUM_CMN_PLLC_PARENTS] = { ++ [CMN_PLLLC] = { 0, 1 }, ++ [CMN_PLLLC1] = { 1, 0 }, ++}; + + struct cdns_sierra_inst { + struct phy *phy; +@@ -436,11 +439,25 @@ static const struct phy_ops ops = { + static u8 cdns_sierra_pll_mux_get_parent(struct clk_hw *hw) + { + struct cdns_sierra_pll_mux *mux = to_cdns_sierra_pll_mux(hw); ++ struct regmap_field *plllc1en_field = mux->plllc1en_field; ++ struct regmap_field *termen_field = mux->termen_field; + struct regmap_field *field = mux->pfdclk_sel_preg; + unsigned int val; ++ int index; + + regmap_field_read(field, &val); +- return clk_mux_val_to_index(hw, cdns_sierra_pll_mux_table, 0, val); ++ ++ if (strstr(clk_hw_get_name(hw), clk_names[CDNS_SIERRA_PLL_CMNLC1])) { ++ index = clk_mux_val_to_index(hw, cdns_sierra_pll_mux_table[CMN_PLLLC1], 0, val); ++ if (index == 1) { ++ regmap_field_write(plllc1en_field, 1); ++ regmap_field_write(termen_field, 1); ++ } ++ } else { ++ index = clk_mux_val_to_index(hw, cdns_sierra_pll_mux_table[CMN_PLLLC], 0, val); ++ } ++ ++ return index; + } + + static int cdns_sierra_pll_mux_set_parent(struct clk_hw *hw, u8 index) +@@ -458,7 +475,11 @@ static int cdns_sierra_pll_mux_set_parent(struct clk_hw *hw, u8 index) + ret |= regmap_field_write(termen_field, 1); + } + +- val = cdns_sierra_pll_mux_table[index]; ++ if (strstr(clk_hw_get_name(hw), clk_names[CDNS_SIERRA_PLL_CMNLC1])) ++ val = cdns_sierra_pll_mux_table[CMN_PLLLC1][index]; ++ else ++ val = cdns_sierra_pll_mux_table[CMN_PLLLC][index]; ++ + ret |= regmap_field_write(field, val); + + return ret; +@@ -496,8 +517,8 @@ static int cdns_sierra_pll_mux_register(struct cdns_sierra_phy *sp, + for (i = 0; i < num_parents; i++) { + clk = sp->input_clks[pll_mux_parent_index[clk_index][i]]; + if (IS_ERR_OR_NULL(clk)) { +- dev_err(dev, "No parent clock for derived_refclk\n"); +- return PTR_ERR(clk); ++ dev_err(dev, "No parent clock for PLL mux clocks\n"); ++ return IS_ERR(clk) ? PTR_ERR(clk) : -ENOENT; + } + parent_names[i] = __clk_get_name(clk); + } +diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c +index 28ad9403c4414..67b005d5b9e35 100644 +--- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c ++++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c +@@ -146,6 +146,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) + return -ENOMEM; + + mipi_tx->driver_data = of_device_get_match_data(dev); ++ if (!mipi_tx->driver_data) ++ return -ENODEV; + + mipi_tx->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mipi_tx->regs)) +diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c +index cdcef865fe9e5..db39b0c4649a2 100644 +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -12,6 +12,7 @@ + #include <linux/iopoll.h> + #include <linux/mfd/syscon.h> + #include <linux/module.h> ++#include <linux/nvmem-consumer.h> + #include <linux/of_address.h> + #include <linux/of_device.h> + #include <linux/phy/phy.h> +@@ -41,6 +42,9 @@ + #define SSUSB_SIFSLV_V2_U3PHYD 0x200 + #define SSUSB_SIFSLV_V2_U3PHYA 0x400 + ++#define U3P_MISC_REG1 0x04 ++#define MR1_EFUSE_AUTO_LOAD_DIS BIT(6) ++ + #define U3P_USBPHYACR0 0x000 + #define PA0_RG_U2PLL_FORCE_ON BIT(15) + #define PA0_USB20_PLL_PREDIV GENMASK(7, 6) +@@ -133,6 +137,8 @@ + #define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24) + + #define U3P_U3_PHYA_REG0 0x000 ++#define P3A_RG_IEXT_INTR GENMASK(15, 10) ++#define P3A_RG_IEXT_INTR_VAL(x) ((0x3f & (x)) << 10) + #define P3A_RG_CLKDRV_OFF GENMASK(3, 2) + #define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2) + +@@ -187,6 +193,19 @@ + #define P3D_RG_FWAKE_TH GENMASK(21, 16) + #define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16) + ++#define U3P_U3_PHYD_IMPCAL0 0x010 ++#define P3D_RG_FORCE_TX_IMPEL BIT(31) ++#define P3D_RG_TX_IMPEL GENMASK(28, 24) ++#define P3D_RG_TX_IMPEL_VAL(x) ((0x1f & (x)) << 24) ++ ++#define U3P_U3_PHYD_IMPCAL1 0x014 ++#define P3D_RG_FORCE_RX_IMPEL BIT(31) ++#define P3D_RG_RX_IMPEL GENMASK(28, 24) ++#define P3D_RG_RX_IMPEL_VAL(x) ((0x1f & (x)) << 24) ++ ++#define U3P_U3_PHYD_RSV 0x054 ++#define P3D_RG_EFUSE_AUTO_LOAD_DIS BIT(12) ++ + #define U3P_U3_PHYD_CDR1 0x05c + #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) + #define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) +@@ -307,6 +326,11 @@ struct mtk_phy_pdata { + * 48M PLL, fix it by switching PLL to 26M from default 48M + */ + bool sw_pll_48m_to_26m; ++ /* ++ * Some SoCs (e.g. mt8195) drop a bit when use auto load efuse, ++ * support sw way, also support it for v2/v3 optionally. ++ */ ++ bool sw_efuse_supported; + enum mtk_phy_version version; + }; + +@@ -336,6 +360,10 @@ struct mtk_phy_instance { + struct regmap *type_sw; + u32 type_sw_reg; + u32 type_sw_index; ++ u32 efuse_sw_en; ++ u32 efuse_intr; ++ u32 efuse_tx_imp; ++ u32 efuse_rx_imp; + int eye_src; + int eye_vrt; + int eye_term; +@@ -1040,6 +1068,130 @@ static int phy_type_set(struct mtk_phy_instance *instance) + return 0; + } + ++static int phy_efuse_get(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) ++{ ++ struct device *dev = &instance->phy->dev; ++ int ret = 0; ++ ++ /* tphy v1 doesn't support sw efuse, skip it */ ++ if (!tphy->pdata->sw_efuse_supported) { ++ instance->efuse_sw_en = 0; ++ return 0; ++ } ++ ++ /* software efuse is optional */ ++ instance->efuse_sw_en = device_property_read_bool(dev, "nvmem-cells"); ++ if (!instance->efuse_sw_en) ++ return 0; ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr); ++ if (ret) { ++ dev_err(dev, "fail to get u2 intr efuse, %d\n", ret); ++ break; ++ } ++ ++ /* no efuse, ignore it */ ++ if (!instance->efuse_intr) { ++ dev_warn(dev, "no u2 intr efuse, but dts enable it\n"); ++ instance->efuse_sw_en = 0; ++ break; ++ } ++ ++ dev_dbg(dev, "u2 efuse - intr %x\n", instance->efuse_intr); ++ break; ++ ++ case PHY_TYPE_USB3: ++ case PHY_TYPE_PCIE: ++ ret = nvmem_cell_read_variable_le_u32(dev, "intr", &instance->efuse_intr); ++ if (ret) { ++ dev_err(dev, "fail to get u3 intr efuse, %d\n", ret); ++ break; ++ } ++ ++ ret = nvmem_cell_read_variable_le_u32(dev, "rx_imp", &instance->efuse_rx_imp); ++ if (ret) { ++ dev_err(dev, "fail to get u3 rx_imp efuse, %d\n", ret); ++ break; ++ } ++ ++ ret = nvmem_cell_read_variable_le_u32(dev, "tx_imp", &instance->efuse_tx_imp); ++ if (ret) { ++ dev_err(dev, "fail to get u3 tx_imp efuse, %d\n", ret); ++ break; ++ } ++ ++ /* no efuse, ignore it */ ++ if (!instance->efuse_intr && ++ !instance->efuse_rx_imp && ++ !instance->efuse_tx_imp) { ++ dev_warn(dev, "no u3 intr efuse, but dts enable it\n"); ++ instance->efuse_sw_en = 0; ++ break; ++ } ++ ++ dev_dbg(dev, "u3 efuse - intr %x, rx_imp %x, tx_imp %x\n", ++ instance->efuse_intr, instance->efuse_rx_imp,instance->efuse_tx_imp); ++ break; ++ default: ++ dev_err(dev, "no sw efuse for type %d\n", instance->type); ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static void phy_efuse_set(struct mtk_phy_instance *instance) ++{ ++ struct device *dev = &instance->phy->dev; ++ struct u2phy_banks *u2_banks = &instance->u2_banks; ++ struct u3phy_banks *u3_banks = &instance->u3_banks; ++ u32 tmp; ++ ++ if (!instance->efuse_sw_en) ++ return; ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ tmp = readl(u2_banks->misc + U3P_MISC_REG1); ++ tmp |= MR1_EFUSE_AUTO_LOAD_DIS; ++ writel(tmp, u2_banks->misc + U3P_MISC_REG1); ++ ++ tmp = readl(u2_banks->com + U3P_USBPHYACR1); ++ tmp &= ~PA1_RG_INTR_CAL; ++ tmp |= PA1_RG_INTR_CAL_VAL(instance->efuse_intr); ++ writel(tmp, u2_banks->com + U3P_USBPHYACR1); ++ break; ++ case PHY_TYPE_USB3: ++ case PHY_TYPE_PCIE: ++ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); ++ tmp |= P3D_RG_EFUSE_AUTO_LOAD_DIS; ++ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RSV); ++ ++ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); ++ tmp &= ~P3D_RG_TX_IMPEL; ++ tmp |= P3D_RG_TX_IMPEL_VAL(instance->efuse_tx_imp); ++ tmp |= P3D_RG_FORCE_TX_IMPEL; ++ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); ++ ++ tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); ++ tmp &= ~P3D_RG_RX_IMPEL; ++ tmp |= P3D_RG_RX_IMPEL_VAL(instance->efuse_rx_imp); ++ tmp |= P3D_RG_FORCE_RX_IMPEL; ++ writel(tmp, u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); ++ ++ tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); ++ tmp &= ~P3A_RG_IEXT_INTR; ++ tmp |= P3A_RG_IEXT_INTR_VAL(instance->efuse_intr); ++ writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0); ++ break; ++ default: ++ dev_warn(dev, "no sw efuse for type %d\n", instance->type); ++ break; ++ } ++} ++ + static int mtk_phy_init(struct phy *phy) + { + struct mtk_phy_instance *instance = phy_get_drvdata(phy); +@@ -1050,6 +1202,8 @@ static int mtk_phy_init(struct phy *phy) + if (ret) + return ret; + ++ phy_efuse_set(instance); ++ + switch (instance->type) { + case PHY_TYPE_USB2: + u2_phy_instance_init(tphy, instance); +@@ -1134,6 +1288,7 @@ static struct phy *mtk_phy_xlate(struct device *dev, + struct mtk_phy_instance *instance = NULL; + struct device_node *phy_np = args->np; + int index; ++ int ret; + + if (args->args_count != 1) { + dev_err(dev, "invalid number of cells in 'phy' property\n"); +@@ -1174,6 +1329,10 @@ static struct phy *mtk_phy_xlate(struct device *dev, + return ERR_PTR(-EINVAL); + } + ++ ret = phy_efuse_get(tphy, instance); ++ if (ret) ++ return ERR_PTR(ret); ++ + phy_parse_property(tphy, instance); + phy_type_set(instance); + +@@ -1196,10 +1355,12 @@ static const struct mtk_phy_pdata tphy_v1_pdata = { + + static const struct mtk_phy_pdata tphy_v2_pdata = { + .avoid_rx_sen_degradation = false, ++ .sw_efuse_supported = true, + .version = MTK_PHY_V2, + }; + + static const struct mtk_phy_pdata tphy_v3_pdata = { ++ .sw_efuse_supported = true, + .version = MTK_PHY_V3, + }; + +@@ -1210,6 +1371,7 @@ static const struct mtk_phy_pdata mt8173_pdata = { + + static const struct mtk_phy_pdata mt8195_pdata = { + .sw_pll_48m_to_26m = true, ++ .sw_efuse_supported = true, + .version = MTK_PHY_V3, + }; + +diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c +index 4076580fc2cd9..ab1b0986aa671 100644 +--- a/drivers/phy/microchip/sparx5_serdes.c ++++ b/drivers/phy/microchip/sparx5_serdes.c +@@ -2475,10 +2475,10 @@ static int sparx5_serdes_probe(struct platform_device *pdev) + return -EINVAL; + } + iomem = devm_ioremap(priv->dev, iores->start, resource_size(iores)); +- if (IS_ERR(iomem)) { ++ if (!iomem) { + dev_err(priv->dev, "Unable to get serdes registers: %s\n", + iores->name); +- return PTR_ERR(iomem); ++ return -ENOMEM; + } + for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) { + struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx]; +diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c +index 288c9c67aa748..ccb4045685cdd 100644 +--- a/drivers/phy/phy-core-mipi-dphy.c ++++ b/drivers/phy/phy-core-mipi-dphy.c +@@ -36,7 +36,7 @@ int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, + + cfg->clk_miss = 0; + cfg->clk_post = 60000 + 52 * ui; +- cfg->clk_pre = 8000; ++ cfg->clk_pre = 8; + cfg->clk_prepare = 38000; + cfg->clk_settle = 95000; + cfg->clk_term_en = 0; +@@ -97,7 +97,7 @@ int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg) + if (cfg->clk_post < (60000 + 52 * ui)) + return -EINVAL; + +- if (cfg->clk_pre < 8000) ++ if (cfg->clk_pre < 8) + return -EINVAL; + + if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000) +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c +index f14032170b1c1..06b04606dd7ea 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp.c +@@ -3632,7 +3632,7 @@ static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { + .nlanes = 1, + + .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, +- .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), + .tx_tbl = sc8180x_qmp_pcie_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), + .rx_tbl = sc8180x_qmp_pcie_rx_tbl, +diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c +index 3c1d3b71c825b..f1d97fbd13318 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c ++++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c +@@ -561,7 +561,7 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) + { + struct device *dev = &qphy->phy->dev; + const struct qusb2_phy_cfg *cfg = qphy->cfg; +- u8 *val; ++ u8 *val, hstx_trim; + + /* efuse register is optional */ + if (!qphy->cell) +@@ -575,7 +575,13 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) + * set while configuring the phy. + */ + val = nvmem_cell_read(qphy->cell, NULL); +- if (IS_ERR(val) || !val[0]) { ++ if (IS_ERR(val)) { ++ dev_dbg(dev, "failed to read a valid hs-tx trim value\n"); ++ return; ++ } ++ hstx_trim = val[0]; ++ kfree(val); ++ if (!hstx_trim) { + dev_dbg(dev, "failed to read a valid hs-tx trim value\n"); + return; + } +@@ -583,12 +589,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) + /* Fused TUNE1/2 value is the higher nibble only */ + if (cfg->update_tune1_with_efuse) + qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], +- val[0] << HSTX_TRIM_SHIFT, +- HSTX_TRIM_MASK); ++ hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK); + else + qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2], +- val[0] << HSTX_TRIM_SHIFT, +- HSTX_TRIM_MASK); ++ hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK); + } + + static int qusb2_phy_set_mode(struct phy *phy, +diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c +index ae4bac024c7b1..7e61202aa234e 100644 +--- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c ++++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c +@@ -33,7 +33,7 @@ + + #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) + #define RETENABLEN BIT(3) +-#define FSEL_MASK GENMASK(7, 5) ++#define FSEL_MASK GENMASK(6, 4) + #define FSEL_DEFAULT (0x3 << 4) + + #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58) +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c +index 347dc79a18c18..630e01b5c19b9 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c +@@ -5,6 +5,7 @@ + * Author: Wyon Bi <bivvy.bi@rock-chips.com> + */ + ++#include <linux/bits.h> + #include <linux/kernel.h> + #include <linux/clk.h> + #include <linux/iopoll.h> +@@ -364,7 +365,7 @@ static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno) + * The value of counter for HS Tclk-pre + * Tclk-pre = Tpin_txbyteclkhs * value + */ +- clk_pre = DIV_ROUND_UP(cfg->clk_pre, t_txbyteclkhs); ++ clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE); + + /* + * The value of counter for HS Tlpx Time +diff --git a/drivers/phy/socionext/phy-uniphier-usb3ss.c b/drivers/phy/socionext/phy-uniphier-usb3ss.c +index 6700645bcbe6b..3b5ffc16a6947 100644 +--- a/drivers/phy/socionext/phy-uniphier-usb3ss.c ++++ b/drivers/phy/socionext/phy-uniphier-usb3ss.c +@@ -22,11 +22,13 @@ + #include <linux/reset.h> + + #define SSPHY_TESTI 0x0 +-#define SSPHY_TESTO 0x4 + #define TESTI_DAT_MASK GENMASK(13, 6) + #define TESTI_ADR_MASK GENMASK(5, 1) + #define TESTI_WR_EN BIT(0) + ++#define SSPHY_TESTO 0x4 ++#define TESTO_DAT_MASK GENMASK(7, 0) ++ + #define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) } + + #define CDR_CPD_TRIM PHY_F(7, 3, 0) /* RxPLL charge pump current */ +@@ -84,12 +86,12 @@ static void uniphier_u3ssphy_set_param(struct uniphier_u3ssphy_priv *priv, + val = FIELD_PREP(TESTI_DAT_MASK, 1); + val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no); + uniphier_u3ssphy_testio_write(priv, val); +- val = readl(priv->base + SSPHY_TESTO); ++ val = readl(priv->base + SSPHY_TESTO) & TESTO_DAT_MASK; + + /* update value */ +- val &= ~FIELD_PREP(TESTI_DAT_MASK, field_mask); ++ val &= ~field_mask; + data = field_mask & (p->value << p->field.lsb); +- val = FIELD_PREP(TESTI_DAT_MASK, data); ++ val = FIELD_PREP(TESTI_DAT_MASK, data | val); + val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no); + uniphier_u3ssphy_testio_write(priv, val); + uniphier_u3ssphy_testio_write(priv, val | TESTI_WR_EN); +diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c +index 937a14fa7448a..da05642d3bd4a 100644 +--- a/drivers/phy/st/phy-stm32-usbphyc.c ++++ b/drivers/phy/st/phy-stm32-usbphyc.c +@@ -225,7 +225,7 @@ static int stm32_usbphyc_pll_enable(struct stm32_usbphyc *usbphyc) + + ret = __stm32_usbphyc_pll_disable(usbphyc); + if (ret) +- return ret; ++ goto dec_n_pll_cons; + } + + ret = stm32_usbphyc_regulators_enable(usbphyc); +diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c +index 5fd2e8a08bfcf..d0ab69750c6b4 100644 +--- a/drivers/phy/ti/phy-gmii-sel.c ++++ b/drivers/phy/ti/phy-gmii-sel.c +@@ -320,6 +320,8 @@ static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv) + u64 size; + + offset = of_get_address(dev->of_node, 0, &size, NULL); ++ if (!offset) ++ return -EINVAL; + priv->num_ports = size / sizeof(u32); + if (!priv->num_ports) + return -EINVAL; +diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c +index 126f5b8735cc1..8963fbf7aa73b 100644 +--- a/drivers/phy/ti/phy-j721e-wiz.c ++++ b/drivers/phy/ti/phy-j721e-wiz.c +@@ -233,6 +233,7 @@ static const struct clk_div_table clk_div_table[] = { + { .val = 1, .div = 2, }, + { .val = 2, .div = 4, }, + { .val = 3, .div = 8, }, ++ { /* sentinel */ }, + }; + + static const struct wiz_clk_div_sel clk_div_sel[] = { +diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c +index f478d8a17115b..9be9535ad7ab7 100644 +--- a/drivers/phy/xilinx/phy-zynqmp.c ++++ b/drivers/phy/xilinx/phy-zynqmp.c +@@ -134,7 +134,8 @@ + #define PROT_BUS_WIDTH_10 0x0 + #define PROT_BUS_WIDTH_20 0x1 + #define PROT_BUS_WIDTH_40 0x2 +-#define PROT_BUS_WIDTH_SHIFT 2 ++#define PROT_BUS_WIDTH_SHIFT(n) ((n) * 2) ++#define PROT_BUS_WIDTH_MASK(n) GENMASK((n) * 2 + 1, (n) * 2) + + /* Number of GT lanes */ + #define NUM_LANES 4 +@@ -445,12 +446,12 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy *gtr_phy) + static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy) + { + struct xpsgtr_dev *gtr_dev = gtr_phy->dev; ++ u32 mask = PROT_BUS_WIDTH_MASK(gtr_phy->lane); ++ u32 val = PROT_BUS_WIDTH_10 << PROT_BUS_WIDTH_SHIFT(gtr_phy->lane); + + /* Set SGMII protocol TX and RX bus width to 10 bits. */ +- xpsgtr_write(gtr_dev, TX_PROT_BUS_WIDTH, +- PROT_BUS_WIDTH_10 << (gtr_phy->lane * PROT_BUS_WIDTH_SHIFT)); +- xpsgtr_write(gtr_dev, RX_PROT_BUS_WIDTH, +- PROT_BUS_WIDTH_10 << (gtr_phy->lane * PROT_BUS_WIDTH_SHIFT)); ++ xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val); ++ xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val); + + xpsgtr_bypass_scrambler_8b10b(gtr_phy); + } +diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig +index c9c5efc927311..5973a279e6b8c 100644 +--- a/drivers/pinctrl/bcm/Kconfig ++++ b/drivers/pinctrl/bcm/Kconfig +@@ -35,6 +35,7 @@ config PINCTRL_BCM63XX + select PINCONF + select GENERIC_PINCONF + select GPIOLIB ++ select REGMAP + select GPIO_REGMAP + + config PINCTRL_BCM6318 +diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +index 6e6fefeb21ead..cb339299adf92 100644 +--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c +@@ -1243,6 +1243,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) + raw_spin_lock_init(&pc->irq_lock[i]); + } + ++ pc->pctl_desc = *pdata->pctl_desc; ++ pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); ++ if (IS_ERR(pc->pctl_dev)) { ++ gpiochip_remove(&pc->gpio_chip); ++ return PTR_ERR(pc->pctl_dev); ++ } ++ ++ pc->gpio_range = *pdata->gpio_range; ++ pc->gpio_range.base = pc->gpio_chip.base; ++ pc->gpio_range.gc = &pc->gpio_chip; ++ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); ++ + girq = &pc->gpio_chip.irq; + girq->chip = &bcm2835_gpio_irq_chip; + girq->parent_handler = bcm2835_gpio_irq_handler; +@@ -1250,15 +1262,19 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) + girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, + sizeof(*girq->parents), + GFP_KERNEL); +- if (!girq->parents) +- return -ENOMEM; ++ if (!girq->parents) { ++ err = -ENOMEM; ++ goto out_remove; ++ } + + if (is_7211) { + pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, + sizeof(*pc->wake_irq), + GFP_KERNEL); +- if (!pc->wake_irq) +- return -ENOMEM; ++ if (!pc->wake_irq) { ++ err = -ENOMEM; ++ goto out_remove; ++ } + } + + /* +@@ -1286,8 +1302,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) + + len = strlen(dev_name(pc->dev)) + 16; + name = devm_kzalloc(pc->dev, len, GFP_KERNEL); +- if (!name) +- return -ENOMEM; ++ if (!name) { ++ err = -ENOMEM; ++ goto out_remove; ++ } + + snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); + +@@ -1306,22 +1324,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) + err = gpiochip_add_data(&pc->gpio_chip, pc); + if (err) { + dev_err(dev, "could not add GPIO chip\n"); +- return err; +- } +- +- pc->pctl_desc = *pdata->pctl_desc; +- pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); +- if (IS_ERR(pc->pctl_dev)) { +- gpiochip_remove(&pc->gpio_chip); +- return PTR_ERR(pc->pctl_dev); ++ goto out_remove; + } + +- pc->gpio_range = *pdata->gpio_range; +- pc->gpio_range.base = pc->gpio_chip.base; +- pc->gpio_range.gc = &pc->gpio_chip; +- pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); +- + return 0; ++ ++out_remove: ++ pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); ++ return err; + } + + static struct platform_driver bcm2835_pinctrl_driver = { +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index 5082102d7d0d9..ffe39336fcaca 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -2100,6 +2100,8 @@ int pinctrl_enable(struct pinctrl_dev *pctldev) + if (error) { + dev_err(pctldev->dev, "could not claim hogs: %i\n", + error); ++ pinctrl_free_pindescs(pctldev, pctldev->desc->pins, ++ pctldev->desc->npins); + mutex_destroy(&pctldev->mutex); + kfree(pctldev); + +diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c +index 85750974d1825..826d494f3cc66 100644 +--- a/drivers/pinctrl/intel/pinctrl-intel.c ++++ b/drivers/pinctrl/intel/pinctrl-intel.c +@@ -451,8 +451,8 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) + value &= ~PADCFG0_PMODE_MASK; + value |= PADCFG0_PMODE_GPIO; + +- /* Disable input and output buffers */ +- value |= PADCFG0_GPIORXDIS; ++ /* Disable TX buffer and enable RX (this will be input) */ ++ value &= ~PADCFG0_GPIORXDIS; + value |= PADCFG0_GPIOTXDIS; + + /* Disable SCI/SMI/NMI generation */ +@@ -497,9 +497,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, + + intel_gpio_set_gpio_mode(padcfg0); + +- /* Disable TX buffer and enable RX (this will be input) */ +- __intel_gpio_set_direction(padcfg0, true); +- + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +@@ -1115,9 +1112,6 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) + + intel_gpio_set_gpio_mode(reg); + +- /* Disable TX buffer and enable RX (this will be input) */ +- __intel_gpio_set_direction(reg, true); +- + value = readl(reg); + + value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV); +@@ -1216,6 +1210,39 @@ static irqreturn_t intel_gpio_irq(int irq, void *data) + return IRQ_RETVAL(ret); + } + ++static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) ++{ ++ int i; ++ ++ for (i = 0; i < pctrl->ncommunities; i++) { ++ const struct intel_community *community; ++ void __iomem *base; ++ unsigned int gpp; ++ ++ community = &pctrl->communities[i]; ++ base = community->regs; ++ ++ for (gpp = 0; gpp < community->ngpps; gpp++) { ++ /* Mask and clear all interrupts */ ++ writel(0, base + community->ie_offset + gpp * 4); ++ writel(0xffff, base + community->is_offset + gpp * 4); ++ } ++ } ++} ++ ++static int intel_gpio_irq_init_hw(struct gpio_chip *gc) ++{ ++ struct intel_pinctrl *pctrl = gpiochip_get_data(gc); ++ ++ /* ++ * Make sure the interrupt lines are in a proper state before ++ * further configuration. ++ */ ++ intel_gpio_irq_init(pctrl); ++ ++ return 0; ++} ++ + static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl, + const struct intel_community *community) + { +@@ -1320,6 +1347,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) + girq->num_parents = 0; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; ++ girq->init_hw = intel_gpio_irq_init_hw; + + ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); + if (ret) { +@@ -1695,26 +1723,6 @@ int intel_pinctrl_suspend_noirq(struct device *dev) + } + EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq); + +-static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) +-{ +- size_t i; +- +- for (i = 0; i < pctrl->ncommunities; i++) { +- const struct intel_community *community; +- void __iomem *base; +- unsigned int gpp; +- +- community = &pctrl->communities[i]; +- base = community->regs; +- +- for (gpp = 0; gpp < community->ngpps; gpp++) { +- /* Mask and clear all interrupts */ +- writel(0, base + community->ie_offset + gpp * 4); +- writel(0xffff, base + community->is_offset + gpp * 4); +- } +- } +-} +- + static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value) + { + u32 curr, updated; +diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +index 45ebdeba985ae..12163d3c4bcb0 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +@@ -285,8 +285,12 @@ static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n, + desc = (const struct mtk_pin_desc *)hw->soc->pins; + *gpio_chip = &hw->chip; + +- /* Be greedy to guess first gpio_n is equal to eint_n */ +- if (desc[eint_n].eint.eint_n == eint_n) ++ /* ++ * Be greedy to guess first gpio_n is equal to eint_n. ++ * Only eint virtual eint number is greater than gpio number. ++ */ ++ if (hw->soc->npins > eint_n && ++ desc[eint_n].eint.eint_n == eint_n) + *gpio_n = eint_n; + else + *gpio_n = mtk_xt_find_eint_num(hw, eint_n); +diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c +index bae9d429b813e..ecab9064a8458 100644 +--- a/drivers/pinctrl/pinctrl-amd.c ++++ b/drivers/pinctrl/pinctrl-amd.c +@@ -598,14 +598,14 @@ static struct irq_chip amd_gpio_irqchip = { + + #define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF)) + +-static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) ++static bool do_amd_gpio_irq_handler(int irq, void *dev_id) + { + struct amd_gpio *gpio_dev = dev_id; + struct gpio_chip *gc = &gpio_dev->gc; +- irqreturn_t ret = IRQ_NONE; + unsigned int i, irqnr; + unsigned long flags; + u32 __iomem *regs; ++ bool ret = false; + u32 regval; + u64 status, mask; + +@@ -627,6 +627,14 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) + /* Each status bit covers four pins */ + for (i = 0; i < 4; i++) { + regval = readl(regs + i); ++ /* caused wake on resume context for shared IRQ */ ++ if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) { ++ dev_dbg(&gpio_dev->pdev->dev, ++ "Waking due to GPIO %d: 0x%x", ++ irqnr + i, regval); ++ return true; ++ } ++ + if (!(regval & PIN_IRQ_PENDING) || + !(regval & BIT(INTERRUPT_MASK_OFF))) + continue; +@@ -650,9 +658,12 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) + } + writel(regval, regs + i); + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); +- ret = IRQ_HANDLED; ++ ret = true; + } + } ++ /* did not cause wake on resume context for shared IRQ */ ++ if (irq < 0) ++ return false; + + /* Signal EOI to the GPIO unit */ + raw_spin_lock_irqsave(&gpio_dev->lock, flags); +@@ -664,6 +675,16 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) + return ret; + } + ++static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) ++{ ++ return IRQ_RETVAL(do_amd_gpio_irq_handler(irq, dev_id)); ++} ++ ++static bool __maybe_unused amd_gpio_check_wake(void *dev_id) ++{ ++ return do_amd_gpio_irq_handler(-1, dev_id); ++} ++ + static int amd_get_groups_count(struct pinctrl_dev *pctldev) + { + struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev); +@@ -1033,6 +1054,7 @@ static int amd_gpio_probe(struct platform_device *pdev) + goto out2; + + platform_set_drvdata(pdev, gpio_dev); ++ acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev); + + dev_dbg(&pdev->dev, "amd gpio driver loaded\n"); + return ret; +@@ -1050,6 +1072,7 @@ static int amd_gpio_remove(struct platform_device *pdev) + gpio_dev = platform_get_drvdata(pdev); + + gpiochip_remove(&gpio_dev->gc); ++ acpi_unregister_wakeup_handler(amd_gpio_check_wake, gpio_dev); + + return 0; + } +diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c +index fb713f9c53d0e..3f0143087cc77 100644 +--- a/drivers/pinctrl/pinctrl-equilibrium.c ++++ b/drivers/pinctrl/pinctrl-equilibrium.c +@@ -675,6 +675,11 @@ static int eqbr_build_functions(struct eqbr_pinctrl_drv_data *drvdata) + return ret; + + for (i = 0; i < nr_funcs; i++) { ++ ++ /* Ignore the same function with multiple groups */ ++ if (funcs[i].name == NULL) ++ continue; ++ + ret = pinmux_generic_add_function(drvdata->pctl_dev, + funcs[i].name, + funcs[i].groups, +@@ -815,7 +820,7 @@ static int pinctrl_reg(struct eqbr_pinctrl_drv_data *drvdata) + + ret = eqbr_build_functions(drvdata); + if (ret) { +- dev_err(dev, "Failed to build groups\n"); ++ dev_err(dev, "Failed to build functions\n"); + return ret; + } + +diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c +index 49e32684dbb25..ecab6bf63dc6d 100644 +--- a/drivers/pinctrl/pinctrl-k210.c ++++ b/drivers/pinctrl/pinctrl-k210.c +@@ -482,7 +482,7 @@ static int k210_pinconf_get_drive(unsigned int max_strength_ua) + { + int i; + +- for (i = K210_PC_DRIVE_MAX; i; i--) { ++ for (i = K210_PC_DRIVE_MAX; i >= 0; i--) { + if (k210_pinconf_drive_strength[i] <= max_strength_ua) + return i; + } +@@ -527,7 +527,7 @@ static int k210_pinconf_set_param(struct pinctrl_dev *pctldev, + case PIN_CONFIG_BIAS_PULL_UP: + if (!arg) + return -EINVAL; +- val |= K210_PC_PD; ++ val |= K210_PC_PU; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg *= 1000; +diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c +index 5ce260f152ce5..dc52da94af0b9 100644 +--- a/drivers/pinctrl/pinctrl-rockchip.c ++++ b/drivers/pinctrl/pinctrl-rockchip.c +@@ -2748,7 +2748,7 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, info); + +- ret = of_platform_populate(np, rockchip_bank_match, NULL, NULL); ++ ret = of_platform_populate(np, NULL, NULL, &pdev->dev); + if (ret) { + dev_err(&pdev->dev, "failed to register gpio device\n"); + return ret; +diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig +index 5ff4207df66e1..f1b5176a5085b 100644 +--- a/drivers/pinctrl/qcom/Kconfig ++++ b/drivers/pinctrl/qcom/Kconfig +@@ -189,6 +189,7 @@ config PINCTRL_QCOM_SPMI_PMIC + select PINMUX + select PINCONF + select GENERIC_PINCONF ++ select GPIOLIB + select GPIOLIB_IRQCHIP + select IRQ_DOMAIN_HIERARCHY + help +@@ -203,6 +204,7 @@ config PINCTRL_QCOM_SSBI_PMIC + select PINMUX + select PINCONF + select GENERIC_PINCONF ++ select GPIOLIB + select GPIOLIB_IRQCHIP + select IRQ_DOMAIN_HIERARCHY + help +diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c +index c51793f6546f1..fdfd7b8f3a76d 100644 +--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c ++++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c +@@ -1310,6 +1310,7 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = { + .ngpios = 151, + .wakeirq_map = sdm845_pdc_map, + .nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map), ++ .wakeirq_dual_edge_errata = true, + }; + + static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = { +diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c +index 4d8f8636c2b39..1c042d39380c6 100644 +--- a/drivers/pinctrl/qcom/pinctrl-sm8350.c ++++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c +@@ -1597,10 +1597,10 @@ static const struct msm_pingroup sm8350_groups[] = { + [200] = PINGROUP(200, qdss_gpio, _, _, _, _, _, _, _, _), + [201] = PINGROUP(201, _, _, _, _, _, _, _, _, _), + [202] = PINGROUP(202, _, _, _, _, _, _, _, _, _), +- [203] = UFS_RESET(ufs_reset, 0x1d8000), +- [204] = SDC_PINGROUP(sdc2_clk, 0x1cf000, 14, 6), +- [205] = SDC_PINGROUP(sdc2_cmd, 0x1cf000, 11, 3), +- [206] = SDC_PINGROUP(sdc2_data, 0x1cf000, 9, 0), ++ [203] = UFS_RESET(ufs_reset, 0xd8000), ++ [204] = SDC_PINGROUP(sdc2_clk, 0xcf000, 14, 6), ++ [205] = SDC_PINGROUP(sdc2_cmd, 0xcf000, 11, 3), ++ [206] = SDC_PINGROUP(sdc2_data, 0xcf000, 9, 0), + }; + + static const struct msm_gpio_wakeirq_map sm8350_pdc_map[] = { +diff --git a/drivers/pinctrl/ralink/pinctrl-mt7620.c b/drivers/pinctrl/ralink/pinctrl-mt7620.c +index 425d55a2ee19f..6853b5b8b0fe7 100644 +--- a/drivers/pinctrl/ralink/pinctrl-mt7620.c ++++ b/drivers/pinctrl/ralink/pinctrl-mt7620.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + ++#include <asm/mach-ralink/ralink_regs.h> + #include <asm/mach-ralink/mt7620.h> + #include <linux/module.h> + #include <linux/platform_device.h> +diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c +index f2ab02225837e..f29130957e49a 100644 +--- a/drivers/pinctrl/renesas/core.c ++++ b/drivers/pinctrl/renesas/core.c +@@ -890,7 +890,7 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, + if (!field->pin && !field->offset && !field->size) + continue; + +- mask = GENMASK(field->offset + field->size, field->offset); ++ mask = GENMASK(field->offset + field->size - 1, field->offset); + if (mask & seen) + sh_pfc_err("drive_reg 0x%x: field %u overlap\n", + drive->reg, i); +diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +index dbf2f521bb272..20b2af889ca96 100644 +--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c ++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c +@@ -852,7 +852,7 @@ static const u32 rzg2l_gpio_configs[] = { + RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS), +- RZG2L_GPIO_PORT_PACK(3, 0x22, RZG2L_MPXED_PIN_FUNCS), ++ RZG2L_GPIO_PORT_PACK(3, 0x21, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IOLH_ETH0)), +diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c +index dfd8888a222a4..8934b4878fa85 100644 +--- a/drivers/pinctrl/stm32/pinctrl-stm32.c ++++ b/drivers/pinctrl/stm32/pinctrl-stm32.c +@@ -1251,10 +1251,10 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + bank_nr = args.args[1] / STM32_GPIO_PINS_PER_BANK; + bank->gpio_chip.base = args.args[1]; + +- npins = args.args[2]; +- while (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, +- ++i, &args)) +- npins += args.args[2]; ++ /* get the last defined gpio line (offset + nb of pins) */ ++ npins = args.args[0] + args.args[2]; ++ while (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, ++i, &args)) ++ npins = max(npins, (int)(args.args[0] + args.args[2])); + } else { + bank_nr = pctl->nbanks; + bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; +diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c +index ce1917e230f41..152b71226a807 100644 +--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c ++++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c +@@ -363,16 +363,16 @@ static const struct sunxi_desc_pin h616_pins[] = { + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* CTS */ +- SUNXI_FUNCTION(0x3, "i2s3"), /* DO0 */ ++ SUNXI_FUNCTION(0x3, "i2s3_dout0"), /* DO0 */ + SUNXI_FUNCTION(0x4, "spi1"), /* MISO */ +- SUNXI_FUNCTION(0x5, "i2s3"), /* DI1 */ ++ SUNXI_FUNCTION(0x5, "i2s3_din1"), /* DI1 */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), +- SUNXI_FUNCTION(0x3, "i2s3"), /* DI0 */ ++ SUNXI_FUNCTION(0x3, "i2s3_din0"), /* DI0 */ + SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */ +- SUNXI_FUNCTION(0x3, "i2s3"), /* DO1 */ ++ SUNXI_FUNCTION(0x5, "i2s3_dout1"), /* DO1 */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), +diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c +index 862c84efb718f..ce3f9ea415117 100644 +--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c ++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c +@@ -36,6 +36,13 @@ + #include "../core.h" + #include "pinctrl-sunxi.h" + ++/* ++ * These lock classes tell lockdep that GPIO IRQs are in a different ++ * category than their parents, so it won't report false recursion. ++ */ ++static struct lock_class_key sunxi_pinctrl_irq_lock_class; ++static struct lock_class_key sunxi_pinctrl_irq_request_class; ++ + static struct irq_chip sunxi_pinctrl_edge_irq_chip; + static struct irq_chip sunxi_pinctrl_level_irq_chip; + +@@ -1551,6 +1558,8 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev, + for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) { + int irqno = irq_create_mapping(pctl->domain, i); + ++ irq_set_lockdep_class(irqno, &sunxi_pinctrl_irq_lock_class, ++ &sunxi_pinctrl_irq_request_class); + irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip, + handle_edge_irq); + irq_set_chip_data(irqno, pctl); +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 04bc3b50aa7a4..65b4a819f1bdf 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -1374,8 +1374,8 @@ static int mlxbf_pmc_map_counters(struct device *dev) + pmc->block[i].counters = info[2]; + pmc->block[i].type = info[3]; + +- if (IS_ERR(pmc->block[i].mmio_base)) +- return PTR_ERR(pmc->block[i].mmio_base); ++ if (!pmc->block[i].mmio_base) ++ return -ENOMEM; + + ret = mlxbf_pmc_create_groups(dev, i); + if (ret) +diff --git a/drivers/platform/surface/surface3_power.c b/drivers/platform/surface/surface3_power.c +index 90c1568ea4e09..3cc004c68bdba 100644 +--- a/drivers/platform/surface/surface3_power.c ++++ b/drivers/platform/surface/surface3_power.c +@@ -233,14 +233,21 @@ static int mshw0011_bix(struct mshw0011_data *cdata, struct bix *bix) + } + bix->last_full_charg_capacity = ret; + +- /* get serial number */ ++ /* ++ * Get serial number, on some devices (with unofficial replacement ++ * battery?) reading any of the serial number range addresses gets ++ * nacked in this case just leave the serial number empty. ++ */ + ret = i2c_smbus_read_i2c_block_data(client, MSHW0011_BAT0_REG_SERIAL_NO, + sizeof(buf), buf); +- if (ret != sizeof(buf)) { ++ if (ret == -EREMOTEIO) { ++ /* no serial number available */ ++ } else if (ret != sizeof(buf)) { + dev_err(&client->dev, "Error reading serial no: %d\n", ret); + return ret; ++ } else { ++ snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf); + } +- snprintf(bix->serial, ARRAY_SIZE(bix->serial), "%3pE%6pE", buf + 7, buf); + + /* get cycle count */ + ret = i2c_smbus_read_word_data(client, MSHW0011_BAT0_REG_CYCLE_CNT); +diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c +index 4428c4330229a..1679811eff502 100644 +--- a/drivers/platform/surface/surface_aggregator_registry.c ++++ b/drivers/platform/surface/surface_aggregator_registry.c +@@ -77,6 +77,42 @@ static const struct software_node ssam_node_bas_dtx = { + .parent = &ssam_node_root, + }; + ++/* HID keyboard (TID1). */ ++static const struct software_node ssam_node_hid_tid1_keyboard = { ++ .name = "ssam:01:15:01:01:00", ++ .parent = &ssam_node_root, ++}; ++ ++/* HID pen stash (TID1; pen taken / stashed away evens). */ ++static const struct software_node ssam_node_hid_tid1_penstash = { ++ .name = "ssam:01:15:01:02:00", ++ .parent = &ssam_node_root, ++}; ++ ++/* HID touchpad (TID1). */ ++static const struct software_node ssam_node_hid_tid1_touchpad = { ++ .name = "ssam:01:15:01:03:00", ++ .parent = &ssam_node_root, ++}; ++ ++/* HID device instance 6 (TID1, unknown HID device). */ ++static const struct software_node ssam_node_hid_tid1_iid6 = { ++ .name = "ssam:01:15:01:06:00", ++ .parent = &ssam_node_root, ++}; ++ ++/* HID device instance 7 (TID1, unknown HID device). */ ++static const struct software_node ssam_node_hid_tid1_iid7 = { ++ .name = "ssam:01:15:01:07:00", ++ .parent = &ssam_node_root, ++}; ++ ++/* HID system controls (TID1). */ ++static const struct software_node ssam_node_hid_tid1_sysctrl = { ++ .name = "ssam:01:15:01:08:00", ++ .parent = &ssam_node_root, ++}; ++ + /* HID keyboard. */ + static const struct software_node ssam_node_hid_main_keyboard = { + .name = "ssam:01:15:02:01:00", +@@ -159,6 +195,21 @@ static const struct software_node *ssam_node_group_sl3[] = { + NULL, + }; + ++/* Devices for Surface Laptop Studio. */ ++static const struct software_node *ssam_node_group_sls[] = { ++ &ssam_node_root, ++ &ssam_node_bat_ac, ++ &ssam_node_bat_main, ++ &ssam_node_tmp_pprof, ++ &ssam_node_hid_tid1_keyboard, ++ &ssam_node_hid_tid1_penstash, ++ &ssam_node_hid_tid1_touchpad, ++ &ssam_node_hid_tid1_iid6, ++ &ssam_node_hid_tid1_iid7, ++ &ssam_node_hid_tid1_sysctrl, ++ NULL, ++}; ++ + /* Devices for Surface Laptop Go. */ + static const struct software_node *ssam_node_group_slg1[] = { + &ssam_node_root, +@@ -507,6 +558,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = { + /* Surface Laptop Go 1 */ + { "MSHW0118", (unsigned long)ssam_node_group_slg1 }, + ++ /* Surface Laptop Studio */ ++ { "MSHW0123", (unsigned long)ssam_node_group_sls }, ++ + { }, + }; + MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_match); +diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile +index 69690e26bb6d4..2734a771d1f00 100644 +--- a/drivers/platform/x86/Makefile ++++ b/drivers/platform/x86/Makefile +@@ -67,7 +67,7 @@ obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o + obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o + + # Intel +-obj-$(CONFIG_X86_PLATFORM_DRIVERS_INTEL) += intel/ ++obj-y += intel/ + + # MSI + obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o +diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c +index fc95620101e85..d3efd514614c0 100644 +--- a/drivers/platform/x86/amd-pmc.c ++++ b/drivers/platform/x86/amd-pmc.c +@@ -70,7 +70,7 @@ + #define AMD_CPU_ID_CZN AMD_CPU_ID_RN + #define AMD_CPU_ID_YC 0x14B5 + +-#define PMC_MSG_DELAY_MIN_US 100 ++#define PMC_MSG_DELAY_MIN_US 50 + #define RESPONSE_REGISTER_LOOP_MAX 20000 + + #define SOC_SUBSYSTEM_IP_MAX 12 +@@ -375,7 +375,8 @@ static int __maybe_unused amd_pmc_resume(struct device *dev) + } + + static const struct dev_pm_ops amd_pmc_pm_ops = { +- SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(amd_pmc_suspend, amd_pmc_resume) ++ .suspend_noirq = amd_pmc_suspend, ++ .resume_noirq = amd_pmc_resume, + }; + + static const struct pci_device_id pmc_pci_ids[] = { +diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c +index 9aae45a452002..57553f9b4d1dc 100644 +--- a/drivers/platform/x86/apple-gmux.c ++++ b/drivers/platform/x86/apple-gmux.c +@@ -625,7 +625,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + } + + gmux_data->iostart = res->start; +- gmux_data->iolen = res->end - res->start; ++ gmux_data->iolen = resource_size(res); + + if (gmux_data->iolen < GMUX_MIN_IO_LEN) { + pr_err("gmux I/O region too small (%lu < %u)\n", +diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig +index 2fffa57e596e4..fe224a54f24c0 100644 +--- a/drivers/platform/x86/dell/Kconfig ++++ b/drivers/platform/x86/dell/Kconfig +@@ -187,7 +187,7 @@ config DELL_WMI_AIO + + config DELL_WMI_DESCRIPTOR + tristate +- default m ++ default n + depends on ACPI_WMI + + config DELL_WMI_LED +diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c +index cc53f725c0419..ef24f53753c6e 100644 +--- a/drivers/platform/x86/hp_accel.c ++++ b/drivers/platform/x86/hp_accel.c +@@ -331,9 +331,11 @@ static int lis3lv02d_probe(struct platform_device *device) + INIT_WORK(&hpled_led.work, delayed_set_status_worker); + ret = led_classdev_register(NULL, &hpled_led.led_classdev); + if (ret) { ++ i8042_remove_filter(hp_accel_i8042_filter); + lis3lv02d_joystick_disable(&lis3_dev); + lis3lv02d_poweroff(&lis3_dev); + flush_work(&hpled_led.work); ++ lis3lv02d_remove_fs(&lis3_dev); + return ret; + } + +diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig +index 0b21468e1bd01..02e4481b384e4 100644 +--- a/drivers/platform/x86/intel/Kconfig ++++ b/drivers/platform/x86/intel/Kconfig +@@ -3,19 +3,6 @@ + # Intel x86 Platform Specific Drivers + # + +-menuconfig X86_PLATFORM_DRIVERS_INTEL +- bool "Intel x86 Platform Specific Device Drivers" +- default y +- help +- Say Y here to get to see options for device drivers for +- various Intel x86 platforms, including vendor-specific +- drivers. This option alone does not add any kernel code. +- +- If you say N, all options in this submenu will be skipped +- and disabled. +- +-if X86_PLATFORM_DRIVERS_INTEL +- + source "drivers/platform/x86/intel/atomisp2/Kconfig" + source "drivers/platform/x86/intel/int1092/Kconfig" + source "drivers/platform/x86/intel/int33fe/Kconfig" +@@ -167,5 +154,3 @@ config INTEL_UNCORE_FREQ_CONTROL + + To compile this driver as a module, choose M here: the module + will be called intel-uncore-frequency. +- +-endif # X86_PLATFORM_DRIVERS_INTEL +diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c +index 08598942a6d78..41a2a026f1568 100644 +--- a/drivers/platform/x86/intel/hid.c ++++ b/drivers/platform/x86/intel/hid.c +@@ -99,6 +99,20 @@ static const struct dmi_system_id button_array_table[] = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Tablet Gen 2"), + }, + }, ++ { ++ .ident = "Microsoft Surface Go 3", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), ++ }, ++ }, ++ { ++ .ident = "Microsoft Surface Go 3", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), ++ }, ++ }, + { } + }; + +diff --git a/drivers/platform/x86/intel/pmc/pltdrv.c b/drivers/platform/x86/intel/pmc/pltdrv.c +index 73797680b895c..15ca8afdd973d 100644 +--- a/drivers/platform/x86/intel/pmc/pltdrv.c ++++ b/drivers/platform/x86/intel/pmc/pltdrv.c +@@ -65,7 +65,7 @@ static int __init pmc_core_platform_init(void) + + retval = platform_device_register(pmc_core_device); + if (retval) +- kfree(pmc_core_device); ++ platform_device_put(pmc_core_device); + + return retval; + } +diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +index c9a85eb2e8600..e8424e70d81d2 100644 +--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c ++++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +@@ -596,7 +596,10 @@ static long isst_if_def_ioctl(struct file *file, unsigned int cmd, + return ret; + } + +-static DEFINE_MUTEX(punit_misc_dev_lock); ++/* Lock to prevent module registration when already opened by user space */ ++static DEFINE_MUTEX(punit_misc_dev_open_lock); ++/* Lock to allow one share misc device for all ISST interace */ ++static DEFINE_MUTEX(punit_misc_dev_reg_lock); + static int misc_usage_count; + static int misc_device_ret; + static int misc_device_open; +@@ -606,7 +609,7 @@ static int isst_if_open(struct inode *inode, struct file *file) + int i, ret = 0; + + /* Fail open, if a module is going away */ +- mutex_lock(&punit_misc_dev_lock); ++ mutex_lock(&punit_misc_dev_open_lock); + for (i = 0; i < ISST_IF_DEV_MAX; ++i) { + struct isst_if_cmd_cb *cb = &punit_callbacks[i]; + +@@ -628,7 +631,7 @@ static int isst_if_open(struct inode *inode, struct file *file) + } else { + misc_device_open++; + } +- mutex_unlock(&punit_misc_dev_lock); ++ mutex_unlock(&punit_misc_dev_open_lock); + + return ret; + } +@@ -637,7 +640,7 @@ static int isst_if_relase(struct inode *inode, struct file *f) + { + int i; + +- mutex_lock(&punit_misc_dev_lock); ++ mutex_lock(&punit_misc_dev_open_lock); + misc_device_open--; + for (i = 0; i < ISST_IF_DEV_MAX; ++i) { + struct isst_if_cmd_cb *cb = &punit_callbacks[i]; +@@ -645,7 +648,7 @@ static int isst_if_relase(struct inode *inode, struct file *f) + if (cb->registered) + module_put(cb->owner); + } +- mutex_unlock(&punit_misc_dev_lock); ++ mutex_unlock(&punit_misc_dev_open_lock); + + return 0; + } +@@ -662,6 +665,43 @@ static struct miscdevice isst_if_char_driver = { + .fops = &isst_if_char_driver_ops, + }; + ++static int isst_misc_reg(void) ++{ ++ mutex_lock(&punit_misc_dev_reg_lock); ++ if (misc_device_ret) ++ goto unlock_exit; ++ ++ if (!misc_usage_count) { ++ misc_device_ret = isst_if_cpu_info_init(); ++ if (misc_device_ret) ++ goto unlock_exit; ++ ++ misc_device_ret = misc_register(&isst_if_char_driver); ++ if (misc_device_ret) { ++ isst_if_cpu_info_exit(); ++ goto unlock_exit; ++ } ++ } ++ misc_usage_count++; ++ ++unlock_exit: ++ mutex_unlock(&punit_misc_dev_reg_lock); ++ ++ return misc_device_ret; ++} ++ ++static void isst_misc_unreg(void) ++{ ++ mutex_lock(&punit_misc_dev_reg_lock); ++ if (misc_usage_count) ++ misc_usage_count--; ++ if (!misc_usage_count && !misc_device_ret) { ++ misc_deregister(&isst_if_char_driver); ++ isst_if_cpu_info_exit(); ++ } ++ mutex_unlock(&punit_misc_dev_reg_lock); ++} ++ + /** + * isst_if_cdev_register() - Register callback for IOCTL + * @device_type: The device type this callback handling. +@@ -679,38 +719,31 @@ static struct miscdevice isst_if_char_driver = { + */ + int isst_if_cdev_register(int device_type, struct isst_if_cmd_cb *cb) + { +- if (misc_device_ret) +- return misc_device_ret; ++ int ret; + + if (device_type >= ISST_IF_DEV_MAX) + return -EINVAL; + +- mutex_lock(&punit_misc_dev_lock); ++ mutex_lock(&punit_misc_dev_open_lock); ++ /* Device is already open, we don't want to add new callbacks */ + if (misc_device_open) { +- mutex_unlock(&punit_misc_dev_lock); ++ mutex_unlock(&punit_misc_dev_open_lock); + return -EAGAIN; + } +- if (!misc_usage_count) { +- int ret; +- +- misc_device_ret = misc_register(&isst_if_char_driver); +- if (misc_device_ret) +- goto unlock_exit; +- +- ret = isst_if_cpu_info_init(); +- if (ret) { +- misc_deregister(&isst_if_char_driver); +- misc_device_ret = ret; +- goto unlock_exit; +- } +- } + memcpy(&punit_callbacks[device_type], cb, sizeof(*cb)); + punit_callbacks[device_type].registered = 1; +- misc_usage_count++; +-unlock_exit: +- mutex_unlock(&punit_misc_dev_lock); ++ mutex_unlock(&punit_misc_dev_open_lock); + +- return misc_device_ret; ++ ret = isst_misc_reg(); ++ if (ret) { ++ /* ++ * No need of mutex as the misc device register failed ++ * as no one can open device yet. Hence no contention. ++ */ ++ punit_callbacks[device_type].registered = 0; ++ return ret; ++ } ++ return 0; + } + EXPORT_SYMBOL_GPL(isst_if_cdev_register); + +@@ -725,16 +758,12 @@ EXPORT_SYMBOL_GPL(isst_if_cdev_register); + */ + void isst_if_cdev_unregister(int device_type) + { +- mutex_lock(&punit_misc_dev_lock); +- misc_usage_count--; ++ isst_misc_unreg(); ++ mutex_lock(&punit_misc_dev_open_lock); + punit_callbacks[device_type].registered = 0; + if (device_type == ISST_IF_DEV_MBOX) + isst_delete_hash(); +- if (!misc_usage_count && !misc_device_ret) { +- misc_deregister(&isst_if_char_driver); +- isst_if_cpu_info_exit(); +- } +- mutex_unlock(&punit_misc_dev_lock); ++ mutex_unlock(&punit_misc_dev_open_lock); + } + EXPORT_SYMBOL_GPL(isst_if_cdev_unregister); + +diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c +index 9472aae72df29..c4d9c45350f7c 100644 +--- a/drivers/platform/x86/think-lmi.c ++++ b/drivers/platform/x86/think-lmi.c +@@ -888,8 +888,10 @@ static int tlmi_analyze(void) + break; + if (!item) + break; +- if (!*item) ++ if (!*item) { ++ kfree(item); + continue; ++ } + + /* It is not allowed to have '/' for file name. Convert it into '\'. */ + strreplace(item, '/', '\\'); +@@ -902,6 +904,7 @@ static int tlmi_analyze(void) + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (!setting) { + ret = -ENOMEM; ++ kfree(item); + goto fail_clear_attr; + } + setting->index = i; +@@ -916,7 +919,6 @@ static int tlmi_analyze(void) + } + kobject_init(&setting->kobj, &tlmi_attr_setting_ktype); + tlmi_priv.setting[i] = setting; +- tlmi_priv.settings_count++; + kfree(item); + } + +@@ -983,7 +985,12 @@ static void tlmi_remove(struct wmi_device *wdev) + + static int tlmi_probe(struct wmi_device *wdev, const void *context) + { +- tlmi_analyze(); ++ int ret; ++ ++ ret = tlmi_analyze(); ++ if (ret) ++ return ret; ++ + return tlmi_sysfs_init(); + } + +diff --git a/drivers/platform/x86/think-lmi.h b/drivers/platform/x86/think-lmi.h +index f8e26823075fd..2ce5086a5af27 100644 +--- a/drivers/platform/x86/think-lmi.h ++++ b/drivers/platform/x86/think-lmi.h +@@ -55,7 +55,6 @@ struct tlmi_attr_setting { + struct think_lmi { + struct wmi_device *wmi_device; + +- int settings_count; + bool can_set_bios_settings; + bool can_get_bios_selections; + bool can_set_bios_password; +diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c +index 50ff04c84650c..3dc055ce6e61b 100644 +--- a/drivers/platform/x86/thinkpad_acpi.c ++++ b/drivers/platform/x86/thinkpad_acpi.c +@@ -1178,15 +1178,6 @@ static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk) + return status; + } + +-/* Query FW and update rfkill sw state for all rfkill switches */ +-static void tpacpi_rfk_update_swstate_all(void) +-{ +- unsigned int i; +- +- for (i = 0; i < TPACPI_RFK_SW_MAX; i++) +- tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]); +-} +- + /* + * Sync the HW-blocking state of all rfkill switches, + * do notice it causes the rfkill core to schedule uevents +@@ -3129,9 +3120,6 @@ static void tpacpi_send_radiosw_update(void) + if (wlsw == TPACPI_RFK_RADIO_OFF) + tpacpi_rfk_update_hwblock_state(true); + +- /* Sync sw blocking state */ +- tpacpi_rfk_update_swstate_all(); +- + /* Sync hw blocking state last if it is hw-unblocked */ + if (wlsw == TPACPI_RFK_RADIO_ON) + tpacpi_rfk_update_hwblock_state(false); +@@ -8853,6 +8841,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = { + TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (1st gen) */ + TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (2nd gen) */ + TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (3nd gen) */ ++ TPACPI_Q_LNV3('N', '4', '0', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (4nd gen) */ + TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL), /* P15 (1st gen) / P15v (1st gen) */ + TPACPI_Q_LNV3('N', '3', '2', TPACPI_FAN_2CTL), /* X1 Carbon (9th gen) */ + }; +@@ -9145,7 +9134,7 @@ static int fan_write_cmd_level(const char *cmd, int *rc) + + if (strlencmp(cmd, "level auto") == 0) + level = TP_EC_FAN_AUTO; +- else if ((strlencmp(cmd, "level disengaged") == 0) | ++ else if ((strlencmp(cmd, "level disengaged") == 0) || + (strlencmp(cmd, "level full-speed") == 0)) + level = TP_EC_FAN_FULLSPEED; + else if (sscanf(cmd, "level %d", &level) != 1) +diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c +index 033f797861d8a..c608078538a79 100644 +--- a/drivers/platform/x86/touchscreen_dmi.c ++++ b/drivers/platform/x86/touchscreen_dmi.c +@@ -773,6 +773,21 @@ static const struct ts_dmi_data predia_basic_data = { + .properties = predia_basic_props, + }; + ++static const struct property_entry rwc_nanote_p8_props[] = { ++ PROPERTY_ENTRY_U32("touchscreen-min-y", 46), ++ PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), ++ PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), ++ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), ++ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-rwc-nanote-p8.fw"), ++ PROPERTY_ENTRY_U32("silead,max-fingers", 10), ++ { } ++}; ++ ++static const struct ts_dmi_data rwc_nanote_p8_data = { ++ .acpi_name = "MSSL1680:00", ++ .properties = rwc_nanote_p8_props, ++}; ++ + static const struct property_entry schneider_sct101ctm_props[] = { + PROPERTY_ENTRY_U32("touchscreen-size-x", 1715), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), +@@ -1379,6 +1394,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), + }, + }, ++ { ++ /* RWC NANOTE P8 */ ++ .driver_data = (void *)&rwc_nanote_p8_data, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Default string"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "AY07J"), ++ DMI_MATCH(DMI_PRODUCT_SKU, "0001") ++ }, ++ }, + { + /* Schneider SCT101CTM */ + .driver_data = (void *)&schneider_sct101ctm_data, +diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c +index a76313006bdc4..1b65bb61ce888 100644 +--- a/drivers/platform/x86/wmi.c ++++ b/drivers/platform/x86/wmi.c +@@ -353,7 +353,14 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, + * the WQxx method failed - we should disable collection anyway. + */ + if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { +- status = acpi_execute_simple_method(handle, wc_method, 0); ++ /* ++ * Ignore whether this WCxx call succeeds or not since ++ * the previously executed WQxx method call might have ++ * succeeded, and returning the failing status code ++ * of this call would throw away the result of the WQxx ++ * call, potentially leaking memory. ++ */ ++ acpi_execute_simple_method(handle, wc_method, 0); + } + + return status; +diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c +index 026649409135c..64def79d557a8 100644 +--- a/drivers/power/reset/at91-reset.c ++++ b/drivers/power/reset/at91-reset.c +@@ -193,7 +193,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) + return -ENOMEM; + + reset->rstc_base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); +- if (!reset->rstc_base) { ++ if (IS_ERR(reset->rstc_base)) { + dev_err(&pdev->dev, "Could not map reset controller address\n"); + return -ENODEV; + } +@@ -203,7 +203,7 @@ static int __init at91_reset_probe(struct platform_device *pdev) + for_each_matching_node_and_match(np, at91_ramc_of_match, &match) { + reset->ramc_lpr = (u32)match->data; + reset->ramc_base[idx] = devm_of_iomap(&pdev->dev, np, 0, NULL); +- if (!reset->ramc_base[idx]) { ++ if (IS_ERR(reset->ramc_base[idx])) { + dev_err(&pdev->dev, "Could not map ram controller address\n"); + of_node_put(np); + return -ENODEV; +diff --git a/drivers/power/reset/ltc2952-poweroff.c b/drivers/power/reset/ltc2952-poweroff.c +index 8688c8ba8894c..81be33c041d6b 100644 +--- a/drivers/power/reset/ltc2952-poweroff.c ++++ b/drivers/power/reset/ltc2952-poweroff.c +@@ -161,8 +161,8 @@ static void ltc2952_poweroff_kill(void) + + static void ltc2952_poweroff_default(struct ltc2952_poweroff *data) + { +- data->wde_interval = 300L * 1E6L; +- data->trigger_delay = ktime_set(2, 500L*1E6L); ++ data->wde_interval = 300L * NSEC_PER_MSEC; ++ data->trigger_delay = ktime_set(2, 500L * NSEC_PER_MSEC); + + hrtimer_init(&data->timer_trigger, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + data->timer_trigger.function = ltc2952_poweroff_timer_trigger; +diff --git a/drivers/power/reset/mt6323-poweroff.c b/drivers/power/reset/mt6323-poweroff.c +index 0532803e6cbc4..d90e76fcb9383 100644 +--- a/drivers/power/reset/mt6323-poweroff.c ++++ b/drivers/power/reset/mt6323-poweroff.c +@@ -57,6 +57,9 @@ static int mt6323_pwrc_probe(struct platform_device *pdev) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -EINVAL; ++ + pwrc->base = res->start; + pwrc->regmap = mt6397_chip->regmap; + pwrc->dev = &pdev->dev; +diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c +index 945c3257ca931..fe814805c68b5 100644 +--- a/drivers/power/supply/bq25890_charger.c ++++ b/drivers/power/supply/bq25890_charger.c +@@ -581,12 +581,12 @@ static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq) + + if (!new_state.online && bq->state.online) { /* power removed */ + /* disable ADC */ +- ret = bq25890_field_write(bq, F_CONV_START, 0); ++ ret = bq25890_field_write(bq, F_CONV_RATE, 0); + if (ret < 0) + goto error; + } else if (new_state.online && !bq->state.online) { /* power inserted */ + /* enable ADC, to have control of charge current/voltage */ +- ret = bq25890_field_write(bq, F_CONV_START, 1); ++ ret = bq25890_field_write(bq, F_CONV_RATE, 1); + if (ret < 0) + goto error; + } +diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c +index 46f078350fd3f..cf38cbfe13e9d 100644 +--- a/drivers/power/supply/bq27xxx_battery_i2c.c ++++ b/drivers/power/supply/bq27xxx_battery_i2c.c +@@ -187,7 +187,8 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client, + dev_err(&client->dev, + "Unable to register IRQ %d error %d\n", + client->irq, ret); +- return ret; ++ bq27xxx_battery_teardown(di); ++ goto err_failed; + } + } + +diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c +index 3cea92e28dc3e..a9aef1e8b186e 100644 +--- a/drivers/power/supply/max17040_battery.c ++++ b/drivers/power/supply/max17040_battery.c +@@ -449,6 +449,8 @@ static int max17040_probe(struct i2c_client *client, + + chip->client = client; + chip->regmap = devm_regmap_init_i2c(client, &max17040_regmap); ++ if (IS_ERR(chip->regmap)) ++ return PTR_ERR(chip->regmap); + chip_id = (enum chip_id) id->driver_data; + if (client->dev.of_node) { + ret = max17040_get_of_data(chip); +diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c +index 8dffae76b6a31..aaf6f1bd3d298 100644 +--- a/drivers/power/supply/max17042_battery.c ++++ b/drivers/power/supply/max17042_battery.c +@@ -313,7 +313,10 @@ static int max17042_get_property(struct power_supply *psy, + val->intval = data * 625 / 8; + break; + case POWER_SUPPLY_PROP_CAPACITY: +- ret = regmap_read(map, MAX17042_RepSOC, &data); ++ if (chip->pdata->enable_current_sense) ++ ret = regmap_read(map, MAX17042_RepSOC, &data); ++ else ++ ret = regmap_read(map, MAX17042_VFSOC, &data); + if (ret < 0) + return ret; + +@@ -857,7 +860,8 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) + regmap_read(map, MAX17042_RepSOC, &soc); + soc >>= 8; + soc_tr = (soc + off) << 8; +- soc_tr |= (soc - off); ++ if (off < soc) ++ soc_tr |= soc - off; + regmap_write(map, MAX17042_SALRT_Th, soc_tr); + } + +@@ -876,6 +880,10 @@ static irqreturn_t max17042_thread_handler(int id, void *dev) + max17042_set_soc_threshold(chip, 1); + } + ++ /* we implicitly handle all alerts via power_supply_changed */ ++ regmap_clear_bits(chip->regmap, MAX17042_STATUS, ++ 0xFFFF & ~(STATUS_POR_BIT | STATUS_BST_BIT)); ++ + power_supply_changed(chip->battery); + return IRQ_HANDLED; + } +diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c +index 0c2132c7f5d40..a6e9afa5a1cff 100644 +--- a/drivers/power/supply/power_supply_core.c ++++ b/drivers/power/supply/power_supply_core.c +@@ -853,6 +853,10 @@ power_supply_find_ocv2cap_table(struct power_supply_battery_info *info, + return NULL; + + for (i = 0; i < POWER_SUPPLY_OCV_TEMP_MAX; i++) { ++ /* Out of capacity tables */ ++ if (!info->ocv_table[i]) ++ break; ++ + temp_diff = abs(info->ocv_temp[i] - temp); + + if (temp_diff < best_temp_diff) { +diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c +index 9ad0afe83d1b7..7a23c70f48791 100644 +--- a/drivers/power/supply/rt5033_battery.c ++++ b/drivers/power/supply/rt5033_battery.c +@@ -60,7 +60,7 @@ static int rt5033_battery_get_watt_prop(struct i2c_client *client, + regmap_read(battery->regmap, regh, &msb); + regmap_read(battery->regmap, regl, &lsb); + +- ret = ((msb << 4) + (lsb >> 4)) * 1250 / 1000; ++ ret = ((msb << 4) + (lsb >> 4)) * 1250; + + return ret; + } +diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c +index caf9b37c5eb1e..e238ae8e94709 100644 +--- a/drivers/ptp/ptp_ocp.c ++++ b/drivers/ptp/ptp_ocp.c +@@ -1049,10 +1049,11 @@ ptp_ocp_register_ext(struct ptp_ocp *bp, struct ocp_resource *r) + if (!ext) + return -ENOMEM; + +- err = -EINVAL; + ext->mem = ptp_ocp_get_mem(bp, r); +- if (!ext->mem) ++ if (IS_ERR(ext->mem)) { ++ err = PTR_ERR(ext->mem); + goto out; ++ } + + ext->bp = bp; + ext->info = r->extra; +@@ -1122,8 +1123,8 @@ ptp_ocp_register_mem(struct ptp_ocp *bp, struct ocp_resource *r) + void __iomem *mem; + + mem = ptp_ocp_get_mem(bp, r); +- if (!mem) +- return -EINVAL; ++ if (IS_ERR(mem)) ++ return PTR_ERR(mem); + + bp_assign_entry(bp, r, mem); + +diff --git a/drivers/ptp/ptp_vclock.c b/drivers/ptp/ptp_vclock.c +index baee0379482bc..ab1d233173e13 100644 +--- a/drivers/ptp/ptp_vclock.c ++++ b/drivers/ptp/ptp_vclock.c +@@ -185,8 +185,8 @@ out: + } + EXPORT_SYMBOL(ptp_get_vclocks_index); + +-void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps, +- int vclock_index) ++ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps, ++ int vclock_index) + { + char name[PTP_CLOCK_NAME_LEN] = ""; + struct ptp_vclock *vclock; +@@ -198,12 +198,12 @@ void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps, + snprintf(name, PTP_CLOCK_NAME_LEN, "ptp%d", vclock_index); + dev = class_find_device_by_name(ptp_class, name); + if (!dev) +- return; ++ return 0; + + ptp = dev_get_drvdata(dev); + if (!ptp->is_virtual_clock) { + put_device(dev); +- return; ++ return 0; + } + + vclock = info_to_vclock(ptp->info); +@@ -215,7 +215,7 @@ void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps, + spin_unlock_irqrestore(&vclock->lock, flags); + + put_device(dev); +- hwtstamps->hwtstamp = ns_to_ktime(ns); ++ return ns_to_ktime(ns); + } + EXPORT_SYMBOL(ptp_convert_timestamp); + #endif +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index ca6caba8a191a..46e76b5b21efe 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -6010,9 +6010,8 @@ core_initcall(regulator_init); + static int regulator_late_cleanup(struct device *dev, void *data) + { + struct regulator_dev *rdev = dev_to_rdev(dev); +- const struct regulator_ops *ops = rdev->desc->ops; + struct regulation_constraints *c = rdev->constraints; +- int enabled, ret; ++ int ret; + + if (c && c->always_on) + return 0; +@@ -6025,14 +6024,8 @@ static int regulator_late_cleanup(struct device *dev, void *data) + if (rdev->use_count) + goto unlock; + +- /* If we can't read the status assume it's always on. */ +- if (ops->is_enabled) +- enabled = ops->is_enabled(rdev); +- else +- enabled = 1; +- +- /* But if reading the status failed, assume that it's off. */ +- if (enabled <= 0) ++ /* If reading the status failed, assume that it's off. */ ++ if (_regulator_is_enabled(rdev) <= 0) + goto unlock; + + if (have_full_constraints()) { +diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c +index e669250902580..0a4fd449c27d1 100644 +--- a/drivers/regulator/da9121-regulator.c ++++ b/drivers/regulator/da9121-regulator.c +@@ -253,6 +253,11 @@ static int da9121_set_current_limit(struct regulator_dev *rdev, + goto error; + } + ++ if (rdev->desc->ops->is_enabled(rdev)) { ++ ret = -EBUSY; ++ goto error; ++ } ++ + ret = da9121_ceiling_selector(rdev, min_ua, max_ua, &sel); + if (ret < 0) + goto error; +diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c +index b3da0dc58782f..639b71eb41ffe 100644 +--- a/drivers/regulator/qcom-labibb-regulator.c ++++ b/drivers/regulator/qcom-labibb-regulator.c +@@ -260,7 +260,7 @@ static irqreturn_t qcom_labibb_ocp_isr(int irq, void *chip) + + /* If the regulator is not enabled, this is a fake event */ + if (!ops->is_enabled(vreg->rdev)) +- return 0; ++ return IRQ_HANDLED; + + /* If we tried to recover for too many times it's not getting better */ + if (vreg->ocp_irq_count > LABIBB_MAX_OCP_COUNT) +diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c +index 198fcc6551f6d..8e077792bddd9 100644 +--- a/drivers/regulator/qcom_smd-regulator.c ++++ b/drivers/regulator/qcom_smd-regulator.c +@@ -9,6 +9,7 @@ + #include <linux/of_device.h> + #include <linux/platform_device.h> + #include <linux/regulator/driver.h> ++#include <linux/regulator/of_regulator.h> + #include <linux/soc/qcom/smd-rpm.h> + + struct qcom_rpm_reg { +@@ -1190,52 +1191,91 @@ static const struct of_device_id rpm_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, rpm_of_match); + +-static int rpm_reg_probe(struct platform_device *pdev) ++/** ++ * rpm_regulator_init_vreg() - initialize all attributes of a qcom_smd-regulator ++ * @vreg: Pointer to the individual qcom_smd-regulator resource ++ * @dev: Pointer to the top level qcom_smd-regulator PMIC device ++ * @node: Pointer to the individual qcom_smd-regulator resource ++ * device node ++ * @rpm: Pointer to the rpm bus node ++ * @pmic_rpm_data: Pointer to a null-terminated array of qcom_smd-regulator ++ * resources defined for the top level PMIC device ++ * ++ * Return: 0 on success, errno on failure ++ */ ++static int rpm_regulator_init_vreg(struct qcom_rpm_reg *vreg, struct device *dev, ++ struct device_node *node, struct qcom_smd_rpm *rpm, ++ const struct rpm_regulator_data *pmic_rpm_data) + { +- const struct rpm_regulator_data *reg; +- const struct of_device_id *match; +- struct regulator_config config = { }; ++ struct regulator_config config = {}; ++ const struct rpm_regulator_data *rpm_data; + struct regulator_dev *rdev; ++ int ret; ++ ++ for (rpm_data = pmic_rpm_data; rpm_data->name; rpm_data++) ++ if (of_node_name_eq(node, rpm_data->name)) ++ break; ++ ++ if (!rpm_data->name) { ++ dev_err(dev, "Unknown regulator %pOFn\n", node); ++ return -EINVAL; ++ } ++ ++ vreg->dev = dev; ++ vreg->rpm = rpm; ++ vreg->type = rpm_data->type; ++ vreg->id = rpm_data->id; ++ ++ memcpy(&vreg->desc, rpm_data->desc, sizeof(vreg->desc)); ++ vreg->desc.name = rpm_data->name; ++ vreg->desc.supply_name = rpm_data->supply; ++ vreg->desc.owner = THIS_MODULE; ++ vreg->desc.type = REGULATOR_VOLTAGE; ++ vreg->desc.of_match = rpm_data->name; ++ ++ config.dev = dev; ++ config.of_node = node; ++ config.driver_data = vreg; ++ ++ rdev = devm_regulator_register(dev, &vreg->desc, &config); ++ if (IS_ERR(rdev)) { ++ ret = PTR_ERR(rdev); ++ dev_err(dev, "%pOFn: devm_regulator_register() failed, ret=%d\n", node, ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rpm_reg_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ const struct rpm_regulator_data *vreg_data; ++ struct device_node *node; + struct qcom_rpm_reg *vreg; + struct qcom_smd_rpm *rpm; ++ int ret; + + rpm = dev_get_drvdata(pdev->dev.parent); + if (!rpm) { +- dev_err(&pdev->dev, "unable to retrieve handle to rpm\n"); ++ dev_err(&pdev->dev, "Unable to retrieve handle to rpm\n"); + return -ENODEV; + } + +- match = of_match_device(rpm_of_match, &pdev->dev); +- if (!match) { +- dev_err(&pdev->dev, "failed to match device\n"); ++ vreg_data = of_device_get_match_data(dev); ++ if (!vreg_data) + return -ENODEV; +- } + +- for (reg = match->data; reg->name; reg++) { ++ for_each_available_child_of_node(dev->of_node, node) { + vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); + if (!vreg) + return -ENOMEM; + +- vreg->dev = &pdev->dev; +- vreg->type = reg->type; +- vreg->id = reg->id; +- vreg->rpm = rpm; +- +- memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc)); +- +- vreg->desc.id = -1; +- vreg->desc.owner = THIS_MODULE; +- vreg->desc.type = REGULATOR_VOLTAGE; +- vreg->desc.name = reg->name; +- vreg->desc.supply_name = reg->supply; +- vreg->desc.of_match = reg->name; +- +- config.dev = &pdev->dev; +- config.driver_data = vreg; +- rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config); +- if (IS_ERR(rdev)) { +- dev_err(&pdev->dev, "failed to register %s\n", reg->name); +- return PTR_ERR(rdev); ++ ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data); ++ ++ if (ret < 0) { ++ of_node_put(node); ++ return ret; + } + } + +diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c +index 7c111bbdc2afa..35269f9982105 100644 +--- a/drivers/regulator/s5m8767.c ++++ b/drivers/regulator/s5m8767.c +@@ -850,18 +850,15 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) + /* DS4 GPIO */ + gpio_direction_output(pdata->buck_ds[2], 0x0); + +- if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || +- pdata->buck4_gpiodvs) { +- regmap_update_bits(s5m8767->iodev->regmap_pmic, +- S5M8767_REG_BUCK2CTRL, 1 << 1, +- (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1)); +- regmap_update_bits(s5m8767->iodev->regmap_pmic, +- S5M8767_REG_BUCK3CTRL, 1 << 1, +- (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1)); +- regmap_update_bits(s5m8767->iodev->regmap_pmic, +- S5M8767_REG_BUCK4CTRL, 1 << 1, +- (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1)); +- } ++ regmap_update_bits(s5m8767->iodev->regmap_pmic, ++ S5M8767_REG_BUCK2CTRL, 1 << 1, ++ (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1)); ++ regmap_update_bits(s5m8767->iodev->regmap_pmic, ++ S5M8767_REG_BUCK3CTRL, 1 << 1, ++ (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1)); ++ regmap_update_bits(s5m8767->iodev->regmap_pmic, ++ S5M8767_REG_BUCK4CTRL, 1 << 1, ++ (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1)); + + /* Initialize GPIO DVS registers */ + for (i = 0; i < 8; i++) { +diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c +index d88f76f5305eb..05c39e1c56b49 100644 +--- a/drivers/remoteproc/imx_rproc.c ++++ b/drivers/remoteproc/imx_rproc.c +@@ -71,6 +71,7 @@ struct imx_rproc_mem { + /* att flags */ + /* M4 own area. Can be mapped at probe */ + #define ATT_OWN BIT(1) ++#define ATT_IOMEM BIT(2) + + /* address translation table */ + struct imx_rproc_att { +@@ -117,7 +118,7 @@ struct imx_rproc { + static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { + /* dev addr , sys addr , size , flags */ + /* ITCM */ +- { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN }, ++ { 0x00000000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM }, + /* OCRAM_S */ + { 0x00180000, 0x00180000, 0x00009000, 0 }, + /* OCRAM */ +@@ -131,7 +132,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { + /* DDR (Code) - alias */ + { 0x10000000, 0x40000000, 0x0FFE0000, 0 }, + /* DTCM */ +- { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, ++ { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM }, + /* OCRAM_S - alias */ + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, + /* OCRAM */ +@@ -147,7 +148,7 @@ static const struct imx_rproc_att imx_rproc_att_imx8mn[] = { + static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { + /* dev addr , sys addr , size , flags */ + /* TCML - alias */ +- { 0x00000000, 0x007e0000, 0x00020000, 0 }, ++ { 0x00000000, 0x007e0000, 0x00020000, ATT_IOMEM}, + /* OCRAM_S */ + { 0x00180000, 0x00180000, 0x00008000, 0 }, + /* OCRAM */ +@@ -159,9 +160,9 @@ static const struct imx_rproc_att imx_rproc_att_imx8mq[] = { + /* DDR (Code) - alias */ + { 0x10000000, 0x80000000, 0x0FFE0000, 0 }, + /* TCML */ +- { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN }, ++ { 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM}, + /* TCMU */ +- { 0x20000000, 0x00800000, 0x00020000, ATT_OWN }, ++ { 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM}, + /* OCRAM_S */ + { 0x20180000, 0x00180000, 0x00008000, ATT_OWN }, + /* OCRAM */ +@@ -199,12 +200,12 @@ static const struct imx_rproc_att imx_rproc_att_imx7d[] = { + /* OCRAM_PXP (Code) - alias */ + { 0x00940000, 0x00940000, 0x00008000, 0 }, + /* TCML (Code) */ +- { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, ++ { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM }, + /* DDR (Code) - alias, first part of DDR (Data) */ + { 0x10000000, 0x80000000, 0x0FFF0000, 0 }, + + /* TCMU (Data) */ +- { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, ++ { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM }, + /* OCRAM (Data) */ + { 0x20200000, 0x00900000, 0x00020000, 0 }, + /* OCRAM_EPDC (Data) */ +@@ -218,18 +219,18 @@ static const struct imx_rproc_att imx_rproc_att_imx7d[] = { + static const struct imx_rproc_att imx_rproc_att_imx6sx[] = { + /* dev addr , sys addr , size , flags */ + /* TCML (M4 Boot Code) - alias */ +- { 0x00000000, 0x007F8000, 0x00008000, 0 }, ++ { 0x00000000, 0x007F8000, 0x00008000, ATT_IOMEM }, + /* OCRAM_S (Code) */ + { 0x00180000, 0x008F8000, 0x00004000, 0 }, + /* OCRAM_S (Code) - alias */ + { 0x00180000, 0x008FC000, 0x00004000, 0 }, + /* TCML (Code) */ +- { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN }, ++ { 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM }, + /* DDR (Code) - alias, first part of DDR (Data) */ + { 0x10000000, 0x80000000, 0x0FFF8000, 0 }, + + /* TCMU (Data) */ +- { 0x20000000, 0x00800000, 0x00008000, ATT_OWN }, ++ { 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM }, + /* OCRAM_S (Data) - alias? */ + { 0x208F8000, 0x008F8000, 0x00004000, 0 }, + /* DDR (Data) */ +@@ -341,7 +342,7 @@ static int imx_rproc_stop(struct rproc *rproc) + } + + static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, +- size_t len, u64 *sys) ++ size_t len, u64 *sys, bool *is_iomem) + { + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int i; +@@ -354,6 +355,8 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, + unsigned int offset = da - att->da; + + *sys = att->sa + offset; ++ if (is_iomem) ++ *is_iomem = att->flags & ATT_IOMEM; + return 0; + } + } +@@ -377,7 +380,7 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i + * On device side we have many aliases, so we need to convert device + * address (M4) to system bus address first. + */ +- if (imx_rproc_da_to_sys(priv, da, len, &sys)) ++ if (imx_rproc_da_to_sys(priv, da, len, &sys, is_iomem)) + return NULL; + + for (i = 0; i < IMX_RPROC_MEM_MAX; i++) { +@@ -553,8 +556,12 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, + if (b >= IMX_RPROC_MEM_MAX) + break; + +- priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, +- att->sa, att->size); ++ if (att->flags & ATT_IOMEM) ++ priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, ++ att->sa, att->size); ++ else ++ priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, ++ att->sa, att->size); + if (!priv->mem[b].cpu_addr) { + dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa); + return -ENOMEM; +@@ -575,8 +582,8 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, + struct resource res; + + node = of_parse_phandle(np, "memory-region", a); +- /* Not map vdev region */ +- if (!strcmp(node->name, "vdev")) ++ /* Not map vdevbuffer, vdevring region */ ++ if (!strncmp(node->name, "vdev", strlen("vdev"))) + continue; + err = of_address_to_resource(node, 0, &res); + if (err) { +@@ -597,7 +604,7 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, + } + priv->mem[b].sys_addr = res.start; + priv->mem[b].size = resource_size(&res); +- if (!strcmp(node->name, "rsc_table")) ++ if (!strcmp(node->name, "rsc-table")) + priv->rsc_table = priv->mem[b].cpu_addr; + b++; + } +@@ -823,6 +830,7 @@ static int imx_rproc_remove(struct platform_device *pdev) + clk_disable_unprepare(priv->clk); + rproc_del(rproc); + imx_rproc_free_mbox(rproc); ++ destroy_workqueue(priv->workqueue); + rproc_free(rproc); + + return 0; +diff --git a/drivers/remoteproc/qcom_pil_info.c b/drivers/remoteproc/qcom_pil_info.c +index 7c007dd7b2000..aca21560e20b8 100644 +--- a/drivers/remoteproc/qcom_pil_info.c ++++ b/drivers/remoteproc/qcom_pil_info.c +@@ -104,7 +104,7 @@ int qcom_pil_info_store(const char *image, phys_addr_t base, size_t size) + return -ENOMEM; + + found_unused: +- memcpy_toio(entry, image, PIL_RELOC_NAME_LEN); ++ memcpy_toio(entry, image, strnlen(image, PIL_RELOC_NAME_LEN)); + found_existing: + /* Use two writel() as base is only aligned to 4 bytes on odd entries */ + writel(base, entry + PIL_RELOC_NAME_LEN); +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 401b1ec907852..699eaac5b760e 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -661,6 +661,7 @@ static const struct adsp_data sm8350_cdsp_resource = { + }, + .proxy_pd_names = (char*[]){ + "cx", ++ "mxc", + NULL + }, + .ssr_name = "cdsp", +diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c +index 502b6604b757b..775df165eb450 100644 +--- a/drivers/remoteproc/remoteproc_core.c ++++ b/drivers/remoteproc/remoteproc_core.c +@@ -556,9 +556,6 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, + /* Initialise vdev subdevice */ + snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index); + rvdev->dev.parent = &rproc->dev; +- ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); +- if (ret) +- return ret; + rvdev->dev.release = rproc_rvdev_release; + dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name); + dev_set_drvdata(&rvdev->dev, rvdev); +@@ -568,6 +565,11 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, + put_device(&rvdev->dev); + return ret; + } ++ ++ ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); ++ if (ret) ++ goto free_rvdev; ++ + /* Make device dma capable by inheriting from parent's capabilities */ + set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent)); + +diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c +index aee657cc08c6a..c892f433a323e 100644 +--- a/drivers/remoteproc/remoteproc_coredump.c ++++ b/drivers/remoteproc/remoteproc_coredump.c +@@ -152,8 +152,8 @@ static void rproc_copy_segment(struct rproc *rproc, void *dest, + struct rproc_dump_segment *segment, + size_t offset, size_t size) + { ++ bool is_iomem = false; + void *ptr; +- bool is_iomem; + + if (segment->dump) { + segment->dump(rproc, segment, dest, offset, size); +diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c +index 469c52e62faff..d635d19a5aa8a 100644 +--- a/drivers/remoteproc/remoteproc_elf_loader.c ++++ b/drivers/remoteproc/remoteproc_elf_loader.c +@@ -178,8 +178,8 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) + u64 filesz = elf_phdr_get_p_filesz(class, phdr); + u64 offset = elf_phdr_get_p_offset(class, phdr); + u32 type = elf_phdr_get_p_type(class, phdr); ++ bool is_iomem = false; + void *ptr; +- bool is_iomem; + + if (type != PT_LOAD) + continue; +@@ -220,7 +220,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) + /* put the segment where the remote processor expects it */ + if (filesz) { + if (is_iomem) +- memcpy_fromio(ptr, (void __iomem *)(elf_data + offset), filesz); ++ memcpy_toio((void __iomem *)ptr, elf_data + offset, filesz); + else + memcpy(ptr, elf_data + offset, filesz); + } +diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c +index e0704fd2b5336..1e83150388506 100644 +--- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c ++++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c +@@ -137,7 +137,12 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev) + dev_set_drvdata(dev, priv); + + pm_runtime_enable(&pdev->dev); +- pm_runtime_resume_and_get(&pdev->dev); ++ error = pm_runtime_resume_and_get(&pdev->dev); ++ if (error < 0) { ++ pm_runtime_disable(&pdev->dev); ++ reset_control_assert(priv->rstc); ++ return dev_err_probe(&pdev->dev, error, "pm_runtime_resume_and_get failed"); ++ } + + /* put pll and phy into reset state */ + spin_lock_irqsave(&priv->lock, flags); +diff --git a/drivers/reset/tegra/reset-bpmp.c b/drivers/reset/tegra/reset-bpmp.c +index 4c5bba52b1059..24d3395964cc4 100644 +--- a/drivers/reset/tegra/reset-bpmp.c ++++ b/drivers/reset/tegra/reset-bpmp.c +@@ -20,7 +20,6 @@ static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc, + struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc); + struct mrq_reset_request request; + struct tegra_bpmp_message msg; +- int err; + + memset(&request, 0, sizeof(request)); + request.cmd = command; +@@ -31,13 +30,7 @@ static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc, + msg.tx.data = &request; + msg.tx.size = sizeof(request); + +- err = tegra_bpmp_transfer(bpmp, &msg); +- if (err) +- return err; +- if (msg.rx.ret) +- return -EINVAL; +- +- return 0; ++ return tegra_bpmp_transfer(bpmp, &msg); + } + + static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc, +diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c +index 2bebc9b2d1634..49dd5a2009982 100644 +--- a/drivers/rpmsg/rpmsg_char.c ++++ b/drivers/rpmsg/rpmsg_char.c +@@ -92,7 +92,7 @@ static int rpmsg_eptdev_destroy(struct device *dev, void *data) + /* wake up any blocked readers */ + wake_up_interruptible(&eptdev->readq); + +- device_del(&eptdev->dev); ++ cdev_device_del(&eptdev->cdev, &eptdev->dev); + put_device(&eptdev->dev); + + return 0; +@@ -335,7 +335,6 @@ static void rpmsg_eptdev_release_device(struct device *dev) + + ida_simple_remove(&rpmsg_ept_ida, dev->id); + ida_simple_remove(&rpmsg_minor_ida, MINOR(eptdev->dev.devt)); +- cdev_del(&eptdev->cdev); + kfree(eptdev); + } + +@@ -380,19 +379,13 @@ static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev, + dev->id = ret; + dev_set_name(dev, "rpmsg%d", ret); + +- ret = cdev_add(&eptdev->cdev, dev->devt, 1); ++ ret = cdev_device_add(&eptdev->cdev, &eptdev->dev); + if (ret) + goto free_ept_ida; + + /* We can now rely on the release function for cleanup */ + dev->release = rpmsg_eptdev_release_device; + +- ret = device_add(dev); +- if (ret) { +- dev_err(dev, "device_add failed: %d\n", ret); +- put_device(dev); +- } +- + return ret; + + free_ept_ida: +@@ -461,7 +454,6 @@ static void rpmsg_ctrldev_release_device(struct device *dev) + + ida_simple_remove(&rpmsg_ctrl_ida, dev->id); + ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt)); +- cdev_del(&ctrldev->cdev); + kfree(ctrldev); + } + +@@ -496,19 +488,13 @@ static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev) + dev->id = ret; + dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret); + +- ret = cdev_add(&ctrldev->cdev, dev->devt, 1); ++ ret = cdev_device_add(&ctrldev->cdev, &ctrldev->dev); + if (ret) + goto free_ctrl_ida; + + /* We can now rely on the release function for cleanup */ + dev->release = rpmsg_ctrldev_release_device; + +- ret = device_add(dev); +- if (ret) { +- dev_err(&rpdev->dev, "device_add failed: %d\n", ret); +- put_device(dev); +- } +- + dev_set_drvdata(&rpdev->dev, ctrldev); + + return ret; +@@ -534,7 +520,7 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev) + if (ret) + dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret); + +- device_del(&ctrldev->dev); ++ cdev_device_del(&ctrldev->cdev, &ctrldev->dev); + put_device(&ctrldev->dev); + } + +diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c +index 9151836190ce3..a71de08acc7b9 100644 +--- a/drivers/rpmsg/rpmsg_core.c ++++ b/drivers/rpmsg/rpmsg_core.c +@@ -519,13 +519,25 @@ static int rpmsg_dev_probe(struct device *dev) + err = rpdrv->probe(rpdev); + if (err) { + dev_err(dev, "%s: failed: %d\n", __func__, err); +- if (ept) +- rpmsg_destroy_ept(ept); +- goto out; ++ goto destroy_ept; + } + +- if (ept && rpdev->ops->announce_create) ++ if (ept && rpdev->ops->announce_create) { + err = rpdev->ops->announce_create(rpdev); ++ if (err) { ++ dev_err(dev, "failed to announce creation\n"); ++ goto remove_rpdev; ++ } ++ } ++ ++ return 0; ++ ++remove_rpdev: ++ if (rpdrv->remove) ++ rpdrv->remove(rpdev); ++destroy_ept: ++ if (ept) ++ rpmsg_destroy_ept(ept); + out: + return err; + } +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 4eb53412b8085..dc3f8b0dde989 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -457,7 +457,10 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) + min = t->time.tm_min; + sec = t->time.tm_sec; + ++ spin_lock_irq(&rtc_lock); + rtc_control = CMOS_READ(RTC_CONTROL); ++ spin_unlock_irq(&rtc_lock); ++ + if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + /* Writing 0xff means "don't care" or "match all". */ + mon = (mon <= 12) ? bin2bcd(mon) : 0xff; +diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c +index b3de6d2e680a4..2f83adef966eb 100644 +--- a/drivers/rtc/rtc-ds1302.c ++++ b/drivers/rtc/rtc-ds1302.c +@@ -199,11 +199,18 @@ static const struct of_device_id ds1302_dt_ids[] = { + MODULE_DEVICE_TABLE(of, ds1302_dt_ids); + #endif + ++static const struct spi_device_id ds1302_spi_ids[] = { ++ { .name = "ds1302", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(spi, ds1302_spi_ids); ++ + static struct spi_driver ds1302_driver = { + .driver.name = "rtc-ds1302", + .driver.of_match_table = of_match_ptr(ds1302_dt_ids), + .probe = ds1302_probe, + .remove = ds1302_remove, ++ .id_table = ds1302_spi_ids, + }; + + module_spi_driver(ds1302_driver); +diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c +index 66fc8617d07ee..93ce72b9ae59e 100644 +--- a/drivers/rtc/rtc-ds1390.c ++++ b/drivers/rtc/rtc-ds1390.c +@@ -219,12 +219,19 @@ static const struct of_device_id ds1390_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, ds1390_of_match); + ++static const struct spi_device_id ds1390_spi_ids[] = { ++ { .name = "ds1390" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(spi, ds1390_spi_ids); ++ + static struct spi_driver ds1390_driver = { + .driver = { + .name = "rtc-ds1390", + .of_match_table = of_match_ptr(ds1390_of_match), + }, + .probe = ds1390_probe, ++ .id_table = ds1390_spi_ids, + }; + + module_spi_driver(ds1390_driver); +diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c +index dcfaf09946ee3..2065842f775d6 100644 +--- a/drivers/rtc/rtc-mc146818-lib.c ++++ b/drivers/rtc/rtc-mc146818-lib.c +@@ -104,7 +104,7 @@ again: + time->tm_year += real_year - 72; + #endif + +- if (century > 20) ++ if (century > 19) + time->tm_year += (century - 19) * 100; + + /* +diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c +index bad7792b6ca58..0d515b3df5710 100644 +--- a/drivers/rtc/rtc-mcp795.c ++++ b/drivers/rtc/rtc-mcp795.c +@@ -430,12 +430,19 @@ static const struct of_device_id mcp795_of_match[] = { + MODULE_DEVICE_TABLE(of, mcp795_of_match); + #endif + ++static const struct spi_device_id mcp795_spi_ids[] = { ++ { .name = "mcp795" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(spi, mcp795_spi_ids); ++ + static struct spi_driver mcp795_driver = { + .driver = { + .name = "rtc-mcp795", + .of_match_table = of_match_ptr(mcp795_of_match), + }, + .probe = mcp795_probe, ++ .id_table = mcp795_spi_ids, + }; + + module_spi_driver(mcp795_driver); +diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c +index 0f58cac81d8c0..7473e6c8a183b 100644 +--- a/drivers/rtc/rtc-pcf2123.c ++++ b/drivers/rtc/rtc-pcf2123.c +@@ -451,12 +451,21 @@ static const struct of_device_id pcf2123_dt_ids[] = { + MODULE_DEVICE_TABLE(of, pcf2123_dt_ids); + #endif + ++static const struct spi_device_id pcf2123_spi_ids[] = { ++ { .name = "pcf2123", }, ++ { .name = "rv2123", }, ++ { .name = "rtc-pcf2123", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(spi, pcf2123_spi_ids); ++ + static struct spi_driver pcf2123_driver = { + .driver = { + .name = "rtc-pcf2123", + .of_match_table = of_match_ptr(pcf2123_dt_ids), + }, + .probe = pcf2123_probe, ++ .id_table = pcf2123_spi_ids, + }; + + module_spi_driver(pcf2123_driver); +diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c +index d2f1d8f754bf3..cf8119b6d3204 100644 +--- a/drivers/rtc/rtc-pxa.c ++++ b/drivers/rtc/rtc-pxa.c +@@ -330,6 +330,10 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) + if (sa1100_rtc->irq_alarm < 0) + return -ENXIO; + ++ sa1100_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); ++ if (IS_ERR(sa1100_rtc->rtc)) ++ return PTR_ERR(sa1100_rtc->rtc); ++ + pxa_rtc->base = devm_ioremap(dev, pxa_rtc->ress->start, + resource_size(pxa_rtc->ress)); + if (!pxa_rtc->base) { +diff --git a/drivers/rtc/rtc-rv3032.c b/drivers/rtc/rtc-rv3032.c +index d63102d5cb1e4..1b62ed2f14594 100644 +--- a/drivers/rtc/rtc-rv3032.c ++++ b/drivers/rtc/rtc-rv3032.c +@@ -617,11 +617,11 @@ static int rv3032_clkout_set_rate(struct clk_hw *hw, unsigned long rate, + + ret = rv3032_enter_eerd(rv3032, &eerd); + if (ret) +- goto exit_eerd; ++ return ret; + + ret = regmap_write(rv3032->regmap, RV3032_CLKOUT1, hfd & 0xff); + if (ret) +- return ret; ++ goto exit_eerd; + + ret = regmap_write(rv3032->regmap, RV3032_CLKOUT2, RV3032_CLKOUT2_OS | + FIELD_PREP(RV3032_CLKOUT2_HFD_MSK, hfd >> 8)); +diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c +index 1f5fab617b679..f7e75d9fedf61 100644 +--- a/drivers/s390/char/tape_std.c ++++ b/drivers/s390/char/tape_std.c +@@ -53,7 +53,6 @@ int + tape_std_assign(struct tape_device *device) + { + int rc; +- struct timer_list timeout; + struct tape_request *request; + + request = tape_alloc_request(2, 11); +@@ -70,7 +69,7 @@ tape_std_assign(struct tape_device *device) + * So we set up a timeout for this call. + */ + timer_setup(&request->timer, tape_std_assign_timeout, 0); +- mod_timer(&timeout, jiffies + 2 * HZ); ++ mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000)); + + rc = tape_do_io_interruptible(device, request); + +diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c +index 44461928aab8a..c278097926093 100644 +--- a/drivers/s390/cio/css.c ++++ b/drivers/s390/cio/css.c +@@ -437,8 +437,8 @@ static ssize_t dev_busid_show(struct device *dev, + struct subchannel *sch = to_subchannel(dev); + struct pmcw *pmcw = &sch->schib.pmcw; + +- if ((pmcw->st == SUBCHANNEL_TYPE_IO || +- pmcw->st == SUBCHANNEL_TYPE_MSG) && pmcw->dnv) ++ if ((pmcw->st == SUBCHANNEL_TYPE_IO && pmcw->dnv) || ++ (pmcw->st == SUBCHANNEL_TYPE_MSG && pmcw->w)) + return sysfs_emit(buf, "0.%x.%04x\n", sch->schid.ssid, + pmcw->dev); + else +diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c +index 8d14569823d73..61cde02b23fec 100644 +--- a/drivers/s390/cio/device.c ++++ b/drivers/s390/cio/device.c +@@ -1194,7 +1194,7 @@ static int io_subchannel_chp_event(struct subchannel *sch, + else + path_event[chpid] = PE_NONE; + } +- if (cdev) ++ if (cdev && cdev->drv && cdev->drv->path_event) + cdev->drv->path_event(cdev, path_event); + break; + } +diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c +index 0fe7b2f2e7f52..c533d1dadc6bb 100644 +--- a/drivers/s390/cio/device_ops.c ++++ b/drivers/s390/cio/device_ops.c +@@ -825,13 +825,23 @@ EXPORT_SYMBOL_GPL(ccw_device_get_chid); + */ + void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size) + { +- return cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size); ++ void *addr; ++ ++ if (!get_device(&cdev->dev)) ++ return NULL; ++ addr = cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size); ++ if (IS_ERR_OR_NULL(addr)) ++ put_device(&cdev->dev); ++ return addr; + } + EXPORT_SYMBOL(ccw_device_dma_zalloc); + + void ccw_device_dma_free(struct ccw_device *cdev, void *cpu_addr, size_t size) + { ++ if (!cpu_addr) ++ return; + cio_gp_dma_free(cdev->private->dma_pool, cpu_addr, size); ++ put_device(&cdev->dev); + } + EXPORT_SYMBOL(ccw_device_dma_free); + +diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c +index 9ea48bf0ee40d..032bf7b282bab 100644 +--- a/drivers/s390/crypto/ap_queue.c ++++ b/drivers/s390/crypto/ap_queue.c +@@ -157,6 +157,8 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq) + switch (status.response_code) { + case AP_RESPONSE_NORMAL: + aq->queue_count = max_t(int, 0, aq->queue_count - 1); ++ if (!status.queue_empty && !aq->queue_count) ++ aq->queue_count++; + if (aq->queue_count > 0) + mod_timer(&aq->timeout, + jiffies + aq->request_timeout); +diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c +index d24cafe02708f..511bf8e0a436c 100644 +--- a/drivers/s390/scsi/zfcp_fc.c ++++ b/drivers/s390/scsi/zfcp_fc.c +@@ -521,6 +521,8 @@ static void zfcp_fc_adisc_handler(void *data) + goto out; + } + ++ /* re-init to undo drop from zfcp_fc_adisc() */ ++ port->d_id = ntoh24(adisc_resp->adisc_port_id); + /* port is good, unblock rport without going through erp */ + zfcp_scsi_schedule_rport_register(port); + out: +@@ -534,6 +536,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port) + struct zfcp_fc_req *fc_req; + struct zfcp_adapter *adapter = port->adapter; + struct Scsi_Host *shost = adapter->scsi_host; ++ u32 d_id; + int ret; + + fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_ATOMIC); +@@ -558,7 +561,15 @@ static int zfcp_fc_adisc(struct zfcp_port *port) + fc_req->u.adisc.req.adisc_cmd = ELS_ADISC; + hton24(fc_req->u.adisc.req.adisc_port_id, fc_host_port_id(shost)); + +- ret = zfcp_fsf_send_els(adapter, port->d_id, &fc_req->ct_els, ++ d_id = port->d_id; /* remember as destination for send els below */ ++ /* ++ * Force fresh GID_PN lookup on next port recovery. ++ * Must happen after request setup and before sending request, ++ * to prevent race with port->d_id re-init in zfcp_fc_adisc_handler(). ++ */ ++ port->d_id = 0; ++ ++ ret = zfcp_fsf_send_els(adapter, d_id, &fc_req->ct_els, + ZFCP_FC_CTELS_TMO); + if (ret) + kmem_cache_free(zfcp_fc_req_cache, fc_req); +diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c +index ffb3919675734..97be0765cb9bd 100644 +--- a/drivers/scsi/advansys.c ++++ b/drivers/scsi/advansys.c +@@ -3308,8 +3308,8 @@ static void asc_prt_adv_board_info(struct seq_file *m, struct Scsi_Host *shost) + shost->host_no); + + seq_printf(m, +- " iop_base 0x%lx, cable_detect: %X, err_code %u\n", +- (unsigned long)v->iop_base, ++ " iop_base 0x%p, cable_detect: %X, err_code %u\n", ++ v->iop_base, + AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT, + v->err_code); + +diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +index 8863a74e6c57d..e2586472ecad4 100644 +--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c ++++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +@@ -82,7 +82,7 @@ static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba); + static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba); + static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, + struct device *parent, int npiv); +-static void bnx2fc_destroy_work(struct work_struct *work); ++static void bnx2fc_port_destroy(struct fcoe_port *port); + + static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev); + static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device +@@ -508,7 +508,8 @@ static int bnx2fc_l2_rcv_thread(void *arg) + + static void bnx2fc_recv_frame(struct sk_buff *skb) + { +- u32 fr_len; ++ u64 crc_err; ++ u32 fr_len, fr_crc; + struct fc_lport *lport; + struct fcoe_rcv_info *fr; + struct fc_stats *stats; +@@ -542,6 +543,11 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) + skb_pull(skb, sizeof(struct fcoe_hdr)); + fr_len = skb->len - sizeof(struct fcoe_crc_eof); + ++ stats = per_cpu_ptr(lport->stats, get_cpu()); ++ stats->RxFrames++; ++ stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; ++ put_cpu(); ++ + fp = (struct fc_frame *)skb; + fc_frame_init(fp); + fr_dev(fp) = lport; +@@ -624,16 +630,15 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) + return; + } + +- stats = per_cpu_ptr(lport->stats, smp_processor_id()); +- stats->RxFrames++; +- stats->RxWords += fr_len / FCOE_WORD_TO_BYTE; ++ fr_crc = le32_to_cpu(fr_crc(fp)); + +- if (le32_to_cpu(fr_crc(fp)) != +- ~crc32(~0, skb->data, fr_len)) { +- if (stats->InvalidCRCCount < 5) ++ if (unlikely(fr_crc != ~crc32(~0, skb->data, fr_len))) { ++ stats = per_cpu_ptr(lport->stats, get_cpu()); ++ crc_err = (stats->InvalidCRCCount++); ++ put_cpu(); ++ if (crc_err < 5) + printk(KERN_WARNING PFX "dropping frame with " + "CRC error\n"); +- stats->InvalidCRCCount++; + kfree_skb(skb); + return; + } +@@ -907,9 +912,6 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, + __bnx2fc_destroy(interface); + } + mutex_unlock(&bnx2fc_dev_lock); +- +- /* Ensure ALL destroy work has been completed before return */ +- flush_workqueue(bnx2fc_wq); + return; + + default: +@@ -1215,8 +1217,8 @@ static int bnx2fc_vport_destroy(struct fc_vport *vport) + mutex_unlock(&n_port->lp_mutex); + bnx2fc_free_vport(interface->hba, port->lport); + bnx2fc_port_shutdown(port->lport); ++ bnx2fc_port_destroy(port); + bnx2fc_interface_put(interface); +- queue_work(bnx2fc_wq, &port->destroy_work); + return 0; + } + +@@ -1525,7 +1527,6 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, + port->lport = lport; + port->priv = interface; + port->get_netdev = bnx2fc_netdev; +- INIT_WORK(&port->destroy_work, bnx2fc_destroy_work); + + /* Configure fcoe_port */ + rc = bnx2fc_lport_config(lport); +@@ -1653,8 +1654,8 @@ static void __bnx2fc_destroy(struct bnx2fc_interface *interface) + bnx2fc_interface_cleanup(interface); + bnx2fc_stop(interface); + list_del(&interface->list); ++ bnx2fc_port_destroy(port); + bnx2fc_interface_put(interface); +- queue_work(bnx2fc_wq, &port->destroy_work); + } + + /** +@@ -1694,15 +1695,12 @@ netdev_err: + return rc; + } + +-static void bnx2fc_destroy_work(struct work_struct *work) ++static void bnx2fc_port_destroy(struct fcoe_port *port) + { +- struct fcoe_port *port; + struct fc_lport *lport; + +- port = container_of(work, struct fcoe_port, destroy_work); + lport = port->lport; +- +- BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n"); ++ BNX2FC_HBA_DBG(lport, "Entered %s, destroying lport %p\n", __func__, lport); + + bnx2fc_if_destroy(lport); + } +@@ -2556,9 +2554,6 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev) + __bnx2fc_destroy(interface); + mutex_unlock(&bnx2fc_dev_lock); + +- /* Ensure ALL destroy work has been completed before return */ +- flush_workqueue(bnx2fc_wq); +- + bnx2fc_ulp_stop(hba); + /* unregister cnic device */ + if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic)) +diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c +index dc98f51f466fb..d5ac938970232 100644 +--- a/drivers/scsi/csiostor/csio_lnode.c ++++ b/drivers/scsi/csiostor/csio_lnode.c +@@ -619,7 +619,7 @@ csio_ln_vnp_read_cbfn(struct csio_hw *hw, struct csio_mb *mbp) + struct fc_els_csp *csp; + struct fc_els_cssp *clsp; + enum fw_retval retval; +- __be32 nport_id; ++ __be32 nport_id = 0; + + retval = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)); + if (retval != FW_SUCCESS) { +diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c +index 24c7cefb0b78a..1c79e6c271630 100644 +--- a/drivers/scsi/dc395x.c ++++ b/drivers/scsi/dc395x.c +@@ -4618,6 +4618,7 @@ static int dc395x_init_one(struct pci_dev *dev, const struct pci_device_id *id) + /* initialise the adapter and everything we need */ + if (adapter_init(acb, io_port_base, io_port_len, irq)) { + dprintkl(KERN_INFO, "adapter init failed\n"); ++ acb = NULL; + goto fail; + } + +diff --git a/drivers/scsi/elx/libefc/efc_els.c b/drivers/scsi/elx/libefc/efc_els.c +index 24db0accb256e..5f690378fe9a9 100644 +--- a/drivers/scsi/elx/libefc/efc_els.c ++++ b/drivers/scsi/elx/libefc/efc_els.c +@@ -46,18 +46,14 @@ efc_els_io_alloc_size(struct efc_node *node, u32 reqlen, u32 rsplen) + + efc = node->efc; + +- spin_lock_irqsave(&node->els_ios_lock, flags); +- + if (!node->els_io_enabled) { + efc_log_err(efc, "els io alloc disabled\n"); +- spin_unlock_irqrestore(&node->els_ios_lock, flags); + return NULL; + } + + els = mempool_alloc(efc->els_io_pool, GFP_ATOMIC); + if (!els) { + atomic_add_return(1, &efc->els_io_alloc_failed_count); +- spin_unlock_irqrestore(&node->els_ios_lock, flags); + return NULL; + } + +@@ -74,7 +70,6 @@ efc_els_io_alloc_size(struct efc_node *node, u32 reqlen, u32 rsplen) + &els->io.req.phys, GFP_DMA); + if (!els->io.req.virt) { + mempool_free(els, efc->els_io_pool); +- spin_unlock_irqrestore(&node->els_ios_lock, flags); + return NULL; + } + +@@ -94,10 +89,11 @@ efc_els_io_alloc_size(struct efc_node *node, u32 reqlen, u32 rsplen) + + /* add els structure to ELS IO list */ + INIT_LIST_HEAD(&els->list_entry); ++ spin_lock_irqsave(&node->els_ios_lock, flags); + list_add_tail(&els->list_entry, &node->els_ios_list); ++ spin_unlock_irqrestore(&node->els_ios_lock, flags); + } + +- spin_unlock_irqrestore(&node->els_ios_lock, flags); + return els; + } + +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index 24b72ee4246fb..0165dad803001 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -388,6 +388,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) + shost->shost_state = SHOST_CREATED; + INIT_LIST_HEAD(&shost->__devices); + INIT_LIST_HEAD(&shost->__targets); ++ INIT_LIST_HEAD(&shost->eh_abort_list); + INIT_LIST_HEAD(&shost->eh_cmd_q); + INIT_LIST_HEAD(&shost->starved_list); + init_waitqueue_head(&shost->host_wait); +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 5bc91d34df634..cbc263ec9d661 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -3101,6 +3101,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) + { + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; ++ char *tmp_persistent_address = conn->persistent_address; ++ char *tmp_local_ipaddr = conn->local_ipaddr; + + del_timer_sync(&conn->transport_timer); + +@@ -3122,8 +3124,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) + spin_lock_bh(&session->frwd_lock); + free_pages((unsigned long) conn->data, + get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); +- kfree(conn->persistent_address); +- kfree(conn->local_ipaddr); + /* regular RX path uses back_lock */ + spin_lock_bh(&session->back_lock); + kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, +@@ -3135,6 +3135,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) + mutex_unlock(&session->eh_mutex); + + iscsi_destroy_conn(cls_conn); ++ kfree(tmp_persistent_address); ++ kfree(tmp_local_ipaddr); + } + EXPORT_SYMBOL_GPL(iscsi_conn_teardown); + +diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h +index befeb7c342903..1044832b60549 100644 +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -593,6 +593,7 @@ struct lpfc_vport { + #define FC_VPORT_LOGO_RCVD 0x200 /* LOGO received on vport */ + #define FC_RSCN_DISCOVERY 0x400 /* Auth all devices after RSCN */ + #define FC_LOGO_RCVD_DID_CHNG 0x800 /* FDISC on phys port detect DID chng*/ ++#define FC_PT2PT_NO_NVME 0x1000 /* Don't send NVME PRLI */ + #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ + #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ + #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ +@@ -1022,7 +1023,6 @@ struct lpfc_hba { + #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ + #define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */ + #define HBA_IOQ_FLUSH 0x8000 /* FCP/NVME I/O queues being flushed */ +-#define HBA_FW_DUMP_OP 0x10000 /* Skips fn reset before FW dump */ + #define HBA_RECOVERABLE_UE 0x20000 /* Firmware supports recoverable UE */ + #define HBA_FORCED_LINK_SPEED 0x40000 /* + * Firmware supports Forced Link Speed +@@ -1038,6 +1038,7 @@ struct lpfc_hba { + #define HBA_HBEAT_TMO 0x8000000 /* HBEAT initiated after timeout */ + #define HBA_FLOGI_OUTSTANDING 0x10000000 /* FLOGI is outstanding */ + ++ struct completion *fw_dump_cmpl; /* cmpl event tracker for fw_dump */ + uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ + struct lpfc_dmabuf slim2p; + +@@ -1163,6 +1164,16 @@ struct lpfc_hba { + uint32_t cfg_hostmem_hgp; + uint32_t cfg_log_verbose; + uint32_t cfg_enable_fc4_type; ++#define LPFC_ENABLE_FCP 1 ++#define LPFC_ENABLE_NVME 2 ++#define LPFC_ENABLE_BOTH 3 ++#if (IS_ENABLED(CONFIG_NVME_FC)) ++#define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_BOTH ++#define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_BOTH ++#else ++#define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_FCP ++#define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_FCP ++#endif + uint32_t cfg_aer_support; + uint32_t cfg_sriov_nr_virtfn; + uint32_t cfg_request_firmware_upgrade; +@@ -1184,9 +1195,6 @@ struct lpfc_hba { + uint32_t cfg_ras_fwlog_func; + uint32_t cfg_enable_bbcr; /* Enable BB Credit Recovery */ + uint32_t cfg_enable_dpp; /* Enable Direct Packet Push */ +-#define LPFC_ENABLE_FCP 1 +-#define LPFC_ENABLE_NVME 2 +-#define LPFC_ENABLE_BOTH 3 + uint32_t cfg_enable_pbde; + uint32_t cfg_enable_mi; + struct nvmet_fc_target_port *targetport; +diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c +index ebe417921dac0..9f3f7805f1f95 100644 +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -1315,6 +1315,9 @@ lpfc_issue_lip(struct Scsi_Host *shost) + pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; + pmboxq->u.mb.mbxOwner = OWN_HOST; + ++ if ((vport->fc_flag & FC_PT2PT) && (vport->fc_flag & FC_PT2PT_NO_NVME)) ++ vport->fc_flag &= ~FC_PT2PT_NO_NVME; ++ + mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2); + + if ((mbxstatus == MBX_SUCCESS) && +@@ -1709,25 +1712,25 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) + before_fc_flag = phba->pport->fc_flag; + sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn; + +- /* Disable SR-IOV virtual functions if enabled */ +- if (phba->cfg_sriov_nr_virtfn) { +- pci_disable_sriov(pdev); +- phba->cfg_sriov_nr_virtfn = 0; +- } ++ if (opcode == LPFC_FW_DUMP) { ++ init_completion(&online_compl); ++ phba->fw_dump_cmpl = &online_compl; ++ } else { ++ /* Disable SR-IOV virtual functions if enabled */ ++ if (phba->cfg_sriov_nr_virtfn) { ++ pci_disable_sriov(pdev); ++ phba->cfg_sriov_nr_virtfn = 0; ++ } + +- if (opcode == LPFC_FW_DUMP) +- phba->hba_flag |= HBA_FW_DUMP_OP; ++ status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); + +- status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); ++ if (status != 0) ++ return status; + +- if (status != 0) { +- phba->hba_flag &= ~HBA_FW_DUMP_OP; +- return status; ++ /* wait for the device to be quiesced before firmware reset */ ++ msleep(100); + } + +- /* wait for the device to be quiesced before firmware reset */ +- msleep(100); +- + reg_val = readl(phba->sli4_hba.conf_regs_memmap_p + + LPFC_CTL_PDEV_CTL_OFFSET); + +@@ -1756,24 +1759,42 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "3153 Fail to perform the requested " + "access: x%x\n", reg_val); ++ if (phba->fw_dump_cmpl) ++ phba->fw_dump_cmpl = NULL; + return rc; + } + + /* keep the original port state */ +- if (before_fc_flag & FC_OFFLINE_MODE) +- goto out; +- +- init_completion(&online_compl); +- job_posted = lpfc_workq_post_event(phba, &status, &online_compl, +- LPFC_EVT_ONLINE); +- if (!job_posted) ++ if (before_fc_flag & FC_OFFLINE_MODE) { ++ if (phba->fw_dump_cmpl) ++ phba->fw_dump_cmpl = NULL; + goto out; ++ } + +- wait_for_completion(&online_compl); ++ /* Firmware dump will trigger an HA_ERATT event, and ++ * lpfc_handle_eratt_s4 routine already handles bringing the port back ++ * online. ++ */ ++ if (opcode == LPFC_FW_DUMP) { ++ wait_for_completion(phba->fw_dump_cmpl); ++ } else { ++ init_completion(&online_compl); ++ job_posted = lpfc_workq_post_event(phba, &status, &online_compl, ++ LPFC_EVT_ONLINE); ++ if (!job_posted) ++ goto out; + ++ wait_for_completion(&online_compl); ++ } + out: + /* in any case, restore the virtual functions enabled as before */ + if (sriov_nr_virtfn) { ++ /* If fw_dump was performed, first disable to clean up */ ++ if (opcode == LPFC_FW_DUMP) { ++ pci_disable_sriov(pdev); ++ phba->cfg_sriov_nr_virtfn = 0; ++ } ++ + sriov_err = + lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn); + if (!sriov_err) +@@ -3960,8 +3981,8 @@ LPFC_ATTR_R(nvmet_mrq_post, + * 3 - register both FCP and NVME + * Supported values are [1,3]. Default value is 3 + */ +-LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_BOTH, +- LPFC_ENABLE_FCP, LPFC_ENABLE_BOTH, ++LPFC_ATTR_R(enable_fc4_type, LPFC_DEF_ENBL_FC4_TYPE, ++ LPFC_ENABLE_FCP, LPFC_MAX_ENBL_FC4_TYPE, + "Enable FC4 Protocol support - FCP / NVME"); + + /* +diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h +index c512f41991429..c9770b1d2366a 100644 +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -119,6 +119,8 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *, + struct lpfc_nodelist *lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did); + struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *); + int lpfc_nlp_put(struct lpfc_nodelist *); ++void lpfc_check_nlp_post_devloss(struct lpfc_vport *vport, ++ struct lpfc_nodelist *ndlp); + void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_iocbq *rspiocb); + int lpfc_nlp_not_used(struct lpfc_nodelist *ndlp); +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c +index bd6d459afce54..08b2e85dcd7d8 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -2954,8 +2954,8 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, + char mybuf[64]; + char *pbuf; + +- if (nbytes > 64) +- nbytes = 64; ++ if (nbytes > 63) ++ nbytes = 63; + + memset(mybuf, 0, sizeof(mybuf)); + +diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h +index 871b665bd72e3..37a4b79010bfc 100644 +--- a/drivers/scsi/lpfc/lpfc_disc.h ++++ b/drivers/scsi/lpfc/lpfc_disc.h +@@ -85,6 +85,13 @@ enum lpfc_fc4_xpt_flags { + NLP_XPT_HAS_HH = 0x10 + }; + ++enum lpfc_nlp_save_flags { ++ /* devloss occurred during recovery */ ++ NLP_IN_RECOV_POST_DEV_LOSS = 0x1, ++ /* wait for outstanding LOGO to cmpl */ ++ NLP_WAIT_FOR_LOGO = 0x2, ++}; ++ + struct lpfc_nodelist { + struct list_head nlp_listp; + struct serv_parm fc_sparam; /* buffer for service params */ +@@ -144,8 +151,9 @@ struct lpfc_nodelist { + unsigned long *active_rrqs_xri_bitmap; + struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ + uint32_t fc4_prli_sent; +- u32 upcall_flags; +-#define NLP_WAIT_FOR_LOGO 0x2 ++ ++ /* flags to keep ndlp alive until special conditions are met */ ++ enum lpfc_nlp_save_flags save_flags; + + enum lpfc_fc4_xpt_flags fc4_xpt_flags; + +diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c +index 052c0e5b11195..886006ad12a29 100644 +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -1059,9 +1059,10 @@ stop_rr_fcf_flogi: + + lpfc_printf_vlog(vport, KERN_WARNING, LOG_TRACE_EVENT, + "0150 FLOGI failure Status:x%x/x%x " +- "xri x%x TMO:x%x\n", ++ "xri x%x TMO:x%x refcnt %d\n", + irsp->ulpStatus, irsp->un.ulpWord[4], +- cmdiocb->sli4_xritag, irsp->ulpTimeout); ++ cmdiocb->sli4_xritag, irsp->ulpTimeout, ++ kref_read(&ndlp->kref)); + + /* If this is not a loop open failure, bail out */ + if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && +@@ -1071,7 +1072,8 @@ stop_rr_fcf_flogi: + + /* FLOGI failed, so there is no fabric */ + spin_lock_irq(shost->host_lock); +- vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); ++ vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP | ++ FC_PT2PT_NO_NVME); + spin_unlock_irq(shost->host_lock); + + /* If private loop, then allow max outstanding els to be +@@ -1122,12 +1124,12 @@ stop_rr_fcf_flogi: + /* FLOGI completes successfully */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0101 FLOGI completes successfully, I/O tag:x%x, " +- "xri x%x Data: x%x x%x x%x x%x x%x x%x x%x\n", ++ "xri x%x Data: x%x x%x x%x x%x x%x x%x x%x %d\n", + cmdiocb->iotag, cmdiocb->sli4_xritag, + irsp->un.ulpWord[4], sp->cmn.e_d_tov, + sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution, + vport->port_state, vport->fc_flag, +- sp->cmn.priority_tagging); ++ sp->cmn.priority_tagging, kref_read(&ndlp->kref)); + + if (sp->cmn.priority_tagging) + vport->vmid_flag |= LPFC_VMID_ISSUE_QFPA; +@@ -1205,8 +1207,6 @@ flogifail: + phba->fcf.fcf_flag &= ~FCF_DISCOVERY; + spin_unlock_irq(&phba->hbalock); + +- if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) +- lpfc_nlp_put(ndlp); + if (!lpfc_error_lost_link(irsp)) { + /* FLOGI failed, so just use loop map to make discovery list */ + lpfc_disc_list_loopmap(vport); +@@ -2899,9 +2899,9 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + irsp = &(rspiocb->iocb); + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_LOGO_SND; +- if (ndlp->upcall_flags & NLP_WAIT_FOR_LOGO) { ++ if (ndlp->save_flags & NLP_WAIT_FOR_LOGO) { + wake_up_waiter = 1; +- ndlp->upcall_flags &= ~NLP_WAIT_FOR_LOGO; ++ ndlp->save_flags &= ~NLP_WAIT_FOR_LOGO; + } + spin_unlock_irq(&ndlp->lock); + +@@ -3532,11 +3532,6 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) + return 1; + } + +- /* This will cause the callback-function lpfc_cmpl_els_cmd to +- * trigger the release of node. +- */ +- if (!(vport->fc_flag & FC_PT2PT)) +- lpfc_nlp_put(ndlp); + return 0; + } + +@@ -4593,6 +4588,23 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + /* Added for Vendor specifc support + * Just keep retrying for these Rsn / Exp codes + */ ++ if ((vport->fc_flag & FC_PT2PT) && ++ cmd == ELS_CMD_NVMEPRLI) { ++ switch (stat.un.b.lsRjtRsnCode) { ++ case LSRJT_UNABLE_TPC: ++ case LSRJT_INVALID_CMD: ++ case LSRJT_LOGICAL_ERR: ++ case LSRJT_CMD_UNSUPPORTED: ++ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, ++ "0168 NVME PRLI LS_RJT " ++ "reason %x port doesn't " ++ "support NVME, disabling NVME\n", ++ stat.un.b.lsRjtRsnCode); ++ retry = 0; ++ vport->fc_flag |= FC_PT2PT_NO_NVME; ++ goto out_retry; ++ } ++ } + switch (stat.un.b.lsRjtRsnCode) { + case LSRJT_UNABLE_TPC: + /* The driver has a VALID PLOGI but the rport has +@@ -5076,14 +5088,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + /* NPort Recovery mode or node is just allocated */ + if (!lpfc_nlp_not_used(ndlp)) { + /* A LOGO is completing and the node is in NPR state. +- * If this a fabric node that cleared its transport +- * registration, release the rpi. ++ * Just unregister the RPI because the node is still ++ * required. + */ +- spin_lock_irq(&ndlp->lock); +- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; +- if (phba->sli_rev == LPFC_SLI_REV4) +- ndlp->nlp_flag |= NLP_RELEASE_RPI; +- spin_unlock_irq(&ndlp->lock); + lpfc_unreg_rpi(vport, ndlp); + } else { + /* Indicate the node has already released, should +@@ -6216,6 +6223,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) + * from backend + */ + lpfc_nlp_unreg_node(vport, ndlp); ++ lpfc_unreg_rpi(vport, ndlp); + continue; + } + +@@ -6882,6 +6890,7 @@ static int + lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) + { + LPFC_MBOXQ_t *mbox = NULL; ++ struct lpfc_dmabuf *mp; + int rc; + + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); +@@ -6897,8 +6906,11 @@ lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) + mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0; + mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context; + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); +- if (rc == MBX_NOT_FINISHED) ++ if (rc == MBX_NOT_FINISHED) { ++ mp = (struct lpfc_dmabuf *)mbox->ctx_buf; ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); + goto issue_mbox_fail; ++ } + + return 0; + +@@ -10713,6 +10725,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + irsp->ulpStatus, irsp->un.ulpWord[4]); + goto fdisc_failed; + } ++ ++ lpfc_check_nlp_post_devloss(vport, ndlp); ++ + spin_lock_irq(shost->host_lock); + vport->fc_flag &= ~FC_VPORT_CVL_RCVD; + vport->fc_flag &= ~FC_VPORT_LOGO_RCVD; +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 7195ca0275f93..3bb7c2aa949f7 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -209,7 +209,12 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) + + spin_lock_irqsave(&ndlp->lock, iflags); + ndlp->nlp_flag |= NLP_IN_DEV_LOSS; +- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ++ ++ /* If there is a PLOGI in progress, and we are in a ++ * NLP_NPR_2B_DISC state, don't turn off the flag. ++ */ ++ if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE) ++ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + + /* + * The backend does not expect any more calls associated with this +@@ -340,6 +345,37 @@ static void lpfc_check_inactive_vmid(struct lpfc_hba *phba) + lpfc_destroy_vport_work_array(phba, vports); + } + ++/** ++ * lpfc_check_nlp_post_devloss - Check to restore ndlp refcnt after devloss ++ * @vport: Pointer to vport object. ++ * @ndlp: Pointer to remote node object. ++ * ++ * If NLP_IN_RECOV_POST_DEV_LOSS flag was set due to outstanding recovery of ++ * node during dev_loss_tmo processing, then this function restores the nlp_put ++ * kref decrement from lpfc_dev_loss_tmo_handler. ++ **/ ++void ++lpfc_check_nlp_post_devloss(struct lpfc_vport *vport, ++ struct lpfc_nodelist *ndlp) ++{ ++ unsigned long iflags; ++ ++ spin_lock_irqsave(&ndlp->lock, iflags); ++ if (ndlp->save_flags & NLP_IN_RECOV_POST_DEV_LOSS) { ++ ndlp->save_flags &= ~NLP_IN_RECOV_POST_DEV_LOSS; ++ spin_unlock_irqrestore(&ndlp->lock, iflags); ++ lpfc_nlp_get(ndlp); ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE, ++ "8438 Devloss timeout reversed on DID x%x " ++ "refcnt %d ndlp %p flag x%x " ++ "port_state = x%x\n", ++ ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp, ++ ndlp->nlp_flag, vport->port_state); ++ spin_lock_irqsave(&ndlp->lock, iflags); ++ } ++ spin_unlock_irqrestore(&ndlp->lock, iflags); ++} ++ + /** + * lpfc_dev_loss_tmo_handler - Remote node devloss timeout handler + * @ndlp: Pointer to remote node object. +@@ -358,6 +394,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) + uint8_t *name; + int warn_on = 0; + int fcf_inuse = 0; ++ bool recovering = false; ++ struct fc_vport *fc_vport = NULL; + unsigned long iflags; + + vport = ndlp->vport; +@@ -394,6 +432,64 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) + + /* Fabric nodes are done. */ + if (ndlp->nlp_type & NLP_FABRIC) { ++ spin_lock_irqsave(&ndlp->lock, iflags); ++ /* In massive vport configuration settings, it's possible ++ * dev_loss_tmo fired during node recovery. So, check if ++ * fabric nodes are in discovery states outstanding. ++ */ ++ switch (ndlp->nlp_DID) { ++ case Fabric_DID: ++ fc_vport = vport->fc_vport; ++ if (fc_vport && ++ fc_vport->vport_state == FC_VPORT_INITIALIZING) ++ recovering = true; ++ break; ++ case Fabric_Cntl_DID: ++ if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) ++ recovering = true; ++ break; ++ case FDMI_DID: ++ fallthrough; ++ case NameServer_DID: ++ if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && ++ ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) ++ recovering = true; ++ break; ++ } ++ spin_unlock_irqrestore(&ndlp->lock, iflags); ++ ++ /* Mark an NLP_IN_RECOV_POST_DEV_LOSS flag to know if reversing ++ * the following lpfc_nlp_put is necessary after fabric node is ++ * recovered. ++ */ ++ if (recovering) { ++ lpfc_printf_vlog(vport, KERN_INFO, ++ LOG_DISCOVERY | LOG_NODE, ++ "8436 Devloss timeout marked on " ++ "DID x%x refcnt %d ndlp %p " ++ "flag x%x port_state = x%x\n", ++ ndlp->nlp_DID, kref_read(&ndlp->kref), ++ ndlp, ndlp->nlp_flag, ++ vport->port_state); ++ spin_lock_irqsave(&ndlp->lock, iflags); ++ ndlp->save_flags |= NLP_IN_RECOV_POST_DEV_LOSS; ++ spin_unlock_irqrestore(&ndlp->lock, iflags); ++ } else if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { ++ /* Fabric node fully recovered before this dev_loss_tmo ++ * queue work is processed. Thus, ignore the ++ * dev_loss_tmo event. ++ */ ++ lpfc_printf_vlog(vport, KERN_INFO, ++ LOG_DISCOVERY | LOG_NODE, ++ "8437 Devloss timeout ignored on " ++ "DID x%x refcnt %d ndlp %p " ++ "flag x%x port_state = x%x\n", ++ ndlp->nlp_DID, kref_read(&ndlp->kref), ++ ndlp, ndlp->nlp_flag, ++ vport->port_state); ++ return fcf_inuse; ++ } ++ + lpfc_nlp_put(ndlp); + return fcf_inuse; + } +@@ -423,6 +519,14 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) + ndlp->nlp_state, ndlp->nlp_rpi); + } + ++ /* If we are devloss, but we are in the process of rediscovering the ++ * ndlp, don't issue a NLP_EVT_DEVICE_RM event. ++ */ ++ if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE && ++ ndlp->nlp_state <= NLP_STE_PRLI_ISSUE) { ++ return fcf_inuse; ++ } ++ + if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) + lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); + +@@ -765,10 +869,16 @@ lpfc_work_done(struct lpfc_hba *phba) + if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) + lpfc_sli4_post_async_mbox(phba); + +- if (ha_copy & HA_ERATT) ++ if (ha_copy & HA_ERATT) { + /* Handle the error attention event */ + lpfc_handle_eratt(phba); + ++ if (phba->fw_dump_cmpl) { ++ complete(phba->fw_dump_cmpl); ++ phba->fw_dump_cmpl = NULL; ++ } ++ } ++ + if (ha_copy & HA_MBATT) + lpfc_sli_handle_mb_event(phba); + +@@ -4351,6 +4461,8 @@ lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) + goto out; + } + ++ lpfc_check_nlp_post_devloss(vport, ndlp); ++ + if (phba->sli_rev < LPFC_SLI_REV4) + ndlp->nlp_rpi = mb->un.varWords[0]; + +@@ -4360,6 +4472,7 @@ lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) + ndlp->nlp_state); + + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ++ ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; + ndlp->nlp_type |= NLP_FABRIC; + lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); + +@@ -4449,8 +4562,9 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + fc_remote_port_rolechg(rport, rport_ids.roles); + + lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, +- "3183 %s rport x%px DID x%x, role x%x\n", +- __func__, rport, rport->port_id, rport->roles); ++ "3183 %s rport x%px DID x%x, role x%x refcnt %d\n", ++ __func__, rport, rport->port_id, rport->roles, ++ kref_read(&ndlp->kref)); + + if ((rport->scsi_target_id != -1) && + (rport->scsi_target_id < LPFC_MAX_TARGET)) { +@@ -4475,8 +4589,9 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) + + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "3184 rport unregister x%06x, rport x%px " +- "xptflg x%x\n", +- ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags); ++ "xptflg x%x refcnt %d\n", ++ ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags, ++ kref_read(&ndlp->kref)); + + fc_remote_port_delete(rport); + lpfc_nlp_put(ndlp); +@@ -4525,9 +4640,10 @@ lpfc_nlp_counters(struct lpfc_vport *vport, int state, int count) + void + lpfc_nlp_reg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + { +- + unsigned long iflags; + ++ lpfc_check_nlp_post_devloss(vport, ndlp); ++ + spin_lock_irqsave(&ndlp->lock, iflags); + if (ndlp->fc4_xpt_flags & NLP_XPT_REGD) { + /* Already registered with backend, trigger rescan */ +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index 195169badb372..3eebcae52784d 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -2055,7 +2055,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) + } + if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && + reg_err2 == SLIPORT_ERR2_REG_FW_RESTART) { +- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, ++ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "3143 Port Down: Firmware Update " + "Detected\n"); + en_rn_msg = false; +@@ -3694,12 +3694,16 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) + lpfc_disc_state_machine(vports[i], ndlp, + NULL, NLP_EVT_DEVICE_RECOVERY); + +- /* Don't remove the node unless the ++ /* Don't remove the node unless the node + * has been unregistered with the +- * transport. If so, let dev_loss +- * take care of the node. ++ * transport, and we're not in recovery ++ * before dev_loss_tmo triggered. ++ * Otherwise, let dev_loss take care of ++ * the node. + */ +- if (!(ndlp->fc4_xpt_flags & ++ if (!(ndlp->save_flags & ++ NLP_IN_RECOV_POST_DEV_LOSS) && ++ !(ndlp->fc4_xpt_flags & + (NVME_XPT_REGD | SCSI_XPT_REGD))) + lpfc_disc_state_machine + (vports[i], ndlp, +@@ -5310,8 +5314,10 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, + */ + if (!(phba->hba_flag & HBA_FCOE_MODE)) { + rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); +- if (rc == MBX_NOT_FINISHED) ++ if (rc == MBX_NOT_FINISHED) { ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); + goto out_free_dmabuf; ++ } + return; + } + /* +@@ -6262,8 +6268,10 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc) + } + + rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); +- if (rc == MBX_NOT_FINISHED) ++ if (rc == MBX_NOT_FINISHED) { ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); + goto out_free_dmabuf; ++ } + return; + + out_free_dmabuf: +diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c +index 27263f02ab9f6..fdf5e777bf113 100644 +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -322,6 +322,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + { + struct lpfc_hba *phba = vport->phba; + struct lpfc_dmabuf *pcmd; ++ struct lpfc_dmabuf *mp; + uint64_t nlp_portwwn = 0; + uint32_t *lp; + IOCB_t *icmd; +@@ -571,6 +572,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + * a default RPI. + */ + if (phba->sli_rev == LPFC_SLI_REV4) { ++ mp = (struct lpfc_dmabuf *)login_mbox->ctx_buf; ++ if (mp) { ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); ++ kfree(mp); ++ } + mempool_free(login_mbox, phba->mbox_mem_pool); + login_mbox = NULL; + } else { +@@ -1955,8 +1961,9 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, + * is configured try it. + */ + ndlp->nlp_fc4_type |= NLP_FC4_FCP; +- if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || +- (vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { ++ if ((!(vport->fc_flag & FC_PT2PT_NO_NVME)) && ++ (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH || ++ vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { + ndlp->nlp_fc4_type |= NLP_FC4_NVME; + /* We need to update the localport also */ + lpfc_nvme_update_localport(vport); +diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c +index 479b3eed62085..66cb66aea2cf9 100644 +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -209,8 +209,9 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport) + * calling state machine to remove the node. + */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, +- "6146 remoteport delete of remoteport x%px\n", +- remoteport); ++ "6146 remoteport delete of remoteport x%px, ndlp x%px " ++ "DID x%x xflags x%x\n", ++ remoteport, ndlp, ndlp->nlp_DID, ndlp->fc4_xpt_flags); + spin_lock_irq(&ndlp->lock); + + /* The register rebind might have occurred before the delete +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index befdf864c43bd..3d9175f1b6787 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -6455,28 +6455,28 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) + + /* Issue LOGO, if no LOGO is outstanding */ + spin_lock_irqsave(&pnode->lock, flags); +- if (!(pnode->upcall_flags & NLP_WAIT_FOR_LOGO) && ++ if (!(pnode->save_flags & NLP_WAIT_FOR_LOGO) && + !pnode->logo_waitq) { + pnode->logo_waitq = &waitq; + pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; + pnode->nlp_flag |= NLP_ISSUE_LOGO; +- pnode->upcall_flags |= NLP_WAIT_FOR_LOGO; ++ pnode->save_flags |= NLP_WAIT_FOR_LOGO; + spin_unlock_irqrestore(&pnode->lock, flags); + lpfc_unreg_rpi(vport, pnode); + wait_event_timeout(waitq, +- (!(pnode->upcall_flags & ++ (!(pnode->save_flags & + NLP_WAIT_FOR_LOGO)), + msecs_to_jiffies(dev_loss_tmo * + 1000)); + +- if (pnode->upcall_flags & NLP_WAIT_FOR_LOGO) { ++ if (pnode->save_flags & NLP_WAIT_FOR_LOGO) { + lpfc_printf_vlog(vport, KERN_ERR, logit, + "0725 SCSI layer TGTRST " + "failed & LOGO TMO (%d, %llu) " + "return x%x\n", + tgt_id, lun_id, status); + spin_lock_irqsave(&pnode->lock, flags); +- pnode->upcall_flags &= ~NLP_WAIT_FOR_LOGO; ++ pnode->save_flags &= ~NLP_WAIT_FOR_LOGO; + } else { + spin_lock_irqsave(&pnode->lock, flags); + } +@@ -6628,6 +6628,13 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd) + if (rc) + goto error; + ++ /* Wait for successful restart of adapter */ ++ if (phba->sli_rev < LPFC_SLI_REV4) { ++ rc = lpfc_sli_chipset_init(phba); ++ if (rc) ++ goto error; ++ } ++ + rc = lpfc_online(phba); + if (rc) + goto error; +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 026a1196a54d5..68d8e55c1205c 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -5043,12 +5043,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) + phba->fcf.fcf_flag = 0; + spin_unlock_irq(&phba->hbalock); + +- /* SLI4 INTF 2: if FW dump is being taken skip INIT_PORT */ +- if (phba->hba_flag & HBA_FW_DUMP_OP) { +- phba->hba_flag &= ~HBA_FW_DUMP_OP; +- return rc; +- } +- + /* Now physically reset the device */ + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "0389 Performing PCI function reset!\n"); +@@ -8153,6 +8147,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) + struct lpfc_vport *vport = phba->pport; + struct lpfc_dmabuf *mp; + struct lpfc_rqb *rqbp; ++ u32 flg; + + /* Perform a PCI function reset to start from clean */ + rc = lpfc_pci_function_reset(phba); +@@ -8166,7 +8161,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) + else { + spin_lock_irq(&phba->hbalock); + phba->sli.sli_flag |= LPFC_SLI_ACTIVE; ++ flg = phba->sli.sli_flag; + spin_unlock_irq(&phba->hbalock); ++ /* Allow a little time after setting SLI_ACTIVE for any polled ++ * MBX commands to complete via BSG. ++ */ ++ for (i = 0; i < 50 && (flg & LPFC_SLI_MBOX_ACTIVE); i++) { ++ msleep(20); ++ spin_lock_irq(&phba->hbalock); ++ flg = phba->sli.sli_flag; ++ spin_unlock_irq(&phba->hbalock); ++ } + } + + lpfc_sli4_dip(phba); +@@ -9750,7 +9755,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, + "(%d):2541 Mailbox command x%x " + "(x%x/x%x) failure: " + "mqe_sta: x%x mcqe_sta: x%x/x%x " +- "Data: x%x x%x\n,", ++ "Data: x%x x%x\n", + mboxq->vport ? mboxq->vport->vpi : 0, + mboxq->u.mb.mbxCommand, + lpfc_sli_config_mbox_subsys_get(phba, +@@ -9784,7 +9789,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, + "(%d):2597 Sync Mailbox command " + "x%x (x%x/x%x) failure: " + "mqe_sta: x%x mcqe_sta: x%x/x%x " +- "Data: x%x x%x\n,", ++ "Data: x%x x%x\n", + mboxq->vport ? mboxq->vport->vpi : 0, + mboxq->u.mb.mbxCommand, + lpfc_sli_config_mbox_subsys_get(phba, +@@ -12404,17 +12409,17 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; +- if (cmdiocb->iocb_flag & LPFC_IO_FCP) { +- abtsiocbp->iocb_flag |= LPFC_IO_FCP; +- abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; +- } ++ if (cmdiocb->iocb_flag & LPFC_IO_FCP) ++ abtsiocbp->iocb_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX); + if (cmdiocb->iocb_flag & LPFC_IO_FOF) + abtsiocbp->iocb_flag |= LPFC_IO_FOF; + +- if (phba->link_state >= LPFC_LINK_UP) +- iabt->ulpCommand = CMD_ABORT_XRI_CN; +- else ++ if (phba->link_state < LPFC_LINK_UP || ++ (phba->sli_rev == LPFC_SLI_REV4 && ++ phba->sli4_hba.link_state.status == LPFC_FC_LA_TYPE_LINK_DOWN)) + iabt->ulpCommand = CMD_CLOSE_XRI_CN; ++ else ++ iabt->ulpCommand = CMD_ABORT_XRI_CN; + + if (cmpl) + abtsiocbp->iocb_cmpl = cmpl; +@@ -12488,15 +12493,54 @@ lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) + } + + /** +- * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN ++ * lpfc_sli_validate_fcp_iocb_for_abort - filter iocbs appropriate for FCP aborts ++ * @iocbq: Pointer to iocb object. ++ * @vport: Pointer to driver virtual port object. ++ * ++ * This function acts as an iocb filter for functions which abort FCP iocbs. ++ * ++ * Return values ++ * -ENODEV, if a null iocb or vport ptr is encountered ++ * -EINVAL, if the iocb is not an FCP I/O, not on the TX cmpl queue, premarked as ++ * driver already started the abort process, or is an abort iocb itself ++ * 0, passes criteria for aborting the FCP I/O iocb ++ **/ ++static int ++lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq, ++ struct lpfc_vport *vport) ++{ ++ IOCB_t *icmd = NULL; ++ ++ /* No null ptr vports */ ++ if (!iocbq || iocbq->vport != vport) ++ return -ENODEV; ++ ++ /* iocb must be for FCP IO, already exists on the TX cmpl queue, ++ * can't be premarked as driver aborted, nor be an ABORT iocb itself ++ */ ++ icmd = &iocbq->iocb; ++ if (!(iocbq->iocb_flag & LPFC_IO_FCP) || ++ !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || ++ (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) || ++ (icmd->ulpCommand == CMD_ABORT_XRI_CN || ++ icmd->ulpCommand == CMD_CLOSE_XRI_CN)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/** ++ * lpfc_sli_validate_fcp_iocb - validate commands associated with a SCSI target + * @iocbq: Pointer to driver iocb object. + * @vport: Pointer to driver virtual port object. + * @tgt_id: SCSI ID of the target. + * @lun_id: LUN ID of the scsi device. + * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST + * +- * This function acts as an iocb filter for functions which abort or count +- * all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return ++ * This function acts as an iocb filter for validating a lun/SCSI target/SCSI ++ * host. ++ * ++ * It will return + * 0 if the filtering criteria is met for the given iocb and will return + * 1 if the filtering criteria is not met. + * If ctx_cmd == LPFC_CTX_LUN, the function returns 0 only if the +@@ -12515,22 +12559,8 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, + lpfc_ctx_cmd ctx_cmd) + { + struct lpfc_io_buf *lpfc_cmd; +- IOCB_t *icmd = NULL; + int rc = 1; + +- if (!iocbq || iocbq->vport != vport) +- return rc; +- +- if (!(iocbq->iocb_flag & LPFC_IO_FCP) || +- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) || +- iocbq->iocb_flag & LPFC_DRIVER_ABORTED) +- return rc; +- +- icmd = &iocbq->iocb; +- if (icmd->ulpCommand == CMD_ABORT_XRI_CN || +- icmd->ulpCommand == CMD_CLOSE_XRI_CN) +- return rc; +- + lpfc_cmd = container_of(iocbq, struct lpfc_io_buf, cur_iocbq); + + if (lpfc_cmd->pCmd == NULL) +@@ -12585,17 +12615,33 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, + { + struct lpfc_hba *phba = vport->phba; + struct lpfc_iocbq *iocbq; ++ IOCB_t *icmd = NULL; + int sum, i; ++ unsigned long iflags; + +- spin_lock_irq(&phba->hbalock); ++ spin_lock_irqsave(&phba->hbalock, iflags); + for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { + iocbq = phba->sli.iocbq_lookup[i]; + +- if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, +- ctx_cmd) == 0) ++ if (!iocbq || iocbq->vport != vport) ++ continue; ++ if (!(iocbq->iocb_flag & LPFC_IO_FCP) || ++ !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) ++ continue; ++ ++ /* Include counting outstanding aborts */ ++ icmd = &iocbq->iocb; ++ if (icmd->ulpCommand == CMD_ABORT_XRI_CN || ++ icmd->ulpCommand == CMD_CLOSE_XRI_CN) { ++ sum++; ++ continue; ++ } ++ ++ if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, ++ ctx_cmd) == 0) + sum++; + } +- spin_unlock_irq(&phba->hbalock); ++ spin_unlock_irqrestore(&phba->hbalock, iflags); + + return sum; + } +@@ -12662,7 +12708,11 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + * + * This function sends an abort command for every SCSI command + * associated with the given virtual port pending on the ring +- * filtered by lpfc_sli_validate_fcp_iocb function. ++ * filtered by lpfc_sli_validate_fcp_iocb_for_abort and then ++ * lpfc_sli_validate_fcp_iocb function. The ordering for validation before ++ * submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort ++ * followed by lpfc_sli_validate_fcp_iocb. ++ * + * When abort_cmd == LPFC_CTX_LUN, the function sends abort only to the + * FCP iocbs associated with lun specified by tgt_id and lun_id + * parameters +@@ -12694,6 +12744,9 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, + for (i = 1; i <= phba->sli.last_iotag; i++) { + iocbq = phba->sli.iocbq_lookup[i]; + ++ if (lpfc_sli_validate_fcp_iocb_for_abort(iocbq, vport)) ++ continue; ++ + if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, + abort_cmd) != 0) + continue; +@@ -12726,7 +12779,11 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, + * + * This function sends an abort command for every SCSI command + * associated with the given virtual port pending on the ring +- * filtered by lpfc_sli_validate_fcp_iocb function. ++ * filtered by lpfc_sli_validate_fcp_iocb_for_abort and then ++ * lpfc_sli_validate_fcp_iocb function. The ordering for validation before ++ * submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort ++ * followed by lpfc_sli_validate_fcp_iocb. ++ * + * When taskmgmt_cmd == LPFC_CTX_LUN, the function sends abort only to the + * FCP iocbs associated with lun specified by tgt_id and lun_id + * parameters +@@ -12764,6 +12821,9 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, + for (i = 1; i <= phba->sli.last_iotag; i++) { + iocbq = phba->sli.iocbq_lookup[i]; + ++ if (lpfc_sli_validate_fcp_iocb_for_abort(iocbq, vport)) ++ continue; ++ + if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, + cmd) != 0) + continue; +@@ -13317,6 +13377,7 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) + uint32_t uerr_sta_hi, uerr_sta_lo; + uint32_t if_type, portsmphr; + struct lpfc_register portstat_reg; ++ u32 logmask; + + /* + * For now, use the SLI4 device internal unrecoverable error +@@ -13367,7 +13428,12 @@ lpfc_sli4_eratt_read(struct lpfc_hba *phba) + readl(phba->sli4_hba.u.if_type2.ERR1regaddr); + phba->work_status[1] = + readl(phba->sli4_hba.u.if_type2.ERR2regaddr); +- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, ++ logmask = LOG_TRACE_EVENT; ++ if (phba->work_status[0] == ++ SLIPORT_ERR1_REG_ERR_CODE_2 && ++ phba->work_status[1] == SLIPORT_ERR2_REG_FW_RESTART) ++ logmask = LOG_SLI; ++ lpfc_printf_log(phba, KERN_ERR, logmask, + "2885 Port Status Event: " + "port status reg 0x%x, " + "port smphr reg 0x%x, " +@@ -21107,6 +21173,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) + fail_msg, + piocbq->iotag, piocbq->sli4_xritag); + list_add_tail(&piocbq->list, &completions); ++ fail_msg = NULL; + } + spin_unlock_irqrestore(&pring->ring_lock, iflags); + } +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index 26d0cf9353dd6..eb5ceb75a15ec 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -3530,6 +3530,9 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, + if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) + return IRQ_HANDLED; + ++ if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1)) ++ return 0; ++ + desc = fusion->reply_frames_desc[MSIxIndex] + + fusion->last_reply_idx[MSIxIndex]; + +@@ -3540,11 +3543,11 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, + reply_descript_type = reply_desc->ReplyFlags & + MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; + +- if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) ++ if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { ++ if (irq_context) ++ atomic_dec(&irq_context->in_used); + return IRQ_NONE; +- +- if (irq_context && !atomic_add_unless(&irq_context->in_used, 1, 1)) +- return 0; ++ } + + num_completed = 0; + +diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h +index 9787b53a2b598..2cc42432bd0c0 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr.h ++++ b/drivers/scsi/mpi3mr/mpi3mr.h +@@ -79,7 +79,8 @@ extern int prot_mask; + + /* Operational queue management definitions */ + #define MPI3MR_OP_REQ_Q_QD 512 +-#define MPI3MR_OP_REP_Q_QD 4096 ++#define MPI3MR_OP_REP_Q_QD 1024 ++#define MPI3MR_OP_REP_Q_QD4K 4096 + #define MPI3MR_OP_REQ_Q_SEG_SIZE 4096 + #define MPI3MR_OP_REP_Q_SEG_SIZE 4096 + #define MPI3MR_MAX_SEG_LIST_SIZE 4096 +diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c +index 4a8316c6bd41a..5af36c54cb596 100644 +--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c ++++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c +@@ -1278,7 +1278,7 @@ static void mpi3mr_free_op_req_q_segments(struct mpi3mr_ioc *mrioc, u16 q_idx) + mrioc->op_reply_qinfo[q_idx].q_segment_list = NULL; + } + } else +- size = mrioc->req_qinfo[q_idx].num_requests * ++ size = mrioc->req_qinfo[q_idx].segment_qd * + mrioc->facts.op_req_sz; + + for (j = 0; j < mrioc->req_qinfo[q_idx].num_segments; j++) { +@@ -1565,6 +1565,8 @@ static int mpi3mr_create_op_reply_q(struct mpi3mr_ioc *mrioc, u16 qidx) + + reply_qid = qidx + 1; + op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; ++ if (!mrioc->pdev->revision) ++ op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD4K; + op_reply_q->ci = 0; + op_reply_q->ephase = 1; + atomic_set(&op_reply_q->pend_ios, 0); +diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c +index 27eb652b564f5..81dab9b82f79f 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_base.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c +@@ -639,8 +639,8 @@ static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc) + mpi_request->IOCParameter = MPI26_SET_IOC_PARAMETER_SYNC_TIMESTAMP; + current_time = ktime_get_real(); + TimeStamp = ktime_to_ms(current_time); +- mpi_request->Reserved7 = cpu_to_le32(TimeStamp & 0xFFFFFFFF); +- mpi_request->IOCParameterValue = cpu_to_le32(TimeStamp >> 32); ++ mpi_request->Reserved7 = cpu_to_le32(TimeStamp >> 32); ++ mpi_request->IOCParameterValue = cpu_to_le32(TimeStamp & 0xFFFFFFFF); + init_completion(&ioc->scsih_cmds.done); + ioc->put_smid_default(ioc, smid); + dinitprintk(ioc, ioc_info(ioc, +diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h +index f87c0911f66ad..1b3a44ce65aae 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_base.h ++++ b/drivers/scsi/mpt3sas/mpt3sas_base.h +@@ -142,6 +142,8 @@ + + #define MPT_MAX_CALLBACKS 32 + ++#define MPT_MAX_HBA_NUM_PHYS 32 ++ + #define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ + /* reserved for issuing internally framed scsi io cmds */ + #define INTERNAL_SCSIIO_CMDS_COUNT 3 +@@ -798,6 +800,7 @@ struct _sas_phy { + * @enclosure_handle: handle for this a member of an enclosure + * @device_info: bitwise defining capabilities of this sas_host/expander + * @responding: used in _scsih_expander_device_mark_responding ++ * @nr_phys_allocated: Allocated memory for this many count phys + * @phy: a list of phys that make up this sas_host/expander + * @sas_port_list: list of ports attached to this sas_host/expander + * @port: hba port entry containing node's port number info +@@ -813,6 +816,7 @@ struct _sas_node { + u16 enclosure_handle; + u64 enclosure_logical_id; + u8 responding; ++ u8 nr_phys_allocated; + struct hba_port *port; + struct _sas_phy *phy; + struct list_head sas_port_list; +diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +index ad1b6c2b37a74..c1f900c6ea003 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c +@@ -3869,7 +3869,7 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, + + shost_for_each_device(sdev, ioc->shost) { + sas_device_priv_data = sdev->hostdata; +- if (!sas_device_priv_data) ++ if (!sas_device_priv_data || !sas_device_priv_data->sas_target) + continue; + if (sas_device_priv_data->sas_target->sas_address + != sas_address) +@@ -6406,11 +6406,26 @@ _scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc) + int i, j, count = 0, lcount = 0; + int ret; + u64 sas_addr; ++ u8 num_phys; + + drsprintk(ioc, ioc_info(ioc, + "updating ports for sas_host(0x%016llx)\n", + (unsigned long long)ioc->sas_hba.sas_address)); + ++ mpt3sas_config_get_number_hba_phys(ioc, &num_phys); ++ if (!num_phys) { ++ ioc_err(ioc, "failure at %s:%d/%s()!\n", ++ __FILE__, __LINE__, __func__); ++ return; ++ } ++ ++ if (num_phys > ioc->sas_hba.nr_phys_allocated) { ++ ioc_err(ioc, "failure at %s:%d/%s()!\n", ++ __FILE__, __LINE__, __func__); ++ return; ++ } ++ ioc->sas_hba.num_phys = num_phys; ++ + port_table = kcalloc(ioc->sas_hba.num_phys, + sizeof(struct hba_port), GFP_KERNEL); + if (!port_table) +@@ -6611,6 +6626,30 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) + ioc->sas_hba.phy[i].hba_vphy = 1; + } + ++ /* ++ * Add new HBA phys to STL if these new phys got added as part ++ * of HBA Firmware upgrade/downgrade operation. ++ */ ++ if (!ioc->sas_hba.phy[i].phy) { ++ if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, ++ &phy_pg0, i))) { ++ ioc_err(ioc, "failure at %s:%d/%s()!\n", ++ __FILE__, __LINE__, __func__); ++ continue; ++ } ++ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & ++ MPI2_IOCSTATUS_MASK; ++ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { ++ ioc_err(ioc, "failure at %s:%d/%s()!\n", ++ __FILE__, __LINE__, __func__); ++ continue; ++ } ++ ioc->sas_hba.phy[i].phy_id = i; ++ mpt3sas_transport_add_host_phy(ioc, ++ &ioc->sas_hba.phy[i], phy_pg0, ++ ioc->sas_hba.parent_dev); ++ continue; ++ } + ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; + attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. + AttachedDevHandle); +@@ -6622,6 +6661,19 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) + attached_handle, i, link_rate, + ioc->sas_hba.phy[i].port); + } ++ /* ++ * Clear the phy details if this phy got disabled as part of ++ * HBA Firmware upgrade/downgrade operation. ++ */ ++ for (i = ioc->sas_hba.num_phys; ++ i < ioc->sas_hba.nr_phys_allocated; i++) { ++ if (ioc->sas_hba.phy[i].phy && ++ ioc->sas_hba.phy[i].phy->negotiated_linkrate >= ++ SAS_LINK_RATE_1_5_GBPS) ++ mpt3sas_transport_update_links(ioc, ++ ioc->sas_hba.sas_address, 0, i, ++ MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED, NULL); ++ } + out: + kfree(sas_iounit_pg0); + } +@@ -6654,7 +6706,10 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) + __FILE__, __LINE__, __func__); + return; + } +- ioc->sas_hba.phy = kcalloc(num_phys, ++ ++ ioc->sas_hba.nr_phys_allocated = max_t(u8, ++ MPT_MAX_HBA_NUM_PHYS, num_phys); ++ ioc->sas_hba.phy = kcalloc(ioc->sas_hba.nr_phys_allocated, + sizeof(struct _sas_phy), GFP_KERNEL); + if (!ioc->sas_hba.phy) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", +diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c +index 07f274afd7e5e..a4d244ee4548c 100644 +--- a/drivers/scsi/myrs.c ++++ b/drivers/scsi/myrs.c +@@ -2265,7 +2265,8 @@ static void myrs_cleanup(struct myrs_hba *cs) + myrs_unmap(cs); + + if (cs->mmio_base) { +- cs->disable_intr(cs); ++ if (cs->disable_intr) ++ cs->disable_intr(cs); + iounmap(cs->mmio_base); + cs->mmio_base = NULL; + } +diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c +index 63690508313b7..5e6b23da4157c 100644 +--- a/drivers/scsi/pm8001/pm8001_hwi.c ++++ b/drivers/scsi/pm8001/pm8001_hwi.c +@@ -1325,7 +1325,9 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, + int q_index = circularQ - pm8001_ha->inbnd_q_tbl; + int rv; + +- WARN_ON(q_index >= PM8001_MAX_INB_NUM); ++ if (WARN_ON(q_index >= pm8001_ha->max_q_num)) ++ return -EINVAL; ++ + spin_lock_irqsave(&circularQ->iq_lock, flags); + rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, + &pMessage); +@@ -2693,7 +2695,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + u32 tag = le32_to_cpu(psataPayload->tag); + u32 port_id = le32_to_cpu(psataPayload->port_id); + u32 dev_id = le32_to_cpu(psataPayload->device_id); +- unsigned long flags; + + ccb = &pm8001_ha->ccb_info[tag]; + +@@ -2733,8 +2734,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + ts->resp = SAS_TASK_COMPLETE; + ts->stat = SAS_DATA_OVERRUN; + ts->residual = 0; +- if (pm8001_dev) +- atomic_dec(&pm8001_dev->running_req); + break; + case IO_XFER_ERROR_BREAK: + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); +@@ -2776,7 +2775,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); + ts->resp = SAS_TASK_COMPLETE; + ts->stat = SAS_QUEUE_FULL; +- pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); + return; + } + break; +@@ -2862,20 +2860,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + ts->stat = SAS_OPEN_TO; + break; + } +- spin_lock_irqsave(&t->task_state_lock, flags); +- t->task_state_flags &= ~SAS_TASK_STATE_PENDING; +- t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; +- t->task_state_flags |= SAS_TASK_STATE_DONE; +- if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { +- spin_unlock_irqrestore(&t->task_state_lock, flags); +- pm8001_dbg(pm8001_ha, FAIL, +- "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", +- t, event, ts->resp, ts->stat); +- pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); +- } else { +- spin_unlock_irqrestore(&t->task_state_lock, flags); +- pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); +- } + } + + /*See the comments for mpi_ssp_completion */ +@@ -3169,7 +3153,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) + * fw_control_context->usrAddr + */ + complete(pm8001_ha->nvmd_completion); +- pm8001_dbg(pm8001_ha, MSG, "Set nvm data complete!\n"); ++ pm8001_dbg(pm8001_ha, MSG, "Get nvmd data complete!\n"); + ccb->task = NULL; + ccb->ccb_tag = 0xFFFFFFFF; + pm8001_tag_free(pm8001_ha, tag); +diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c +index 47db7e0beae6f..a25a34535b7a4 100644 +--- a/drivers/scsi/pm8001/pm8001_init.c ++++ b/drivers/scsi/pm8001/pm8001_init.c +@@ -281,12 +281,12 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, + if (rc) { + pm8001_dbg(pm8001_ha, FAIL, + "pm8001_setup_irq failed [ret: %d]\n", rc); +- goto err_out_shost; ++ goto err_out; + } + /* Request Interrupt */ + rc = pm8001_request_irq(pm8001_ha); + if (rc) +- goto err_out_shost; ++ goto err_out; + + count = pm8001_ha->max_q_num; + /* Queues are chosen based on the number of cores/msix availability */ +@@ -422,8 +422,6 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, + pm8001_tag_init(pm8001_ha); + return 0; + +-err_out_shost: +- scsi_remove_host(pm8001_ha->shost); + err_out_nodev: + for (i = 0; i < pm8001_ha->max_memcnt; i++) { + if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) { +@@ -1198,6 +1196,7 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost, + goto err_out; + + /* Memory region for ccb_info*/ ++ pm8001_ha->ccb_count = ccb_count; + pm8001_ha->ccb_info = + kcalloc(ccb_count, sizeof(struct pm8001_ccb_info), GFP_KERNEL); + if (!pm8001_ha->ccb_info) { +@@ -1259,6 +1258,16 @@ static void pm8001_pci_remove(struct pci_dev *pdev) + tasklet_kill(&pm8001_ha->tasklet[j]); + #endif + scsi_host_put(pm8001_ha->shost); ++ ++ for (i = 0; i < pm8001_ha->ccb_count; i++) { ++ dma_free_coherent(&pm8001_ha->pdev->dev, ++ sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG, ++ pm8001_ha->ccb_info[i].buf_prd, ++ pm8001_ha->ccb_info[i].ccb_dma_handle); ++ } ++ kfree(pm8001_ha->ccb_info); ++ kfree(pm8001_ha->devices); ++ + pm8001_free(pm8001_ha); + kfree(sha->sas_phy); + kfree(sha->sas_port); +diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c +index 32e60f0c3b148..491cecbbe1aa7 100644 +--- a/drivers/scsi/pm8001/pm8001_sas.c ++++ b/drivers/scsi/pm8001/pm8001_sas.c +@@ -753,8 +753,13 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, + res = -TMF_RESP_FUNC_FAILED; + /* Even TMF timed out, return direct. */ + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { ++ struct pm8001_ccb_info *ccb = task->lldd_task; ++ + pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n", + tmf->tmf); ++ ++ if (ccb) ++ ccb->task = NULL; + goto ex_err; + } + +diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h +index 62d08b535a4b6..f40a41f450d9b 100644 +--- a/drivers/scsi/pm8001/pm8001_sas.h ++++ b/drivers/scsi/pm8001/pm8001_sas.h +@@ -457,6 +457,7 @@ struct outbound_queue_table { + __le32 producer_index; + u32 consumer_idx; + spinlock_t oq_lock; ++ unsigned long lock_flags; + }; + struct pm8001_hba_memspace { + void __iomem *memvirtaddr; +@@ -516,6 +517,7 @@ struct pm8001_hba_info { + u32 iomb_size; /* SPC and SPCV IOMB size */ + struct pm8001_device *devices; + struct pm8001_ccb_info *ccb_info; ++ u32 ccb_count; + #ifdef PM8001_USE_MSIX + int number_of_intr;/*will be used in remove()*/ + char intr_drvname[PM8001_MAX_MSIX_VEC] +@@ -738,9 +740,7 @@ pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha, + { + pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb_idx); + smp_mb(); /*in order to force CPU ordering*/ +- spin_unlock(&pm8001_ha->lock); + task->task_done(task); +- spin_lock(&pm8001_ha->lock); + } + + #endif +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c +index 6ffe17b849ae8..3056f3615ab8a 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -2184,9 +2184,9 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); ++ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + if (t->slow_task) + complete(&t->slow_task->completion); +- pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + } else { + spin_unlock_irqrestore(&t->task_state_lock, flags); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); +@@ -2379,7 +2379,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + + /*See the comments for mpi_ssp_completion */ + static void +-mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ++mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, ++ struct outbound_queue_table *circularQ, void *piomb) + { + struct sas_task *t; + struct pm8001_ccb_info *ccb; +@@ -2616,7 +2617,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); + ts->resp = SAS_TASK_UNDELIVERED; + ts->stat = SAS_QUEUE_FULL; ++ spin_unlock_irqrestore(&circularQ->oq_lock, ++ circularQ->lock_flags); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); ++ spin_lock_irqsave(&circularQ->oq_lock, ++ circularQ->lock_flags); + return; + } + break; +@@ -2632,7 +2637,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); + ts->resp = SAS_TASK_UNDELIVERED; + ts->stat = SAS_QUEUE_FULL; ++ spin_unlock_irqrestore(&circularQ->oq_lock, ++ circularQ->lock_flags); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); ++ spin_lock_irqsave(&circularQ->oq_lock, ++ circularQ->lock_flags); + return; + } + break; +@@ -2656,7 +2665,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY); + ts->resp = SAS_TASK_UNDELIVERED; + ts->stat = SAS_QUEUE_FULL; ++ spin_unlock_irqrestore(&circularQ->oq_lock, ++ circularQ->lock_flags); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); ++ spin_lock_irqsave(&circularQ->oq_lock, ++ circularQ->lock_flags); + return; + } + break; +@@ -2727,7 +2740,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_DS_NON_OPERATIONAL); + ts->resp = SAS_TASK_UNDELIVERED; + ts->stat = SAS_QUEUE_FULL; ++ spin_unlock_irqrestore(&circularQ->oq_lock, ++ circularQ->lock_flags); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); ++ spin_lock_irqsave(&circularQ->oq_lock, ++ circularQ->lock_flags); + return; + } + break; +@@ -2747,7 +2764,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_DS_IN_ERROR); + ts->resp = SAS_TASK_UNDELIVERED; + ts->stat = SAS_QUEUE_FULL; ++ spin_unlock_irqrestore(&circularQ->oq_lock, ++ circularQ->lock_flags); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); ++ spin_lock_irqsave(&circularQ->oq_lock, ++ circularQ->lock_flags); + return; + } + break; +@@ -2780,17 +2801,22 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); ++ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + if (t->slow_task) + complete(&t->slow_task->completion); +- pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + } else { + spin_unlock_irqrestore(&t->task_state_lock, flags); ++ spin_unlock_irqrestore(&circularQ->oq_lock, ++ circularQ->lock_flags); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); ++ spin_lock_irqsave(&circularQ->oq_lock, ++ circularQ->lock_flags); + } + } + + /*See the comments for mpi_ssp_completion */ +-static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) ++static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, ++ struct outbound_queue_table *circularQ, void *piomb) + { + struct sas_task *t; + struct task_status_struct *ts; +@@ -2802,7 +2828,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + u32 tag = le32_to_cpu(psataPayload->tag); + u32 port_id = le32_to_cpu(psataPayload->port_id); + u32 dev_id = le32_to_cpu(psataPayload->device_id); +- unsigned long flags; + + ccb = &pm8001_ha->ccb_info[tag]; + +@@ -2840,8 +2865,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + ts->resp = SAS_TASK_COMPLETE; + ts->stat = SAS_DATA_OVERRUN; + ts->residual = 0; +- if (pm8001_dev) +- atomic_dec(&pm8001_dev->running_req); + break; + case IO_XFER_ERROR_BREAK: + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); +@@ -2890,7 +2913,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); + ts->resp = SAS_TASK_COMPLETE; + ts->stat = SAS_QUEUE_FULL; +- pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); + return; + } + break; +@@ -2990,20 +3012,6 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb) + ts->stat = SAS_OPEN_TO; + break; + } +- spin_lock_irqsave(&t->task_state_lock, flags); +- t->task_state_flags &= ~SAS_TASK_STATE_PENDING; +- t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; +- t->task_state_flags |= SAS_TASK_STATE_DONE; +- if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { +- spin_unlock_irqrestore(&t->task_state_lock, flags); +- pm8001_dbg(pm8001_ha, FAIL, +- "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", +- t, event, ts->resp, ts->stat); +- pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); +- } else { +- spin_unlock_irqrestore(&t->task_state_lock, flags); +- pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); +- } + } + + /*See the comments for mpi_ssp_completion */ +@@ -3902,7 +3910,8 @@ static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha, + * @pm8001_ha: our hba card information + * @piomb: IO message buffer + */ +-static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) ++static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, ++ struct outbound_queue_table *circularQ, void *piomb) + { + __le32 pHeader = *(__le32 *)piomb; + u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF); +@@ -3944,11 +3953,11 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) + break; + case OPC_OUB_SATA_COMP: + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n"); +- mpi_sata_completion(pm8001_ha, piomb); ++ mpi_sata_completion(pm8001_ha, circularQ, piomb); + break; + case OPC_OUB_SATA_EVENT: + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n"); +- mpi_sata_event(pm8001_ha, piomb); ++ mpi_sata_event(pm8001_ha, circularQ, piomb); + break; + case OPC_OUB_SSP_EVENT: + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n"); +@@ -4117,13 +4126,24 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) + void *pMsg1 = NULL; + u8 bc; + u32 ret = MPI_IO_STATUS_FAIL; +- unsigned long flags; + u32 regval; + ++ /* ++ * Fatal errors are programmed to be signalled in irq vector ++ * pm8001_ha->max_q_num - 1 through pm8001_ha->main_cfg_tbl.pm80xx_tbl. ++ * fatal_err_interrupt ++ */ + if (vec == (pm8001_ha->max_q_num - 1)) { ++ u32 mipsall_ready; ++ ++ if (pm8001_ha->chip_id == chip_8008 || ++ pm8001_ha->chip_id == chip_8009) ++ mipsall_ready = SCRATCH_PAD_MIPSALL_READY_8PORT; ++ else ++ mipsall_ready = SCRATCH_PAD_MIPSALL_READY_16PORT; ++ + regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); +- if ((regval & SCRATCH_PAD_MIPSALL_READY) != +- SCRATCH_PAD_MIPSALL_READY) { ++ if ((regval & mipsall_ready) != mipsall_ready) { + pm8001_ha->controller_fatal_error = true; + pm8001_dbg(pm8001_ha, FAIL, + "Firmware Fatal error! Regval:0x%x\n", +@@ -4134,7 +4154,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) + } + } + circularQ = &pm8001_ha->outbnd_q_tbl[vec]; +- spin_lock_irqsave(&circularQ->oq_lock, flags); ++ spin_lock_irqsave(&circularQ->oq_lock, circularQ->lock_flags); + do { + /* spurious interrupt during setup if kexec-ing and + * driver doing a doorbell access w/ the pre-kexec oq +@@ -4145,7 +4165,8 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) + ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); + if (MPI_IO_STATUS_SUCCESS == ret) { + /* process the outbound message */ +- process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4)); ++ process_one_iomb(pm8001_ha, circularQ, ++ (void *)(pMsg1 - 4)); + /* free the message from the outbound circular buffer */ + pm8001_mpi_msg_free_set(pm8001_ha, pMsg1, + circularQ, bc); +@@ -4160,7 +4181,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) + break; + } + } while (1); +- spin_unlock_irqrestore(&circularQ->oq_lock, flags); ++ spin_unlock_irqrestore(&circularQ->oq_lock, circularQ->lock_flags); + return ret; + } + +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h +index c7e5d93bea924..c41ed039c92ac 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.h ++++ b/drivers/scsi/pm8001/pm80xx_hwi.h +@@ -1405,8 +1405,12 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; + #define SCRATCH_PAD_BOOT_LOAD_SUCCESS 0x0 + #define SCRATCH_PAD_IOP0_READY 0xC00 + #define SCRATCH_PAD_IOP1_READY 0x3000 +-#define SCRATCH_PAD_MIPSALL_READY (SCRATCH_PAD_IOP1_READY | \ ++#define SCRATCH_PAD_MIPSALL_READY_16PORT (SCRATCH_PAD_IOP1_READY | \ + SCRATCH_PAD_IOP0_READY | \ ++ SCRATCH_PAD_ILA_READY | \ ++ SCRATCH_PAD_RAAE_READY) ++#define SCRATCH_PAD_MIPSALL_READY_8PORT (SCRATCH_PAD_IOP0_READY | \ ++ SCRATCH_PAD_ILA_READY | \ + SCRATCH_PAD_RAAE_READY) + + /* boot loader state */ +diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c +index 3404782988d58..bb5761ed3f511 100644 +--- a/drivers/scsi/qedf/qedf_io.c ++++ b/drivers/scsi/qedf/qedf_io.c +@@ -2257,6 +2257,7 @@ process_els: + io_req->tm_flags == FCP_TMF_TGT_RESET) { + clear_bit(QEDF_CMD_OUTSTANDING, &io_req->flags); + io_req->sc_cmd = NULL; ++ kref_put(&io_req->refcount, qedf_release_cmd); + complete(&io_req->tm_done); + } + +diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c +index 42d0d941dba5c..544401f76c079 100644 +--- a/drivers/scsi/qedf/qedf_main.c ++++ b/drivers/scsi/qedf/qedf_main.c +@@ -911,7 +911,7 @@ void qedf_ctx_soft_reset(struct fc_lport *lport) + struct qed_link_output if_link; + + if (lport->vport) { +- QEDF_ERR(NULL, "Cannot issue host reset on NPIV port.\n"); ++ printk_ratelimited("Cannot issue host reset on NPIV port.\n"); + return; + } + +@@ -1862,6 +1862,7 @@ static int qedf_vport_create(struct fc_vport *vport, bool disabled) + vport_qedf->cmd_mgr = base_qedf->cmd_mgr; + init_completion(&vport_qedf->flogi_compl); + INIT_LIST_HEAD(&vport_qedf->fcports); ++ INIT_DELAYED_WORK(&vport_qedf->stag_work, qedf_stag_change_work); + + rc = qedf_vport_libfc_config(vport, vn_port); + if (rc) { +@@ -3416,7 +3417,9 @@ retry_probe: + qedf->devlink = qed_ops->common->devlink_register(qedf->cdev); + if (IS_ERR(qedf->devlink)) { + QEDF_ERR(&qedf->dbg_ctx, "Cannot register devlink\n"); ++ rc = PTR_ERR(qedf->devlink); + qedf->devlink = NULL; ++ goto err2; + } + } + +@@ -3976,7 +3979,9 @@ void qedf_stag_change_work(struct work_struct *work) + struct qedf_ctx *qedf = + container_of(work, struct qedf_ctx, stag_work.work); + +- QEDF_ERR(&qedf->dbg_ctx, "Performing software context reset.\n"); ++ printk_ratelimited("[%s]:[%s:%d]:%d: Performing software context reset.", ++ dev_name(&qedf->pdev->dev), __func__, __LINE__, ++ qedf->dbg_ctx.host_no); + qedf_ctx_soft_reset(qedf->lport); + } + +diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c +index d01cd829ef975..df9ce6ed52bf9 100644 +--- a/drivers/scsi/qedi/qedi_fw.c ++++ b/drivers/scsi/qedi/qedi_fw.c +@@ -772,11 +772,10 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, + qedi_cmd->list_tmf_work = NULL; + } + } ++ spin_unlock_bh(&qedi_conn->tmf_work_lock); + +- if (!found) { +- spin_unlock_bh(&qedi_conn->tmf_work_lock); ++ if (!found) + goto check_cleanup_reqs; +- } + + QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_SCSI_TM, + "TMF work, cqe->tid=0x%x, tmf flags=0x%x, cid=0x%x\n", +@@ -807,7 +806,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, + qedi_cmd->state = CLEANUP_RECV; + unlock: + spin_unlock_bh(&conn->session->back_lock); +- spin_unlock_bh(&qedi_conn->tmf_work_lock); + wake_up_interruptible(&qedi_conn->wait_queue); + return; + +diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c +index d09776b77af2e..cb5f2ecb652d3 100644 +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -1868,6 +1868,18 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, + return strlen(buf); + } + ++static const struct { ++ u16 rate; ++ char *str; ++} port_speed_str[] = { ++ { PORT_SPEED_4GB, "4" }, ++ { PORT_SPEED_8GB, "8" }, ++ { PORT_SPEED_16GB, "16" }, ++ { PORT_SPEED_32GB, "32" }, ++ { PORT_SPEED_64GB, "64" }, ++ { PORT_SPEED_10GB, "10" }, ++}; ++ + static ssize_t + qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, + char *buf) +@@ -1875,7 +1887,8 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, + struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; + ssize_t rval; +- char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"}; ++ u16 i; ++ char *speed = "Unknown"; + + rval = qla2x00_get_data_rate(vha); + if (rval != QLA_SUCCESS) { +@@ -1884,7 +1897,14 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, + return -EINVAL; + } + +- return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]); ++ for (i = 0; i < ARRAY_SIZE(port_speed_str); i++) { ++ if (port_speed_str[i].rate != ha->link_data_rate) ++ continue; ++ speed = port_speed_str[i].str; ++ break; ++ } ++ ++ return scnprintf(buf, PAGE_SIZE, "%s\n", speed); + } + + static ssize_t +diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c +index 25549a8a2d72d..7cf1f78cbaeee 100644 +--- a/drivers/scsi/qla2xxx/qla_dbg.c ++++ b/drivers/scsi/qla2xxx/qla_dbg.c +@@ -2491,6 +2491,9 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) + struct va_format vaf; + char pbuf[64]; + ++ if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled()) ++ return; ++ + va_start(va, fmt); + + vaf.fmt = fmt; +diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c +index ad746c62f0d44..a04693498dc01 100644 +--- a/drivers/scsi/qla2xxx/qla_edif.c ++++ b/drivers/scsi/qla2xxx/qla_edif.c +@@ -290,63 +290,6 @@ qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid) + return false; + } + +-static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state, +- int waitonly) +-{ +- int cnt, max_cnt = 200; +- bool traced = false; +- +- fcport->keep_nport_handle = 1; +- +- if (!waitonly) { +- qla2x00_set_fcport_disc_state(fcport, state); +- qlt_schedule_sess_for_deletion(fcport); +- } else { +- qla2x00_set_fcport_disc_state(fcport, state); +- } +- +- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, +- "%s: waiting for session, max_cnt=%u\n", +- __func__, max_cnt); +- +- cnt = 0; +- +- if (waitonly) { +- /* Marker wait min 10 msecs. */ +- msleep(50); +- cnt += 50; +- } +- while (1) { +- if (!traced) { +- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, +- "%s: session sleep.\n", +- __func__); +- traced = true; +- } +- msleep(20); +- cnt++; +- if (waitonly && (fcport->disc_state == state || +- fcport->disc_state == DSC_LOGIN_COMPLETE)) +- break; +- if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) +- break; +- if (cnt > max_cnt) +- break; +- } +- +- if (!waitonly) { +- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, +- "%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n", +- __func__, fcport->port_name, fcport->loop_id, +- fcport->d_id.b24, fcport, fcport->disc_state, cnt); +- } else { +- ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, +- "%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n", +- __func__, fcport->port_name, fcport->loop_id, +- fcport->d_id.b24, fcport, fcport->disc_state, cnt); +- } +-} +- + static void + qla_edif_free_sa_ctl(fc_port_t *fcport, struct edif_sa_ctl *sa_ctl, + int index) +@@ -529,7 +472,8 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + struct app_start_reply appreply; + struct fc_port *fcport, *tf; + +- ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__); ++ ql_log(ql_log_info, vha, 0x1313, ++ "EDIF application registration with driver, FC device connections will be re-established.\n"); + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, &appstart, +@@ -554,37 +498,36 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + qla2xxx_wake_dpc(vha); + } else { + list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { ++ ql_dbg(ql_dbg_edif, vha, 0x2058, ++ "FCSP - nn %8phN pn %8phN portid=%06x.\n", ++ fcport->node_name, fcport->port_name, ++ fcport->d_id.b24); + ql_dbg(ql_dbg_edif, vha, 0xf084, +- "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n", +- __func__, fcport, fcport->port_name, +- fcport->loop_id, fcport->d_id.b24, +- fcport->logout_on_delete); +- +- ql_dbg(ql_dbg_edif, vha, 0xf084, +- "keep %d els_logo %d disc state %d auth state %d stop state %d\n", +- fcport->keep_nport_handle, +- fcport->send_els_logo, fcport->disc_state, +- fcport->edif.auth_state, fcport->edif.app_stop); ++ "%s: se_sess %p / sess %p from port %8phC " ++ "loop_id %#04x s_id %06x logout %d " ++ "keep %d els_logo %d disc state %d auth state %d" ++ "stop state %d\n", ++ __func__, fcport->se_sess, fcport, ++ fcport->port_name, fcport->loop_id, ++ fcport->d_id.b24, fcport->logout_on_delete, ++ fcport->keep_nport_handle, fcport->send_els_logo, ++ fcport->disc_state, fcport->edif.auth_state, ++ fcport->edif.app_stop); + + if (atomic_read(&vha->loop_state) == LOOP_DOWN) + break; +- if (!(fcport->flags & FCF_FCSP_DEVICE)) +- continue; + + fcport->edif.app_started = 1; +- if (fcport->edif.app_stop || +- (fcport->disc_state != DSC_LOGIN_COMPLETE && +- fcport->disc_state != DSC_LOGIN_PEND && +- fcport->disc_state != DSC_DELETED)) { +- /* no activity */ +- fcport->edif.app_stop = 0; +- +- ql_dbg(ql_dbg_edif, vha, 0x911e, +- "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", +- __func__, fcport->port_name); +- fcport->edif.app_sess_online = 1; +- qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); +- } ++ fcport->login_retry = vha->hw->login_retry_count; ++ ++ /* no activity */ ++ fcport->edif.app_stop = 0; ++ ++ ql_dbg(ql_dbg_edif, vha, 0x911e, ++ "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", ++ __func__, fcport->port_name); ++ fcport->edif.app_sess_online = 0; ++ qlt_schedule_sess_for_deletion(fcport); + qla_edif_sa_ctl_init(vha, fcport); + } + } +@@ -601,14 +544,14 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + appreply.edif_enode_active = vha->pur_cinfo.enode_flags; + appreply.edif_edb_active = vha->e_dbell.db_flags; + +- bsg_job->reply_len = sizeof(struct fc_bsg_reply) + +- sizeof(struct app_start_reply); ++ bsg_job->reply_len = sizeof(struct fc_bsg_reply); + + SET_DID_STATUS(bsg_reply->result, DID_OK); + +- sg_copy_from_buffer(bsg_job->reply_payload.sg_list, +- bsg_job->reply_payload.sg_cnt, &appreply, +- sizeof(struct app_start_reply)); ++ bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, ++ bsg_job->reply_payload.sg_cnt, ++ &appreply, ++ sizeof(struct app_start_reply)); + + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s app start completed with 0x%x\n", +@@ -800,15 +743,15 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s AUTH complete - RESUME with prli for wwpn %8phC\n", + __func__, fcport->port_name); +- qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 1); + qla24xx_post_prli_work(vha, fcport); + } + + errstate_exit: + bsg_job->reply_len = sizeof(struct fc_bsg_reply); +- sg_copy_from_buffer(bsg_job->reply_payload.sg_list, +- bsg_job->reply_payload.sg_cnt, &appplogireply, +- sizeof(struct app_plogi_reply)); ++ bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, ++ bsg_job->reply_payload.sg_cnt, ++ &appplogireply, ++ sizeof(struct app_plogi_reply)); + + return rval; + } +@@ -873,7 +816,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + + if (qla_ini_mode_enabled(fcport->vha)) { + fcport->send_els_logo = 1; +- qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); ++ qlt_schedule_sess_for_deletion(fcport); + } + } + +@@ -891,7 +834,7 @@ static int + qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + { + int32_t rval = 0; +- int32_t num_cnt; ++ int32_t pcnt = 0; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + struct app_pinfo_req app_req; + struct app_pinfo_reply *app_reply; +@@ -903,16 +846,14 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + bsg_job->request_payload.sg_cnt, &app_req, + sizeof(struct app_pinfo_req)); + +- num_cnt = app_req.num_ports; /* num of ports alloc'd by app */ +- + app_reply = kzalloc((sizeof(struct app_pinfo_reply) + +- sizeof(struct app_pinfo) * num_cnt), GFP_KERNEL); ++ sizeof(struct app_pinfo) * app_req.num_ports), GFP_KERNEL); ++ + if (!app_reply) { + SET_DID_STATUS(bsg_reply->result, DID_ERROR); + rval = -1; + } else { + struct fc_port *fcport = NULL, *tf; +- uint32_t pcnt = 0; + + list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { + if (!(fcport->flags & FCF_FCSP_DEVICE)) +@@ -924,7 +865,7 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + "APP request entry - portid=%06x.\n", tdid.b24); + + /* Ran out of space */ +- if (pcnt > app_req.num_ports) ++ if (pcnt >= app_req.num_ports) + break; + + if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24) +@@ -981,9 +922,11 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + SET_DID_STATUS(bsg_reply->result, DID_OK); + } + +- sg_copy_from_buffer(bsg_job->reply_payload.sg_list, +- bsg_job->reply_payload.sg_cnt, app_reply, +- sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * num_cnt); ++ bsg_job->reply_len = sizeof(struct fc_bsg_reply); ++ bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, ++ bsg_job->reply_payload.sg_cnt, ++ app_reply, ++ sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * pcnt); + + kfree(app_reply); + +@@ -1000,10 +943,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + { + int32_t rval = 0; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; +- uint32_t ret_size, size; ++ uint32_t size; + + struct app_sinfo_req app_req; + struct app_stats_reply *app_reply; ++ uint32_t pcnt = 0; + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, &app_req, +@@ -1019,18 +963,12 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + size = sizeof(struct app_stats_reply) + + (sizeof(struct app_sinfo) * app_req.num_ports); + +- if (size > bsg_job->reply_payload.payload_len) +- ret_size = bsg_job->reply_payload.payload_len; +- else +- ret_size = size; +- + app_reply = kzalloc(size, GFP_KERNEL); + if (!app_reply) { + SET_DID_STATUS(bsg_reply->result, DID_ERROR); + rval = -1; + } else { + struct fc_port *fcport = NULL, *tf; +- uint32_t pcnt = 0; + + list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { + if (fcport->edif.enable) { +@@ -1054,9 +992,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) + SET_DID_STATUS(bsg_reply->result, DID_OK); + } + ++ bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_reply->reply_payload_rcv_len = + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, +- bsg_job->reply_payload.sg_cnt, app_reply, ret_size); ++ bsg_job->reply_payload.sg_cnt, app_reply, ++ sizeof(struct app_stats_reply) + (sizeof(struct app_sinfo) * pcnt)); + + kfree(app_reply); + +@@ -1130,8 +1070,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) + __func__, + bsg_request->rqst_data.h_vendor.vendor_cmd[1]); + rval = EXT_STATUS_INVALID_PARAM; +- bsg_job->reply_len = sizeof(struct fc_bsg_reply); +- SET_DID_STATUS(bsg_reply->result, DID_ERROR); ++ done = false; + break; + } + +@@ -1651,6 +1590,40 @@ qla_enode_stop(scsi_qla_host_t *vha) + spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags); + } + ++static void qla_enode_clear(scsi_qla_host_t *vha, port_id_t portid) ++{ ++ unsigned long flags; ++ struct enode *e, *tmp; ++ struct purexevent *purex; ++ LIST_HEAD(enode_list); ++ ++ if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) { ++ ql_dbg(ql_dbg_edif, vha, 0x09102, ++ "%s enode not active\n", __func__); ++ return; ++ } ++ spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags); ++ list_for_each_entry_safe(e, tmp, &vha->pur_cinfo.head, list) { ++ purex = &e->u.purexinfo; ++ if (purex->pur_info.pur_sid.b24 == portid.b24) { ++ ql_dbg(ql_dbg_edif, vha, 0x911d, ++ "%s free ELS sid=%06x. xchg %x, nb=%xh\n", ++ __func__, portid.b24, ++ purex->pur_info.pur_rx_xchg_address, ++ purex->pur_info.pur_bytes_rcvd); ++ ++ list_del_init(&e->list); ++ list_add_tail(&e->list, &enode_list); ++ } ++ } ++ spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags); ++ ++ list_for_each_entry_safe(e, tmp, &enode_list, list) { ++ list_del_init(&e->list); ++ qla_enode_free(vha, e); ++ } ++} ++ + /* + * allocate enode struct and populate buffer + * returns: enode pointer with buffers +@@ -1850,6 +1823,57 @@ qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node) + node->ntype = N_UNDEF; + } + ++static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid) ++{ ++ unsigned long flags; ++ struct edb_node *e, *tmp; ++ port_id_t sid; ++ LIST_HEAD(edb_list); ++ ++ if (vha->e_dbell.db_flags != EDB_ACTIVE) { ++ /* doorbell list not enabled */ ++ ql_dbg(ql_dbg_edif, vha, 0x09102, ++ "%s doorbell not enabled\n", __func__); ++ return; ++ } ++ ++ /* grab lock so list doesn't move */ ++ spin_lock_irqsave(&vha->e_dbell.db_lock, flags); ++ list_for_each_entry_safe(e, tmp, &vha->e_dbell.head, list) { ++ switch (e->ntype) { ++ case VND_CMD_AUTH_STATE_NEEDED: ++ case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN: ++ sid = e->u.plogi_did; ++ break; ++ case VND_CMD_AUTH_STATE_ELS_RCVD: ++ sid = e->u.els_sid; ++ break; ++ case VND_CMD_AUTH_STATE_SAUPDATE_COMPL: ++ /* app wants to see this */ ++ continue; ++ default: ++ ql_log(ql_log_warn, vha, 0x09102, ++ "%s unknown node type: %x\n", __func__, e->ntype); ++ sid.b24 = 0; ++ break; ++ } ++ if (sid.b24 == portid.b24) { ++ ql_dbg(ql_dbg_edif, vha, 0x910f, ++ "%s free doorbell event : node type = %x %p\n", ++ __func__, e->ntype, e); ++ list_del_init(&e->list); ++ list_add_tail(&e->list, &edb_list); ++ } ++ } ++ spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags); ++ ++ list_for_each_entry_safe(e, tmp, &edb_list, list) { ++ qla_edb_node_free(vha, e); ++ list_del_init(&e->list); ++ kfree(e); ++ } ++} ++ + /* function called when app is stopping */ + + void +@@ -2357,7 +2381,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) + return; + } + +- if (totlen > MAX_PAYLOAD) { ++ if (totlen > ELS_MAX_PAYLOAD) { + ql_dbg(ql_dbg_edif, vha, 0x0910d, + "%s WARNING: verbose ELS frame received (totlen=%x)\n", + __func__, totlen); +@@ -2436,7 +2460,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) + ql_dbg(ql_dbg_edif, host, 0x0910c, + "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n", + __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24, +- purex->pur_info.pur_did.b24, p->rx_xchg_addr); ++ purex->pur_info.pur_did.b24, purex->pur_info.pur_rx_xchg_address); + + qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL); + } +@@ -3459,3 +3483,12 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess) + qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24); + } + } ++ ++void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport) ++{ ++ if (!(fcport->flags & FCF_FCSP_DEVICE)) ++ return; ++ ++ qla_edb_clear(vha, fcport->d_id); ++ qla_enode_clear(vha, fcport->d_id); ++} +diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h +index 9e8f28d0caa1b..45cf87e337780 100644 +--- a/drivers/scsi/qla2xxx/qla_edif.h ++++ b/drivers/scsi/qla2xxx/qla_edif.h +@@ -93,7 +93,6 @@ struct sa_update_28xx { + }; + + #define NUM_ENTRIES 256 +-#define MAX_PAYLOAD 1024 + #define PUR_GET 1 + + struct dinfo { +@@ -128,6 +127,8 @@ struct enode { + } u; + }; + ++#define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES)) ++ + #define EDIF_SESSION_DOWN(_s) \ + (qla_ini_mode_enabled(_s->vha) && (_s->disc_state == DSC_DELETE_PEND || \ + _s->disc_state == DSC_DELETED || \ +diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h +index 58b718d35d19a..53026d82ebffe 100644 +--- a/drivers/scsi/qla2xxx/qla_edif_bsg.h ++++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h +@@ -8,7 +8,7 @@ + #define __QLA_EDIF_BSG_H + + /* BSG Vendor specific commands */ +-#define ELS_MAX_PAYLOAD 1024 ++#define ELS_MAX_PAYLOAD 2112 + #ifndef WWN_SIZE + #define WWN_SIZE 8 + #endif +diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h +index 1c3f055d41b8e..2c7e91bffb827 100644 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -142,6 +142,8 @@ void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport, + void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport); + int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsgjob); + void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess); ++void qla_edif_clear_appdata(struct scsi_qla_host *vha, ++ struct fc_port *fcport); + const char *sc_to_str(uint16_t cmd); + + /* +@@ -171,7 +173,6 @@ extern int ql2xasynctmfenable; + extern int ql2xgffidenable; + extern int ql2xenabledif; + extern int ql2xenablehba_err_chk; +-extern int ql2xtargetreset; + extern int ql2xdontresethba; + extern uint64_t ql2xmaxlun; + extern int ql2xmdcapmask; +@@ -816,7 +817,6 @@ extern void qlafx00_abort_iocb(srb_t *, struct abort_iocb_entry_fx00 *); + extern void qlafx00_fxdisc_iocb(srb_t *, struct fxdisc_entry_fx00 *); + extern void qlafx00_timer_routine(scsi_qla_host_t *); + extern int qlafx00_rescan_isp(scsi_qla_host_t *); +-extern int qlafx00_loop_reset(scsi_qla_host_t *vha); + + /* qla82xx related functions */ + +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 5fc7697f0af4c..847a6e5d9cb07 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -987,8 +987,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) + sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1], + sp->u.iocb_cmd.u.mbx.in_mb[2]); + +- if (res == QLA_FUNCTION_TIMEOUT) +- return; + + sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE); + memset(&ea, 0, sizeof(ea)); +@@ -1026,8 +1024,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + + list_for_each_entry_safe(fcport, tf, &h, gnl_entry) { +- list_del_init(&fcport->gnl_entry); + spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); ++ list_del_init(&fcport->gnl_entry); + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + ea.fcport = fcport; +@@ -1786,16 +1784,52 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) + fc_port_t *fcport; + unsigned long flags; + +- fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); +- if (fcport) { +- if (fcport->flags & FCF_FCP2_DEVICE) { +- ql_dbg(ql_dbg_disc, vha, 0x2115, +- "Delaying session delete for FCP2 portid=%06x %8phC ", +- fcport->d_id.b24, fcport->port_name); +- return; ++ switch (ea->id.b.rsvd_1) { ++ case RSCN_PORT_ADDR: ++ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); ++ if (fcport) { ++ if (fcport->flags & FCF_FCP2_DEVICE) { ++ ql_dbg(ql_dbg_disc, vha, 0x2115, ++ "Delaying session delete for FCP2 portid=%06x %8phC ", ++ fcport->d_id.b24, fcport->port_name); ++ return; ++ } ++ fcport->scan_needed = 1; ++ fcport->rscn_gen++; + } +- fcport->scan_needed = 1; +- fcport->rscn_gen++; ++ break; ++ case RSCN_AREA_ADDR: ++ list_for_each_entry(fcport, &vha->vp_fcports, list) { ++ if (fcport->flags & FCF_FCP2_DEVICE) ++ continue; ++ ++ if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) { ++ fcport->scan_needed = 1; ++ fcport->rscn_gen++; ++ } ++ } ++ break; ++ case RSCN_DOM_ADDR: ++ list_for_each_entry(fcport, &vha->vp_fcports, list) { ++ if (fcport->flags & FCF_FCP2_DEVICE) ++ continue; ++ ++ if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) { ++ fcport->scan_needed = 1; ++ fcport->rscn_gen++; ++ } ++ } ++ break; ++ case RSCN_FAB_ADDR: ++ default: ++ list_for_each_entry(fcport, &vha->vp_fcports, list) { ++ if (fcport->flags & FCF_FCP2_DEVICE) ++ continue; ++ ++ fcport->scan_needed = 1; ++ fcport->rscn_gen++; ++ } ++ break; + } + + spin_lock_irqsave(&vha->work_lock, flags); +@@ -4433,6 +4467,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha) + (ha->flags.fawwpn_enabled) ? "enabled" : "disabled"); + } + ++ /* ELS pass through payload is limit by frame size. */ ++ if (ha->flags.edif_enabled) ++ mid_init_cb->init_cb.frame_payload_size = cpu_to_le16(ELS_MAX_PAYLOAD); ++ + rval = qla2x00_init_firmware(vha, ha->init_cb_size); + next_check: + if (rval) { +@@ -5335,15 +5373,14 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) + "LOOP READY.\n"); + ha->flags.fw_init_done = 1; + ++ /* ++ * use link up to wake up app to get ready for ++ * authentication. ++ */ + if (ha->flags.edif_enabled && +- !(vha->e_dbell.db_flags & EDB_ACTIVE) && +- N2N_TOPO(vha->hw)) { +- /* +- * use port online to wake up app to get ready +- * for authentication +- */ +- qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE, 0); +- } ++ !(vha->e_dbell.db_flags & EDB_ACTIVE)) ++ qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ++ ha->link_data_rate); + + /* + * Process any ATIO queue entries that came in +diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c +index 7811c4952035b..a6debeea30798 100644 +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -1695,10 +1695,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, + mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; + if (IS_FWI2_CAPABLE(vha->hw)) + mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; +- if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { +- mcp->in_mb |= MBX_15; +- mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23; +- } ++ if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) ++ mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23; + + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; +diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c +index 6e920da64863e..350b0c4346fb6 100644 +--- a/drivers/scsi/qla2xxx/qla_mr.c ++++ b/drivers/scsi/qla2xxx/qla_mr.c +@@ -738,29 +738,6 @@ qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag) + return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); + } + +-int +-qlafx00_loop_reset(scsi_qla_host_t *vha) +-{ +- int ret; +- struct fc_port *fcport; +- struct qla_hw_data *ha = vha->hw; +- +- if (ql2xtargetreset) { +- list_for_each_entry(fcport, &vha->vp_fcports, list) { +- if (fcport->port_type != FCT_TARGET) +- continue; +- +- ret = ha->isp_ops->target_reset(fcport, 0, 0); +- if (ret != QLA_SUCCESS) { +- ql_dbg(ql_dbg_taskm, vha, 0x803d, +- "Bus Reset failed: Reset=%d " +- "d_id=%x.\n", ret, fcport->d_id.b24); +- } +- } +- } +- return QLA_SUCCESS; +-} +- + int + qlafx00_iospace_config(struct qla_hw_data *ha) + { +diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c +index 1c5da2dbd6f97..877b2b6250204 100644 +--- a/drivers/scsi/qla2xxx/qla_nvme.c ++++ b/drivers/scsi/qla2xxx/qla_nvme.c +@@ -228,6 +228,8 @@ static void qla_nvme_abort_work(struct work_struct *work) + fc_port_t *fcport = sp->fcport; + struct qla_hw_data *ha = fcport->vha->hw; + int rval, abts_done_called = 1; ++ bool io_wait_for_abort_done; ++ uint32_t handle; + + ql_dbg(ql_dbg_io, fcport->vha, 0xffff, + "%s called for sp=%p, hndl=%x on fcport=%p desc=%p deleted=%d\n", +@@ -244,12 +246,20 @@ static void qla_nvme_abort_work(struct work_struct *work) + goto out; + } + ++ /* ++ * sp may not be valid after abort_command if return code is either ++ * SUCCESS or ERR_FROM_FW codes, so cache the value here. ++ */ ++ io_wait_for_abort_done = ql2xabts_wait_nvme && ++ QLA_ABTS_WAIT_ENABLED(sp); ++ handle = sp->handle; ++ + rval = ha->isp_ops->abort_command(sp); + + ql_dbg(ql_dbg_io, fcport->vha, 0x212b, + "%s: %s command for sp=%p, handle=%x on fcport=%p rval=%x\n", + __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", +- sp, sp->handle, fcport, rval); ++ sp, handle, fcport, rval); + + /* + * If async tmf is enabled, the abort callback is called only on +@@ -264,7 +274,7 @@ static void qla_nvme_abort_work(struct work_struct *work) + * are waited until ABTS complete. This kref is decreased + * at qla24xx_abort_sp_done function. + */ +- if (abts_done_called && ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp)) ++ if (abts_done_called && io_wait_for_abort_done) + return; + out: + /* kref_get was done before work was schedule. */ +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 836fedcea241b..8d87cfae9c598 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -202,12 +202,6 @@ MODULE_PARM_DESC(ql2xdbwr, + " 0 -- Regular doorbell.\n" + " 1 -- CAMRAM doorbell (faster).\n"); + +-int ql2xtargetreset = 1; +-module_param(ql2xtargetreset, int, S_IRUGO); +-MODULE_PARM_DESC(ql2xtargetreset, +- "Enable target reset." +- "Default is 1 - use hw defaults."); +- + int ql2xgffidenable; + module_param(ql2xgffidenable, int, S_IRUGO); + MODULE_PARM_DESC(ql2xgffidenable, +@@ -1258,6 +1252,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) + uint32_t ratov_j; + struct qla_qpair *qpair; + unsigned long flags; ++ int fast_fail_status = SUCCESS; + + if (qla2x00_isp_reg_stat(ha)) { + ql_log(ql_log_info, vha, 0x8042, +@@ -1266,9 +1261,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) + return FAILED; + } + ++ /* Save any FAST_IO_FAIL value to return later if abort succeeds */ + ret = fc_block_scsi_eh(cmd); + if (ret != 0) +- return ret; ++ fast_fail_status = ret; + + sp = scsi_cmd_priv(cmd); + qpair = sp->qpair; +@@ -1276,7 +1272,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) + vha->cmd_timeout_cnt++; + + if ((sp->fcport && sp->fcport->deleted) || !qpair) +- return SUCCESS; ++ return fast_fail_status != SUCCESS ? fast_fail_status : FAILED; + + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + sp->comp = ∁ +@@ -1311,7 +1307,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) + __func__, ha->r_a_tov/10); + ret = FAILED; + } else { +- ret = SUCCESS; ++ ret = fast_fail_status; + } + break; + default: +@@ -1693,27 +1689,10 @@ int + qla2x00_loop_reset(scsi_qla_host_t *vha) + { + int ret; +- struct fc_port *fcport; + struct qla_hw_data *ha = vha->hw; + +- if (IS_QLAFX00(ha)) { +- return qlafx00_loop_reset(vha); +- } +- +- if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) { +- list_for_each_entry(fcport, &vha->vp_fcports, list) { +- if (fcport->port_type != FCT_TARGET) +- continue; +- +- ret = ha->isp_ops->target_reset(fcport, 0, 0); +- if (ret != QLA_SUCCESS) { +- ql_dbg(ql_dbg_taskm, vha, 0x802c, +- "Bus Reset failed: Reset=%d " +- "d_id=%x.\n", ret, fcport->d_id.b24); +- } +- } +- } +- ++ if (IS_QLAFX00(ha)) ++ return QLA_SUCCESS; + + if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) { + atomic_set(&vha->loop_state, LOOP_DOWN); +@@ -4358,7 +4337,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, + + /* allocate the purex dma pool */ + ha->purex_dma_pool = dma_pool_create(name, &ha->pdev->dev, +- MAX_PAYLOAD, 8, 0); ++ ELS_MAX_PAYLOAD, 8, 0); + + if (!ha->purex_dma_pool) { + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, +diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c +index 7d8242c120fc7..1aaa4238cb722 100644 +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1003,6 +1003,7 @@ void qlt_free_session_done(struct work_struct *work) + "%s bypassing release_all_sadb\n", + __func__); + } ++ qla_edif_clear_appdata(vha, sess); + qla_edif_sess_down(vha, sess); + } + qla2x00_mark_device_lost(vha, sess, 0); +diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c +index 291ecc33b1fe6..4fc9466d820a7 100644 +--- a/drivers/scsi/scsi.c ++++ b/drivers/scsi/scsi.c +@@ -209,11 +209,11 @@ void scsi_finish_command(struct scsi_cmnd *cmd) + + + /* +- * 1024 is big enough for saturating the fast scsi LUN now ++ * 1024 is big enough for saturating fast SCSI LUNs. + */ + int scsi_device_max_queue_depth(struct scsi_device *sdev) + { +- return max_t(int, sdev->host->can_queue, 1024); ++ return min_t(int, sdev->host->can_queue, 1024); + } + + /** +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 66f507469a31a..cfeadd5f61f18 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -1189,7 +1189,7 @@ static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr, + __func__, off_dst, scsi_bufflen(scp), act_len, + scsi_get_resid(scp)); + n = scsi_bufflen(scp) - (off_dst + act_len); +- scsi_set_resid(scp, min_t(int, scsi_get_resid(scp), n)); ++ scsi_set_resid(scp, min_t(u32, scsi_get_resid(scp), n)); + return 0; + } + +@@ -1562,7 +1562,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + unsigned char pq_pdt; + unsigned char *arr; + unsigned char *cmd = scp->cmnd; +- int alloc_len, n, ret; ++ u32 alloc_len, n; ++ int ret; + bool have_wlun, is_disk, is_zbc, is_disk_zbc; + + alloc_len = get_unaligned_be16(cmd + 3); +@@ -1585,7 +1586,8 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + kfree(arr); + return check_condition_result; + } else if (0x1 & cmd[1]) { /* EVPD bit set */ +- int lu_id_num, port_group_id, target_dev_id, len; ++ int lu_id_num, port_group_id, target_dev_id; ++ u32 len; + char lu_id_str[6]; + int host_no = devip->sdbg_host->shost->host_no; + +@@ -1676,9 +1678,9 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + kfree(arr); + return check_condition_result; + } +- len = min(get_unaligned_be16(arr + 2) + 4, alloc_len); ++ len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len); + ret = fill_from_dev_buffer(scp, arr, +- min(len, SDEBUG_MAX_INQ_ARR_SZ)); ++ min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); + kfree(arr); + return ret; + } +@@ -1714,7 +1716,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + } + put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */ + ret = fill_from_dev_buffer(scp, arr, +- min_t(int, alloc_len, SDEBUG_LONG_INQ_SZ)); ++ min_t(u32, alloc_len, SDEBUG_LONG_INQ_SZ)); + kfree(arr); + return ret; + } +@@ -1729,8 +1731,8 @@ static int resp_requests(struct scsi_cmnd *scp, + unsigned char *cmd = scp->cmnd; + unsigned char arr[SCSI_SENSE_BUFFERSIZE]; /* assume >= 18 bytes */ + bool dsense = !!(cmd[1] & 1); +- int alloc_len = cmd[4]; +- int len = 18; ++ u32 alloc_len = cmd[4]; ++ u32 len = 18; + int stopped_state = atomic_read(&devip->stopped); + + memset(arr, 0, sizeof(arr)); +@@ -1774,7 +1776,7 @@ static int resp_requests(struct scsi_cmnd *scp, + arr[7] = 0xa; + } + } +- return fill_from_dev_buffer(scp, arr, min_t(int, len, alloc_len)); ++ return fill_from_dev_buffer(scp, arr, min_t(u32, len, alloc_len)); + } + + static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) +@@ -1856,7 +1858,7 @@ static int resp_readcap16(struct scsi_cmnd *scp, + { + unsigned char *cmd = scp->cmnd; + unsigned char arr[SDEBUG_READCAP16_ARR_SZ]; +- int alloc_len; ++ u32 alloc_len; + + alloc_len = get_unaligned_be32(cmd + 10); + /* following just in case virtual_gb changed */ +@@ -1885,7 +1887,7 @@ static int resp_readcap16(struct scsi_cmnd *scp, + } + + return fill_from_dev_buffer(scp, arr, +- min_t(int, alloc_len, SDEBUG_READCAP16_ARR_SZ)); ++ min_t(u32, alloc_len, SDEBUG_READCAP16_ARR_SZ)); + } + + #define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 +@@ -1896,8 +1898,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd *scp, + unsigned char *cmd = scp->cmnd; + unsigned char *arr; + int host_no = devip->sdbg_host->shost->host_no; +- int n, ret, alen, rlen; + int port_group_a, port_group_b, port_a, port_b; ++ u32 alen, n, rlen; ++ int ret; + + alen = get_unaligned_be32(cmd + 6); + arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); +@@ -1959,9 +1962,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd *scp, + * - The constructed command length + * - The maximum array size + */ +- rlen = min_t(int, alen, n); ++ rlen = min(alen, n); + ret = fill_from_dev_buffer(scp, arr, +- min_t(int, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); ++ min_t(u32, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); + kfree(arr); + return ret; + } +@@ -2311,7 +2314,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + { + int pcontrol, pcode, subpcode, bd_len; + unsigned char dev_spec; +- int alloc_len, offset, len, target_dev_id; ++ u32 alloc_len, offset, len; ++ int target_dev_id; + int target = scp->device->id; + unsigned char *ap; + unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; +@@ -2467,7 +2471,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, + arr[0] = offset - 1; + else + put_unaligned_be16((offset - 2), arr + 0); +- return fill_from_dev_buffer(scp, arr, min_t(int, alloc_len, offset)); ++ return fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, offset)); + } + + #define SDEBUG_MAX_MSELECT_SZ 512 +@@ -2498,11 +2502,11 @@ static int resp_mode_select(struct scsi_cmnd *scp, + __func__, param_len, res); + md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2); + bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6); +- if (md_len > 2) { ++ off = bd_len + (mselect6 ? 4 : 8); ++ if (md_len > 2 || off >= res) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); + return check_condition_result; + } +- off = bd_len + (mselect6 ? 4 : 8); + mpage = arr[off] & 0x3f; + ps = !!(arr[off] & 0x80); + if (ps) { +@@ -2582,7 +2586,8 @@ static int resp_ie_l_pg(unsigned char *arr) + static int resp_log_sense(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) + { +- int ppc, sp, pcode, subpcode, alloc_len, len, n; ++ int ppc, sp, pcode, subpcode; ++ u32 alloc_len, len, n; + unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; + unsigned char *cmd = scp->cmnd; + +@@ -2652,9 +2657,9 @@ static int resp_log_sense(struct scsi_cmnd *scp, + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); + return check_condition_result; + } +- len = min_t(int, get_unaligned_be16(arr + 2) + 4, alloc_len); ++ len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len); + return fill_from_dev_buffer(scp, arr, +- min_t(int, len, SDEBUG_MAX_INQ_ARR_SZ)); ++ min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); + } + + static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip) +@@ -4258,6 +4263,8 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + mk_sense_invalid_opcode(scp); + return check_condition_result; + } ++ if (vnum == 0) ++ return 0; /* not an error */ + a_num = is_bytchk3 ? 1 : vnum; + /* Treat following check like one for read (i.e. no write) access */ + ret = check_device_access_params(scp, lba, a_num, false); +@@ -4321,6 +4328,8 @@ static int resp_report_zones(struct scsi_cmnd *scp, + } + zs_lba = get_unaligned_be64(cmd + 2); + alloc_len = get_unaligned_be32(cmd + 10); ++ if (alloc_len == 0) ++ return 0; /* not an error */ + rep_opts = cmd[14] & 0x3f; + partial = cmd[14] & 0x80; + +@@ -4333,7 +4342,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, + rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD), + max_zones); + +- arr = kcalloc(RZONES_DESC_HD, alloc_len, GFP_ATOMIC); ++ arr = kzalloc(alloc_len, GFP_ATOMIC); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); +@@ -4425,7 +4434,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, + put_unaligned_be64(sdebug_capacity - 1, arr + 8); + + rep_len = (unsigned long)desc - (unsigned long)arr; +- ret = fill_from_dev_buffer(scp, arr, min_t(int, alloc_len, rep_len)); ++ ret = fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, rep_len)); + + fini: + read_unlock(macc_lckp); +@@ -4648,6 +4657,7 @@ static void zbc_rwp_zone(struct sdebug_dev_info *devip, + struct sdeb_zone_state *zsp) + { + enum sdebug_z_cond zc; ++ struct sdeb_store_info *sip = devip2sip(devip, false); + + if (zbc_zone_is_conv(zsp)) + return; +@@ -4659,6 +4669,10 @@ static void zbc_rwp_zone(struct sdebug_dev_info *devip, + if (zsp->z_cond == ZC4_CLOSED) + devip->nr_closed--; + ++ if (zsp->z_wp > zsp->z_start) ++ memset(sip->storep + zsp->z_start * sdebug_sector_size, 0, ++ (zsp->z_wp - zsp->z_start) * sdebug_sector_size); ++ + zsp->z_non_seq_resource = false; + zsp->z_wp = zsp->z_start; + zsp->z_cond = ZC1_EMPTY; +diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c +index d9109771f274d..db8517f1a485a 100644 +--- a/drivers/scsi/scsi_debugfs.c ++++ b/drivers/scsi/scsi_debugfs.c +@@ -9,6 +9,7 @@ + static const char *const scsi_cmd_flags[] = { + SCSI_CMD_FLAG_NAME(TAGGED), + SCSI_CMD_FLAG_NAME(INITIALIZED), ++ SCSI_CMD_FLAG_NAME(LAST), + }; + #undef SCSI_CMD_FLAG_NAME + +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index b6c86cce57bfa..408d49c304b8d 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -135,6 +135,23 @@ static bool scsi_eh_should_retry_cmd(struct scsi_cmnd *cmd) + return true; + } + ++static void scsi_eh_complete_abort(struct scsi_cmnd *scmd, struct Scsi_Host *shost) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(shost->host_lock, flags); ++ list_del_init(&scmd->eh_entry); ++ /* ++ * If the abort succeeds, and there is no further ++ * EH action, clear the ->last_reset time. ++ */ ++ if (list_empty(&shost->eh_abort_list) && ++ list_empty(&shost->eh_cmd_q)) ++ if (shost->eh_deadline != -1) ++ shost->last_reset = 0; ++ spin_unlock_irqrestore(shost->host_lock, flags); ++} ++ + /** + * scmd_eh_abort_handler - Handle command aborts + * @work: command to be aborted. +@@ -152,6 +169,7 @@ scmd_eh_abort_handler(struct work_struct *work) + container_of(work, struct scsi_cmnd, abort_work.work); + struct scsi_device *sdev = scmd->device; + enum scsi_disposition rtn; ++ unsigned long flags; + + if (scsi_host_eh_past_deadline(sdev->host)) { + SCSI_LOG_ERROR_RECOVERY(3, +@@ -175,12 +193,14 @@ scmd_eh_abort_handler(struct work_struct *work) + SCSI_LOG_ERROR_RECOVERY(3, + scmd_printk(KERN_WARNING, scmd, + "retry aborted command\n")); ++ scsi_eh_complete_abort(scmd, sdev->host); + scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); + return; + } else { + SCSI_LOG_ERROR_RECOVERY(3, + scmd_printk(KERN_WARNING, scmd, + "finish aborted command\n")); ++ scsi_eh_complete_abort(scmd, sdev->host); + scsi_finish_command(scmd); + return; + } +@@ -193,6 +213,9 @@ scmd_eh_abort_handler(struct work_struct *work) + } + } + ++ spin_lock_irqsave(sdev->host->host_lock, flags); ++ list_del_init(&scmd->eh_entry); ++ spin_unlock_irqrestore(sdev->host->host_lock, flags); + scsi_eh_scmd_add(scmd); + } + +@@ -223,6 +246,8 @@ scsi_abort_command(struct scsi_cmnd *scmd) + spin_lock_irqsave(shost->host_lock, flags); + if (shost->eh_deadline != -1 && !shost->last_reset) + shost->last_reset = jiffies; ++ BUG_ON(!list_empty(&scmd->eh_entry)); ++ list_add_tail(&scmd->eh_entry, &shost->eh_abort_list); + spin_unlock_irqrestore(shost->host_lock, flags); + + scmd->eh_eflags |= SCSI_EH_ABORT_SCHEDULED; +diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c +index 6ff2207bd45a0..a06c61f22742e 100644 +--- a/drivers/scsi/scsi_ioctl.c ++++ b/drivers/scsi/scsi_ioctl.c +@@ -347,6 +347,8 @@ static int scsi_fill_sghdr_rq(struct scsi_device *sdev, struct request *rq, + { + struct scsi_request *req = scsi_req(rq); + ++ if (hdr->cmd_len < 6) ++ return -EMSGSIZE; + if (copy_from_user(req->cmd, hdr->cmdp, hdr->cmd_len)) + return -EFAULT; + if (!scsi_cmd_allowed(req->cmd, mode)) +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 572673873ddf8..ef4361b2d1423 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1143,6 +1143,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) + cmd->sense_buffer = buf; + cmd->prot_sdb = prot; + cmd->flags = flags; ++ INIT_LIST_HEAD(&cmd->eh_entry); + INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); + cmd->jiffies_at_alloc = jiffies_at_alloc; + cmd->retries = retries; +@@ -1174,8 +1175,6 @@ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, + } + + cmd->cmd_len = scsi_req(req)->cmd_len; +- if (cmd->cmd_len == 0) +- cmd->cmd_len = scsi_command_size(cmd->cmnd); + cmd->cmnd = scsi_req(req)->cmd; + cmd->transfersize = blk_rq_bytes(req); + cmd->allowed = scsi_req(req)->retries; +@@ -2075,7 +2074,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); + /** + * scsi_mode_sense - issue a mode sense, falling back from 10 to six bytes if necessary. + * @sdev: SCSI device to be queried +- * @dbd: set if mode sense will allow block descriptors to be returned ++ * @dbd: set to prevent mode sense from returning block descriptors + * @modepage: mode page being requested + * @buffer: request buffer (may not be smaller than eight bytes) + * @len: length of request buffer. +@@ -2110,18 +2109,18 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, + sshdr = &my_sshdr; + + retry: +- use_10_for_ms = sdev->use_10_for_ms; ++ use_10_for_ms = sdev->use_10_for_ms || len > 255; + + if (use_10_for_ms) { +- if (len < 8) +- len = 8; ++ if (len < 8 || len > 65535) ++ return -EINVAL; + + cmd[0] = MODE_SENSE_10; +- cmd[8] = len; ++ put_unaligned_be16(len, &cmd[7]); + header_length = 8; + } else { + if (len < 4) +- len = 4; ++ return -EINVAL; + + cmd[0] = MODE_SENSE; + cmd[4] = len; +@@ -2145,9 +2144,15 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, + if ((sshdr->sense_key == ILLEGAL_REQUEST) && + (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { + /* +- * Invalid command operation code ++ * Invalid command operation code: retry using ++ * MODE SENSE(6) if this was a MODE SENSE(10) ++ * request, except if the request mode page is ++ * too large for MODE SENSE single byte ++ * allocation length field. + */ + if (use_10_for_ms) { ++ if (len > 255) ++ return -EIO; + sdev->use_10_for_ms = 0; + goto retry; + } +@@ -2171,12 +2176,11 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, + data->longlba = 0; + data->block_descriptor_length = 0; + } else if (use_10_for_ms) { +- data->length = buffer[0]*256 + buffer[1] + 2; ++ data->length = get_unaligned_be16(&buffer[0]) + 2; + data->medium_type = buffer[2]; + data->device_specific = buffer[3]; + data->longlba = buffer[4] & 0x01; +- data->block_descriptor_length = buffer[6]*256 +- + buffer[7]; ++ data->block_descriptor_length = get_unaligned_be16(&buffer[6]); + } else { + data->length = buffer[0] + 1; + data->medium_type = buffer[1]; +diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c +index 3717eea37ecb3..e91a0a5bc7a3e 100644 +--- a/drivers/scsi/scsi_pm.c ++++ b/drivers/scsi/scsi_pm.c +@@ -262,7 +262,7 @@ static int sdev_runtime_resume(struct device *dev) + blk_pre_runtime_resume(sdev->request_queue); + if (pm && pm->runtime_resume) + err = pm->runtime_resume(dev); +- blk_post_runtime_resume(sdev->request_queue, err); ++ blk_post_runtime_resume(sdev->request_queue); + + return err; + } +diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c +index fe22191522a3b..7266880c70c21 100644 +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -198,6 +198,48 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, + SCSI_TIMEOUT, 3, NULL); + } + ++static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev, ++ unsigned int depth) ++{ ++ int new_shift = sbitmap_calculate_shift(depth); ++ bool need_alloc = !sdev->budget_map.map; ++ bool need_free = false; ++ int ret; ++ struct sbitmap sb_backup; ++ ++ /* ++ * realloc if new shift is calculated, which is caused by setting ++ * up one new default queue depth after calling ->slave_configure ++ */ ++ if (!need_alloc && new_shift != sdev->budget_map.shift) ++ need_alloc = need_free = true; ++ ++ if (!need_alloc) ++ return 0; ++ ++ /* ++ * Request queue has to be frozen for reallocating budget map, ++ * and here disk isn't added yet, so freezing is pretty fast ++ */ ++ if (need_free) { ++ blk_mq_freeze_queue(sdev->request_queue); ++ sb_backup = sdev->budget_map; ++ } ++ ret = sbitmap_init_node(&sdev->budget_map, ++ scsi_device_max_queue_depth(sdev), ++ new_shift, GFP_KERNEL, ++ sdev->request_queue->node, false, true); ++ if (need_free) { ++ if (ret) ++ sdev->budget_map = sb_backup; ++ else ++ sbitmap_free(&sb_backup); ++ ret = 0; ++ blk_mq_unfreeze_queue(sdev->request_queue); ++ } ++ return ret; ++} ++ + /** + * scsi_alloc_sdev - allocate and setup a scsi_Device + * @starget: which target to allocate a &scsi_device for +@@ -291,11 +333,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, + * default device queue depth to figure out sbitmap shift + * since we use this queue depth most of times. + */ +- if (sbitmap_init_node(&sdev->budget_map, +- scsi_device_max_queue_depth(sdev), +- sbitmap_calculate_shift(depth), +- GFP_KERNEL, sdev->request_queue->node, +- false, true)) { ++ if (scsi_realloc_sdev_budget_map(sdev, depth)) { + put_device(&starget->dev); + kfree(sdev); + goto out; +@@ -1001,6 +1039,13 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, + } + return SCSI_SCAN_NO_RESPONSE; + } ++ ++ /* ++ * The queue_depth is often changed in ->slave_configure. ++ * Set up budget map again since memory consumption of ++ * the map depends on actual queue depth. ++ */ ++ scsi_realloc_sdev_budget_map(sdev, sdev->queue_depth); + } + + if (sdev->scsi_level >= SCSI_3) +diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c +index a35841b34bfd9..920aae661c5b2 100644 +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -797,6 +797,7 @@ store_state_field(struct device *dev, struct device_attribute *attr, + int i, ret; + struct scsi_device *sdev = to_scsi_device(dev); + enum scsi_device_state state = 0; ++ bool rescan_dev = false; + + for (i = 0; i < ARRAY_SIZE(sdev_states); i++) { + const int len = strlen(sdev_states[i].name); +@@ -815,20 +816,27 @@ store_state_field(struct device *dev, struct device_attribute *attr, + } + + mutex_lock(&sdev->state_mutex); +- ret = scsi_device_set_state(sdev, state); +- /* +- * If the device state changes to SDEV_RUNNING, we need to +- * run the queue to avoid I/O hang, and rescan the device +- * to revalidate it. Running the queue first is necessary +- * because another thread may be waiting inside +- * blk_mq_freeze_queue_wait() and because that call may be +- * waiting for pending I/O to finish. +- */ +- if (ret == 0 && state == SDEV_RUNNING) { ++ if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) { ++ ret = 0; ++ } else { ++ ret = scsi_device_set_state(sdev, state); ++ if (ret == 0 && state == SDEV_RUNNING) ++ rescan_dev = true; ++ } ++ mutex_unlock(&sdev->state_mutex); ++ ++ if (rescan_dev) { ++ /* ++ * If the device state changes to SDEV_RUNNING, we need to ++ * run the queue to avoid I/O hang, and rescan the device ++ * to revalidate it. Running the queue first is necessary ++ * because another thread may be waiting inside ++ * blk_mq_freeze_queue_wait() and because that call may be ++ * waiting for pending I/O to finish. ++ */ + blk_mq_run_hw_queues(sdev->request_queue, true); + scsi_rescan_device(dev); + } +- mutex_unlock(&sdev->state_mutex); + + return ret == 0 ? count : -EINVAL; + } +@@ -1388,6 +1396,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) + * We're treating error on bsg register as non-fatal, so + * pretend nothing went wrong. + */ ++ error = PTR_ERR(sdev->bsg_dev); + sdev_printk(KERN_INFO, sdev, + "Failed to register bsg queue, errno=%d\n", + error); +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index 78343d3f93857..554b6f7842236 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work) + } + spin_unlock_irqrestore(&session->lock, flags); + +- if (session->transport->session_recovery_timedout) +- session->transport->session_recovery_timedout(session); +- + ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n"); + scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE); + ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n"); ++ ++ if (session->transport->session_recovery_timedout) ++ session->transport->session_recovery_timedout(session); + } + + static void __iscsi_unblock_session(struct work_struct *work) +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index fce63335084ed..78ead3369779c 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2607,6 +2607,13 @@ sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage, + unsigned char *buffer, int len, struct scsi_mode_data *data, + struct scsi_sense_hdr *sshdr) + { ++ /* ++ * If we must use MODE SENSE(10), make sure that the buffer length ++ * is at least 8 bytes so that the mode sense header fits. ++ */ ++ if (sdkp->device->use_10_for_ms && len < 8) ++ len = 8; ++ + return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len, + SD_TIMEOUT, sdkp->max_retries, data, + sshdr); +diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c +index ecb2af3f43ca3..a5453f5e87c3e 100644 +--- a/drivers/scsi/smartpqi/smartpqi_init.c ++++ b/drivers/scsi/smartpqi/smartpqi_init.c +@@ -234,15 +234,46 @@ static inline bool pqi_is_hba_lunid(u8 *scsi3addr) + return pqi_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID); + } + ++#define PQI_DRIVER_SCRATCH_PQI_MODE 0x1 ++#define PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED 0x2 ++ + static inline enum pqi_ctrl_mode pqi_get_ctrl_mode(struct pqi_ctrl_info *ctrl_info) + { +- return sis_read_driver_scratch(ctrl_info); ++ return sis_read_driver_scratch(ctrl_info) & PQI_DRIVER_SCRATCH_PQI_MODE ? PQI_MODE : SIS_MODE; + } + + static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info *ctrl_info, + enum pqi_ctrl_mode mode) + { +- sis_write_driver_scratch(ctrl_info, mode); ++ u32 driver_scratch; ++ ++ driver_scratch = sis_read_driver_scratch(ctrl_info); ++ ++ if (mode == PQI_MODE) ++ driver_scratch |= PQI_DRIVER_SCRATCH_PQI_MODE; ++ else ++ driver_scratch &= ~PQI_DRIVER_SCRATCH_PQI_MODE; ++ ++ sis_write_driver_scratch(ctrl_info, driver_scratch); ++} ++ ++static inline bool pqi_is_fw_triage_supported(struct pqi_ctrl_info *ctrl_info) ++{ ++ return (sis_read_driver_scratch(ctrl_info) & PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED) != 0; ++} ++ ++static inline void pqi_save_fw_triage_setting(struct pqi_ctrl_info *ctrl_info, bool is_supported) ++{ ++ u32 driver_scratch; ++ ++ driver_scratch = sis_read_driver_scratch(ctrl_info); ++ ++ if (is_supported) ++ driver_scratch |= PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED; ++ else ++ driver_scratch &= ~PQI_DRIVER_SCRATCH_FW_TRIAGE_SUPPORTED; ++ ++ sis_write_driver_scratch(ctrl_info, driver_scratch); + } + + static inline void pqi_ctrl_block_scan(struct pqi_ctrl_info *ctrl_info) +@@ -7301,6 +7332,7 @@ static void pqi_ctrl_update_feature_flags(struct pqi_ctrl_info *ctrl_info, + ctrl_info->unique_wwid_in_report_phys_lun_supported = + firmware_feature->enabled; + break; ++ pqi_save_fw_triage_setting(ctrl_info, firmware_feature->enabled); + } + + pqi_firmware_feature_status(ctrl_info, firmware_feature); +@@ -7627,6 +7659,11 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info) + u32 product_id; + + if (reset_devices) { ++ if (pqi_is_fw_triage_supported(ctrl_info)) { ++ rc = sis_wait_for_fw_triage_completion(ctrl_info); ++ if (rc) ++ return rc; ++ } + sis_soft_reset(ctrl_info); + msleep(PQI_POST_RESET_DELAY_SECS * PQI_HZ); + } else { +diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c +index d63c46a8e38bb..8acd3a80f5822 100644 +--- a/drivers/scsi/smartpqi/smartpqi_sis.c ++++ b/drivers/scsi/smartpqi/smartpqi_sis.c +@@ -51,12 +51,20 @@ + #define SIS_BASE_STRUCT_REVISION 9 + #define SIS_BASE_STRUCT_ALIGNMENT 16 + ++#define SIS_CTRL_KERNEL_FW_TRIAGE 0x3 + #define SIS_CTRL_KERNEL_UP 0x80 + #define SIS_CTRL_KERNEL_PANIC 0x100 + #define SIS_CTRL_READY_TIMEOUT_SECS 180 + #define SIS_CTRL_READY_RESUME_TIMEOUT_SECS 90 + #define SIS_CTRL_READY_POLL_INTERVAL_MSECS 10 + ++enum sis_fw_triage_status { ++ FW_TRIAGE_NOT_STARTED = 0, ++ FW_TRIAGE_STARTED, ++ FW_TRIAGE_COND_INVALID, ++ FW_TRIAGE_COMPLETED ++}; ++ + #pragma pack(1) + + /* for use with SIS_CMD_INIT_BASE_STRUCT_ADDRESS command */ +@@ -419,12 +427,55 @@ u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info) + return readl(&ctrl_info->registers->sis_driver_scratch); + } + ++static inline enum sis_fw_triage_status ++ sis_read_firmware_triage_status(struct pqi_ctrl_info *ctrl_info) ++{ ++ return ((enum sis_fw_triage_status)(readl(&ctrl_info->registers->sis_firmware_status) & ++ SIS_CTRL_KERNEL_FW_TRIAGE)); ++} ++ + void sis_soft_reset(struct pqi_ctrl_info *ctrl_info) + { + writel(SIS_SOFT_RESET, + &ctrl_info->registers->sis_host_to_ctrl_doorbell); + } + ++#define SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS 300 ++#define SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS 1 ++ ++int sis_wait_for_fw_triage_completion(struct pqi_ctrl_info *ctrl_info) ++{ ++ int rc; ++ enum sis_fw_triage_status status; ++ unsigned long timeout; ++ ++ timeout = (SIS_FW_TRIAGE_STATUS_TIMEOUT_SECS * PQI_HZ) + jiffies; ++ while (1) { ++ status = sis_read_firmware_triage_status(ctrl_info); ++ if (status == FW_TRIAGE_COND_INVALID) { ++ dev_err(&ctrl_info->pci_dev->dev, ++ "firmware triage condition invalid\n"); ++ rc = -EINVAL; ++ break; ++ } else if (status == FW_TRIAGE_NOT_STARTED || ++ status == FW_TRIAGE_COMPLETED) { ++ rc = 0; ++ break; ++ } ++ ++ if (time_after(jiffies, timeout)) { ++ dev_err(&ctrl_info->pci_dev->dev, ++ "timed out waiting for firmware triage status\n"); ++ rc = -ETIMEDOUT; ++ break; ++ } ++ ++ ssleep(SIS_FW_TRIAGE_STATUS_POLL_INTERVAL_SECS); ++ } ++ ++ return rc; ++} ++ + static void __attribute__((unused)) verify_structures(void) + { + BUILD_BUG_ON(offsetof(struct sis_base_struct, +diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h +index d29c1352a826a..c1db93054c863 100644 +--- a/drivers/scsi/smartpqi/smartpqi_sis.h ++++ b/drivers/scsi/smartpqi/smartpqi_sis.h +@@ -28,5 +28,6 @@ void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value); + u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info); + void sis_soft_reset(struct pqi_ctrl_info *ctrl_info); + u32 sis_get_product_id(struct pqi_ctrl_info *ctrl_info); ++int sis_wait_for_fw_triage_completion(struct pqi_ctrl_info *ctrl_info); + + #endif /* _SMARTPQI_SIS_H */ +diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c +index 8b17b35283aa5..1203374828b97 100644 +--- a/drivers/scsi/sr.c ++++ b/drivers/scsi/sr.c +@@ -851,7 +851,7 @@ static void get_capabilities(struct scsi_cd *cd) + + + /* allocate transfer buffer */ +- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); ++ buffer = kmalloc(512, GFP_KERNEL); + if (!buffer) { + sr_printk(KERN_ERR, cd, "out of memory.\n"); + return; +diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c +index 1f988a1b9166f..a61635326ae0a 100644 +--- a/drivers/scsi/sr_vendor.c ++++ b/drivers/scsi/sr_vendor.c +@@ -131,7 +131,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) + if (cd->vendor == VENDOR_TOSHIBA) + density = (blocklength > 2048) ? 0x81 : 0x83; + +- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); ++ buffer = kmalloc(512, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + +@@ -179,7 +179,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) + if (cd->cdi.mask & CDC_MULTI_SESSION) + return 0; + +- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); ++ buffer = kmalloc(512, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + +diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c b/drivers/scsi/ufs/tc-dwc-g210-pci.c +index 679289e1a78e6..7b08e2e07cc5f 100644 +--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c ++++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c +@@ -110,7 +110,6 @@ tc_dwc_g210_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + return err; + } + +- pci_set_drvdata(pdev, hba); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_allow(&pdev->dev); + +diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c +index 80b3545dd17d6..4e53857605de8 100644 +--- a/drivers/scsi/ufs/ufs-mediatek.c ++++ b/drivers/scsi/ufs/ufs-mediatek.c +@@ -501,7 +501,7 @@ static void ufs_mtk_init_va09_pwr_ctrl(struct ufs_hba *hba) + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + host->reg_va09 = regulator_get(hba->dev, "va09"); +- if (!host->reg_va09) ++ if (IS_ERR(host->reg_va09)) + dev_info(hba->dev, "failed to get va09"); + else + host->caps |= UFS_MTK_CAP_VA09_PWR_CTRL; +diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c +index 51424557810da..f76692053ca17 100644 +--- a/drivers/scsi/ufs/ufshcd-pci.c ++++ b/drivers/scsi/ufs/ufshcd-pci.c +@@ -421,6 +421,13 @@ static int ufs_intel_lkf_init(struct ufs_hba *hba) + return err; + } + ++static int ufs_intel_adl_init(struct ufs_hba *hba) ++{ ++ hba->nop_out_timeout = 200; ++ hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; ++ return ufs_intel_common_init(hba); ++} ++ + static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = { + .name = "intel-pci", + .init = ufs_intel_common_init, +@@ -449,6 +456,15 @@ static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = { + .device_reset = ufs_intel_device_reset, + }; + ++static struct ufs_hba_variant_ops ufs_intel_adl_hba_vops = { ++ .name = "intel-pci", ++ .init = ufs_intel_adl_init, ++ .exit = ufs_intel_common_exit, ++ .link_startup_notify = ufs_intel_link_startup_notify, ++ .resume = ufs_intel_resume, ++ .device_reset = ufs_intel_device_reset, ++}; ++ + #ifdef CONFIG_PM_SLEEP + static int ufshcd_pci_restore(struct device *dev) + { +@@ -522,8 +538,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + return err; + } + +- pci_set_drvdata(pdev, hba); +- + hba->vops = (struct ufs_hba_variant_ops *)id->driver_data; + + err = ufshcd_init(hba, mmio_base, pdev->irq); +@@ -563,6 +577,8 @@ static const struct pci_device_id ufshcd_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, + { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, + { PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops }, ++ { PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, ++ { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, + { } /* terminate list */ + }; + +diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c +index 8859c13f4e091..87975d1a21c8b 100644 +--- a/drivers/scsi/ufs/ufshcd-pltfrm.c ++++ b/drivers/scsi/ufs/ufshcd-pltfrm.c +@@ -91,7 +91,12 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) + + clki->min_freq = clkfreq[i]; + clki->max_freq = clkfreq[i+1]; +- clki->name = kstrdup(name, GFP_KERNEL); ++ clki->name = devm_kstrdup(dev, name, GFP_KERNEL); ++ if (!clki->name) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ + if (!strcmp(name, "ref_clk")) + clki->keep_link_active = true; + dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz", +@@ -126,7 +131,9 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, + if (!vreg) + return -ENOMEM; + +- vreg->name = kstrdup(name, GFP_KERNEL); ++ vreg->name = devm_kstrdup(dev, name, GFP_KERNEL); ++ if (!vreg->name) ++ return -ENOMEM; + + snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name); + if (of_property_read_u32(np, prop_name, &vreg->max_uA)) { +@@ -361,8 +368,6 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, + goto dealloc_host; + } + +- platform_set_drvdata(pdev, hba); +- + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index 41f2ff35f82b2..cdec85bcc4ccc 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -125,8 +125,9 @@ EXPORT_SYMBOL_GPL(ufshcd_dump_regs); + enum { + UFSHCD_MAX_CHANNEL = 0, + UFSHCD_MAX_ID = 1, +- UFSHCD_CMD_PER_LUN = 32, +- UFSHCD_CAN_QUEUE = 32, ++ UFSHCD_NUM_RESERVED = 1, ++ UFSHCD_CMD_PER_LUN = 32 - UFSHCD_NUM_RESERVED, ++ UFSHCD_CAN_QUEUE = 32 - UFSHCD_NUM_RESERVED, + }; + + /* UFSHCD error handling flags */ +@@ -222,8 +223,7 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba); + static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd); + static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); + static void ufshcd_hba_exit(struct ufs_hba *hba); +-static int ufshcd_clear_ua_wluns(struct ufs_hba *hba); +-static int ufshcd_probe_hba(struct ufs_hba *hba, bool async); ++static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params); + static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); + static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); + static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); +@@ -1658,7 +1658,8 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) + bool flush_result; + unsigned long flags; + +- if (!ufshcd_is_clkgating_allowed(hba)) ++ if (!ufshcd_is_clkgating_allowed(hba) || ++ !hba->clk_gating.is_initialized) + goto out; + spin_lock_irqsave(hba->host->host_lock, flags); + hba->clk_gating.active_reqs++; +@@ -1818,7 +1819,7 @@ static void __ufshcd_release(struct ufs_hba *hba) + + if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended || + hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || +- hba->outstanding_tasks || ++ hba->outstanding_tasks || !hba->clk_gating.is_initialized || + hba->active_uic_cmd || hba->uic_async_done || + hba->clk_gating.state == CLKS_OFF) + return; +@@ -1953,11 +1954,15 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) + { + if (!hba->clk_gating.is_initialized) + return; ++ + ufshcd_remove_clk_gating_sysfs(hba); +- cancel_work_sync(&hba->clk_gating.ungate_work); +- cancel_delayed_work_sync(&hba->clk_gating.gate_work); +- destroy_workqueue(hba->clk_gating.clk_gating_workq); ++ ++ /* Ungate the clock if necessary. */ ++ ufshcd_hold(hba, false); + hba->clk_gating.is_initialized = false; ++ ufshcd_release(hba); ++ ++ destroy_workqueue(hba->clk_gating.clk_gating_workq); + } + + /* Must be called with host lock acquired */ +@@ -2181,6 +2186,7 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba) + hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1; + hba->nutmrs = + ((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1; ++ hba->reserved_slot = hba->nutrs - 1; + + /* Read crypto capabilities */ + err = ufshcd_hba_init_crypto_capabilities(hba); +@@ -2906,30 +2912,15 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, + static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, + enum dev_cmd_type cmd_type, int timeout) + { +- struct request_queue *q = hba->cmd_queue; + DECLARE_COMPLETION_ONSTACK(wait); +- struct request *req; ++ const u32 tag = hba->reserved_slot; + struct ufshcd_lrb *lrbp; + int err; +- int tag; + +- down_read(&hba->clk_scaling_lock); ++ /* Protects use of hba->reserved_slot. */ ++ lockdep_assert_held(&hba->dev_cmd.lock); + +- /* +- * Get free slot, sleep if slots are unavailable. +- * Even though we use wait_event() which sleeps indefinitely, +- * the maximum wait time is bounded by SCSI request timeout. +- */ +- req = blk_get_request(q, REQ_OP_DRV_OUT, 0); +- if (IS_ERR(req)) { +- err = PTR_ERR(req); +- goto out_unlock; +- } +- tag = req->tag; +- WARN_ONCE(tag < 0, "Invalid tag %d\n", tag); +- /* Set the timeout such that the SCSI error handler is not activated. */ +- req->timeout = msecs_to_jiffies(2 * timeout); +- blk_mq_start_request(req); ++ down_read(&hba->clk_scaling_lock); + + lrbp = &hba->lrb[tag]; + WARN_ON(lrbp->cmd); +@@ -2947,8 +2938,6 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, + (struct utp_upiu_req *)lrbp->ucd_rsp_ptr); + + out: +- blk_put_request(req); +-out_unlock: + up_read(&hba->clk_scaling_lock); + return err; + } +@@ -4073,8 +4062,6 @@ int ufshcd_link_recovery(struct ufs_hba *hba) + if (ret) + dev_err(hba->dev, "%s: link recovery failed, err %d", + __func__, ret); +- else +- ufshcd_clear_ua_wluns(hba); + + return ret; + } +@@ -5959,7 +5946,6 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) + ufshcd_release(hba); + if (ufshcd_is_clkscaling_supported(hba)) + ufshcd_clk_scaling_suspend(hba, false); +- ufshcd_clear_ua_wluns(hba); + ufshcd_rpm_put(hba); + } + +@@ -6386,9 +6372,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba) + irqreturn_t ret = IRQ_NONE; + int tag; + +- pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); +- + spin_lock_irqsave(hba->host->host_lock, flags); ++ pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); + issued = hba->outstanding_tasks & ~pending; + for_each_set_bit(tag, &issued, hba->nutmrs) { + struct request *req = hba->tmf_rqs[tag]; +@@ -6545,11 +6530,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, + err = wait_for_completion_io_timeout(&wait, + msecs_to_jiffies(TM_CMD_TIMEOUT)); + if (!err) { +- /* +- * Make sure that ufshcd_compl_tm() does not trigger a +- * use-after-free. +- */ +- req->end_io_data = NULL; + ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR); + dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n", + __func__, tm_function); +@@ -6645,28 +6625,16 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, + enum dev_cmd_type cmd_type, + enum query_opcode desc_op) + { +- struct request_queue *q = hba->cmd_queue; + DECLARE_COMPLETION_ONSTACK(wait); +- struct request *req; ++ const u32 tag = hba->reserved_slot; + struct ufshcd_lrb *lrbp; + int err = 0; +- int tag; + u8 upiu_flags; + +- down_read(&hba->clk_scaling_lock); +- +- req = blk_get_request(q, REQ_OP_DRV_OUT, 0); +- if (IS_ERR(req)) { +- err = PTR_ERR(req); +- goto out_unlock; +- } +- tag = req->tag; +- WARN_ONCE(tag < 0, "Invalid tag %d\n", tag); ++ /* Protects use of hba->reserved_slot. */ ++ lockdep_assert_held(&hba->dev_cmd.lock); + +- if (unlikely(test_bit(tag, &hba->outstanding_reqs))) { +- err = -EBUSY; +- goto out; +- } ++ down_read(&hba->clk_scaling_lock); + + lrbp = &hba->lrb[tag]; + WARN_ON(lrbp->cmd); +@@ -6735,9 +6703,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, + ufshcd_add_query_upiu_trace(hba, err ? UFS_QUERY_ERR : UFS_QUERY_COMP, + (struct utp_upiu_req *)lrbp->ucd_rsp_ptr); + +-out: +- blk_put_request(req); +-out_unlock: + up_read(&hba->clk_scaling_lock); + return err; + } +@@ -7044,6 +7009,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) + goto release; + } + ++ lrbp->cmd = NULL; + err = SUCCESS; + + release: +@@ -7875,8 +7841,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) + if (ret) + goto out; + +- ufshcd_clear_ua_wluns(hba); +- + /* Initialize devfreq after UFS device is detected */ + if (ufshcd_is_clkscaling_supported(hba)) { + memcpy(&hba->clk_scaling.saved_pwr_info.info, +@@ -7902,116 +7866,6 @@ out: + return ret; + } + +-static void ufshcd_request_sense_done(struct request *rq, blk_status_t error) +-{ +- if (error != BLK_STS_OK) +- pr_err("%s: REQUEST SENSE failed (%d)\n", __func__, error); +- kfree(rq->end_io_data); +- blk_put_request(rq); +-} +- +-static int +-ufshcd_request_sense_async(struct ufs_hba *hba, struct scsi_device *sdev) +-{ +- /* +- * Some UFS devices clear unit attention condition only if the sense +- * size used (UFS_SENSE_SIZE in this case) is non-zero. +- */ +- static const u8 cmd[6] = {REQUEST_SENSE, 0, 0, 0, UFS_SENSE_SIZE, 0}; +- struct scsi_request *rq; +- struct request *req; +- char *buffer; +- int ret; +- +- buffer = kzalloc(UFS_SENSE_SIZE, GFP_KERNEL); +- if (!buffer) +- return -ENOMEM; +- +- req = blk_get_request(sdev->request_queue, REQ_OP_DRV_IN, +- /*flags=*/BLK_MQ_REQ_PM); +- if (IS_ERR(req)) { +- ret = PTR_ERR(req); +- goto out_free; +- } +- +- ret = blk_rq_map_kern(sdev->request_queue, req, +- buffer, UFS_SENSE_SIZE, GFP_NOIO); +- if (ret) +- goto out_put; +- +- rq = scsi_req(req); +- rq->cmd_len = ARRAY_SIZE(cmd); +- memcpy(rq->cmd, cmd, rq->cmd_len); +- rq->retries = 3; +- req->timeout = 1 * HZ; +- req->rq_flags |= RQF_PM | RQF_QUIET; +- req->end_io_data = buffer; +- +- blk_execute_rq_nowait(/*bd_disk=*/NULL, req, /*at_head=*/true, +- ufshcd_request_sense_done); +- return 0; +- +-out_put: +- blk_put_request(req); +-out_free: +- kfree(buffer); +- return ret; +-} +- +-static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun) +-{ +- struct scsi_device *sdp; +- unsigned long flags; +- int ret = 0; +- +- spin_lock_irqsave(hba->host->host_lock, flags); +- if (wlun == UFS_UPIU_UFS_DEVICE_WLUN) +- sdp = hba->sdev_ufs_device; +- else if (wlun == UFS_UPIU_RPMB_WLUN) +- sdp = hba->sdev_rpmb; +- else +- BUG(); +- if (sdp) { +- ret = scsi_device_get(sdp); +- if (!ret && !scsi_device_online(sdp)) { +- ret = -ENODEV; +- scsi_device_put(sdp); +- } +- } else { +- ret = -ENODEV; +- } +- spin_unlock_irqrestore(hba->host->host_lock, flags); +- if (ret) +- goto out_err; +- +- ret = ufshcd_request_sense_async(hba, sdp); +- scsi_device_put(sdp); +-out_err: +- if (ret) +- dev_err(hba->dev, "%s: UAC clear LU=%x ret = %d\n", +- __func__, wlun, ret); +- return ret; +-} +- +-static int ufshcd_clear_ua_wluns(struct ufs_hba *hba) +-{ +- int ret = 0; +- +- if (!hba->wlun_dev_clr_ua) +- goto out; +- +- ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN); +- if (!ret) +- ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN); +- if (!ret) +- hba->wlun_dev_clr_ua = false; +-out: +- if (ret) +- dev_err(hba->dev, "%s: Failed to clear UAC WLUNS ret = %d\n", +- __func__, ret); +- return ret; +-} +- + /** + * ufshcd_probe_hba - probe hba to detect device and initialize it + * @hba: per-adapter instance +@@ -8062,8 +7916,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params) + /* UFS device is also active now */ + ufshcd_set_ufs_dev_active(hba); + ufshcd_force_reset_auto_bkops(hba); +- hba->wlun_dev_clr_ua = true; +- hba->wlun_rpmb_clr_ua = true; + + /* Gear up to HS gear if supported */ + if (hba->max_pwr_info.is_valid) { +@@ -8591,7 +8443,7 @@ static void ufshcd_hba_exit(struct ufs_hba *hba) + * @pwr_mode: device power mode to set + * + * Returns 0 if requested power mode is set successfully +- * Returns non-zero if failed to set the requested power mode ++ * Returns < 0 if failed to set the requested power mode + */ + static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + enum ufs_dev_pwr_mode pwr_mode) +@@ -8600,7 +8452,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + struct scsi_sense_hdr sshdr; + struct scsi_device *sdp; + unsigned long flags; +- int ret; ++ int ret, retries; + + spin_lock_irqsave(hba->host->host_lock, flags); + sdp = hba->sdev_ufs_device; +@@ -8625,8 +8477,6 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + * handling context. + */ + hba->host->eh_noresume = 1; +- if (hba->wlun_dev_clr_ua) +- ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN); + + cmd[4] = pwr_mode << 4; + +@@ -8635,14 +8485,23 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + * callbacks hence set the RQF_PM flag so that it doesn't resume the + * already suspended childs. + */ +- ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, +- START_STOP_TIMEOUT, 0, 0, RQF_PM, NULL); ++ for (retries = 3; retries > 0; --retries) { ++ ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, ++ START_STOP_TIMEOUT, 0, 0, RQF_PM, NULL); ++ if (!scsi_status_is_check_condition(ret) || ++ !scsi_sense_valid(&sshdr) || ++ sshdr.sense_key != UNIT_ATTENTION) ++ break; ++ } + if (ret) { + sdev_printk(KERN_WARNING, sdp, + "START_STOP failed for power mode: %d, result %x\n", + pwr_mode, ret); +- if (ret > 0 && scsi_sense_valid(&sshdr)) +- scsi_print_sense_hdr(sdp, NULL, &sshdr); ++ if (ret > 0) { ++ if (scsi_sense_valid(&sshdr)) ++ scsi_print_sense_hdr(sdp, NULL, &sshdr); ++ ret = -EIO; ++ } + } + + if (!ret) +@@ -9485,6 +9344,13 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + struct device *dev = hba->dev; + char eh_wq_name[sizeof("ufs_eh_wq_00")]; + ++ /* ++ * dev_set_drvdata() must be called before any callbacks are registered ++ * that use dev_get_drvdata() (frequency scaling, clock scaling, hwmon, ++ * sysfs). ++ */ ++ dev_set_drvdata(dev, hba); ++ + if (!mmio_base) { + dev_err(hba->dev, + "Invalid memory reference for mmio_base is NULL\n"); +@@ -9527,8 +9393,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + /* Configure LRB */ + ufshcd_host_memory_configure(hba); + +- host->can_queue = hba->nutrs; +- host->cmd_per_lun = hba->nutrs; ++ host->can_queue = hba->nutrs - UFSHCD_NUM_RESERVED; ++ host->cmd_per_lun = hba->nutrs - UFSHCD_NUM_RESERVED; + host->max_id = UFSHCD_MAX_ID; + host->max_lun = UFS_MAX_LUNS; + host->max_channel = UFSHCD_MAX_CHANNEL; +@@ -9699,10 +9565,6 @@ void ufshcd_resume_complete(struct device *dev) + ufshcd_rpm_put(hba); + hba->complete_put = false; + } +- if (hba->rpmb_complete_put) { +- ufshcd_rpmb_rpm_put(hba); +- hba->rpmb_complete_put = false; +- } + } + EXPORT_SYMBOL_GPL(ufshcd_resume_complete); + +@@ -9725,10 +9587,6 @@ int ufshcd_suspend_prepare(struct device *dev) + } + hba->complete_put = true; + } +- if (hba->sdev_rpmb) { +- ufshcd_rpmb_rpm_get_sync(hba); +- hba->rpmb_complete_put = true; +- } + return 0; + } + EXPORT_SYMBOL_GPL(ufshcd_suspend_prepare); +@@ -9797,49 +9655,6 @@ static struct scsi_driver ufs_dev_wlun_template = { + }, + }; + +-static int ufshcd_rpmb_probe(struct device *dev) +-{ +- return is_rpmb_wlun(to_scsi_device(dev)) ? 0 : -ENODEV; +-} +- +-static inline int ufshcd_clear_rpmb_uac(struct ufs_hba *hba) +-{ +- int ret = 0; +- +- if (!hba->wlun_rpmb_clr_ua) +- return 0; +- ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN); +- if (!ret) +- hba->wlun_rpmb_clr_ua = 0; +- return ret; +-} +- +-#ifdef CONFIG_PM +-static int ufshcd_rpmb_resume(struct device *dev) +-{ +- struct ufs_hba *hba = wlun_dev_to_hba(dev); +- +- if (hba->sdev_rpmb) +- ufshcd_clear_rpmb_uac(hba); +- return 0; +-} +-#endif +- +-static const struct dev_pm_ops ufs_rpmb_pm_ops = { +- SET_RUNTIME_PM_OPS(NULL, ufshcd_rpmb_resume, NULL) +- SET_SYSTEM_SLEEP_PM_OPS(NULL, ufshcd_rpmb_resume) +-}; +- +-/* ufs_rpmb_wlun_template - Describes UFS RPMB WLUN. Used only to send UAC. */ +-static struct scsi_driver ufs_rpmb_wlun_template = { +- .gendrv = { +- .name = "ufs_rpmb_wlun", +- .owner = THIS_MODULE, +- .probe = ufshcd_rpmb_probe, +- .pm = &ufs_rpmb_pm_ops, +- }, +-}; +- + static int __init ufshcd_core_init(void) + { + int ret; +@@ -9848,24 +9663,13 @@ static int __init ufshcd_core_init(void) + + ret = scsi_register_driver(&ufs_dev_wlun_template.gendrv); + if (ret) +- goto debugfs_exit; +- +- ret = scsi_register_driver(&ufs_rpmb_wlun_template.gendrv); +- if (ret) +- goto unregister; +- +- return ret; +-unregister: +- scsi_unregister_driver(&ufs_dev_wlun_template.gendrv); +-debugfs_exit: +- ufs_debugfs_exit(); ++ ufs_debugfs_exit(); + return ret; + } + + static void __exit ufshcd_core_exit(void) + { + ufs_debugfs_exit(); +- scsi_unregister_driver(&ufs_rpmb_wlun_template.gendrv); + scsi_unregister_driver(&ufs_dev_wlun_template.gendrv); + } + +diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h +index 41f6e06f91856..d470a52ff24c3 100644 +--- a/drivers/scsi/ufs/ufshcd.h ++++ b/drivers/scsi/ufs/ufshcd.h +@@ -725,6 +725,7 @@ struct ufs_hba_monitor { + * @capabilities: UFS Controller Capabilities + * @nutrs: Transfer Request Queue depth supported by controller + * @nutmrs: Task Management Queue depth supported by controller ++ * @reserved_slot: Used to submit device commands. Protected by @dev_cmd.lock. + * @ufs_version: UFS Version to which controller complies + * @vops: pointer to variant specific operations + * @priv: pointer to variant specific private data +@@ -813,6 +814,7 @@ struct ufs_hba { + u32 capabilities; + int nutrs; + int nutmrs; ++ u32 reserved_slot; + u32 ufs_version; + const struct ufs_hba_variant_ops *vops; + struct ufs_hba_variant_params *vps; +@@ -871,9 +873,6 @@ struct ufs_hba { + struct ufs_vreg_info vreg_info; + struct list_head clk_list_head; + +- bool wlun_dev_clr_ua; +- bool wlun_rpmb_clr_ua; +- + /* Number of requests aborts */ + int req_abort_count; + +@@ -920,7 +919,6 @@ struct ufs_hba { + #endif + u32 luns_avail; + bool complete_put; +- bool rpmb_complete_put; + }; + + /* Returns true if clocks can be gated. Otherwise false */ +@@ -1393,14 +1391,4 @@ static inline int ufshcd_rpm_put(struct ufs_hba *hba) + return pm_runtime_put(&hba->sdev_ufs_device->sdev_gendev); + } + +-static inline int ufshcd_rpmb_rpm_get_sync(struct ufs_hba *hba) +-{ +- return pm_runtime_get_sync(&hba->sdev_rpmb->sdev_gendev); +-} +- +-static inline int ufshcd_rpmb_rpm_put(struct ufs_hba *hba) +-{ +- return pm_runtime_put(&hba->sdev_rpmb->sdev_gendev); +-} +- + #endif /* End of Header */ +diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h +index de95be5d11d4e..3ed60068c4ea6 100644 +--- a/drivers/scsi/ufs/ufshci.h ++++ b/drivers/scsi/ufs/ufshci.h +@@ -142,7 +142,8 @@ static inline u32 ufshci_version(u32 major, u32 minor) + #define INT_FATAL_ERRORS (DEVICE_FATAL_ERROR |\ + CONTROLLER_FATAL_ERROR |\ + SYSTEM_BUS_FATAL_ERROR |\ +- CRYPTO_ENGINE_FATAL_ERROR) ++ CRYPTO_ENGINE_FATAL_ERROR |\ ++ UIC_LINK_LOST) + + /* HCS - Host Controller Status 30h */ + #define DEVICE_PRESENT 0x1 +diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c +index 026a133149dce..a86d0cc50de21 100644 +--- a/drivers/scsi/ufs/ufshpb.c ++++ b/drivers/scsi/ufs/ufshpb.c +@@ -394,8 +394,6 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) + if (!ufshpb_is_supported_chunk(hpb, transfer_len)) + return 0; + +- WARN_ON_ONCE(transfer_len > HPB_MULTI_CHUNK_HIGH); +- + if (hpb->is_hcm) { + /* + * in host control mode, reads are the main source for +@@ -1572,7 +1570,7 @@ static void ufshpb_lu_parameter_init(struct ufs_hba *hba, + if (ufshpb_is_legacy(hba)) + hpb->pre_req_max_tr_len = HPB_LEGACY_CHUNK_HIGH; + else +- hpb->pre_req_max_tr_len = HPB_MULTI_CHUNK_HIGH; ++ hpb->pre_req_max_tr_len = hpb_dev_info->max_hpb_single_cmd; + + hpb->lu_pinned_start = hpb_lu_info->pinned_start; + hpb->lu_pinned_end = hpb_lu_info->num_pinned ? +@@ -2371,11 +2369,11 @@ static int ufshpb_get_lu_info(struct ufs_hba *hba, int lun, + + ufshcd_map_desc_id_to_length(hba, QUERY_DESC_IDN_UNIT, &size); + +- pm_runtime_get_sync(hba->dev); ++ ufshcd_rpm_get_sync(hba); + ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, + QUERY_DESC_IDN_UNIT, lun, 0, + desc_buf, &size); +- pm_runtime_put_sync(hba->dev); ++ ufshcd_rpm_put_sync(hba); + + if (ret) { + dev_err(hba->dev, +@@ -2582,7 +2580,7 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf) + { + struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev; + int version, ret; +- u32 max_hpb_single_cmd = HPB_MULTI_CHUNK_LOW; ++ int max_single_cmd; + + hpb_dev_info->control_mode = desc_buf[DEVICE_DESC_PARAM_HPB_CONTROL]; + +@@ -2598,21 +2596,22 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf) + if (version == HPB_SUPPORT_LEGACY_VERSION) + hpb_dev_info->is_legacy = true; + +- pm_runtime_get_sync(hba->dev); +- ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, +- QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_hpb_single_cmd); +- pm_runtime_put_sync(hba->dev); +- +- if (ret) +- dev_err(hba->dev, "%s: idn: read max size of single hpb cmd query request failed", +- __func__); +- hpb_dev_info->max_hpb_single_cmd = max_hpb_single_cmd; +- + /* + * Get the number of user logical unit to check whether all + * scsi_device finish initialization + */ + hpb_dev_info->num_lu = desc_buf[DEVICE_DESC_PARAM_NUM_LU]; ++ ++ if (hpb_dev_info->is_legacy) ++ return; ++ ++ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, ++ QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_single_cmd); ++ ++ if (ret) ++ hpb_dev_info->max_hpb_single_cmd = HPB_LEGACY_CHUNK_HIGH; ++ else ++ hpb_dev_info->max_hpb_single_cmd = min(max_single_cmd + 1, HPB_MULTI_CHUNK_HIGH); + } + + void ufshpb_init(struct ufs_hba *hba) +diff --git a/drivers/scsi/ufs/ufshpb.h b/drivers/scsi/ufs/ufshpb.h +index f15d8fdbce2ef..b475dbd789883 100644 +--- a/drivers/scsi/ufs/ufshpb.h ++++ b/drivers/scsi/ufs/ufshpb.h +@@ -31,7 +31,6 @@ + + /* hpb support chunk size */ + #define HPB_LEGACY_CHUNK_HIGH 1 +-#define HPB_MULTI_CHUNK_LOW 7 + #define HPB_MULTI_CHUNK_HIGH 255 + + /* hpb vender defined opcode */ +diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c +index ce1ba1b936298..9419d6d1d8d26 100644 +--- a/drivers/scsi/vmw_pvscsi.c ++++ b/drivers/scsi/vmw_pvscsi.c +@@ -586,9 +586,12 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, + * Commands like INQUIRY may transfer less data than + * requested by the initiator via bufflen. Set residual + * count to make upper layer aware of the actual amount +- * of data returned. ++ * of data returned. There are cases when controller ++ * returns zero dataLen with non zero data - do not set ++ * residual count in that case. + */ +- scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen); ++ if (e->dataLen && (e->dataLen < scsi_bufflen(cmd))) ++ scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen); + cmd->result = (DID_OK << 16); + break; + +diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c +index 0204e314b4825..17b8c88840873 100644 +--- a/drivers/scsi/xen-scsifront.c ++++ b/drivers/scsi/xen-scsifront.c +@@ -233,12 +233,11 @@ static void scsifront_gnttab_done(struct vscsifrnt_info *info, + return; + + for (i = 0; i < shadow->nr_grants; i++) { +- if (unlikely(gnttab_query_foreign_access(shadow->gref[i]))) { ++ if (unlikely(!gnttab_try_end_foreign_access(shadow->gref[i]))) { + shost_printk(KERN_ALERT, info->host, KBUILD_MODNAME + "grant still in use by backend\n"); + BUG(); + } +- gnttab_end_foreign_access(shadow->gref[i], 0, 0UL); + } + + kfree(shadow->sg); +diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c +index bd0fbcdbdefe9..e24e220e56eea 100644 +--- a/drivers/sh/maple/maple.c ++++ b/drivers/sh/maple/maple.c +@@ -834,8 +834,10 @@ static int __init maple_bus_init(void) + + maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN); + +- if (!maple_queue_cache) ++ if (!maple_queue_cache) { ++ retval = -ENOMEM; + goto cleanup_bothirqs; ++ } + + INIT_LIST_HEAD(&maple_waitq); + INIT_LIST_HEAD(&maple_sentq); +@@ -848,6 +850,7 @@ static int __init maple_bus_init(void) + if (!mdev[i]) { + while (i-- > 0) + maple_free_dev(mdev[i]); ++ retval = -ENOMEM; + goto cleanup_cache; + } + baseunits[i] = mdev[i]; +diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c +index 72771e018c42e..258894ed234b3 100644 +--- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c ++++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c +@@ -306,10 +306,9 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) + } + + lpc_ctrl->clk = devm_clk_get(dev, NULL); +- if (IS_ERR(lpc_ctrl->clk)) { +- dev_err(dev, "couldn't get clock\n"); +- return PTR_ERR(lpc_ctrl->clk); +- } ++ if (IS_ERR(lpc_ctrl->clk)) ++ return dev_err_probe(dev, PTR_ERR(lpc_ctrl->clk), ++ "couldn't get clock\n"); + rc = clk_prepare_enable(lpc_ctrl->clk); + if (rc) { + dev_err(dev, "couldn't enable clock\n"); +diff --git a/drivers/soc/fsl/dpaa2-console.c b/drivers/soc/fsl/dpaa2-console.c +index 27243f706f376..53917410f2bdb 100644 +--- a/drivers/soc/fsl/dpaa2-console.c ++++ b/drivers/soc/fsl/dpaa2-console.c +@@ -231,6 +231,7 @@ static ssize_t dpaa2_console_read(struct file *fp, char __user *buf, + cd->cur_ptr += bytes; + written += bytes; + ++ kfree(kbuf); + return written; + + err_free_buf: +diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c +index 7351f30305506..779c319a4b820 100644 +--- a/drivers/soc/fsl/dpio/dpio-service.c ++++ b/drivers/soc/fsl/dpio/dpio-service.c +@@ -59,7 +59,7 @@ static inline struct dpaa2_io *service_select_by_cpu(struct dpaa2_io *d, + * potentially being migrated away. + */ + if (cpu < 0) +- cpu = smp_processor_id(); ++ cpu = raw_smp_processor_id(); + + /* If a specific cpu was requested, pick it up immediately */ + return dpio_by_cpu[cpu]; +diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c +index f13da4d7d1c52..3ec8ab08b9889 100644 +--- a/drivers/soc/fsl/dpio/qbman-portal.c ++++ b/drivers/soc/fsl/dpio/qbman-portal.c +@@ -732,8 +732,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, + int i, num_enqueued = 0; + unsigned long irq_flags; + +- spin_lock(&s->access_spinlock); +- local_irq_save(irq_flags); ++ spin_lock_irqsave(&s->access_spinlock, irq_flags); + + half_mask = (s->eqcr.pi_ci_mask>>1); + full_mask = s->eqcr.pi_ci_mask; +@@ -744,8 +743,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, + s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size, + eqcr_ci, s->eqcr.ci); + if (!s->eqcr.available) { +- local_irq_restore(irq_flags); +- spin_unlock(&s->access_spinlock); ++ spin_unlock_irqrestore(&s->access_spinlock, irq_flags); + return 0; + } + } +@@ -784,8 +782,7 @@ int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s, + dma_wmb(); + qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI, + (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb); +- local_irq_restore(irq_flags); +- spin_unlock(&s->access_spinlock); ++ spin_unlock_irqrestore(&s->access_spinlock, irq_flags); + + return num_enqueued; + } +diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c +index d5e9a5f2c0874..75eabfb916cb5 100644 +--- a/drivers/soc/fsl/guts.c ++++ b/drivers/soc/fsl/guts.c +@@ -28,7 +28,6 @@ struct fsl_soc_die_attr { + static struct guts *guts; + static struct soc_device_attribute soc_dev_attr; + static struct soc_device *soc_dev; +-static struct device_node *root; + + + /* SoC die attribute definition for QorIQ platform */ +@@ -138,7 +137,7 @@ static u32 fsl_guts_get_svr(void) + + static int fsl_guts_probe(struct platform_device *pdev) + { +- struct device_node *np = pdev->dev.of_node; ++ struct device_node *root, *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct resource *res; + const struct fsl_soc_die_attr *soc_die; +@@ -161,8 +160,14 @@ static int fsl_guts_probe(struct platform_device *pdev) + root = of_find_node_by_path("/"); + if (of_property_read_string(root, "model", &machine)) + of_property_read_string_index(root, "compatible", 0, &machine); +- if (machine) +- soc_dev_attr.machine = machine; ++ if (machine) { ++ soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL); ++ if (!soc_dev_attr.machine) { ++ of_node_put(root); ++ return -ENOMEM; ++ } ++ } ++ of_node_put(root); + + svr = fsl_guts_get_svr(); + soc_die = fsl_soc_die_match(svr, fsl_soc_die); +@@ -197,7 +202,6 @@ static int fsl_guts_probe(struct platform_device *pdev) + static int fsl_guts_remove(struct platform_device *dev) + { + soc_device_unregister(soc_dev); +- of_node_put(root); + return 0; + } + +diff --git a/drivers/soc/fsl/qe/qe_io.c b/drivers/soc/fsl/qe/qe_io.c +index e277c827bdf33..a5e2d0e5ab511 100644 +--- a/drivers/soc/fsl/qe/qe_io.c ++++ b/drivers/soc/fsl/qe/qe_io.c +@@ -35,6 +35,8 @@ int par_io_init(struct device_node *np) + if (ret) + return ret; + par_io = ioremap(res.start, resource_size(&res)); ++ if (!par_io) ++ return -ENOMEM; + + if (!of_property_read_u32(np, "num-ports", &num_ports)) + num_par_io_ports = num_ports; +diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c +index 34a9ac1f2b9b1..b4aa28420f2a8 100644 +--- a/drivers/soc/imx/gpcv2.c ++++ b/drivers/soc/imx/gpcv2.c +@@ -244,6 +244,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) + goto out_regulator_disable; + } + ++ reset_control_assert(domain->reset); ++ + if (domain->bits.pxx) { + /* request the domain to power up */ + regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ, +@@ -266,8 +268,6 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd) + GPC_PGC_CTRL_PCR); + } + +- reset_control_assert(domain->reset); +- + /* delay for reset to propagate */ + udelay(5); + +@@ -369,7 +369,7 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd) + } + } + +- pm_runtime_put(domain->dev); ++ pm_runtime_put_sync_suspend(domain->dev); + + return 0; + +diff --git a/drivers/soc/imx/soc-imx.c b/drivers/soc/imx/soc-imx.c +index ac6d856ba228d..77bc12039c3d4 100644 +--- a/drivers/soc/imx/soc-imx.c ++++ b/drivers/soc/imx/soc-imx.c +@@ -36,6 +36,10 @@ static int __init imx_soc_device_init(void) + int ret; + int i; + ++ /* Return early if this is running on devices with different SoCs */ ++ if (!__mxc_cpu_type) ++ return 0; ++ + if (of_machine_is_compatible("fsl,ls1021a")) + return 0; + +diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c +index 475a57b435b24..2e455d9e3d94a 100644 +--- a/drivers/soc/qcom/apr.c ++++ b/drivers/soc/qcom/apr.c +@@ -321,12 +321,14 @@ static int of_apr_add_pd_lookups(struct device *dev) + 1, &service_path); + if (ret < 0) { + dev_err(dev, "pdr service path missing: %d\n", ret); ++ of_node_put(node); + return ret; + } + + pds = pdr_add_lookup(apr->pdr, service_name, service_path); + if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) { + dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds)); ++ of_node_put(node); + return PTR_ERR(pds); + } + } +diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c +index 4ce8e816154f9..84dd93472a252 100644 +--- a/drivers/soc/qcom/cpr.c ++++ b/drivers/soc/qcom/cpr.c +@@ -1010,7 +1010,7 @@ static int cpr_interpolate(const struct corner *corner, int step_volt, + return corner->uV; + + temp = f_diff * (uV_high - uV_low); +- do_div(temp, f_high - f_low); ++ temp = div64_ul(temp, f_high - f_low); + + /* + * max_volt_scale has units of uV/MHz while freq values +diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c +index 15a36dcab990e..e53109a5c3da9 100644 +--- a/drivers/soc/qcom/llcc-qcom.c ++++ b/drivers/soc/qcom/llcc-qcom.c +@@ -115,7 +115,7 @@ static const struct llcc_slice_config sc7280_data[] = { + { LLCC_CMPT, 10, 768, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, + { LLCC_GPUHTW, 11, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, + { LLCC_GPU, 12, 512, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, +- { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 1, 0}, ++ { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 0, 1, 0}, + { LLCC_MDMPNG, 21, 768, 0, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, + { LLCC_WLHW, 24, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, + { LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0}, +diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c +index fa209b479ab35..d98cc8c2e5d5c 100644 +--- a/drivers/soc/qcom/rpmhpd.c ++++ b/drivers/soc/qcom/rpmhpd.c +@@ -30,6 +30,7 @@ + * @active_only: True if it represents an Active only peer + * @corner: current corner + * @active_corner: current active corner ++ * @enable_corner: lowest non-zero corner + * @level: An array of level (vlvl) to corner (hlvl) mappings + * derived from cmd-db + * @level_count: Number of levels supported by the power domain. max +@@ -47,6 +48,7 @@ struct rpmhpd { + const bool active_only; + unsigned int corner; + unsigned int active_corner; ++ unsigned int enable_corner; + u32 level[RPMH_ARC_MAX_LEVELS]; + size_t level_count; + bool enabled; +@@ -204,7 +206,7 @@ static const struct rpmhpd_desc sm8250_desc = { + static struct rpmhpd sm8350_mxc_ao; + static struct rpmhpd sm8350_mxc = { + .pd = { .name = "mxc", }, +- .peer = &sm8150_mmcx_ao, ++ .peer = &sm8350_mxc_ao, + .res_name = "mxc.lvl", + }; + +@@ -385,13 +387,13 @@ static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner) + static int rpmhpd_power_on(struct generic_pm_domain *domain) + { + struct rpmhpd *pd = domain_to_rpmhpd(domain); +- int ret = 0; ++ unsigned int corner; ++ int ret; + + mutex_lock(&rpmhpd_lock); + +- if (pd->corner) +- ret = rpmhpd_aggregate_corner(pd, pd->corner); +- ++ corner = max(pd->corner, pd->enable_corner); ++ ret = rpmhpd_aggregate_corner(pd, corner); + if (!ret) + pd->enabled = true; + +@@ -436,6 +438,10 @@ static int rpmhpd_set_performance_state(struct generic_pm_domain *domain, + i--; + + if (pd->enabled) { ++ /* Ensure that the domain isn't turn off */ ++ if (i < pd->enable_corner) ++ i = pd->enable_corner; ++ + ret = rpmhpd_aggregate_corner(pd, i); + if (ret) + goto out; +@@ -472,6 +478,10 @@ static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd) + for (i = 0; i < rpmhpd->level_count; i++) { + rpmhpd->level[i] = buf[i]; + ++ /* Remember the first corner with non-zero level */ ++ if (!rpmhpd->level[rpmhpd->enable_corner] && rpmhpd->level[i]) ++ rpmhpd->enable_corner = i; ++ + /* + * The AUX data may be zero padded. These 0 valued entries at + * the end of the map must be ignored. +diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c +index 52e5811671155..5beb452f24013 100644 +--- a/drivers/soc/qcom/socinfo.c ++++ b/drivers/soc/qcom/socinfo.c +@@ -87,8 +87,8 @@ static const char *const pmic_models[] = { + [15] = "PM8901", + [16] = "PM8950/PM8027", + [17] = "PMI8950/ISL9519", +- [18] = "PM8921", +- [19] = "PM8018", ++ [18] = "PMK8001/PM8921", ++ [19] = "PMI8996/PM8018", + [20] = "PM8998/PM8015", + [21] = "PMI8998/PM8014", + [22] = "PM8821", +diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig +index 5745d7e5908e9..1f643c0f5c93f 100644 +--- a/drivers/soc/samsung/Kconfig ++++ b/drivers/soc/samsung/Kconfig +@@ -25,6 +25,7 @@ config EXYNOS_PMU + bool "Exynos PMU controller driver" if COMPILE_TEST + depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST) + select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS ++ select MFD_CORE + + # There is no need to enable these drivers for ARMv8 + config EXYNOS_PMU_ARM_DRIVERS +diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c +index f2151815db585..e714ed3b61bc3 100644 +--- a/drivers/soc/tegra/fuse/fuse-tegra.c ++++ b/drivers/soc/tegra/fuse/fuse-tegra.c +@@ -320,7 +320,7 @@ static struct platform_driver tegra_fuse_driver = { + }; + builtin_platform_driver(tegra_fuse_driver); + +-bool __init tegra_fuse_read_spare(unsigned int spare) ++u32 __init tegra_fuse_read_spare(unsigned int spare) + { + unsigned int offset = fuse->soc->info->spare + spare * 4; + +diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h +index de58feba04350..ecff0c08e9595 100644 +--- a/drivers/soc/tegra/fuse/fuse.h ++++ b/drivers/soc/tegra/fuse/fuse.h +@@ -65,7 +65,7 @@ struct tegra_fuse { + void tegra_init_revision(void); + void tegra_init_apbmisc(void); + +-bool __init tegra_fuse_read_spare(unsigned int spare); ++u32 __init tegra_fuse_read_spare(unsigned int spare); + u32 __init tegra_fuse_read_early(unsigned int offset); + + u8 tegra_get_major_rev(void); +diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c +index 50091c4ec9481..a60e142ade344 100644 +--- a/drivers/soc/tegra/pmc.c ++++ b/drivers/soc/tegra/pmc.c +@@ -782,7 +782,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, + + err = reset_control_deassert(pg->reset); + if (err) +- goto powergate_off; ++ goto disable_clks; + + usleep_range(10, 20); + +diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c +index 49da387d77494..b36779309e49b 100644 +--- a/drivers/soc/ti/pruss.c ++++ b/drivers/soc/ti/pruss.c +@@ -129,7 +129,7 @@ static int pruss_clk_init(struct pruss *pruss, struct device_node *cfg_node) + + clks_np = of_get_child_by_name(cfg_node, "clocks"); + if (!clks_np) { +- dev_err(dev, "%pOF is missing its 'clocks' node\n", clks_np); ++ dev_err(dev, "%pOF is missing its 'clocks' node\n", cfg_node); + return -ENODEV; + } + +diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c +index 1b115734a8f6b..67369e941d0d6 100644 +--- a/drivers/soundwire/bus.c ++++ b/drivers/soundwire/bus.c +@@ -1110,7 +1110,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) + if (!simple_clk_stop) { + ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + if (ret < 0) +- dev_warn(&slave->dev, "clock stop deprepare wait failed:%d\n", ret); ++ dev_warn(bus->dev, "clock stop deprepare wait failed:%d\n", ret); + } + + list_for_each_entry(slave, &bus->slaves, node) { +diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c +index b6cad0d59b7b9..49900cd207bc7 100644 +--- a/drivers/soundwire/debugfs.c ++++ b/drivers/soundwire/debugfs.c +@@ -19,7 +19,7 @@ void sdw_bus_debugfs_init(struct sdw_bus *bus) + return; + + /* create the debugfs master-N */ +- snprintf(name, sizeof(name), "master-%d", bus->link_id); ++ snprintf(name, sizeof(name), "master-%d-%d", bus->id, bus->link_id); + bus->debugfs = debugfs_create_dir(name, sdw_debugfs_root); + } + +diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c +index 95d4fa32c2995..92d9610df1fd8 100644 +--- a/drivers/spi/atmel-quadspi.c ++++ b/drivers/spi/atmel-quadspi.c +@@ -310,7 +310,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, + return mode; + ifr |= atmel_qspi_modes[mode].config; + +- if (op->dummy.buswidth && op->dummy.nbytes) ++ if (op->dummy.nbytes) + dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth; + + /* +diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c +index 46feafe4e201c..d8cc4b270644a 100644 +--- a/drivers/spi/spi-armada-3700.c ++++ b/drivers/spi/spi-armada-3700.c +@@ -901,7 +901,7 @@ static int a3700_spi_probe(struct platform_device *pdev) + return 0; + + error_clk: +- clk_disable_unprepare(spi->clk); ++ clk_unprepare(spi->clk); + error: + spi_master_put(master); + out: +diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c +index 3043677ba2226..ae8c86be77869 100644 +--- a/drivers/spi/spi-bcm-qspi.c ++++ b/drivers/spi/spi-bcm-qspi.c +@@ -395,7 +395,8 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, + if (addrlen == BSPI_ADDRLEN_4BYTES) + bpp = BSPI_BPP_ADDR_SELECT_MASK; + +- bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth; ++ if (op->dummy.nbytes) ++ bpp |= (op->dummy.nbytes * 8) / op->dummy.buswidth; + + switch (width) { + case SPI_NBITS_SINGLE: +@@ -551,7 +552,7 @@ static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs) + u32 rd = 0; + u32 wr = 0; + +- if (qspi->base[CHIP_SELECT]) { ++ if (cs >= 0 && qspi->base[CHIP_SELECT]) { + rd = bcm_qspi_read(qspi, CHIP_SELECT, 0); + wr = (rd & ~0xff) | (1 << cs); + if (rd == wr) +@@ -1460,7 +1461,7 @@ int bcm_qspi_probe(struct platform_device *pdev, + &qspi->dev_ids[val]); + if (ret < 0) { + dev_err(&pdev->dev, "IRQ %s not found\n", name); +- goto qspi_probe_err; ++ goto qspi_unprepare_err; + } + + qspi->dev_ids[val].dev = qspi; +@@ -1475,7 +1476,7 @@ int bcm_qspi_probe(struct platform_device *pdev, + if (!num_ints) { + dev_err(&pdev->dev, "no IRQs registered, cannot init driver\n"); + ret = -EINVAL; +- goto qspi_probe_err; ++ goto qspi_unprepare_err; + } + + bcm_qspi_hw_init(qspi); +@@ -1499,6 +1500,7 @@ int bcm_qspi_probe(struct platform_device *pdev, + + qspi_reg_err: + bcm_qspi_hw_uninit(qspi); ++qspi_unprepare_err: + clk_disable_unprepare(qspi->clk); + qspi_probe_err: + kfree(qspi->dev_ids); +diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c +index 58b823a16fc4d..525cc0143a305 100644 +--- a/drivers/spi/spi-hisi-kunpeng.c ++++ b/drivers/spi/spi-hisi-kunpeng.c +@@ -127,7 +127,6 @@ struct hisi_spi { + void __iomem *regs; + int irq; + u32 fifo_len; /* depth of the FIFO buffer */ +- u16 bus_num; + + /* Current message transfer state info */ + const void *tx; +@@ -165,7 +164,10 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs) + { + char name[32]; + +- snprintf(name, 32, "hisi_spi%d", hs->bus_num); ++ struct spi_controller *master; ++ ++ master = container_of(hs->dev, struct spi_controller, dev); ++ snprintf(name, 32, "hisi_spi%d", master->bus_num); + hs->debugfs = debugfs_create_dir(name, NULL); + if (!hs->debugfs) + return -ENOMEM; +@@ -467,7 +469,6 @@ static int hisi_spi_probe(struct platform_device *pdev) + hs = spi_controller_get_devdata(master); + hs->dev = dev; + hs->irq = irq; +- hs->bus_num = pdev->id; + + hs->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hs->regs)) +@@ -490,7 +491,7 @@ static int hisi_spi_probe(struct platform_device *pdev) + master->use_gpio_descriptors = true; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); +- master->bus_num = hs->bus_num; ++ master->bus_num = pdev->id; + master->setup = hisi_spi_setup; + master->cleanup = hisi_spi_cleanup; + master->transfer_one = hisi_spi_transfer_one; +@@ -506,15 +507,15 @@ static int hisi_spi_probe(struct platform_device *pdev) + return ret; + } + +- if (hisi_spi_debugfs_init(hs)) +- dev_info(dev, "failed to create debugfs dir\n"); +- + ret = spi_register_controller(master); + if (ret) { + dev_err(dev, "failed to register spi master, ret=%d\n", ret); + return ret; + } + ++ if (hisi_spi_debugfs_init(hs)) ++ dev_info(dev, "failed to create debugfs dir\n"); ++ + dev_info(dev, "hw version:0x%x max-freq:%u kHz\n", + readl(hs->regs + HISI_SPI_VERSION), + master->max_speed_hz / 1000); +diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c +index c208efeadd184..0bc7daa7afc83 100644 +--- a/drivers/spi/spi-meson-spicc.c ++++ b/drivers/spi/spi-meson-spicc.c +@@ -693,6 +693,11 @@ static int meson_spicc_probe(struct platform_device *pdev) + writel_relaxed(0, spicc->base + SPICC_INTREG); + + irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ ret = irq; ++ goto out_master; ++ } ++ + ret = devm_request_irq(&pdev->dev, irq, meson_spicc_irq, + 0, NULL, spicc); + if (ret) { +diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c +index 8eca6f24cb799..c8ed7815c4ba6 100644 +--- a/drivers/spi/spi-meson-spifc.c ++++ b/drivers/spi/spi-meson-spifc.c +@@ -349,6 +349,7 @@ static int meson_spifc_probe(struct platform_device *pdev) + return 0; + out_clk: + clk_disable_unprepare(spifc->clk); ++ pm_runtime_disable(spifc->dev); + out_err: + spi_master_put(master); + return ret; +diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c +index a15de10ee286a..753bd313e6fda 100644 +--- a/drivers/spi/spi-mt65xx.c ++++ b/drivers/spi/spi-mt65xx.c +@@ -624,7 +624,7 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) + else + mdata->state = MTK_SPI_IDLE; + +- if (!master->can_dma(master, master->cur_msg->spi, trans)) { ++ if (!master->can_dma(master, NULL, trans)) { + if (trans->rx_buf) { + cnt = mdata->xfer_len / 4; + ioread32_rep(mdata->base + SPI_RX_DATA_REG, +diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c +index 41e7b341d2616..5c93730615f8d 100644 +--- a/drivers/spi/spi-mtk-nor.c ++++ b/drivers/spi/spi-mtk-nor.c +@@ -160,7 +160,7 @@ static bool mtk_nor_match_read(const struct spi_mem_op *op) + { + int dummy = 0; + +- if (op->dummy.buswidth) ++ if (op->dummy.nbytes) + dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth; + + if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) { +diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c +index c53138ce00309..83796a4ead34a 100644 +--- a/drivers/spi/spi-rpc-if.c ++++ b/drivers/spi/spi-rpc-if.c +@@ -139,7 +139,9 @@ static int rpcif_spi_probe(struct platform_device *pdev) + return -ENOMEM; + + rpc = spi_controller_get_devdata(ctlr); +- rpcif_sw_init(rpc, parent); ++ error = rpcif_sw_init(rpc, parent); ++ if (error) ++ return error; + + platform_set_drvdata(pdev, ctlr); + +diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c +index 27f35aa2d746d..ffdc55f87e821 100644 +--- a/drivers/spi/spi-stm32-qspi.c ++++ b/drivers/spi/spi-stm32-qspi.c +@@ -397,7 +397,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) + ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1); + } + +- if (op->dummy.buswidth && op->dummy.nbytes) ++ if (op->dummy.nbytes) + ccr |= FIELD_PREP(CCR_DCYC_MASK, + op->dummy.nbytes * 8 / op->dummy.buswidth); + +@@ -688,7 +688,7 @@ static int stm32_qspi_probe(struct platform_device *pdev) + struct resource *res; + int ret, irq; + +- ctrl = spi_alloc_master(dev, sizeof(*qspi)); ++ ctrl = devm_spi_alloc_master(dev, sizeof(*qspi)); + if (!ctrl) + return -ENOMEM; + +@@ -697,58 +697,46 @@ static int stm32_qspi_probe(struct platform_device *pdev) + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi"); + qspi->io_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(qspi->io_base)) { +- ret = PTR_ERR(qspi->io_base); +- goto err_master_put; +- } ++ if (IS_ERR(qspi->io_base)) ++ return PTR_ERR(qspi->io_base); + + qspi->phys_base = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm"); + qspi->mm_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(qspi->mm_base)) { +- ret = PTR_ERR(qspi->mm_base); +- goto err_master_put; +- } ++ if (IS_ERR(qspi->mm_base)) ++ return PTR_ERR(qspi->mm_base); + + qspi->mm_size = resource_size(res); +- if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ) { +- ret = -EINVAL; +- goto err_master_put; +- } ++ if (qspi->mm_size > STM32_QSPI_MAX_MMAP_SZ) ++ return -EINVAL; + + irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- ret = irq; +- goto err_master_put; +- } ++ if (irq < 0) ++ return irq; + + ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, + dev_name(dev), qspi); + if (ret) { + dev_err(dev, "failed to request irq\n"); +- goto err_master_put; ++ return ret; + } + + init_completion(&qspi->data_completion); + init_completion(&qspi->match_completion); + + qspi->clk = devm_clk_get(dev, NULL); +- if (IS_ERR(qspi->clk)) { +- ret = PTR_ERR(qspi->clk); +- goto err_master_put; +- } ++ if (IS_ERR(qspi->clk)) ++ return PTR_ERR(qspi->clk); + + qspi->clk_rate = clk_get_rate(qspi->clk); +- if (!qspi->clk_rate) { +- ret = -EINVAL; +- goto err_master_put; +- } ++ if (!qspi->clk_rate) ++ return -EINVAL; + + ret = clk_prepare_enable(qspi->clk); + if (ret) { + dev_err(dev, "can not enable the clock\n"); +- goto err_master_put; ++ return ret; + } + + rstc = devm_reset_control_get_exclusive(dev, NULL); +@@ -784,7 +772,7 @@ static int stm32_qspi_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + pm_runtime_get_noresume(dev); + +- ret = devm_spi_register_master(dev, ctrl); ++ ret = spi_register_master(ctrl); + if (ret) + goto err_pm_runtime_free; + +@@ -806,8 +794,6 @@ err_dma_free: + stm32_qspi_dma_free(qspi); + err_clk_disable: + clk_disable_unprepare(qspi->clk); +-err_master_put: +- spi_master_put(qspi->ctrl); + + return ret; + } +@@ -817,6 +803,7 @@ static int stm32_qspi_remove(struct platform_device *pdev) + struct stm32_qspi *qspi = platform_get_drvdata(pdev); + + pm_runtime_get_sync(qspi->dev); ++ spi_unregister_master(qspi->ctrl); + /* disable qspi */ + writel_relaxed(0, qspi->io_base + QSPI_CR); + stm32_qspi_dma_free(qspi); +diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c +index 8900e51e1a1cc..cc0da48222311 100644 +--- a/drivers/spi/spi-uniphier.c ++++ b/drivers/spi/spi-uniphier.c +@@ -726,7 +726,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) + if (ret) { + dev_err(&pdev->dev, "failed to get TX DMA capacities: %d\n", + ret); +- goto out_disable_clk; ++ goto out_release_dma; + } + dma_tx_burst = caps.max_burst; + } +@@ -735,7 +735,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) + if (IS_ERR_OR_NULL(master->dma_rx)) { + if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; +- goto out_disable_clk; ++ goto out_release_dma; + } + master->dma_rx = NULL; + dma_rx_burst = INT_MAX; +@@ -744,7 +744,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) + if (ret) { + dev_err(&pdev->dev, "failed to get RX DMA capacities: %d\n", + ret); +- goto out_disable_clk; ++ goto out_release_dma; + } + dma_rx_burst = caps.max_burst; + } +@@ -753,10 +753,20 @@ static int uniphier_spi_probe(struct platform_device *pdev) + + ret = devm_spi_register_master(&pdev->dev, master); + if (ret) +- goto out_disable_clk; ++ goto out_release_dma; + + return 0; + ++out_release_dma: ++ if (!IS_ERR_OR_NULL(master->dma_rx)) { ++ dma_release_channel(master->dma_rx); ++ master->dma_rx = NULL; ++ } ++ if (!IS_ERR_OR_NULL(master->dma_tx)) { ++ dma_release_channel(master->dma_tx); ++ master->dma_tx = NULL; ++ } ++ + out_disable_clk: + clk_disable_unprepare(priv->clk); + +@@ -767,12 +777,13 @@ out_master_put: + + static int uniphier_spi_remove(struct platform_device *pdev) + { +- struct uniphier_spi_priv *priv = platform_get_drvdata(pdev); ++ struct spi_master *master = platform_get_drvdata(pdev); ++ struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + +- if (priv->master->dma_tx) +- dma_release_channel(priv->master->dma_tx); +- if (priv->master->dma_rx) +- dma_release_channel(priv->master->dma_rx); ++ if (master->dma_tx) ++ dma_release_channel(master->dma_tx); ++ if (master->dma_rx) ++ dma_release_channel(master->dma_rx); + + clk_disable_unprepare(priv->clk); + +diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c +index cfa222c9bd5e7..78f31b61a2aac 100644 +--- a/drivers/spi/spi-zynq-qspi.c ++++ b/drivers/spi/spi-zynq-qspi.c +@@ -570,6 +570,9 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem, + + if (op->dummy.nbytes) { + tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL); ++ if (!tmpbuf) ++ return -ENOMEM; ++ + memset(tmpbuf, 0xff, op->dummy.nbytes); + reinit_completion(&xqspi->data_completion); + xqspi->txbuf = tmpbuf; +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 926b68aa45d3e..a42b9e8521ce0 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -451,6 +451,47 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) + { + sdrv->driver.owner = owner; + sdrv->driver.bus = &spi_bus_type; ++ ++ /* ++ * For Really Good Reasons we use spi: modaliases not of: ++ * modaliases for DT so module autoloading won't work if we ++ * don't have a spi_device_id as well as a compatible string. ++ */ ++ if (sdrv->driver.of_match_table) { ++ const struct of_device_id *of_id; ++ ++ for (of_id = sdrv->driver.of_match_table; of_id->compatible[0]; ++ of_id++) { ++ const char *of_name; ++ ++ /* Strip off any vendor prefix */ ++ of_name = strnchr(of_id->compatible, ++ sizeof(of_id->compatible), ','); ++ if (of_name) ++ of_name++; ++ else ++ of_name = of_id->compatible; ++ ++ if (sdrv->id_table) { ++ const struct spi_device_id *spi_id; ++ ++ for (spi_id = sdrv->id_table; spi_id->name[0]; ++ spi_id++) ++ if (strcmp(spi_id->name, of_name) == 0) ++ break; ++ ++ if (spi_id->name[0]) ++ continue; ++ } else { ++ if (strcmp(sdrv->driver.name, of_name) == 0) ++ continue; ++ } ++ ++ pr_warn("SPI driver %s has no spi_device_id for %s\n", ++ sdrv->driver.name, of_id->compatible); ++ } ++ } ++ + return driver_register(&sdrv->driver); + } + EXPORT_SYMBOL_GPL(__spi_register_driver); +@@ -827,12 +868,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) + spi->controller->last_cs_enable = enable; + spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; + +- if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || +- !spi->controller->set_cs_timing) { +- if (activate) +- spi_delay_exec(&spi->cs_setup, NULL); +- else +- spi_delay_exec(&spi->cs_hold, NULL); ++ if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || ++ !spi->controller->set_cs_timing) && !activate) { ++ spi_delay_exec(&spi->cs_hold, NULL); + } + + if (spi->mode & SPI_CS_HIGH) +@@ -874,7 +912,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) + + if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || + !spi->controller->set_cs_timing) { +- if (!activate) ++ if (activate) ++ spi_delay_exec(&spi->cs_setup, NULL); ++ else + spi_delay_exec(&spi->cs_inactive, NULL); + } + } +@@ -2979,12 +3019,6 @@ void spi_unregister_controller(struct spi_controller *ctlr) + + device_del(&ctlr->dev); + +- /* Release the last reference on the controller if its driver +- * has not yet been converted to devm_spi_alloc_master/slave(). +- */ +- if (!ctlr->devm_allocated) +- put_device(&ctlr->dev); +- + /* free bus id */ + mutex_lock(&board_lock); + if (found == ctlr) +@@ -2993,6 +3027,12 @@ void spi_unregister_controller(struct spi_controller *ctlr) + + if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) + mutex_unlock(&ctlr->add_lock); ++ ++ /* Release the last reference on the controller if its driver ++ * has not yet been converted to devm_spi_alloc_master/slave(). ++ */ ++ if (!ctlr->devm_allocated) ++ put_device(&ctlr->dev); + } + EXPORT_SYMBOL_GPL(spi_unregister_controller); + +diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c +index cf263a58a1489..6fd549a424d53 100644 +--- a/drivers/staging/fbtft/fb_ssd1351.c ++++ b/drivers/staging/fbtft/fb_ssd1351.c +@@ -187,7 +187,6 @@ static struct fbtft_display display = { + }, + }; + +-#ifdef CONFIG_FB_BACKLIGHT + static int update_onboard_backlight(struct backlight_device *bd) + { + struct fbtft_par *par = bl_get_data(bd); +@@ -231,9 +230,6 @@ static void register_onboard_backlight(struct fbtft_par *par) + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; + } +-#else +-static void register_onboard_backlight(struct fbtft_par *par) { }; +-#endif + + FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1351", &display); + +diff --git a/drivers/staging/fbtft/fb_st7789v.c b/drivers/staging/fbtft/fb_st7789v.c +index abe9395a0aefd..861a154144e66 100644 +--- a/drivers/staging/fbtft/fb_st7789v.c ++++ b/drivers/staging/fbtft/fb_st7789v.c +@@ -144,6 +144,8 @@ static int init_display(struct fbtft_par *par) + { + int rc; + ++ par->fbtftops.reset(par); ++ + rc = init_tearing_effect_line(par); + if (rc) + return rc; +diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c +index ed992ca605ebe..1690358b8f018 100644 +--- a/drivers/staging/fbtft/fbtft-core.c ++++ b/drivers/staging/fbtft/fbtft-core.c +@@ -128,7 +128,6 @@ static int fbtft_request_gpios(struct fbtft_par *par) + return 0; + } + +-#ifdef CONFIG_FB_BACKLIGHT + static int fbtft_backlight_update_status(struct backlight_device *bd) + { + struct fbtft_par *par = bl_get_data(bd); +@@ -161,6 +160,7 @@ void fbtft_unregister_backlight(struct fbtft_par *par) + par->info->bl_dev = NULL; + } + } ++EXPORT_SYMBOL(fbtft_unregister_backlight); + + static const struct backlight_ops fbtft_bl_ops = { + .get_brightness = fbtft_backlight_get_brightness, +@@ -198,12 +198,7 @@ void fbtft_register_backlight(struct fbtft_par *par) + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; + } +-#else +-void fbtft_register_backlight(struct fbtft_par *par) { }; +-void fbtft_unregister_backlight(struct fbtft_par *par) { }; +-#endif + EXPORT_SYMBOL(fbtft_register_backlight); +-EXPORT_SYMBOL(fbtft_unregister_backlight); + + static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, + int ye) +@@ -853,13 +848,11 @@ int fbtft_register_framebuffer(struct fb_info *fb_info) + fb_info->fix.smem_len >> 10, text1, + HZ / fb_info->fbdefio->delay, text2); + +-#ifdef CONFIG_FB_BACKLIGHT + /* Turn on backlight if available */ + if (fb_info->bl_dev) { + fb_info->bl_dev->props.power = FB_BLANK_UNBLANK; + fb_info->bl_dev->ops->update_status(fb_info->bl_dev); + } +-#endif + + return 0; + +diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h +index 76f8c090a8370..06afaa9d505ba 100644 +--- a/drivers/staging/fbtft/fbtft.h ++++ b/drivers/staging/fbtft/fbtft.h +@@ -332,7 +332,10 @@ static int __init fbtft_driver_module_init(void) \ + ret = spi_register_driver(&fbtft_driver_spi_driver); \ + if (ret < 0) \ + return ret; \ +- return platform_driver_register(&fbtft_driver_platform_driver); \ ++ ret = platform_driver_register(&fbtft_driver_platform_driver); \ ++ if (ret < 0) \ ++ spi_unregister_driver(&fbtft_driver_spi_driver); \ ++ return ret; \ + } \ + \ + static void __exit fbtft_driver_module_exit(void) \ +diff --git a/drivers/staging/greybus/audio_helper.c b/drivers/staging/greybus/audio_helper.c +index 1ed4772d27715..843760675876a 100644 +--- a/drivers/staging/greybus/audio_helper.c ++++ b/drivers/staging/greybus/audio_helper.c +@@ -192,7 +192,11 @@ int gbaudio_remove_component_controls(struct snd_soc_component *component, + unsigned int num_controls) + { + struct snd_card *card = component->card->snd_card; ++ int err; + +- return gbaudio_remove_controls(card, component->dev, controls, +- num_controls, component->name_prefix); ++ down_write(&card->controls_rwsem); ++ err = gbaudio_remove_controls(card, component->dev, controls, ++ num_controls, component->name_prefix); ++ up_write(&card->controls_rwsem); ++ return err; + } +diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c +index 1e613d42d8237..62d7674852bec 100644 +--- a/drivers/staging/greybus/audio_topology.c ++++ b/drivers/staging/greybus/audio_topology.c +@@ -147,6 +147,9 @@ static const char **gb_generate_enum_strings(struct gbaudio_module_info *gb, + + items = le32_to_cpu(gbenum->items); + strings = devm_kcalloc(gb->dev, items, sizeof(char *), GFP_KERNEL); ++ if (!strings) ++ return NULL; ++ + data = gbenum->names; + + for (i = 0; i < items; i++) { +@@ -655,6 +658,8 @@ static int gbaudio_tplg_create_enum_kctl(struct gbaudio_module_info *gb, + /* since count=1, and reg is dummy */ + gbe->items = le32_to_cpu(gb_enum->items); + gbe->texts = gb_generate_enum_strings(gb, gb_enum); ++ if (!gbe->texts) ++ return -ENOMEM; + + /* debug enum info */ + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->items, +@@ -862,6 +867,8 @@ static int gbaudio_tplg_create_enum_ctl(struct gbaudio_module_info *gb, + /* since count=1, and reg is dummy */ + gbe->items = le32_to_cpu(gb_enum->items); + gbe->texts = gb_generate_enum_strings(gb, gb_enum); ++ if (!gbe->texts) ++ return -ENOMEM; + + /* debug enum info */ + dev_dbg(gb->dev, "Max:%d, name_length:%d\n", gbe->items, +@@ -974,6 +981,44 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, + return ret; + } + ++static const struct snd_soc_dapm_widget gbaudio_widgets[] = { ++ [snd_soc_dapm_spk] = SND_SOC_DAPM_SPK(NULL, gbcodec_event_spk), ++ [snd_soc_dapm_hp] = SND_SOC_DAPM_HP(NULL, gbcodec_event_hp), ++ [snd_soc_dapm_mic] = SND_SOC_DAPM_MIC(NULL, gbcodec_event_int_mic), ++ [snd_soc_dapm_output] = SND_SOC_DAPM_OUTPUT(NULL), ++ [snd_soc_dapm_input] = SND_SOC_DAPM_INPUT(NULL), ++ [snd_soc_dapm_switch] = SND_SOC_DAPM_SWITCH_E(NULL, SND_SOC_NOPM, ++ 0, 0, NULL, ++ gbaudio_widget_event, ++ SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMD), ++ [snd_soc_dapm_pga] = SND_SOC_DAPM_PGA_E(NULL, SND_SOC_NOPM, ++ 0, 0, NULL, 0, ++ gbaudio_widget_event, ++ SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMD), ++ [snd_soc_dapm_mixer] = SND_SOC_DAPM_MIXER_E(NULL, SND_SOC_NOPM, ++ 0, 0, NULL, 0, ++ gbaudio_widget_event, ++ SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMD), ++ [snd_soc_dapm_mux] = SND_SOC_DAPM_MUX_E(NULL, SND_SOC_NOPM, ++ 0, 0, NULL, ++ gbaudio_widget_event, ++ SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMD), ++ [snd_soc_dapm_aif_in] = SND_SOC_DAPM_AIF_IN_E(NULL, NULL, 0, ++ SND_SOC_NOPM, 0, 0, ++ gbaudio_widget_event, ++ SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMD), ++ [snd_soc_dapm_aif_out] = SND_SOC_DAPM_AIF_OUT_E(NULL, NULL, 0, ++ SND_SOC_NOPM, 0, 0, ++ gbaudio_widget_event, ++ SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMD), ++}; ++ + static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, + struct snd_soc_dapm_widget *dw, + struct gb_audio_widget *w, int *w_size) +@@ -1034,6 +1079,10 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, + csize += le16_to_cpu(gbenum->names_length); + control->texts = (const char * const *) + gb_generate_enum_strings(module, gbenum); ++ if (!control->texts) { ++ ret = -ENOMEM; ++ goto error; ++ } + control->items = le32_to_cpu(gbenum->items); + } else { + csize = sizeof(struct gb_audio_control); +@@ -1052,77 +1101,37 @@ static int gbaudio_tplg_create_widget(struct gbaudio_module_info *module, + + switch (w->type) { + case snd_soc_dapm_spk: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_SPK(w->name, gbcodec_event_spk); ++ *dw = gbaudio_widgets[w->type]; + module->op_devices |= GBAUDIO_DEVICE_OUT_SPEAKER; + break; + case snd_soc_dapm_hp: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_HP(w->name, gbcodec_event_hp); ++ *dw = gbaudio_widgets[w->type]; + module->op_devices |= (GBAUDIO_DEVICE_OUT_WIRED_HEADSET + | GBAUDIO_DEVICE_OUT_WIRED_HEADPHONE); + module->ip_devices |= GBAUDIO_DEVICE_IN_WIRED_HEADSET; + break; + case snd_soc_dapm_mic: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_MIC(w->name, gbcodec_event_int_mic); ++ *dw = gbaudio_widgets[w->type]; + module->ip_devices |= GBAUDIO_DEVICE_IN_BUILTIN_MIC; + break; + case snd_soc_dapm_output: +- *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_OUTPUT(w->name); +- break; + case snd_soc_dapm_input: +- *dw = (struct snd_soc_dapm_widget)SND_SOC_DAPM_INPUT(w->name); +- break; + case snd_soc_dapm_switch: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_SWITCH_E(w->name, SND_SOC_NOPM, 0, 0, +- widget_kctls, +- gbaudio_widget_event, +- SND_SOC_DAPM_PRE_PMU | +- SND_SOC_DAPM_POST_PMD); +- break; + case snd_soc_dapm_pga: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_PGA_E(w->name, SND_SOC_NOPM, 0, 0, NULL, 0, +- gbaudio_widget_event, +- SND_SOC_DAPM_PRE_PMU | +- SND_SOC_DAPM_POST_PMD); +- break; + case snd_soc_dapm_mixer: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_MIXER_E(w->name, SND_SOC_NOPM, 0, 0, NULL, +- 0, gbaudio_widget_event, +- SND_SOC_DAPM_PRE_PMU | +- SND_SOC_DAPM_POST_PMD); +- break; + case snd_soc_dapm_mux: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_MUX_E(w->name, SND_SOC_NOPM, 0, 0, +- widget_kctls, gbaudio_widget_event, +- SND_SOC_DAPM_PRE_PMU | +- SND_SOC_DAPM_POST_PMD); ++ *dw = gbaudio_widgets[w->type]; + break; + case snd_soc_dapm_aif_in: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_AIF_IN_E(w->name, w->sname, 0, +- SND_SOC_NOPM, +- 0, 0, gbaudio_widget_event, +- SND_SOC_DAPM_PRE_PMU | +- SND_SOC_DAPM_POST_PMD); +- break; + case snd_soc_dapm_aif_out: +- *dw = (struct snd_soc_dapm_widget) +- SND_SOC_DAPM_AIF_OUT_E(w->name, w->sname, 0, +- SND_SOC_NOPM, +- 0, 0, gbaudio_widget_event, +- SND_SOC_DAPM_PRE_PMU | +- SND_SOC_DAPM_POST_PMD); ++ *dw = gbaudio_widgets[w->type]; ++ dw->sname = w->sname; + break; + default: + ret = -EINVAL; + goto error; + } ++ dw->name = w->name; + + dev_dbg(module->dev, "%s: widget of type %d created\n", dw->name, + dw->id); +@@ -1183,6 +1192,10 @@ static int gbaudio_tplg_process_kcontrols(struct gbaudio_module_info *module, + csize += le16_to_cpu(gbenum->names_length); + control->texts = (const char * const *) + gb_generate_enum_strings(module, gbenum); ++ if (!control->texts) { ++ ret = -ENOMEM; ++ goto error; ++ } + control->items = le32_to_cpu(gbenum->items); + } else { + csize = sizeof(struct gb_audio_control); +diff --git a/drivers/staging/ks7010/Kconfig b/drivers/staging/ks7010/Kconfig +index 0987fdc2f70db..8ea6c09286798 100644 +--- a/drivers/staging/ks7010/Kconfig ++++ b/drivers/staging/ks7010/Kconfig +@@ -5,6 +5,9 @@ config KS7010 + select WIRELESS_EXT + select WEXT_PRIV + select FW_LOADER ++ select CRYPTO ++ select CRYPTO_HASH ++ select CRYPTO_MICHAEL_MIC + help + This is a driver for KeyStream KS7010 based SDIO WIFI cards. It is + found on at least later Spectec SDW-821 (FCC-ID "S2Y-WLAN-11G-K" only, +diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c +index 362ed44b4effa..e046489cd253b 100644 +--- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c ++++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c +@@ -835,7 +835,6 @@ static int lm3554_probe(struct i2c_client *client) + int err = 0; + struct lm3554 *flash; + unsigned int i; +- int ret; + + flash = kzalloc(sizeof(*flash), GFP_KERNEL); + if (!flash) +@@ -844,7 +843,7 @@ static int lm3554_probe(struct i2c_client *client) + flash->pdata = lm3554_platform_data_func(client); + if (IS_ERR(flash->pdata)) { + err = PTR_ERR(flash->pdata); +- goto fail1; ++ goto free_flash; + } + + v4l2_i2c_subdev_init(&flash->sd, client, &lm3554_ops); +@@ -852,12 +851,12 @@ static int lm3554_probe(struct i2c_client *client) + flash->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + flash->mode = ATOMISP_FLASH_MODE_OFF; + flash->timeout = LM3554_MAX_TIMEOUT / LM3554_TIMEOUT_STEPSIZE - 1; +- ret = ++ err = + v4l2_ctrl_handler_init(&flash->ctrl_handler, + ARRAY_SIZE(lm3554_controls)); +- if (ret) { ++ if (err) { + dev_err(&client->dev, "error initialize a ctrl_handler.\n"); +- goto fail3; ++ goto unregister_subdev; + } + + for (i = 0; i < ARRAY_SIZE(lm3554_controls); i++) +@@ -866,14 +865,15 @@ static int lm3554_probe(struct i2c_client *client) + + if (flash->ctrl_handler.error) { + dev_err(&client->dev, "ctrl_handler error.\n"); +- goto fail3; ++ err = flash->ctrl_handler.error; ++ goto free_handler; + } + + flash->sd.ctrl_handler = &flash->ctrl_handler; + err = media_entity_pads_init(&flash->sd.entity, 0, NULL); + if (err) { + dev_err(&client->dev, "error initialize a media entity.\n"); +- goto fail2; ++ goto free_handler; + } + + flash->sd.entity.function = MEDIA_ENT_F_FLASH; +@@ -884,16 +884,27 @@ static int lm3554_probe(struct i2c_client *client) + + err = lm3554_gpio_init(client); + if (err) { +- dev_err(&client->dev, "gpio request/direction_output fail"); +- goto fail3; ++ dev_err(&client->dev, "gpio request/direction_output fail.\n"); ++ goto cleanup_media; ++ } ++ ++ err = atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH); ++ if (err) { ++ dev_err(&client->dev, "fail to register atomisp i2c module.\n"); ++ goto uninit_gpio; + } +- return atomisp_register_i2c_module(&flash->sd, NULL, LED_FLASH); +-fail3: ++ ++ return 0; ++ ++uninit_gpio: ++ lm3554_gpio_uninit(client); ++cleanup_media: + media_entity_cleanup(&flash->sd.entity); ++free_handler: + v4l2_ctrl_handler_free(&flash->ctrl_handler); +-fail2: ++unregister_subdev: + v4l2_device_unregister_subdev(&flash->sd); +-fail1: ++free_flash: + kfree(flash); + + return err; +diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h +index 874115f35fcad..798b28e134b64 100644 +--- a/drivers/staging/media/atomisp/i2c/ov2680.h ++++ b/drivers/staging/media/atomisp/i2c/ov2680.h +@@ -289,8 +289,6 @@ static struct ov2680_reg const ov2680_global_setting[] = { + */ + static struct ov2680_reg const ov2680_QCIF_30fps[] = { + {0x3086, 0x01}, +- {0x3501, 0x24}, +- {0x3502, 0x40}, + {0x370a, 0x23}, + {0x3801, 0xa0}, + {0x3802, 0x00}, +@@ -334,8 +332,6 @@ static struct ov2680_reg const ov2680_QCIF_30fps[] = { + */ + static struct ov2680_reg const ov2680_CIF_30fps[] = { + {0x3086, 0x01}, +- {0x3501, 0x24}, +- {0x3502, 0x40}, + {0x370a, 0x23}, + {0x3801, 0xa0}, + {0x3802, 0x00}, +@@ -377,8 +373,6 @@ static struct ov2680_reg const ov2680_CIF_30fps[] = { + */ + static struct ov2680_reg const ov2680_QVGA_30fps[] = { + {0x3086, 0x01}, +- {0x3501, 0x24}, +- {0x3502, 0x40}, + {0x370a, 0x23}, + {0x3801, 0xa0}, + {0x3802, 0x00}, +@@ -420,8 +414,6 @@ static struct ov2680_reg const ov2680_QVGA_30fps[] = { + */ + static struct ov2680_reg const ov2680_656x496_30fps[] = { + {0x3086, 0x01}, +- {0x3501, 0x24}, +- {0x3502, 0x40}, + {0x370a, 0x23}, + {0x3801, 0xa0}, + {0x3802, 0x00}, +@@ -463,8 +455,6 @@ static struct ov2680_reg const ov2680_656x496_30fps[] = { + */ + static struct ov2680_reg const ov2680_720x592_30fps[] = { + {0x3086, 0x01}, +- {0x3501, 0x26}, +- {0x3502, 0x40}, + {0x370a, 0x23}, + {0x3801, 0x00}, // X_ADDR_START; + {0x3802, 0x00}, +@@ -508,8 +498,6 @@ static struct ov2680_reg const ov2680_720x592_30fps[] = { + */ + static struct ov2680_reg const ov2680_800x600_30fps[] = { + {0x3086, 0x01}, +- {0x3501, 0x26}, +- {0x3502, 0x40}, + {0x370a, 0x23}, + {0x3801, 0x00}, + {0x3802, 0x00}, +@@ -551,8 +539,6 @@ static struct ov2680_reg const ov2680_800x600_30fps[] = { + */ + static struct ov2680_reg const ov2680_720p_30fps[] = { + {0x3086, 0x00}, +- {0x3501, 0x48}, +- {0x3502, 0xe0}, + {0x370a, 0x21}, + {0x3801, 0xa0}, + {0x3802, 0x00}, +@@ -594,8 +580,6 @@ static struct ov2680_reg const ov2680_720p_30fps[] = { + */ + static struct ov2680_reg const ov2680_1296x976_30fps[] = { + {0x3086, 0x00}, +- {0x3501, 0x48}, +- {0x3502, 0xe0}, + {0x370a, 0x21}, + {0x3801, 0xa0}, + {0x3802, 0x00}, +@@ -637,8 +621,6 @@ static struct ov2680_reg const ov2680_1296x976_30fps[] = { + */ + static struct ov2680_reg const ov2680_1456x1096_30fps[] = { + {0x3086, 0x00}, +- {0x3501, 0x48}, +- {0x3502, 0xe0}, + {0x370a, 0x21}, + {0x3801, 0x90}, + {0x3802, 0x00}, +@@ -682,8 +664,6 @@ static struct ov2680_reg const ov2680_1456x1096_30fps[] = { + + static struct ov2680_reg const ov2680_1616x916_30fps[] = { + {0x3086, 0x00}, +- {0x3501, 0x48}, +- {0x3502, 0xe0}, + {0x370a, 0x21}, + {0x3801, 0x00}, + {0x3802, 0x00}, +@@ -726,8 +706,6 @@ static struct ov2680_reg const ov2680_1616x916_30fps[] = { + #if 0 + static struct ov2680_reg const ov2680_1616x1082_30fps[] = { + {0x3086, 0x00}, +- {0x3501, 0x48}, +- {0x3502, 0xe0}, + {0x370a, 0x21}, + {0x3801, 0x00}, + {0x3802, 0x00}, +@@ -769,8 +747,6 @@ static struct ov2680_reg const ov2680_1616x1082_30fps[] = { + */ + static struct ov2680_reg const ov2680_1616x1216_30fps[] = { + {0x3086, 0x00}, +- {0x3501, 0x48}, +- {0x3502, 0xe0}, + {0x370a, 0x21}, + {0x3801, 0x00}, + {0x3802, 0x00}, +diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c +index 366161cff5602..ef0b0963cf930 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c +@@ -1715,6 +1715,12 @@ void atomisp_wdt_refresh_pipe(struct atomisp_video_pipe *pipe, + { + unsigned long next; + ++ if (!pipe->asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, pipe->vdev.name); ++ return; ++ } ++ + if (delay != ATOMISP_WDT_KEEP_CURRENT_DELAY) + pipe->wdt_duration = delay; + +@@ -1777,6 +1783,12 @@ void atomisp_wdt_refresh(struct atomisp_sub_device *asd, unsigned int delay) + /* ISP2401 */ + void atomisp_wdt_stop_pipe(struct atomisp_video_pipe *pipe, bool sync) + { ++ if (!pipe->asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, pipe->vdev.name); ++ return; ++ } ++ + if (!atomisp_is_wdt_running(pipe)) + return; + +@@ -4109,6 +4121,12 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) + unsigned long irqflags; + bool need_to_enqueue_buffer = false; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, pipe->vdev.name); ++ return; ++ } ++ + if (atomisp_is_vf_pipe(pipe)) + return; + +@@ -4196,6 +4214,12 @@ int atomisp_set_parameters(struct video_device *vdev, + struct atomisp_css_params *css_param = &asd->params.css_param; + int ret; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { + dev_err(asd->isp->dev, "%s: internal error!\n", __func__); + return -EINVAL; +@@ -4857,6 +4881,12 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, + int source_pad = atomisp_subdev_source_pad(vdev); + int ret; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (!isp->inputs[asd->input_curr].camera) + return -EINVAL; + +@@ -5194,10 +5224,17 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, + int (*configure_pp_input)(struct atomisp_sub_device *asd, + unsigned int width, unsigned int height) = + configure_pp_input_nop; +- u16 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); ++ u16 stream_index; + const struct atomisp_in_fmt_conv *fc; + int ret, i; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); ++ + v4l2_fh_init(&fh.vfh, vdev); + + isp_sink_crop = atomisp_subdev_get_rect( +@@ -5493,7 +5530,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, + unsigned int padding_w, unsigned int padding_h, + unsigned int dvs_env_w, unsigned int dvs_env_h) + { +- struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; ++ struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); ++ struct atomisp_sub_device *asd = pipe->asd; + const struct atomisp_format_bridge *format; + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_state pad_state = { +@@ -5504,7 +5542,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, + }; + struct v4l2_mbus_framefmt *ffmt = &vformat.format; + struct v4l2_mbus_framefmt *req_ffmt; +- struct atomisp_device *isp = asd->isp; ++ struct atomisp_device *isp; + struct atomisp_input_stream_info *stream_info = + (struct atomisp_input_stream_info *)ffmt->reserved; + u16 stream_index = ATOMISP_INPUT_STREAM_GENERAL; +@@ -5512,6 +5550,14 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, + struct v4l2_subdev_fh fh; + int ret; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ ++ isp = asd->isp; ++ + v4l2_fh_init(&fh.vfh, vdev); + + stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); +@@ -5602,6 +5648,12 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) + struct v4l2_subdev_fh fh; + int ret; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (source_pad >= ATOMISP_SUBDEV_PADS_NUM) + return -EINVAL; + +@@ -6034,6 +6086,12 @@ int atomisp_set_fmt_file(struct video_device *vdev, struct v4l2_format *f) + struct v4l2_subdev_fh fh; + int ret; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + v4l2_fh_init(&fh.vfh, vdev); + + dev_dbg(isp->dev, "setting fmt %ux%u 0x%x for file inject\n", +@@ -6359,6 +6417,12 @@ bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) + { + struct atomisp_sub_device *asd = pipe->asd; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, pipe->vdev.name); ++ return false; ++ } ++ + if (pipe == &asd->video_out_vf) + return true; + +@@ -6572,6 +6636,12 @@ static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) + { + struct atomisp_sub_device *asd = pipe->asd; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, pipe->vdev.name); ++ return -EINVAL; ++ } ++ + if (ATOMISP_USE_YUVPP(asd)) { + return IA_CSS_PIPE_ID_YUVPP; + } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { +@@ -6609,6 +6679,12 @@ int atomisp_get_invalid_frame_num(struct video_device *vdev, + struct ia_css_pipe_info p_info; + int ret; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (asd->isp->inputs[asd->input_curr].camera_caps-> + sensor[asd->sensor_curr].stream_num > 1) { + /* External ISP */ +diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c +index f82bf082aa796..18fff47bd25d2 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_fops.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c +@@ -877,6 +877,11 @@ done: + else + pipe->users++; + rt_mutex_unlock(&isp->mutex); ++ ++ /* Ensure that a mode is set */ ++ if (asd) ++ v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); ++ + return 0; + + css_error: +@@ -1171,6 +1176,12 @@ static int atomisp_mmap(struct file *file, struct vm_area_struct *vma) + u32 origin_size, new_size; + int ret; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (!(vma->vm_flags & (VM_WRITE | VM_READ))) + return -EACCES; + +diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +index d8c9e31314b2e..62dc06e224765 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +@@ -481,7 +481,7 @@ fail: + + static u8 gmin_get_pmic_id_and_addr(struct device *dev) + { +- struct i2c_client *power; ++ struct i2c_client *power = NULL; + static u8 pmic_i2c_addr; + + if (pmic_id) +diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +index c8a625667e81e..b7dda4b96d49c 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +@@ -646,6 +646,12 @@ static int atomisp_g_input(struct file *file, void *fh, unsigned int *input) + struct atomisp_device *isp = video_get_drvdata(vdev); + struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + rt_mutex_lock(&isp->mutex); + *input = asd->input_curr; + rt_mutex_unlock(&isp->mutex); +@@ -665,6 +671,12 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) + struct v4l2_subdev *motor; + int ret; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + rt_mutex_lock(&isp->mutex); + if (input >= ATOM_ISP_MAX_INPUTS || input >= isp->input_cnt) { + dev_dbg(isp->dev, "input_cnt: %d\n", isp->input_cnt); +@@ -761,18 +773,33 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, + struct video_device *vdev = video_devdata(file); + struct atomisp_device *isp = video_get_drvdata(vdev); + struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; +- struct v4l2_subdev_mbus_code_enum code = { 0 }; ++ struct v4l2_subdev_mbus_code_enum code = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_subdev *camera; + unsigned int i, fi = 0; + int rval; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ ++ camera = isp->inputs[asd->input_curr].camera; ++ if(!camera) { ++ dev_err(isp->dev, "%s(): camera is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + rt_mutex_lock(&isp->mutex); +- rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, +- enum_mbus_code, NULL, &code); ++ ++ rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code); + if (rval == -ENOIOCTLCMD) { + dev_warn(isp->dev, +- "enum_mbus_code pad op not supported. Please fix your sensor driver!\n"); +- // rval = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, +- // video, enum_mbus_fmt, 0, &code.code); ++ "enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n", ++ camera->name); + } + rt_mutex_unlock(&isp->mutex); + +@@ -802,6 +829,8 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, + f->pixelformat = format->pixelformat; + return 0; + } ++ dev_err(isp->dev, "%s(): format for code %x not found.\n", ++ __func__, code.code); + + return -EINVAL; + } +@@ -834,6 +863,72 @@ static int atomisp_g_fmt_file(struct file *file, void *fh, + return 0; + } + ++static int atomisp_adjust_fmt(struct v4l2_format *f) ++{ ++ const struct atomisp_format_bridge *format_bridge; ++ u32 padded_width; ++ ++ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); ++ ++ padded_width = f->fmt.pix.width + pad_w; ++ ++ if (format_bridge->planar) { ++ f->fmt.pix.bytesperline = padded_width; ++ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * ++ DIV_ROUND_UP(format_bridge->depth * ++ padded_width, 8)); ++ } else { ++ f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth * ++ padded_width, 8); ++ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); ++ } ++ ++ if (f->fmt.pix.field == V4L2_FIELD_ANY) ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ ++ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); ++ if (!format_bridge) ++ return -EINVAL; ++ ++ /* Currently, raw formats are broken!!! */ ++ if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { ++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; ++ ++ format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); ++ if (!format_bridge) ++ return -EINVAL; ++ } ++ ++ padded_width = f->fmt.pix.width + pad_w; ++ ++ if (format_bridge->planar) { ++ f->fmt.pix.bytesperline = padded_width; ++ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * ++ DIV_ROUND_UP(format_bridge->depth * ++ padded_width, 8)); ++ } else { ++ f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth * ++ padded_width, 8); ++ f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); ++ } ++ ++ if (f->fmt.pix.field == V4L2_FIELD_ANY) ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ ++ /* ++ * FIXME: do we need to setup this differently, depending on the ++ * sensor or the pipeline? ++ */ ++ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; ++ f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709; ++ f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709; ++ ++ f->fmt.pix.width -= pad_w; ++ f->fmt.pix.height -= pad_h; ++ ++ return 0; ++} ++ + /* This function looks up the closest available resolution. */ + static int atomisp_try_fmt_cap(struct file *file, void *fh, + struct v4l2_format *f) +@@ -845,7 +940,11 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh, + rt_mutex_lock(&isp->mutex); + ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL); + rt_mutex_unlock(&isp->mutex); +- return ret; ++ ++ if (ret) ++ return ret; ++ ++ return atomisp_adjust_fmt(f); + } + + static int atomisp_s_fmt_cap(struct file *file, void *fh, +@@ -1024,9 +1123,16 @@ int __atomisp_reqbufs(struct file *file, void *fh, + struct ia_css_frame *frame; + struct videobuf_vmalloc_memory *vm_mem; + u16 source_pad = atomisp_subdev_source_pad(vdev); +- u16 stream_id = atomisp_source_pad_to_stream_id(asd, source_pad); ++ u16 stream_id; + int ret = 0, i = 0; + ++ if (!asd) { ++ dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ stream_id = atomisp_source_pad_to_stream_id(asd, source_pad); ++ + if (req->count == 0) { + mutex_lock(&pipe->capq.vb_lock); + if (!list_empty(&pipe->capq.stream)) +@@ -1154,6 +1260,12 @@ static int atomisp_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) + u32 pgnr; + int ret = 0; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + rt_mutex_lock(&isp->mutex); + if (isp->isp_fatal_error) { + ret = -EIO; +@@ -1389,6 +1501,12 @@ static int atomisp_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) + struct atomisp_device *isp = video_get_drvdata(vdev); + int ret = 0; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + rt_mutex_lock(&isp->mutex); + + if (isp->isp_fatal_error) { +@@ -1640,6 +1758,12 @@ static int atomisp_streamon(struct file *file, void *fh, + int ret = 0; + unsigned long irqflags; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + dev_dbg(isp->dev, "Start stream on pad %d for asd%d\n", + atomisp_subdev_source_pad(vdev), asd->index); + +@@ -1901,6 +2025,12 @@ int __atomisp_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) + unsigned long flags; + bool first_streamoff = false; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + dev_dbg(isp->dev, "Stop stream on pad %d for asd%d\n", + atomisp_subdev_source_pad(vdev), asd->index); + +@@ -2150,6 +2280,12 @@ static int atomisp_g_ctrl(struct file *file, void *fh, + struct atomisp_device *isp = video_get_drvdata(vdev); + int i, ret = -EINVAL; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + for (i = 0; i < ctrls_num; i++) { + if (ci_v4l2_controls[i].id == control->id) { + ret = 0; +@@ -2229,6 +2365,12 @@ static int atomisp_s_ctrl(struct file *file, void *fh, + struct atomisp_device *isp = video_get_drvdata(vdev); + int i, ret = -EINVAL; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + for (i = 0; i < ctrls_num; i++) { + if (ci_v4l2_controls[i].id == control->id) { + ret = 0; +@@ -2310,6 +2452,12 @@ static int atomisp_queryctl(struct file *file, void *fh, + struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_device *isp = video_get_drvdata(vdev); + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + switch (qc->id) { + case V4L2_CID_FOCUS_ABSOLUTE: + case V4L2_CID_FOCUS_RELATIVE: +@@ -2355,6 +2503,12 @@ static int atomisp_camera_g_ext_ctrls(struct file *file, void *fh, + int i; + int ret = 0; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (!IS_ISP2401) + motor = isp->inputs[asd->input_curr].motor; + else +@@ -2466,6 +2620,12 @@ static int atomisp_camera_s_ext_ctrls(struct file *file, void *fh, + int i; + int ret = 0; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (!IS_ISP2401) + motor = isp->inputs[asd->input_curr].motor; + else +@@ -2591,6 +2751,12 @@ static int atomisp_g_parm(struct file *file, void *fh, + struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_device *isp = video_get_drvdata(vdev); + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_err(isp->dev, "unsupported v4l2 buf type\n"); + return -EINVAL; +@@ -2613,6 +2779,12 @@ static int atomisp_s_parm(struct file *file, void *fh, + int rval; + int fps; + ++ if (!asd) { ++ dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", ++ __func__, vdev->name); ++ return -EINVAL; ++ } ++ + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev_err(isp->dev, "unsupported v4l2 buf type\n"); + return -EINVAL; +diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c +index 12f22ad007c73..ffaf11e0b0ad8 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c +@@ -1164,23 +1164,28 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) + + atomisp_init_acc_pipe(asd, &asd->video_acc); + +- ret = atomisp_video_init(&asd->video_in, "MEMORY"); ++ ret = atomisp_video_init(&asd->video_in, "MEMORY", ++ ATOMISP_RUN_MODE_SDV); + if (ret < 0) + return ret; + +- ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE"); ++ ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE", ++ ATOMISP_RUN_MODE_STILL_CAPTURE); + if (ret < 0) + return ret; + +- ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER"); ++ ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER", ++ ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE); + if (ret < 0) + return ret; + +- ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW"); ++ ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW", ++ ATOMISP_RUN_MODE_PREVIEW); + if (ret < 0) + return ret; + +- ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO"); ++ ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO", ++ ATOMISP_RUN_MODE_VIDEO); + if (ret < 0) + return ret; + +diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h +index d6fcfab6352d7..a8d210ea5f8be 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h ++++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h +@@ -81,6 +81,9 @@ struct atomisp_video_pipe { + /* the link list to store per_frame parameters */ + struct list_head per_frame_params; + ++ /* Store here the initial run mode */ ++ unsigned int default_run_mode; ++ + unsigned int buffers_in_css; + + /* irq_lock is used to protect video buffer state change operations and +diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +index 1e324f1f656e5..14c39b8987c95 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c ++++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +@@ -447,7 +447,8 @@ const struct atomisp_dfs_config dfs_config_cht_soc = { + .dfs_table_size = ARRAY_SIZE(dfs_rules_cht_soc), + }; + +-int atomisp_video_init(struct atomisp_video_pipe *video, const char *name) ++int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, ++ unsigned int run_mode) + { + int ret; + const char *direction; +@@ -478,6 +479,7 @@ int atomisp_video_init(struct atomisp_video_pipe *video, const char *name) + "ATOMISP ISP %s %s", name, direction); + video->vdev.release = video_device_release_empty; + video_set_drvdata(&video->vdev, video->isp); ++ video->default_run_mode = run_mode; + + return 0; + } +@@ -711,15 +713,15 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) + + dev_dbg(isp->dev, "IUNIT power-%s.\n", enable ? "on" : "off"); + +- /*WA:Enable DVFS*/ ++ /* WA for P-Unit, if DVFS enabled, ISP timeout observed */ + if (IS_CHT && enable) +- punit_ddr_dvfs_enable(true); ++ punit_ddr_dvfs_enable(false); + + /* + * FIXME:WA for ECS28A, with this sleep, CTS + * android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceAbort + * PASS, no impact on other platforms +- */ ++ */ + if (IS_BYT && enable) + msleep(10); + +@@ -727,7 +729,7 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) + iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, + val, MRFLD_ISPSSPM0_ISPSSC_MASK); + +- /*WA:Enable DVFS*/ ++ /* WA:Enable DVFS */ + if (IS_CHT && !enable) + punit_ddr_dvfs_enable(true); + +@@ -1182,6 +1184,7 @@ static void atomisp_unregister_entities(struct atomisp_device *isp) + + v4l2_device_unregister(&isp->v4l2_dev); + media_device_unregister(&isp->media_dev); ++ media_device_cleanup(&isp->media_dev); + } + + static int atomisp_register_entities(struct atomisp_device *isp) +diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h +index 81bb356b81720..72611b8286a4a 100644 +--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h ++++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h +@@ -27,7 +27,8 @@ struct v4l2_device; + struct atomisp_device; + struct firmware; + +-int atomisp_video_init(struct atomisp_video_pipe *video, const char *name); ++int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, ++ unsigned int run_mode); + void atomisp_acc_init(struct atomisp_acc_pipe *video, const char *name); + void atomisp_video_unregister(struct atomisp_video_pipe *video); + void atomisp_acc_unregister(struct atomisp_acc_pipe *video); +diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c +index c4b35cbab3737..ba25d0da8b811 100644 +--- a/drivers/staging/media/atomisp/pci/sh_css.c ++++ b/drivers/staging/media/atomisp/pci/sh_css.c +@@ -522,6 +522,7 @@ ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream) + return bpp; + } + ++/* TODO: move define to proper file in tools */ + #define GP_ISEL_TPG_MODE 0x90058 + + #if !defined(ISP2401) +@@ -573,12 +574,8 @@ sh_css_config_input_network(struct ia_css_stream *stream) + vblank_cycles = vblank_lines * (width + hblank_cycles); + sh_css_sp_configure_sync_gen(width, height, hblank_cycles, + vblank_cycles); +- if (!IS_ISP2401) { +- if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) { +- /* TODO: move define to proper file in tools */ +- ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0); +- } +- } ++ if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) ++ ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0); + } + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "sh_css_config_input_network() leave:\n"); +@@ -1009,16 +1006,14 @@ static bool sh_css_translate_stream_cfg_to_isys_stream_descr( + * ia_css_isys_stream_capture_indication() instead of + * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of + * capture takes longer than getting an ISYS frame +- * +- * Only 2401 relevant ?? + */ +-#if 0 // FIXME: NOT USED on Yocto Aero +- isys_stream_descr->polling_mode +- = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST +- : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; +- ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, +- "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); +-#endif ++ if (IS_ISP2401) { ++ isys_stream_descr->polling_mode ++ = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST ++ : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME; ++ ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, ++ "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n"); ++ } + + return rc; + } +@@ -1433,7 +1428,7 @@ static void start_pipe( + + assert(me); /* all callers are in this file and call with non null argument */ + +- if (!IS_ISP2401) { ++ if (IS_ISP2401) { + coord = &me->config.internal_frame_origin_bqs_on_sctbl; + params = me->stream->isp_params_configs; + } +diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c +index 75489f7d75eec..c1f2f6151c5f8 100644 +--- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c ++++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c +@@ -374,17 +374,17 @@ static bool buffers_needed(struct ia_css_pipe *pipe) + { + if (!IS_ISP2401) { + if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) +- return false; +- else + return true; ++ else ++ return false; + } + + if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR || + pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG || + pipe->stream->config.mode == IA_CSS_INPUT_MODE_PRBS) +- return false; ++ return true; + +- return true; ++ return false; + } + + int +@@ -423,14 +423,17 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, + return 0; /* AM TODO: Check */ + } + +- if (!IS_ISP2401) ++ if (!IS_ISP2401) { + port = (unsigned int)pipe->stream->config.source.port.port; +- else +- err = ia_css_mipi_is_source_port_valid(pipe, &port); ++ } else { ++ /* Returns true if port is valid. So, invert it */ ++ err = !ia_css_mipi_is_source_port_valid(pipe, &port); ++ } + + assert(port < N_CSI_PORTS); + +- if (port >= N_CSI_PORTS || err) { ++ if ((!IS_ISP2401 && port >= N_CSI_PORTS) || ++ (IS_ISP2401 && err)) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "allocate_mipi_frames(%p) exit: error: port is not correct (port=%d).\n", + pipe, port); +@@ -552,14 +555,17 @@ free_mipi_frames(struct ia_css_pipe *pipe) + return err; + } + +- if (!IS_ISP2401) ++ if (!IS_ISP2401) { + port = (unsigned int)pipe->stream->config.source.port.port; +- else +- err = ia_css_mipi_is_source_port_valid(pipe, &port); ++ } else { ++ /* Returns true if port is valid. So, invert it */ ++ err = !ia_css_mipi_is_source_port_valid(pipe, &port); ++ } + + assert(port < N_CSI_PORTS); + +- if (port >= N_CSI_PORTS || err) { ++ if ((!IS_ISP2401 && port >= N_CSI_PORTS) || ++ (IS_ISP2401 && err)) { + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "free_mipi_frames(%p, %d) exit: error: pipe port is not correct.\n", + pipe, port); +@@ -663,14 +669,17 @@ send_mipi_frames(struct ia_css_pipe *pipe) + /* TODO: AM: maybe this should be returning an error. */ + } + +- if (!IS_ISP2401) ++ if (!IS_ISP2401) { + port = (unsigned int)pipe->stream->config.source.port.port; +- else +- err = ia_css_mipi_is_source_port_valid(pipe, &port); ++ } else { ++ /* Returns true if port is valid. So, invert it */ ++ err = !ia_css_mipi_is_source_port_valid(pipe, &port); ++ } + + assert(port < N_CSI_PORTS); + +- if (port >= N_CSI_PORTS || err) { ++ if ((!IS_ISP2401 && port >= N_CSI_PORTS) || ++ (IS_ISP2401 && err)) { + IA_CSS_ERROR("send_mipi_frames(%p) exit: invalid port specified (port=%d).\n", + pipe, port); + return err; +diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c +index dbd3bfe3d343c..ccc0078795648 100644 +--- a/drivers/staging/media/atomisp/pci/sh_css_params.c ++++ b/drivers/staging/media/atomisp/pci/sh_css_params.c +@@ -2431,7 +2431,7 @@ sh_css_create_isp_params(struct ia_css_stream *stream, + unsigned int i; + struct sh_css_ddr_address_map *ddr_ptrs; + struct sh_css_ddr_address_map_size *ddr_ptrs_size; +- int err = 0; ++ int err; + size_t params_size; + struct ia_css_isp_parameters *params = + kvmalloc(sizeof(struct ia_css_isp_parameters), GFP_KERNEL); +@@ -2473,7 +2473,11 @@ sh_css_create_isp_params(struct ia_css_stream *stream, + succ &= (ddr_ptrs->macc_tbl != mmgr_NULL); + + *isp_params_out = params; +- return err; ++ ++ if (!succ) ++ return -ENOMEM; ++ ++ return 0; + } + + static bool +diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c +index 20e5081588719..281aa585e3375 100644 +--- a/drivers/staging/media/hantro/hantro_drv.c ++++ b/drivers/staging/media/hantro/hantro_drv.c +@@ -958,7 +958,7 @@ static int hantro_probe(struct platform_device *pdev) + ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare clocks\n"); +- return ret; ++ goto err_pm_disable; + } + + ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev); +@@ -1014,6 +1014,7 @@ err_v4l2_unreg: + v4l2_device_unregister(&vpu->v4l2_dev); + err_clk_unprepare: + clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks); ++err_pm_disable: + pm_runtime_dont_use_autosuspend(vpu->dev); + pm_runtime_disable(vpu->dev); + return ret; +diff --git a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +index 56cf261a8e958..9cd713c02a455 100644 +--- a/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c ++++ b/drivers/staging/media/hantro/hantro_h1_jpeg_enc.c +@@ -140,7 +140,7 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) + return 0; + } + +-void hantro_jpeg_enc_done(struct hantro_ctx *ctx) ++void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx) + { + struct hantro_dev *vpu = ctx->dev; + u32 bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8; +diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h +index df7b5e3a57b9b..fd738653a5735 100644 +--- a/drivers/staging/media/hantro/hantro_hw.h ++++ b/drivers/staging/media/hantro/hantro_hw.h +@@ -235,7 +235,8 @@ int hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx); + int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx); + int hantro_jpeg_enc_init(struct hantro_ctx *ctx); + void hantro_jpeg_enc_exit(struct hantro_ctx *ctx); +-void hantro_jpeg_enc_done(struct hantro_ctx *ctx); ++void hantro_h1_jpeg_enc_done(struct hantro_ctx *ctx); ++void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx); + + dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, + unsigned int dpb_idx); +diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c +index 991213ce16108..5d9ff420f0b5f 100644 +--- a/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c ++++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_jpeg_enc.c +@@ -171,3 +171,20 @@ int rockchip_vpu2_jpeg_enc_run(struct hantro_ctx *ctx) + + return 0; + } ++ ++void rockchip_vpu2_jpeg_enc_done(struct hantro_ctx *ctx) ++{ ++ struct hantro_dev *vpu = ctx->dev; ++ u32 bytesused = vepu_read(vpu, VEPU_REG_STR_BUF_LIMIT) / 8; ++ struct vb2_v4l2_buffer *dst_buf = hantro_get_dst_buf(ctx); ++ ++ /* ++ * TODO: Rework the JPEG encoder to eliminate the need ++ * for a bounce buffer. ++ */ ++ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) + ++ ctx->vpu_dst_fmt->header_size, ++ ctx->jpeg_enc.bounce_buffer.cpu, bytesused); ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, ++ ctx->vpu_dst_fmt->header_size + bytesused); ++} +diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c +index d4f52957cc534..0c22039162a00 100644 +--- a/drivers/staging/media/hantro/rockchip_vpu_hw.c ++++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c +@@ -343,7 +343,7 @@ static const struct hantro_codec_ops rk3066_vpu_codec_ops[] = { + .run = hantro_h1_jpeg_enc_run, + .reset = rockchip_vpu1_enc_reset, + .init = hantro_jpeg_enc_init, +- .done = hantro_jpeg_enc_done, ++ .done = hantro_h1_jpeg_enc_done, + .exit = hantro_jpeg_enc_exit, + }, + [HANTRO_MODE_H264_DEC] = { +@@ -371,7 +371,7 @@ static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = { + .run = hantro_h1_jpeg_enc_run, + .reset = rockchip_vpu1_enc_reset, + .init = hantro_jpeg_enc_init, +- .done = hantro_jpeg_enc_done, ++ .done = hantro_h1_jpeg_enc_done, + .exit = hantro_jpeg_enc_exit, + }, + [HANTRO_MODE_H264_DEC] = { +@@ -399,6 +399,7 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = { + .run = rockchip_vpu2_jpeg_enc_run, + .reset = rockchip_vpu2_enc_reset, + .init = hantro_jpeg_enc_init, ++ .done = rockchip_vpu2_jpeg_enc_done, + .exit = hantro_jpeg_enc_exit, + }, + [HANTRO_MODE_H264_DEC] = { +diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c +index d186179388d03..4d873726a461b 100644 +--- a/drivers/staging/media/imx/imx-media-dev-common.c ++++ b/drivers/staging/media/imx/imx-media-dev-common.c +@@ -367,6 +367,8 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev, + imxmd->v4l2_dev.notify = imx_media_notify; + strscpy(imxmd->v4l2_dev.name, "imx-media", + sizeof(imxmd->v4l2_dev.name)); ++ snprintf(imxmd->md.bus_info, sizeof(imxmd->md.bus_info), ++ "platform:%s", dev_name(imxmd->md.dev)); + + media_device_init(&imxmd->md); + +diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.c b/drivers/staging/media/ipu3/ipu3-css-fw.c +index 45aff76198e2c..981693eed8155 100644 +--- a/drivers/staging/media/ipu3/ipu3-css-fw.c ++++ b/drivers/staging/media/ipu3/ipu3-css-fw.c +@@ -124,12 +124,11 @@ int imgu_css_fw_init(struct imgu_css *css) + /* Check and display fw header info */ + + css->fwp = (struct imgu_fw_header *)css->fw->data; +- if (css->fw->size < sizeof(struct imgu_fw_header *) || ++ if (css->fw->size < struct_size(css->fwp, binary_header, 1) || + css->fwp->file_header.h_size != sizeof(struct imgu_fw_bi_file_h)) + goto bad_fw; +- if (sizeof(struct imgu_fw_bi_file_h) + +- css->fwp->file_header.binary_nr * sizeof(struct imgu_fw_info) > +- css->fw->size) ++ if (struct_size(css->fwp, binary_header, ++ css->fwp->file_header.binary_nr) > css->fw->size) + goto bad_fw; + + dev_info(dev, "loaded firmware version %.64s, %u binaries, %zu bytes\n", +diff --git a/drivers/staging/media/ipu3/ipu3-css-fw.h b/drivers/staging/media/ipu3/ipu3-css-fw.h +index 3c078f15a2959..c0bc57fd678a7 100644 +--- a/drivers/staging/media/ipu3/ipu3-css-fw.h ++++ b/drivers/staging/media/ipu3/ipu3-css-fw.h +@@ -171,7 +171,7 @@ struct imgu_fw_bi_file_h { + + struct imgu_fw_header { + struct imgu_fw_bi_file_h file_header; +- struct imgu_fw_info binary_header[1]; /* binary_nr items */ ++ struct imgu_fw_info binary_header[]; /* binary_nr items */ + }; + + /******************* Firmware functions *******************/ +diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c +index 38a2407645096..90c86ba5040e3 100644 +--- a/drivers/staging/media/ipu3/ipu3-v4l2.c ++++ b/drivers/staging/media/ipu3/ipu3-v4l2.c +@@ -592,11 +592,12 @@ static const struct imgu_fmt *find_format(struct v4l2_format *f, u32 type) + static int imgu_vidioc_querycap(struct file *file, void *fh, + struct v4l2_capability *cap) + { +- struct imgu_video_device *node = file_to_intel_imgu_node(file); ++ struct imgu_device *imgu = video_drvdata(file); + + strscpy(cap->driver, IMGU_NAME, sizeof(cap->driver)); + strscpy(cap->card, IMGU_NAME, sizeof(cap->card)); +- snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", node->name); ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", ++ pci_name(imgu->pci_dev)); + + return 0; + } +@@ -696,7 +697,7 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, + + /* CSS expects some format on OUT queue */ + if (i != IPU3_CSS_QUEUE_OUT && +- !imgu_pipe->nodes[inode].enabled) { ++ !imgu_pipe->nodes[inode].enabled && !try) { + fmts[i] = NULL; + continue; + } +diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c +index 76e97cbe25123..951e19231da21 100644 +--- a/drivers/staging/media/rkvdec/rkvdec-h264.c ++++ b/drivers/staging/media/rkvdec/rkvdec-h264.c +@@ -1015,8 +1015,9 @@ static int rkvdec_h264_adjust_fmt(struct rkvdec_ctx *ctx, + struct v4l2_pix_format_mplane *fmt = &f->fmt.pix_mp; + + fmt->num_planes = 1; +- fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * +- RKVDEC_H264_MAX_DEPTH_IN_BYTES; ++ if (!fmt->plane_fmt[0].sizeimage) ++ fmt->plane_fmt[0].sizeimage = fmt->width * fmt->height * ++ RKVDEC_H264_MAX_DEPTH_IN_BYTES; + return 0; + } + +diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c +index 7131156c1f2cf..3f3f96488d741 100644 +--- a/drivers/staging/media/rkvdec/rkvdec.c ++++ b/drivers/staging/media/rkvdec/rkvdec.c +@@ -280,31 +280,20 @@ static int rkvdec_try_output_fmt(struct file *file, void *priv, + return 0; + } + +-static int rkvdec_s_fmt(struct file *file, void *priv, +- struct v4l2_format *f, +- int (*try_fmt)(struct file *, void *, +- struct v4l2_format *)) ++static int rkvdec_s_capture_fmt(struct file *file, void *priv, ++ struct v4l2_format *f) + { + struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); + struct vb2_queue *vq; ++ int ret; + +- if (!try_fmt) +- return -EINVAL; +- +- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); ++ /* Change not allowed if queue is busy */ ++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, ++ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (vb2_is_busy(vq)) + return -EBUSY; + +- return try_fmt(file, priv, f); +-} +- +-static int rkvdec_s_capture_fmt(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct rkvdec_ctx *ctx = fh_to_rkvdec_ctx(priv); +- int ret; +- +- ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_capture_fmt); ++ ret = rkvdec_try_capture_fmt(file, priv, f); + if (ret) + return ret; + +@@ -319,9 +308,20 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, + struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx; + const struct rkvdec_coded_fmt_desc *desc; + struct v4l2_format *cap_fmt; +- struct vb2_queue *peer_vq; ++ struct vb2_queue *peer_vq, *vq; + int ret; + ++ /* ++ * In order to support dynamic resolution change, the decoder admits ++ * a resolution change, as long as the pixelformat remains. Can't be ++ * done if streaming. ++ */ ++ vq = v4l2_m2m_get_vq(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ if (vb2_is_streaming(vq) || ++ (vb2_is_busy(vq) && ++ f->fmt.pix_mp.pixelformat != ctx->coded_fmt.fmt.pix_mp.pixelformat)) ++ return -EBUSY; ++ + /* + * Since format change on the OUTPUT queue will reset the CAPTURE + * queue, we can't allow doing so when the CAPTURE queue has buffers +@@ -331,7 +331,7 @@ static int rkvdec_s_output_fmt(struct file *file, void *priv, + if (vb2_is_busy(peer_vq)) + return -EBUSY; + +- ret = rkvdec_s_fmt(file, priv, f, rkvdec_try_output_fmt); ++ ret = rkvdec_try_output_fmt(file, priv, f); + if (ret) + return ret; + +diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile +index 861adacf6c729..5f9612af3fa3c 100644 +--- a/drivers/staging/most/dim2/Makefile ++++ b/drivers/staging/most/dim2/Makefile +@@ -1,4 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + obj-$(CONFIG_MOST_DIM2) += most_dim2.o + +-most_dim2-objs := dim2.o hal.o sysfs.o ++most_dim2-objs := dim2.o hal.o +diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c +index 093ef9a2b2919..81e062009d271 100644 +--- a/drivers/staging/most/dim2/dim2.c ++++ b/drivers/staging/most/dim2/dim2.c +@@ -117,7 +117,8 @@ struct dim2_platform_data { + (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \ + ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A)) + +-bool dim2_sysfs_get_state_cb(void) ++static ssize_t state_show(struct device *dev, struct device_attribute *attr, ++ char *buf) + { + bool state; + unsigned long flags; +@@ -126,9 +127,18 @@ bool dim2_sysfs_get_state_cb(void) + state = dim_get_lock_state(); + spin_unlock_irqrestore(&dim_lock, flags); + +- return state; ++ return sysfs_emit(buf, "%s\n", state ? "locked" : ""); + } + ++static DEVICE_ATTR_RO(state); ++ ++static struct attribute *dim2_attrs[] = { ++ &dev_attr_state.attr, ++ NULL, ++}; ++ ++ATTRIBUTE_GROUPS(dim2); ++ + /** + * dimcb_on_error - callback from HAL to report miscommunication between + * HDM and HAL +@@ -716,6 +726,23 @@ static int get_dim2_clk_speed(const char *clock_speed, u8 *val) + return -EINVAL; + } + ++static void dim2_release(struct device *d) ++{ ++ struct dim2_hdm *dev = container_of(d, struct dim2_hdm, dev); ++ unsigned long flags; ++ ++ kthread_stop(dev->netinfo_task); ++ ++ spin_lock_irqsave(&dim_lock, flags); ++ dim_shutdown(); ++ spin_unlock_irqrestore(&dim_lock, flags); ++ ++ if (dev->disable_platform) ++ dev->disable_platform(to_platform_device(d->parent)); ++ ++ kfree(dev); ++} ++ + /* + * dim2_probe - dim2 probe handler + * @pdev: platform device structure +@@ -736,7 +763,7 @@ static int dim2_probe(struct platform_device *pdev) + + enum { MLB_INT_IDX, AHB0_INT_IDX }; + +- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + +@@ -748,25 +775,27 @@ static int dim2_probe(struct platform_device *pdev) + "microchip,clock-speed", &clock_speed); + if (ret) { + dev_err(&pdev->dev, "missing dt property clock-speed\n"); +- return ret; ++ goto err_free_dev; + } + + ret = get_dim2_clk_speed(clock_speed, &dev->clk_speed); + if (ret) { + dev_err(&pdev->dev, "bad dt property clock-speed\n"); +- return ret; ++ goto err_free_dev; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->io_base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(dev->io_base)) +- return PTR_ERR(dev->io_base); ++ if (IS_ERR(dev->io_base)) { ++ ret = PTR_ERR(dev->io_base); ++ goto err_free_dev; ++ } + + of_id = of_match_node(dim2_of_match, pdev->dev.of_node); + pdata = of_id->data; + ret = pdata && pdata->enable ? pdata->enable(pdev) : 0; + if (ret) +- return ret; ++ goto err_free_dev; + + dev->disable_platform = pdata ? pdata->disable : NULL; + +@@ -857,32 +886,19 @@ static int dim2_probe(struct platform_device *pdev) + dev->most_iface.request_netinfo = request_netinfo; + dev->most_iface.driver_dev = &pdev->dev; + dev->most_iface.dev = &dev->dev; +- dev->dev.init_name = "dim2_state"; ++ dev->dev.init_name = dev->name; + dev->dev.parent = &pdev->dev; ++ dev->dev.release = dim2_release; + +- ret = most_register_interface(&dev->most_iface); +- if (ret) { +- dev_err(&pdev->dev, "failed to register MOST interface\n"); +- goto err_stop_thread; +- } +- +- ret = dim2_sysfs_probe(&dev->dev); +- if (ret) { +- dev_err(&pdev->dev, "failed to create sysfs attribute\n"); +- goto err_unreg_iface; +- } +- +- return 0; ++ return most_register_interface(&dev->most_iface); + +-err_unreg_iface: +- most_deregister_interface(&dev->most_iface); +-err_stop_thread: +- kthread_stop(dev->netinfo_task); + err_shutdown_dim: + dim_shutdown(); + err_disable_platform: + if (dev->disable_platform) + dev->disable_platform(pdev); ++err_free_dev: ++ kfree(dev); + + return ret; + } +@@ -896,18 +912,8 @@ err_disable_platform: + static int dim2_remove(struct platform_device *pdev) + { + struct dim2_hdm *dev = platform_get_drvdata(pdev); +- unsigned long flags; + +- dim2_sysfs_destroy(&dev->dev); + most_deregister_interface(&dev->most_iface); +- kthread_stop(dev->netinfo_task); +- +- spin_lock_irqsave(&dim_lock, flags); +- dim_shutdown(); +- spin_unlock_irqrestore(&dim_lock, flags); +- +- if (dev->disable_platform) +- dev->disable_platform(pdev); + + return 0; + } +@@ -1082,6 +1088,7 @@ static struct platform_driver dim2_driver = { + .driver = { + .name = "hdm_dim2", + .of_match_table = dim2_of_match, ++ .dev_groups = dim2_groups, + }, + }; + +diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c +deleted file mode 100644 +index c85b2cdcdca3d..0000000000000 +--- a/drivers/staging/most/dim2/sysfs.c ++++ /dev/null +@@ -1,49 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * sysfs.c - MediaLB sysfs information +- * +- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG +- */ +- +-/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include <linux/kernel.h> +-#include "sysfs.h" +-#include <linux/device.h> +- +-static ssize_t state_show(struct device *dev, struct device_attribute *attr, +- char *buf) +-{ +- bool state = dim2_sysfs_get_state_cb(); +- +- return sprintf(buf, "%s\n", state ? "locked" : ""); +-} +- +-static DEVICE_ATTR_RO(state); +- +-static struct attribute *dev_attrs[] = { +- &dev_attr_state.attr, +- NULL, +-}; +- +-static struct attribute_group dev_attr_group = { +- .attrs = dev_attrs, +-}; +- +-static const struct attribute_group *dev_attr_groups[] = { +- &dev_attr_group, +- NULL, +-}; +- +-int dim2_sysfs_probe(struct device *dev) +-{ +- dev->groups = dev_attr_groups; +- return device_register(dev); +-} +- +-void dim2_sysfs_destroy(struct device *dev) +-{ +- device_unregister(dev); +-} +diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h +index 24277a17cff3d..09115cf4ed00e 100644 +--- a/drivers/staging/most/dim2/sysfs.h ++++ b/drivers/staging/most/dim2/sysfs.h +@@ -16,15 +16,4 @@ struct medialb_bus { + struct kobject kobj_group; + }; + +-struct device; +- +-int dim2_sysfs_probe(struct device *dev); +-void dim2_sysfs_destroy(struct device *dev); +- +-/* +- * callback, +- * must deliver MediaLB state as true if locked or false if unlocked +- */ +-bool dim2_sysfs_get_state_cb(void); +- + #endif /* DIM2_SYSFS_H */ +diff --git a/drivers/staging/r8188eu/core/rtw_led.c b/drivers/staging/r8188eu/core/rtw_led.c +index b33e34cce12e4..f9a8cdd9a1689 100644 +--- a/drivers/staging/r8188eu/core/rtw_led.c ++++ b/drivers/staging/r8188eu/core/rtw_led.c +@@ -74,6 +74,7 @@ void DeInitLed871x(struct LED_871x *pLed) + _cancel_workitem_sync(&pLed->BlinkWorkItem); + _cancel_timer_ex(&pLed->BlinkTimer); + ResetLedStatus(pLed); ++ SwLedOff(pLed->padapter, pLed); + } + + /* */ +diff --git a/drivers/staging/r8188eu/core/rtw_mlme.c b/drivers/staging/r8188eu/core/rtw_mlme.c +index 1115ff5d865ad..bd991d7ed8090 100644 +--- a/drivers/staging/r8188eu/core/rtw_mlme.c ++++ b/drivers/staging/r8188eu/core/rtw_mlme.c +@@ -1722,6 +1722,8 @@ int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, in + psetkeyparm->grpkey = 1; + break; + default: ++ kfree(psetkeyparm); ++ kfree(pcmd); + res = _FAIL; + goto exit; + } +diff --git a/drivers/staging/r8188eu/core/rtw_mlme_ext.c b/drivers/staging/r8188eu/core/rtw_mlme_ext.c +index 5a472a4954b0f..63d312d01171e 100644 +--- a/drivers/staging/r8188eu/core/rtw_mlme_ext.c ++++ b/drivers/staging/r8188eu/core/rtw_mlme_ext.c +@@ -104,6 +104,7 @@ static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { + {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ + {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ + {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ ++ {0x00}, /* 0x13 */ + {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ + {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ + {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ +@@ -115,6 +116,7 @@ static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { + {0x00}, /* 0x1C, */ + {0x00}, /* 0x1D, */ + {0x00}, /* 0x1E, */ ++ {0x00}, /* 0x1F, */ + /* 0x20 ~ 0x7F , New Define ===== */ + {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ + {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ +@@ -7080,12 +7082,12 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct cmd_priv *pcmdpriv = &padapter->cmdpriv; + +- pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); ++ pcmd_obj = kzalloc(sizeof(*pcmd_obj), GFP_ATOMIC); + if (!pcmd_obj) + return; + + cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); +- pevtcmd = kzalloc(cmdsz, GFP_KERNEL); ++ pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); + if (!pevtcmd) { + kfree(pcmd_obj); + return; +diff --git a/drivers/staging/r8188eu/os_dep/ioctl_linux.c b/drivers/staging/r8188eu/os_dep/ioctl_linux.c +index 1fd3750760018..0eccce57c63a6 100644 +--- a/drivers/staging/r8188eu/os_dep/ioctl_linux.c ++++ b/drivers/staging/r8188eu/os_dep/ioctl_linux.c +@@ -1978,7 +1978,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, + struct ieee_param *param = NULL; + struct iw_point *pencoding = &wrqu->encoding; + struct iw_encode_ext *pext = (struct iw_encode_ext *)extra; +- int ret = 0; ++ int ret = -1; + + param_len = sizeof(struct ieee_param) + pext->key_len; + param = kzalloc(param_len, GFP_KERNEL); +@@ -2004,7 +2004,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, + alg_name = "CCMP"; + break; + default: +- return -1; ++ goto out; + } + + strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); +@@ -2031,6 +2031,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, + + ret = wpa_set_encryption(dev, param, param_len); + ++out: + kfree(param); + return ret; + } +@@ -2060,6 +2061,7 @@ static int rtw_wx_read32(struct net_device *dev, + u32 data32; + u32 bytes; + u8 *ptmp; ++ int ret; + + padapter = (struct adapter *)rtw_netdev_priv(dev); + p = &wrqu->data; +@@ -2092,12 +2094,17 @@ static int rtw_wx_read32(struct net_device *dev, + break; + default: + DBG_88E(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_free_ptmp; + } + DBG_88E(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra); + + kfree(ptmp); + return 0; ++ ++err_free_ptmp: ++ kfree(ptmp); ++ return ret; + } + + static int rtw_wx_write32(struct net_device *dev, +diff --git a/drivers/staging/r8188eu/os_dep/mlme_linux.c b/drivers/staging/r8188eu/os_dep/mlme_linux.c +index e3ee9dc7ab900..b0d1e20edc4c2 100644 +--- a/drivers/staging/r8188eu/os_dep/mlme_linux.c ++++ b/drivers/staging/r8188eu/os_dep/mlme_linux.c +@@ -114,7 +114,7 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie) + + buff = NULL; + if (authmode == _WPA_IE_ID_) { +- buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL); ++ buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC); + if (!buff) + return; + p = buff; +diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +index a7dd1578b2c6a..616ab3c8fde4f 100644 +--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c ++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +@@ -2549,13 +2549,14 @@ static void _rtl92e_pci_disconnect(struct pci_dev *pdev) + free_irq(dev->irq, dev); + priv->irq = 0; + } +- free_rtllib(dev); + + if (dev->mem_start != 0) { + iounmap((void __iomem *)dev->mem_start); + release_mem_region(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); + } ++ ++ free_rtllib(dev); + } + + pci_disable_device(pdev); +diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h +index c6f8b772335c1..c985e4ebc545a 100644 +--- a/drivers/staging/rtl8192e/rtllib.h ++++ b/drivers/staging/rtl8192e/rtllib.h +@@ -1980,7 +1980,7 @@ void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn); + void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee); + + void rtllib_start_ibss(struct rtllib_device *ieee); +-void rtllib_softmac_init(struct rtllib_device *ieee); ++int rtllib_softmac_init(struct rtllib_device *ieee); + void rtllib_softmac_free(struct rtllib_device *ieee); + void rtllib_disassociate(struct rtllib_device *ieee); + void rtllib_stop_scan(struct rtllib_device *ieee); +diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c +index 64d9feee1f392..f00ac94b2639b 100644 +--- a/drivers/staging/rtl8192e/rtllib_module.c ++++ b/drivers/staging/rtl8192e/rtllib_module.c +@@ -88,7 +88,7 @@ struct net_device *alloc_rtllib(int sizeof_priv) + err = rtllib_networks_allocate(ieee); + if (err) { + pr_err("Unable to allocate beacon storage: %d\n", err); +- goto failed; ++ goto free_netdev; + } + rtllib_networks_initialize(ieee); + +@@ -121,11 +121,13 @@ struct net_device *alloc_rtllib(int sizeof_priv) + ieee->hwsec_active = 0; + + memset(ieee->swcamtable, 0, sizeof(struct sw_cam_table) * 32); +- rtllib_softmac_init(ieee); ++ err = rtllib_softmac_init(ieee); ++ if (err) ++ goto free_crypt_info; + + ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL); + if (!ieee->pHTInfo) +- return NULL; ++ goto free_softmac; + + HTUpdateDefaultSetting(ieee); + HTInitializeHTInfo(ieee); +@@ -141,8 +143,14 @@ struct net_device *alloc_rtllib(int sizeof_priv) + + return dev; + +- failed: ++free_softmac: ++ rtllib_softmac_free(ieee); ++free_crypt_info: ++ lib80211_crypt_info_free(&ieee->crypt_info); ++ rtllib_networks_free(ieee); ++free_netdev: + free_netdev(dev); ++ + return NULL; + } + EXPORT_SYMBOL(alloc_rtllib); +diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c +index d2726d01c7573..503d33be71d99 100644 +--- a/drivers/staging/rtl8192e/rtllib_softmac.c ++++ b/drivers/staging/rtl8192e/rtllib_softmac.c +@@ -2952,7 +2952,7 @@ void rtllib_start_protocol(struct rtllib_device *ieee) + } + } + +-void rtllib_softmac_init(struct rtllib_device *ieee) ++int rtllib_softmac_init(struct rtllib_device *ieee) + { + int i; + +@@ -2963,7 +2963,8 @@ void rtllib_softmac_init(struct rtllib_device *ieee) + ieee->seq_ctrl[i] = 0; + ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC); + if (!ieee->dot11d_info) +- netdev_err(ieee->dev, "Can't alloc memory for DOT11D\n"); ++ return -ENOMEM; ++ + ieee->LinkDetectInfo.SlotIndex = 0; + ieee->LinkDetectInfo.SlotNum = 2; + ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0; +@@ -3029,6 +3030,7 @@ void rtllib_softmac_init(struct rtllib_device *ieee) + + tasklet_setup(&ieee->ps_task, rtllib_sta_ps); + ++ return 0; + } + + void rtllib_softmac_free(struct rtllib_device *ieee) +diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c +index b6698656fc014..cf5cfee2936fd 100644 +--- a/drivers/staging/rtl8192u/r8192U_core.c ++++ b/drivers/staging/rtl8192u/r8192U_core.c +@@ -229,7 +229,7 @@ int write_nic_byte_E(struct net_device *dev, int indx, u8 data) + + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, +- indx | 0xfe00, 0, usbdata, 1, HZ / 2); ++ indx | 0xfe00, 0, usbdata, 1, 500); + kfree(usbdata); + + if (status < 0) { +@@ -251,7 +251,7 @@ int read_nic_byte_E(struct net_device *dev, int indx, u8 *data) + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, +- indx | 0xfe00, 0, usbdata, 1, HZ / 2); ++ indx | 0xfe00, 0, usbdata, 1, 500); + *data = *usbdata; + kfree(usbdata); + +@@ -279,7 +279,7 @@ int write_nic_byte(struct net_device *dev, int indx, u8 data) + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, +- usbdata, 1, HZ / 2); ++ usbdata, 1, 500); + kfree(usbdata); + + if (status < 0) { +@@ -305,7 +305,7 @@ int write_nic_word(struct net_device *dev, int indx, u16 data) + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, +- usbdata, 2, HZ / 2); ++ usbdata, 2, 500); + kfree(usbdata); + + if (status < 0) { +@@ -331,7 +331,7 @@ int write_nic_dword(struct net_device *dev, int indx, u32 data) + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL8187_REQ_SET_REGS, RTL8187_REQT_WRITE, + (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, +- usbdata, 4, HZ / 2); ++ usbdata, 4, 500); + kfree(usbdata); + + if (status < 0) { +@@ -355,7 +355,7 @@ int read_nic_byte(struct net_device *dev, int indx, u8 *data) + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, +- usbdata, 1, HZ / 2); ++ usbdata, 1, 500); + *data = *usbdata; + kfree(usbdata); + +@@ -380,7 +380,7 @@ int read_nic_word(struct net_device *dev, int indx, u16 *data) + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, +- usbdata, 2, HZ / 2); ++ usbdata, 2, 500); + *data = *usbdata; + kfree(usbdata); + +@@ -404,7 +404,7 @@ static int read_nic_word_E(struct net_device *dev, int indx, u16 *data) + + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, +- indx | 0xfe00, 0, usbdata, 2, HZ / 2); ++ indx | 0xfe00, 0, usbdata, 2, 500); + *data = *usbdata; + kfree(usbdata); + +@@ -430,7 +430,7 @@ int read_nic_dword(struct net_device *dev, int indx, u32 *data) + status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL8187_REQ_GET_REGS, RTL8187_REQT_READ, + (indx & 0xff) | 0xff00, (indx >> 8) & 0x0f, +- usbdata, 4, HZ / 2); ++ usbdata, 4, 500); + *data = *usbdata; + kfree(usbdata); + +diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c +index 505ebeb643dc2..cae04272deffe 100644 +--- a/drivers/staging/rtl8712/usb_intf.c ++++ b/drivers/staging/rtl8712/usb_intf.c +@@ -595,12 +595,12 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) + + /* never exit with a firmware callback pending */ + wait_for_completion(&padapter->rtl8712_fw_ready); ++ if (pnetdev->reg_state != NETREG_UNINITIALIZED) ++ unregister_netdev(pnetdev); /* will call netdev_close() */ + usb_set_intfdata(pusb_intf, NULL); + release_firmware(padapter->fw); + if (drvpriv.drv_registered) + padapter->surprise_removed = true; +- if (pnetdev->reg_state != NETREG_UNINITIALIZED) +- unregister_netdev(pnetdev); /* will call netdev_close() */ + r8712_flush_rwctrl_works(padapter); + r8712_flush_led_works(padapter); + udelay(1); +diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c +index 655497cead122..f984a5ab2c6ff 100644 +--- a/drivers/staging/rtl8712/usb_ops_linux.c ++++ b/drivers/staging/rtl8712/usb_ops_linux.c +@@ -494,7 +494,7 @@ int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value, + memcpy(pIo_buf, pdata, len); + } + status = usb_control_msg(udev, pipe, request, reqtype, value, index, +- pIo_buf, len, HZ / 2); ++ pIo_buf, len, 500); + if (status > 0) { /* Success this control transfer. */ + if (requesttype == 0x01) { + /* For Control read transfer, we have to copy the read +diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c +index ab6a24d70cc96..cf79bec916c51 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c +@@ -897,7 +897,6 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) + { + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct wlan_network *tgt_network = &pmlmepriv->cur_network; +- struct sta_priv *pstapriv = &adapter->stapriv; + struct dvobj_priv *psdpriv = adapter->dvobj; + struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; + +@@ -905,11 +904,7 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) + struct sta_info *psta; + + psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.mac_address); +- spin_lock_bh(&(pstapriv->sta_hash_lock)); + rtw_free_stainfo(adapter, psta); +- +- spin_unlock_bh(&(pstapriv->sta_hash_lock)); +- + } + + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) { +@@ -1239,16 +1234,13 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) + rtw_indicate_connect(adapter); + } + ++ spin_unlock_bh(&pmlmepriv->scanned_queue.lock); ++ + /* s5. Cancel assoc_timer */ + del_timer_sync(&pmlmepriv->assoc_timer); +- + } else { + spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); +- goto ignore_joinbss_callback; + } +- +- spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); +- + } else if (pnetwork->join_res == -4) { + rtw_reset_securitypriv(adapter); + _set_timer(&pmlmepriv->assoc_timer, 1); +diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +index 375d2a742dd2d..ad9c237054c4b 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c ++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +@@ -1489,9 +1489,7 @@ unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame) + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + +- /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ + /* rtw_free_stainfo(padapter, psta); */ +- /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ + + netdev_dbg(padapter->pnetdev, + "ap recv deauth reason code(%d) sta:%pM\n", reason, +@@ -1565,9 +1563,7 @@ unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame) + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + +- /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ + /* rtw_free_stainfo(padapter, psta); */ +- /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ + + netdev_dbg(padapter->pnetdev, + "ap recv disassoc reason code(%d) sta:%pM\n", +@@ -5919,7 +5915,6 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) + struct sta_info *psta_bmc; + struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; + struct xmit_frame *pxmitframe = NULL; +- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct sta_priv *pstapriv = &padapter->stapriv; + + /* for BC/MC Frames */ +@@ -5930,8 +5925,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) + if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { + msleep(10);/* 10ms, ATIM(HIQ) Windows */ + +- /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ +- spin_lock_bh(&pxmitpriv->lock); ++ spin_lock_bh(&psta_bmc->sleep_q.lock); + + xmitframe_phead = get_list_head(&psta_bmc->sleep_q); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { +@@ -5954,8 +5948,7 @@ u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) + rtw_hal_xmitframe_enqueue(padapter, pxmitframe); + } + +- /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ +- spin_unlock_bh(&pxmitpriv->lock); ++ spin_unlock_bh(&psta_bmc->sleep_q.lock); + + /* check hi queue and bmc_sleepq */ + rtw_chk_hi_queue_cmd(padapter); +diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c +index 5b0a596eefb77..3564e2af5741b 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_recv.c ++++ b/drivers/staging/rtl8723bs/core/rtw_recv.c +@@ -953,10 +953,8 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_ + if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) { + struct list_head *xmitframe_plist, *xmitframe_phead; + struct xmit_frame *pxmitframe = NULL; +- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + +- /* spin_lock_bh(&psta->sleep_q.lock); */ +- spin_lock_bh(&pxmitpriv->lock); ++ spin_lock_bh(&psta->sleep_q.lock); + + xmitframe_phead = get_list_head(&psta->sleep_q); + xmitframe_plist = get_next(xmitframe_phead); +@@ -987,12 +985,10 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_ + update_beacon(padapter, WLAN_EID_TIM, NULL, true); + } + +- /* spin_unlock_bh(&psta->sleep_q.lock); */ +- spin_unlock_bh(&pxmitpriv->lock); ++ spin_unlock_bh(&psta->sleep_q.lock); + + } else { +- /* spin_unlock_bh(&psta->sleep_q.lock); */ +- spin_unlock_bh(&pxmitpriv->lock); ++ spin_unlock_bh(&psta->sleep_q.lock); + + if (pstapriv->tim_bitmap&BIT(psta->aid)) { + if (psta->sleepq_len == 0) { +diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c +index 67ca219f95bf8..3d269842677dd 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c ++++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c +@@ -263,7 +263,6 @@ exit: + return psta; + } + +-/* using pstapriv->sta_hash_lock to protect */ + u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) + { + int i; +@@ -289,51 +288,55 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) + + /* list_del_init(&psta->wakeup_list); */ + +- spin_lock_bh(&pxmitpriv->lock); +- ++ spin_lock_bh(&psta->sleep_q.lock); + rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); + psta->sleepq_len = 0; ++ spin_unlock_bh(&psta->sleep_q.lock); ++ ++ spin_lock_bh(&pxmitpriv->lock); + + /* vo */ +- /* spin_lock_bh(&(pxmitpriv->vo_pending.lock)); */ ++ spin_lock_bh(&pstaxmitpriv->vo_q.sta_pending.lock); + rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); + list_del_init(&(pstaxmitpriv->vo_q.tx_pending)); + phwxmit = pxmitpriv->hwxmits; + phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; + pstaxmitpriv->vo_q.qcnt = 0; +- /* spin_unlock_bh(&(pxmitpriv->vo_pending.lock)); */ ++ spin_unlock_bh(&pstaxmitpriv->vo_q.sta_pending.lock); + + /* vi */ +- /* spin_lock_bh(&(pxmitpriv->vi_pending.lock)); */ ++ spin_lock_bh(&pstaxmitpriv->vi_q.sta_pending.lock); + rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); + list_del_init(&(pstaxmitpriv->vi_q.tx_pending)); + phwxmit = pxmitpriv->hwxmits+1; + phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; + pstaxmitpriv->vi_q.qcnt = 0; +- /* spin_unlock_bh(&(pxmitpriv->vi_pending.lock)); */ ++ spin_unlock_bh(&pstaxmitpriv->vi_q.sta_pending.lock); + + /* be */ +- /* spin_lock_bh(&(pxmitpriv->be_pending.lock)); */ ++ spin_lock_bh(&pstaxmitpriv->be_q.sta_pending.lock); + rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); + list_del_init(&(pstaxmitpriv->be_q.tx_pending)); + phwxmit = pxmitpriv->hwxmits+2; + phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; + pstaxmitpriv->be_q.qcnt = 0; +- /* spin_unlock_bh(&(pxmitpriv->be_pending.lock)); */ ++ spin_unlock_bh(&pstaxmitpriv->be_q.sta_pending.lock); + + /* bk */ +- /* spin_lock_bh(&(pxmitpriv->bk_pending.lock)); */ ++ spin_lock_bh(&pstaxmitpriv->bk_q.sta_pending.lock); + rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); + list_del_init(&(pstaxmitpriv->bk_q.tx_pending)); + phwxmit = pxmitpriv->hwxmits+3; + phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; + pstaxmitpriv->bk_q.qcnt = 0; +- /* spin_unlock_bh(&(pxmitpriv->bk_pending.lock)); */ ++ spin_unlock_bh(&pstaxmitpriv->bk_q.sta_pending.lock); + + spin_unlock_bh(&pxmitpriv->lock); + ++ spin_lock_bh(&pstapriv->sta_hash_lock); + list_del_init(&psta->hash_list); + pstapriv->asoc_sta_count--; ++ spin_unlock_bh(&pstapriv->sta_hash_lock); + + /* re-init sta_info; 20061114 will be init in alloc_stainfo */ + /* _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); */ +@@ -428,6 +431,7 @@ void rtw_free_all_stainfo(struct adapter *padapter) + struct sta_info *psta = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; + struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter); ++ LIST_HEAD(stainfo_free_list); + + if (pstapriv->asoc_sta_count == 1) + return; +@@ -440,11 +444,16 @@ void rtw_free_all_stainfo(struct adapter *padapter) + psta = list_entry(plist, struct sta_info, hash_list); + + if (pbcmc_stainfo != psta) +- rtw_free_stainfo(padapter, psta); ++ list_move(&psta->hash_list, &stainfo_free_list); + } + } + + spin_unlock_bh(&pstapriv->sta_hash_lock); ++ ++ list_for_each_safe(plist, tmp, &stainfo_free_list) { ++ psta = list_entry(plist, struct sta_info, hash_list); ++ rtw_free_stainfo(padapter, psta); ++ } + } + + /* any station allocated can be searched by hash list */ +diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c +index 79e4d7df1ef57..6b37b42ec2266 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c ++++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c +@@ -1723,15 +1723,12 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram + struct list_head *plist, *phead, *tmp; + struct xmit_frame *pxmitframe; + +- spin_lock_bh(&pframequeue->lock); +- + phead = get_list_head(pframequeue); + list_for_each_safe(plist, tmp, phead) { + pxmitframe = list_entry(plist, struct xmit_frame, list); + + rtw_free_xmitframe(pxmitpriv, pxmitframe); + } +- spin_unlock_bh(&pframequeue->lock); + } + + s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe) +@@ -1786,6 +1783,7 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) + struct sta_info *psta; + struct tx_servq *ptxservq; + struct pkt_attrib *pattrib = &pxmitframe->attrib; ++ struct xmit_priv *xmit_priv = &padapter->xmitpriv; + struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; + signed int res = _SUCCESS; + +@@ -1803,12 +1801,14 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) + + ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); + ++ spin_lock_bh(&xmit_priv->lock); + if (list_empty(&ptxservq->tx_pending)) + list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue)); + + list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); + ptxservq->qcnt++; + phwxmits[ac_index].accnt++; ++ spin_unlock_bh(&xmit_priv->lock); + + exit: + +@@ -2191,11 +2191,10 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) + struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; + struct xmit_frame *pxmitframe = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; +- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + + psta_bmc = rtw_get_bcmc_stainfo(padapter); + +- spin_lock_bh(&pxmitpriv->lock); ++ spin_lock_bh(&psta->sleep_q.lock); + + xmitframe_phead = get_list_head(&psta->sleep_q); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { +@@ -2296,7 +2295,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) + + _exit: + +- spin_unlock_bh(&pxmitpriv->lock); ++ spin_unlock_bh(&psta->sleep_q.lock); + + if (update_mask) + update_beacon(padapter, WLAN_EID_TIM, NULL, true); +@@ -2308,9 +2307,8 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst + struct list_head *xmitframe_plist, *xmitframe_phead, *tmp; + struct xmit_frame *pxmitframe = NULL; + struct sta_priv *pstapriv = &padapter->stapriv; +- struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + +- spin_lock_bh(&pxmitpriv->lock); ++ spin_lock_bh(&psta->sleep_q.lock); + + xmitframe_phead = get_list_head(&psta->sleep_q); + list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) { +@@ -2363,7 +2361,7 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst + } + } + +- spin_unlock_bh(&pxmitpriv->lock); ++ spin_unlock_bh(&psta->sleep_q.lock); + } + + void enqueue_pending_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c +index 156d6aba18ca1..5f5c4719b5868 100644 +--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c ++++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c +@@ -507,9 +507,7 @@ s32 rtl8723bs_hal_xmit( + rtw_issue_addbareq_cmd(padapter, pxmitframe); + } + +- spin_lock_bh(&pxmitpriv->lock); + err = rtw_xmitframe_enqueue(padapter, pxmitframe); +- spin_unlock_bh(&pxmitpriv->lock); + if (err != _SUCCESS) { + rtw_free_xmitframe(pxmitpriv, pxmitframe); + +diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +index 9d4a233a861e3..295121c268bd4 100644 +--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +@@ -835,9 +835,7 @@ static int rtw_add_sta(struct net_device *dev, struct ieee_param *param) + psta = rtw_get_stainfo(pstapriv, param->sta_addr); + if (psta) + { +- spin_lock_bh(&(pstapriv->sta_hash_lock)); + rtw_free_stainfo(padapter, psta); +- spin_unlock_bh(&(pstapriv->sta_hash_lock)); + + psta = NULL; + } +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +index 967f10b9582a8..ea9a53bdb4174 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +@@ -1033,15 +1033,27 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header, + + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + ++ rcu_read_lock(); + service = handle_to_service(handle); +- if (WARN_ON(!service)) ++ if (WARN_ON(!service)) { ++ rcu_read_unlock(); + return VCHIQ_SUCCESS; ++ } + + user_service = (struct user_service *)service->base.userdata; + instance = user_service->instance; + +- if (!instance || instance->closing) ++ if (!instance || instance->closing) { ++ rcu_read_unlock(); + return VCHIQ_SUCCESS; ++ } ++ ++ /* ++ * As hopping around different synchronization mechanism, ++ * taking an extra reference results in simpler implementation. ++ */ ++ vchiq_service_get(service); ++ rcu_read_unlock(); + + vchiq_log_trace(vchiq_arm_log_level, + "%s - service %lx(%d,%p), reason %d, header %lx, instance %lx, bulk_userdata %lx", +@@ -1074,6 +1086,7 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header, + NULL, user_service, bulk_userdata); + if (status != VCHIQ_SUCCESS) { + DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ vchiq_service_put(service); + return status; + } + } +@@ -1084,11 +1097,13 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header, + vchiq_log_info(vchiq_arm_log_level, + "%s interrupted", __func__); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ vchiq_service_put(service); + return VCHIQ_RETRY; + } else if (instance->closing) { + vchiq_log_info(vchiq_arm_log_level, + "%s closing", __func__); + DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ vchiq_service_put(service); + return VCHIQ_ERROR; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); +@@ -1117,6 +1132,7 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header, + header = NULL; + } + DEBUG_TRACE(SERVICE_CALLBACK_LINE); ++ vchiq_service_put(service); + + if (skip_completion) + return VCHIQ_SUCCESS; +diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c +index e06d7e1ebe9c3..61b8cc05f2935 100644 +--- a/drivers/staging/wfx/bus_sdio.c ++++ b/drivers/staging/wfx/bus_sdio.c +@@ -120,19 +120,22 @@ static int wfx_sdio_irq_subscribe(void *priv) + return ret; + } + ++ flags = irq_get_trigger_type(bus->of_irq); ++ if (!flags) ++ flags = IRQF_TRIGGER_HIGH; ++ flags |= IRQF_ONESHOT; ++ ret = devm_request_threaded_irq(&bus->func->dev, bus->of_irq, NULL, ++ wfx_sdio_irq_handler_ext, flags, ++ "wfx", bus); ++ if (ret) ++ return ret; + sdio_claim_host(bus->func); + cccr = sdio_f0_readb(bus->func, SDIO_CCCR_IENx, NULL); + cccr |= BIT(0); + cccr |= BIT(bus->func->num); + sdio_f0_writeb(bus->func, cccr, SDIO_CCCR_IENx, NULL); + sdio_release_host(bus->func); +- flags = irq_get_trigger_type(bus->of_irq); +- if (!flags) +- flags = IRQF_TRIGGER_HIGH; +- flags |= IRQF_ONESHOT; +- return devm_request_threaded_irq(&bus->func->dev, bus->of_irq, NULL, +- wfx_sdio_irq_handler_ext, flags, +- "wfx", bus); ++ return 0; + } + + static int wfx_sdio_irq_unsubscribe(void *priv) +diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c +index 8c8524679ba38..0d869b5e309c0 100644 +--- a/drivers/staging/wlan-ng/hfa384x_usb.c ++++ b/drivers/staging/wlan-ng/hfa384x_usb.c +@@ -3778,18 +3778,18 @@ static void hfa384x_usb_throttlefn(struct timer_list *t) + + spin_lock_irqsave(&hw->ctlxq.lock, flags); + +- /* +- * We need to check BOTH the RX and the TX throttle controls, +- * so we use the bitwise OR instead of the logical OR. +- */ + pr_debug("flags=0x%lx\n", hw->usb_flags); +- if (!hw->wlandev->hwremoved && +- ((test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && +- !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) | +- (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && +- !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) +- )) { +- schedule_work(&hw->usb_work); ++ if (!hw->wlandev->hwremoved) { ++ bool rx_throttle = test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && ++ !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags); ++ bool tx_throttle = test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && ++ !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags); ++ /* ++ * We need to check BOTH the RX and the TX throttle controls, ++ * so we use the bitwise OR instead of the logical OR. ++ */ ++ if (rx_throttle | tx_throttle) ++ schedule_work(&hw->usb_work); + } + + spin_unlock_irqrestore(&hw->ctlxq.lock, flags); +diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c +index 8075f60fd02c3..2d5cf1714ae05 100644 +--- a/drivers/target/iscsi/iscsi_target_tpg.c ++++ b/drivers/target/iscsi/iscsi_target_tpg.c +@@ -443,6 +443,9 @@ static bool iscsit_tpg_check_network_portal( + break; + } + spin_unlock(&tpg->tpg_np_lock); ++ ++ if (match) ++ break; + } + spin_unlock(&tiqn->tiqn_tpg_lock); + +diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c +index cb1de1ecaaa61..bd0f2ce011dd7 100644 +--- a/drivers/target/target_core_alua.c ++++ b/drivers/target/target_core_alua.c +@@ -1674,7 +1674,6 @@ int core_alua_set_tg_pt_gp_id( + pr_err("Maximum ALUA alua_tg_pt_gps_count:" + " 0x0000ffff reached\n"); + spin_unlock(&dev->t10_alua.tg_pt_gps_lock); +- kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); + return -ENOSPC; + } + again: +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 8cb1fa0c05857..44bb380e7390c 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -772,6 +772,8 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) + INIT_LIST_HEAD(&dev->t10_alua.lba_map_list); + spin_lock_init(&dev->t10_alua.lba_map_lock); + ++ INIT_WORK(&dev->delayed_cmd_work, target_do_delayed_work); ++ + dev->t10_wwn.t10_dev = dev; + /* + * Use OpenFabrics IEEE Company ID: 00 14 05 +diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h +index a343bcfa2180f..a889a6237d9c1 100644 +--- a/drivers/target/target_core_internal.h ++++ b/drivers/target/target_core_internal.h +@@ -151,6 +151,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); + void transport_clear_lun_ref(struct se_lun *); + sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); + void target_qf_do_work(struct work_struct *work); ++void target_do_delayed_work(struct work_struct *work); + bool target_check_wce(struct se_device *dev); + bool target_check_fua(struct se_device *dev); + void __target_execute_cmd(struct se_cmd *, bool); +diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c +index e7fcbc09f9dbc..bac111456fa1d 100644 +--- a/drivers/target/target_core_tmr.c ++++ b/drivers/target/target_core_tmr.c +@@ -50,15 +50,6 @@ EXPORT_SYMBOL(core_tmr_alloc_req); + + void core_tmr_release_req(struct se_tmr_req *tmr) + { +- struct se_device *dev = tmr->tmr_dev; +- unsigned long flags; +- +- if (dev) { +- spin_lock_irqsave(&dev->se_tmr_lock, flags); +- list_del_init(&tmr->tmr_list); +- spin_unlock_irqrestore(&dev->se_tmr_lock, flags); +- } +- + kfree(tmr); + } + +@@ -156,13 +147,6 @@ void core_tmr_abort_task( + se_cmd->state_active = false; + spin_unlock_irqrestore(&dev->queues[i].lock, flags); + +- /* +- * Ensure that this ABORT request is visible to the LU +- * RESET code. +- */ +- if (!tmr->tmr_dev) +- WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < 0); +- + if (dev->transport->tmr_notify) + dev->transport->tmr_notify(dev, TMR_ABORT_TASK, + &aborted_list); +@@ -234,6 +218,7 @@ static void core_tmr_drain_tmr_list( + } + + list_move_tail(&tmr_p->tmr_list, &drain_tmr_list); ++ tmr_p->tmr_dev = NULL; + } + spin_unlock_irqrestore(&dev->se_tmr_lock, flags); + +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 14c6f2bb1b01d..72edf5bd75ee6 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -676,6 +676,21 @@ static void target_remove_from_state_list(struct se_cmd *cmd) + spin_unlock_irqrestore(&dev->queues[cmd->cpuid].lock, flags); + } + ++static void target_remove_from_tmr_list(struct se_cmd *cmd) ++{ ++ struct se_device *dev = NULL; ++ unsigned long flags; ++ ++ if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) ++ dev = cmd->se_tmr_req->tmr_dev; ++ ++ if (dev) { ++ spin_lock_irqsave(&dev->se_tmr_lock, flags); ++ if (cmd->se_tmr_req->tmr_dev) ++ list_del_init(&cmd->se_tmr_req->tmr_list); ++ spin_unlock_irqrestore(&dev->se_tmr_lock, flags); ++ } ++} + /* + * This function is called by the target core after the target core has + * finished processing a SCSI command or SCSI TMF. Both the regular command +@@ -687,13 +702,6 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd) + { + unsigned long flags; + +- target_remove_from_state_list(cmd); +- +- /* +- * Clear struct se_cmd->se_lun before the handoff to FE. +- */ +- cmd->se_lun = NULL; +- + spin_lock_irqsave(&cmd->t_state_lock, flags); + /* + * Determine if frontend context caller is requesting the stopping of +@@ -728,8 +736,16 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) + if (!lun) + return; + ++ target_remove_from_state_list(cmd); ++ target_remove_from_tmr_list(cmd); ++ + if (cmpxchg(&cmd->lun_ref_active, true, false)) + percpu_ref_put(&lun->lun_ref); ++ ++ /* ++ * Clear struct se_cmd->se_lun before the handoff to FE. ++ */ ++ cmd->se_lun = NULL; + } + + static void target_complete_failure_work(struct work_struct *work) +@@ -2173,32 +2189,35 @@ static bool target_handle_task_attr(struct se_cmd *cmd) + */ + switch (cmd->sam_task_attr) { + case TCM_HEAD_TAG: ++ atomic_inc_mb(&dev->non_ordered); + pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x\n", + cmd->t_task_cdb[0]); + return false; + case TCM_ORDERED_TAG: +- atomic_inc_mb(&dev->dev_ordered_sync); ++ atomic_inc_mb(&dev->delayed_cmd_count); + + pr_debug("Added ORDERED for CDB: 0x%02x to ordered list\n", + cmd->t_task_cdb[0]); +- +- /* +- * Execute an ORDERED command if no other older commands +- * exist that need to be completed first. +- */ +- if (!atomic_read(&dev->simple_cmds)) +- return false; + break; + default: + /* + * For SIMPLE and UNTAGGED Task Attribute commands + */ +- atomic_inc_mb(&dev->simple_cmds); ++ atomic_inc_mb(&dev->non_ordered); ++ ++ if (atomic_read(&dev->delayed_cmd_count) == 0) ++ return false; + break; + } + +- if (atomic_read(&dev->dev_ordered_sync) == 0) +- return false; ++ if (cmd->sam_task_attr != TCM_ORDERED_TAG) { ++ atomic_inc_mb(&dev->delayed_cmd_count); ++ /* ++ * We will account for this when we dequeue from the delayed ++ * list. ++ */ ++ atomic_dec_mb(&dev->non_ordered); ++ } + + spin_lock(&dev->delayed_cmd_lock); + list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list); +@@ -2206,6 +2225,12 @@ static bool target_handle_task_attr(struct se_cmd *cmd) + + pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to delayed CMD listn", + cmd->t_task_cdb[0], cmd->sam_task_attr); ++ /* ++ * We may have no non ordered cmds when this function started or we ++ * could have raced with the last simple/head cmd completing, so kick ++ * the delayed handler here. ++ */ ++ schedule_work(&dev->delayed_cmd_work); + return true; + } + +@@ -2243,29 +2268,48 @@ EXPORT_SYMBOL(target_execute_cmd); + * Process all commands up to the last received ORDERED task attribute which + * requires another blocking boundary + */ +-static void target_restart_delayed_cmds(struct se_device *dev) ++void target_do_delayed_work(struct work_struct *work) + { +- for (;;) { ++ struct se_device *dev = container_of(work, struct se_device, ++ delayed_cmd_work); ++ ++ spin_lock(&dev->delayed_cmd_lock); ++ while (!dev->ordered_sync_in_progress) { + struct se_cmd *cmd; + +- spin_lock(&dev->delayed_cmd_lock); +- if (list_empty(&dev->delayed_cmd_list)) { +- spin_unlock(&dev->delayed_cmd_lock); ++ if (list_empty(&dev->delayed_cmd_list)) + break; +- } + + cmd = list_entry(dev->delayed_cmd_list.next, + struct se_cmd, se_delayed_node); ++ ++ if (cmd->sam_task_attr == TCM_ORDERED_TAG) { ++ /* ++ * Check if we started with: ++ * [ordered] [simple] [ordered] ++ * and we are now at the last ordered so we have to wait ++ * for the simple cmd. ++ */ ++ if (atomic_read(&dev->non_ordered) > 0) ++ break; ++ ++ dev->ordered_sync_in_progress = true; ++ } ++ + list_del(&cmd->se_delayed_node); ++ atomic_dec_mb(&dev->delayed_cmd_count); + spin_unlock(&dev->delayed_cmd_lock); + ++ if (cmd->sam_task_attr != TCM_ORDERED_TAG) ++ atomic_inc_mb(&dev->non_ordered); ++ + cmd->transport_state |= CMD_T_SENT; + + __target_execute_cmd(cmd, true); + +- if (cmd->sam_task_attr == TCM_ORDERED_TAG) +- break; ++ spin_lock(&dev->delayed_cmd_lock); + } ++ spin_unlock(&dev->delayed_cmd_lock); + } + + /* +@@ -2283,14 +2327,17 @@ static void transport_complete_task_attr(struct se_cmd *cmd) + goto restart; + + if (cmd->sam_task_attr == TCM_SIMPLE_TAG) { +- atomic_dec_mb(&dev->simple_cmds); ++ atomic_dec_mb(&dev->non_ordered); + dev->dev_cur_ordered_id++; + } else if (cmd->sam_task_attr == TCM_HEAD_TAG) { ++ atomic_dec_mb(&dev->non_ordered); + dev->dev_cur_ordered_id++; + pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n", + dev->dev_cur_ordered_id); + } else if (cmd->sam_task_attr == TCM_ORDERED_TAG) { +- atomic_dec_mb(&dev->dev_ordered_sync); ++ spin_lock(&dev->delayed_cmd_lock); ++ dev->ordered_sync_in_progress = false; ++ spin_unlock(&dev->delayed_cmd_lock); + + dev->dev_cur_ordered_id++; + pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", +@@ -2299,7 +2346,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd) + cmd->se_cmd_flags &= ~SCF_TASK_ATTR_SET; + + restart: +- target_restart_delayed_cmds(dev); ++ if (atomic_read(&dev->delayed_cmd_count) > 0) ++ schedule_work(&dev->delayed_cmd_work); + } + + static void transport_complete_qf(struct se_cmd *cmd) +diff --git a/drivers/tee/amdtee/core.c b/drivers/tee/amdtee/core.c +index da6b88e80dc07..297dc62bca298 100644 +--- a/drivers/tee/amdtee/core.c ++++ b/drivers/tee/amdtee/core.c +@@ -203,9 +203,8 @@ static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta, + + *ta_size = roundup(fw->size, PAGE_SIZE); + *ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size)); +- if (IS_ERR(*ta)) { +- pr_err("%s: get_free_pages failed 0x%llx\n", __func__, +- (u64)*ta); ++ if (!*ta) { ++ pr_err("%s: get_free_pages failed\n", __func__); + rc = -ENOMEM; + goto rel_fw; + } +diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c +index 5363ebebfc357..50c0d839fe751 100644 +--- a/drivers/tee/optee/core.c ++++ b/drivers/tee/optee/core.c +@@ -588,6 +588,7 @@ static int optee_remove(struct platform_device *pdev) + /* Unregister OP-TEE specific client devices on TEE bus */ + optee_unregister_devices(); + ++ teedev_close_context(optee->ctx); + /* + * Ask OP-TEE to free all cached shared memory objects to decrease + * reference counters and also avoid wild pointers in secure world +@@ -633,6 +634,7 @@ static int optee_probe(struct platform_device *pdev) + struct optee *optee = NULL; + void *memremaped_shm = NULL; + struct tee_device *teedev; ++ struct tee_context *ctx; + u32 sec_caps; + int rc; + +@@ -719,6 +721,12 @@ static int optee_probe(struct platform_device *pdev) + optee_supp_init(&optee->supp); + optee->memremaped_shm = memremaped_shm; + optee->pool = pool; ++ ctx = teedev_open(optee->teedev); ++ if (IS_ERR(ctx)) { ++ rc = PTR_ERR(ctx); ++ goto err; ++ } ++ optee->ctx = ctx; + + /* + * Ensure that there are no pre-existing shm objects before enabling +diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h +index f6bb4a763ba94..ea09533e30cde 100644 +--- a/drivers/tee/optee/optee_private.h ++++ b/drivers/tee/optee/optee_private.h +@@ -70,6 +70,7 @@ struct optee_supp { + * struct optee - main service struct + * @supp_teedev: supplicant device + * @teedev: client device ++ * @ctx: driver internal TEE context + * @invoke_fn: function to issue smc or hvc + * @call_queue: queue of threads waiting to call @invoke_fn + * @wait_queue: queue of threads from secure world waiting for a +@@ -87,6 +88,7 @@ struct optee { + struct tee_device *supp_teedev; + struct tee_device *teedev; + optee_invoke_fn *invoke_fn; ++ struct tee_context *ctx; + struct optee_call_queue call_queue; + struct optee_wait_queue wait_queue; + struct optee_supp supp; +diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c +index efbaff7ad7e59..456833d820078 100644 +--- a/drivers/tee/optee/rpc.c ++++ b/drivers/tee/optee/rpc.c +@@ -285,6 +285,7 @@ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz) + } + + static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, ++ struct optee *optee, + struct optee_msg_arg *arg, + struct optee_call_ctx *call_ctx) + { +@@ -314,7 +315,8 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx, + shm = cmd_alloc_suppl(ctx, sz); + break; + case OPTEE_RPC_SHM_TYPE_KERNEL: +- shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV); ++ shm = tee_shm_alloc(optee->ctx, sz, ++ TEE_SHM_MAPPED | TEE_SHM_PRIV); + break; + default: + arg->ret = TEEC_ERROR_BAD_PARAMETERS; +@@ -471,7 +473,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee, + break; + case OPTEE_RPC_CMD_SHM_ALLOC: + free_pages_list(call_ctx); +- handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx); ++ handle_rpc_func_cmd_shm_alloc(ctx, optee, arg, call_ctx); + break; + case OPTEE_RPC_CMD_SHM_FREE: + handle_rpc_func_cmd_shm_free(ctx, arg); +@@ -502,7 +504,7 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param, + + switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) { + case OPTEE_SMC_RPC_FUNC_ALLOC: +- shm = tee_shm_alloc(ctx, param->a1, ++ shm = tee_shm_alloc(optee->ctx, param->a1, + TEE_SHM_MAPPED | TEE_SHM_PRIV); + if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) { + reg_pair_from_64(¶m->a1, ¶m->a2, pa); +diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c +index d167039af519e..1aa843f2ecc7c 100644 +--- a/drivers/tee/optee/shm_pool.c ++++ b/drivers/tee/optee/shm_pool.c +@@ -41,10 +41,8 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm, + goto err; + } + +- for (i = 0; i < nr_pages; i++) { +- pages[i] = page; +- page++; +- } ++ for (i = 0; i < nr_pages; i++) ++ pages[i] = page + i; + + shm->flags |= TEE_SHM_REGISTER; + rc = optee_shm_register(shm->ctx, shm, pages, nr_pages, +diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c +index 2b37bc408fc3d..3fc426dad2df3 100644 +--- a/drivers/tee/tee_core.c ++++ b/drivers/tee/tee_core.c +@@ -43,7 +43,7 @@ static DEFINE_SPINLOCK(driver_lock); + static struct class *tee_class; + static dev_t tee_devt; + +-static struct tee_context *teedev_open(struct tee_device *teedev) ++struct tee_context *teedev_open(struct tee_device *teedev) + { + int rc; + struct tee_context *ctx; +@@ -70,6 +70,7 @@ err: + return ERR_PTR(rc); + + } ++EXPORT_SYMBOL_GPL(teedev_open); + + void teedev_ctx_get(struct tee_context *ctx) + { +@@ -96,11 +97,14 @@ void teedev_ctx_put(struct tee_context *ctx) + kref_put(&ctx->refcount, teedev_ctx_release); + } + +-static void teedev_close_context(struct tee_context *ctx) ++void teedev_close_context(struct tee_context *ctx) + { +- tee_device_put(ctx->teedev); ++ struct tee_device *teedev = ctx->teedev; ++ + teedev_ctx_put(ctx); ++ tee_device_put(teedev); + } ++EXPORT_SYMBOL_GPL(teedev_close_context); + + static int tee_open(struct inode *inode, struct file *filp) + { +diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c +index 8a9384a64f3e2..499fccba3d74b 100644 +--- a/drivers/tee/tee_shm.c ++++ b/drivers/tee/tee_shm.c +@@ -1,11 +1,11 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* +- * Copyright (c) 2015-2016, Linaro Limited ++ * Copyright (c) 2015-2017, 2019-2021 Linaro Limited + */ ++#include <linux/anon_inodes.h> + #include <linux/device.h> +-#include <linux/dma-buf.h> +-#include <linux/fdtable.h> + #include <linux/idr.h> ++#include <linux/mm.h> + #include <linux/sched.h> + #include <linux/slab.h> + #include <linux/tee_drv.h> +@@ -28,16 +28,8 @@ static void release_registered_pages(struct tee_shm *shm) + } + } + +-static void tee_shm_release(struct tee_shm *shm) ++static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) + { +- struct tee_device *teedev = shm->ctx->teedev; +- +- if (shm->flags & TEE_SHM_DMA_BUF) { +- mutex_lock(&teedev->mutex); +- idr_remove(&teedev->idr, shm->id); +- mutex_unlock(&teedev->mutex); +- } +- + if (shm->flags & TEE_SHM_POOL) { + struct tee_shm_pool_mgr *poolm; + +@@ -64,45 +56,6 @@ static void tee_shm_release(struct tee_shm *shm) + tee_device_put(teedev); + } + +-static struct sg_table *tee_shm_op_map_dma_buf(struct dma_buf_attachment +- *attach, enum dma_data_direction dir) +-{ +- return NULL; +-} +- +-static void tee_shm_op_unmap_dma_buf(struct dma_buf_attachment *attach, +- struct sg_table *table, +- enum dma_data_direction dir) +-{ +-} +- +-static void tee_shm_op_release(struct dma_buf *dmabuf) +-{ +- struct tee_shm *shm = dmabuf->priv; +- +- tee_shm_release(shm); +-} +- +-static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +-{ +- struct tee_shm *shm = dmabuf->priv; +- size_t size = vma->vm_end - vma->vm_start; +- +- /* Refuse sharing shared memory provided by application */ +- if (shm->flags & TEE_SHM_USER_MAPPED) +- return -EINVAL; +- +- return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT, +- size, vma->vm_page_prot); +-} +- +-static const struct dma_buf_ops tee_shm_dma_buf_ops = { +- .map_dma_buf = tee_shm_op_map_dma_buf, +- .unmap_dma_buf = tee_shm_op_unmap_dma_buf, +- .release = tee_shm_op_release, +- .mmap = tee_shm_op_mmap, +-}; +- + struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) + { + struct tee_device *teedev = ctx->teedev; +@@ -137,6 +90,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) + goto err_dev_put; + } + ++ refcount_set(&shm->refcount, 1); + shm->flags = flags | TEE_SHM_POOL; + shm->ctx = ctx; + if (flags & TEE_SHM_DMA_BUF) +@@ -150,10 +104,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) + goto err_kfree; + } + +- + if (flags & TEE_SHM_DMA_BUF) { +- DEFINE_DMA_BUF_EXPORT_INFO(exp_info); +- + mutex_lock(&teedev->mutex); + shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); + mutex_unlock(&teedev->mutex); +@@ -161,28 +112,11 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) + ret = ERR_PTR(shm->id); + goto err_pool_free; + } +- +- exp_info.ops = &tee_shm_dma_buf_ops; +- exp_info.size = shm->size; +- exp_info.flags = O_RDWR; +- exp_info.priv = shm; +- +- shm->dmabuf = dma_buf_export(&exp_info); +- if (IS_ERR(shm->dmabuf)) { +- ret = ERR_CAST(shm->dmabuf); +- goto err_rem; +- } + } + + teedev_ctx_get(ctx); + + return shm; +-err_rem: +- if (flags & TEE_SHM_DMA_BUF) { +- mutex_lock(&teedev->mutex); +- idr_remove(&teedev->idr, shm->id); +- mutex_unlock(&teedev->mutex); +- } + err_pool_free: + poolm->ops->free(poolm, shm); + err_kfree: +@@ -243,6 +177,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, + goto err; + } + ++ refcount_set(&shm->refcount, 1); + shm->flags = flags | TEE_SHM_REGISTER; + shm->ctx = ctx; + shm->id = -1; +@@ -303,22 +238,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, + goto err; + } + +- if (flags & TEE_SHM_DMA_BUF) { +- DEFINE_DMA_BUF_EXPORT_INFO(exp_info); +- +- exp_info.ops = &tee_shm_dma_buf_ops; +- exp_info.size = shm->size; +- exp_info.flags = O_RDWR; +- exp_info.priv = shm; +- +- shm->dmabuf = dma_buf_export(&exp_info); +- if (IS_ERR(shm->dmabuf)) { +- ret = ERR_CAST(shm->dmabuf); +- teedev->desc->ops->shm_unregister(ctx, shm); +- goto err; +- } +- } +- + return shm; + err: + if (shm) { +@@ -336,6 +255,35 @@ err: + } + EXPORT_SYMBOL_GPL(tee_shm_register); + ++static int tee_shm_fop_release(struct inode *inode, struct file *filp) ++{ ++ tee_shm_put(filp->private_data); ++ return 0; ++} ++ ++static int tee_shm_fop_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ struct tee_shm *shm = filp->private_data; ++ size_t size = vma->vm_end - vma->vm_start; ++ ++ /* Refuse sharing shared memory provided by application */ ++ if (shm->flags & TEE_SHM_USER_MAPPED) ++ return -EINVAL; ++ ++ /* check for overflowing the buffer's size */ ++ if (vma->vm_pgoff + vma_pages(vma) > shm->size >> PAGE_SHIFT) ++ return -EINVAL; ++ ++ return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT, ++ size, vma->vm_page_prot); ++} ++ ++static const struct file_operations tee_shm_fops = { ++ .owner = THIS_MODULE, ++ .release = tee_shm_fop_release, ++ .mmap = tee_shm_fop_mmap, ++}; ++ + /** + * tee_shm_get_fd() - Increase reference count and return file descriptor + * @shm: Shared memory handle +@@ -348,10 +296,11 @@ int tee_shm_get_fd(struct tee_shm *shm) + if (!(shm->flags & TEE_SHM_DMA_BUF)) + return -EINVAL; + +- get_dma_buf(shm->dmabuf); +- fd = dma_buf_fd(shm->dmabuf, O_CLOEXEC); ++ /* matched by tee_shm_put() in tee_shm_op_release() */ ++ refcount_inc(&shm->refcount); ++ fd = anon_inode_getfd("tee_shm", &tee_shm_fops, shm, O_RDWR); + if (fd < 0) +- dma_buf_put(shm->dmabuf); ++ tee_shm_put(shm); + return fd; + } + +@@ -361,17 +310,7 @@ int tee_shm_get_fd(struct tee_shm *shm) + */ + void tee_shm_free(struct tee_shm *shm) + { +- /* +- * dma_buf_put() decreases the dmabuf reference counter and will +- * call tee_shm_release() when the last reference is gone. +- * +- * In the case of driver private memory we call tee_shm_release +- * directly instead as it doesn't have a reference counter. +- */ +- if (shm->flags & TEE_SHM_DMA_BUF) +- dma_buf_put(shm->dmabuf); +- else +- tee_shm_release(shm); ++ tee_shm_put(shm); + } + EXPORT_SYMBOL_GPL(tee_shm_free); + +@@ -478,10 +417,15 @@ struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id) + teedev = ctx->teedev; + mutex_lock(&teedev->mutex); + shm = idr_find(&teedev->idr, id); ++ /* ++ * If the tee_shm was found in the IDR it must have a refcount ++ * larger than 0 due to the guarantee in tee_shm_put() below. So ++ * it's safe to use refcount_inc(). ++ */ + if (!shm || shm->ctx != ctx) + shm = ERR_PTR(-EINVAL); +- else if (shm->flags & TEE_SHM_DMA_BUF) +- get_dma_buf(shm->dmabuf); ++ else ++ refcount_inc(&shm->refcount); + mutex_unlock(&teedev->mutex); + return shm; + } +@@ -493,7 +437,24 @@ EXPORT_SYMBOL_GPL(tee_shm_get_from_id); + */ + void tee_shm_put(struct tee_shm *shm) + { +- if (shm->flags & TEE_SHM_DMA_BUF) +- dma_buf_put(shm->dmabuf); ++ struct tee_device *teedev = shm->ctx->teedev; ++ bool do_release = false; ++ ++ mutex_lock(&teedev->mutex); ++ if (refcount_dec_and_test(&shm->refcount)) { ++ /* ++ * refcount has reached 0, we must now remove it from the ++ * IDR before releasing the mutex. This will guarantee that ++ * the refcount_inc() in tee_shm_get_from_id() never starts ++ * from 0. ++ */ ++ if (shm->flags & TEE_SHM_DMA_BUF) ++ idr_remove(&teedev->idr, shm->id); ++ do_release = true; ++ } ++ mutex_unlock(&teedev->mutex); ++ ++ if (do_release) ++ tee_shm_release(teedev, shm); + } + EXPORT_SYMBOL_GPL(tee_shm_put); +diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c +index 7442e013738f8..af666bd9e8d4d 100644 +--- a/drivers/thermal/imx8mm_thermal.c ++++ b/drivers/thermal/imx8mm_thermal.c +@@ -21,6 +21,7 @@ + #define TPS 0x4 + #define TRITSR 0x20 /* TMU immediate temp */ + ++#define TER_ADC_PD BIT(30) + #define TER_EN BIT(31) + #define TRITSR_TEMP0_VAL_MASK 0xff + #define TRITSR_TEMP1_VAL_MASK 0xff0000 +@@ -113,6 +114,8 @@ static void imx8mm_tmu_enable(struct imx8mm_tmu *tmu, bool enable) + + val = readl_relaxed(tmu->base + TER); + val = enable ? (val | TER_EN) : (val & ~TER_EN); ++ if (tmu->socdata->version == TMU_VER2) ++ val = enable ? (val & ~TER_ADC_PD) : (val | TER_ADC_PD); + writel_relaxed(val, tmu->base + TER); + } + +diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c +index 2c7473d86a59b..16663373b6829 100644 +--- a/drivers/thermal/imx_thermal.c ++++ b/drivers/thermal/imx_thermal.c +@@ -15,6 +15,7 @@ + #include <linux/regmap.h> + #include <linux/thermal.h> + #include <linux/nvmem-consumer.h> ++#include <linux/pm_runtime.h> + + #define REG_SET 0x4 + #define REG_CLR 0x8 +@@ -194,6 +195,7 @@ static struct thermal_soc_data thermal_imx7d_data = { + }; + + struct imx_thermal_data { ++ struct device *dev; + struct cpufreq_policy *policy; + struct thermal_zone_device *tz; + struct thermal_cooling_device *cdev; +@@ -252,44 +254,15 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) + const struct thermal_soc_data *soc_data = data->socdata; + struct regmap *map = data->tempmon; + unsigned int n_meas; +- bool wait, run_measurement; + u32 val; ++ int ret; + +- run_measurement = !data->irq_enabled; +- if (!run_measurement) { +- /* Check if a measurement is currently in progress */ +- regmap_read(map, soc_data->temp_data, &val); +- wait = !(val & soc_data->temp_valid_mask); +- } else { +- /* +- * Every time we measure the temperature, we will power on the +- * temperature sensor, enable measurements, take a reading, +- * disable measurements, power off the temperature sensor. +- */ +- regmap_write(map, soc_data->sensor_ctrl + REG_CLR, +- soc_data->power_down_mask); +- regmap_write(map, soc_data->sensor_ctrl + REG_SET, +- soc_data->measure_temp_mask); +- +- wait = true; +- } +- +- /* +- * According to the temp sensor designers, it may require up to ~17us +- * to complete a measurement. +- */ +- if (wait) +- usleep_range(20, 50); ++ ret = pm_runtime_resume_and_get(data->dev); ++ if (ret < 0) ++ return ret; + + regmap_read(map, soc_data->temp_data, &val); + +- if (run_measurement) { +- regmap_write(map, soc_data->sensor_ctrl + REG_CLR, +- soc_data->measure_temp_mask); +- regmap_write(map, soc_data->sensor_ctrl + REG_SET, +- soc_data->power_down_mask); +- } +- + if ((val & soc_data->temp_valid_mask) == 0) { + dev_dbg(&tz->device, "temp measurement never finished\n"); + return -EAGAIN; +@@ -328,6 +301,8 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) + enable_irq(data->irq); + } + ++ pm_runtime_put(data->dev); ++ + return 0; + } + +@@ -335,24 +310,16 @@ static int imx_change_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) + { + struct imx_thermal_data *data = tz->devdata; +- struct regmap *map = data->tempmon; +- const struct thermal_soc_data *soc_data = data->socdata; + + if (mode == THERMAL_DEVICE_ENABLED) { +- regmap_write(map, soc_data->sensor_ctrl + REG_CLR, +- soc_data->power_down_mask); +- regmap_write(map, soc_data->sensor_ctrl + REG_SET, +- soc_data->measure_temp_mask); ++ pm_runtime_get(data->dev); + + if (!data->irq_enabled) { + data->irq_enabled = true; + enable_irq(data->irq); + } + } else { +- regmap_write(map, soc_data->sensor_ctrl + REG_CLR, +- soc_data->measure_temp_mask); +- regmap_write(map, soc_data->sensor_ctrl + REG_SET, +- soc_data->power_down_mask); ++ pm_runtime_put(data->dev); + + if (data->irq_enabled) { + disable_irq(data->irq); +@@ -393,6 +360,11 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip, + int temp) + { + struct imx_thermal_data *data = tz->devdata; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(data->dev); ++ if (ret < 0) ++ return ret; + + /* do not allow changing critical threshold */ + if (trip == IMX_TRIP_CRITICAL) +@@ -406,6 +378,8 @@ static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip, + + imx_set_alarm_temp(data, temp); + ++ pm_runtime_put(data->dev); ++ + return 0; + } + +@@ -681,6 +655,8 @@ static int imx_thermal_probe(struct platform_device *pdev) + if (!data) + return -ENOMEM; + ++ data->dev = &pdev->dev; ++ + map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon"); + if (IS_ERR(map)) { + ret = PTR_ERR(map); +@@ -800,6 +776,16 @@ static int imx_thermal_probe(struct platform_device *pdev) + data->socdata->power_down_mask); + regmap_write(map, data->socdata->sensor_ctrl + REG_SET, + data->socdata->measure_temp_mask); ++ /* After power up, we need a delay before first access can be done. */ ++ usleep_range(20, 50); ++ ++ /* the core was configured and enabled just before */ ++ pm_runtime_set_active(&pdev->dev); ++ pm_runtime_enable(data->dev); ++ ++ ret = pm_runtime_resume_and_get(data->dev); ++ if (ret < 0) ++ goto disable_runtime_pm; + + data->irq_enabled = true; + ret = thermal_zone_device_enable(data->tz); +@@ -814,10 +800,15 @@ static int imx_thermal_probe(struct platform_device *pdev) + goto thermal_zone_unregister; + } + ++ pm_runtime_put(data->dev); ++ + return 0; + + thermal_zone_unregister: + thermal_zone_device_unregister(data->tz); ++disable_runtime_pm: ++ pm_runtime_put_noidle(data->dev); ++ pm_runtime_disable(data->dev); + clk_disable: + clk_disable_unprepare(data->thermal_clk); + legacy_cleanup: +@@ -829,13 +820,9 @@ legacy_cleanup: + static int imx_thermal_remove(struct platform_device *pdev) + { + struct imx_thermal_data *data = platform_get_drvdata(pdev); +- struct regmap *map = data->tempmon; + +- /* Disable measurements */ +- regmap_write(map, data->socdata->sensor_ctrl + REG_SET, +- data->socdata->power_down_mask); +- if (!IS_ERR(data->thermal_clk)) +- clk_disable_unprepare(data->thermal_clk); ++ pm_runtime_put_noidle(data->dev); ++ pm_runtime_disable(data->dev); + + thermal_zone_device_unregister(data->tz); + imx_thermal_unregister_legacy_cooling(data); +@@ -858,29 +845,79 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev) + ret = thermal_zone_device_disable(data->tz); + if (ret) + return ret; ++ ++ return pm_runtime_force_suspend(data->dev); ++} ++ ++static int __maybe_unused imx_thermal_resume(struct device *dev) ++{ ++ struct imx_thermal_data *data = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = pm_runtime_force_resume(data->dev); ++ if (ret) ++ return ret; ++ /* Enabled thermal sensor after resume */ ++ return thermal_zone_device_enable(data->tz); ++} ++ ++static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev) ++{ ++ struct imx_thermal_data *data = dev_get_drvdata(dev); ++ const struct thermal_soc_data *socdata = data->socdata; ++ struct regmap *map = data->tempmon; ++ int ret; ++ ++ ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR, ++ socdata->measure_temp_mask); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(map, socdata->sensor_ctrl + REG_SET, ++ socdata->power_down_mask); ++ if (ret) ++ return ret; ++ + clk_disable_unprepare(data->thermal_clk); + + return 0; + } + +-static int __maybe_unused imx_thermal_resume(struct device *dev) ++static int __maybe_unused imx_thermal_runtime_resume(struct device *dev) + { + struct imx_thermal_data *data = dev_get_drvdata(dev); ++ const struct thermal_soc_data *socdata = data->socdata; ++ struct regmap *map = data->tempmon; + int ret; + + ret = clk_prepare_enable(data->thermal_clk); + if (ret) + return ret; +- /* Enabled thermal sensor after resume */ +- ret = thermal_zone_device_enable(data->tz); ++ ++ ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR, ++ socdata->power_down_mask); ++ if (ret) ++ return ret; ++ ++ ret = regmap_write(map, socdata->sensor_ctrl + REG_SET, ++ socdata->measure_temp_mask); + if (ret) + return ret; + ++ /* ++ * According to the temp sensor designers, it may require up to ~17us ++ * to complete a measurement. ++ */ ++ usleep_range(20, 50); ++ + return 0; + } + +-static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops, +- imx_thermal_suspend, imx_thermal_resume); ++static const struct dev_pm_ops imx_thermal_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume) ++ SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend, ++ imx_thermal_runtime_resume, NULL) ++}; + + static struct platform_driver imx_thermal = { + .driver = { +diff --git a/drivers/thermal/intel/int340x_thermal/Kconfig b/drivers/thermal/intel/int340x_thermal/Kconfig +index 45c31f3d6054b..5d046de96a5d0 100644 +--- a/drivers/thermal/intel/int340x_thermal/Kconfig ++++ b/drivers/thermal/intel/int340x_thermal/Kconfig +@@ -5,12 +5,12 @@ + + config INT340X_THERMAL + tristate "ACPI INT340X thermal drivers" +- depends on X86 && ACPI && PCI ++ depends on X86_64 && ACPI && PCI + select THERMAL_GOV_USER_SPACE + select ACPI_THERMAL_REL + select ACPI_FAN + select INTEL_SOC_DTS_IOSF_CORE +- select PROC_THERMAL_MMIO_RAPL if X86_64 && POWERCAP ++ select PROC_THERMAL_MMIO_RAPL if POWERCAP + help + Newer laptops and tablets that use ACPI may have thermal sensors and + other devices with thermal control capabilities outside the core +diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +index 19926beeb3b71..176b8e5d21246 100644 +--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c ++++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +@@ -405,6 +405,10 @@ static void int3400_notify(acpi_handle handle, + thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", therm_event); + thermal_prop[4] = NULL; + kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, thermal_prop); ++ kfree(thermal_prop[0]); ++ kfree(thermal_prop[1]); ++ kfree(thermal_prop[2]); ++ kfree(thermal_prop[3]); + } + + static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, +diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c +index acebc8ba94e29..217786fba185c 100644 +--- a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c ++++ b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c +@@ -44,15 +44,21 @@ static int int3401_remove(struct platform_device *pdev) + } + + #ifdef CONFIG_PM_SLEEP ++static int int3401_thermal_suspend(struct device *dev) ++{ ++ return proc_thermal_suspend(dev); ++} + static int int3401_thermal_resume(struct device *dev) + { + return proc_thermal_resume(dev); + } + #else ++#define int3401_thermal_suspend NULL + #define int3401_thermal_resume NULL + #endif + +-static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, NULL, int3401_thermal_resume); ++static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, int3401_thermal_suspend, ++ int3401_thermal_resume); + + static struct platform_driver int3401_driver = { + .probe = int3401_add, +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +index fb64acfd5e07d..a8d98f1bd6c67 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +@@ -68,8 +68,7 @@ static const struct attribute_group power_limit_attribute_group = { + .name = "power_limits" + }; + +-static ssize_t tcc_offset_degree_celsius_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static int tcc_get_offset(void) + { + u64 val; + int err; +@@ -78,8 +77,20 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev, + if (err) + return err; + +- val = (val >> 24) & 0x3f; +- return sprintf(buf, "%d\n", (int)val); ++ return (val >> 24) & 0x3f; ++} ++ ++static ssize_t tcc_offset_degree_celsius_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int tcc; ++ ++ tcc = tcc_get_offset(); ++ if (tcc < 0) ++ return tcc; ++ ++ return sprintf(buf, "%d\n", tcc); + } + + static int tcc_offset_update(unsigned int tcc) +@@ -107,8 +118,6 @@ static int tcc_offset_update(unsigned int tcc) + return 0; + } + +-static int tcc_offset_save = -1; +- + static ssize_t tcc_offset_degree_celsius_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +@@ -131,8 +140,6 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, + if (err) + return err; + +- tcc_offset_save = tcc; +- + return count; + } + +@@ -345,6 +352,18 @@ void proc_thermal_remove(struct proc_thermal_device *proc_priv) + } + EXPORT_SYMBOL_GPL(proc_thermal_remove); + ++static int tcc_offset_save = -1; ++ ++int proc_thermal_suspend(struct device *dev) ++{ ++ tcc_offset_save = tcc_get_offset(); ++ if (tcc_offset_save < 0) ++ dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(proc_thermal_suspend); ++ + int proc_thermal_resume(struct device *dev) + { + struct proc_thermal_device *proc_dev; +@@ -352,6 +371,7 @@ int proc_thermal_resume(struct device *dev) + proc_dev = dev_get_drvdata(dev); + proc_thermal_read_ppcc(proc_dev); + ++ /* Do not update if saving failed */ + if (tcc_offset_save >= 0) + tcc_offset_update(tcc_offset_save); + +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +index 5a1cfe4864f16..9b2a64ef55d02 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +@@ -80,9 +80,11 @@ void proc_thermal_rfim_remove(struct pci_dev *pdev); + int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); + void proc_thermal_mbox_remove(struct pci_dev *pdev); + +-int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp); ++int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); ++int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); + int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); + void proc_thermal_remove(struct proc_thermal_device *proc_priv); ++int proc_thermal_suspend(struct device *dev); + int proc_thermal_resume(struct device *dev); + int proc_thermal_mmio_add(struct pci_dev *pdev, + struct proc_thermal_device *proc_priv, +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +index 11dd2e825f4ff..b4bcd3fe9eb2f 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +@@ -314,6 +314,20 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev) + } + + #ifdef CONFIG_PM_SLEEP ++static int proc_thermal_pci_suspend(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct proc_thermal_device *proc_priv; ++ struct proc_thermal_pci *pci_info; ++ ++ proc_priv = pci_get_drvdata(pdev); ++ pci_info = proc_priv->priv_data; ++ ++ if (!pci_info->no_legacy) ++ return proc_thermal_suspend(dev); ++ ++ return 0; ++} + static int proc_thermal_pci_resume(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); +@@ -335,10 +349,12 @@ static int proc_thermal_pci_resume(struct device *dev) + return 0; + } + #else ++#define proc_thermal_pci_suspend NULL + #define proc_thermal_pci_resume NULL + #endif + +-static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume); ++static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, ++ proc_thermal_pci_resume); + + static const struct pci_device_id proc_thermal_pci_ids[] = { + { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c +index f5fc1791b11ef..4571a1a53b841 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c +@@ -107,15 +107,21 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev) + } + + #ifdef CONFIG_PM_SLEEP ++static int proc_thermal_pci_suspend(struct device *dev) ++{ ++ return proc_thermal_suspend(dev); ++} + static int proc_thermal_pci_resume(struct device *dev) + { + return proc_thermal_resume(dev); + } + #else ++#define proc_thermal_pci_suspend NULL + #define proc_thermal_pci_resume NULL + #endif + +-static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume); ++static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, ++ proc_thermal_pci_resume); + + static const struct pci_device_id proc_thermal_pci_ids[] = { + { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c +index 59e93b04f0a9e..0b89a4340ff4e 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c +@@ -7,6 +7,7 @@ + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/pci.h> ++#include <linux/io-64-nonatomic-lo-hi.h> + #include "processor_thermal_device.h" + + #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E +@@ -23,19 +24,15 @@ + + static DEFINE_MUTEX(mbox_lock); + +-static int send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp) ++static int wait_for_mbox_ready(struct proc_thermal_device *proc_priv) + { +- struct proc_thermal_device *proc_priv; + u32 retries, data; + int ret; + +- mutex_lock(&mbox_lock); +- proc_priv = pci_get_drvdata(pdev); +- + /* Poll for rb bit == 0 */ + retries = MBOX_RETRY_COUNT; + do { +- data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); ++ data = readl(proc_priv->mmio_base + MBOX_OFFSET_INTERFACE); + if (data & BIT_ULL(MBOX_BUSY_BIT)) { + ret = -EBUSY; + continue; +@@ -44,49 +41,78 @@ static int send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cm + break; + } while (--retries); + ++ return ret; ++} ++ ++static int send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) ++{ ++ struct proc_thermal_device *proc_priv; ++ u32 reg_data; ++ int ret; ++ ++ proc_priv = pci_get_drvdata(pdev); ++ ++ mutex_lock(&mbox_lock); ++ ++ ret = wait_for_mbox_ready(proc_priv); + if (ret) + goto unlock_mbox; + +- if (cmd_id == MBOX_CMD_WORKLOAD_TYPE_WRITE) +- writel(cmd_data, (void __iomem *) ((proc_priv->mmio_base + MBOX_OFFSET_DATA))); +- ++ writel(data, (proc_priv->mmio_base + MBOX_OFFSET_DATA)); + /* Write command register */ +- data = BIT_ULL(MBOX_BUSY_BIT) | cmd_id; +- writel(data, (void __iomem *) ((proc_priv->mmio_base + MBOX_OFFSET_INTERFACE))); ++ reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; ++ writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); + +- /* Poll for rb bit == 0 */ +- retries = MBOX_RETRY_COUNT; +- do { +- data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); +- if (data & BIT_ULL(MBOX_BUSY_BIT)) { +- ret = -EBUSY; +- continue; +- } ++ ret = wait_for_mbox_ready(proc_priv); + +- if (data) { +- ret = -ENXIO; +- goto unlock_mbox; +- } ++unlock_mbox: ++ mutex_unlock(&mbox_lock); ++ return ret; ++} + +- if (cmd_id == MBOX_CMD_WORKLOAD_TYPE_READ) { +- data = readl((void __iomem *) (proc_priv->mmio_base + MBOX_OFFSET_DATA)); +- *cmd_resp = data & 0xff; +- } ++static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) ++{ ++ struct proc_thermal_device *proc_priv; ++ u32 reg_data; ++ int ret; + +- ret = 0; +- break; +- } while (--retries); ++ proc_priv = pci_get_drvdata(pdev); ++ ++ mutex_lock(&mbox_lock); ++ ++ ret = wait_for_mbox_ready(proc_priv); ++ if (ret) ++ goto unlock_mbox; ++ ++ /* Write command register */ ++ reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; ++ writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); ++ ++ ret = wait_for_mbox_ready(proc_priv); ++ if (ret) ++ goto unlock_mbox; ++ ++ if (id == MBOX_CMD_WORKLOAD_TYPE_READ) ++ *resp = readl(proc_priv->mmio_base + MBOX_OFFSET_DATA); ++ else ++ *resp = readq(proc_priv->mmio_base + MBOX_OFFSET_DATA); + + unlock_mbox: + mutex_unlock(&mbox_lock); + return ret; + } + +-int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp) ++int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) + { +- return send_mbox_cmd(pdev, cmd_id, cmd_data, cmd_resp); ++ return send_mbox_read_cmd(pdev, id, resp); + } +-EXPORT_SYMBOL_GPL(processor_thermal_send_mbox_cmd); ++EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL); ++ ++int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) ++{ ++ return send_mbox_write_cmd(pdev, id, data); ++} ++EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL); + + /* List of workload types */ + static const char * const workload_types[] = { +@@ -99,7 +125,6 @@ static const char * const workload_types[] = { + NULL + }; + +- + static ssize_t workload_available_types_show(struct device *dev, + struct device_attribute *attr, + char *buf) +@@ -141,7 +166,7 @@ static ssize_t workload_type_store(struct device *dev, + + data |= ret; + +- ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data, NULL); ++ ret = send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data); + if (ret) + return false; + +@@ -153,10 +178,10 @@ static ssize_t workload_type_show(struct device *dev, + char *buf) + { + struct pci_dev *pdev = to_pci_dev(dev); +- u32 cmd_resp; ++ u64 cmd_resp; + int ret; + +- ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp); ++ ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); + if (ret) + return false; + +@@ -181,17 +206,15 @@ static const struct attribute_group workload_req_attribute_group = { + .name = "workload_request" + }; + +- +- + static bool workload_req_created; + + int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) + { +- u32 cmd_resp; ++ u64 cmd_resp; + int ret; + + /* Check if there is a mailbox support, if fails return success */ +- ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp); ++ ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); + if (ret) + return 0; + +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +index 2b8a3235d518b..8c42e76620333 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +@@ -9,6 +9,8 @@ + #include <linux/pci.h> + #include "processor_thermal_device.h" + ++MODULE_IMPORT_NS(INT340X_THERMAL); ++ + struct mmio_reg { + int read_only; + u32 offset; +@@ -29,7 +31,7 @@ static const char * const fivr_strings[] = { + }; + + static const struct mmio_reg tgl_fivr_mmio_regs[] = { +- { 0, 0x5A18, 3, 0x7, 12}, /* vco_ref_code_lo */ ++ { 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */ + { 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */ + { 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */ + { 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */ +@@ -194,8 +196,7 @@ static ssize_t rfi_restriction_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) + { +- u16 cmd_id = 0x0008; +- u32 cmd_resp; ++ u16 id = 0x0008; + u32 input; + int ret; + +@@ -203,7 +204,7 @@ static ssize_t rfi_restriction_store(struct device *dev, + if (ret) + return ret; + +- ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, input, &cmd_resp); ++ ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input); + if (ret) + return ret; + +@@ -214,30 +215,30 @@ static ssize_t rfi_restriction_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- u16 cmd_id = 0x0007; +- u32 cmd_resp; ++ u16 id = 0x0007; ++ u64 resp; + int ret; + +- ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp); ++ ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp); + if (ret) + return ret; + +- return sprintf(buf, "%u\n", cmd_resp); ++ return sprintf(buf, "%llu\n", resp); + } + + static ssize_t ddr_data_rate_show(struct device *dev, + struct device_attribute *attr, + char *buf) + { +- u16 cmd_id = 0x0107; +- u32 cmd_resp; ++ u16 id = 0x0107; ++ u64 resp; + int ret; + +- ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp); ++ ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp); + if (ret) + return ret; + +- return sprintf(buf, "%u\n", cmd_resp); ++ return sprintf(buf, "%llu\n", resp); + } + + static DEVICE_ATTR_RW(rfi_restriction); +diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig +index 7d942f71e5328..bfd889422dd32 100644 +--- a/drivers/thermal/qcom/Kconfig ++++ b/drivers/thermal/qcom/Kconfig +@@ -34,7 +34,7 @@ config QCOM_SPMI_TEMP_ALARM + + config QCOM_LMH + tristate "Qualcomm Limits Management Hardware" +- depends on ARCH_QCOM ++ depends on ARCH_QCOM && QCOM_SCM + help + This enables initialization of Qualcomm limits management + hardware(LMh). LMh allows for hardware-enforced mitigation for cpus based on +diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c +index b1162e566a707..99a8d9f3e03ca 100644 +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -603,22 +603,21 @@ int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp) + int ret; + + /* VER_0 doesn't have VALID bit */ +- if (tsens_version(priv) >= VER_0_1) { +- ret = regmap_field_read(priv->rf[valid_idx], &valid); +- if (ret) +- return ret; +- while (!valid) { +- /* Valid bit is 0 for 6 AHB clock cycles. +- * At 19.2MHz, 1 AHB clock is ~60ns. +- * We should enter this loop very, very rarely. +- */ +- ndelay(400); +- ret = regmap_field_read(priv->rf[valid_idx], &valid); +- if (ret) +- return ret; +- } +- } ++ if (tsens_version(priv) == VER_0) ++ goto get_temp; ++ ++ /* Valid bit is 0 for 6 AHB clock cycles. ++ * At 19.2MHz, 1 AHB clock is ~60ns. ++ * We should enter this loop very, very rarely. ++ * Wait 1 us since it's the min of poll_timeout macro. ++ * Old value was 400 ns. ++ */ ++ ret = regmap_field_read_poll_timeout(priv->rf[valid_idx], valid, ++ valid, 1, 20 * USEC_PER_MSEC); ++ if (ret) ++ return ret; + ++get_temp: + /* Valid bit is set, OK to read the temperature */ + *temp = tsens_hw_to_mC(s, temp_idx); + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 51374f4e1ccaf..13891745a9719 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -419,6 +419,8 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) + { + struct thermal_instance *pos; + tz->temperature = THERMAL_TEMP_INVALID; ++ tz->prev_low_trip = -INT_MAX; ++ tz->prev_high_trip = INT_MAX; + list_for_each_entry(pos, &tz->thermal_instances, tz_node) + pos->initialized = false; + } +@@ -887,7 +889,7 @@ __thermal_cooling_device_register(struct device_node *np, + { + struct thermal_cooling_device *cdev; + struct thermal_zone_device *pos = NULL; +- int ret; ++ int id, ret; + + if (!ops || !ops->get_max_state || !ops->get_cur_state || + !ops->set_cur_state) +@@ -901,6 +903,11 @@ __thermal_cooling_device_register(struct device_node *np, + if (ret < 0) + goto out_kfree_cdev; + cdev->id = ret; ++ id = ret; ++ ++ ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); ++ if (ret) ++ goto out_ida_remove; + + cdev->type = kstrdup(type ? type : "", GFP_KERNEL); + if (!cdev->type) { +@@ -916,7 +923,6 @@ __thermal_cooling_device_register(struct device_node *np, + cdev->device.class = &thermal_class; + cdev->devdata = devdata; + thermal_cooling_device_setup_sysfs(cdev); +- dev_set_name(&cdev->device, "cooling_device%d", cdev->id); + ret = device_register(&cdev->device); + if (ret) + goto out_kfree_type; +@@ -941,8 +947,9 @@ __thermal_cooling_device_register(struct device_node *np, + out_kfree_type: + kfree(cdev->type); + put_device(&cdev->device); ++ cdev = NULL; + out_ida_remove: +- ida_simple_remove(&thermal_cdev_ida, cdev->id); ++ ida_simple_remove(&thermal_cdev_ida, id); + out_kfree_cdev: + kfree(cdev); + return ERR_PTR(ret); +@@ -1227,6 +1234,10 @@ thermal_zone_device_register(const char *type, int trips, int mask, + tz->id = id; + strlcpy(tz->type, type, sizeof(tz->type)); + ++ result = dev_set_name(&tz->device, "thermal_zone%d", tz->id); ++ if (result) ++ goto remove_id; ++ + if (!ops->critical) + ops->critical = thermal_zone_device_critical; + +@@ -1248,7 +1259,6 @@ thermal_zone_device_register(const char *type, int trips, int mask, + /* A new thermal zone needs to be updated anyway. */ + atomic_set(&tz->need_update, 1); + +- dev_set_name(&tz->device, "thermal_zone%d", tz->id); + result = device_register(&tz->device); + if (result) + goto release_device; +diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c +index 1234dbe958951..41c8d47805c4e 100644 +--- a/drivers/thermal/thermal_netlink.c ++++ b/drivers/thermal/thermal_netlink.c +@@ -418,11 +418,12 @@ static int thermal_genl_cmd_tz_get_trip(struct param *p) + for (i = 0; i < tz->trips; i++) { + + enum thermal_trip_type type; +- int temp, hyst; ++ int temp, hyst = 0; + + tz->ops->get_trip_type(tz, i, &type); + tz->ops->get_trip_temp(tz, i, &temp); +- tz->ops->get_trip_hyst(tz, i, &hyst); ++ if (tz->ops->get_trip_hyst) ++ tz->ops->get_trip_hyst(tz, i, &hyst); + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) || +diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c +index 6379f26a335f6..9233f7e744544 100644 +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -89,7 +89,7 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_temp) ++ if (!data->ops || !data->ops->get_temp) + return -EINVAL; + + return data->ops->get_temp(data->sensor_data, temp); +@@ -186,6 +186,9 @@ static int of_thermal_set_emul_temp(struct thermal_zone_device *tz, + { + struct __thermal_zone *data = tz->devdata; + ++ if (!data->ops || !data->ops->set_emul_temp) ++ return -EINVAL; ++ + return data->ops->set_emul_temp(data->sensor_data, temp); + } + +@@ -194,7 +197,7 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_trend) ++ if (!data->ops || !data->ops->get_trend) + return -EINVAL; + + return data->ops->get_trend(data->sensor_data, trip, trend); +@@ -301,7 +304,7 @@ static int of_thermal_set_trip_temp(struct thermal_zone_device *tz, int trip, + if (trip >= data->ntrips || trip < 0) + return -EDOM; + +- if (data->ops->set_trip_temp) { ++ if (data->ops && data->ops->set_trip_temp) { + int ret; + + ret = data->ops->set_trip_temp(data->sensor_data, trip, temp); +diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c +index b67e72d5644b3..7c9597a339295 100644 +--- a/drivers/thunderbolt/acpi.c ++++ b/drivers/thunderbolt/acpi.c +@@ -7,6 +7,7 @@ + */ + + #include <linux/acpi.h> ++#include <linux/pm_runtime.h> + + #include "tb.h" + +@@ -74,8 +75,18 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, + pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) { + const struct device_link *link; + ++ /* ++ * Make them both active first to make sure the NHI does ++ * not runtime suspend before the consumer. The ++ * pm_runtime_put() below then allows the consumer to ++ * runtime suspend again (which then allows NHI runtime ++ * suspend too now that the device link is established). ++ */ ++ pm_runtime_get_sync(&pdev->dev); ++ + link = device_link_add(&pdev->dev, &nhi->pdev->dev, + DL_FLAG_AUTOREMOVE_SUPPLIER | ++ DL_FLAG_RPM_ACTIVE | + DL_FLAG_PM_RUNTIME); + if (link) { + dev_dbg(&nhi->pdev->dev, "created link from %s\n", +@@ -84,6 +95,8 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, + dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", + dev_name(&pdev->dev)); + } ++ ++ pm_runtime_put(&pdev->dev); + } + + out_put: +diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c +index f0bf01ea069ae..8ee7ce1206925 100644 +--- a/drivers/tty/hvc/hvc_xen.c ++++ b/drivers/tty/hvc/hvc_xen.c +@@ -37,6 +37,8 @@ struct xencons_info { + struct xenbus_device *xbdev; + struct xencons_interface *intf; + unsigned int evtchn; ++ XENCONS_RING_IDX out_cons; ++ unsigned int out_cons_same; + struct hvc_struct *hvc; + int irq; + int vtermno; +@@ -138,6 +140,8 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) + XENCONS_RING_IDX cons, prod; + int recv = 0; + struct xencons_info *xencons = vtermno_to_xencons(vtermno); ++ unsigned int eoiflag = 0; ++ + if (xencons == NULL) + return -EINVAL; + intf = xencons->intf; +@@ -157,7 +161,27 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) + mb(); /* read ring before consuming */ + intf->in_cons = cons; + +- notify_daemon(xencons); ++ /* ++ * When to mark interrupt having been spurious: ++ * - there was no new data to be read, and ++ * - the backend did not consume some output bytes, and ++ * - the previous round with no read data didn't see consumed bytes ++ * (we might have a race with an interrupt being in flight while ++ * updating xencons->out_cons, so account for that by allowing one ++ * round without any visible reason) ++ */ ++ if (intf->out_cons != xencons->out_cons) { ++ xencons->out_cons = intf->out_cons; ++ xencons->out_cons_same = 0; ++ } ++ if (recv) { ++ notify_daemon(xencons); ++ } else if (xencons->out_cons_same++ > 1) { ++ eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ } ++ ++ xen_irq_lateeoi(xencons->irq, eoiflag); ++ + return recv; + } + +@@ -386,7 +410,7 @@ static int xencons_connect_backend(struct xenbus_device *dev, + if (ret) + return ret; + info->evtchn = evtchn; +- irq = bind_evtchn_to_irq(evtchn); ++ irq = bind_interdomain_evtchn_to_irq_lateeoi(dev, evtchn); + if (irq < 0) + return irq; + info->irq = irq; +@@ -550,7 +574,7 @@ static int __init xen_hvc_init(void) + return r; + + info = vtermno_to_xencons(HVC_COOKIE); +- info->irq = bind_evtchn_to_irq(info->evtchn); ++ info->irq = bind_evtchn_to_irq_lateeoi(info->evtchn); + } + if (info->irq < 0) + info->irq = 0; /* NO_IRQ */ +diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c +index 1216f3985e18e..da375851af4e6 100644 +--- a/drivers/tty/mxser.c ++++ b/drivers/tty/mxser.c +@@ -261,7 +261,6 @@ struct mxser_port { + unsigned int xmit_head; + unsigned int xmit_tail; + unsigned int xmit_cnt; +- int closing; + + spinlock_t slock; + }; +@@ -923,7 +922,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) + return; + if (tty_port_close_start(port, tty, filp) == 0) + return; +- info->closing = 1; + mutex_lock(&port->mutex); + mxser_close_port(port); + mxser_flush_buffer(tty); +@@ -932,7 +930,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) + mxser_shutdown_port(port); + tty_port_set_initialized(port, 0); + mutex_unlock(&port->mutex); +- info->closing = 0; + /* Right now the tty_port set is done outside of the close_end helper + as we don't yet have everyone using refcounts */ + tty_port_close_end(port, tty); +@@ -1693,7 +1690,7 @@ static bool mxser_port_isr(struct mxser_port *port) + + iir &= MOXA_MUST_IIR_MASK; + tty = tty_port_tty_get(&port->port); +- if (!tty || port->closing || !tty_port_initialized(&port->port)) { ++ if (!tty) { + status = inb(port->ioaddr + UART_LSR); + outb(MOXA_MUST_FCR_GDA_MODE_ENABLE | UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, +diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c +index 1d92d2a848894..8643b143c408e 100644 +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -318,6 +318,7 @@ static struct tty_driver *gsm_tty_driver; + #define GSM1_ESCAPE_BITS 0x20 + #define XON 0x11 + #define XOFF 0x13 ++#define ISO_IEC_646_MASK 0x7F + + static const struct tty_port_operations gsm_port_ops; + +@@ -434,7 +435,7 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci) + modembits |= MDM_RTR; + if (dlci->modem_tx & TIOCM_RI) + modembits |= MDM_IC; +- if (dlci->modem_tx & TIOCM_CD) ++ if (dlci->modem_tx & TIOCM_CD || dlci->gsm->initiator) + modembits |= MDM_DV; + return modembits; + } +@@ -527,7 +528,8 @@ static int gsm_stuff_frame(const u8 *input, u8 *output, int len) + int olen = 0; + while (len--) { + if (*input == GSM1_SOF || *input == GSM1_ESCAPE +- || *input == XON || *input == XOFF) { ++ || (*input & ISO_IEC_646_MASK) == XON ++ || (*input & ISO_IEC_646_MASK) == XOFF) { + *output++ = GSM1_ESCAPE; + *output++ = *input++ ^ GSM1_ESCAPE_BITS; + olen++; +@@ -1007,25 +1009,25 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data, + * @tty: virtual tty bound to the DLCI + * @dlci: DLCI to affect + * @modem: modem bits (full EA) +- * @clen: command length ++ * @slen: number of signal octets + * + * Used when a modem control message or line state inline in adaption + * layer 2 is processed. Sort out the local modem state and throttles + */ + + static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, +- u32 modem, int clen) ++ u32 modem, int slen) + { + int mlines = 0; + u8 brk = 0; + int fc; + +- /* The modem status command can either contain one octet (v.24 signals) +- or two octets (v.24 signals + break signals). The length field will +- either be 2 or 3 respectively. This is specified in section +- 5.4.6.3.7 of the 27.010 mux spec. */ ++ /* The modem status command can either contain one octet (V.24 signals) ++ * or two octets (V.24 signals + break signals). This is specified in ++ * section 5.4.6.3.7 of the 07.10 mux spec. ++ */ + +- if (clen == 2) ++ if (slen == 1) + modem = modem & 0x7f; + else { + brk = modem & 0x7f; +@@ -1082,6 +1084,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) + unsigned int brk = 0; + struct gsm_dlci *dlci; + int len = clen; ++ int slen; + const u8 *dp = data; + struct tty_struct *tty; + +@@ -1101,6 +1104,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) + return; + dlci = gsm->dlci[addr]; + ++ slen = len; + while (gsm_read_ea(&modem, *dp++) == 0) { + len--; + if (len == 0) +@@ -1117,7 +1121,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) + modem |= (brk & 0x7f); + } + tty = tty_port_tty_get(&dlci->port); +- gsm_process_modem(tty, dlci, modem, clen); ++ gsm_process_modem(tty, dlci, modem, slen); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); +@@ -1427,6 +1431,9 @@ static void gsm_dlci_close(struct gsm_dlci *dlci) + if (dlci->addr != 0) { + tty_port_tty_hangup(&dlci->port, false); + kfifo_reset(&dlci->fifo); ++ /* Ensure that gsmtty_open() can return. */ ++ tty_port_set_initialized(&dlci->port, 0); ++ wake_up_interruptible(&dlci->port.open_wait); + } else + dlci->gsm->dead = true; + wake_up(&dlci->gsm->event); +@@ -1486,7 +1493,7 @@ static void gsm_dlci_t1(struct timer_list *t) + dlci->mode = DLCI_MODE_ADM; + gsm_dlci_open(dlci); + } else { +- gsm_dlci_close(dlci); ++ gsm_dlci_begin_close(dlci); /* prevent half open link */ + } + + break; +@@ -1565,6 +1572,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen) + struct tty_struct *tty; + unsigned int modem = 0; + int len = clen; ++ int slen = 0; + + if (debug & 16) + pr_debug("%d bytes for tty\n", len); +@@ -1577,12 +1585,14 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen) + case 2: /* Asynchronous serial with line state in each frame */ + while (gsm_read_ea(&modem, *data++) == 0) { + len--; ++ slen++; + if (len == 0) + return; + } ++ slen++; + tty = tty_port_tty_get(port); + if (tty) { +- gsm_process_modem(tty, dlci, modem, clen); ++ gsm_process_modem(tty, dlci, modem, slen); + tty_kref_put(tty); + } + fallthrough; +@@ -1720,7 +1730,12 @@ static void gsm_dlci_release(struct gsm_dlci *dlci) + gsm_destroy_network(dlci); + mutex_unlock(&dlci->mutex); + +- tty_hangup(tty); ++ /* We cannot use tty_hangup() because in tty_kref_put() the tty ++ * driver assumes that the hangup queue is free and reuses it to ++ * queue release_one_tty() -> NULL pointer panic in ++ * process_one_work(). ++ */ ++ tty_vhangup(tty); + + tty_port_tty_set(&dlci->port, NULL); + tty_kref_put(tty); +@@ -3173,9 +3188,9 @@ static void gsmtty_throttle(struct tty_struct *tty) + if (dlci->state == DLCI_CLOSED) + return; + if (C_CRTSCTS(tty)) +- dlci->modem_tx &= ~TIOCM_DTR; ++ dlci->modem_tx &= ~TIOCM_RTS; + dlci->throttled = true; +- /* Send an MSC with DTR cleared */ ++ /* Send an MSC with RTS cleared */ + gsmtty_modem_update(dlci, 0); + } + +@@ -3185,9 +3200,9 @@ static void gsmtty_unthrottle(struct tty_struct *tty) + if (dlci->state == DLCI_CLOSED) + return; + if (C_CRTSCTS(tty)) +- dlci->modem_tx |= TIOCM_DTR; ++ dlci->modem_tx |= TIOCM_RTS; + dlci->throttled = false; +- /* Send an MSC with DTR set */ ++ /* Send an MSC with RTS set */ + gsmtty_modem_update(dlci, 0); + } + +diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c +index 580a37b3fe1b9..166f651fde33a 100644 +--- a/drivers/tty/n_hdlc.c ++++ b/drivers/tty/n_hdlc.c +@@ -140,6 +140,8 @@ struct n_hdlc { + struct n_hdlc_buf_list rx_buf_list; + struct n_hdlc_buf_list tx_free_buf_list; + struct n_hdlc_buf_list rx_free_buf_list; ++ struct work_struct write_work; ++ struct tty_struct *tty_for_write_work; + }; + + /* +@@ -154,6 +156,7 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); + /* Local functions */ + + static struct n_hdlc *n_hdlc_alloc(void); ++static void n_hdlc_tty_write_work(struct work_struct *work); + + /* max frame size for memory allocations */ + static int maxframe = 4096; +@@ -210,6 +213,8 @@ static void n_hdlc_tty_close(struct tty_struct *tty) + wake_up_interruptible(&tty->read_wait); + wake_up_interruptible(&tty->write_wait); + ++ cancel_work_sync(&n_hdlc->write_work); ++ + n_hdlc_free_buf_list(&n_hdlc->rx_free_buf_list); + n_hdlc_free_buf_list(&n_hdlc->tx_free_buf_list); + n_hdlc_free_buf_list(&n_hdlc->rx_buf_list); +@@ -241,6 +246,8 @@ static int n_hdlc_tty_open(struct tty_struct *tty) + return -ENFILE; + } + ++ INIT_WORK(&n_hdlc->write_work, n_hdlc_tty_write_work); ++ n_hdlc->tty_for_write_work = tty; + tty->disc_data = n_hdlc; + tty->receive_room = 65536; + +@@ -334,6 +341,20 @@ check_again: + goto check_again; + } /* end of n_hdlc_send_frames() */ + ++/** ++ * n_hdlc_tty_write_work - Asynchronous callback for transmit wakeup ++ * @work: pointer to work_struct ++ * ++ * Called when low level device driver can accept more send data. ++ */ ++static void n_hdlc_tty_write_work(struct work_struct *work) ++{ ++ struct n_hdlc *n_hdlc = container_of(work, struct n_hdlc, write_work); ++ struct tty_struct *tty = n_hdlc->tty_for_write_work; ++ ++ n_hdlc_send_frames(n_hdlc, tty); ++} /* end of n_hdlc_tty_write_work() */ ++ + /** + * n_hdlc_tty_wakeup - Callback for transmit wakeup + * @tty: pointer to associated tty instance data +@@ -344,7 +365,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) + { + struct n_hdlc *n_hdlc = tty->disc_data; + +- n_hdlc_send_frames(n_hdlc, tty); ++ schedule_work(&n_hdlc->write_work); + } /* end of n_hdlc_tty_wakeup() */ + + /** +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 0ec93f1a61f5d..de5b45de50402 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -1369,7 +1369,7 @@ handle_newline: + put_tty_queue(c, ldata); + smp_store_release(&ldata->canon_head, ldata->read_head); + kill_fasync(&tty->fasync, SIGIO, POLL_IN); +- wake_up_interruptible_poll(&tty->read_wait, EPOLLIN); ++ wake_up_interruptible_poll(&tty->read_wait, EPOLLIN | EPOLLRDNORM); + return; + } + } +@@ -1589,7 +1589,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, + + if (read_cnt(ldata)) { + kill_fasync(&tty->fasync, SIGIO, POLL_IN); +- wake_up_interruptible_poll(&tty->read_wait, EPOLLIN); ++ wake_up_interruptible_poll(&tty->read_wait, EPOLLIN | EPOLLRDNORM); + } + } + +@@ -1963,7 +1963,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, + return false; + + canon_head = smp_load_acquire(&ldata->canon_head); +- n = min(*nr + 1, canon_head - ldata->read_tail); ++ n = min(*nr, canon_head - ldata->read_tail); + + tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); + size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); +@@ -1985,10 +1985,8 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, + n += N_TTY_BUF_SIZE; + c = n + found; + +- if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) { +- c = min(*nr, c); ++ if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) + n = c; +- } + + n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", + __func__, eol, found, n, c, tail, more); +diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c +index 7f656fac503fe..0877cf24f7de0 100644 +--- a/drivers/tty/serial/8250/8250_bcm7271.c ++++ b/drivers/tty/serial/8250/8250_bcm7271.c +@@ -237,6 +237,7 @@ struct brcmuart_priv { + u32 rx_err; + u32 rx_timeout; + u32 rx_abort; ++ u32 saved_mctrl; + }; + + static struct dentry *brcmuart_debugfs_root; +@@ -1075,14 +1076,18 @@ static int brcmuart_probe(struct platform_device *pdev) + priv->rx_bufs = dma_alloc_coherent(dev, + priv->rx_size, + &priv->rx_addr, GFP_KERNEL); +- if (!priv->rx_bufs) ++ if (!priv->rx_bufs) { ++ ret = -EINVAL; + goto err; ++ } + priv->tx_size = UART_XMIT_SIZE; + priv->tx_buf = dma_alloc_coherent(dev, + priv->tx_size, + &priv->tx_addr, GFP_KERNEL); +- if (!priv->tx_buf) ++ if (!priv->tx_buf) { ++ ret = -EINVAL; + goto err; ++ } + } + + ret = serial8250_register_8250_port(&up); +@@ -1096,6 +1101,7 @@ static int brcmuart_probe(struct platform_device *pdev) + if (priv->dma_enabled) { + dma_irq = platform_get_irq_byname(pdev, "dma"); + if (dma_irq < 0) { ++ ret = dma_irq; + dev_err(dev, "no IRQ resource info\n"); + goto err1; + } +@@ -1115,7 +1121,7 @@ err1: + err: + brcmuart_free_bufs(dev, priv); + brcmuart_arbitration(priv, 0); +- return -ENODEV; ++ return ret; + } + + static int brcmuart_remove(struct platform_device *pdev) +@@ -1133,16 +1139,27 @@ static int brcmuart_remove(struct platform_device *pdev) + static int __maybe_unused brcmuart_suspend(struct device *dev) + { + struct brcmuart_priv *priv = dev_get_drvdata(dev); ++ struct uart_8250_port *up = serial8250_get_port(priv->line); ++ struct uart_port *port = &up->port; + + serial8250_suspend_port(priv->line); + clk_disable_unprepare(priv->baud_mux_clk); + ++ /* ++ * This will prevent resume from enabling RTS before the ++ * baud rate has been resored. ++ */ ++ priv->saved_mctrl = port->mctrl; ++ port->mctrl = 0; ++ + return 0; + } + + static int __maybe_unused brcmuart_resume(struct device *dev) + { + struct brcmuart_priv *priv = dev_get_drvdata(dev); ++ struct uart_8250_port *up = serial8250_get_port(priv->line); ++ struct uart_port *port = &up->port; + int ret; + + ret = clk_prepare_enable(priv->baud_mux_clk); +@@ -1165,6 +1182,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev) + start_rx_dma(serial8250_get_port(priv->line)); + } + serial8250_resume_port(priv->line); ++ port->mctrl = priv->saved_mctrl; + return 0; + } + +diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c +index a3a0154da567d..49559731bbcf1 100644 +--- a/drivers/tty/serial/8250/8250_dw.c ++++ b/drivers/tty/serial/8250/8250_dw.c +@@ -726,7 +726,7 @@ static struct platform_driver dw8250_platform_driver = { + .name = "dw-apb-uart", + .pm = &dw8250_pm_ops, + .of_match_table = dw8250_of_match, +- .acpi_match_table = ACPI_PTR(dw8250_acpi_match), ++ .acpi_match_table = dw8250_acpi_match, + }, + .probe = dw8250_probe, + .remove = dw8250_remove, +diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c +index 31c9e83ea3cb2..251f0018ae8ca 100644 +--- a/drivers/tty/serial/8250/8250_fintek.c ++++ b/drivers/tty/serial/8250/8250_fintek.c +@@ -290,25 +290,6 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) + } + } + +-static void fintek_8250_goto_highspeed(struct uart_8250_port *uart, +- struct fintek_8250 *pdata) +-{ +- sio_write_reg(pdata, LDN, pdata->index); +- +- switch (pdata->pid) { +- case CHIP_ID_F81966: +- case CHIP_ID_F81866: /* set uart clock for high speed serial mode */ +- sio_write_mask_reg(pdata, F81866_UART_CLK, +- F81866_UART_CLK_MASK, +- F81866_UART_CLK_14_769MHZ); +- +- uart->port.uartclk = 921600 * 16; +- break; +- default: /* leave clock speed untouched */ +- break; +- } +-} +- + static void fintek_8250_set_termios(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +@@ -430,7 +411,6 @@ static int probe_setup_port(struct fintek_8250 *pdata, + + fintek_8250_set_irq_mode(pdata, level_mode); + fintek_8250_set_max_fifo(pdata); +- fintek_8250_goto_highspeed(uart, pdata); + + fintek_8250_exit_key(addr[i]); + +diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c +index 673cda3d011d0..948d0a1c6ae8e 100644 +--- a/drivers/tty/serial/8250/8250_gsc.c ++++ b/drivers/tty/serial/8250/8250_gsc.c +@@ -26,7 +26,7 @@ static int __init serial_init_chip(struct parisc_device *dev) + unsigned long address; + int err; + +-#ifdef CONFIG_64BIT ++#if defined(CONFIG_64BIT) && defined(CONFIG_IOSAPIC) + if (!dev->irq && (dev->id.sversion == 0xad)) + dev->irq = iosapic_serial_irq(dev); + #endif +diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c +index bce28729dd7bd..be8626234627e 100644 +--- a/drivers/tty/serial/8250/8250_of.c ++++ b/drivers/tty/serial/8250/8250_of.c +@@ -83,8 +83,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev, + port->mapsize = resource_size(&resource); + + /* Check for shifted address mapping */ +- if (of_property_read_u32(np, "reg-offset", &prop) == 0) ++ if (of_property_read_u32(np, "reg-offset", &prop) == 0) { ++ if (prop >= port->mapsize) { ++ dev_warn(&ofdev->dev, "reg-offset %u exceeds region size %pa\n", ++ prop, &port->mapsize); ++ ret = -EINVAL; ++ goto err_unprepare; ++ } ++ + port->mapbase += prop; ++ port->mapsize -= prop; ++ } + + port->iotype = UPIO_MEM; + if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index 726912b16a559..114a49da564a9 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -1349,29 +1349,33 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud, + { + int scr; + int lcr; +- int actual_baud; +- int tolerance; + +- for (scr = 5 ; scr <= 15 ; scr++) { +- actual_baud = 921600 * 16 / scr; +- tolerance = actual_baud / 50; ++ for (scr = 16; scr > 4; scr--) { ++ unsigned int maxrate = port->uartclk / scr; ++ unsigned int divisor = max(maxrate / baud, 1U); ++ int delta = maxrate / divisor - baud; + +- if ((baud < actual_baud + tolerance) && +- (baud > actual_baud - tolerance)) { ++ if (baud > maxrate + baud / 50) ++ continue; + ++ if (delta > baud / 50) ++ divisor++; ++ ++ if (divisor > 0xffff) ++ continue; ++ ++ /* Update delta due to possible divisor change */ ++ delta = maxrate / divisor - baud; ++ if (abs(delta) < baud / 50) { + lcr = serial_port_in(port, UART_LCR); + serial_port_out(port, UART_LCR, lcr | 0x80); +- +- serial_port_out(port, UART_DLL, 1); +- serial_port_out(port, UART_DLM, 0); ++ serial_port_out(port, UART_DLL, divisor & 0xff); ++ serial_port_out(port, UART_DLM, divisor >> 8 & 0xff); + serial_port_out(port, 2, 16 - scr); + serial_port_out(port, UART_LCR, lcr); + return; +- } else if (baud > actual_baud) { +- break; + } + } +- serial8250_do_set_divisor(port, baud, quot, quot_frac); + } + static int pci_pericom_setup(struct serial_private *priv, + const struct pciserial_board *board, +@@ -2317,12 +2321,19 @@ static struct pci_serial_quirk pci_serial_quirks[] = { + .setup = pci_pericom_setup_four_at_eight, + }, + { +- .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, ++ .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, ++ { ++ .vendor = PCI_VENDOR_ID_ACCESIO, ++ .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = pci_pericom_setup_four_at_eight, ++ }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, +@@ -5192,8 +5203,30 @@ static const struct pci_device_id serial_pci_tbl[] = { + { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */ + pbn_b2_4_115200 }, ++ /* Brainboxes Devices */ ++ /* ++ * Brainboxes UC-101 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0BA1, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, ++ /* ++ * Brainboxes UC-235/246 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0AA1, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_1_115200 }, ++ /* ++ * Brainboxes UC-257 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0861, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, + /* +- * BrainBoxes UC-260 ++ * Brainboxes UC-260/271/701/756 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x0D21, + PCI_ANY_ID, PCI_ANY_ID, +@@ -5201,7 +5234,81 @@ static const struct pci_device_id serial_pci_tbl[] = { + pbn_b2_4_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x0E34, + PCI_ANY_ID, PCI_ANY_ID, +- PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, ++ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, ++ pbn_b2_4_115200 }, ++ /* ++ * Brainboxes UC-268 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0841, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_4_115200 }, ++ /* ++ * Brainboxes UC-275/279 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0881, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_8_115200 }, ++ /* ++ * Brainboxes UC-302 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x08E1, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, ++ /* ++ * Brainboxes UC-310 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x08C1, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, ++ /* ++ * Brainboxes UC-313 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x08A3, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, ++ /* ++ * Brainboxes UC-320/324 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0A61, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_1_115200 }, ++ /* ++ * Brainboxes UC-346 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0B02, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_4_115200 }, ++ /* ++ * Brainboxes UC-357 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0A81, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, ++ { PCI_VENDOR_ID_INTASHIELD, 0x0A83, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_2_115200 }, ++ /* ++ * Brainboxes UC-368 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0C41, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, ++ pbn_b2_4_115200 }, ++ /* ++ * Brainboxes UC-420/431 ++ */ ++ { PCI_VENDOR_ID_INTASHIELD, 0x0921, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, 0, + pbn_b2_4_115200 }, + /* + * Perle PCI-RAS cards +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index 66374704747ec..ec88b706e882f 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -2024,13 +2024,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) + struct uart_8250_port *up = up_to_u8250p(port); + unsigned char mcr; + +- if (port->rs485.flags & SER_RS485_ENABLED) { +- if (serial8250_in_MCR(up) & UART_MCR_RTS) +- mctrl |= TIOCM_RTS; +- else +- mctrl &= ~TIOCM_RTS; +- } +- + mcr = serial8250_TIOCM_to_MCR(mctrl); + + mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; +@@ -2696,21 +2689,32 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, + void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) + { + struct uart_8250_port *up = up_to_u8250p(port); ++ struct tty_port *tport = &port->state->port; + unsigned int baud, quot, frac = 0; + struct ktermios *termios; ++ struct tty_struct *tty; + unsigned long flags; + +- mutex_lock(&port->state->port.mutex); ++ tty = tty_port_tty_get(tport); ++ if (!tty) { ++ mutex_lock(&tport->mutex); ++ port->uartclk = uartclk; ++ mutex_unlock(&tport->mutex); ++ return; ++ } ++ ++ down_write(&tty->termios_rwsem); ++ mutex_lock(&tport->mutex); + + if (port->uartclk == uartclk) + goto out_lock; + + port->uartclk = uartclk; + +- if (!tty_port_initialized(&port->state->port)) ++ if (!tty_port_initialized(tport)) + goto out_lock; + +- termios = &port->state->port.tty->termios; ++ termios = &tty->termios; + + baud = serial8250_get_baud_rate(port, termios, NULL); + quot = serial8250_get_divisor(port, baud, &frac); +@@ -2727,7 +2731,9 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) + serial8250_rpm_put(up); + + out_lock: +- mutex_unlock(&port->state->port.mutex); ++ mutex_unlock(&tport->mutex); ++ up_write(&tty->termios_rwsem); ++ tty_kref_put(tty); + } + EXPORT_SYMBOL_GPL(serial8250_update_uartclk); + +diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c +index e744b953ca346..47654073123d6 100644 +--- a/drivers/tty/serial/amba-pl010.c ++++ b/drivers/tty/serial/amba-pl010.c +@@ -446,14 +446,11 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, + if ((termios->c_cflag & CREAD) == 0) + uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; + +- /* first, disable everything */ + old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; + + if (UART_ENABLE_MS(port, termios->c_cflag)) + old_cr |= UART010_CR_MSIE; + +- writel(0, uap->port.membase + UART010_CR); +- + /* Set baud rate */ + quot -= 1; + writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index d361cd84ff8cf..da54f827c5efc 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1615,8 +1615,12 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) + container_of(port, struct uart_amba_port, port); + unsigned int cr; + +- if (port->rs485.flags & SER_RS485_ENABLED) +- mctrl &= ~TIOCM_RTS; ++ if (port->rs485.flags & SER_RS485_ENABLED) { ++ if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ++ mctrl &= ~TIOCM_RTS; ++ else ++ mctrl |= TIOCM_RTS; ++ } + + cr = pl011_read(uap, REG_CR); + +@@ -2105,9 +2109,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, + if (port->rs485.flags & SER_RS485_ENABLED) + termios->c_cflag &= ~CRTSCTS; + +- /* first, disable everything */ + old_cr = pl011_read(uap, REG_CR); +- pl011_write(0, uap, REG_CR); + + if (termios->c_cflag & CRTSCTS) { + if (old_cr & UART011_CR_RTS) +@@ -2183,32 +2185,13 @@ static const char *pl011_type(struct uart_port *port) + return uap->port.type == PORT_AMBA ? uap->type : NULL; + } + +-/* +- * Release the memory region(s) being used by 'port' +- */ +-static void pl011_release_port(struct uart_port *port) +-{ +- release_mem_region(port->mapbase, SZ_4K); +-} +- +-/* +- * Request the memory region(s) being used by 'port' +- */ +-static int pl011_request_port(struct uart_port *port) +-{ +- return request_mem_region(port->mapbase, SZ_4K, "uart-pl011") +- != NULL ? 0 : -EBUSY; +-} +- + /* + * Configure/autoconfigure the port. + */ + static void pl011_config_port(struct uart_port *port, int flags) + { +- if (flags & UART_CONFIG_TYPE) { ++ if (flags & UART_CONFIG_TYPE) + port->type = PORT_AMBA; +- pl011_request_port(port); +- } + } + + /* +@@ -2223,6 +2206,8 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) + ret = -EINVAL; + if (ser->baud_base < 9600) + ret = -EINVAL; ++ if (port->mapbase != (unsigned long) ser->iomem_base) ++ ret = -EINVAL; + return ret; + } + +@@ -2275,8 +2260,6 @@ static const struct uart_ops amba_pl011_pops = { + .flush_buffer = pl011_dma_flush_buffer, + .set_termios = pl011_set_termios, + .type = pl011_type, +- .release_port = pl011_release_port, +- .request_port = pl011_request_port, + .config_port = pl011_config_port, + .verify_port = pl011_verify_port, + #ifdef CONFIG_CONSOLE_POLL +@@ -2306,8 +2289,6 @@ static const struct uart_ops sbsa_uart_pops = { + .shutdown = sbsa_uart_shutdown, + .set_termios = sbsa_uart_set_termios, + .type = pl011_type, +- .release_port = pl011_release_port, +- .request_port = pl011_request_port, + .config_port = pl011_config_port, + .verify_port = pl011_verify_port, + #ifdef CONFIG_CONSOLE_POLL +@@ -2947,6 +2928,7 @@ MODULE_DEVICE_TABLE(of, sbsa_uart_of_match); + + static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = { + { "ARMH0011", 0 }, ++ { "ARMHB000", 0 }, + {}, + }; + MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index 249ea35088d27..dd350c5908804 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -1004,6 +1004,13 @@ static void atmel_tx_dma(struct uart_port *port) + desc->callback = atmel_complete_tx_dma; + desc->callback_param = atmel_port; + atmel_port->cookie_tx = dmaengine_submit(desc); ++ if (dma_submit_error(atmel_port->cookie_tx)) { ++ dev_err(port->dev, "dma_submit_error %d\n", ++ atmel_port->cookie_tx); ++ return; ++ } ++ ++ dma_async_issue_pending(chan); + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) +@@ -1258,6 +1265,13 @@ static int atmel_prepare_rx_dma(struct uart_port *port) + desc->callback_param = port; + atmel_port->desc_rx = desc; + atmel_port->cookie_rx = dmaengine_submit(desc); ++ if (dma_submit_error(atmel_port->cookie_rx)) { ++ dev_err(port->dev, "dma_submit_error %d\n", ++ atmel_port->cookie_rx); ++ goto chan_err; ++ } ++ ++ dma_async_issue_pending(atmel_port->chan_rx); + + return 0; + +diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c +index c719aa2b18328..d6d3db9c3b1f8 100644 +--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c ++++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c +@@ -1090,6 +1090,7 @@ static void cpm_put_poll_char(struct uart_port *port, + cpm_uart_early_write(pinfo, ch, 1, false); + } + ++#ifdef CONFIG_SERIAL_CPM_CONSOLE + static struct uart_port *udbg_port; + + static void udbg_cpm_putc(char c) +@@ -1114,6 +1115,7 @@ static int udbg_cpm_getc(void) + cpu_relax(); + return c; + } ++#endif /* CONFIG_SERIAL_CPM_CONSOLE */ + + #endif /* CONFIG_CONSOLE_POLL */ + +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index b1e7190ae4836..ac5112def40d1 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -2625,6 +2625,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); + OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); + OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); + OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); ++OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); + EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); + EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); + +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index 8b121cd869e94..7820049aba5af 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -486,18 +486,21 @@ static void imx_uart_stop_tx(struct uart_port *port) + static void imx_uart_stop_rx(struct uart_port *port) + { + struct imx_port *sport = (struct imx_port *)port; +- u32 ucr1, ucr2; ++ u32 ucr1, ucr2, ucr4; + + ucr1 = imx_uart_readl(sport, UCR1); + ucr2 = imx_uart_readl(sport, UCR2); ++ ucr4 = imx_uart_readl(sport, UCR4); + + if (sport->dma_is_enabled) { + ucr1 &= ~(UCR1_RXDMAEN | UCR1_ATDMAEN); + } else { + ucr1 &= ~UCR1_RRDYEN; + ucr2 &= ~UCR2_ATEN; ++ ucr4 &= ~UCR4_OREN; + } + imx_uart_writel(sport, ucr1, UCR1); ++ imx_uart_writel(sport, ucr4, UCR4); + + ucr2 &= ~UCR2_RXEN; + imx_uart_writel(sport, ucr2, UCR2); +@@ -1544,7 +1547,7 @@ static void imx_uart_shutdown(struct uart_port *port) + imx_uart_writel(sport, ucr1, UCR1); + + ucr4 = imx_uart_readl(sport, UCR4); +- ucr4 &= ~(UCR4_OREN | UCR4_TCEN); ++ ucr4 &= ~UCR4_TCEN; + imx_uart_writel(sport, ucr4, UCR4); + + spin_unlock_irqrestore(&sport->port.lock, flags); +@@ -2017,7 +2020,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) + * If the port was already initialised (eg, by a boot loader), + * try to determine the current setup. + */ +-static void __init ++static void + imx_uart_console_get_options(struct imx_port *sport, int *baud, + int *parity, int *bits) + { +@@ -2076,7 +2079,7 @@ imx_uart_console_get_options(struct imx_port *sport, int *baud, + } + } + +-static int __init ++static int + imx_uart_console_setup(struct console *co, char *options) + { + struct imx_port *sport; +diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c +index dbc0559a91575..7f74bf7bdcff8 100644 +--- a/drivers/tty/serial/liteuart.c ++++ b/drivers/tty/serial/liteuart.c +@@ -270,8 +270,10 @@ static int liteuart_probe(struct platform_device *pdev) + + /* get membase */ + port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); +- if (IS_ERR(port->membase)) +- return PTR_ERR(port->membase); ++ if (IS_ERR(port->membase)) { ++ ret = PTR_ERR(port->membase); ++ goto err_erase_id; ++ } + + /* values not from device tree */ + port->dev = &pdev->dev; +@@ -285,7 +287,18 @@ static int liteuart_probe(struct platform_device *pdev) + port->line = dev_id; + spin_lock_init(&port->lock); + +- return uart_add_one_port(&liteuart_driver, &uart->port); ++ platform_set_drvdata(pdev, port); ++ ++ ret = uart_add_one_port(&liteuart_driver, &uart->port); ++ if (ret) ++ goto err_erase_id; ++ ++ return 0; ++ ++err_erase_id: ++ xa_erase(&liteuart_array, uart->id); ++ ++ return ret; + } + + static int liteuart_remove(struct platform_device *pdev) +@@ -293,6 +306,7 @@ static int liteuart_remove(struct platform_device *pdev) + struct uart_port *port = platform_get_drvdata(pdev); + struct liteuart_port *uart = to_liteuart_port(port); + ++ uart_remove_one_port(&liteuart_driver, port); + xa_erase(&liteuart_array, uart->id); + + return 0; +@@ -422,4 +436,4 @@ module_exit(liteuart_exit); + MODULE_AUTHOR("Antmicro <www.antmicro.com>"); + MODULE_DESCRIPTION("LiteUART serial driver"); + MODULE_LICENSE("GPL v2"); +-MODULE_ALIAS("platform: liteuart"); ++MODULE_ALIAS("platform:liteuart"); +diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c +index fcef7a961430b..489d19274f9ad 100644 +--- a/drivers/tty/serial/msm_serial.c ++++ b/drivers/tty/serial/msm_serial.c +@@ -598,6 +598,9 @@ static void msm_start_rx_dma(struct msm_port *msm_port) + u32 val; + int ret; + ++ if (IS_ENABLED(CONFIG_CONSOLE_POLL)) ++ return; ++ + if (!dma->chan) + return; + +diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c +index acbb615dd28fd..0ab788058fa2a 100644 +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -734,12 +734,15 @@ static irqreturn_t sc16is7xx_irq(int irq, void *dev_id) + static void sc16is7xx_tx_proc(struct kthread_work *ws) + { + struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port); ++ struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + + if ((port->rs485.flags & SER_RS485_ENABLED) && + (port->rs485.delay_rts_before_send > 0)) + msleep(port->rs485.delay_rts_before_send); + ++ mutex_lock(&s->efr_lock); + sc16is7xx_handle_tx(port); ++ mutex_unlock(&s->efr_lock); + } + + static void sc16is7xx_reconf_rs485(struct uart_port *port) +diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c +index 45e2e4109acd0..b6223fab0687d 100644 +--- a/drivers/tty/serial/serial-tegra.c ++++ b/drivers/tty/serial/serial-tegra.c +@@ -1506,7 +1506,7 @@ static struct tegra_uart_chip_data tegra20_uart_chip_data = { + .fifo_mode_enable_status = false, + .uart_max_port = 5, + .max_dma_burst_bytes = 4, +- .error_tolerance_low_range = 0, ++ .error_tolerance_low_range = -4, + .error_tolerance_high_range = 4, + }; + +@@ -1517,7 +1517,7 @@ static struct tegra_uart_chip_data tegra30_uart_chip_data = { + .fifo_mode_enable_status = false, + .uart_max_port = 5, + .max_dma_burst_bytes = 4, +- .error_tolerance_low_range = 0, ++ .error_tolerance_low_range = -4, + .error_tolerance_high_range = 4, + }; + +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index 0e2e35ab64c79..dc6129ddef85d 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -162,7 +162,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise) + int RTS_after_send = !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND); + + if (raise) { +- if (rs485_on && !RTS_after_send) { ++ if (rs485_on && RTS_after_send) { + uart_set_mctrl(uport, TIOCM_DTR); + uart_clear_mctrl(uport, TIOCM_RTS); + } else { +@@ -171,7 +171,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise) + } else { + unsigned int clear = TIOCM_DTR; + +- clear |= (!rs485_on || !RTS_after_send) ? TIOCM_RTS : 0; ++ clear |= (!rs485_on || RTS_after_send) ? TIOCM_RTS : 0; + uart_clear_mctrl(uport, clear); + } + } +@@ -222,7 +222,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, + if (retval == 0) { + if (uart_console(uport) && uport->cons->cflag) { + tty->termios.c_cflag = uport->cons->cflag; ++ tty->termios.c_ispeed = uport->cons->ispeed; ++ tty->termios.c_ospeed = uport->cons->ospeed; + uport->cons->cflag = 0; ++ uport->cons->ispeed = 0; ++ uport->cons->ospeed = 0; + } + /* + * Initialise the hardware port settings. +@@ -290,8 +294,11 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) + /* + * Turn off DTR and RTS early. + */ +- if (uport && uart_console(uport) && tty) ++ if (uport && uart_console(uport) && tty) { + uport->cons->cflag = tty->termios.c_cflag; ++ uport->cons->ispeed = tty->termios.c_ispeed; ++ uport->cons->ospeed = tty->termios.c_ospeed; ++ } + + if (!tty || C_HUPCL(tty)) + uart_port_dtr_rts(uport, 0); +@@ -1068,6 +1075,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) + goto out; + + if (!tty_io_error(tty)) { ++ if (uport->rs485.flags & SER_RS485_ENABLED) { ++ set &= ~TIOCM_RTS; ++ clear &= ~TIOCM_RTS; ++ } ++ + uart_update_mctrl(uport, set, clear); + ret = 0; + } +@@ -1542,6 +1554,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) + { + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport = uart_port_check(state); ++ char *buf; + + /* + * At this point, we stop accepting input. To do this, we +@@ -1563,8 +1576,18 @@ static void uart_tty_port_shutdown(struct tty_port *port) + */ + tty_port_set_suspended(port, 0); + +- uart_change_pm(state, UART_PM_STATE_OFF); ++ /* ++ * Free the transmit buffer. ++ */ ++ spin_lock_irq(&uport->lock); ++ buf = state->xmit.buf; ++ state->xmit.buf = NULL; ++ spin_unlock_irq(&uport->lock); ++ ++ if (buf) ++ free_page((unsigned long)buf); + ++ uart_change_pm(state, UART_PM_STATE_OFF); + } + + static void uart_wait_until_sent(struct tty_struct *tty, int timeout) +@@ -2094,8 +2117,11 @@ uart_set_options(struct uart_port *port, struct console *co, + * Allow the setting of the UART parameters with a NULL console + * too: + */ +- if (co) ++ if (co) { + co->cflag = termios.c_cflag; ++ co->ispeed = termios.c_ispeed; ++ co->ospeed = termios.c_ospeed; ++ } + + return 0; + } +@@ -2229,6 +2255,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) + */ + memset(&termios, 0, sizeof(struct ktermios)); + termios.c_cflag = uport->cons->cflag; ++ termios.c_ispeed = uport->cons->ispeed; ++ termios.c_ospeed = uport->cons->ospeed; + + /* + * If that's unset, use the tty termios setting. +@@ -2365,7 +2393,8 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, + * We probably don't need a spinlock around this, but + */ + spin_lock_irqsave(&port->lock, flags); +- port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR); ++ port->mctrl &= TIOCM_DTR; ++ port->ops->set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); + + /* +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index 8f032e77b954a..810a1b0b65203 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -421,10 +421,22 @@ static void stm32_usart_transmit_chars(struct uart_port *port) + struct stm32_port *stm32_port = to_stm32_port(port); + const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + struct circ_buf *xmit = &port->state->xmit; ++ u32 isr; ++ int ret; + + if (port->x_char) { + if (stm32_port->tx_dma_busy) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); ++ ++ /* Check that TDR is empty before filling FIFO */ ++ ret = ++ readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, ++ isr, ++ (isr & USART_SR_TXE), ++ 10, 1000); ++ if (ret) ++ dev_warn(port->dev, "1 character may be erased\n"); ++ + writel_relaxed(port->x_char, port->membase + ofs->tdr); + port->x_char = 0; + port->icount.tx++; +@@ -575,7 +587,7 @@ static void stm32_usart_start_tx(struct uart_port *port) + struct serial_rs485 *rs485conf = &port->rs485; + struct circ_buf *xmit = &port->state->xmit; + +- if (uart_circ_empty(xmit)) ++ if (uart_circ_empty(xmit) && !port->x_char) + return; + + if (rs485conf->flags & SER_RS485_ENABLED) { +@@ -691,6 +703,11 @@ static void stm32_usart_shutdown(struct uart_port *port) + u32 val, isr; + int ret; + ++ if (stm32_port->tx_dma_busy) { ++ dmaengine_terminate_async(stm32_port->tx_ch); ++ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); ++ } ++ + /* Disable modem control interrupts */ + stm32_usart_disable_ms(port); + +@@ -1385,7 +1402,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR); + + if (stm32_port->tx_ch) { +- dmaengine_terminate_async(stm32_port->tx_ch); + stm32_usart_of_dma_tx_remove(stm32_port, pdev); + dma_release_channel(stm32_port->tx_ch); + } +diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c +index dfc1ba4e15724..36871cebd6a0f 100644 +--- a/drivers/tty/serial/uartlite.c ++++ b/drivers/tty/serial/uartlite.c +@@ -612,7 +612,7 @@ static struct uart_driver ulite_uart_driver = { + * + * Returns: 0 on success, <0 otherwise + */ +-static int ulite_assign(struct device *dev, int id, u32 base, int irq, ++static int ulite_assign(struct device *dev, int id, phys_addr_t base, int irq, + struct uartlite_data *pdata) + { + struct uart_port *port; +diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c +index 962e522ccc45c..d5e243908d9fd 100644 +--- a/drivers/tty/serial/xilinx_uartps.c ++++ b/drivers/tty/serial/xilinx_uartps.c +@@ -601,9 +601,10 @@ static void cdns_uart_start_tx(struct uart_port *port) + if (uart_circ_empty(&port->state->xmit)) + return; + ++ writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); ++ + cdns_uart_handle_tx(port); + +- writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); + /* Enable the TX Empty interrupt */ + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); + } +diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c +index 635d0af229b72..6c7e65b1d9a1c 100644 +--- a/drivers/tty/tty_buffer.c ++++ b/drivers/tty/tty_buffer.c +@@ -544,6 +544,9 @@ static void flush_to_ldisc(struct work_struct *work) + if (!count) + break; + head->read += count; ++ ++ if (need_resched()) ++ cond_resched(); + } + + mutex_unlock(&buf->lock); +diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c +index 3639bb6dc372e..58013698635f0 100644 +--- a/drivers/tty/vt/vt_ioctl.c ++++ b/drivers/tty/vt/vt_ioctl.c +@@ -599,8 +599,8 @@ static int vt_setactivate(struct vt_setactivate __user *sa) + if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) + return -ENXIO; + +- vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES + 1); + vsa.console--; ++ vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES); + console_lock(); + ret = vc_allocate(vsa.console); + if (ret) { +@@ -845,6 +845,7 @@ int vt_ioctl(struct tty_struct *tty, + return -ENXIO; + + arg--; ++ arg = array_index_nospec(arg, MAX_NR_CONSOLES); + console_lock(); + ret = vc_allocate(arg); + console_unlock(); +diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c +index 1f3b4a1422126..f9af7ebe003d7 100644 +--- a/drivers/usb/cdns3/cdns3-gadget.c ++++ b/drivers/usb/cdns3/cdns3-gadget.c +@@ -337,19 +337,6 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep) + cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); + } + +-static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) +-{ +- struct cdns3_endpoint *priv_ep = priv_req->priv_ep; +- int current_trb = priv_req->start_trb; +- +- while (current_trb != priv_req->end_trb) { +- cdns3_ep_inc_deq(priv_ep); +- current_trb = priv_ep->dequeue; +- } +- +- cdns3_ep_inc_deq(priv_ep); +-} +- + /** + * cdns3_allow_enable_l1 - enable/disable permits to transition to L1. + * @priv_dev: Extended gadget object +@@ -1517,10 +1504,11 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, + + trb = priv_ep->trb_pool + priv_ep->dequeue; + +- /* Request was dequeued and TRB was changed to TRB_LINK. */ +- if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { ++ /* The TRB was changed as link TRB, and the request was handled at ep_dequeue */ ++ while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { + trace_cdns3_complete_trb(priv_ep, trb); +- cdns3_move_deq_to_next_trb(priv_req); ++ cdns3_ep_inc_deq(priv_ep); ++ trb = priv_ep->trb_pool + priv_ep->dequeue; + } + + if (!request->stream_id) { +diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c +index 27df0c6978978..e85bf768c66da 100644 +--- a/drivers/usb/cdns3/cdnsp-gadget.c ++++ b/drivers/usb/cdns3/cdnsp-gadget.c +@@ -1541,15 +1541,27 @@ static int cdnsp_gadget_pullup(struct usb_gadget *gadget, int is_on) + { + struct cdnsp_device *pdev = gadget_to_cdnsp(gadget); + struct cdns *cdns = dev_get_drvdata(pdev->dev); ++ unsigned long flags; + + trace_cdnsp_pullup(is_on); + ++ /* ++ * Disable events handling while controller is being ++ * enabled/disabled. ++ */ ++ disable_irq(cdns->dev_irq); ++ spin_lock_irqsave(&pdev->lock, flags); ++ + if (!is_on) { + cdnsp_reset_device(pdev); + cdns_clear_vbus(cdns); + } else { + cdns_set_vbus(cdns); + } ++ ++ spin_unlock_irqrestore(&pdev->lock, flags); ++ enable_irq(cdns->dev_irq); ++ + return 0; + } + +diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c +index ad9aee3f1e398..97866bfb2da9d 100644 +--- a/drivers/usb/cdns3/cdnsp-mem.c ++++ b/drivers/usb/cdns3/cdnsp-mem.c +@@ -987,6 +987,9 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev, + + /* Set up the endpoint ring. */ + pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags); ++ if (!pep->ring) ++ return -ENOMEM; ++ + pep->skip = false; + + /* Fill the endpoint context */ +diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c +index 1b1438457fb04..e45c3d6e1536c 100644 +--- a/drivers/usb/cdns3/cdnsp-ring.c ++++ b/drivers/usb/cdns3/cdnsp-ring.c +@@ -1029,6 +1029,8 @@ static void cdnsp_process_ctrl_td(struct cdnsp_device *pdev, + return; + } + ++ *status = 0; ++ + cdnsp_finish_td(pdev, td, event, pep, status); + } + +@@ -1523,7 +1525,14 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data) + spin_lock_irqsave(&pdev->lock, flags); + + if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) { +- cdnsp_died(pdev); ++ /* ++ * While removing or stopping driver there may still be deferred ++ * not handled interrupt which should not be treated as error. ++ * Driver should simply ignore it. ++ */ ++ if (pdev->gadget_driver) ++ cdnsp_died(pdev); ++ + spin_unlock_irqrestore(&pdev->lock, flags); + return IRQ_HANDLED; + } +diff --git a/drivers/usb/cdns3/cdnsp-trace.h b/drivers/usb/cdns3/cdnsp-trace.h +index 6a2571c6aa9ed..5983dfb996537 100644 +--- a/drivers/usb/cdns3/cdnsp-trace.h ++++ b/drivers/usb/cdns3/cdnsp-trace.h +@@ -57,9 +57,9 @@ DECLARE_EVENT_CLASS(cdnsp_log_ep, + __entry->first_prime_det = pep->stream_info.first_prime_det; + __entry->drbls_count = pep->stream_info.drbls_count; + ), +- TP_printk("%s: SID: %08x ep state: %x stream: enabled: %d num %d " ++ TP_printk("%s: SID: %08x, ep state: %x, stream: enabled: %d num %d " + "tds %d, first prime: %d drbls %d", +- __get_str(name), __entry->state, __entry->stream_id, ++ __get_str(name), __entry->stream_id, __entry->state, + __entry->enabled, __entry->num_streams, __entry->td_count, + __entry->first_prime_det, __entry->drbls_count) + ); +diff --git a/drivers/usb/cdns3/drd.c b/drivers/usb/cdns3/drd.c +index 55c73b1d87047..d00ff98dffabf 100644 +--- a/drivers/usb/cdns3/drd.c ++++ b/drivers/usb/cdns3/drd.c +@@ -483,11 +483,11 @@ int cdns_drd_exit(struct cdns *cdns) + /* Indicate the cdns3 core was power lost before */ + bool cdns_power_is_lost(struct cdns *cdns) + { +- if (cdns->version == CDNS3_CONTROLLER_V1) { +- if (!(readl(&cdns->otg_v1_regs->simulate) & BIT(0))) ++ if (cdns->version == CDNS3_CONTROLLER_V0) { ++ if (!(readl(&cdns->otg_v0_regs->simulate) & BIT(0))) + return true; + } else { +- if (!(readl(&cdns->otg_v0_regs->simulate) & BIT(0))) ++ if (!(readl(&cdns->otg_v1_regs->simulate) & BIT(0))) + return true; + } + return false; +diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c +index f1d100671ee6a..097142ffb1842 100644 +--- a/drivers/usb/chipidea/ci_hdrc_imx.c ++++ b/drivers/usb/chipidea/ci_hdrc_imx.c +@@ -420,15 +420,15 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) + data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); + if (IS_ERR(data->phy)) { + ret = PTR_ERR(data->phy); +- if (ret == -ENODEV) { +- data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0); +- if (IS_ERR(data->phy)) { +- ret = PTR_ERR(data->phy); +- if (ret == -ENODEV) +- data->phy = NULL; +- else +- goto err_clk; +- } ++ if (ret != -ENODEV) ++ goto err_clk; ++ data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0); ++ if (IS_ERR(data->phy)) { ++ ret = PTR_ERR(data->phy); ++ if (ret == -ENODEV) ++ data->phy = NULL; ++ else ++ goto err_clk; + } + } + +diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c +index 2b18f5088ae4a..a56f06368d142 100644 +--- a/drivers/usb/chipidea/core.c ++++ b/drivers/usb/chipidea/core.c +@@ -514,7 +514,7 @@ int hw_device_reset(struct ci_hdrc *ci) + return 0; + } + +-static irqreturn_t ci_irq(int irq, void *data) ++static irqreturn_t ci_irq_handler(int irq, void *data) + { + struct ci_hdrc *ci = data; + irqreturn_t ret = IRQ_NONE; +@@ -567,6 +567,15 @@ static irqreturn_t ci_irq(int irq, void *data) + return ret; + } + ++static void ci_irq(struct ci_hdrc *ci) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ci_irq_handler(ci->irq, ci); ++ local_irq_restore(flags); ++} ++ + static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, + void *ptr) + { +@@ -576,7 +585,7 @@ static int ci_cable_notifier(struct notifier_block *nb, unsigned long event, + cbl->connected = event; + cbl->changed = true; + +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + return NOTIFY_DONE; + } + +@@ -617,7 +626,7 @@ static int ci_usb_role_switch_set(struct usb_role_switch *sw, + if (cable) { + cable->changed = true; + cable->connected = false; +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + spin_unlock_irqrestore(&ci->lock, flags); + if (ci->wq && role != USB_ROLE_NONE) + flush_workqueue(ci->wq); +@@ -635,7 +644,7 @@ static int ci_usb_role_switch_set(struct usb_role_switch *sw, + if (cable) { + cable->changed = true; + cable->connected = true; +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + } + spin_unlock_irqrestore(&ci->lock, flags); + pm_runtime_put_sync(ci->dev); +@@ -1174,7 +1183,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) + } + } + +- ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, ++ ret = devm_request_irq(dev, ci->irq, ci_irq_handler, IRQF_SHARED, + ci->platdata->name, ci); + if (ret) + goto stop; +@@ -1295,11 +1304,11 @@ static void ci_extcon_wakeup_int(struct ci_hdrc *ci) + + if (!IS_ERR(cable_id->edev) && ci->is_otg && + (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + + if (!IS_ERR(cable_vbus->edev) && ci->is_otg && + (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + } + + static int ci_controller_resume(struct device *dev) +diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c +index 4169cf40a03b5..5509d3847af4b 100644 +--- a/drivers/usb/common/ulpi.c ++++ b/drivers/usb/common/ulpi.c +@@ -39,8 +39,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) + struct ulpi *ulpi = to_ulpi_dev(dev); + const struct ulpi_device_id *id; + +- /* Some ULPI devices don't have a vendor id so rely on OF match */ +- if (ulpi->id.vendor == 0) ++ /* ++ * Some ULPI devices don't have a vendor id ++ * or provide an id_table so rely on OF match. ++ */ ++ if (ulpi->id.vendor == 0 || !drv->id_table) + return of_driver_match_device(dev, driver); + + for (id = drv->id_table; id->vendor; id++) +@@ -127,6 +130,7 @@ static const struct attribute_group *ulpi_dev_attr_groups[] = { + + static void ulpi_dev_release(struct device *dev) + { ++ of_node_put(dev->of_node); + kfree(to_ulpi_dev(dev)); + } + +@@ -244,12 +248,16 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) + return ret; + + ret = ulpi_read_id(ulpi); +- if (ret) ++ if (ret) { ++ of_node_put(ulpi->dev.of_node); + return ret; ++ } + + ret = device_register(&ulpi->dev); +- if (ret) ++ if (ret) { ++ put_device(&ulpi->dev); + return ret; ++ } + + dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n", + ulpi->id.vendor, ulpi->id.product); +@@ -296,7 +304,6 @@ EXPORT_SYMBOL_GPL(ulpi_register_interface); + */ + void ulpi_unregister_interface(struct ulpi *ulpi) + { +- of_node_put(ulpi->dev.of_node); + device_unregister(&ulpi->dev); + } + EXPORT_SYMBOL_GPL(ulpi_unregister_interface); +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index b199eb65f3780..00e28456e4cc2 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -406,7 +406,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, + * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0 + * (see the end of section 5.6.3), so don't warn about them. + */ +- maxp = usb_endpoint_maxp(&endpoint->desc); ++ maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize); + if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) { + dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n", + cfgno, inum, asnum, d->bEndpointAddress); +@@ -422,9 +422,9 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, + maxpacket_maxes = full_speed_maxpacket_maxes; + break; + case USB_SPEED_HIGH: +- /* Bits 12..11 are allowed only for HS periodic endpoints */ ++ /* Multiple-transactions bits are allowed only for HS periodic endpoints */ + if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) { +- i = maxp & (BIT(12) | BIT(11)); ++ i = maxp & USB_EP_MAXP_MULT_MASK; + maxp &= ~i; + } + fallthrough; +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 9618ba622a2d0..fa66e6e587928 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -32,6 +32,7 @@ + #include <linux/usb.h> + #include <linux/usbdevice_fs.h> + #include <linux/usb/hcd.h> /* for usbcore internals */ ++#include <linux/usb/quirks.h> + #include <linux/cdev.h> + #include <linux/notifier.h> + #include <linux/security.h> +@@ -1102,14 +1103,55 @@ static int usbdev_release(struct inode *inode, struct file *file) + return 0; + } + ++static void usbfs_blocking_completion(struct urb *urb) ++{ ++ complete((struct completion *) urb->context); ++} ++ ++/* ++ * Much like usb_start_wait_urb, but returns status separately from ++ * actual_length and uses a killable wait. ++ */ ++static int usbfs_start_wait_urb(struct urb *urb, int timeout, ++ unsigned int *actlen) ++{ ++ DECLARE_COMPLETION_ONSTACK(ctx); ++ unsigned long expire; ++ int rc; ++ ++ urb->context = &ctx; ++ urb->complete = usbfs_blocking_completion; ++ *actlen = 0; ++ rc = usb_submit_urb(urb, GFP_KERNEL); ++ if (unlikely(rc)) ++ return rc; ++ ++ expire = (timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT); ++ rc = wait_for_completion_killable_timeout(&ctx, expire); ++ if (rc <= 0) { ++ usb_kill_urb(urb); ++ *actlen = urb->actual_length; ++ if (urb->status != -ENOENT) ++ ; /* Completed before it was killed */ ++ else if (rc < 0) ++ return -EINTR; ++ else ++ return -ETIMEDOUT; ++ } ++ *actlen = urb->actual_length; ++ return urb->status; ++} ++ + static int do_proc_control(struct usb_dev_state *ps, + struct usbdevfs_ctrltransfer *ctrl) + { + struct usb_device *dev = ps->dev; + unsigned int tmo; + unsigned char *tbuf; +- unsigned wLength; ++ unsigned int wLength, actlen; + int i, pipe, ret; ++ struct urb *urb = NULL; ++ struct usb_ctrlrequest *dr = NULL; + + ret = check_ctrlrecip(ps, ctrl->bRequestType, ctrl->bRequest, + ctrl->wIndex); +@@ -1122,51 +1164,63 @@ static int do_proc_control(struct usb_dev_state *ps, + sizeof(struct usb_ctrlrequest)); + if (ret) + return ret; ++ ++ ret = -ENOMEM; + tbuf = (unsigned char *)__get_free_page(GFP_KERNEL); +- if (!tbuf) { +- ret = -ENOMEM; ++ if (!tbuf) + goto done; +- } ++ urb = usb_alloc_urb(0, GFP_NOIO); ++ if (!urb) ++ goto done; ++ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); ++ if (!dr) ++ goto done; ++ ++ dr->bRequestType = ctrl->bRequestType; ++ dr->bRequest = ctrl->bRequest; ++ dr->wValue = cpu_to_le16(ctrl->wValue); ++ dr->wIndex = cpu_to_le16(ctrl->wIndex); ++ dr->wLength = cpu_to_le16(ctrl->wLength); ++ + tmo = ctrl->timeout; + snoop(&dev->dev, "control urb: bRequestType=%02x " + "bRequest=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, + ctrl->wIndex, ctrl->wLength); +- if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) { ++ ++ if ((ctrl->bRequestType & USB_DIR_IN) && wLength) { + pipe = usb_rcvctrlpipe(dev, 0); +- snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, NULL, 0); ++ usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf, ++ wLength, NULL, NULL); ++ snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, NULL, 0); + + usb_unlock_device(dev); +- i = usb_control_msg(dev, pipe, ctrl->bRequest, +- ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, +- tbuf, ctrl->wLength, tmo); ++ i = usbfs_start_wait_urb(urb, tmo, &actlen); + usb_lock_device(dev); +- snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, +- tbuf, max(i, 0)); +- if ((i > 0) && ctrl->wLength) { +- if (copy_to_user(ctrl->data, tbuf, i)) { ++ snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen); ++ if (!i && actlen) { ++ if (copy_to_user(ctrl->data, tbuf, actlen)) { + ret = -EFAULT; +- goto done; ++ goto recv_fault; + } + } + } else { +- if (ctrl->wLength) { +- if (copy_from_user(tbuf, ctrl->data, ctrl->wLength)) { ++ if (wLength) { ++ if (copy_from_user(tbuf, ctrl->data, wLength)) { + ret = -EFAULT; + goto done; + } + } + pipe = usb_sndctrlpipe(dev, 0); +- snoop_urb(dev, NULL, pipe, ctrl->wLength, tmo, SUBMIT, +- tbuf, ctrl->wLength); ++ usb_fill_control_urb(urb, dev, pipe, (unsigned char *) dr, tbuf, ++ wLength, NULL, NULL); ++ snoop_urb(dev, NULL, pipe, wLength, tmo, SUBMIT, tbuf, wLength); + + usb_unlock_device(dev); +- i = usb_control_msg(dev, pipe, ctrl->bRequest, +- ctrl->bRequestType, ctrl->wValue, ctrl->wIndex, +- tbuf, ctrl->wLength, tmo); ++ i = usbfs_start_wait_urb(urb, tmo, &actlen); + usb_lock_device(dev); +- snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0); ++ snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0); + } + if (i < 0 && i != -EPIPE) { + dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL " +@@ -1174,8 +1228,15 @@ static int do_proc_control(struct usb_dev_state *ps, + current->comm, ctrl->bRequestType, ctrl->bRequest, + ctrl->wLength, i); + } +- ret = i; ++ ret = (i < 0 ? i : actlen); ++ ++ recv_fault: ++ /* Linger a bit, prior to the next control message. */ ++ if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) ++ msleep(200); + done: ++ kfree(dr); ++ usb_free_urb(urb); + free_page((unsigned long) tbuf); + usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) + + sizeof(struct usb_ctrlrequest)); +@@ -1195,10 +1256,11 @@ static int do_proc_bulk(struct usb_dev_state *ps, + struct usbdevfs_bulktransfer *bulk) + { + struct usb_device *dev = ps->dev; +- unsigned int tmo, len1, pipe; +- int len2; ++ unsigned int tmo, len1, len2, pipe; + unsigned char *tbuf; + int i, ret; ++ struct urb *urb = NULL; ++ struct usb_host_endpoint *ep; + + ret = findintfep(ps->dev, bulk->ep); + if (ret < 0) +@@ -1206,14 +1268,17 @@ static int do_proc_bulk(struct usb_dev_state *ps, + ret = checkintf(ps, ret); + if (ret) + return ret; ++ ++ len1 = bulk->len; ++ if (len1 < 0 || len1 >= (INT_MAX - sizeof(struct urb))) ++ return -EINVAL; ++ + if (bulk->ep & USB_DIR_IN) + pipe = usb_rcvbulkpipe(dev, bulk->ep & 0x7f); + else + pipe = usb_sndbulkpipe(dev, bulk->ep & 0x7f); +- if (!usb_maxpacket(dev, pipe, !(bulk->ep & USB_DIR_IN))) +- return -EINVAL; +- len1 = bulk->len; +- if (len1 >= (INT_MAX - sizeof(struct urb))) ++ ep = usb_pipe_endpoint(dev, pipe); ++ if (!ep || !usb_endpoint_maxp(&ep->desc)) + return -EINVAL; + ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb)); + if (ret) +@@ -1223,17 +1288,29 @@ static int do_proc_bulk(struct usb_dev_state *ps, + * len1 can be almost arbitrarily large. Don't WARN if it's + * too big, just fail the request. + */ ++ ret = -ENOMEM; + tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN); +- if (!tbuf) { +- ret = -ENOMEM; ++ if (!tbuf) ++ goto done; ++ urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!urb) + goto done; ++ ++ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT) { ++ pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); ++ usb_fill_int_urb(urb, dev, pipe, tbuf, len1, ++ NULL, NULL, ep->desc.bInterval); ++ } else { ++ usb_fill_bulk_urb(urb, dev, pipe, tbuf, len1, NULL, NULL); + } ++ + tmo = bulk->timeout; + if (bulk->ep & 0x80) { + snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0); + + usb_unlock_device(dev); +- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); ++ i = usbfs_start_wait_urb(urb, tmo, &len2); + usb_lock_device(dev); + snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2); + +@@ -1253,12 +1330,13 @@ static int do_proc_bulk(struct usb_dev_state *ps, + snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1); + + usb_unlock_device(dev); +- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); ++ i = usbfs_start_wait_urb(urb, tmo, &len2); + usb_lock_device(dev); + snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0); + } + ret = (i < 0 ? i : len2); + done: ++ usb_free_urb(urb); + kfree(tbuf); + usbfs_decrease_memory_usage(len1 + sizeof(struct urb)); + return ret; +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 7ee6e4cc0d89e..dd3c288fa952f 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -753,6 +753,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) + { + struct urb *urb; + int length; ++ int status; + unsigned long flags; + char buffer[6]; /* Any root hubs with > 31 ports? */ + +@@ -770,11 +771,17 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) + if (urb) { + clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); + hcd->status_urb = NULL; ++ if (urb->transfer_buffer_length >= length) { ++ status = 0; ++ } else { ++ status = -EOVERFLOW; ++ length = urb->transfer_buffer_length; ++ } + urb->actual_length = length; + memcpy(urb->transfer_buffer, buffer, length); + + usb_hcd_unlink_urb_from_ep(hcd, urb); +- usb_hcd_giveback_urb(hcd, urb, 0); ++ usb_hcd_giveback_urb(hcd, urb, status); + } else { + length = 0; + set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); +@@ -1556,6 +1563,13 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) + urb->hcpriv = NULL; + INIT_LIST_HEAD(&urb->urb_list); + atomic_dec(&urb->use_count); ++ /* ++ * Order the write of urb->use_count above before the read ++ * of urb->reject below. Pairs with the memory barriers in ++ * usb_kill_urb() and usb_poison_urb(). ++ */ ++ smp_mb__after_atomic(); ++ + atomic_dec(&urb->dev->urbnum); + if (atomic_read(&urb->reject)) + wake_up(&usb_kill_urb_queue); +@@ -1658,6 +1672,13 @@ static void __usb_hcd_giveback_urb(struct urb *urb) + + usb_anchor_resume_wakeups(anchor); + atomic_dec(&urb->use_count); ++ /* ++ * Order the write of urb->use_count above before the read ++ * of urb->reject below. Pairs with the memory barriers in ++ * usb_kill_urb() and usb_poison_urb(). ++ */ ++ smp_mb__after_atomic(); ++ + if (unlikely(atomic_read(&urb->reject))) + wake_up(&usb_kill_urb_queue); + usb_put_urb(urb); +@@ -2795,7 +2816,6 @@ int usb_add_hcd(struct usb_hcd *hcd, + { + int retval; + struct usb_device *rhdev; +- struct usb_hcd *shared_hcd; + + if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) { + hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev); +@@ -2956,26 +2976,13 @@ int usb_add_hcd(struct usb_hcd *hcd, + goto err_hcd_driver_start; + } + +- /* starting here, usbcore will pay attention to the shared HCD roothub */ +- shared_hcd = hcd->shared_hcd; +- if (!usb_hcd_is_primary_hcd(hcd) && shared_hcd && HCD_DEFER_RH_REGISTER(shared_hcd)) { +- retval = register_root_hub(shared_hcd); +- if (retval != 0) +- goto err_register_root_hub; +- +- if (shared_hcd->uses_new_polling && HCD_POLL_RH(shared_hcd)) +- usb_hcd_poll_rh_status(shared_hcd); +- } +- + /* starting here, usbcore will pay attention to this root hub */ +- if (!HCD_DEFER_RH_REGISTER(hcd)) { +- retval = register_root_hub(hcd); +- if (retval != 0) +- goto err_register_root_hub; ++ retval = register_root_hub(hcd); ++ if (retval != 0) ++ goto err_register_root_hub; + +- if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) +- usb_hcd_poll_rh_status(hcd); +- } ++ if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) ++ usb_hcd_poll_rh_status(hcd); + + return retval; + +@@ -3013,7 +3020,6 @@ EXPORT_SYMBOL_GPL(usb_add_hcd); + void usb_remove_hcd(struct usb_hcd *hcd) + { + struct usb_device *rhdev = hcd->self.root_hub; +- bool rh_registered; + + dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); + +@@ -3024,7 +3030,6 @@ void usb_remove_hcd(struct usb_hcd *hcd) + + dev_dbg(hcd->self.controller, "roothub graceful disconnect\n"); + spin_lock_irq (&hcd_root_hub_lock); +- rh_registered = hcd->rh_registered; + hcd->rh_registered = 0; + spin_unlock_irq (&hcd_root_hub_lock); + +@@ -3034,8 +3039,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) + cancel_work_sync(&hcd->died_work); + + mutex_lock(&usb_bus_idr_lock); +- if (rh_registered) +- usb_disconnect(&rhdev); /* Sets rhdev to NULL */ ++ usb_disconnect(&rhdev); /* Sets rhdev to NULL */ + mutex_unlock(&usb_bus_idr_lock); + + /* +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 86658a81d2844..ac6c5ccfe1cb7 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1110,7 +1110,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + } else { + hub_power_on(hub, true); + } +- } ++ /* Give some time on remote wakeup to let links to transit to U0 */ ++ } else if (hub_is_superspeed(hub->hdev)) ++ msleep(20); ++ + init2: + + /* +@@ -1225,7 +1228,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) + */ + if (portchange || (hub_is_superspeed(hub->hdev) && + port_resumed)) +- set_bit(port1, hub->change_bits); ++ set_bit(port1, hub->event_bits); + + } else if (udev->persist_enabled) { + #ifdef CONFIG_PM +@@ -4700,8 +4703,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, + if (oldspeed == USB_SPEED_LOW) + delay = HUB_LONG_RESET_TIME; + +- mutex_lock(hcd->address0_mutex); +- + /* Reset the device; full speed may morph to high speed */ + /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ + retval = hub_port_reset(hub, port1, udev, delay, false); +@@ -5016,7 +5017,6 @@ fail: + hub_port_disable(hub, port1, 0); + update_devnum(udev, devnum); /* for disconnect processing */ + } +- mutex_unlock(hcd->address0_mutex); + return retval; + } + +@@ -5191,6 +5191,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; + static int unreliable_port = -1; ++ bool retry_locked; + + /* Disconnect any existing devices under this port */ + if (udev) { +@@ -5246,8 +5247,11 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + unit_load = 100; + + status = 0; +- for (i = 0; i < PORT_INIT_TRIES; i++) { + ++ for (i = 0; i < PORT_INIT_TRIES; i++) { ++ usb_lock_port(port_dev); ++ mutex_lock(hcd->address0_mutex); ++ retry_locked = true; + /* reallocate for each attempt, since references + * to the previous one can escape in various ways + */ +@@ -5255,6 +5259,8 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + if (!udev) { + dev_err(&port_dev->dev, + "couldn't allocate usb_device\n"); ++ mutex_unlock(hcd->address0_mutex); ++ usb_unlock_port(port_dev); + goto done; + } + +@@ -5276,12 +5282,14 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + } + + /* reset (non-USB 3.0 devices) and get descriptor */ +- usb_lock_port(port_dev); + status = hub_port_init(hub, udev, port1, i); +- usb_unlock_port(port_dev); + if (status < 0) + goto loop; + ++ mutex_unlock(hcd->address0_mutex); ++ usb_unlock_port(port_dev); ++ retry_locked = false; ++ + if (udev->quirks & USB_QUIRK_DELAY_INIT) + msleep(2000); + +@@ -5374,6 +5382,10 @@ loop: + usb_ep0_reinit(udev); + release_devnum(udev); + hub_free_dev(udev); ++ if (retry_locked) { ++ mutex_unlock(hcd->address0_mutex); ++ usb_unlock_port(port_dev); ++ } + usb_put_dev(udev); + if ((status == -ENOTCONN) || (status == -ENOTSUPP)) + break; +@@ -5915,6 +5927,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + bos = udev->bos; + udev->bos = NULL; + ++ mutex_lock(hcd->address0_mutex); ++ + for (i = 0; i < PORT_INIT_TRIES; ++i) { + + /* ep0 maxpacket size may change; let the HCD know about it. +@@ -5924,6 +5938,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) + if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) + break; + } ++ mutex_unlock(hcd->address0_mutex); + + if (ret < 0) + goto re_enumerate; +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 8239fe7129dd7..d3c14b5ed4a1f 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -434,6 +434,12 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x1532, 0x0116), .driver_info = + USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, + ++ /* Lenovo USB-C to Ethernet Adapter RTL8153-04 */ ++ { USB_DEVICE(0x17ef, 0x720c), .driver_info = USB_QUIRK_NO_LPM }, ++ ++ /* Lenovo Powered USB-C Travel Hub (4X90S92381, RTL8153 GigE) */ ++ { USB_DEVICE(0x17ef, 0x721e), .driver_info = USB_QUIRK_NO_LPM }, ++ + /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */ + { USB_DEVICE(0x17ef, 0xa012), .driver_info = + USB_QUIRK_DISCONNECT_SUSPEND }, +diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c +index 30727729a44cc..33d62d7e3929f 100644 +--- a/drivers/usb/core/urb.c ++++ b/drivers/usb/core/urb.c +@@ -715,6 +715,12 @@ void usb_kill_urb(struct urb *urb) + if (!(urb && urb->dev && urb->ep)) + return; + atomic_inc(&urb->reject); ++ /* ++ * Order the write of urb->reject above before the read ++ * of urb->use_count below. Pairs with the barriers in ++ * __usb_hcd_giveback_urb() and usb_hcd_submit_urb(). ++ */ ++ smp_mb__after_atomic(); + + usb_hcd_unlink_urb(urb, -ENOENT); + wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); +@@ -756,6 +762,12 @@ void usb_poison_urb(struct urb *urb) + if (!urb) + return; + atomic_inc(&urb->reject); ++ /* ++ * Order the write of urb->reject above before the read ++ * of urb->use_count below. Pairs with the barriers in ++ * __usb_hcd_giveback_urb() and usb_hcd_submit_urb(). ++ */ ++ smp_mb__after_atomic(); + + if (!urb->dev || !urb->ep) + return; +diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h +index cb9059a8444b5..71e62b3081dbb 100644 +--- a/drivers/usb/dwc2/core.h ++++ b/drivers/usb/dwc2/core.h +@@ -1417,6 +1417,7 @@ void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); + void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); + int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); + #define dwc2_is_device_connected(hsotg) (hsotg->connected) ++#define dwc2_is_device_enabled(hsotg) (hsotg->enabled) + int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg); + int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup); + int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg); +@@ -1453,6 +1454,7 @@ static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, + int testmode) + { return 0; } + #define dwc2_is_device_connected(hsotg) (0) ++#define dwc2_is_device_enabled(hsotg) (0) + static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) + { return 0; } + static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, +diff --git a/drivers/usb/dwc2/drd.c b/drivers/usb/dwc2/drd.c +index 2d4176f5788eb..36f2c38416e5e 100644 +--- a/drivers/usb/dwc2/drd.c ++++ b/drivers/usb/dwc2/drd.c +@@ -7,6 +7,7 @@ + * Author(s): Amelie Delaunay <amelie.delaunay@st.com> + */ + ++#include <linux/clk.h> + #include <linux/iopoll.h> + #include <linux/platform_device.h> + #include <linux/usb/role.h> +@@ -25,9 +26,9 @@ static void dwc2_ovr_init(struct dwc2_hsotg *hsotg) + gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); + dwc2_writel(hsotg, gotgctl, GOTGCTL); + +- dwc2_force_mode(hsotg, false); +- + spin_unlock_irqrestore(&hsotg->lock, flags); ++ ++ dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST)); + } + + static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) +@@ -39,6 +40,7 @@ static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) + (!valid && !(gotgctl & GOTGCTL_ASESVLD))) + return -EALREADY; + ++ gotgctl &= ~GOTGCTL_BVALOVAL; + if (valid) + gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL; + else +@@ -57,6 +59,7 @@ static int dwc2_ovr_bvalid(struct dwc2_hsotg *hsotg, bool valid) + (!valid && !(gotgctl & GOTGCTL_BSESVLD))) + return -EALREADY; + ++ gotgctl &= ~GOTGCTL_AVALOVAL; + if (valid) + gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; + else +@@ -86,14 +89,30 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) + } + #endif + ++ /* ++ * In case of USB_DR_MODE_PERIPHERAL, clock is disabled at the end of ++ * the probe and enabled on udc_start. ++ * If role-switch set is called before the udc_start, we need to enable ++ * the clock to read/write GOTGCTL and GUSBCFG registers to override ++ * mode and sessions. It is the case if cable is plugged at boot. ++ */ ++ if (!hsotg->ll_hw_enabled && hsotg->clk) { ++ int ret = clk_prepare_enable(hsotg->clk); ++ ++ if (ret) ++ return ret; ++ } ++ + spin_lock_irqsave(&hsotg->lock, flags); + + if (role == USB_ROLE_HOST) { + already = dwc2_ovr_avalid(hsotg, true); + } else if (role == USB_ROLE_DEVICE) { + already = dwc2_ovr_bvalid(hsotg, true); +- /* This clear DCTL.SFTDISCON bit */ +- dwc2_hsotg_core_connect(hsotg); ++ if (dwc2_is_device_enabled(hsotg)) { ++ /* This clear DCTL.SFTDISCON bit */ ++ dwc2_hsotg_core_connect(hsotg); ++ } + } else { + if (dwc2_is_device_mode(hsotg)) { + if (!dwc2_ovr_bvalid(hsotg, false)) +@@ -110,6 +129,9 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) + /* This will raise a Connector ID Status Change Interrupt */ + dwc2_force_mode(hsotg, role == USB_ROLE_HOST); + ++ if (!hsotg->ll_hw_enabled && hsotg->clk) ++ clk_disable_unprepare(hsotg->clk); ++ + dev_dbg(hsotg->dev, "%s-session valid\n", + role == USB_ROLE_NONE ? "No" : + role == USB_ROLE_HOST ? "A" : "B"); +diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c +index 11d85a6e0b0dc..0909b088a284b 100644 +--- a/drivers/usb/dwc2/gadget.c ++++ b/drivers/usb/dwc2/gadget.c +@@ -1198,6 +1198,8 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, + } + ctrl |= DXEPCTL_CNAK; + } else { ++ hs_req->req.frame_number = hs_ep->target_frame; ++ hs_req->req.actual = 0; + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA); + return; + } +@@ -2857,9 +2859,12 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep) + + do { + hs_req = get_ep_head(hs_ep); +- if (hs_req) ++ if (hs_req) { ++ hs_req->req.frame_number = hs_ep->target_frame; ++ hs_req->req.actual = 0; + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, + -ENODATA); ++ } + dwc2_gadget_incr_frame_num(hs_ep); + /* Update current frame number value. */ + hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg); +@@ -2912,8 +2917,11 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep) + + while (dwc2_gadget_target_frame_elapsed(ep)) { + hs_req = get_ep_head(ep); +- if (hs_req) ++ if (hs_req) { ++ hs_req->req.frame_number = ep->target_frame; ++ hs_req->req.actual = 0; + dwc2_hsotg_complete_request(hsotg, ep, hs_req, -ENODATA); ++ } + + dwc2_gadget_incr_frame_num(ep); + /* Update current frame number value. */ +@@ -3002,8 +3010,11 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) + + while (dwc2_gadget_target_frame_elapsed(hs_ep)) { + hs_req = get_ep_head(hs_ep); +- if (hs_req) ++ if (hs_req) { ++ hs_req->req.frame_number = hs_ep->target_frame; ++ hs_req->req.actual = 0; + dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA); ++ } + + dwc2_gadget_incr_frame_num(hs_ep); + /* Update current frame number value. */ +@@ -4963,7 +4974,18 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg) + hsotg->params.g_np_tx_fifo_size); + dev_dbg(dev, "RXFIFO size: %d\n", hsotg->params.g_rx_fifo_size); + +- hsotg->gadget.max_speed = USB_SPEED_HIGH; ++ switch (hsotg->params.speed) { ++ case DWC2_SPEED_PARAM_LOW: ++ hsotg->gadget.max_speed = USB_SPEED_LOW; ++ break; ++ case DWC2_SPEED_PARAM_FULL: ++ hsotg->gadget.max_speed = USB_SPEED_FULL; ++ break; ++ default: ++ hsotg->gadget.max_speed = USB_SPEED_HIGH; ++ break; ++ } ++ + hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; + hsotg->gadget.name = dev_name(dev); + hsotg->remote_wakeup_allowed = 0; +@@ -5074,7 +5096,7 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) + hsotg->gadget.speed = USB_SPEED_UNKNOWN; + spin_unlock_irqrestore(&hsotg->lock, flags); + +- for (ep = 0; ep < hsotg->num_of_eps; ep++) { ++ for (ep = 1; ep < hsotg->num_of_eps; ep++) { + if (hsotg->eps_in[ep]) + dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep); + if (hsotg->eps_out[ep]) +diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c +index a215ec9e172e6..657dbd50faf11 100644 +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -4403,11 +4403,12 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) + * If not hibernation nor partial power down are supported, + * clock gating is used to save power. + */ +- if (!hsotg->params.no_clock_gating) ++ if (!hsotg->params.no_clock_gating) { + dwc2_host_enter_clock_gating(hsotg); + +- /* After entering suspend, hardware is not accessible */ +- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ /* After entering suspend, hardware is not accessible */ ++ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ++ } + break; + default: + goto skip_power_saving; +diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c +index 89a788326c562..24beff610cf2c 100644 +--- a/drivers/usb/dwc2/hcd_queue.c ++++ b/drivers/usb/dwc2/hcd_queue.c +@@ -59,7 +59,7 @@ + #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) + + /* If we get a NAK, wait this long before retrying */ +-#define DWC2_RETRY_WAIT_DELAY (1 * 1E6L) ++#define DWC2_RETRY_WAIT_DELAY (1 * NSEC_PER_MSEC) + + /** + * dwc2_periodic_channel_available() - Checks that a channel is available for a +diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c +index c8f18f3ba9e35..c331a5128c2c0 100644 +--- a/drivers/usb/dwc2/platform.c ++++ b/drivers/usb/dwc2/platform.c +@@ -575,6 +575,9 @@ static int dwc2_driver_probe(struct platform_device *dev) + ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; + ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; + dwc2_writel(hsotg, ggpio, GGPIO); ++ ++ /* ID/VBUS detection startup time */ ++ usleep_range(5000, 7000); + } + + retval = dwc2_drd_init(hsotg); +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 0104a80b185e1..357b7805896e7 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1565,9 +1565,11 @@ static int dwc3_probe(struct platform_device *pdev) + + dwc3_get_properties(dwc); + +- ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); +- if (ret) +- return ret; ++ if (!dwc->sysdev_is_parent) { ++ ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); ++ if (ret) ++ return ret; ++ } + + dwc->reset = devm_reset_control_array_get_optional_shared(dev); + if (IS_ERR(dwc->reset)) +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 5612bfdf37da9..fd5d42ec53501 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -143,7 +143,7 @@ + #define DWC3_GHWPARAMS8 0xc600 + #define DWC3_GUCTL3 0xc60c + #define DWC3_GFLADJ 0xc630 +-#define DWC3_GHWPARAMS9 0xc680 ++#define DWC3_GHWPARAMS9 0xc6e0 + + /* Device Registers */ + #define DWC3_DCFG 0xc700 +@@ -723,6 +723,7 @@ struct dwc3_ep { + #define DWC3_EP_FORCE_RESTART_STREAM BIT(9) + #define DWC3_EP_FIRST_STREAM_PRIMED BIT(10) + #define DWC3_EP_PENDING_CLEAR_STALL BIT(11) ++#define DWC3_EP_TXFIFO_RESIZED BIT(12) + + /* This last one is specific to EP0 */ + #define DWC3_EP0_DIR_IN BIT(31) +diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c +index d0f9b7c296b0d..bd814df3bf8b8 100644 +--- a/drivers/usb/dwc3/dwc3-meson-g12a.c ++++ b/drivers/usb/dwc3/dwc3-meson-g12a.c +@@ -755,16 +755,16 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev) + + ret = dwc3_meson_g12a_get_phys(priv); + if (ret) +- goto err_disable_clks; ++ goto err_rearm; + + ret = priv->drvdata->setup_regmaps(priv, base); + if (ret) +- goto err_disable_clks; ++ goto err_rearm; + + if (priv->vbus) { + ret = regulator_enable(priv->vbus); + if (ret) +- goto err_disable_clks; ++ goto err_rearm; + } + + /* Get dr_mode */ +@@ -825,6 +825,9 @@ err_disable_regulator: + if (priv->vbus) + regulator_disable(priv->vbus); + ++err_rearm: ++ reset_control_rearm(priv->reset); ++ + err_disable_clks: + clk_bulk_disable_unprepare(priv->drvdata->num_clks, + priv->drvdata->clks); +@@ -852,6 +855,8 @@ static int dwc3_meson_g12a_remove(struct platform_device *pdev) + pm_runtime_put_noidle(dev); + pm_runtime_set_suspended(dev); + ++ reset_control_rearm(priv->reset); ++ + clk_bulk_disable_unprepare(priv->drvdata->num_clks, + priv->drvdata->clks); + +@@ -892,7 +897,7 @@ static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev) + phy_exit(priv->phys[i]); + } + +- reset_control_assert(priv->reset); ++ reset_control_rearm(priv->reset); + + return 0; + } +@@ -902,7 +907,9 @@ static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev) + struct dwc3_meson_g12a *priv = dev_get_drvdata(dev); + int i, ret; + +- reset_control_deassert(priv->reset); ++ ret = reset_control_reset(priv->reset); ++ if (ret) ++ return ret; + + ret = priv->drvdata->usb_init(priv); + if (ret) +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index 7ff8fc8f79a9b..1ecedbb1684c8 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -85,8 +85,8 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = { + static struct gpiod_lookup_table platform_bytcr_gpios = { + .dev_id = "0000:00:16.0", + .table = { +- GPIO_LOOKUP("INT33FC:00", 54, "reset", GPIO_ACTIVE_HIGH), +- GPIO_LOOKUP("INT33FC:02", 14, "cs", GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP("INT33FC:00", 54, "cs", GPIO_ACTIVE_HIGH), ++ GPIO_LOOKUP("INT33FC:02", 14, "reset", GPIO_ACTIVE_HIGH), + {} + }, + }; +@@ -119,6 +119,13 @@ static const struct property_entry dwc3_pci_intel_properties[] = { + {} + }; + ++static const struct property_entry dwc3_pci_intel_byt_properties[] = { ++ PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), ++ PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), ++ PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), ++ {} ++}; ++ + static const struct property_entry dwc3_pci_mrfld_properties[] = { + PROPERTY_ENTRY_STRING("dr_mode", "otg"), + PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), +@@ -161,6 +168,10 @@ static const struct software_node dwc3_pci_intel_swnode = { + .properties = dwc3_pci_intel_properties, + }; + ++static const struct software_node dwc3_pci_intel_byt_swnode = { ++ .properties = dwc3_pci_intel_byt_properties, ++}; ++ + static const struct software_node dwc3_pci_intel_mrfld_swnode = { + .properties = dwc3_pci_mrfld_properties, + }; +@@ -344,7 +355,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = { + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BYT), +- (kernel_ulong_t) &dwc3_pci_intel_swnode, }, ++ (kernel_ulong_t) &dwc3_pci_intel_byt_swnode, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD), + (kernel_ulong_t) &dwc3_pci_intel_mrfld_swnode, }, +diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c +index 9abbd01028c5f..b81a9e1c13153 100644 +--- a/drivers/usb/dwc3/dwc3-qcom.c ++++ b/drivers/usb/dwc3/dwc3-qcom.c +@@ -649,7 +649,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) + struct dwc3_qcom *qcom = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node, *dwc3_np; + struct device *dev = &pdev->dev; +- struct property *prop; + int ret; + + dwc3_np = of_get_compatible_child(np, "snps,dwc3"); +@@ -658,20 +657,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) + return -ENODEV; + } + +- prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL); +- if (!prop) { +- ret = -ENOMEM; +- dev_err(dev, "unable to allocate memory for property\n"); +- goto node_put; +- } +- +- prop->name = "tx-fifo-resize"; +- ret = of_add_property(dwc3_np, prop); +- if (ret) { +- dev_err(dev, "unable to add property\n"); +- goto node_put; +- } +- + ret = of_platform_populate(np, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to register dwc3 core - %d\n", ret); +@@ -784,9 +769,12 @@ static int dwc3_qcom_probe(struct platform_device *pdev) + + if (qcom->acpi_pdata->is_urs) { + qcom->urs_usb = dwc3_qcom_create_urs_usb_platdev(dev); +- if (!qcom->urs_usb) { ++ if (IS_ERR_OR_NULL(qcom->urs_usb)) { + dev_err(dev, "failed to create URS USB platdev\n"); +- return -ENODEV; ++ if (!qcom->urs_usb) ++ return -ENODEV; ++ else ++ return PTR_ERR(qcom->urs_usb); + } + } + } +diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c +index 9cc3ad701a295..a6f3a9b38789e 100644 +--- a/drivers/usb/dwc3/dwc3-xilinx.c ++++ b/drivers/usb/dwc3/dwc3-xilinx.c +@@ -99,17 +99,29 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data) + struct device *dev = priv_data->dev; + struct reset_control *crst, *hibrst, *apbrst; + struct phy *usb3_phy; +- int ret; ++ int ret = 0; + u32 reg; + +- usb3_phy = devm_phy_get(dev, "usb3-phy"); +- if (PTR_ERR(usb3_phy) == -EPROBE_DEFER) { +- ret = -EPROBE_DEFER; ++ usb3_phy = devm_phy_optional_get(dev, "usb3-phy"); ++ if (IS_ERR(usb3_phy)) { ++ ret = PTR_ERR(usb3_phy); ++ dev_err_probe(dev, ret, ++ "failed to get USB3 PHY\n"); + goto err; +- } else if (IS_ERR(usb3_phy)) { +- usb3_phy = NULL; + } + ++ /* ++ * The following core resets are not required unless a USB3 PHY ++ * is used, and the subsequent register settings are not required ++ * unless a core reset is performed (they should be set properly ++ * by the first-stage boot loader, but may be reverted by a core ++ * reset). They may also break the configuration if USB3 is actually ++ * in use but the usb3-phy entry is missing from the device tree. ++ * Therefore, skip these operations in this case. ++ */ ++ if (!usb3_phy) ++ goto skip_usb3_phy; ++ + crst = devm_reset_control_get_exclusive(dev, "usb_crst"); + if (IS_ERR(crst)) { + ret = PTR_ERR(crst); +@@ -188,6 +200,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data) + goto err; + } + ++skip_usb3_phy: + /* + * This routes the USB DMA traffic to go through FPD path instead + * of reaching DDR directly. This traffic routing is needed to +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 4519d06c9ca2b..00cf8ebcb338c 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -310,13 +310,24 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, + if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { + int link_state; + ++ /* ++ * Initiate remote wakeup if the link state is in U3 when ++ * operating in SS/SSP or L1/L2 when operating in HS/FS. If the ++ * link state is in U1/U2, no remote wakeup is needed. The Start ++ * Transfer command will initiate the link recovery. ++ */ + link_state = dwc3_gadget_get_link_state(dwc); +- if (link_state == DWC3_LINK_STATE_U1 || +- link_state == DWC3_LINK_STATE_U2 || +- link_state == DWC3_LINK_STATE_U3) { ++ switch (link_state) { ++ case DWC3_LINK_STATE_U2: ++ if (dwc->gadget->speed >= USB_SPEED_SUPER) ++ break; ++ ++ fallthrough; ++ case DWC3_LINK_STATE_U3: + ret = __dwc3_gadget_wakeup(dwc); + dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n", + ret); ++ break; + } + } + +@@ -702,6 +713,7 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) + DWC31_GTXFIFOSIZ_TXFRAMNUM; + + dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size); ++ dep->flags &= ~DWC3_EP_TXFIFO_RESIZED; + } + dwc->num_ep_resized = 0; + } +@@ -747,6 +759,10 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) + if (!usb_endpoint_dir_in(dep->endpoint.desc) || dep->number <= 1) + return 0; + ++ /* bail if already resized */ ++ if (dep->flags & DWC3_EP_TXFIFO_RESIZED) ++ return 0; ++ + ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); + + if ((dep->endpoint.maxburst > 1 && +@@ -807,6 +823,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) + } + + dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size); ++ dep->flags |= DWC3_EP_TXFIFO_RESIZED; + dwc->num_ep_resized++; + + return 0; +@@ -995,7 +1012,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) + + dep->stream_capable = false; + dep->type = 0; +- dep->flags = 0; ++ dep->flags &= DWC3_EP_TXFIFO_RESIZED; + + return 0; + } +@@ -1254,6 +1271,19 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, + if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) + trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(stream_id); + ++ /* ++ * As per data book 4.2.3.2TRB Control Bit Rules section ++ * ++ * The controller autonomously checks the HWO field of a TRB to determine if the ++ * entire TRB is valid. Therefore, software must ensure that the rest of the TRB ++ * is valid before setting the HWO field to '1'. In most systems, this means that ++ * software must update the fourth DWORD of a TRB last. ++ * ++ * However there is a possibility of CPU re-ordering here which can cause ++ * controller to observe the HWO bit set prematurely. ++ * Add a write memory barrier to prevent CPU re-ordering. ++ */ ++ wmb(); + trb->ctrl |= DWC3_TRB_CTRL_HWO; + + dwc3_ep_inc_enq(dep); +@@ -3246,6 +3276,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, + struct dwc3 *dwc = dep->dwc; + bool no_started_trb = true; + ++ if (!dep->endpoint.desc) ++ return no_started_trb; ++ + dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); + + if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) +@@ -3293,6 +3326,9 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, + { + int status = 0; + ++ if (!dep->endpoint.desc) ++ return; ++ + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) + dwc3_gadget_endpoint_frame_from_event(dep, event); + +@@ -3346,6 +3382,14 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep, + if (cmd != DWC3_DEPCMD_ENDTRANSFER) + return; + ++ /* ++ * The END_TRANSFER command will cause the controller to generate a ++ * NoStream Event, and it's not due to the host DP NoStream rejection. ++ * Ignore the next NoStream event. ++ */ ++ if (dep->stream_capable) ++ dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM; ++ + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + dep->flags &= ~DWC3_EP_TRANSFER_STARTED; + dwc3_gadget_ep_cleanup_cancelled_requests(dep); +@@ -3568,14 +3612,6 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, + WARN_ON_ONCE(ret); + dep->resource_index = 0; + +- /* +- * The END_TRANSFER command will cause the controller to generate a +- * NoStream Event, and it's not due to the host DP NoStream rejection. +- * Ignore the next NoStream event. +- */ +- if (dep->stream_capable) +- dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM; +- + if (!interrupt) + dep->flags &= ~DWC3_EP_TRANSFER_STARTED; + else +@@ -4095,9 +4131,11 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_evt) + unsigned long flags; + irqreturn_t ret = IRQ_NONE; + ++ local_bh_disable(); + spin_lock_irqsave(&dwc->lock, flags); + ret = dwc3_process_event_buf(evt); + spin_unlock_irqrestore(&dwc->lock, flags); ++ local_bh_enable(); + + return ret; + } +diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c +index be4ecbabdd586..6c0434100e38c 100644 +--- a/drivers/usb/early/xhci-dbc.c ++++ b/drivers/usb/early/xhci-dbc.c +@@ -14,7 +14,6 @@ + #include <linux/pci_ids.h> + #include <linux/memblock.h> + #include <linux/io.h> +-#include <linux/iopoll.h> + #include <asm/pci-direct.h> + #include <asm/fixmap.h> + #include <linux/bcd.h> +@@ -136,9 +135,17 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, int wait, int delay) + { + u32 result; + +- return readl_poll_timeout_atomic(ptr, result, +- ((result & mask) == done), +- delay, wait); ++ /* Can not use readl_poll_timeout_atomic() for early boot things */ ++ do { ++ result = readl(ptr); ++ result &= mask; ++ if (result == done) ++ return 0; ++ udelay(delay); ++ wait -= delay; ++ } while (wait > 0); ++ ++ return -ETIMEDOUT; + } + + static void __init xdbc_bios_handoff(void) +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index 504c1cbc255d1..553382ce38378 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -1679,6 +1679,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + struct usb_function *f = NULL; + u8 endp; + ++ if (w_length > USB_COMP_EP0_BUFSIZ) { ++ if (ctrl->bRequestType & USB_DIR_IN) { ++ /* Cast away the const, we are going to overwrite on purpose. */ ++ __le16 *temp = (__le16 *)&ctrl->wLength; ++ ++ *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); ++ w_length = USB_COMP_EP0_BUFSIZ; ++ } else { ++ goto done; ++ } ++ } ++ + /* partial re-init of the response message; the function or the + * gadget might need to intercept e.g. a control-OUT completion + * when we delegate to it. +@@ -1963,6 +1975,9 @@ unknown: + if (w_index != 0x5 || (w_value >> 8)) + break; + interface = w_value & 0xFF; ++ if (interface >= MAX_CONFIG_INTERFACES || ++ !os_desc_cfg->interface[interface]) ++ break; + buf[6] = w_index; + count = count_ext_prop(os_desc_cfg, + interface); +@@ -2209,7 +2224,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite, + if (!cdev->req) + return -ENOMEM; + +- cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); ++ cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); + if (!cdev->req->buf) + goto fail; + +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index 8260f38025b72..02f70c5c65fc2 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -614,7 +614,7 @@ static int ffs_ep0_open(struct inode *inode, struct file *file) + file->private_data = ffs; + ffs_data_opened(ffs); + +- return 0; ++ return stream_open(inode, file); + } + + static int ffs_ep0_release(struct inode *inode, struct file *file) +@@ -1154,7 +1154,7 @@ ffs_epfile_open(struct inode *inode, struct file *file) + file->private_data = epfile; + ffs_data_opened(epfile->ffs); + +- return 0; ++ return stream_open(inode, file); + } + + static int ffs_aio_cancel(struct kiocb *kiocb) +@@ -1711,16 +1711,24 @@ static void ffs_data_put(struct ffs_data *ffs) + + static void ffs_data_closed(struct ffs_data *ffs) + { ++ struct ffs_epfile *epfiles; ++ unsigned long flags; ++ + ENTER(); + + if (atomic_dec_and_test(&ffs->opened)) { + if (ffs->no_disconnect) { + ffs->state = FFS_DEACTIVATED; +- if (ffs->epfiles) { +- ffs_epfiles_destroy(ffs->epfiles, +- ffs->eps_count); +- ffs->epfiles = NULL; +- } ++ spin_lock_irqsave(&ffs->eps_lock, flags); ++ epfiles = ffs->epfiles; ++ ffs->epfiles = NULL; ++ spin_unlock_irqrestore(&ffs->eps_lock, ++ flags); ++ ++ if (epfiles) ++ ffs_epfiles_destroy(epfiles, ++ ffs->eps_count); ++ + if (ffs->setup_state == FFS_SETUP_PENDING) + __ffs_ep0_stall(ffs); + } else { +@@ -1767,17 +1775,34 @@ static struct ffs_data *ffs_data_new(const char *dev_name) + + static void ffs_data_clear(struct ffs_data *ffs) + { ++ struct ffs_epfile *epfiles; ++ unsigned long flags; ++ + ENTER(); + + ffs_closed(ffs); + + BUG_ON(ffs->gadget); + +- if (ffs->epfiles) +- ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count); ++ spin_lock_irqsave(&ffs->eps_lock, flags); ++ epfiles = ffs->epfiles; ++ ffs->epfiles = NULL; ++ spin_unlock_irqrestore(&ffs->eps_lock, flags); + +- if (ffs->ffs_eventfd) ++ /* ++ * potential race possible between ffs_func_eps_disable ++ * & ffs_epfile_release therefore maintaining a local ++ * copy of epfile will save us from use-after-free. ++ */ ++ if (epfiles) { ++ ffs_epfiles_destroy(epfiles, ffs->eps_count); ++ ffs->epfiles = NULL; ++ } ++ ++ if (ffs->ffs_eventfd) { + eventfd_ctx_put(ffs->ffs_eventfd); ++ ffs->ffs_eventfd = NULL; ++ } + + kfree(ffs->raw_descs_data); + kfree(ffs->raw_strings); +@@ -1790,7 +1815,6 @@ static void ffs_data_reset(struct ffs_data *ffs) + + ffs_data_clear(ffs); + +- ffs->epfiles = NULL; + ffs->raw_descs_data = NULL; + ffs->raw_descs = NULL; + ffs->raw_strings = NULL; +@@ -1919,12 +1943,15 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) + + static void ffs_func_eps_disable(struct ffs_function *func) + { +- struct ffs_ep *ep = func->eps; +- struct ffs_epfile *epfile = func->ffs->epfiles; +- unsigned count = func->ffs->eps_count; ++ struct ffs_ep *ep; ++ struct ffs_epfile *epfile; ++ unsigned short count; + unsigned long flags; + + spin_lock_irqsave(&func->ffs->eps_lock, flags); ++ count = func->ffs->eps_count; ++ epfile = func->ffs->epfiles; ++ ep = func->eps; + while (count--) { + /* pending requests get nuked */ + if (ep->ep) +@@ -1942,14 +1969,18 @@ static void ffs_func_eps_disable(struct ffs_function *func) + + static int ffs_func_eps_enable(struct ffs_function *func) + { +- struct ffs_data *ffs = func->ffs; +- struct ffs_ep *ep = func->eps; +- struct ffs_epfile *epfile = ffs->epfiles; +- unsigned count = ffs->eps_count; ++ struct ffs_data *ffs; ++ struct ffs_ep *ep; ++ struct ffs_epfile *epfile; ++ unsigned short count; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&func->ffs->eps_lock, flags); ++ ffs = func->ffs; ++ ep = func->eps; ++ epfile = ffs->epfiles; ++ count = ffs->eps_count; + while(count--) { + ep->ep->driver_data = ep; + +diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c +index 1abf08e5164af..6803cd60cc6dc 100644 +--- a/drivers/usb/gadget/function/f_sourcesink.c ++++ b/drivers/usb/gadget/function/f_sourcesink.c +@@ -584,6 +584,7 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, + + if (is_iso) { + switch (speed) { ++ case USB_SPEED_SUPER_PLUS: + case USB_SPEED_SUPER: + size = ss->isoc_maxpacket * + (ss->isoc_mult + 1) * +diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c +index ef55b8bb5870a..5226a47b68fda 100644 +--- a/drivers/usb/gadget/function/f_uac2.c ++++ b/drivers/usb/gadget/function/f_uac2.c +@@ -202,7 +202,7 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = { + + .bDescriptorSubtype = UAC_INPUT_TERMINAL, + /* .bTerminalID = DYNAMIC */ +- .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED), ++ .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE), + .bAssocTerminal = 0, + /* .bCSourceID = DYNAMIC */ + .iChannelNames = 0, +@@ -230,7 +230,7 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = { + + .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, + /* .bTerminalID = DYNAMIC */ +- .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED), ++ .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER), + .bAssocTerminal = 0, + /* .bSourceID = DYNAMIC */ + /* .bCSourceID = DYNAMIC */ +diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c +index 64de9f1b874c5..0f14c5291af07 100644 +--- a/drivers/usb/gadget/function/rndis.c ++++ b/drivers/usb/gadget/function/rndis.c +@@ -637,14 +637,17 @@ static int rndis_set_response(struct rndis_params *params, + rndis_set_cmplt_type *resp; + rndis_resp_t *r; + ++ BufLength = le32_to_cpu(buf->InformationBufferLength); ++ BufOffset = le32_to_cpu(buf->InformationBufferOffset); ++ if ((BufLength > RNDIS_MAX_TOTAL_SIZE) || ++ (BufOffset + 8 >= RNDIS_MAX_TOTAL_SIZE)) ++ return -EINVAL; ++ + r = rndis_add_response(params, sizeof(rndis_set_cmplt_type)); + if (!r) + return -ENOMEM; + resp = (rndis_set_cmplt_type *)r->buf; + +- BufLength = le32_to_cpu(buf->InformationBufferLength); +- BufOffset = le32_to_cpu(buf->InformationBufferOffset); +- + #ifdef VERBOSE_DEBUG + pr_debug("%s: Length: %d\n", __func__, BufLength); + pr_debug("%s: Offset: %d\n", __func__, BufOffset); +@@ -919,6 +922,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) + params->resp_avail = resp_avail; + params->v = v; + INIT_LIST_HEAD(¶ms->resp_queue); ++ spin_lock_init(¶ms->resp_lock); + pr_debug("%s: configNr = %d\n", __func__, i); + + return params; +@@ -1012,12 +1016,14 @@ void rndis_free_response(struct rndis_params *params, u8 *buf) + { + rndis_resp_t *r, *n; + ++ spin_lock(¶ms->resp_lock); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { + if (r->buf == buf) { + list_del(&r->list); + kfree(r); + } + } ++ spin_unlock(¶ms->resp_lock); + } + EXPORT_SYMBOL_GPL(rndis_free_response); + +@@ -1027,14 +1033,17 @@ u8 *rndis_get_next_response(struct rndis_params *params, u32 *length) + + if (!length) return NULL; + ++ spin_lock(¶ms->resp_lock); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { + if (!r->send) { + r->send = 1; + *length = r->length; ++ spin_unlock(¶ms->resp_lock); + return r->buf; + } + } + ++ spin_unlock(¶ms->resp_lock); + return NULL; + } + EXPORT_SYMBOL_GPL(rndis_get_next_response); +@@ -1051,7 +1060,9 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length) + r->length = length; + r->send = 0; + ++ spin_lock(¶ms->resp_lock); + list_add_tail(&r->list, ¶ms->resp_queue); ++ spin_unlock(¶ms->resp_lock); + return r; + } + +diff --git a/drivers/usb/gadget/function/rndis.h b/drivers/usb/gadget/function/rndis.h +index f6167f7fea82b..6206b8b7490f6 100644 +--- a/drivers/usb/gadget/function/rndis.h ++++ b/drivers/usb/gadget/function/rndis.h +@@ -174,6 +174,7 @@ typedef struct rndis_params { + void (*resp_avail)(void *v); + void *v; + struct list_head resp_queue; ++ spinlock_t resp_lock; + } rndis_params; + + /* RNDIS Message parser and other useless functions */ +diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c +index ad16163b5ff80..d22ac23c94b0f 100644 +--- a/drivers/usb/gadget/function/u_audio.c ++++ b/drivers/usb/gadget/function/u_audio.c +@@ -1097,7 +1097,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, + } + + kctl->id.device = pcm->device; +- kctl->id.subdevice = i; ++ kctl->id.subdevice = 0; + + err = snd_ctl_add(card, kctl); + if (err < 0) +@@ -1120,7 +1120,7 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, + } + + kctl->id.device = pcm->device; +- kctl->id.subdevice = i; ++ kctl->id.subdevice = 0; + + + kctl->tlv.c = u_audio_volume_tlv; +diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c +index 85a3f6d4b5af3..d15a54f6c24b9 100644 +--- a/drivers/usb/gadget/function/u_ether.c ++++ b/drivers/usb/gadget/function/u_ether.c +@@ -17,6 +17,7 @@ + #include <linux/etherdevice.h> + #include <linux/ethtool.h> + #include <linux/if_vlan.h> ++#include <linux/etherdevice.h> + + #include "u_ether.h" + +@@ -861,19 +862,23 @@ int gether_register_netdev(struct net_device *net) + { + struct eth_dev *dev; + struct usb_gadget *g; +- struct sockaddr sa; + int status; + + if (!net->dev.parent) + return -EINVAL; + dev = netdev_priv(net); + g = dev->gadget; ++ ++ net->addr_assign_type = NET_ADDR_RANDOM; ++ eth_hw_addr_set(net, dev->dev_mac); ++ + status = register_netdev(net); + if (status < 0) { + dev_dbg(&g->dev, "register_netdev failed, %d\n", status); + return status; + } else { + INFO(dev, "HOST MAC %pM\n", dev->host_mac); ++ INFO(dev, "MAC %pM\n", dev->dev_mac); + + /* two kinds of host-initiated state changes: + * - iff DATA transfer is active, carrier is "on" +@@ -881,15 +886,6 @@ int gether_register_netdev(struct net_device *net) + */ + netif_carrier_off(net); + } +- sa.sa_family = net->type; +- memcpy(sa.sa_data, dev->dev_mac, ETH_ALEN); +- rtnl_lock(); +- status = dev_set_mac_address(net, &sa, NULL); +- rtnl_unlock(); +- if (status) +- pr_warn("cannot set self ethernet address: %d\n", status); +- else +- INFO(dev, "MAC %pM\n", dev->dev_mac); + + return status; + } +diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h +index 255a61bd6a6a8..9d5f17b551bbd 100644 +--- a/drivers/usb/gadget/function/uvc.h ++++ b/drivers/usb/gadget/function/uvc.h +@@ -126,6 +126,7 @@ struct uvc_device { + enum uvc_state state; + struct usb_function func; + struct uvc_video video; ++ bool func_connected; + + /* Descriptors */ + struct { +@@ -156,6 +157,7 @@ static inline struct uvc_device *to_uvc(struct usb_function *f) + struct uvc_file_handle { + struct v4l2_fh vfh; + struct uvc_video *device; ++ bool is_uvc_app_handle; + }; + + #define to_uvc_file_handle(handle) \ +diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c +index 4ca89eab61590..197c26f7aec63 100644 +--- a/drivers/usb/gadget/function/uvc_v4l2.c ++++ b/drivers/usb/gadget/function/uvc_v4l2.c +@@ -227,17 +227,55 @@ static int + uvc_v4l2_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) + { ++ struct uvc_device *uvc = video_get_drvdata(fh->vdev); ++ struct uvc_file_handle *handle = to_uvc_file_handle(fh); ++ int ret; ++ + if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) + return -EINVAL; + +- return v4l2_event_subscribe(fh, sub, 2, NULL); ++ if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) ++ return -EBUSY; ++ ++ ret = v4l2_event_subscribe(fh, sub, 2, NULL); ++ if (ret < 0) ++ return ret; ++ ++ if (sub->type == UVC_EVENT_SETUP) { ++ uvc->func_connected = true; ++ handle->is_uvc_app_handle = true; ++ uvc_function_connect(uvc); ++ } ++ ++ return 0; ++} ++ ++static void uvc_v4l2_disable(struct uvc_device *uvc) ++{ ++ uvc->func_connected = false; ++ uvc_function_disconnect(uvc); ++ uvcg_video_enable(&uvc->video, 0); ++ uvcg_free_buffers(&uvc->video.queue); + } + + static int + uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) + { +- return v4l2_event_unsubscribe(fh, sub); ++ struct uvc_device *uvc = video_get_drvdata(fh->vdev); ++ struct uvc_file_handle *handle = to_uvc_file_handle(fh); ++ int ret; ++ ++ ret = v4l2_event_unsubscribe(fh, sub); ++ if (ret < 0) ++ return ret; ++ ++ if (sub->type == UVC_EVENT_SETUP && handle->is_uvc_app_handle) { ++ uvc_v4l2_disable(uvc); ++ handle->is_uvc_app_handle = false; ++ } ++ ++ return 0; + } + + static long +@@ -292,7 +330,6 @@ uvc_v4l2_open(struct file *file) + handle->device = &uvc->video; + file->private_data = &handle->vfh; + +- uvc_function_connect(uvc); + return 0; + } + +@@ -304,11 +341,9 @@ uvc_v4l2_release(struct file *file) + struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); + struct uvc_video *video = handle->device; + +- uvc_function_disconnect(uvc); +- + mutex_lock(&video->mutex); +- uvcg_video_enable(video, 0); +- uvcg_free_buffers(&video->queue); ++ if (handle->is_uvc_app_handle) ++ uvc_v4l2_disable(uvc); + mutex_unlock(&video->mutex); + + file->private_data = NULL; +diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c +index e1d566c9918ae..6bcbad3825802 100644 +--- a/drivers/usb/gadget/legacy/dbgp.c ++++ b/drivers/usb/gadget/legacy/dbgp.c +@@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep) + goto fail_1; + } + +- req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL); ++ req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL); + if (!req->buf) { + err = -ENOMEM; + stp = 2; +@@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget, + void *data = NULL; + u16 len = 0; + ++ if (length > DBGP_REQ_LEN) { ++ if (ctrl->bRequestType & USB_DIR_IN) { ++ /* Cast away the const, we are going to overwrite on purpose. */ ++ __le16 *temp = (__le16 *)&ctrl->wLength; ++ ++ *temp = cpu_to_le16(DBGP_REQ_LEN); ++ length = DBGP_REQ_LEN; ++ } else { ++ return err; ++ } ++ } ++ ++ + if (request == USB_REQ_GET_DESCRIPTOR) { + switch (value>>8) { + case USB_DT_DEVICE: +diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c +index 5b27d289443fe..3912cc805f3af 100644 +--- a/drivers/usb/gadget/legacy/hid.c ++++ b/drivers/usb/gadget/legacy/hid.c +@@ -99,8 +99,10 @@ static int do_config(struct usb_configuration *c) + + list_for_each_entry(e, &hidg_func_list, node) { + e->f = usb_get_function(e->fi); +- if (IS_ERR(e->f)) ++ if (IS_ERR(e->f)) { ++ status = PTR_ERR(e->f); + goto put; ++ } + status = usb_add_function(c, e->f); + if (status < 0) { + usb_put_function(e->f); +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index 539220d7f5b62..3279b4767424c 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -110,6 +110,8 @@ enum ep0_state { + /* enough for the whole queue: most events invalidate others */ + #define N_EVENT 5 + ++#define RBUF_SIZE 256 ++ + struct dev_data { + spinlock_t lock; + refcount_t count; +@@ -144,7 +146,7 @@ struct dev_data { + struct dentry *dentry; + + /* except this scratch i/o buffer for ep0 */ +- u8 rbuf [256]; ++ u8 rbuf[RBUF_SIZE]; + }; + + static inline void get_dev (struct dev_data *data) +@@ -1334,6 +1336,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + ++ if (w_length > RBUF_SIZE) { ++ if (ctrl->bRequestType & USB_DIR_IN) { ++ /* Cast away the const, we are going to overwrite on purpose. */ ++ __le16 *temp = (__le16 *)&ctrl->wLength; ++ ++ *temp = cpu_to_le16(RBUF_SIZE); ++ w_length = RBUF_SIZE; ++ } else { ++ return value; ++ } ++ } ++ + spin_lock (&dev->lock); + dev->setup_abort = 0; + if (dev->state == STATE_DEV_UNCONNECTED) { +@@ -1815,8 +1829,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + spin_lock_irq (&dev->lock); + value = -EINVAL; + if (dev->buf) { ++ spin_unlock_irq(&dev->lock); + kfree(kbuf); +- goto fail; ++ return value; + } + dev->buf = kbuf; + +@@ -1863,8 +1878,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + + value = usb_gadget_probe_driver(&gadgetfs_driver); + if (value != 0) { +- kfree (dev->buf); +- dev->buf = NULL; ++ spin_lock_irq(&dev->lock); ++ goto fail; + } else { + /* at this point "good" hardware has for the first time + * let the USB the host see us. alternatively, if users +@@ -1881,6 +1896,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + return value; + + fail: ++ dev->config = NULL; ++ dev->hs_config = NULL; ++ dev->dev = NULL; + spin_unlock_irq (&dev->lock); + pr_debug ("%s: %s fail %zd, %p\n", shortname, __func__, value, dev); + kfree (dev->buf); +diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c +index c5a2c734234a5..d86c3a36441ee 100644 +--- a/drivers/usb/gadget/legacy/raw_gadget.c ++++ b/drivers/usb/gadget/legacy/raw_gadget.c +@@ -1004,7 +1004,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, + ret = -EBUSY; + goto out_unlock; + } +- if ((in && !ep->ep->caps.dir_in) || (!in && ep->ep->caps.dir_in)) { ++ if (in != usb_endpoint_dir_in(ep->ep->desc)) { + dev_dbg(&dev->gadget->dev, "fail, wrong direction\n"); + ret = -EINVAL; + goto out_unlock; +diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig +index 8c614bb86c665..69394dc1cdfb6 100644 +--- a/drivers/usb/gadget/udc/Kconfig ++++ b/drivers/usb/gadget/udc/Kconfig +@@ -330,6 +330,7 @@ config USB_AMD5536UDC + config USB_FSL_QE + tristate "Freescale QE/CPM USB Device Controller" + depends on FSL_SOC && (QUICC_ENGINE || CPM) ++ depends on !64BIT || BROKEN + help + Some of Freescale PowerPC processors have a Full Speed + QE/CPM2 USB controller, which support device mode with 4 +diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c +index 57d417a7c3e0a..601829a6b4bad 100644 +--- a/drivers/usb/gadget/udc/renesas_usb3.c ++++ b/drivers/usb/gadget/udc/renesas_usb3.c +@@ -2378,6 +2378,8 @@ static void handle_ext_role_switch_states(struct device *dev, + switch (role) { + case USB_ROLE_NONE: + usb3->connection_state = USB_ROLE_NONE; ++ if (cur_role == USB_ROLE_HOST) ++ device_release_driver(host); + if (usb3->driver) + usb3_disconnect(usb3); + usb3_vbus_out(usb3, false); +diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c +index fb4ffedd6f0dd..9cf43731bcd18 100644 +--- a/drivers/usb/gadget/udc/udc-xilinx.c ++++ b/drivers/usb/gadget/udc/udc-xilinx.c +@@ -1612,6 +1612,8 @@ static void xudc_getstatus(struct xusb_udc *udc) + break; + case USB_RECIP_ENDPOINT: + epnum = udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; ++ if (epnum >= XUSB_MAX_ENDPOINTS) ++ goto stall; + target_ep = &udc->ep[epnum]; + epcfgreg = udc->read_fn(udc->addr + target_ep->offset); + halt = epcfgreg & XUSB_EP_CFG_STALL_MASK; +@@ -1679,6 +1681,10 @@ static void xudc_set_clear_feature(struct xusb_udc *udc) + case USB_RECIP_ENDPOINT: + if (!udc->setup.wValue) { + endpoint = udc->setup.wIndex & USB_ENDPOINT_NUMBER_MASK; ++ if (endpoint >= XUSB_MAX_ENDPOINTS) { ++ xudc_ep0_stall(udc); ++ return; ++ } + target_ep = &udc->ep[endpoint]; + outinbit = udc->setup.wIndex & USB_ENDPOINT_DIR_MASK; + outinbit = outinbit >> 7; +diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c +index d3626bfa966b4..6a0f64c9e5e88 100644 +--- a/drivers/usb/host/ehci-brcm.c ++++ b/drivers/usb/host/ehci-brcm.c +@@ -62,8 +62,12 @@ static int ehci_brcm_hub_control( + u32 __iomem *status_reg; + unsigned long flags; + int retval, irq_disabled = 0; ++ u32 temp; + +- status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; ++ temp = (wIndex & 0xff) - 1; ++ if (temp >= HCS_N_PORTS_MAX) /* Avoid index-out-of-bounds warning */ ++ temp = 0; ++ status_reg = &ehci->regs->port_status[temp]; + + /* + * RESUME is cleared when GetPortStatus() is called 20ms after start +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 1776c05d0a486..1440803216297 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -635,7 +635,16 @@ static int ehci_run (struct usb_hcd *hcd) + /* Wait until HC become operational */ + ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + msleep(5); +- rc = ehci_handshake(ehci, &ehci->regs->status, STS_HALT, 0, 100 * 1000); ++ ++ /* For Aspeed, STS_HALT also depends on ASS/PSS status. ++ * Check CMD_RUN instead. ++ */ ++ if (ehci->is_aspeed) ++ rc = ehci_handshake(ehci, &ehci->regs->command, CMD_RUN, ++ 1, 100 * 1000); ++ else ++ rc = ehci_handshake(ehci, &ehci->regs->status, STS_HALT, ++ 0, 100 * 1000); + + up_write(&ehci_cf_port_reset_rwsem); + +diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c +index c70f2d0b4aaf0..c3dc906274d93 100644 +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -297,6 +297,12 @@ static int ehci_platform_probe(struct platform_device *dev) + "has-transaction-translator")) + hcd->has_tt = 1; + ++ if (of_device_is_compatible(dev->dev.of_node, ++ "aspeed,ast2500-ehci") || ++ of_device_is_compatible(dev->dev.of_node, ++ "aspeed,ast2600-ehci")) ++ ehci->is_aspeed = 1; ++ + if (soc_device_match(quirk_poll_match)) + priv->quirk_poll = true; + +diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h +index 80bb823aa9fe8..fdd073cc053b8 100644 +--- a/drivers/usb/host/ehci.h ++++ b/drivers/usb/host/ehci.h +@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controller */ + unsigned need_oc_pp_cycle:1; /* MPC834X port power */ + unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ + unsigned spurious_oc:1; ++ unsigned is_aspeed:1; + + /* required for usb32 quirk */ + #define OHCI_CTRL_HCFS (3 << 6) +diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c +index 59cc1bc7f12f5..30de85a707fef 100644 +--- a/drivers/usb/host/max3421-hcd.c ++++ b/drivers/usb/host/max3421-hcd.c +@@ -125,8 +125,6 @@ struct max3421_hcd { + + struct task_struct *spi_thread; + +- struct max3421_hcd *next; +- + enum max3421_rh_state rh_state; + /* lower 16 bits contain port status, upper 16 bits the change mask: */ + u32 port_status; +@@ -174,8 +172,6 @@ struct max3421_ep { + u8 retransmit; /* packet needs retransmission */ + }; + +-static struct max3421_hcd *max3421_hcd_list; +- + #define MAX3421_FIFO_SIZE 64 + + #define MAX3421_SPI_DIR_RD 0 /* read register from MAX3421 */ +@@ -1882,9 +1878,8 @@ max3421_probe(struct spi_device *spi) + } + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + max3421_hcd = hcd_to_max3421(hcd); +- max3421_hcd->next = max3421_hcd_list; +- max3421_hcd_list = max3421_hcd; + INIT_LIST_HEAD(&max3421_hcd->ep_list); ++ spi_set_drvdata(spi, max3421_hcd); + + max3421_hcd->tx = kmalloc(sizeof(*max3421_hcd->tx), GFP_KERNEL); + if (!max3421_hcd->tx) +@@ -1934,28 +1929,18 @@ error: + static int + max3421_remove(struct spi_device *spi) + { +- struct max3421_hcd *max3421_hcd = NULL, **prev; +- struct usb_hcd *hcd = NULL; ++ struct max3421_hcd *max3421_hcd; ++ struct usb_hcd *hcd; + unsigned long flags; + +- for (prev = &max3421_hcd_list; *prev; prev = &(*prev)->next) { +- max3421_hcd = *prev; +- hcd = max3421_to_hcd(max3421_hcd); +- if (hcd->self.controller == &spi->dev) +- break; +- } +- if (!max3421_hcd) { +- dev_err(&spi->dev, "no MAX3421 HCD found for SPI device %p\n", +- spi); +- return -ENODEV; +- } ++ max3421_hcd = spi_get_drvdata(spi); ++ hcd = max3421_to_hcd(max3421_hcd); + + usb_remove_hcd(hcd); + + spin_lock_irqsave(&max3421_hcd->lock, flags); + + kthread_stop(max3421_hcd->spi_thread); +- *prev = max3421_hcd->next; + + spin_unlock_irqrestore(&max3421_hcd->lock, flags); + +diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c +index 08ec2ab0d95a5..3f3d62dc06746 100644 +--- a/drivers/usb/host/ohci-tmio.c ++++ b/drivers/usb/host/ohci-tmio.c +@@ -199,7 +199,7 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev) + if (usb_disabled()) + return -ENODEV; + +- if (!cell) ++ if (!cell || !regs || !config || !sram) + return -EINVAL; + + if (irq < 0) +diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c +index 70dbd95c3f063..be9e9db7cad10 100644 +--- a/drivers/usb/host/uhci-platform.c ++++ b/drivers/usb/host/uhci-platform.c +@@ -113,7 +113,8 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev) + num_ports); + } + if (of_device_is_compatible(np, "aspeed,ast2400-uhci") || +- of_device_is_compatible(np, "aspeed,ast2500-uhci")) { ++ of_device_is_compatible(np, "aspeed,ast2500-uhci") || ++ of_device_is_compatible(np, "aspeed,ast2600-uhci")) { + uhci->is_aspeed = 1; + dev_info(&pdev->dev, + "Enabled Aspeed implementation workarounds\n"); +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index a3f875eea7519..df3522dab31b5 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -257,7 +257,6 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, + { + u16 temp; + +- desc->bPwrOn2PwrGood = 10; /* xhci section 5.4.9 says 20ms max */ + desc->bHubContrCurrent = 0; + + desc->bNbrPorts = ports; +@@ -292,6 +291,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, + desc->bDescriptorType = USB_DT_HUB; + temp = 1 + (ports / 8); + desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp; ++ desc->bPwrOn2PwrGood = 10; /* xhci section 5.4.8 says 20ms */ + + /* The Device Removable bits are reported on a byte granularity. + * If the port doesn't exist within that byte, the bit is set to 0. +@@ -344,6 +344,7 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, + xhci_common_hub_descriptor(xhci, desc, ports); + desc->bDescriptorType = USB_DT_SS_HUB; + desc->bDescLength = USB_DT_SS_HUB_SIZE; ++ desc->bPwrOn2PwrGood = 50; /* usb 3.1 may fail if less than 100ms */ + + /* header decode latency should be zero for roothubs, + * see section 4.23.5.2. +@@ -716,6 +717,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, + continue; + + retval = xhci_disable_slot(xhci, i); ++ xhci_free_virt_device(xhci, i); + if (retval) + xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", + i, retval); +diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c +index 134f4789bd897..b4c84b3635074 100644 +--- a/drivers/usb/host/xhci-mtk-sch.c ++++ b/drivers/usb/host/xhci-mtk-sch.c +@@ -781,7 +781,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) + + ret = xhci_check_bandwidth(hcd, udev); + if (!ret) +- INIT_LIST_HEAD(&mtk->bw_ep_chk_list); ++ list_del_init(&mtk->bw_ep_chk_list); + + return ret; + } +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 2484a9d38ce2b..de9a9ea2cabc2 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -65,6 +65,15 @@ + #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba + #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb + #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 0x161a ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 0x161b ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 0x161d ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6 ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7 ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 0x161c ++#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8 0x161f ++ + #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 + #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 + #define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242 +@@ -114,7 +123,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + /* Look for vendor-specific quirks */ + if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && + (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || +- pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 || + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) { + if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && + pdev->revision == 0x0) { +@@ -149,6 +157,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1009) + xhci->quirks |= XHCI_BROKEN_STREAMS; + ++ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && ++ pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1100) ++ xhci->quirks |= XHCI_TRUST_TX_LENGTH; ++ + if (pdev->vendor == PCI_VENDOR_ID_NEC) + xhci->quirks |= XHCI_NEC_HOST; + +@@ -317,6 +329,17 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) + xhci->quirks |= XHCI_NO_SOFT_RETRY; + ++ if (pdev->vendor == PCI_VENDOR_ID_AMD && ++ (pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_1 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_2 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 || ++ pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8)) ++ xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; ++ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, + "QUIRK: Resetting on resume"); +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index c1edcc9b13cec..dc570ce4e8319 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -437,6 +437,9 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; + ++ if (pm_runtime_suspended(dev)) ++ pm_runtime_resume(dev); ++ + ret = xhci_priv_suspend_quirk(hcd); + if (ret) + return ret; +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 311597bba80e2..d0b6806275e01 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -366,7 +366,9 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci, + /* Must be called with xhci->lock held, releases and aquires lock back */ + static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) + { +- u32 temp_32; ++ struct xhci_segment *new_seg = xhci->cmd_ring->deq_seg; ++ union xhci_trb *new_deq = xhci->cmd_ring->dequeue; ++ u64 crcr; + int ret; + + xhci_dbg(xhci, "Abort command ring\n"); +@@ -375,13 +377,18 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) + + /* + * The control bits like command stop, abort are located in lower +- * dword of the command ring control register. Limit the write +- * to the lower dword to avoid corrupting the command ring pointer +- * in case if the command ring is stopped by the time upper dword +- * is written. ++ * dword of the command ring control register. ++ * Some controllers require all 64 bits to be written to abort the ring. ++ * Make sure the upper dword is valid, pointing to the next command, ++ * avoiding corrupting the command ring pointer in case the command ring ++ * is stopped by the time the upper dword is written. + */ +- temp_32 = readl(&xhci->op_regs->cmd_ring); +- writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); ++ next_trb(xhci, NULL, &new_seg, &new_deq); ++ if (trb_is_link(new_deq)) ++ next_trb(xhci, NULL, &new_seg, &new_deq); ++ ++ crcr = xhci_trb_virt_to_dma(new_seg, new_deq); ++ xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); + + /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the + * completion of the Command Abort operation. If CRR is not negated in 5 +@@ -1518,7 +1525,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) + if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) + /* Delete default control endpoint resources */ + xhci_free_device_endpoint_resources(xhci, virt_dev, true); +- xhci_free_virt_device(xhci, slot_id); + } + + static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, +diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c +index 1bf494b649bd2..c8af2cd2216d6 100644 +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -1400,6 +1400,7 @@ static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra) + + static int tegra_xusb_probe(struct platform_device *pdev) + { ++ struct of_phandle_args args; + struct tegra_xusb *tegra; + struct device_node *np; + struct resource *regs; +@@ -1454,10 +1455,17 @@ static int tegra_xusb_probe(struct platform_device *pdev) + goto put_padctl; + } + +- tegra->padctl_irq = of_irq_get(np, 0); +- if (tegra->padctl_irq <= 0) { +- err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq; +- goto put_padctl; ++ /* Older device-trees don't have padctrl interrupt */ ++ err = of_irq_parse_one(np, 0, &args); ++ if (!err) { ++ tegra->padctl_irq = of_irq_get(np, 0); ++ if (tegra->padctl_irq <= 0) { ++ err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq; ++ goto put_padctl; ++ } ++ } else { ++ dev_dbg(&pdev->dev, ++ "%pOF is missing an interrupt, disabling PM support\n", np); + } + + tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host"); +@@ -1696,11 +1704,15 @@ static int tegra_xusb_probe(struct platform_device *pdev) + goto remove_usb3; + } + +- err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq, NULL, tegra_xusb_padctl_irq, +- IRQF_ONESHOT, dev_name(&pdev->dev), tegra); +- if (err < 0) { +- dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err); +- goto remove_usb3; ++ if (tegra->padctl_irq) { ++ err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq, ++ NULL, tegra_xusb_padctl_irq, ++ IRQF_ONESHOT, dev_name(&pdev->dev), ++ tegra); ++ if (err < 0) { ++ dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err); ++ goto remove_usb3; ++ } + } + + err = tegra_xusb_enable_firmware_messages(tegra); +@@ -1718,13 +1730,16 @@ static int tegra_xusb_probe(struct platform_device *pdev) + /* Enable wake for both USB 2.0 and USB 3.0 roothubs */ + device_init_wakeup(&tegra->hcd->self.root_hub->dev, true); + device_init_wakeup(&xhci->shared_hcd->self.root_hub->dev, true); +- device_init_wakeup(tegra->dev, true); + + pm_runtime_use_autosuspend(tegra->dev); + pm_runtime_set_autosuspend_delay(tegra->dev, 2000); + pm_runtime_mark_last_busy(tegra->dev); + pm_runtime_set_active(tegra->dev); +- pm_runtime_enable(tegra->dev); ++ ++ if (tegra->padctl_irq) { ++ device_init_wakeup(tegra->dev, true); ++ pm_runtime_enable(tegra->dev); ++ } + + return 0; + +@@ -1772,7 +1787,9 @@ static int tegra_xusb_remove(struct platform_device *pdev) + dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt, + tegra->fw.phys); + +- pm_runtime_disable(&pdev->dev); ++ if (tegra->padctl_irq) ++ pm_runtime_disable(&pdev->dev); ++ + pm_runtime_put(&pdev->dev); + + tegra_xusb_powergate_partitions(tegra); +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 541fe4dcc43a2..d7c0bf494d930 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -692,7 +692,6 @@ int xhci_run(struct usb_hcd *hcd) + if (ret) + xhci_free_command(xhci, command); + } +- set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Finished xhci_run for USB2 roothub"); + +@@ -1092,6 +1091,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + int retval = 0; + bool comp_timer_running = false; + bool pending_portevent = false; ++ bool reinit_xhc = false; + + if (!hcd->state) + return 0; +@@ -1108,10 +1108,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + + spin_lock_irq(&xhci->lock); +- if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend) +- hibernated = true; + +- if (!hibernated) { ++ if (hibernated || xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend) ++ reinit_xhc = true; ++ ++ if (!reinit_xhc) { + /* + * Some controllers might lose power during suspend, so wait + * for controller not ready bit to clear, just as in xHC init. +@@ -1144,12 +1145,17 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + spin_unlock_irq(&xhci->lock); + return -ETIMEDOUT; + } +- temp = readl(&xhci->op_regs->status); + } + +- /* If restore operation fails, re-initialize the HC during resume */ +- if ((temp & STS_SRE) || hibernated) { ++ temp = readl(&xhci->op_regs->status); ++ ++ /* re-initialize the HC on Restore Error, or Host Controller Error */ ++ if (temp & (STS_SRE | STS_HCE)) { ++ reinit_xhc = true; ++ xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp); ++ } + ++ if (reinit_xhc) { + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + !(xhci_all_ports_seen_u0(xhci))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); +@@ -1605,9 +1611,12 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag + struct urb_priv *urb_priv; + int num_tds; + +- if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, +- true, true, __func__) <= 0) ++ if (!urb) + return -EINVAL; ++ ret = xhci_check_args(hcd, urb->dev, urb->ep, ++ true, true, __func__); ++ if (ret <= 0) ++ return ret ? ret : -EINVAL; + + slot_id = urb->dev->slot_id; + ep_index = xhci_get_endpoint_index(&urb->ep->desc); +@@ -3324,7 +3333,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, + return -EINVAL; + ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__); + if (ret <= 0) +- return -EINVAL; ++ return ret ? ret : -EINVAL; + if (usb_ss_max_streams(&ep->ss_ep_comp) == 0) { + xhci_warn(xhci, "WARN: SuperSpeed Endpoint Companion" + " descriptor for ep 0x%x does not support streams\n", +@@ -3935,7 +3944,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + struct xhci_slot_ctx *slot_ctx; + int i, ret; + +-#ifndef CONFIG_USB_DEFAULT_PERSIST + /* + * We called pm_runtime_get_noresume when the device was attached. + * Decrement the counter here to allow controller to runtime suspend +@@ -3943,7 +3951,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + */ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + pm_runtime_put_noidle(hcd->self.controller); +-#endif + + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); + /* If the host is halted due to driver unload, we still need to free the +@@ -3962,9 +3969,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) + del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); + } + virt_dev->udev = NULL; +- ret = xhci_disable_slot(xhci, udev->slot_id); +- if (ret) +- xhci_free_virt_device(xhci, udev->slot_id); ++ xhci_disable_slot(xhci, udev->slot_id); ++ xhci_free_virt_device(xhci, udev->slot_id); + } + + int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) +@@ -3974,7 +3980,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) + u32 state; + int ret = 0; + +- command = xhci_alloc_command(xhci, false, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, true, GFP_KERNEL); + if (!command) + return -ENOMEM; + +@@ -3999,6 +4005,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) + } + xhci_ring_cmd_db(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); ++ ++ wait_for_completion(command->completion); ++ ++ if (command->status != COMP_SUCCESS) ++ xhci_warn(xhci, "Unsuccessful disable slot %u command, status %d\n", ++ slot_id, command->status); ++ ++ xhci_free_command(xhci, command); ++ + return ret; + } + +@@ -4095,23 +4110,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) + + xhci_debugfs_create_slot(xhci, slot_id); + +-#ifndef CONFIG_USB_DEFAULT_PERSIST + /* + * If resetting upon resume, we can't put the controller into runtime + * suspend if there is a device attached. + */ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + pm_runtime_get_noresume(hcd->self.controller); +-#endif + + /* Is this a LS or FS device under a HS hub? */ + /* Hub or peripherial? */ + return 1; + + disable_slot: +- ret = xhci_disable_slot(xhci, udev->slot_id); +- if (ret) +- xhci_free_virt_device(xhci, udev->slot_id); ++ xhci_disable_slot(xhci, udev->slot_id); ++ xhci_free_virt_device(xhci, udev->slot_id); + + return 0; + } +@@ -4241,6 +4253,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, + + mutex_unlock(&xhci->mutex); + ret = xhci_disable_slot(xhci, udev->slot_id); ++ xhci_free_virt_device(xhci, udev->slot_id); + if (!ret) + xhci_alloc_dev(hcd, udev); + kfree(command->completion); +diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c +index e5a8fcdbb78e7..6c38c62d29b26 100644 +--- a/drivers/usb/misc/ftdi-elan.c ++++ b/drivers/usb/misc/ftdi-elan.c +@@ -202,6 +202,7 @@ static void ftdi_elan_delete(struct kref *kref) + mutex_unlock(&ftdi_module_lock); + kfree(ftdi->bulk_in_buffer); + ftdi->bulk_in_buffer = NULL; ++ kfree(ftdi); + } + + static void ftdi_elan_put_kref(struct usb_ftdi *ftdi) +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index efbd317f2f252..988a8c02e7e24 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -99,10 +99,6 @@ struct iowarrior { + /* globals */ + /*--------------*/ + +-/* +- * USB spec identifies 5 second timeouts. +- */ +-#define GET_TIMEOUT 5 + #define USB_REQ_GET_REPORT 0x01 + //#if 0 + static int usb_get_report(struct usb_device *dev, +@@ -114,7 +110,7 @@ static int usb_get_report(struct usb_device *dev, + USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, (type << 8) + id, + inter->desc.bInterfaceNumber, buf, size, +- GET_TIMEOUT*HZ); ++ USB_CTRL_GET_TIMEOUT); + } + //#endif + +@@ -129,7 +125,7 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (type << 8) + id, + intf->cur_altsetting->desc.bInterfaceNumber, buf, +- size, HZ); ++ size, 1000); + } + + /*---------------------*/ +diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c +index a9a65b4bbfede..9977600616d7e 100644 +--- a/drivers/usb/mtu3/mtu3_gadget.c ++++ b/drivers/usb/mtu3/mtu3_gadget.c +@@ -77,7 +77,7 @@ static int mtu3_ep_enable(struct mtu3_ep *mep) + if (usb_endpoint_xfer_int(desc) || + usb_endpoint_xfer_isoc(desc)) { + interval = desc->bInterval; +- interval = clamp_val(interval, 1, 16) - 1; ++ interval = clamp_val(interval, 1, 16); + if (usb_endpoint_xfer_isoc(desc) && comp_desc) + mult = comp_desc->bmAttributes; + } +@@ -89,9 +89,16 @@ static int mtu3_ep_enable(struct mtu3_ep *mep) + if (usb_endpoint_xfer_isoc(desc) || + usb_endpoint_xfer_int(desc)) { + interval = desc->bInterval; +- interval = clamp_val(interval, 1, 16) - 1; ++ interval = clamp_val(interval, 1, 16); + mult = usb_endpoint_maxp_mult(desc) - 1; + } ++ break; ++ case USB_SPEED_FULL: ++ if (usb_endpoint_xfer_isoc(desc)) ++ interval = clamp_val(desc->bInterval, 1, 16); ++ else if (usb_endpoint_xfer_int(desc)) ++ interval = clamp_val(desc->bInterval, 1, 255); ++ + break; + default: + break; /*others are ignored */ +@@ -235,6 +242,7 @@ struct usb_request *mtu3_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) + mreq->request.dma = DMA_ADDR_INVALID; + mreq->epnum = mep->epnum; + mreq->mep = mep; ++ INIT_LIST_HEAD(&mreq->list); + trace_mtu3_alloc_request(mreq); + + return &mreq->request; +diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c +index 3f414f91b5899..2ea3157ddb6e2 100644 +--- a/drivers/usb/mtu3/mtu3_qmu.c ++++ b/drivers/usb/mtu3/mtu3_qmu.c +@@ -273,6 +273,8 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) + gpd->dw3_info |= cpu_to_le32(GPD_EXT_FLAG_ZLP); + } + ++ /* prevent reorder, make sure GPD's HWO is set last */ ++ mb(); + gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); + + mreq->gpd = gpd; +@@ -306,6 +308,8 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) + gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); + ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma)); + gpd->dw3_info = cpu_to_le32(ext_addr); ++ /* prevent reorder, make sure GPD's HWO is set last */ ++ mb(); + gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO); + + mreq->gpd = gpd; +@@ -445,7 +449,8 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) + return; + } + mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_TXPKTRDY); +- ++ /* prevent reorder, make sure GPD's HWO is set last */ ++ mb(); + /* by pass the current GDP */ + gpd_current->dw0_info |= cpu_to_le32(GPD_FLAGS_BPS | GPD_FLAGS_HWO); + +diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig +index 8de143807c1ae..4d61df6a9b5c8 100644 +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -120,7 +120,7 @@ config USB_MUSB_MEDIATEK + tristate "MediaTek platforms" + depends on ARCH_MEDIATEK || COMPILE_TEST + depends on NOP_USB_XCEIV +- depends on GENERIC_PHY ++ select GENERIC_PHY + select USB_ROLE_SWITCH + + comment "MUSB DMA mode" +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index 98c0f4c1bffd9..51274b87f46c9 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1247,9 +1247,11 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, + status = musb_queue_resume_work(musb, + musb_ep_restart_resume_work, + request); +- if (status < 0) ++ if (status < 0) { + dev_err(musb->controller, "%s resume work: %i\n", + __func__, status); ++ list_del(&request->list); ++ } + } + + unlock: +diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c +index c968ecda42aa8..7ed4cc348d993 100644 +--- a/drivers/usb/musb/tusb6010.c ++++ b/drivers/usb/musb/tusb6010.c +@@ -1104,6 +1104,11 @@ static int tusb_musb_init(struct musb *musb) + + /* dma address for async dma */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) { ++ pr_debug("no async dma resource?\n"); ++ ret = -ENODEV; ++ goto done; ++ } + musb->async = mem->start; + + /* dma address for sync dma */ +diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c +index 2db917eab7995..b5a1864e9cfdc 100644 +--- a/drivers/usb/serial/ch341.c ++++ b/drivers/usb/serial/ch341.c +@@ -81,10 +81,10 @@ + #define CH341_QUIRK_SIMULATE_BREAK BIT(1) + + static const struct usb_device_id id_table[] = { +- { USB_DEVICE(0x1a86, 0x5512) }, + { USB_DEVICE(0x1a86, 0x5523) }, + { USB_DEVICE(0x1a86, 0x7522) }, + { USB_DEVICE(0x1a86, 0x7523) }, ++ { USB_DEVICE(0x2184, 0x0057) }, + { USB_DEVICE(0x4348, 0x5523) }, + { USB_DEVICE(0x9986, 0x7523) }, + { }, +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 189279869a8b0..08554e1548420 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -51,6 +51,7 @@ static void cp210x_enable_event_mode(struct usb_serial_port *port); + static void cp210x_disable_event_mode(struct usb_serial_port *port); + + static const struct usb_device_id id_table[] = { ++ { USB_DEVICE(0x0404, 0x034C) }, /* NCR Retail IO Box */ + { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ +@@ -68,6 +69,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ + { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */ ++ { USB_DEVICE(0x106F, 0x0003) }, /* CPI / Money Controls Bulk Coin Recycler */ + { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ + { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ + { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ +@@ -1682,6 +1684,8 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) + + /* 2 banks of GPIO - One for the pins taken from each serial port */ + if (intf_num == 0) { ++ priv->gc.ngpio = 2; ++ + if (mode.eci == CP210X_PIN_MODE_MODEM) { + /* mark all GPIOs of this interface as reserved */ + priv->gpio_altfunc = 0xff; +@@ -1692,8 +1696,9 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) + priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & + CP210X_ECI_GPIO_MODE_MASK) >> + CP210X_ECI_GPIO_MODE_OFFSET); +- priv->gc.ngpio = 2; + } else if (intf_num == 1) { ++ priv->gc.ngpio = 3; ++ + if (mode.sci == CP210X_PIN_MODE_MODEM) { + /* mark all GPIOs of this interface as reserved */ + priv->gpio_altfunc = 0xff; +@@ -1704,7 +1709,6 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) + priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & + CP210X_SCI_GPIO_MODE_MASK) >> + CP210X_SCI_GPIO_MODE_OFFSET); +- priv->gc.ngpio = 3; + } else { + return -ENODEV; + } +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 99d19828dae6d..7e852561d55ca 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -969,6 +969,7 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) }, ++ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_159_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) }, +@@ -977,12 +978,14 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) }, ++ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_235_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) }, ++ { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_320_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) }, +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 755858ca20bac..d1a9564697a4b 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -1506,6 +1506,9 @@ + #define BRAINBOXES_VX_023_PID 0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */ + #define BRAINBOXES_VX_034_PID 0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */ + #define BRAINBOXES_US_101_PID 0x1011 /* US-101 1xRS232 */ ++#define BRAINBOXES_US_159_PID 0x1021 /* US-159 1xRS232 */ ++#define BRAINBOXES_US_235_PID 0x1017 /* US-235 1xRS232 */ ++#define BRAINBOXES_US_320_PID 0x1019 /* US-320 1xRS422/485 */ + #define BRAINBOXES_US_324_PID 0x1013 /* US-324 1xRS422/485 1Mbaud */ + #define BRAINBOXES_US_606_1_PID 0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */ + #define BRAINBOXES_US_606_2_PID 0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */ +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index 87b89c99d5177..1cfcd805f2868 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -2890,22 +2890,22 @@ static int keyspan_port_probe(struct usb_serial_port *port) + for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) { + p_priv->in_buffer[i] = kzalloc(IN_BUFLEN, GFP_KERNEL); + if (!p_priv->in_buffer[i]) +- goto err_in_buffer; ++ goto err_free_in_buffer; + } + + for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) { + p_priv->out_buffer[i] = kzalloc(OUT_BUFLEN, GFP_KERNEL); + if (!p_priv->out_buffer[i]) +- goto err_out_buffer; ++ goto err_free_out_buffer; + } + + p_priv->inack_buffer = kzalloc(INACK_BUFLEN, GFP_KERNEL); + if (!p_priv->inack_buffer) +- goto err_inack_buffer; ++ goto err_free_out_buffer; + + p_priv->outcont_buffer = kzalloc(OUTCONT_BUFLEN, GFP_KERNEL); + if (!p_priv->outcont_buffer) +- goto err_outcont_buffer; ++ goto err_free_inack_buffer; + + p_priv->device_details = d_details; + +@@ -2951,15 +2951,14 @@ static int keyspan_port_probe(struct usb_serial_port *port) + + return 0; + +-err_outcont_buffer: ++err_free_inack_buffer: + kfree(p_priv->inack_buffer); +-err_inack_buffer: ++err_free_out_buffer: + for (i = 0; i < ARRAY_SIZE(p_priv->out_buffer); ++i) + kfree(p_priv->out_buffer[i]); +-err_out_buffer: ++err_free_in_buffer: + for (i = 0; i < ARRAY_SIZE(p_priv->in_buffer); ++i) + kfree(p_priv->in_buffer[i]); +-err_in_buffer: + kfree(p_priv); + + return -ENOMEM; +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index a484ff5e4ebf8..e7755d9cfc61a 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -198,6 +198,8 @@ static void option_instat_callback(struct urb *urb); + + #define DELL_PRODUCT_5821E 0x81d7 + #define DELL_PRODUCT_5821E_ESIM 0x81e0 ++#define DELL_PRODUCT_5829E_ESIM 0x81e4 ++#define DELL_PRODUCT_5829E 0x81e6 + + #define KYOCERA_VENDOR_ID 0x0c88 + #define KYOCERA_PRODUCT_KPC650 0x17da +@@ -1063,6 +1065,10 @@ static const struct usb_device_id option_ids[] = { + .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, + { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5821E_ESIM), + .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, ++ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E), ++ .driver_info = RSVD(0) | RSVD(6) }, ++ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E_ESIM), ++ .driver_info = RSVD(0) | RSVD(6) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, +@@ -1219,6 +1225,14 @@ static const struct usb_device_id option_ids[] = { + .driver_info = NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ + .driver_info = NCTRL(0) | RSVD(1) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */ ++ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */ ++ .driver_info = NCTRL(0) | RSVD(1) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */ ++ .driver_info = NCTRL(2) | RSVD(3) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ ++ .driver_info = NCTRL(0) | RSVD(1) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), + .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), +@@ -1265,8 +1279,16 @@ static const struct usb_device_id option_ids[] = { + .driver_info = NCTRL(2) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff), /* Telit LE910-S1 (ECM) */ + .driver_info = NCTRL(2) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x701a, 0xff), /* Telit LE910R1 (RNDIS) */ ++ .driver_info = NCTRL(2) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x701b, 0xff), /* Telit LE910R1 (ECM) */ ++ .driver_info = NCTRL(2) }, + { USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */ + .driver_info = NCTRL(0) | ZLP }, ++ { USB_DEVICE(TELIT_VENDOR_ID, 0x9200), /* Telit LE910S1 flashing device */ ++ .driver_info = NCTRL(0) | ZLP }, ++ { USB_DEVICE(TELIT_VENDOR_ID, 0x9201), /* Telit LE910R1 flashing device */ ++ .driver_info = NCTRL(0) | ZLP }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), + .driver_info = RSVD(1) }, +@@ -1639,6 +1661,8 @@ static const struct usb_device_id option_ids[] = { + .driver_info = RSVD(2) }, + { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) }, /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */ + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0x00, 0x00) }, /* ZTE MF871A */ ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1485, 0xff, 0xff, 0xff), /* ZTE MF286D */ ++ .driver_info = RSVD(5) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) }, +@@ -2094,6 +2118,9 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ ++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ ++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */ ++ .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ + { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ + { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ +diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c +index f45ca7ddf78ea..a70fd86f735ca 100644 +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -432,6 +432,7 @@ static int pl2303_detect_type(struct usb_serial *serial) + case 0x200: + switch (bcdDevice) { + case 0x100: ++ case 0x105: + case 0x305: + case 0x405: + /* +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index c6b3fcf901805..1a05e3dcfec8a 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -406,6 +406,16 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, + "785EPX Storage", + USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_SINGLE_LUN), + ++/* ++ * Reported by James Buren <braewoods+lkml@braewoods.net> ++ * Virtual ISOs cannot be remounted if ejected while the device is locked ++ * Disable locking to mimic Windows behavior that bypasses the issue ++ */ ++UNUSUAL_DEV( 0x04c5, 0x2028, 0x0001, 0x0001, ++ "iODD", ++ "2531/2541", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE), ++ + /* + * Not sure who reported this originally but + * Pavel Machek <pavel@ucw.cz> reported that the extra US_FL_SINGLE_LUN +@@ -2291,6 +2301,16 @@ UNUSUAL_DEV( 0x2027, 0xa001, 0x0000, 0x9999, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, + US_FL_SCM_MULT_TARG ), + ++/* ++ * Reported by DocMAX <mail@vacharakis.de> ++ * and Thomas Weißschuh <linux@weissschuh.net> ++ */ ++UNUSUAL_DEV( 0x2109, 0x0715, 0x9999, 0x9999, ++ "VIA Labs, Inc.", ++ "VL817 SATA Bridge", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_IGNORE_UAS), ++ + UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, + "ST", + "2A", +diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig +index a0418f23b4aae..ab480f38523aa 100644 +--- a/drivers/usb/typec/Kconfig ++++ b/drivers/usb/typec/Kconfig +@@ -65,9 +65,9 @@ config TYPEC_HD3SS3220 + + config TYPEC_STUSB160X + tristate "STMicroelectronics STUSB160x Type-C controller driver" +- depends on I2C +- depends on REGMAP_I2C + depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH ++ depends on I2C ++ select REGMAP_I2C + help + Say Y or M here if your system has STMicroelectronics STUSB160x + Type-C port controller. +diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c +index 7a2a17866a823..72f9001b07921 100644 +--- a/drivers/usb/typec/tcpm/fusb302.c ++++ b/drivers/usb/typec/tcpm/fusb302.c +@@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) + ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, + FUSB_REG_MASK_BC_LVL | + FUSB_REG_MASK_COMP_CHNG, +- FUSB_REG_MASK_COMP_CHNG); ++ FUSB_REG_MASK_BC_LVL); + if (ret < 0) { + fusb302_log(chip, "cannot set SRC interrupt, ret=%d", + ret); + goto done; + } + chip->intr_comp_chng = true; ++ chip->intr_bc_lvl = false; + break; + case TYPEC_CC_RD: + ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, + FUSB_REG_MASK_BC_LVL | + FUSB_REG_MASK_COMP_CHNG, +- FUSB_REG_MASK_BC_LVL); ++ FUSB_REG_MASK_COMP_CHNG); + if (ret < 0) { + fusb302_log(chip, "cannot set SRC interrupt, ret=%d", + ret); + goto done; + } + chip->intr_bc_lvl = true; ++ chip->intr_comp_chng = false; + break; + default: + break; +diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c +index c15eec9cc460a..7d540afdb7cc3 100644 +--- a/drivers/usb/typec/tcpm/tcpci.c ++++ b/drivers/usb/typec/tcpm/tcpci.c +@@ -75,9 +75,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val) + static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) + { + struct tcpci *tcpci = tcpc_to_tcpci(tcpc); ++ bool vconn_pres; ++ enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1; + unsigned int reg; + int ret; + ++ ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, ®); ++ if (ret < 0) ++ return ret; ++ ++ vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES); ++ if (vconn_pres) { ++ ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, ®); ++ if (ret < 0) ++ return ret; ++ ++ if (reg & TCPC_TCPC_CTRL_ORIENTATION) ++ polarity = TYPEC_POLARITY_CC2; ++ } ++ + switch (cc) { + case TYPEC_CC_RA: + reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) | +@@ -112,6 +128,16 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) + break; + } + ++ if (vconn_pres) { ++ if (polarity == TYPEC_POLARITY_CC2) { ++ reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT); ++ reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT); ++ } else { ++ reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT); ++ reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT); ++ } ++ } ++ + ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg); + if (ret < 0) + return ret; +diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h +index 2be7a77d400ef..b2edd45f13c68 100644 +--- a/drivers/usb/typec/tcpm/tcpci.h ++++ b/drivers/usb/typec/tcpm/tcpci.h +@@ -98,6 +98,7 @@ + #define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4) + #define TCPC_POWER_STATUS_VBUS_DET BIT(3) + #define TCPC_POWER_STATUS_VBUS_PRES BIT(2) ++#define TCPC_POWER_STATUS_VCONN_PRES BIT(1) + #define TCPC_POWER_STATUS_SINKING_VBUS BIT(0) + + #define TCPC_FAULT_STATUS 0x1f +diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c +index 7f2f3ff1b3911..5fce795b69c7f 100644 +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -324,6 +324,7 @@ struct tcpm_port { + + bool attached; + bool connected; ++ bool registered; + bool pd_supported; + enum typec_port_type port_type; + +@@ -4110,11 +4111,7 @@ static void run_state_machine(struct tcpm_port *port) + tcpm_try_src(port) ? SRC_TRY + : SNK_ATTACHED, + 0); +- else +- /* Wait for VBUS, but not forever */ +- tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON); + break; +- + case SRC_TRY: + port->try_src_count++; + tcpm_set_cc(port, tcpm_rp_cc(port)); +@@ -5159,7 +5156,8 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) + case SNK_TRYWAIT_DEBOUNCE: + break; + case SNK_ATTACH_WAIT: +- tcpm_set_state(port, SNK_UNATTACHED, 0); ++ case SNK_DEBOUNCED: ++ /* Do nothing, as TCPM is still waiting for vbus to reaach VSAFE5V to connect */ + break; + + case SNK_NEGOTIATE_CAPABILITIES: +@@ -5266,6 +5264,10 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) + case PR_SWAP_SNK_SRC_SOURCE_ON: + /* Do nothing, vsafe0v is expected during transition */ + break; ++ case SNK_ATTACH_WAIT: ++ case SNK_DEBOUNCED: ++ /*Do nothing, still waiting for VSAFE5V for connect */ ++ break; + default: + if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) + tcpm_set_state(port, SNK_UNATTACHED, 0); +@@ -6295,7 +6297,8 @@ static enum hrtimer_restart state_machine_timer_handler(struct hrtimer *timer) + { + struct tcpm_port *port = container_of(timer, struct tcpm_port, state_machine_timer); + +- kthread_queue_work(port->wq, &port->state_machine); ++ if (port->registered) ++ kthread_queue_work(port->wq, &port->state_machine); + return HRTIMER_NORESTART; + } + +@@ -6303,7 +6306,8 @@ static enum hrtimer_restart vdm_state_machine_timer_handler(struct hrtimer *time + { + struct tcpm_port *port = container_of(timer, struct tcpm_port, vdm_state_machine_timer); + +- kthread_queue_work(port->wq, &port->vdm_state_machine); ++ if (port->registered) ++ kthread_queue_work(port->wq, &port->vdm_state_machine); + return HRTIMER_NORESTART; + } + +@@ -6311,7 +6315,8 @@ static enum hrtimer_restart enable_frs_timer_handler(struct hrtimer *timer) + { + struct tcpm_port *port = container_of(timer, struct tcpm_port, enable_frs_timer); + +- kthread_queue_work(port->wq, &port->enable_frs); ++ if (port->registered) ++ kthread_queue_work(port->wq, &port->enable_frs); + return HRTIMER_NORESTART; + } + +@@ -6319,7 +6324,8 @@ static enum hrtimer_restart send_discover_timer_handler(struct hrtimer *timer) + { + struct tcpm_port *port = container_of(timer, struct tcpm_port, send_discover_timer); + +- kthread_queue_work(port->wq, &port->send_discover_work); ++ if (port->registered) ++ kthread_queue_work(port->wq, &port->send_discover_work); + return HRTIMER_NORESTART; + } + +@@ -6407,6 +6413,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) + typec_port_register_altmodes(port->typec_port, + &tcpm_altmode_ops, port, + port->port_altmode, ALTMODE_DISCOVERY_MAX); ++ port->registered = true; + + mutex_lock(&port->lock); + tcpm_init(port); +@@ -6428,6 +6435,9 @@ void tcpm_unregister_port(struct tcpm_port *port) + { + int i; + ++ port->registered = false; ++ kthread_destroy_worker(port->wq); ++ + hrtimer_cancel(&port->send_discover_timer); + hrtimer_cancel(&port->enable_frs_timer); + hrtimer_cancel(&port->vdm_state_machine_timer); +@@ -6439,7 +6449,6 @@ void tcpm_unregister_port(struct tcpm_port *port) + typec_unregister_port(port->typec_port); + usb_role_switch_put(port->role_sw); + tcpm_debugfs_exit(port); +- kthread_destroy_worker(port->wq); + } + EXPORT_SYMBOL_GPL(tcpm_unregister_port); + +diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c +index ea4cc0a6e40cc..d229d2db44ff0 100644 +--- a/drivers/usb/typec/tipd/core.c ++++ b/drivers/usb/typec/tipd/core.c +@@ -117,7 +117,7 @@ tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len) + u8 data[TPS_MAX_LEN + 1]; + int ret; + +- if (WARN_ON(len + 1 > sizeof(data))) ++ if (len + 1 > sizeof(data)) + return -EINVAL; + + if (!tps->i2c_protocol) +@@ -618,12 +618,12 @@ static int tps6598x_probe(struct i2c_client *client) + + ret = tps6598x_read32(tps, TPS_REG_STATUS, &status); + if (ret < 0) +- return ret; ++ goto err_clear_mask; + trace_tps6598x_status(status); + + ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf); + if (ret < 0) +- return ret; ++ goto err_clear_mask; + + /* + * This fwnode has a "compatible" property, but is never populated as a +@@ -712,7 +712,8 @@ err_role_put: + usb_role_switch_put(tps->role_sw); + err_fwnode_put: + fwnode_handle_put(fwnode); +- ++err_clear_mask: ++ tps6598x_write64(tps, TPS_REG_INT_MASK1, 0); + return ret; + } + +diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c +index bff96d64dddff..6db7c8ddd51cd 100644 +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -325,7 +325,7 @@ static int ucsi_ccg_init(struct ucsi_ccg *uc) + if (status < 0) + return status; + +- if (!data) ++ if (!(data & DEV_INT)) + return 0; + + status = ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data)); +diff --git a/drivers/vdpa/ifcvf/ifcvf_base.c b/drivers/vdpa/ifcvf/ifcvf_base.c +index 2808f1ba9f7b8..7d41dfe48adee 100644 +--- a/drivers/vdpa/ifcvf/ifcvf_base.c ++++ b/drivers/vdpa/ifcvf/ifcvf_base.c +@@ -143,8 +143,8 @@ int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *pdev) + IFCVF_DBG(pdev, "hw->isr = %p\n", hw->isr); + break; + case VIRTIO_PCI_CAP_DEVICE_CFG: +- hw->net_cfg = get_cap_addr(hw, &cap); +- IFCVF_DBG(pdev, "hw->net_cfg = %p\n", hw->net_cfg); ++ hw->dev_cfg = get_cap_addr(hw, &cap); ++ IFCVF_DBG(pdev, "hw->dev_cfg = %p\n", hw->dev_cfg); + break; + } + +@@ -153,7 +153,7 @@ next: + } + + if (hw->common_cfg == NULL || hw->notify_base == NULL || +- hw->isr == NULL || hw->net_cfg == NULL) { ++ hw->isr == NULL || hw->dev_cfg == NULL) { + IFCVF_ERR(pdev, "Incomplete PCI capabilities\n"); + return -EIO; + } +@@ -174,7 +174,7 @@ next: + IFCVF_DBG(pdev, + "PCI capability mapping: common cfg: %p, notify base: %p\n, isr cfg: %p, device cfg: %p, multiplier: %u\n", + hw->common_cfg, hw->notify_base, hw->isr, +- hw->net_cfg, hw->notify_off_multiplier); ++ hw->dev_cfg, hw->notify_off_multiplier); + + return 0; + } +@@ -242,33 +242,54 @@ int ifcvf_verify_min_features(struct ifcvf_hw *hw, u64 features) + return 0; + } + +-void ifcvf_read_net_config(struct ifcvf_hw *hw, u64 offset, ++u32 ifcvf_get_config_size(struct ifcvf_hw *hw) ++{ ++ struct ifcvf_adapter *adapter; ++ u32 config_size; ++ ++ adapter = vf_to_adapter(hw); ++ switch (hw->dev_type) { ++ case VIRTIO_ID_NET: ++ config_size = sizeof(struct virtio_net_config); ++ break; ++ case VIRTIO_ID_BLOCK: ++ config_size = sizeof(struct virtio_blk_config); ++ break; ++ default: ++ config_size = 0; ++ IFCVF_ERR(adapter->pdev, "VIRTIO ID %u not supported\n", hw->dev_type); ++ } ++ ++ return config_size; ++} ++ ++void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset, + void *dst, int length) + { + u8 old_gen, new_gen, *p; + int i; + +- WARN_ON(offset + length > sizeof(struct virtio_net_config)); ++ WARN_ON(offset + length > hw->config_size); + do { + old_gen = ifc_ioread8(&hw->common_cfg->config_generation); + p = dst; + for (i = 0; i < length; i++) +- *p++ = ifc_ioread8(hw->net_cfg + offset + i); ++ *p++ = ifc_ioread8(hw->dev_cfg + offset + i); + + new_gen = ifc_ioread8(&hw->common_cfg->config_generation); + } while (old_gen != new_gen); + } + +-void ifcvf_write_net_config(struct ifcvf_hw *hw, u64 offset, ++void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset, + const void *src, int length) + { + const u8 *p; + int i; + + p = src; +- WARN_ON(offset + length > sizeof(struct virtio_net_config)); ++ WARN_ON(offset + length > hw->config_size); + for (i = 0; i < length; i++) +- ifc_iowrite8(*p++, hw->net_cfg + offset + i); ++ ifc_iowrite8(*p++, hw->dev_cfg + offset + i); + } + + static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features) +diff --git a/drivers/vdpa/ifcvf/ifcvf_base.h b/drivers/vdpa/ifcvf/ifcvf_base.h +index 09918af3ecf82..c486873f370a8 100644 +--- a/drivers/vdpa/ifcvf/ifcvf_base.h ++++ b/drivers/vdpa/ifcvf/ifcvf_base.h +@@ -71,12 +71,14 @@ struct ifcvf_hw { + u64 hw_features; + u32 dev_type; + struct virtio_pci_common_cfg __iomem *common_cfg; +- void __iomem *net_cfg; ++ void __iomem *dev_cfg; + struct vring_info vring[IFCVF_MAX_QUEUES]; + void __iomem * const *base; + char config_msix_name[256]; + struct vdpa_callback config_cb; + unsigned int config_irq; ++ /* virtio-net or virtio-blk device config size */ ++ u32 config_size; + }; + + struct ifcvf_adapter { +@@ -105,9 +107,9 @@ int ifcvf_init_hw(struct ifcvf_hw *hw, struct pci_dev *dev); + int ifcvf_start_hw(struct ifcvf_hw *hw); + void ifcvf_stop_hw(struct ifcvf_hw *hw); + void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid); +-void ifcvf_read_net_config(struct ifcvf_hw *hw, u64 offset, ++void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset, + void *dst, int length); +-void ifcvf_write_net_config(struct ifcvf_hw *hw, u64 offset, ++void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset, + const void *src, int length); + u8 ifcvf_get_status(struct ifcvf_hw *hw); + void ifcvf_set_status(struct ifcvf_hw *hw, u8 status); +@@ -120,4 +122,5 @@ u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid); + int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num); + struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw); + int ifcvf_probed_virtio_net(struct ifcvf_hw *hw); ++u32 ifcvf_get_config_size(struct ifcvf_hw *hw); + #endif /* _IFCVF_H_ */ +diff --git a/drivers/vdpa/ifcvf/ifcvf_main.c b/drivers/vdpa/ifcvf/ifcvf_main.c +index dcd648e1f7e7e..003530b19b4ee 100644 +--- a/drivers/vdpa/ifcvf/ifcvf_main.c ++++ b/drivers/vdpa/ifcvf/ifcvf_main.c +@@ -366,24 +366,9 @@ static u32 ifcvf_vdpa_get_vq_align(struct vdpa_device *vdpa_dev) + + static size_t ifcvf_vdpa_get_config_size(struct vdpa_device *vdpa_dev) + { +- struct ifcvf_adapter *adapter = vdpa_to_adapter(vdpa_dev); + struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); +- struct pci_dev *pdev = adapter->pdev; +- size_t size; +- +- switch (vf->dev_type) { +- case VIRTIO_ID_NET: +- size = sizeof(struct virtio_net_config); +- break; +- case VIRTIO_ID_BLOCK: +- size = sizeof(struct virtio_blk_config); +- break; +- default: +- size = 0; +- IFCVF_ERR(pdev, "VIRTIO ID %u not supported\n", vf->dev_type); +- } + +- return size; ++ return vf->config_size; + } + + static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev, +@@ -392,8 +377,7 @@ static void ifcvf_vdpa_get_config(struct vdpa_device *vdpa_dev, + { + struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); + +- WARN_ON(offset + len > sizeof(struct virtio_net_config)); +- ifcvf_read_net_config(vf, offset, buf, len); ++ ifcvf_read_dev_config(vf, offset, buf, len); + } + + static void ifcvf_vdpa_set_config(struct vdpa_device *vdpa_dev, +@@ -402,8 +386,7 @@ static void ifcvf_vdpa_set_config(struct vdpa_device *vdpa_dev, + { + struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); + +- WARN_ON(offset + len > sizeof(struct virtio_net_config)); +- ifcvf_write_net_config(vf, offset, buf, len); ++ ifcvf_write_dev_config(vf, offset, buf, len); + } + + static void ifcvf_vdpa_set_config_cb(struct vdpa_device *vdpa_dev, +@@ -541,6 +524,7 @@ static int ifcvf_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name) + vf->vring[i].irq = -EINVAL; + + vf->hw_features = ifcvf_get_hw_features(vf); ++ vf->config_size = ifcvf_get_config_size(vf); + + adapter->vdpa.mdev = &ifcvf_mgmt_dev->mdev; + ret = _vdpa_register_device(&adapter->vdpa, vf->nr_vring); +diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c +index bd56de7484dcb..1afbda216df52 100644 +--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c ++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c +@@ -873,8 +873,6 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque + MLX5_SET(virtio_q, vq_ctx, umem_3_id, mvq->umem3.id); + MLX5_SET(virtio_q, vq_ctx, umem_3_size, mvq->umem3.size); + MLX5_SET(virtio_q, vq_ctx, pd, ndev->mvdev.res.pdn); +- if (MLX5_CAP_DEV_VDPA_EMULATION(ndev->mvdev.mdev, eth_frame_offload_type)) +- MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, 1); + + err = mlx5_cmd_exec(ndev->mvdev.mdev, in, inlen, out, sizeof(out)); + if (err) +@@ -1512,9 +1510,11 @@ static int change_num_qps(struct mlx5_vdpa_dev *mvdev, int newqps) + return 0; + + clean_added: +- for (--i; i >= cur_qps; --i) ++ for (--i; i >= 2 * cur_qps; --i) + teardown_vq(ndev, &ndev->vqs[i]); + ++ ndev->cur_num_vqs = 2 * cur_qps; ++ + return err; + } + +@@ -2192,7 +2192,6 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev) + clear_vqs_ready(ndev); + mlx5_vdpa_destroy_mr(&ndev->mvdev); + ndev->mvdev.status = 0; +- ndev->mvdev.mlx_features = 0; + memset(ndev->event_cbs, 0, sizeof(ndev->event_cbs)); + ndev->mvdev.actual_features = 0; + ++mvdev->generation; +diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c +index 1dc121a07a934..12bf3d16a40ff 100644 +--- a/drivers/vdpa/vdpa.c ++++ b/drivers/vdpa/vdpa.c +@@ -353,7 +353,8 @@ static int vdpa_mgmtdev_fill(const struct vdpa_mgmt_dev *mdev, struct sk_buff *m + goto msg_err; + + while (mdev->id_table[i].device) { +- supported_classes |= BIT(mdev->id_table[i].device); ++ if (mdev->id_table[i].device <= 63) ++ supported_classes |= BIT_ULL(mdev->id_table[i].device); + i++; + } + +diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c +index 5f484fff8dbec..41b0cd17fcbac 100644 +--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c ++++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c +@@ -591,8 +591,11 @@ static void vdpasim_free(struct vdpa_device *vdpa) + vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov); + } + +- put_iova_domain(&vdpasim->iova); +- iova_cache_put(); ++ if (vdpa_get_dma_dev(vdpa)) { ++ put_iova_domain(&vdpasim->iova); ++ iova_cache_put(); ++ } ++ + kvfree(vdpasim->buffer); + if (vdpasim->iommu) + vhost_iotlb_free(vdpasim->iommu); +diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c +index 841667a896dd0..8c3de5a76282a 100644 +--- a/drivers/vdpa/vdpa_user/vduse_dev.c ++++ b/drivers/vdpa/vdpa_user/vduse_dev.c +@@ -655,7 +655,8 @@ static void vduse_vdpa_get_config(struct vdpa_device *vdpa, unsigned int offset, + { + struct vduse_dev *dev = vdpa_to_vduse(vdpa); + +- if (len > dev->config_size - offset) ++ if (offset > dev->config_size || ++ len > dev->config_size - offset) + return; + + memcpy(buf, dev->config + offset, len); +@@ -975,7 +976,8 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, + break; + + ret = -EINVAL; +- if (config.length == 0 || ++ if (config.offset > dev->config_size || ++ config.length == 0 || + config.length > dev->config_size - config.offset) + break; + +diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c +index 39039e0461175..d62f05d056b7b 100644 +--- a/drivers/vhost/vdpa.c ++++ b/drivers/vhost/vdpa.c +@@ -197,7 +197,7 @@ static int vhost_vdpa_config_validate(struct vhost_vdpa *v, + struct vdpa_device *vdpa = v->vdpa; + long size = vdpa->config->get_config_size(vdpa); + +- if (c->len == 0) ++ if (c->len == 0 || c->off > size) + return -EINVAL; + + if (c->len > size - c->off) +diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c +index 938aefbc75ecc..d07a20bbc07b7 100644 +--- a/drivers/vhost/vsock.c ++++ b/drivers/vhost/vsock.c +@@ -554,7 +554,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) + virtio_transport_free_pkt(pkt); + + len += sizeof(pkt->hdr); +- vhost_add_used(vq, head, len); ++ vhost_add_used(vq, head, 0); + total_len += len; + added = true; + } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); +@@ -633,16 +633,18 @@ err: + return ret; + } + +-static int vhost_vsock_stop(struct vhost_vsock *vsock) ++static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner) + { + size_t i; +- int ret; ++ int ret = 0; + + mutex_lock(&vsock->dev.mutex); + +- ret = vhost_dev_check_owner(&vsock->dev); +- if (ret) +- goto err; ++ if (check_owner) { ++ ret = vhost_dev_check_owner(&vsock->dev); ++ if (ret) ++ goto err; ++ } + + for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) { + struct vhost_virtqueue *vq = &vsock->vqs[i]; +@@ -757,7 +759,12 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file) + * inefficient. Room for improvement here. */ + vsock_for_each_connected_socket(vhost_vsock_reset_orphans); + +- vhost_vsock_stop(vsock); ++ /* Don't check the owner, because we are in the release path, so we ++ * need to stop the vsock device in any case. ++ * vhost_vsock_stop() can not fail in this case, so we don't need to ++ * check the return code. ++ */ ++ vhost_vsock_stop(vsock, false); + vhost_vsock_flush(vsock); + vhost_dev_stop(&vsock->dev); + +@@ -872,7 +879,7 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl, + if (start) + return vhost_vsock_start(vsock); + else +- return vhost_vsock_stop(vsock); ++ return vhost_vsock_stop(vsock, true); + case VHOST_GET_FEATURES: + features = VHOST_VSOCK_FEATURES; + if (copy_to_user(argp, &features, sizeof(features))) +diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c +index 537fe1b376ad7..fc990e576340b 100644 +--- a/drivers/video/backlight/backlight.c ++++ b/drivers/video/backlight/backlight.c +@@ -688,12 +688,6 @@ static struct backlight_device *of_find_backlight(struct device *dev) + of_node_put(np); + if (!bd) + return ERR_PTR(-EPROBE_DEFER); +- /* +- * Note: gpio_backlight uses brightness as +- * power state during probe +- */ +- if (!bd->props.brightness) +- bd->props.brightness = bd->props.max_brightness; + } + } + +diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c +index d094299c2a485..f12c76d6e61de 100644 +--- a/drivers/video/backlight/qcom-wled.c ++++ b/drivers/video/backlight/qcom-wled.c +@@ -231,14 +231,14 @@ struct wled { + static int wled3_set_brightness(struct wled *wled, u16 brightness) + { + int rc, i; +- u8 v[2]; ++ __le16 v; + +- v[0] = brightness & 0xff; +- v[1] = (brightness >> 8) & 0xf; ++ v = cpu_to_le16(brightness & WLED3_SINK_REG_BRIGHT_MAX); + + for (i = 0; i < wled->cfg.num_strings; ++i) { + rc = regmap_bulk_write(wled->regmap, wled->ctrl_addr + +- WLED3_SINK_REG_BRIGHT(i), v, 2); ++ WLED3_SINK_REG_BRIGHT(wled->cfg.enabled_strings[i]), ++ &v, sizeof(v)); + if (rc < 0) + return rc; + } +@@ -250,18 +250,18 @@ static int wled4_set_brightness(struct wled *wled, u16 brightness) + { + int rc, i; + u16 low_limit = wled->max_brightness * 4 / 1000; +- u8 v[2]; ++ __le16 v; + + /* WLED4's lower limit of operation is 0.4% */ + if (brightness > 0 && brightness < low_limit) + brightness = low_limit; + +- v[0] = brightness & 0xff; +- v[1] = (brightness >> 8) & 0xf; ++ v = cpu_to_le16(brightness & WLED3_SINK_REG_BRIGHT_MAX); + + for (i = 0; i < wled->cfg.num_strings; ++i) { + rc = regmap_bulk_write(wled->regmap, wled->sink_addr + +- WLED4_SINK_REG_BRIGHT(i), v, 2); ++ WLED4_SINK_REG_BRIGHT(wled->cfg.enabled_strings[i]), ++ &v, sizeof(v)); + if (rc < 0) + return rc; + } +@@ -273,21 +273,20 @@ static int wled5_set_brightness(struct wled *wled, u16 brightness) + { + int rc, offset; + u16 low_limit = wled->max_brightness * 1 / 1000; +- u8 v[2]; ++ __le16 v; + + /* WLED5's lower limit is 0.1% */ + if (brightness < low_limit) + brightness = low_limit; + +- v[0] = brightness & 0xff; +- v[1] = (brightness >> 8) & 0x7f; ++ v = cpu_to_le16(brightness & WLED5_SINK_REG_BRIGHT_MAX_15B); + + offset = (wled->cfg.mod_sel == MOD_A) ? + WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB : + WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB; + + rc = regmap_bulk_write(wled->regmap, wled->sink_addr + offset, +- v, 2); ++ &v, sizeof(v)); + return rc; + } + +@@ -572,7 +571,7 @@ unlock_mutex: + + static void wled_auto_string_detection(struct wled *wled) + { +- int rc = 0, i, delay_time_us; ++ int rc = 0, i, j, delay_time_us; + u32 sink_config = 0; + u8 sink_test = 0, sink_valid = 0, val; + bool fault_set; +@@ -619,14 +618,15 @@ static void wled_auto_string_detection(struct wled *wled) + + /* Iterate through the strings one by one */ + for (i = 0; i < wled->cfg.num_strings; i++) { +- sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + i)); ++ j = wled->cfg.enabled_strings[i]; ++ sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + j)); + + /* Enable feedback control */ + rc = regmap_write(wled->regmap, wled->ctrl_addr + +- WLED3_CTRL_REG_FEEDBACK_CONTROL, i + 1); ++ WLED3_CTRL_REG_FEEDBACK_CONTROL, j + 1); + if (rc < 0) { + dev_err(wled->dev, "Failed to enable feedback for SINK %d rc = %d\n", +- i + 1, rc); ++ j + 1, rc); + goto failed_detect; + } + +@@ -635,7 +635,7 @@ static void wled_auto_string_detection(struct wled *wled) + WLED4_SINK_REG_CURR_SINK, sink_test); + if (rc < 0) { + dev_err(wled->dev, "Failed to configure SINK %d rc=%d\n", +- i + 1, rc); ++ j + 1, rc); + goto failed_detect; + } + +@@ -662,7 +662,7 @@ static void wled_auto_string_detection(struct wled *wled) + + if (fault_set) + dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n", +- i + 1); ++ j + 1); + else + sink_valid |= sink_test; + +@@ -702,15 +702,16 @@ static void wled_auto_string_detection(struct wled *wled) + /* Enable valid sinks */ + if (wled->version == 4) { + for (i = 0; i < wled->cfg.num_strings; i++) { ++ j = wled->cfg.enabled_strings[i]; + if (sink_config & +- BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i)) ++ BIT(WLED4_SINK_REG_CURR_SINK_SHFT + j)) + val = WLED4_SINK_REG_STR_MOD_MASK; + else + /* Disable modulator_en for unused sink */ + val = 0; + + rc = regmap_write(wled->regmap, wled->sink_addr + +- WLED4_SINK_REG_STR_MOD_EN(i), val); ++ WLED4_SINK_REG_STR_MOD_EN(j), val); + if (rc < 0) { + dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n", + rc); +@@ -1256,21 +1257,6 @@ static const struct wled_var_cfg wled5_ovp_cfg = { + .size = 16, + }; + +-static u32 wled3_num_strings_values_fn(u32 idx) +-{ +- return idx + 1; +-} +- +-static const struct wled_var_cfg wled3_num_strings_cfg = { +- .fn = wled3_num_strings_values_fn, +- .size = 3, +-}; +- +-static const struct wled_var_cfg wled4_num_strings_cfg = { +- .fn = wled3_num_strings_values_fn, +- .size = 4, +-}; +- + static u32 wled3_switch_freq_values_fn(u32 idx) + { + return 19200 / (2 * (1 + idx)); +@@ -1344,11 +1330,6 @@ static int wled_configure(struct wled *wled) + .val_ptr = &cfg->switch_freq, + .cfg = &wled3_switch_freq_cfg, + }, +- { +- .name = "qcom,num-strings", +- .val_ptr = &cfg->num_strings, +- .cfg = &wled3_num_strings_cfg, +- }, + }; + + const struct wled_u32_opts wled4_opts[] = { +@@ -1372,11 +1353,6 @@ static int wled_configure(struct wled *wled) + .val_ptr = &cfg->switch_freq, + .cfg = &wled3_switch_freq_cfg, + }, +- { +- .name = "qcom,num-strings", +- .val_ptr = &cfg->num_strings, +- .cfg = &wled4_num_strings_cfg, +- }, + }; + + const struct wled_u32_opts wled5_opts[] = { +@@ -1400,11 +1376,6 @@ static int wled_configure(struct wled *wled) + .val_ptr = &cfg->switch_freq, + .cfg = &wled3_switch_freq_cfg, + }, +- { +- .name = "qcom,num-strings", +- .val_ptr = &cfg->num_strings, +- .cfg = &wled4_num_strings_cfg, +- }, + { + .name = "qcom,modulator-sel", + .val_ptr = &cfg->mod_sel, +@@ -1523,16 +1494,57 @@ static int wled_configure(struct wled *wled) + *bool_opts[i].val_ptr = true; + } + +- cfg->num_strings = cfg->num_strings + 1; +- + string_len = of_property_count_elems_of_size(dev->of_node, + "qcom,enabled-strings", + sizeof(u32)); +- if (string_len > 0) +- of_property_read_u32_array(dev->of_node, ++ if (string_len > 0) { ++ if (string_len > wled->max_string_count) { ++ dev_err(dev, "Cannot have more than %d strings\n", ++ wled->max_string_count); ++ return -EINVAL; ++ } ++ ++ rc = of_property_read_u32_array(dev->of_node, + "qcom,enabled-strings", + wled->cfg.enabled_strings, +- sizeof(u32)); ++ string_len); ++ if (rc) { ++ dev_err(dev, "Failed to read %d elements from qcom,enabled-strings: %d\n", ++ string_len, rc); ++ return rc; ++ } ++ ++ for (i = 0; i < string_len; ++i) { ++ if (wled->cfg.enabled_strings[i] >= wled->max_string_count) { ++ dev_err(dev, ++ "qcom,enabled-strings index %d at %d is out of bounds\n", ++ wled->cfg.enabled_strings[i], i); ++ return -EINVAL; ++ } ++ } ++ ++ cfg->num_strings = string_len; ++ } ++ ++ rc = of_property_read_u32(dev->of_node, "qcom,num-strings", &val); ++ if (!rc) { ++ if (val < 1 || val > wled->max_string_count) { ++ dev_err(dev, "qcom,num-strings must be between 1 and %d\n", ++ wled->max_string_count); ++ return -EINVAL; ++ } ++ ++ if (string_len > 0) { ++ dev_warn(dev, "Only one of qcom,num-strings or qcom,enabled-strings" ++ " should be set\n"); ++ if (val > string_len) { ++ dev_err(dev, "qcom,num-strings exceeds qcom,enabled-strings\n"); ++ return -EINVAL; ++ } ++ } ++ ++ cfg->num_strings = val; ++ } + + return 0; + } +diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig +index 840d9813b0bc6..fcc46380e7c91 100644 +--- a/drivers/video/console/Kconfig ++++ b/drivers/video/console/Kconfig +@@ -78,6 +78,26 @@ config FRAMEBUFFER_CONSOLE + help + Low-level framebuffer-based console driver. + ++config FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION ++ bool "Enable legacy fbcon hardware acceleration code" ++ depends on FRAMEBUFFER_CONSOLE ++ default y if PARISC ++ default n ++ help ++ This option enables the fbcon (framebuffer text-based) hardware ++ acceleration for graphics drivers which were written for the fbdev ++ graphics interface. ++ ++ On modern machines, on mainstream machines (like x86-64) or when ++ using a modern Linux distribution those fbdev drivers usually aren't used. ++ So enabling this option wouldn't have any effect, which is why you want ++ to disable this option on such newer machines. ++ ++ If you compile this kernel for older machines which still require the ++ fbdev drivers, you may want to say Y. ++ ++ If unsure, select n. ++ + config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY + bool "Map the console to the primary display device" + depends on FRAMEBUFFER_CONSOLE +diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c +index 1b451165311c9..40496e9e9b438 100644 +--- a/drivers/video/console/sticon.c ++++ b/drivers/video/console/sticon.c +@@ -332,13 +332,13 @@ static u8 sticon_build_attr(struct vc_data *conp, u8 color, + bool blink, bool underline, bool reverse, + bool italic) + { +- u8 attr = ((color & 0x70) >> 1) | ((color & 7)); ++ u8 fg = color & 7; ++ u8 bg = (color & 0x70) >> 4; + +- if (reverse) { +- color = ((color >> 3) & 0x7) | ((color & 0x7) << 3); +- } +- +- return attr; ++ if (reverse) ++ return (fg << 3) | bg; ++ else ++ return (bg << 3) | fg; + } + + static void sticon_invert_region(struct vc_data *conp, u16 *p, int count) +diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c +index ef9c57ce09066..9a49ea6b5112f 100644 +--- a/drivers/video/console/vgacon.c ++++ b/drivers/video/console/vgacon.c +@@ -366,11 +366,17 @@ static void vgacon_init(struct vc_data *c, int init) + struct uni_pagedir *p; + + /* +- * We cannot be loaded as a module, therefore init is always 1, +- * but vgacon_init can be called more than once, and init will +- * not be 1. ++ * We cannot be loaded as a module, therefore init will be 1 ++ * if we are the default console, however if we are a fallback ++ * console, for example if fbcon has failed registration, then ++ * init will be 0, so we need to make sure our boot parameters ++ * have been copied to the console structure for vgacon_resize ++ * ultimately called by vc_resize. Any subsequent calls to ++ * vgacon_init init will have init set to 0 too. + */ + c->vc_can_do_color = vga_can_do_color; ++ c->vc_scan_lines = vga_scan_lines; ++ c->vc_font.height = c->vc_cell_height = vga_video_font_height; + + /* set dimensions manually if init != 0 since vc_resize() will fail */ + if (init) { +@@ -379,8 +385,6 @@ static void vgacon_init(struct vc_data *c, int init) + } else + vc_resize(c, vga_video_num_columns, vga_video_num_lines); + +- c->vc_scan_lines = vga_scan_lines; +- c->vc_font.height = c->vc_cell_height = vga_video_font_height; + c->vc_complement_mask = 0x7700; + if (vga_512_chars) + c->vc_hi_font_mask = 0x0800; +diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c +index 998067b701fa0..393894af26f84 100644 +--- a/drivers/video/fbdev/chipsfb.c ++++ b/drivers/video/fbdev/chipsfb.c +@@ -331,7 +331,7 @@ static const struct fb_var_screeninfo chipsfb_var = { + + static void init_chips(struct fb_info *p, unsigned long addr) + { +- memset(p->screen_base, 0, 0x100000); ++ fb_memset(p->screen_base, 0, 0x100000); + + p->fix = chipsfb_fix; + p->fix.smem_start = addr; +diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c +index 22bb3892f6bd1..a53c1f6906f09 100644 +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -1135,13 +1135,13 @@ static void fbcon_init(struct vc_data *vc, int init) + + ops->graphics = 0; + +- /* +- * No more hw acceleration for fbcon. +- * +- * FIXME: Garbage collect all the now dead code after sufficient time +- * has passed. +- */ +- p->scrollmode = SCROLL_REDRAW; ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION ++ if ((info->flags & FBINFO_HWACCEL_COPYAREA) && ++ !(info->flags & FBINFO_HWACCEL_DISABLED)) ++ p->scrollmode = SCROLL_MOVE; ++ else /* default to something safe */ ++ p->scrollmode = SCROLL_REDRAW; ++#endif + + /* + * ++guenther: console.c:vc_allocate() relies on initializing +@@ -1706,7 +1706,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + count = vc->vc_rows; + if (logo_shown >= 0) + goto redraw_up; +- switch (p->scrollmode) { ++ switch (fb_scrollmode(p)) { + case SCROLL_MOVE: + fbcon_redraw_blit(vc, info, p, t, b - t - count, + count); +@@ -1796,7 +1796,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + count = vc->vc_rows; + if (logo_shown >= 0) + goto redraw_down; +- switch (p->scrollmode) { ++ switch (fb_scrollmode(p)) { + case SCROLL_MOVE: + fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, + -count); +@@ -1947,6 +1947,48 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, + height, width); + } + ++static void updatescrollmode_accel(struct fbcon_display *p, ++ struct fb_info *info, ++ struct vc_data *vc) ++{ ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION ++ struct fbcon_ops *ops = info->fbcon_par; ++ int cap = info->flags; ++ u16 t = 0; ++ int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, ++ info->fix.xpanstep); ++ int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); ++ int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); ++ int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, ++ info->var.xres_virtual); ++ int good_pan = (cap & FBINFO_HWACCEL_YPAN) && ++ divides(ypan, vc->vc_font.height) && vyres > yres; ++ int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && ++ divides(ywrap, vc->vc_font.height) && ++ divides(vc->vc_font.height, vyres) && ++ divides(vc->vc_font.height, yres); ++ int reading_fast = cap & FBINFO_READS_FAST; ++ int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && ++ !(cap & FBINFO_HWACCEL_DISABLED); ++ int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && ++ !(cap & FBINFO_HWACCEL_DISABLED); ++ ++ if (good_wrap || good_pan) { ++ if (reading_fast || fast_copyarea) ++ p->scrollmode = good_wrap ? ++ SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; ++ else ++ p->scrollmode = good_wrap ? SCROLL_REDRAW : ++ SCROLL_PAN_REDRAW; ++ } else { ++ if (reading_fast || (fast_copyarea && !fast_imageblit)) ++ p->scrollmode = SCROLL_MOVE; ++ else ++ p->scrollmode = SCROLL_REDRAW; ++ } ++#endif ++} ++ + static void updatescrollmode(struct fbcon_display *p, + struct fb_info *info, + struct vc_data *vc) +@@ -1962,6 +2004,9 @@ static void updatescrollmode(struct fbcon_display *p, + p->vrows -= (yres - (fh * vc->vc_rows)) / fh; + if ((yres % fh) && (vyres % fh < yres % fh)) + p->vrows--; ++ ++ /* update scrollmode in case hardware acceleration is used */ ++ updatescrollmode_accel(p, info, vc); + } + + #define PITCH(w) (((w) + 7) >> 3) +@@ -2119,7 +2164,7 @@ static int fbcon_switch(struct vc_data *vc) + + updatescrollmode(p, info, vc); + +- switch (p->scrollmode) { ++ switch (fb_scrollmode(p)) { + case SCROLL_WRAP_MOVE: + scrollback_phys_max = p->vrows - vc->vc_rows; + break; +diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h +index 9315b360c8981..0f16cbc99e6a4 100644 +--- a/drivers/video/fbdev/core/fbcon.h ++++ b/drivers/video/fbdev/core/fbcon.h +@@ -29,7 +29,9 @@ struct fbcon_display { + /* Filled in by the low-level console driver */ + const u_char *fontdata; + int userfont; /* != 0 if fontdata kmalloc()ed */ +- u_short scrollmode; /* Scroll Method */ ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION ++ u_short scrollmode; /* Scroll Method, use fb_scrollmode() */ ++#endif + u_short inverse; /* != 0 text black on white as default */ + short yscroll; /* Hardware scrolling */ + int vrows; /* number of virtual rows */ +@@ -208,6 +210,17 @@ static inline int attr_col_ec(int shift, struct vc_data *vc, + #define SCROLL_REDRAW 0x004 + #define SCROLL_PAN_REDRAW 0x005 + ++static inline u_short fb_scrollmode(struct fbcon_display *fb) ++{ ++#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION ++ return fb->scrollmode; ++#else ++ /* hardcoded to SCROLL_REDRAW if acceleration was disabled. */ ++ return SCROLL_REDRAW; ++#endif ++} ++ ++ + #ifdef CONFIG_FB_TILEBLITTING + extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); + #endif +diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c +index 9cd2c4b05c328..2789ace796342 100644 +--- a/drivers/video/fbdev/core/fbcon_ccw.c ++++ b/drivers/video/fbdev/core/fbcon_ccw.c +@@ -65,7 +65,7 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_copyarea area; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); + + area.sx = sy * vc->vc_font.height; + area.sy = vyres - ((sx + width) * vc->vc_font.width); +@@ -83,7 +83,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); + + region.color = attr_bgcol_ec(bgshift,vc,info); + region.dx = sy * vc->vc_font.height; +@@ -140,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, + u32 cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); + + if (!ops->fontbuffer) + return; +@@ -229,7 +229,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; + int err = 1, dx, dy; + char *src; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); + + if (!ops->fontbuffer) + return; +@@ -387,7 +387,7 @@ static int ccw_update_start(struct fb_info *info) + { + struct fbcon_ops *ops = info->fbcon_par; + u32 yoffset; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); + int err; + + yoffset = (vyres - info->var.yres) - ops->var.xoffset; +diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c +index 88d89fad3f05e..86a254c1b2b7b 100644 +--- a/drivers/video/fbdev/core/fbcon_cw.c ++++ b/drivers/video/fbdev/core/fbcon_cw.c +@@ -50,7 +50,7 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_copyarea area; +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vxres = GETVXRES(ops->p, info); + + area.sx = vxres - ((sy + height) * vc->vc_font.height); + area.sy = sx * vc->vc_font.width; +@@ -68,7 +68,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vxres = GETVXRES(ops->p, info); + + region.color = attr_bgcol_ec(bgshift,vc,info); + region.dx = vxres - ((sy + height) * vc->vc_font.height); +@@ -125,7 +125,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, + u32 cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vxres = GETVXRES(ops->p, info); + + if (!ops->fontbuffer) + return; +@@ -212,7 +212,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; + int err = 1, dx, dy; + char *src; +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vxres = GETVXRES(ops->p, info); + + if (!ops->fontbuffer) + return; +@@ -369,7 +369,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, + static int cw_update_start(struct fb_info *info) + { + struct fbcon_ops *ops = info->fbcon_par; +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vxres = GETVXRES(ops->p, info); + u32 xoffset; + int err; + +diff --git a/drivers/video/fbdev/core/fbcon_rotate.h b/drivers/video/fbdev/core/fbcon_rotate.h +index e233444cda664..01cbe303b8a29 100644 +--- a/drivers/video/fbdev/core/fbcon_rotate.h ++++ b/drivers/video/fbdev/core/fbcon_rotate.h +@@ -12,11 +12,11 @@ + #define _FBCON_ROTATE_H + + #define GETVYRES(s,i) ({ \ +- (s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \ ++ (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE) ? \ + (i)->var.yres : (i)->var.yres_virtual; }) + + #define GETVXRES(s,i) ({ \ +- (s == SCROLL_REDRAW || s == SCROLL_MOVE || !(i)->fix.xpanstep) ? \ ++ (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \ + (i)->var.xres : (i)->var.xres_virtual; }) + + +diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c +index 8d5e66b1bdfbb..23bc045769d08 100644 +--- a/drivers/video/fbdev/core/fbcon_ud.c ++++ b/drivers/video/fbdev/core/fbcon_ud.c +@@ -50,8 +50,8 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, + { + struct fbcon_ops *ops = info->fbcon_par; + struct fb_copyarea area; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); ++ u32 vxres = GETVXRES(ops->p, info); + + area.sy = vyres - ((sy + height) * vc->vc_font.height); + area.sx = vxres - ((sx + width) * vc->vc_font.width); +@@ -69,8 +69,8 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, + struct fbcon_ops *ops = info->fbcon_par; + struct fb_fillrect region; + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); ++ u32 vxres = GETVXRES(ops->p, info); + + region.color = attr_bgcol_ec(bgshift,vc,info); + region.dy = vyres - ((sy + height) * vc->vc_font.height); +@@ -162,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, + u32 mod = vc->vc_font.width % 8, cnt, pitch, size; + u32 attribute = get_attribute(info, scr_readw(s)); + u8 *dst, *buf = NULL; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); ++ u32 vxres = GETVXRES(ops->p, info); + + if (!ops->fontbuffer) + return; +@@ -259,8 +259,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; + int err = 1, dx, dy; + char *src; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); ++ u32 vxres = GETVXRES(ops->p, info); + + if (!ops->fontbuffer) + return; +@@ -410,8 +410,8 @@ static int ud_update_start(struct fb_info *info) + { + struct fbcon_ops *ops = info->fbcon_par; + int xoffset, yoffset; +- u32 vyres = GETVYRES(ops->p->scrollmode, info); +- u32 vxres = GETVXRES(ops->p->scrollmode, info); ++ u32 vyres = GETVYRES(ops->p, info); ++ u32 vxres = GETVXRES(ops->p, info); + int err; + + xoffset = vxres - info->var.xres - ops->var.xoffset; +diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c +index 7420d2c16e47e..7bd5e2a4a9da5 100644 +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -1759,6 +1759,53 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, + } + EXPORT_SYMBOL(remove_conflicting_framebuffers); + ++/** ++ * is_firmware_framebuffer - detect if firmware-configured framebuffer matches ++ * @a: memory range, users of which are to be checked ++ * ++ * This function checks framebuffer devices (initialized by firmware/bootloader) ++ * which use memory range described by @a. If @a matchesm the function returns ++ * true, otherwise false. ++ */ ++bool is_firmware_framebuffer(struct apertures_struct *a) ++{ ++ bool do_free = false; ++ bool found = false; ++ int i; ++ ++ if (!a) { ++ a = alloc_apertures(1); ++ if (!a) ++ return false; ++ ++ a->ranges[0].base = 0; ++ a->ranges[0].size = ~0; ++ do_free = true; ++ } ++ ++ mutex_lock(®istration_lock); ++ /* check all firmware fbs and kick off if the base addr overlaps */ ++ for_each_registered_fb(i) { ++ struct apertures_struct *gen_aper; ++ ++ if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) ++ continue; ++ ++ gen_aper = registered_fb[i]->apertures; ++ if (fb_do_apertures_overlap(gen_aper, a)) { ++ found = true; ++ break; ++ } ++ } ++ mutex_unlock(®istration_lock); ++ ++ if (do_free) ++ kfree(a); ++ ++ return found; ++} ++EXPORT_SYMBOL(is_firmware_framebuffer); ++ + /** + * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices + * @pdev: PCI device +diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c +index 8ea8f079cde26..ea42ba6445b2d 100644 +--- a/drivers/video/fbdev/efifb.c ++++ b/drivers/video/fbdev/efifb.c +@@ -47,6 +47,8 @@ static bool use_bgrt = true; + static bool request_mem_succeeded = false; + static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC; + ++static struct pci_dev *efifb_pci_dev; /* dev with BAR covering the efifb */ ++ + static struct fb_var_screeninfo efifb_defined = { + .activate = FB_ACTIVATE_NOW, + .height = -1, +@@ -243,6 +245,9 @@ static inline void efifb_show_boot_graphics(struct fb_info *info) {} + + static void efifb_destroy(struct fb_info *info) + { ++ if (efifb_pci_dev) ++ pm_runtime_put(&efifb_pci_dev->dev); ++ + if (info->screen_base) { + if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) + iounmap(info->screen_base); +@@ -333,7 +338,6 @@ ATTRIBUTE_GROUPS(efifb); + + static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */ + +-static struct pci_dev *efifb_pci_dev; /* dev with BAR covering the efifb */ + static struct resource *bar_resource; + static u64 bar_offset; + +@@ -347,6 +351,17 @@ static int efifb_probe(struct platform_device *dev) + char *option = NULL; + efi_memory_desc_t md; + ++ /* ++ * Generic drivers must not be registered if a framebuffer exists. ++ * If a native driver was probed, the display hardware was already ++ * taken and attempting to use the system framebuffer is dangerous. ++ */ ++ if (num_registered_fb > 0) { ++ dev_err(&dev->dev, ++ "efifb: a framebuffer is already registered\n"); ++ return -EINVAL; ++ } ++ + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled) + return -ENODEV; + +@@ -569,17 +584,22 @@ static int efifb_probe(struct platform_device *dev) + pr_err("efifb: cannot allocate colormap\n"); + goto err_groups; + } ++ ++ if (efifb_pci_dev) ++ WARN_ON(pm_runtime_get_sync(&efifb_pci_dev->dev) < 0); ++ + err = register_framebuffer(info); + if (err < 0) { + pr_err("efifb: cannot register framebuffer\n"); +- goto err_fb_dealoc; ++ goto err_put_rpm_ref; + } + fb_info(info, "%s frame buffer device\n", info->fix.id); +- if (efifb_pci_dev) +- pm_runtime_get_sync(&efifb_pci_dev->dev); + return 0; + +-err_fb_dealoc: ++err_put_rpm_ref: ++ if (efifb_pci_dev) ++ pm_runtime_put(&efifb_pci_dev->dev); ++ + fb_dealloc_cmap(&info->cmap); + err_groups: + sysfs_remove_groups(&dev->dev.kobj, efifb_groups); +@@ -603,8 +623,6 @@ static int efifb_remove(struct platform_device *pdev) + unregister_framebuffer(info); + sysfs_remove_groups(&pdev->dev.kobj, efifb_groups); + framebuffer_release(info); +- if (efifb_pci_dev) +- pm_runtime_put(&efifb_pci_dev->dev); + + return 0; + } +diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c +index 23999df527393..c8e0ea27caf1d 100644 +--- a/drivers/video/fbdev/hyperv_fb.c ++++ b/drivers/video/fbdev/hyperv_fb.c +@@ -287,8 +287,6 @@ struct hvfb_par { + + static uint screen_width = HVFB_WIDTH; + static uint screen_height = HVFB_HEIGHT; +-static uint screen_width_max = HVFB_WIDTH; +-static uint screen_height_max = HVFB_HEIGHT; + static uint screen_depth; + static uint screen_fb_size; + static uint dio_fb_size; /* FB size for deferred IO */ +@@ -582,7 +580,6 @@ static int synthvid_get_supported_resolution(struct hv_device *hdev) + int ret = 0; + unsigned long t; + u8 index; +- int i; + + memset(msg, 0, sizeof(struct synthvid_msg)); + msg->vid_hdr.type = SYNTHVID_RESOLUTION_REQUEST; +@@ -613,13 +610,6 @@ static int synthvid_get_supported_resolution(struct hv_device *hdev) + goto out; + } + +- for (i = 0; i < msg->resolution_resp.resolution_count; i++) { +- screen_width_max = max_t(unsigned int, screen_width_max, +- msg->resolution_resp.supported_resolution[i].width); +- screen_height_max = max_t(unsigned int, screen_height_max, +- msg->resolution_resp.supported_resolution[i].height); +- } +- + screen_width = + msg->resolution_resp.supported_resolution[index].width; + screen_height = +@@ -941,7 +931,7 @@ static void hvfb_get_option(struct fb_info *info) + + if (x < HVFB_WIDTH_MIN || y < HVFB_HEIGHT_MIN || + (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) && +- (x > screen_width_max || y > screen_height_max)) || ++ (x * y * screen_depth / 8 > screen_fb_size)) || + (par->synthvid_version == SYNTHVID_VERSION_WIN8 && + x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) || + (par->synthvid_version == SYNTHVID_VERSION_WIN7 && +@@ -1194,8 +1184,8 @@ static int hvfb_probe(struct hv_device *hdev, + } + + hvfb_get_option(info); +- pr_info("Screen resolution: %dx%d, Color depth: %d\n", +- screen_width, screen_height, screen_depth); ++ pr_info("Screen resolution: %dx%d, Color depth: %d, Frame buffer size: %d\n", ++ screen_width, screen_height, screen_depth, screen_fb_size); + + ret = hvfb_getmem(hdev, info); + if (ret) { +diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c +index 62f0ded706815..b63074fd892e5 100644 +--- a/drivers/video/fbdev/simplefb.c ++++ b/drivers/video/fbdev/simplefb.c +@@ -407,6 +407,17 @@ static int simplefb_probe(struct platform_device *pdev) + struct simplefb_par *par; + struct resource *mem; + ++ /* ++ * Generic drivers must not be registered if a framebuffer exists. ++ * If a native driver was probed, the display hardware was already ++ * taken and attempting to use the system framebuffer is dangerous. ++ */ ++ if (num_registered_fb > 0) { ++ dev_err(&pdev->dev, ++ "simplefb: a framebuffer is already registered\n"); ++ return -EINVAL; ++ } ++ + if (fb_get_options("simplefb", NULL)) + return -ENODEV; + +diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c +index e2757ff1c23d2..96e312a3eac75 100644 +--- a/drivers/video/fbdev/vga16fb.c ++++ b/drivers/video/fbdev/vga16fb.c +@@ -184,6 +184,25 @@ static inline void setindex(int index) + vga_io_w(VGA_GFX_I, index); + } + ++/* Check if the video mode is supported by the driver */ ++static inline int check_mode_supported(void) ++{ ++ /* non-x86 architectures treat orig_video_isVGA as a boolean flag */ ++#if defined(CONFIG_X86) ++ /* only EGA and VGA in 16 color graphic mode are supported */ ++ if (screen_info.orig_video_isVGA != VIDEO_TYPE_EGAC && ++ screen_info.orig_video_isVGA != VIDEO_TYPE_VGAC) ++ return -ENODEV; ++ ++ if (screen_info.orig_video_mode != 0x0D && /* 320x200/4 (EGA) */ ++ screen_info.orig_video_mode != 0x0E && /* 640x200/4 (EGA) */ ++ screen_info.orig_video_mode != 0x10 && /* 640x350/4 (EGA) */ ++ screen_info.orig_video_mode != 0x12) /* 640x480/4 (VGA) */ ++ return -ENODEV; ++#endif ++ return 0; ++} ++ + static void vga16fb_pan_var(struct fb_info *info, + struct fb_var_screeninfo *var) + { +@@ -1422,6 +1441,11 @@ static int __init vga16fb_init(void) + + vga16fb_setup(option); + #endif ++ ++ ret = check_mode_supported(); ++ if (ret) ++ return ret; ++ + ret = platform_driver_register(&vga16fb_driver); + + if (!ret) { +diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c +index e21e1e86ad15f..fe7a8e4034097 100644 +--- a/drivers/virt/nitro_enclaves/ne_misc_dev.c ++++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c +@@ -886,8 +886,9 @@ static int ne_set_user_memory_region_ioctl(struct ne_enclave *ne_enclave, + goto put_pages; + } + +- gup_rc = get_user_pages(mem_region.userspace_addr + memory_size, 1, FOLL_GET, +- ne_mem_region->pages + i, NULL); ++ gup_rc = get_user_pages_unlocked(mem_region.userspace_addr + memory_size, 1, ++ ne_mem_region->pages + i, FOLL_GET); ++ + if (gup_rc < 0) { + rc = gup_rc; + +diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c +index bef8ad6bf4661..4624a2c3d0553 100644 +--- a/drivers/virtio/virtio_mem.c ++++ b/drivers/virtio/virtio_mem.c +@@ -577,7 +577,7 @@ static int virtio_mem_sbm_sb_states_prepare_next_mb(struct virtio_mem *vm) + return -ENOMEM; + + mutex_lock(&vm->hotplug_mutex); +- if (new_bitmap) ++ if (vm->sbm.sb_states) + memcpy(new_bitmap, vm->sbm.sb_states, old_pages * PAGE_SIZE); + + old_bitmap = vm->sbm.sb_states; +diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c +index 3035bb6f54585..603a6f4345efd 100644 +--- a/drivers/virtio/virtio_ring.c ++++ b/drivers/virtio/virtio_ring.c +@@ -268,7 +268,7 @@ size_t virtio_max_dma_size(struct virtio_device *vdev) + size_t max_segment_size = SIZE_MAX; + + if (vring_use_dma_api(vdev)) +- max_segment_size = dma_max_mapping_size(&vdev->dev); ++ max_segment_size = dma_max_mapping_size(vdev->dev.parent); + + return max_segment_size; + } +@@ -1065,6 +1065,8 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, + + head = vq->packed.next_avail_idx; + desc = alloc_indirect_packed(total_sg, gfp); ++ if (!desc) ++ return -ENOMEM; + + if (unlikely(vq->vq.num_free < 1)) { + pr_debug("Can't add buf len 1 - avail = 0\n"); +@@ -1176,6 +1178,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, + unsigned int i, n, c, descs_used, err_idx; + __le16 head_flags, flags; + u16 head, id, prev, curr, avail_used_flags; ++ int err; + + START_USE(vq); + +@@ -1191,9 +1194,16 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, + + BUG_ON(total_sg == 0); + +- if (virtqueue_use_indirect(_vq, total_sg)) +- return virtqueue_add_indirect_packed(vq, sgs, total_sg, +- out_sgs, in_sgs, data, gfp); ++ if (virtqueue_use_indirect(_vq, total_sg)) { ++ err = virtqueue_add_indirect_packed(vq, sgs, total_sg, out_sgs, ++ in_sgs, data, gfp); ++ if (err != -ENOMEM) { ++ END_USE(vq); ++ return err; ++ } ++ ++ /* fall back on direct */ ++ } + + head = vq->packed.next_avail_idx; + avail_used_flags = vq->packed.avail_used_flags; +diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c +index e4f336111edc6..6cef6e2edb892 100644 +--- a/drivers/w1/slaves/w1_ds28e04.c ++++ b/drivers/w1/slaves/w1_ds28e04.c +@@ -32,7 +32,7 @@ static int w1_strong_pullup = 1; + module_param_named(strong_pullup, w1_strong_pullup, int, 0); + + /* enable/disable CRC checking on DS28E04-100 memory accesses */ +-static char w1_enable_crccheck = 1; ++static bool w1_enable_crccheck = true; + + #define W1_EEPROM_SIZE 512 + #define W1_PAGE_COUNT 16 +@@ -339,32 +339,18 @@ static BIN_ATTR_RW(pio, 1); + static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr, + char *buf) + { +- if (put_user(w1_enable_crccheck + 0x30, buf)) +- return -EFAULT; +- +- return sizeof(w1_enable_crccheck); ++ return sysfs_emit(buf, "%d\n", w1_enable_crccheck); + } + + static ssize_t crccheck_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + { +- char val; +- +- if (count != 1 || !buf) +- return -EINVAL; ++ int err = kstrtobool(buf, &w1_enable_crccheck); + +- if (get_user(val, buf)) +- return -EFAULT; ++ if (err) ++ return err; + +- /* convert to decimal */ +- val = val - 0x30; +- if (val != 0 && val != 1) +- return -EINVAL; +- +- /* set the new value */ +- w1_enable_crccheck = val; +- +- return sizeof(w1_enable_crccheck); ++ return count; + } + + static DEVICE_ATTR_RW(crccheck); +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index bf59faeb3de1b..d937f957f8df8 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1679,7 +1679,7 @@ config SIBYTE_WDOG + + config AR7_WDT + tristate "TI AR7 Watchdog Timer" +- depends on AR7 || (MIPS && COMPILE_TEST) ++ depends on AR7 || (MIPS && 32BIT && COMPILE_TEST) + help + Hardware driver for the TI AR7 Watchdog Timer. + +diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c +index f60beec1bbaea..f7d82d2619133 100644 +--- a/drivers/watchdog/f71808e_wdt.c ++++ b/drivers/watchdog/f71808e_wdt.c +@@ -228,15 +228,17 @@ static int watchdog_set_timeout(int timeout) + + mutex_lock(&watchdog.lock); + +- watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; ++ timeout = watchdog.timer_val * 60; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + ++ watchdog.timeout = timeout; ++ + mutex_unlock(&watchdog.lock); + + return 0; +diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c +index 3a50f097ed3ed..8db96b5e72536 100644 +--- a/drivers/xen/balloon.c ++++ b/drivers/xen/balloon.c +@@ -58,6 +58,7 @@ + #include <linux/percpu-defs.h> + #include <linux/slab.h> + #include <linux/sysctl.h> ++#include <linux/moduleparam.h> + + #include <asm/page.h> + #include <asm/tlb.h> +@@ -73,6 +74,12 @@ + #include <xen/page.h> + #include <xen/mem-reservation.h> + ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "xen." ++ ++static uint __read_mostly balloon_boot_timeout = 180; ++module_param(balloon_boot_timeout, uint, 0444); ++ + static int xen_hotplug_unpopulated; + + #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG +@@ -125,12 +132,12 @@ static struct ctl_table xen_root[] = { + * BP_ECANCELED: error, balloon operation canceled. + */ + +-enum bp_state { ++static enum bp_state { + BP_DONE, + BP_WAIT, + BP_EAGAIN, + BP_ECANCELED +-}; ++} balloon_state = BP_DONE; + + /* Main waiting point for xen-balloon thread. */ + static DECLARE_WAIT_QUEUE_HEAD(balloon_thread_wq); +@@ -199,18 +206,15 @@ static struct page *balloon_next_page(struct page *page) + return list_entry(next, struct page, lru); + } + +-static enum bp_state update_schedule(enum bp_state state) ++static void update_schedule(void) + { +- if (state == BP_WAIT) +- return BP_WAIT; +- +- if (state == BP_ECANCELED) +- return BP_ECANCELED; ++ if (balloon_state == BP_WAIT || balloon_state == BP_ECANCELED) ++ return; + +- if (state == BP_DONE) { ++ if (balloon_state == BP_DONE) { + balloon_stats.schedule_delay = 1; + balloon_stats.retry_count = 1; +- return BP_DONE; ++ return; + } + + ++balloon_stats.retry_count; +@@ -219,7 +223,8 @@ static enum bp_state update_schedule(enum bp_state state) + balloon_stats.retry_count > balloon_stats.max_retry_count) { + balloon_stats.schedule_delay = 1; + balloon_stats.retry_count = 1; +- return BP_ECANCELED; ++ balloon_state = BP_ECANCELED; ++ return; + } + + balloon_stats.schedule_delay <<= 1; +@@ -227,7 +232,7 @@ static enum bp_state update_schedule(enum bp_state state) + if (balloon_stats.schedule_delay > balloon_stats.max_schedule_delay) + balloon_stats.schedule_delay = balloon_stats.max_schedule_delay; + +- return BP_EAGAIN; ++ balloon_state = BP_EAGAIN; + } + + #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG +@@ -494,9 +499,9 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) + * Stop waiting if either state is BP_DONE and ballooning action is + * needed, or if the credit has changed while state is not BP_DONE. + */ +-static bool balloon_thread_cond(enum bp_state state, long credit) ++static bool balloon_thread_cond(long credit) + { +- if (state == BP_DONE) ++ if (balloon_state == BP_DONE) + credit = 0; + + return current_credit() != credit || kthread_should_stop(); +@@ -510,13 +515,12 @@ static bool balloon_thread_cond(enum bp_state state, long credit) + */ + static int balloon_thread(void *unused) + { +- enum bp_state state = BP_DONE; + long credit; + unsigned long timeout; + + set_freezable(); + for (;;) { +- switch (state) { ++ switch (balloon_state) { + case BP_DONE: + case BP_ECANCELED: + timeout = 3600 * HZ; +@@ -532,7 +536,7 @@ static int balloon_thread(void *unused) + credit = current_credit(); + + wait_event_freezable_timeout(balloon_thread_wq, +- balloon_thread_cond(state, credit), timeout); ++ balloon_thread_cond(credit), timeout); + + if (kthread_should_stop()) + return 0; +@@ -543,22 +547,23 @@ static int balloon_thread(void *unused) + + if (credit > 0) { + if (balloon_is_inflated()) +- state = increase_reservation(credit); ++ balloon_state = increase_reservation(credit); + else +- state = reserve_additional_memory(); ++ balloon_state = reserve_additional_memory(); + } + + if (credit < 0) { + long n_pages; + + n_pages = min(-credit, si_mem_available()); +- state = decrease_reservation(n_pages, GFP_BALLOON); +- if (state == BP_DONE && n_pages != -credit && ++ balloon_state = decrease_reservation(n_pages, ++ GFP_BALLOON); ++ if (balloon_state == BP_DONE && n_pages != -credit && + n_pages < totalreserve_pages) +- state = BP_EAGAIN; ++ balloon_state = BP_EAGAIN; + } + +- state = update_schedule(state); ++ update_schedule(); + + mutex_unlock(&balloon_mutex); + +@@ -765,3 +770,38 @@ static int __init balloon_init(void) + return 0; + } + subsys_initcall(balloon_init); ++ ++static int __init balloon_wait_finish(void) ++{ ++ long credit, last_credit = 0; ++ unsigned long last_changed = 0; ++ ++ if (!xen_domain()) ++ return -ENODEV; ++ ++ /* PV guests don't need to wait. */ ++ if (xen_pv_domain() || !current_credit()) ++ return 0; ++ ++ pr_notice("Waiting for initial ballooning down having finished.\n"); ++ ++ while ((credit = current_credit()) < 0) { ++ if (credit != last_credit) { ++ last_changed = jiffies; ++ last_credit = credit; ++ } ++ if (balloon_state == BP_ECANCELED) { ++ pr_warn_once("Initial ballooning failed, %ld pages need to be freed.\n", ++ -credit); ++ if (jiffies - last_changed >= HZ * balloon_boot_timeout) ++ panic("Initial ballooning failed!\n"); ++ } ++ ++ schedule_timeout_interruptible(HZ / 10); ++ } ++ ++ pr_notice("Initial ballooning down finished.\n"); ++ ++ return 0; ++} ++late_initcall_sync(balloon_wait_finish); +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index a78704ae36186..46d9295d9a6e4 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -1251,6 +1251,12 @@ int bind_evtchn_to_irq(evtchn_port_t evtchn) + } + EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); + ++int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn) ++{ ++ return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL); ++} ++EXPORT_SYMBOL_GPL(bind_evtchn_to_irq_lateeoi); ++ + static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) + { + struct evtchn_bind_ipi bind_ipi; +diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c +index 3fa40c723e8e9..edb0acd0b8323 100644 +--- a/drivers/xen/gntalloc.c ++++ b/drivers/xen/gntalloc.c +@@ -169,20 +169,14 @@ undo: + __del_gref(gref); + } + +- /* It's possible for the target domain to map the just-allocated grant +- * references by blindly guessing their IDs; if this is done, then +- * __del_gref will leave them in the queue_gref list. They need to be +- * added to the global list so that we can free them when they are no +- * longer referenced. +- */ +- if (unlikely(!list_empty(&queue_gref))) +- list_splice_tail(&queue_gref, &gref_list); + mutex_unlock(&gref_mutex); + return rc; + } + + static void __del_gref(struct gntalloc_gref *gref) + { ++ unsigned long addr; ++ + if (gref->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { + uint8_t *tmp = kmap(gref->page); + tmp[gref->notify.pgoff] = 0; +@@ -196,21 +190,16 @@ static void __del_gref(struct gntalloc_gref *gref) + gref->notify.flags = 0; + + if (gref->gref_id) { +- if (gnttab_query_foreign_access(gref->gref_id)) +- return; +- +- if (!gnttab_end_foreign_access_ref(gref->gref_id, 0)) +- return; +- +- gnttab_free_grant_reference(gref->gref_id); ++ if (gref->page) { ++ addr = (unsigned long)page_to_virt(gref->page); ++ gnttab_end_foreign_access(gref->gref_id, 0, addr); ++ } else ++ gnttab_free_grant_reference(gref->gref_id); + } + + gref_size--; + list_del(&gref->next_gref); + +- if (gref->page) +- __free_page(gref->page); +- + kfree(gref); + } + +diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c +index fec1b65371665..59ffea8000791 100644 +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -250,13 +250,13 @@ void gntdev_put_map(struct gntdev_priv *priv, struct gntdev_grant_map *map) + if (!refcount_dec_and_test(&map->users)) + return; + ++ if (map->pages && !use_ptemod) ++ unmap_grant_pages(map, 0, map->count); ++ + if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) { + notify_remote_via_evtchn(map->notify.event); + evtchn_put(map->notify.event); + } +- +- if (map->pages && !use_ptemod) +- unmap_grant_pages(map, 0, map->count); + gntdev_free_map(map); + } + +diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c +index 3729bea0c9895..5c83d41766c85 100644 +--- a/drivers/xen/grant-table.c ++++ b/drivers/xen/grant-table.c +@@ -134,12 +134,9 @@ struct gnttab_ops { + */ + unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref); + /* +- * Query the status of a grant entry. Ref parameter is reference of +- * queried grant entry, return value is the status of queried entry. +- * Detailed status(writing/reading) can be gotten from the return value +- * by bit operations. ++ * Read the frame number related to a given grant reference. + */ +- int (*query_foreign_access)(grant_ref_t ref); ++ unsigned long (*read_frame)(grant_ref_t ref); + }; + + struct unmap_refs_callback_data { +@@ -284,22 +281,6 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, + } + EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); + +-static int gnttab_query_foreign_access_v1(grant_ref_t ref) +-{ +- return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing); +-} +- +-static int gnttab_query_foreign_access_v2(grant_ref_t ref) +-{ +- return grstatus[ref] & (GTF_reading|GTF_writing); +-} +- +-int gnttab_query_foreign_access(grant_ref_t ref) +-{ +- return gnttab_interface->query_foreign_access(ref); +-} +-EXPORT_SYMBOL_GPL(gnttab_query_foreign_access); +- + static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly) + { + u16 flags, nflags; +@@ -353,6 +334,16 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) + } + EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref); + ++static unsigned long gnttab_read_frame_v1(grant_ref_t ref) ++{ ++ return gnttab_shared.v1[ref].frame; ++} ++ ++static unsigned long gnttab_read_frame_v2(grant_ref_t ref) ++{ ++ return gnttab_shared.v2[ref].full_page.frame; ++} ++ + struct deferred_entry { + struct list_head list; + grant_ref_t ref; +@@ -382,12 +373,9 @@ static void gnttab_handle_deferred(struct timer_list *unused) + spin_unlock_irqrestore(&gnttab_list_lock, flags); + if (_gnttab_end_foreign_access_ref(entry->ref, entry->ro)) { + put_free_entry(entry->ref); +- if (entry->page) { +- pr_debug("freeing g.e. %#x (pfn %#lx)\n", +- entry->ref, page_to_pfn(entry->page)); +- put_page(entry->page); +- } else +- pr_info("freeing g.e. %#x\n", entry->ref); ++ pr_debug("freeing g.e. %#x (pfn %#lx)\n", ++ entry->ref, page_to_pfn(entry->page)); ++ put_page(entry->page); + kfree(entry); + entry = NULL; + } else { +@@ -412,9 +400,18 @@ static void gnttab_handle_deferred(struct timer_list *unused) + static void gnttab_add_deferred(grant_ref_t ref, bool readonly, + struct page *page) + { +- struct deferred_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC); ++ struct deferred_entry *entry; ++ gfp_t gfp = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; + const char *what = KERN_WARNING "leaking"; + ++ entry = kmalloc(sizeof(*entry), gfp); ++ if (!page) { ++ unsigned long gfn = gnttab_interface->read_frame(ref); ++ ++ page = pfn_to_page(gfn_to_pfn(gfn)); ++ get_page(page); ++ } ++ + if (entry) { + unsigned long flags; + +@@ -435,11 +432,21 @@ static void gnttab_add_deferred(grant_ref_t ref, bool readonly, + what, ref, page ? page_to_pfn(page) : -1); + } + ++int gnttab_try_end_foreign_access(grant_ref_t ref) ++{ ++ int ret = _gnttab_end_foreign_access_ref(ref, 0); ++ ++ if (ret) ++ put_free_entry(ref); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(gnttab_try_end_foreign_access); ++ + void gnttab_end_foreign_access(grant_ref_t ref, int readonly, + unsigned long page) + { +- if (gnttab_end_foreign_access_ref(ref, readonly)) { +- put_free_entry(ref); ++ if (gnttab_try_end_foreign_access(ref)) { + if (page != 0) + put_page(virt_to_page(page)); + } else +@@ -1417,7 +1424,7 @@ static const struct gnttab_ops gnttab_v1_ops = { + .update_entry = gnttab_update_entry_v1, + .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1, + .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1, +- .query_foreign_access = gnttab_query_foreign_access_v1, ++ .read_frame = gnttab_read_frame_v1, + }; + + static const struct gnttab_ops gnttab_v2_ops = { +@@ -1429,7 +1436,7 @@ static const struct gnttab_ops gnttab_v2_ops = { + .update_entry = gnttab_update_entry_v2, + .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2, + .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2, +- .query_foreign_access = gnttab_query_foreign_access_v2, ++ .read_frame = gnttab_read_frame_v2, + }; + + static bool gnttab_need_v2(void) +diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c +index 7984645b59563..bbe337dc296e3 100644 +--- a/drivers/xen/pvcalls-front.c ++++ b/drivers/xen/pvcalls-front.c +@@ -337,8 +337,8 @@ static void free_active_ring(struct sock_mapping *map) + if (!map->active.ring) + return; + +- free_pages((unsigned long)map->active.data.in, +- map->active.ring->ring_order); ++ free_pages_exact(map->active.data.in, ++ PAGE_SIZE << map->active.ring->ring_order); + free_page((unsigned long)map->active.ring); + } + +@@ -352,8 +352,8 @@ static int alloc_active_ring(struct sock_mapping *map) + goto out; + + map->active.ring->ring_order = PVCALLS_RING_ORDER; +- bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, +- PVCALLS_RING_ORDER); ++ bytes = alloc_pages_exact(PAGE_SIZE << PVCALLS_RING_ORDER, ++ GFP_KERNEL | __GFP_ZERO); + if (!bytes) + goto out; + +diff --git a/drivers/xen/xen-pciback/conf_space_capability.c b/drivers/xen/xen-pciback/conf_space_capability.c +index 22f13abbe9130..5e53b4817f167 100644 +--- a/drivers/xen/xen-pciback/conf_space_capability.c ++++ b/drivers/xen/xen-pciback/conf_space_capability.c +@@ -160,7 +160,7 @@ static void *pm_ctrl_init(struct pci_dev *dev, int offset) + } + + out: +- return ERR_PTR(err); ++ return err ? ERR_PTR(err) : NULL; + } + + static const struct config_field caplist_pm[] = { +diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c +index e8bed1cb76ba2..df68906812315 100644 +--- a/drivers/xen/xenbus/xenbus_client.c ++++ b/drivers/xen/xenbus/xenbus_client.c +@@ -379,7 +379,14 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr, + unsigned int nr_pages, grant_ref_t *grefs) + { + int err; +- int i, j; ++ unsigned int i; ++ grant_ref_t gref_head; ++ ++ err = gnttab_alloc_grant_references(nr_pages, &gref_head); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "granting access to ring page"); ++ return err; ++ } + + for (i = 0; i < nr_pages; i++) { + unsigned long gfn; +@@ -389,23 +396,14 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr, + else + gfn = virt_to_gfn(vaddr); + +- err = gnttab_grant_foreign_access(dev->otherend_id, gfn, 0); +- if (err < 0) { +- xenbus_dev_fatal(dev, err, +- "granting access to ring page"); +- goto fail; +- } +- grefs[i] = err; ++ grefs[i] = gnttab_claim_grant_reference(&gref_head); ++ gnttab_grant_foreign_access_ref(grefs[i], dev->otherend_id, ++ gfn, 0); + + vaddr = vaddr + XEN_PAGE_SIZE; + } + + return 0; +- +-fail: +- for (j = 0; j < i; j++) +- gnttab_end_foreign_access_ref(grefs[j], 0); +- return err; + } + EXPORT_SYMBOL_GPL(xenbus_grant_ring); + +diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c +index bd003ca8acbe9..fe360c33ce717 100644 +--- a/drivers/xen/xenbus/xenbus_probe.c ++++ b/drivers/xen/xenbus/xenbus_probe.c +@@ -909,7 +909,7 @@ static struct notifier_block xenbus_resume_nb = { + + static int __init xenbus_init(void) + { +- int err = 0; ++ int err; + uint64_t v = 0; + xen_store_domain_type = XS_UNKNOWN; + +@@ -949,6 +949,29 @@ static int __init xenbus_init(void) + err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v); + if (err) + goto out_error; ++ /* ++ * Uninitialized hvm_params are zero and return no error. ++ * Although it is theoretically possible to have ++ * HVM_PARAM_STORE_PFN set to zero on purpose, in reality it is ++ * not zero when valid. If zero, it means that Xenstore hasn't ++ * been properly initialized. Instead of attempting to map a ++ * wrong guest physical address return error. ++ * ++ * Also recognize all bits set as an invalid value. ++ */ ++ if (!v || !~v) { ++ err = -ENOENT; ++ goto out_error; ++ } ++ /* Avoid truncation on 32-bit. */ ++#if BITS_PER_LONG == 32 ++ if (v > ULONG_MAX) { ++ pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n", ++ __func__, v); ++ err = -EINVAL; ++ goto out_error; ++ } ++#endif + xen_store_gfn = (unsigned long)v; + xen_store_interface = + xen_remap(xen_store_gfn << XEN_PAGE_SHIFT, +@@ -983,8 +1006,10 @@ static int __init xenbus_init(void) + */ + proc_create_mount_point("xen"); + #endif ++ return 0; + + out_error: ++ xen_store_domain_type = XS_UNKNOWN; + return err; + } + +diff --git a/fs/9p/fid.c b/fs/9p/fid.c +index b8863dd0de5cc..e8a3b891b0366 100644 +--- a/fs/9p/fid.c ++++ b/fs/9p/fid.c +@@ -96,12 +96,8 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) + dentry, dentry, from_kuid(&init_user_ns, uid), + any); + ret = NULL; +- +- if (d_inode(dentry)) +- ret = v9fs_fid_find_inode(d_inode(dentry), uid); +- + /* we'll recheck under lock if there's anything to look in */ +- if (!ret && dentry->d_fsdata) { ++ if (dentry->d_fsdata) { + struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; + spin_lock(&dentry->d_lock); + hlist_for_each_entry(fid, h, dlist) { +@@ -112,6 +108,9 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) + } + } + spin_unlock(&dentry->d_lock); ++ } else { ++ if (dentry->d_inode) ++ ret = v9fs_fid_find_inode(dentry->d_inode, uid); + } + + return ret; +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 01b9e1281a297..a61df2e0ae521 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -553,7 +553,10 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns, + { + int retval, use_dentry = 0; + struct p9_fid *fid = NULL; +- struct p9_iattr_dotl p9attr; ++ struct p9_iattr_dotl p9attr = { ++ .uid = INVALID_UID, ++ .gid = INVALID_GID, ++ }; + struct inode *inode = d_inode(dentry); + + p9_debug(P9_DEBUG_VFS, "\n"); +@@ -563,14 +566,22 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns, + return retval; + + p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid); +- p9attr.mode = iattr->ia_mode; +- p9attr.uid = iattr->ia_uid; +- p9attr.gid = iattr->ia_gid; +- p9attr.size = iattr->ia_size; +- p9attr.atime_sec = iattr->ia_atime.tv_sec; +- p9attr.atime_nsec = iattr->ia_atime.tv_nsec; +- p9attr.mtime_sec = iattr->ia_mtime.tv_sec; +- p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; ++ if (iattr->ia_valid & ATTR_MODE) ++ p9attr.mode = iattr->ia_mode; ++ if (iattr->ia_valid & ATTR_UID) ++ p9attr.uid = iattr->ia_uid; ++ if (iattr->ia_valid & ATTR_GID) ++ p9attr.gid = iattr->ia_gid; ++ if (iattr->ia_valid & ATTR_SIZE) ++ p9attr.size = iattr->ia_size; ++ if (iattr->ia_valid & ATTR_ATIME_SET) { ++ p9attr.atime_sec = iattr->ia_atime.tv_sec; ++ p9attr.atime_nsec = iattr->ia_atime.tv_nsec; ++ } ++ if (iattr->ia_valid & ATTR_MTIME_SET) { ++ p9attr.mtime_sec = iattr->ia_mtime.tv_sec; ++ p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; ++ } + + if (iattr->ia_valid & ATTR_FILE) { + fid = iattr->ia_file->private_data; +diff --git a/fs/afs/file.c b/fs/afs/file.c +index e6c447ae91f38..b165377179c3c 100644 +--- a/fs/afs/file.c ++++ b/fs/afs/file.c +@@ -502,8 +502,9 @@ static void afs_add_open_mmap(struct afs_vnode *vnode) + if (atomic_inc_return(&vnode->cb_nr_mmap) == 1) { + down_write(&vnode->volume->cell->fs_open_mmaps_lock); + +- list_add_tail(&vnode->cb_mmap_link, +- &vnode->volume->cell->fs_open_mmaps); ++ if (list_empty(&vnode->cb_mmap_link)) ++ list_add_tail(&vnode->cb_mmap_link, ++ &vnode->volume->cell->fs_open_mmaps); + + up_write(&vnode->volume->cell->fs_open_mmaps_lock); + } +diff --git a/fs/afs/super.c b/fs/afs/super.c +index d110def8aa8eb..34c68724c98be 100644 +--- a/fs/afs/super.c ++++ b/fs/afs/super.c +@@ -667,6 +667,7 @@ static void afs_i_init_once(void *_vnode) + INIT_LIST_HEAD(&vnode->pending_locks); + INIT_LIST_HEAD(&vnode->granted_locks); + INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work); ++ INIT_LIST_HEAD(&vnode->cb_mmap_link); + seqlock_init(&vnode->cb_lock); + } + +diff --git a/fs/aio.c b/fs/aio.c +index 51b08ab01dffc..1a78979663dca 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -181,8 +181,9 @@ struct poll_iocb { + struct file *file; + struct wait_queue_head *head; + __poll_t events; +- bool done; + bool cancelled; ++ bool work_scheduled; ++ bool work_need_resched; + struct wait_queue_entry wait; + struct work_struct work; + }; +@@ -1620,6 +1621,51 @@ static void aio_poll_put_work(struct work_struct *work) + iocb_put(iocb); + } + ++/* ++ * Safely lock the waitqueue which the request is on, synchronizing with the ++ * case where the ->poll() provider decides to free its waitqueue early. ++ * ++ * Returns true on success, meaning that req->head->lock was locked, req->wait ++ * is on req->head, and an RCU read lock was taken. Returns false if the ++ * request was already removed from its waitqueue (which might no longer exist). ++ */ ++static bool poll_iocb_lock_wq(struct poll_iocb *req) ++{ ++ wait_queue_head_t *head; ++ ++ /* ++ * While we hold the waitqueue lock and the waitqueue is nonempty, ++ * wake_up_pollfree() will wait for us. However, taking the waitqueue ++ * lock in the first place can race with the waitqueue being freed. ++ * ++ * We solve this as eventpoll does: by taking advantage of the fact that ++ * all users of wake_up_pollfree() will RCU-delay the actual free. If ++ * we enter rcu_read_lock() and see that the pointer to the queue is ++ * non-NULL, we can then lock it without the memory being freed out from ++ * under us, then check whether the request is still on the queue. ++ * ++ * Keep holding rcu_read_lock() as long as we hold the queue lock, in ++ * case the caller deletes the entry from the queue, leaving it empty. ++ * In that case, only RCU prevents the queue memory from being freed. ++ */ ++ rcu_read_lock(); ++ head = smp_load_acquire(&req->head); ++ if (head) { ++ spin_lock(&head->lock); ++ if (!list_empty(&req->wait.entry)) ++ return true; ++ spin_unlock(&head->lock); ++ } ++ rcu_read_unlock(); ++ return false; ++} ++ ++static void poll_iocb_unlock_wq(struct poll_iocb *req) ++{ ++ spin_unlock(&req->head->lock); ++ rcu_read_unlock(); ++} ++ + static void aio_poll_complete_work(struct work_struct *work) + { + struct poll_iocb *req = container_of(work, struct poll_iocb, work); +@@ -1639,14 +1685,27 @@ static void aio_poll_complete_work(struct work_struct *work) + * avoid further branches in the fast path. + */ + spin_lock_irq(&ctx->ctx_lock); +- if (!mask && !READ_ONCE(req->cancelled)) { +- add_wait_queue(req->head, &req->wait); +- spin_unlock_irq(&ctx->ctx_lock); +- return; +- } ++ if (poll_iocb_lock_wq(req)) { ++ if (!mask && !READ_ONCE(req->cancelled)) { ++ /* ++ * The request isn't actually ready to be completed yet. ++ * Reschedule completion if another wakeup came in. ++ */ ++ if (req->work_need_resched) { ++ schedule_work(&req->work); ++ req->work_need_resched = false; ++ } else { ++ req->work_scheduled = false; ++ } ++ poll_iocb_unlock_wq(req); ++ spin_unlock_irq(&ctx->ctx_lock); ++ return; ++ } ++ list_del_init(&req->wait.entry); ++ poll_iocb_unlock_wq(req); ++ } /* else, POLLFREE has freed the waitqueue, so we must complete */ + list_del_init(&iocb->ki_list); + iocb->ki_res.res = mangle_poll(mask); +- req->done = true; + spin_unlock_irq(&ctx->ctx_lock); + + iocb_put(iocb); +@@ -1658,13 +1717,14 @@ static int aio_poll_cancel(struct kiocb *iocb) + struct aio_kiocb *aiocb = container_of(iocb, struct aio_kiocb, rw); + struct poll_iocb *req = &aiocb->poll; + +- spin_lock(&req->head->lock); +- WRITE_ONCE(req->cancelled, true); +- if (!list_empty(&req->wait.entry)) { +- list_del_init(&req->wait.entry); +- schedule_work(&aiocb->poll.work); +- } +- spin_unlock(&req->head->lock); ++ if (poll_iocb_lock_wq(req)) { ++ WRITE_ONCE(req->cancelled, true); ++ if (!req->work_scheduled) { ++ schedule_work(&aiocb->poll.work); ++ req->work_scheduled = true; ++ } ++ poll_iocb_unlock_wq(req); ++ } /* else, the request was force-cancelled by POLLFREE already */ + + return 0; + } +@@ -1681,21 +1741,27 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + if (mask && !(mask & req->events)) + return 0; + +- list_del_init(&req->wait.entry); +- +- if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { ++ /* ++ * Complete the request inline if possible. This requires that three ++ * conditions be met: ++ * 1. An event mask must have been passed. If a plain wakeup was done ++ * instead, then mask == 0 and we have to call vfs_poll() to get ++ * the events, so inline completion isn't possible. ++ * 2. The completion work must not have already been scheduled. ++ * 3. ctx_lock must not be busy. We have to use trylock because we ++ * already hold the waitqueue lock, so this inverts the normal ++ * locking order. Use irqsave/irqrestore because not all ++ * filesystems (e.g. fuse) call this function with IRQs disabled, ++ * yet IRQs have to be disabled before ctx_lock is obtained. ++ */ ++ if (mask && !req->work_scheduled && ++ spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { + struct kioctx *ctx = iocb->ki_ctx; + +- /* +- * Try to complete the iocb inline if we can. Use +- * irqsave/irqrestore because not all filesystems (e.g. fuse) +- * call this function with IRQs disabled and because IRQs +- * have to be disabled before ctx_lock is obtained. +- */ ++ list_del_init(&req->wait.entry); + list_del(&iocb->ki_list); + iocb->ki_res.res = mangle_poll(mask); +- req->done = true; +- if (iocb->ki_eventfd && eventfd_signal_allowed()) { ++ if (iocb->ki_eventfd && !eventfd_signal_allowed()) { + iocb = NULL; + INIT_WORK(&req->work, aio_poll_put_work); + schedule_work(&req->work); +@@ -1704,7 +1770,43 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + if (iocb) + iocb_put(iocb); + } else { +- schedule_work(&req->work); ++ /* ++ * Schedule the completion work if needed. If it was already ++ * scheduled, record that another wakeup came in. ++ * ++ * Don't remove the request from the waitqueue here, as it might ++ * not actually be complete yet (we won't know until vfs_poll() ++ * is called), and we must not miss any wakeups. POLLFREE is an ++ * exception to this; see below. ++ */ ++ if (req->work_scheduled) { ++ req->work_need_resched = true; ++ } else { ++ schedule_work(&req->work); ++ req->work_scheduled = true; ++ } ++ ++ /* ++ * If the waitqueue is being freed early but we can't complete ++ * the request inline, we have to tear down the request as best ++ * we can. That means immediately removing the request from its ++ * waitqueue and preventing all further accesses to the ++ * waitqueue via the request. We also need to schedule the ++ * completion work (done above). Also mark the request as ++ * cancelled, to potentially skip an unneeded call to ->poll(). ++ */ ++ if (mask & POLLFREE) { ++ WRITE_ONCE(req->cancelled, true); ++ list_del_init(&req->wait.entry); ++ ++ /* ++ * Careful: this *must* be the last step, since as soon ++ * as req->head is NULL'ed out, the request can be ++ * completed and freed, since aio_poll_complete_work() ++ * will no longer need to take the waitqueue lock. ++ */ ++ smp_store_release(&req->head, NULL); ++ } + } + return 1; + } +@@ -1712,6 +1814,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, + struct aio_poll_table { + struct poll_table_struct pt; + struct aio_kiocb *iocb; ++ bool queued; + int error; + }; + +@@ -1722,11 +1825,12 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head, + struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt); + + /* multiple wait queues per file are not supported */ +- if (unlikely(pt->iocb->poll.head)) { ++ if (unlikely(pt->queued)) { + pt->error = -EINVAL; + return; + } + ++ pt->queued = true; + pt->error = 0; + pt->iocb->poll.head = head; + add_wait_queue(head, &pt->iocb->poll.wait); +@@ -1751,12 +1855,14 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) + req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP; + + req->head = NULL; +- req->done = false; + req->cancelled = false; ++ req->work_scheduled = false; ++ req->work_need_resched = false; + + apt.pt._qproc = aio_poll_queue_proc; + apt.pt._key = req->events; + apt.iocb = aiocb; ++ apt.queued = false; + apt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */ + + /* initialized the list so that we can do list_empty checks */ +@@ -1765,23 +1871,35 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) + + mask = vfs_poll(req->file, &apt.pt) & req->events; + spin_lock_irq(&ctx->ctx_lock); +- if (likely(req->head)) { +- spin_lock(&req->head->lock); +- if (unlikely(list_empty(&req->wait.entry))) { +- if (apt.error) ++ if (likely(apt.queued)) { ++ bool on_queue = poll_iocb_lock_wq(req); ++ ++ if (!on_queue || req->work_scheduled) { ++ /* ++ * aio_poll_wake() already either scheduled the async ++ * completion work, or completed the request inline. ++ */ ++ if (apt.error) /* unsupported case: multiple queues */ + cancel = true; + apt.error = 0; + mask = 0; + } + if (mask || apt.error) { ++ /* Steal to complete synchronously. */ + list_del_init(&req->wait.entry); + } else if (cancel) { ++ /* Cancel if possible (may be too late though). */ + WRITE_ONCE(req->cancelled, true); +- } else if (!req->done) { /* actually waiting for an event */ ++ } else if (on_queue) { ++ /* ++ * Actually waiting for an event, so add the request to ++ * active_reqs so that it can be cancelled if needed. ++ */ + list_add_tail(&aiocb->ki_list, &ctx->active_reqs); + aiocb->ki_cancel = aio_poll_cancel; + } +- spin_unlock(&req->head->lock); ++ if (on_queue) ++ poll_iocb_unlock_wq(req); + } + if (mask) { /* no async, we'd stolen it */ + aiocb->ki_res.res = mangle_poll(mask); +diff --git a/fs/attr.c b/fs/attr.c +index 473d21b3a86de..66899b6e9bd86 100644 +--- a/fs/attr.c ++++ b/fs/attr.c +@@ -35,7 +35,7 @@ static bool chown_ok(struct user_namespace *mnt_userns, + kuid_t uid) + { + kuid_t kuid = i_uid_into_mnt(mnt_userns, inode); +- if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, kuid)) ++ if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, inode->i_uid)) + return true; + if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN)) + return true; +@@ -62,7 +62,7 @@ static bool chgrp_ok(struct user_namespace *mnt_userns, + { + kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); + if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode)) && +- (in_group_p(gid) || gid_eq(gid, kgid))) ++ (in_group_p(gid) || gid_eq(gid, inode->i_gid))) + return true; + if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN)) + return true; +diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c +index 309516e6a9682..43c89952b7d25 100644 +--- a/fs/btrfs/async-thread.c ++++ b/fs/btrfs/async-thread.c +@@ -234,6 +234,13 @@ static void run_ordered_work(struct __btrfs_workqueue *wq, + ordered_list); + if (!test_bit(WORK_DONE_BIT, &work->flags)) + break; ++ /* ++ * Orders all subsequent loads after reading WORK_DONE_BIT, ++ * paired with the smp_mb__before_atomic in btrfs_work_helper ++ * this guarantees that the ordered function will see all ++ * updates from ordinary work function. ++ */ ++ smp_rmb(); + + /* + * we are going to call the ordered done function, but +@@ -317,6 +324,13 @@ static void btrfs_work_helper(struct work_struct *normal_work) + thresh_exec_hook(wq); + work->func(work); + if (need_order) { ++ /* ++ * Ensures all memory accesses done in the work function are ++ * ordered before setting the WORK_DONE_BIT. Ensuring the thread ++ * which is going to executed the ordered work sees them. ++ * Pairs with the smp_rmb in run_ordered_work. ++ */ ++ smp_mb__before_atomic(); + set_bit(WORK_DONE_BIT, &work->flags); + run_ordered_work(wq, work); + } else { +diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c +index f735b8798ba12..8b090c40daf77 100644 +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -1214,7 +1214,12 @@ again: + ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0); + if (ret < 0) + goto out; +- BUG_ON(ret == 0); ++ if (ret == 0) { ++ /* This shouldn't happen, indicates a bug or fs corruption. */ ++ ASSERT(ret != 0); ++ ret = -EUCLEAN; ++ goto out; ++ } + + #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS + if (trans && likely(trans->type != __TRANS_DUMMY) && +@@ -1360,10 +1365,18 @@ again: + goto out; + if (!ret && extent_item_pos) { + /* +- * we've recorded that parent, so we must extend +- * its inode list here ++ * We've recorded that parent, so we must extend ++ * its inode list here. ++ * ++ * However if there was corruption we may not ++ * have found an eie, return an error in this ++ * case. + */ +- BUG_ON(!eie); ++ ASSERT(eie); ++ if (!eie) { ++ ret = -EUCLEAN; ++ goto out; ++ } + while (eie->next) + eie = eie->next; + eie->next = ref->inode_list; +diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c +index a3b830b8410a8..d721c66d0b41b 100644 +--- a/fs/btrfs/block-group.c ++++ b/fs/btrfs/block-group.c +@@ -902,6 +902,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, + spin_unlock(&cluster->refill_lock); + + btrfs_clear_treelog_bg(block_group); ++ btrfs_clear_data_reloc_bg(block_group); + + path = btrfs_alloc_path(); + if (!path) { +@@ -2510,6 +2511,19 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache, + int ret; + bool dirty_bg_running; + ++ /* ++ * This can only happen when we are doing read-only scrub on read-only ++ * mount. ++ * In that case we should not start a new transaction on read-only fs. ++ * Thus here we skip all chunk allocations. ++ */ ++ if (sb_rdonly(fs_info->sb)) { ++ mutex_lock(&fs_info->ro_block_group_mutex); ++ ret = inc_block_group_ro(cache, 0); ++ mutex_unlock(&fs_info->ro_block_group_mutex); ++ return ret; ++ } ++ + do { + trans = btrfs_join_transaction(fs_info->extent_root); + if (IS_ERR(trans)) +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 84627cbd5b5b5..95a6a63caf047 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1568,12 +1568,9 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct extent_buffer *b; +- int root_lock; ++ int root_lock = 0; + int level = 0; + +- /* We try very hard to do read locks on the root */ +- root_lock = BTRFS_READ_LOCK; +- + if (p->search_commit_root) { + /* + * The commit roots are read only so we always do read locks, +@@ -1611,6 +1608,9 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, + goto out; + } + ++ /* We try very hard to do read locks on the root */ ++ root_lock = BTRFS_READ_LOCK; ++ + /* + * If the level is set to maximum, we can skip trying to get the read + * lock. +@@ -1637,6 +1637,17 @@ static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, + level = btrfs_header_level(b); + + out: ++ /* ++ * The root may have failed to write out at some point, and thus is no ++ * longer valid, return an error in this case. ++ */ ++ if (!extent_buffer_uptodate(b)) { ++ if (root_lock) ++ btrfs_tree_unlock_rw(b, root_lock); ++ free_extent_buffer(b); ++ return ERR_PTR(-EIO); ++ } ++ + p->nodes[level] = b; + if (!p->skip_locking) + p->locks[level] = root_lock; +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index c0cebcf745cef..b46409801647b 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -593,6 +593,9 @@ enum { + /* Indicate whether there are any tree modification log users */ + BTRFS_FS_TREE_MOD_LOG_USERS, + ++ /* Indicate we have half completed snapshot deletions pending. */ ++ BTRFS_FS_UNFINISHED_DROPS, ++ + #if BITS_PER_LONG == 32 + /* Indicate if we have error/warn message printed on 32bit systems */ + BTRFS_FS_32BIT_ERROR, +@@ -1017,6 +1020,13 @@ struct btrfs_fs_info { + spinlock_t treelog_bg_lock; + u64 treelog_bg; + ++ /* ++ * Start of the dedicated data relocation block group, protected by ++ * relocation_bg_lock. ++ */ ++ spinlock_t relocation_bg_lock; ++ u64 data_reloc_bg; ++ + #ifdef CONFIG_BTRFS_FS_REF_VERIFY + spinlock_t ref_verify_lock; + struct rb_root block_tree; +@@ -1091,8 +1101,15 @@ enum { + BTRFS_ROOT_HAS_LOG_TREE, + /* Qgroup flushing is in progress */ + BTRFS_ROOT_QGROUP_FLUSHING, ++ /* This root has a drop operation that was started previously. */ ++ BTRFS_ROOT_UNFINISHED_DROP, + }; + ++static inline void btrfs_wake_unfinished_drop(struct btrfs_fs_info *fs_info) ++{ ++ clear_and_wake_up_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags); ++} ++ + /* + * Record swapped tree blocks of a subvolume tree for delayed subtree trace + * code. For detail check comment in fs/btrfs/qgroup.c. +@@ -3842,6 +3859,11 @@ static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info) + return fs_info->zoned != 0; + } + ++static inline bool btrfs_is_data_reloc_root(const struct btrfs_root *root) ++{ ++ return root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID; ++} ++ + /* + * We use page status Private2 to indicate there is an ordered extent with + * unfinished IO. +diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c +index 2059d1504149a..40c4d6ba3fb9a 100644 +--- a/fs/btrfs/delalloc-space.c ++++ b/fs/btrfs/delalloc-space.c +@@ -143,10 +143,13 @@ int btrfs_check_data_free_space(struct btrfs_inode *inode, + + /* Use new btrfs_qgroup_reserve_data to reserve precious data space. */ + ret = btrfs_qgroup_reserve_data(inode, reserved, start, len); +- if (ret < 0) ++ if (ret < 0) { + btrfs_free_reserved_data_space_noquota(fs_info, len); +- else ++ extent_changeset_free(*reserved); ++ *reserved = NULL; ++ } else { + ret = 0; ++ } + return ret; + } + +@@ -452,8 +455,11 @@ int btrfs_delalloc_reserve_space(struct btrfs_inode *inode, + if (ret < 0) + return ret; + ret = btrfs_delalloc_reserve_metadata(inode, len); +- if (ret < 0) ++ if (ret < 0) { + btrfs_free_reserved_data_space(inode, *reserved, start, len); ++ extent_changeset_free(*reserved); ++ *reserved = NULL; ++ } + return ret; + } + +diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c +index d029be40ea6f0..bdbc310a8f8c5 100644 +--- a/fs/btrfs/dev-replace.c ++++ b/fs/btrfs/dev-replace.c +@@ -325,7 +325,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, + set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE); + device->fs_devices = fs_info->fs_devices; + +- ret = btrfs_get_dev_zone_info(device); ++ ret = btrfs_get_dev_zone_info(device, false); + if (ret) + goto error; + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 355ea88d5c5f7..2180fcef56cab 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1500,7 +1500,7 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev) + goto fail; + + if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID && +- root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { ++ !btrfs_is_data_reloc_root(root)) { + set_bit(BTRFS_ROOT_SHAREABLE, &root->state); + btrfs_check_and_init_root_item(&root->root_item); + } +@@ -1731,6 +1731,14 @@ again: + } + return root; + fail: ++ /* ++ * If our caller provided us an anonymous device, then it's his ++ * responsability to free it in case we fail. So we have to set our ++ * root's anon_dev to 0 to avoid a double free, once by btrfs_put_root() ++ * and once again by our caller. ++ */ ++ if (anon_dev) ++ root->anon_dev = 0; + btrfs_put_root(root); + return ERR_PTR(ret); + } +@@ -2883,6 +2891,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info) + spin_lock_init(&fs_info->buffer_lock); + spin_lock_init(&fs_info->unused_bgs_lock); + spin_lock_init(&fs_info->treelog_bg_lock); ++ spin_lock_init(&fs_info->relocation_bg_lock); + rwlock_init(&fs_info->tree_mod_log_lock); + mutex_init(&fs_info->unused_bg_unpin_mutex); + mutex_init(&fs_info->reclaim_bgs_lock); +@@ -3228,12 +3237,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); + btrfs_init_btree_inode(fs_info); + +- invalidate_bdev(fs_devices->latest_bdev); ++ invalidate_bdev(fs_devices->latest_dev->bdev); + + /* + * Read super block and check the signature bytes only + */ +- disk_super = btrfs_read_dev_super(fs_devices->latest_bdev); ++ disk_super = btrfs_read_dev_super(fs_devices->latest_dev->bdev); + if (IS_ERR(disk_super)) { + err = PTR_ERR(disk_super); + goto fail_alloc; +@@ -3465,7 +3474,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + * below in btrfs_init_dev_replace(). + */ + btrfs_free_extra_devids(fs_devices); +- if (!fs_devices->latest_bdev) { ++ if (!fs_devices->latest_dev->bdev) { + btrfs_err(fs_info, "failed to read devices"); + goto fail_tree_roots; + } +@@ -3556,7 +3565,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + goto fail_sysfs; + } + +- if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info, NULL)) { ++ btrfs_free_zone_cache(fs_info); ++ ++ if (!sb_rdonly(sb) && fs_info->fs_devices->missing_devices && ++ !btrfs_check_rw_degradable(fs_info, NULL)) { + btrfs_warn(fs_info, + "writable mount is not allowed due to too many missing devices"); + goto fail_sysfs; +@@ -3647,6 +3659,10 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + + set_bit(BTRFS_FS_OPEN, &fs_info->flags); + ++ /* Kick the cleaner thread so it'll start deleting snapshots. */ ++ if (test_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags)) ++ wake_up_process(fs_info->cleaner_kthread); ++ + clear_oneshot: + btrfs_clear_oneshot_options(fs_info); + return 0; +@@ -3968,11 +3984,23 @@ static void btrfs_end_empty_barrier(struct bio *bio) + */ + static void write_dev_flush(struct btrfs_device *device) + { +- struct request_queue *q = bdev_get_queue(device->bdev); + struct bio *bio = device->flush_bio; + ++#ifndef CONFIG_BTRFS_FS_CHECK_INTEGRITY ++ /* ++ * When a disk has write caching disabled, we skip submission of a bio ++ * with flush and sync requests before writing the superblock, since ++ * it's not needed. However when the integrity checker is enabled, this ++ * results in reports that there are metadata blocks referred by a ++ * superblock that were not properly flushed. So don't skip the bio ++ * submission only when the integrity checker is enabled for the sake ++ * of simplicity, since this is a debug tool and not meant for use in ++ * non-debug builds. ++ */ ++ struct request_queue *q = bdev_get_queue(device->bdev); + if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) + return; ++#endif + + bio_reset(bio); + bio->bi_end_io = btrfs_end_empty_barrier; +@@ -4316,6 +4344,12 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) + */ + kthread_park(fs_info->cleaner_kthread); + ++ /* ++ * If we had UNFINISHED_DROPS we could still be processing them, so ++ * clear that bit and wake up relocation so it can stop. ++ */ ++ btrfs_wake_unfinished_drop(fs_info); ++ + /* wait for the qgroup rescan worker to stop */ + btrfs_qgroup_wait_for_completion(fs_info, false); + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 0ab456cb4bf80..514adc83577f0 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2376,7 +2376,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset, + + out: + btrfs_free_path(path); +- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) ++ if (btrfs_is_data_reloc_root(root)) + WARN_ON(ret > 0); + return ret; + } +@@ -3495,6 +3495,9 @@ struct find_free_extent_ctl { + /* Allocation is called for tree-log */ + bool for_treelog; + ++ /* Allocation is called for data relocation */ ++ bool for_data_reloc; ++ + /* RAID index, converted from flags */ + int index; + +@@ -3756,6 +3759,7 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, + u64 avail; + u64 bytenr = block_group->start; + u64 log_bytenr; ++ u64 data_reloc_bytenr; + int ret = 0; + bool skip; + +@@ -3773,13 +3777,31 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, + if (skip) + return 1; + ++ /* ++ * Do not allow non-relocation blocks in the dedicated relocation block ++ * group, and vice versa. ++ */ ++ spin_lock(&fs_info->relocation_bg_lock); ++ data_reloc_bytenr = fs_info->data_reloc_bg; ++ if (data_reloc_bytenr && ++ ((ffe_ctl->for_data_reloc && bytenr != data_reloc_bytenr) || ++ (!ffe_ctl->for_data_reloc && bytenr == data_reloc_bytenr))) ++ skip = true; ++ spin_unlock(&fs_info->relocation_bg_lock); ++ if (skip) ++ return 1; ++ + spin_lock(&space_info->lock); + spin_lock(&block_group->lock); + spin_lock(&fs_info->treelog_bg_lock); ++ spin_lock(&fs_info->relocation_bg_lock); + + ASSERT(!ffe_ctl->for_treelog || + block_group->start == fs_info->treelog_bg || + fs_info->treelog_bg == 0); ++ ASSERT(!ffe_ctl->for_data_reloc || ++ block_group->start == fs_info->data_reloc_bg || ++ fs_info->data_reloc_bg == 0); + + if (block_group->ro) { + ret = 1; +@@ -3796,6 +3818,16 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, + goto out; + } + ++ /* ++ * Do not allow currently used block group to be the data relocation ++ * dedicated block group. ++ */ ++ if (ffe_ctl->for_data_reloc && !fs_info->data_reloc_bg && ++ (block_group->used || block_group->reserved)) { ++ ret = 1; ++ goto out; ++ } ++ + avail = block_group->length - block_group->alloc_offset; + if (avail < num_bytes) { + if (ffe_ctl->max_extent_size < avail) { +@@ -3813,6 +3845,9 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, + if (ffe_ctl->for_treelog && !fs_info->treelog_bg) + fs_info->treelog_bg = block_group->start; + ++ if (ffe_ctl->for_data_reloc && !fs_info->data_reloc_bg) ++ fs_info->data_reloc_bg = block_group->start; ++ + ffe_ctl->found_offset = start + block_group->alloc_offset; + block_group->alloc_offset += num_bytes; + spin_lock(&ctl->tree_lock); +@@ -3829,6 +3864,9 @@ static int do_allocation_zoned(struct btrfs_block_group *block_group, + out: + if (ret && ffe_ctl->for_treelog) + fs_info->treelog_bg = 0; ++ if (ret && ffe_ctl->for_data_reloc) ++ fs_info->data_reloc_bg = 0; ++ spin_unlock(&fs_info->relocation_bg_lock); + spin_unlock(&fs_info->treelog_bg_lock); + spin_unlock(&block_group->lock); + spin_unlock(&space_info->lock); +@@ -4085,6 +4123,12 @@ static int prepare_allocation(struct btrfs_fs_info *fs_info, + ffe_ctl->hint_byte = fs_info->treelog_bg; + spin_unlock(&fs_info->treelog_bg_lock); + } ++ if (ffe_ctl->for_data_reloc) { ++ spin_lock(&fs_info->relocation_bg_lock); ++ if (fs_info->data_reloc_bg) ++ ffe_ctl->hint_byte = fs_info->data_reloc_bg; ++ spin_unlock(&fs_info->relocation_bg_lock); ++ } + return 0; + default: + BUG(); +@@ -4129,6 +4173,8 @@ static noinline int find_free_extent(struct btrfs_root *root, + struct btrfs_space_info *space_info; + bool full_search = false; + bool for_treelog = (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); ++ bool for_data_reloc = (btrfs_is_data_reloc_root(root) && ++ flags & BTRFS_BLOCK_GROUP_DATA); + + WARN_ON(num_bytes < fs_info->sectorsize); + +@@ -4143,6 +4189,7 @@ static noinline int find_free_extent(struct btrfs_root *root, + ffe_ctl.found_offset = 0; + ffe_ctl.hint_byte = hint_byte_orig; + ffe_ctl.for_treelog = for_treelog; ++ ffe_ctl.for_data_reloc = for_data_reloc; + ffe_ctl.policy = BTRFS_EXTENT_ALLOC_CLUSTERED; + + /* For clustered allocation */ +@@ -4220,6 +4267,8 @@ search: + if (unlikely(block_group->ro)) { + if (for_treelog) + btrfs_clear_treelog_bg(block_group); ++ if (ffe_ctl.for_data_reloc) ++ btrfs_clear_data_reloc_bg(block_group); + continue; + } + +@@ -4408,6 +4457,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes, + u64 flags; + int ret; + bool for_treelog = (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID); ++ bool for_data_reloc = (btrfs_is_data_reloc_root(root) && is_data); + + flags = get_alloc_profile_by_root(root, is_data); + again: +@@ -4431,8 +4481,8 @@ again: + + sinfo = btrfs_find_space_info(fs_info, flags); + btrfs_err(fs_info, +- "allocation failed flags %llu, wanted %llu tree-log %d", +- flags, num_bytes, for_treelog); ++ "allocation failed flags %llu, wanted %llu tree-log %d, relocation: %d", ++ flags, num_bytes, for_treelog, for_data_reloc); + if (sinfo) + btrfs_dump_space_info(fs_info, sinfo, + num_bytes, 1); +@@ -5491,6 +5541,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc) + int ret; + int level; + bool root_dropped = false; ++ bool unfinished_drop = false; + + btrfs_debug(fs_info, "Drop subvolume %llu", root->root_key.objectid); + +@@ -5533,6 +5584,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc) + * already dropped. + */ + set_bit(BTRFS_ROOT_DELETING, &root->state); ++ unfinished_drop = test_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state); ++ + if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { + level = btrfs_header_level(root->node); + path->nodes[level] = btrfs_lock_root_node(root); +@@ -5707,6 +5760,13 @@ out_free: + kfree(wc); + btrfs_free_path(path); + out: ++ /* ++ * We were an unfinished drop root, check to see if there are any ++ * pending, and if not clear and wake up any waiters. ++ */ ++ if (!err && unfinished_drop) ++ btrfs_maybe_wake_unfinished_drop(fs_info); ++ + /* + * So if we need to stop dropping the snapshot for whatever reason we + * need to make sure to add it back to the dead root list so that we +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index aaddd72253481..50a5cc4fd25b8 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -3327,7 +3327,7 @@ static int alloc_new_bio(struct btrfs_inode *inode, + if (wbc) { + struct block_device *bdev; + +- bdev = fs_info->fs_devices->latest_bdev; ++ bdev = fs_info->fs_devices->latest_dev->bdev; + bio_set_dev(bio, bdev); + wbc_init_bio(wbc, bio); + } +@@ -4284,6 +4284,12 @@ static void set_btree_ioerr(struct page *page, struct extent_buffer *eb) + if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) + return; + ++ /* ++ * A read may stumble upon this buffer later, make sure that it gets an ++ * error and knows there was an error. ++ */ ++ clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); ++ + /* + * If we error out, we should add back the dirty_metadata_bytes + * to make it consistent. +@@ -5120,6 +5126,9 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end, + int extent_writepages(struct address_space *mapping, + struct writeback_control *wbc) + { ++ struct inode *inode = mapping->host; ++ const bool data_reloc = btrfs_is_data_reloc_root(BTRFS_I(inode)->root); ++ const bool zoned = btrfs_is_zoned(BTRFS_I(inode)->root->fs_info); + int ret = 0; + struct extent_page_data epd = { + .bio_ctrl = { 0 }, +@@ -5127,7 +5136,15 @@ int extent_writepages(struct address_space *mapping, + .sync_io = wbc->sync_mode == WB_SYNC_ALL, + }; + ++ /* ++ * Allow only a single thread to do the reloc work in zoned mode to ++ * protect the write pointer updates. ++ */ ++ if (data_reloc && zoned) ++ btrfs_inode_lock(inode, 0); + ret = extent_write_cache_pages(mapping, wbc, &epd); ++ if (data_reloc && zoned) ++ btrfs_inode_unlock(inode, 0); + ASSERT(ret <= 0); + if (ret < 0) { + end_write_bio(&epd, ret); +@@ -6530,6 +6547,14 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num) + if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) + return 0; + ++ /* ++ * We could have had EXTENT_BUFFER_UPTODATE cleared by the write ++ * operation, which could potentially still be in flight. In this case ++ * we simply want to return an error. ++ */ ++ if (unlikely(test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))) ++ return -EIO; ++ + if (eb->fs_info->sectorsize < PAGE_SIZE) + return read_extent_buffer_subpage(eb, wait, mirror_num); + +@@ -6776,14 +6801,24 @@ static void assert_eb_page_uptodate(const struct extent_buffer *eb, + { + struct btrfs_fs_info *fs_info = eb->fs_info; + ++ /* ++ * If we are using the commit root we could potentially clear a page ++ * Uptodate while we're using the extent buffer that we've previously ++ * looked up. We don't want to complain in this case, as the page was ++ * valid before, we just didn't write it out. Instead we want to catch ++ * the case where we didn't actually read the block properly, which ++ * would have !PageUptodate && !PageError, as we clear PageError before ++ * reading. ++ */ + if (fs_info->sectorsize < PAGE_SIZE) { +- bool uptodate; ++ bool uptodate, error; + + uptodate = btrfs_subpage_test_uptodate(fs_info, page, + eb->start, eb->len); +- WARN_ON(!uptodate); ++ error = btrfs_subpage_test_error(fs_info, page, eb->start, eb->len); ++ WARN_ON(!uptodate && !error); + } else { +- WARN_ON(!PageUptodate(page)); ++ WARN_ON(!PageUptodate(page) && !PageError(page)); + } + } + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 7c096ab9bb5eb..58053b5f0ce19 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -60,8 +60,6 @@ struct btrfs_iget_args { + }; + + struct btrfs_dio_data { +- u64 reserve; +- loff_t length; + ssize_t submitted; + struct extent_changeset *data_reserved; + }; +@@ -1151,7 +1149,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, + * fails during the stage where it updates the bytenr of file extent + * items. + */ +- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) ++ if (btrfs_is_data_reloc_root(root)) + min_alloc_size = num_bytes; + else + min_alloc_size = fs_info->sectorsize; +@@ -1187,8 +1185,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, + if (ret) + goto out_drop_extent_cache; + +- if (root->root_key.objectid == +- BTRFS_DATA_RELOC_TREE_OBJECTID) { ++ if (btrfs_is_data_reloc_root(root)) { + ret = btrfs_reloc_clone_csums(inode, start, + cur_alloc_size); + /* +@@ -1504,8 +1501,7 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page, + int *page_started, unsigned long *nr_written) + { + const bool is_space_ino = btrfs_is_free_space_inode(inode); +- const bool is_reloc_ino = (inode->root->root_key.objectid == +- BTRFS_DATA_RELOC_TREE_OBJECTID); ++ const bool is_reloc_ino = btrfs_is_data_reloc_root(inode->root); + const u64 range_bytes = end + 1 - start; + struct extent_io_tree *io_tree = &inode->io_tree; + u64 range_start = start; +@@ -1867,8 +1863,7 @@ out_check: + btrfs_dec_nocow_writers(fs_info, disk_bytenr); + nocow = false; + +- if (root->root_key.objectid == +- BTRFS_DATA_RELOC_TREE_OBJECTID) ++ if (btrfs_is_data_reloc_root(root)) + /* + * Error handled later, as we must prevent + * extent_clear_unlock_delalloc() in error handler +@@ -1948,7 +1943,15 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page + const bool zoned = btrfs_is_zoned(inode->root->fs_info); + + if (should_nocow(inode, start, end)) { +- ASSERT(!zoned); ++ /* ++ * Normally on a zoned device we're only doing COW writes, but ++ * in case of relocation on a zoned filesystem we have taken ++ * precaution, that we're only writing sequentially. It's safe ++ * to use run_delalloc_nocow() here, like for regular ++ * preallocated inodes. ++ */ ++ ASSERT(!zoned || ++ (zoned && btrfs_is_data_reloc_root(inode->root))); + ret = run_delalloc_nocow(inode, locked_page, start, end, + page_started, nr_written); + } else if (!inode_can_compress(inode) || +@@ -2207,7 +2210,7 @@ void btrfs_clear_delalloc_extent(struct inode *vfs_inode, + if (btrfs_is_testing(fs_info)) + return; + +- if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID && ++ if (!btrfs_is_data_reloc_root(root) && + do_list && !(state->state & EXTENT_NORESERVE) && + (*bits & EXTENT_CLEAR_DATA_RESV)) + btrfs_free_reserved_data_space_noquota(fs_info, len); +@@ -2532,7 +2535,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio, + goto mapit; + } else if (async && !skip_sum) { + /* csum items have already been cloned */ +- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) ++ if (btrfs_is_data_reloc_root(root)) + goto mapit; + /* we're doing a write, do the async checksumming */ + ret = btrfs_wq_submit_bio(inode, bio, mirror_num, bio_flags, +@@ -3304,7 +3307,7 @@ unsigned int btrfs_verify_data_csum(struct btrfs_io_bio *io_bio, u32 bio_offset, + u64 file_offset = pg_off + page_offset(page); + int ret; + +- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && ++ if (btrfs_is_data_reloc_root(root) && + test_range_bit(io_tree, file_offset, + file_offset + sectorsize - 1, + EXTENT_NODATASUM, 1, NULL)) { +@@ -4005,7 +4008,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, + * without delay + */ + if (!btrfs_is_free_space_inode(inode) +- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID ++ && !btrfs_is_data_reloc_root(root) + && !test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) { + btrfs_update_root_times(trans, root); + +@@ -7758,6 +7761,10 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map, + { + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); + struct extent_map *em = *map; ++ int type; ++ u64 block_start, orig_start, orig_block_len, ram_bytes; ++ bool can_nocow = false; ++ bool space_reserved = false; + int ret = 0; + + /* +@@ -7772,9 +7779,6 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map, + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) || + ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && + em->block_start != EXTENT_MAP_HOLE)) { +- int type; +- u64 block_start, orig_start, orig_block_len, ram_bytes; +- + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) + type = BTRFS_ORDERED_PREALLOC; + else +@@ -7784,53 +7788,92 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map, + + if (can_nocow_extent(inode, start, &len, &orig_start, + &orig_block_len, &ram_bytes, false) == 1 && +- btrfs_inc_nocow_writers(fs_info, block_start)) { +- struct extent_map *em2; ++ btrfs_inc_nocow_writers(fs_info, block_start)) ++ can_nocow = true; ++ } ++ ++ if (can_nocow) { ++ struct extent_map *em2; + +- em2 = btrfs_create_dio_extent(BTRFS_I(inode), start, len, +- orig_start, block_start, +- len, orig_block_len, +- ram_bytes, type); ++ /* We can NOCOW, so only need to reserve metadata space. */ ++ ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), len); ++ if (ret < 0) { ++ /* Our caller expects us to free the input extent map. */ ++ free_extent_map(em); ++ *map = NULL; + btrfs_dec_nocow_writers(fs_info, block_start); +- if (type == BTRFS_ORDERED_PREALLOC) { +- free_extent_map(em); +- *map = em = em2; +- } ++ goto out; ++ } ++ space_reserved = true; + +- if (em2 && IS_ERR(em2)) { +- ret = PTR_ERR(em2); +- goto out; +- } +- /* +- * For inode marked NODATACOW or extent marked PREALLOC, +- * use the existing or preallocated extent, so does not +- * need to adjust btrfs_space_info's bytes_may_use. +- */ +- btrfs_free_reserved_data_space_noquota(fs_info, len); +- goto skip_cow; ++ em2 = btrfs_create_dio_extent(BTRFS_I(inode), start, len, ++ orig_start, block_start, ++ len, orig_block_len, ++ ram_bytes, type); ++ btrfs_dec_nocow_writers(fs_info, block_start); ++ if (type == BTRFS_ORDERED_PREALLOC) { ++ free_extent_map(em); ++ *map = em = em2; + } +- } + +- /* this will cow the extent */ +- free_extent_map(em); +- *map = em = btrfs_new_extent_direct(BTRFS_I(inode), start, len); +- if (IS_ERR(em)) { +- ret = PTR_ERR(em); +- goto out; ++ if (IS_ERR(em2)) { ++ ret = PTR_ERR(em2); ++ goto out; ++ } ++ } else { ++ const u64 prev_len = len; ++ ++ /* Our caller expects us to free the input extent map. */ ++ free_extent_map(em); ++ *map = NULL; ++ ++ /* We have to COW, so need to reserve metadata and data space. */ ++ ret = btrfs_delalloc_reserve_space(BTRFS_I(inode), ++ &dio_data->data_reserved, ++ start, len); ++ if (ret < 0) ++ goto out; ++ space_reserved = true; ++ ++ em = btrfs_new_extent_direct(BTRFS_I(inode), start, len); ++ if (IS_ERR(em)) { ++ ret = PTR_ERR(em); ++ goto out; ++ } ++ *map = em; ++ len = min(len, em->len - (start - em->start)); ++ if (len < prev_len) ++ btrfs_delalloc_release_space(BTRFS_I(inode), ++ dio_data->data_reserved, ++ start + len, prev_len - len, ++ true); + } + +- len = min(len, em->len - (start - em->start)); ++ /* ++ * We have created our ordered extent, so we can now release our reservation ++ * for an outstanding extent. ++ */ ++ btrfs_delalloc_release_extents(BTRFS_I(inode), len); + +-skip_cow: + /* + * Need to update the i_size under the extent lock so buffered + * readers will get the updated i_size when we unlock. + */ + if (start + len > i_size_read(inode)) + i_size_write(inode, start + len); +- +- dio_data->reserve -= len; + out: ++ if (ret && space_reserved) { ++ btrfs_delalloc_release_extents(BTRFS_I(inode), len); ++ if (can_nocow) { ++ btrfs_delalloc_release_metadata(BTRFS_I(inode), len, true); ++ } else { ++ btrfs_delalloc_release_space(BTRFS_I(inode), ++ dio_data->data_reserved, ++ start, len, true); ++ extent_changeset_free(dio_data->data_reserved); ++ dio_data->data_reserved = NULL; ++ } ++ } + return ret; + } + +@@ -7872,18 +7915,6 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start, + if (!dio_data) + return -ENOMEM; + +- dio_data->length = length; +- if (write) { +- dio_data->reserve = round_up(length, fs_info->sectorsize); +- ret = btrfs_delalloc_reserve_space(BTRFS_I(inode), +- &dio_data->data_reserved, +- start, dio_data->reserve); +- if (ret) { +- extent_changeset_free(dio_data->data_reserved); +- kfree(dio_data); +- return ret; +- } +- } + iomap->private = dio_data; + + +@@ -7962,7 +7993,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start, + iomap->type = IOMAP_MAPPED; + } + iomap->offset = start; +- iomap->bdev = fs_info->fs_devices->latest_bdev; ++ iomap->bdev = fs_info->fs_devices->latest_dev->bdev; + iomap->length = len; + + if (write && btrfs_use_zone_append(BTRFS_I(inode), em->block_start)) +@@ -7976,14 +8007,8 @@ unlock_err: + unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, + &cached_state); + err: +- if (dio_data) { +- btrfs_delalloc_release_space(BTRFS_I(inode), +- dio_data->data_reserved, start, +- dio_data->reserve, true); +- btrfs_delalloc_release_extents(BTRFS_I(inode), dio_data->reserve); +- extent_changeset_free(dio_data->data_reserved); +- kfree(dio_data); +- } ++ kfree(dio_data); ++ + return ret; + } + +@@ -8013,14 +8038,8 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length, + ret = -ENOTBLK; + } + +- if (write) { +- if (dio_data->reserve) +- btrfs_delalloc_release_space(BTRFS_I(inode), +- dio_data->data_reserved, pos, +- dio_data->reserve, true); +- btrfs_delalloc_release_extents(BTRFS_I(inode), dio_data->length); ++ if (write) + extent_changeset_free(dio_data->data_reserved); +- } + out: + kfree(dio_data); + iomap->private = NULL; +@@ -10581,9 +10600,19 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis, + struct btrfs_swap_info *bsi) + { + unsigned long nr_pages; ++ unsigned long max_pages; + u64 first_ppage, first_ppage_reported, next_ppage; + int ret; + ++ /* ++ * Our swapfile may have had its size extended after the swap header was ++ * written. In that case activating the swapfile should not go beyond ++ * the max size set in the swap header. ++ */ ++ if (bsi->nr_pages >= sis->max) ++ return 0; ++ ++ max_pages = sis->max - bsi->nr_pages; + first_ppage = ALIGN(bsi->block_start, PAGE_SIZE) >> PAGE_SHIFT; + next_ppage = ALIGN_DOWN(bsi->block_start + bsi->block_len, + PAGE_SIZE) >> PAGE_SHIFT; +@@ -10591,6 +10620,7 @@ static int btrfs_add_swap_extent(struct swap_info_struct *sis, + if (first_ppage >= next_ppage) + return 0; + nr_pages = next_ppage - first_ppage; ++ nr_pages = min(nr_pages, max_pages); + + first_ppage_reported = first_ppage; + if (bsi->start == 0) +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index cc61813213d83..6a863b3f6de03 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -775,10 +775,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, + goto fail; + } + +- spin_lock(&fs_info->trans_lock); +- list_add(&pending_snapshot->list, +- &trans->transaction->pending_snapshots); +- spin_unlock(&fs_info->trans_lock); ++ trans->pending_snapshot = pending_snapshot; + + ret = btrfs_commit_transaction(trans); + if (ret) +@@ -3098,10 +3095,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, + btrfs_inode_lock(inode, 0); + err = btrfs_delete_subvolume(dir, dentry); + btrfs_inode_unlock(inode, 0); +- if (!err) { +- fsnotify_rmdir(dir, dentry); +- d_delete(dentry); +- } ++ if (!err) ++ d_delete_notify(dir, dentry); + + out_dput: + dput(dentry); +diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c +index 3dbe6eb5fda75..fcd7eb496478c 100644 +--- a/fs/btrfs/lzo.c ++++ b/fs/btrfs/lzo.c +@@ -357,11 +357,23 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) + ASSERT(cur_in / sectorsize == + (cur_in + LZO_LEN - 1) / sectorsize); + cur_page = cb->compressed_pages[cur_in / PAGE_SIZE]; +- kaddr = kmap(cur_page); + ASSERT(cur_page); ++ kaddr = kmap(cur_page); + seg_len = read_compress_length(kaddr + offset_in_page(cur_in)); ++ kunmap(cur_page); + cur_in += LZO_LEN; + ++ if (seg_len > lzo1x_worst_compress(PAGE_SIZE)) { ++ /* ++ * seg_len shouldn't be larger than we have allocated ++ * for workspace->cbuf ++ */ ++ btrfs_err(fs_info, "unexpectedly large lzo segment len %u", ++ seg_len); ++ ret = -EIO; ++ goto out; ++ } ++ + /* Copy the compressed segment payload into workspace */ + copy_compressed_segment(cb, workspace->cbuf, seg_len, &cur_in); + +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index db680f5be745a..2c803108ea944 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -940,6 +940,14 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info) + int ret = 0; + int slot; + ++ /* ++ * We need to have subvol_sem write locked, to prevent races between ++ * concurrent tasks trying to enable quotas, because we will unlock ++ * and relock qgroup_ioctl_lock before setting fs_info->quota_root ++ * and before setting BTRFS_FS_QUOTA_ENABLED. ++ */ ++ lockdep_assert_held_write(&fs_info->subvol_sem); ++ + mutex_lock(&fs_info->qgroup_ioctl_lock); + if (fs_info->quota_root) + goto out; +@@ -1117,8 +1125,19 @@ out_add_root: + goto out_free_path; + } + ++ mutex_unlock(&fs_info->qgroup_ioctl_lock); ++ /* ++ * Commit the transaction while not holding qgroup_ioctl_lock, to avoid ++ * a deadlock with tasks concurrently doing other qgroup operations, such ++ * adding/removing qgroups or adding/deleting qgroup relations for example, ++ * because all qgroup operations first start or join a transaction and then ++ * lock the qgroup_ioctl_lock mutex. ++ * We are safe from a concurrent task trying to enable quotas, by calling ++ * this function, since we are serialized by fs_info->subvol_sem. ++ */ + ret = btrfs_commit_transaction(trans); + trans = NULL; ++ mutex_lock(&fs_info->qgroup_ioctl_lock); + if (ret) + goto out_free_path; + +@@ -1166,11 +1185,33 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + struct btrfs_trans_handle *trans = NULL; + int ret = 0; + ++ /* ++ * We need to have subvol_sem write locked, to prevent races between ++ * concurrent tasks trying to disable quotas, because we will unlock ++ * and relock qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes. ++ */ ++ lockdep_assert_held_write(&fs_info->subvol_sem); ++ + mutex_lock(&fs_info->qgroup_ioctl_lock); + if (!fs_info->quota_root) + goto out; ++ ++ /* ++ * Unlock the qgroup_ioctl_lock mutex before waiting for the rescan worker to ++ * complete. Otherwise we can deadlock because btrfs_remove_qgroup() needs ++ * to lock that mutex while holding a transaction handle and the rescan ++ * worker needs to commit a transaction. ++ */ + mutex_unlock(&fs_info->qgroup_ioctl_lock); + ++ /* ++ * Request qgroup rescan worker to complete and wait for it. This wait ++ * must be done before transaction start for quota disable since it may ++ * deadlock with transaction by the qgroup rescan worker. ++ */ ++ clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); ++ btrfs_qgroup_wait_for_completion(fs_info, false); ++ + /* + * 1 For the root item + * +@@ -1186,14 +1227,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info) + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + trans = NULL; ++ set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); + goto out; + } + + if (!fs_info->quota_root) + goto out; + +- clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); +- btrfs_qgroup_wait_for_completion(fs_info, false); + spin_lock(&fs_info->qgroup_lock); + quota_root = fs_info->quota_root; + fs_info->quota_root = NULL; +@@ -3360,6 +3400,9 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid, + btrfs_warn(fs_info, + "qgroup rescan init failed, qgroup is not enabled"); + ret = -EINVAL; ++ } else if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) { ++ /* Quota disable is in progress */ ++ ret = -EBUSY; + } + + if (ret) { +diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c +index 9b0814318e726..c71e49782e86d 100644 +--- a/fs/btrfs/reflink.c ++++ b/fs/btrfs/reflink.c +@@ -649,7 +649,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len, + static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, + struct inode *dst, u64 dst_loff) + { +- int ret; ++ int ret = 0; + u64 i, tail_len, chunk_count; + struct btrfs_root *root_dst = BTRFS_I(dst)->root; + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 914d403b4415d..a050f9748fa7f 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -2852,31 +2852,6 @@ static noinline_for_stack int prealloc_file_extent_cluster( + if (ret) + return ret; + +- /* +- * On a zoned filesystem, we cannot preallocate the file region. +- * Instead, we dirty and fiemap_write the region. +- */ +- if (btrfs_is_zoned(inode->root->fs_info)) { +- struct btrfs_root *root = inode->root; +- struct btrfs_trans_handle *trans; +- +- end = cluster->end - offset + 1; +- trans = btrfs_start_transaction(root, 1); +- if (IS_ERR(trans)) +- return PTR_ERR(trans); +- +- inode->vfs_inode.i_ctime = current_time(&inode->vfs_inode); +- i_size_write(&inode->vfs_inode, end); +- ret = btrfs_update_inode(trans, root, inode); +- if (ret) { +- btrfs_abort_transaction(trans, ret); +- btrfs_end_transaction(trans); +- return ret; +- } +- +- return btrfs_end_transaction(trans); +- } +- + btrfs_inode_lock(&inode->vfs_inode, 0); + for (nr = 0; nr < cluster->nr; nr++) { + start = cluster->boundary[nr] - offset; +@@ -3084,7 +3059,6 @@ release_page: + static int relocate_file_extent_cluster(struct inode *inode, + struct file_extent_cluster *cluster) + { +- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); + u64 offset = BTRFS_I(inode)->index_cnt; + unsigned long index; + unsigned long last_index; +@@ -3114,8 +3088,6 @@ static int relocate_file_extent_cluster(struct inode *inode, + for (index = (cluster->start - offset) >> PAGE_SHIFT; + index <= last_index && !ret; index++) + ret = relocate_one_page(inode, ra, cluster, &cluster_nr, index); +- if (btrfs_is_zoned(fs_info) && !ret) +- ret = btrfs_wait_ordered_range(inode, 0, (u64)-1); + if (ret == 0) + WARN_ON(cluster_nr != cluster->nr); + out: +@@ -3770,12 +3742,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, + struct btrfs_path *path; + struct btrfs_inode_item *item; + struct extent_buffer *leaf; +- u64 flags = BTRFS_INODE_NOCOMPRESS | BTRFS_INODE_PREALLOC; + int ret; + +- if (btrfs_is_zoned(trans->fs_info)) +- flags &= ~BTRFS_INODE_PREALLOC; +- + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +@@ -3790,7 +3758,8 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, + btrfs_set_inode_generation(leaf, item, 1); + btrfs_set_inode_size(leaf, item, 0); + btrfs_set_inode_mode(leaf, item, S_IFREG | 0600); +- btrfs_set_inode_flags(leaf, item, flags); ++ btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS | ++ BTRFS_INODE_PREALLOC); + btrfs_mark_buffer_dirty(leaf); + out: + btrfs_free_path(path); +@@ -3998,6 +3967,19 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start) + int rw = 0; + int err = 0; + ++ /* ++ * This only gets set if we had a half-deleted snapshot on mount. We ++ * cannot allow relocation to start while we're still trying to clean up ++ * these pending deletions. ++ */ ++ ret = wait_on_bit(&fs_info->flags, BTRFS_FS_UNFINISHED_DROPS, TASK_INTERRUPTIBLE); ++ if (ret) ++ return ret; ++ ++ /* We may have been woken up by close_ctree, so bail if we're closing. */ ++ if (btrfs_fs_closing(fs_info)) ++ return -EINTR; ++ + bg = btrfs_lookup_block_group(fs_info, group_start); + if (!bg) + return -ENOENT; +@@ -4386,8 +4368,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, + if (!rc) + return 0; + +- BUG_ON(rc->stage == UPDATE_DATA_PTRS && +- root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID); ++ BUG_ON(rc->stage == UPDATE_DATA_PTRS && btrfs_is_data_reloc_root(root)); + + level = btrfs_header_level(buf); + if (btrfs_header_generation(buf) <= +diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c +index 702dc5441f039..1fa0e5e2e3505 100644 +--- a/fs/btrfs/root-tree.c ++++ b/fs/btrfs/root-tree.c +@@ -280,6 +280,21 @@ int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info) + + WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state)); + if (btrfs_root_refs(&root->root_item) == 0) { ++ struct btrfs_key drop_key; ++ ++ btrfs_disk_key_to_cpu(&drop_key, &root->root_item.drop_progress); ++ /* ++ * If we have a non-zero drop_progress then we know we ++ * made it partly through deleting this snapshot, and ++ * thus we need to make sure we block any balance from ++ * happening until this snapshot is completely dropped. ++ */ ++ if (drop_key.objectid != 0 || drop_key.type != 0 || ++ drop_key.offset != 0) { ++ set_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags); ++ set_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state); ++ } ++ + set_bit(BTRFS_ROOT_DEAD_TREE, &root->state); + btrfs_add_dead_root(root); + } +@@ -336,7 +351,8 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, + key.offset = ref_id; + again: + ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); +- BUG_ON(ret < 0); ++ if (ret < 0) ++ goto out; + if (ret == 0) { + leaf = path->nodes[0]; + ref = btrfs_item_ptr(leaf, path->slots[0], +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index 088641ba7a8e6..62f4bafbe54bb 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -73,8 +73,8 @@ struct scrub_page { + u64 physical_for_dev_replace; + atomic_t refs; + u8 mirror_num; +- int have_csum:1; +- int io_error:1; ++ unsigned int have_csum:1; ++ unsigned int io_error:1; + u8 csum[BTRFS_CSUM_SIZE]; + + struct scrub_recover *recover; +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index 72f9b865e8479..5612e8bf2ace4 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -4978,6 +4978,10 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) + lock_page(page); + if (!PageUptodate(page)) { + unlock_page(page); ++ btrfs_err(fs_info, ++ "send: IO error at offset %llu for inode %llu root %llu", ++ page_offset(page), sctx->cur_ino, ++ sctx->send_root->root_key.objectid); + put_page(page); + ret = -EIO; + break; +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index 537d90bf5d844..7f91d62c2225a 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -1705,7 +1705,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, + goto error_close_devices; + } + +- bdev = fs_devices->latest_bdev; ++ bdev = fs_devices->latest_dev->bdev; + s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | SB_NOSEC, + fs_info); + if (IS_ERR(s)) { +@@ -2463,30 +2463,16 @@ static int btrfs_unfreeze(struct super_block *sb) + static int btrfs_show_devname(struct seq_file *m, struct dentry *root) + { + struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb); +- struct btrfs_device *dev, *first_dev = NULL; + + /* +- * Lightweight locking of the devices. We should not need +- * device_list_mutex here as we only read the device data and the list +- * is protected by RCU. Even if a device is deleted during the list +- * traversals, we'll get valid data, the freeing callback will wait at +- * least until the rcu_read_unlock. ++ * There should be always a valid pointer in latest_dev, it may be stale ++ * for a short moment in case it's being deleted but still valid until ++ * the end of RCU grace period. + */ + rcu_read_lock(); +- list_for_each_entry_rcu(dev, &fs_info->fs_devices->devices, dev_list) { +- if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state)) +- continue; +- if (!dev->name) +- continue; +- if (!first_dev || dev->devid < first_dev->devid) +- first_dev = dev; +- } +- +- if (first_dev) +- seq_escape(m, rcu_str_deref(first_dev->name), " \t\n\\"); +- else +- WARN_ON(1); ++ seq_escape(m, rcu_str_deref(fs_info->fs_devices->latest_dev->name), " \t\n\\"); + rcu_read_unlock(); ++ + return 0; + } + +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 14b9fdc8aaa9a..9a6009108ea55 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -846,7 +846,37 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root) + static noinline void wait_for_commit(struct btrfs_transaction *commit, + const enum btrfs_trans_state min_state) + { +- wait_event(commit->commit_wait, commit->state >= min_state); ++ struct btrfs_fs_info *fs_info = commit->fs_info; ++ u64 transid = commit->transid; ++ bool put = false; ++ ++ while (1) { ++ wait_event(commit->commit_wait, commit->state >= min_state); ++ if (put) ++ btrfs_put_transaction(commit); ++ ++ if (min_state < TRANS_STATE_COMPLETED) ++ break; ++ ++ /* ++ * A transaction isn't really completed until all of the ++ * previous transactions are completed, but with fsync we can ++ * end up with SUPER_COMMITTED transactions before a COMPLETED ++ * transaction. Wait for those. ++ */ ++ ++ spin_lock(&fs_info->trans_lock); ++ commit = list_first_entry_or_null(&fs_info->trans_list, ++ struct btrfs_transaction, ++ list); ++ if (!commit || commit->transid > transid) { ++ spin_unlock(&fs_info->trans_lock); ++ break; ++ } ++ refcount_inc(&commit->use_count); ++ put = true; ++ spin_unlock(&fs_info->trans_lock); ++ } + } + + int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid) +@@ -1310,6 +1340,32 @@ again: + return 0; + } + ++/* ++ * If we had a pending drop we need to see if there are any others left in our ++ * dead roots list, and if not clear our bit and wake any waiters. ++ */ ++void btrfs_maybe_wake_unfinished_drop(struct btrfs_fs_info *fs_info) ++{ ++ /* ++ * We put the drop in progress roots at the front of the list, so if the ++ * first entry doesn't have UNFINISHED_DROP set we can wake everybody ++ * up. ++ */ ++ spin_lock(&fs_info->trans_lock); ++ if (!list_empty(&fs_info->dead_roots)) { ++ struct btrfs_root *root = list_first_entry(&fs_info->dead_roots, ++ struct btrfs_root, ++ root_list); ++ if (test_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state)) { ++ spin_unlock(&fs_info->trans_lock); ++ return; ++ } ++ } ++ spin_unlock(&fs_info->trans_lock); ++ ++ btrfs_wake_unfinished_drop(fs_info); ++} ++ + /* + * dead roots are old snapshots that need to be deleted. This allocates + * a dirty root struct and adds it into the list of dead roots that need to +@@ -1322,7 +1378,12 @@ void btrfs_add_dead_root(struct btrfs_root *root) + spin_lock(&fs_info->trans_lock); + if (list_empty(&root->root_list)) { + btrfs_grab_root(root); +- list_add_tail(&root->root_list, &fs_info->dead_roots); ++ ++ /* We want to process the partially complete drops first. */ ++ if (test_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state)) ++ list_add(&root->root_list, &fs_info->dead_roots); ++ else ++ list_add_tail(&root->root_list, &fs_info->dead_roots); + } + spin_unlock(&fs_info->trans_lock); + } +@@ -2014,16 +2075,24 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans) + static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info) + { + /* +- * We use writeback_inodes_sb here because if we used ++ * We use try_to_writeback_inodes_sb() here because if we used + * btrfs_start_delalloc_roots we would deadlock with fs freeze. + * Currently are holding the fs freeze lock, if we do an async flush + * we'll do btrfs_join_transaction() and deadlock because we need to + * wait for the fs freeze lock. Using the direct flushing we benefit + * from already being in a transaction and our join_transaction doesn't + * have to re-take the fs freeze lock. ++ * ++ * Note that try_to_writeback_inodes_sb() will only trigger writeback ++ * if it can read lock sb->s_umount. It will always be able to lock it, ++ * except when the filesystem is being unmounted or being frozen, but in ++ * those cases sync_filesystem() is called, which results in calling ++ * writeback_inodes_sb() while holding a write lock on sb->s_umount. ++ * Note that we don't call writeback_inodes_sb() directly, because it ++ * will emit a warning if sb->s_umount is not locked. + */ + if (btrfs_test_opt(fs_info, FLUSHONCOMMIT)) +- writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC); ++ try_to_writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC); + return 0; + } + +@@ -2033,6 +2102,27 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info) + btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); + } + ++/* ++ * Add a pending snapshot associated with the given transaction handle to the ++ * respective handle. This must be called after the transaction commit started ++ * and while holding fs_info->trans_lock. ++ * This serves to guarantee a caller of btrfs_commit_transaction() that it can ++ * safely free the pending snapshot pointer in case btrfs_commit_transaction() ++ * returns an error. ++ */ ++static void add_pending_snapshot(struct btrfs_trans_handle *trans) ++{ ++ struct btrfs_transaction *cur_trans = trans->transaction; ++ ++ if (!trans->pending_snapshot) ++ return; ++ ++ lockdep_assert_held(&trans->fs_info->trans_lock); ++ ASSERT(cur_trans->state >= TRANS_STATE_COMMIT_START); ++ ++ list_add(&trans->pending_snapshot->list, &cur_trans->pending_snapshots); ++} ++ + int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + { + struct btrfs_fs_info *fs_info = trans->fs_info; +@@ -2106,6 +2196,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + if (cur_trans->state >= TRANS_STATE_COMMIT_START) { + enum btrfs_trans_state want_state = TRANS_STATE_COMPLETED; + ++ add_pending_snapshot(trans); ++ + spin_unlock(&fs_info->trans_lock); + refcount_inc(&cur_trans->use_count); + +@@ -2196,6 +2288,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + * COMMIT_DOING so make sure to wait for num_writers to == 1 again. + */ + spin_lock(&fs_info->trans_lock); ++ add_pending_snapshot(trans); + cur_trans->state = TRANS_STATE_COMMIT_DOING; + spin_unlock(&fs_info->trans_lock); + wait_event(cur_trans->writer_wait, +diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h +index ba45065f94511..0ded32bbd001e 100644 +--- a/fs/btrfs/transaction.h ++++ b/fs/btrfs/transaction.h +@@ -123,6 +123,8 @@ struct btrfs_trans_handle { + struct btrfs_transaction *transaction; + struct btrfs_block_rsv *block_rsv; + struct btrfs_block_rsv *orig_rsv; ++ /* Set by a task that wants to create a snapshot. */ ++ struct btrfs_pending_snapshot *pending_snapshot; + refcount_t use_count; + unsigned int type; + /* +@@ -215,6 +217,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid); + + void btrfs_add_dead_root(struct btrfs_root *root); + int btrfs_defrag_root(struct btrfs_root *root); ++void btrfs_maybe_wake_unfinished_drop(struct btrfs_fs_info *fs_info); + int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root); + int btrfs_commit_transaction(struct btrfs_trans_handle *trans); + int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans); +diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c +index 7733e8ac0a698..51382d2be3d44 100644 +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -965,6 +965,7 @@ static int check_dev_item(struct extent_buffer *leaf, + struct btrfs_key *key, int slot) + { + struct btrfs_dev_item *ditem; ++ const u32 item_size = btrfs_item_size_nr(leaf, slot); + + if (unlikely(key->objectid != BTRFS_DEV_ITEMS_OBJECTID)) { + dev_item_err(leaf, slot, +@@ -972,6 +973,13 @@ static int check_dev_item(struct extent_buffer *leaf, + key->objectid, BTRFS_DEV_ITEMS_OBJECTID); + return -EUCLEAN; + } ++ ++ if (unlikely(item_size != sizeof(*ditem))) { ++ dev_item_err(leaf, slot, "invalid item size: has %u expect %zu", ++ item_size, sizeof(*ditem)); ++ return -EUCLEAN; ++ } ++ + ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); + if (unlikely(btrfs_device_id(leaf, ditem) != key->offset)) { + dev_item_err(leaf, slot, +@@ -1007,6 +1015,7 @@ static int check_inode_item(struct extent_buffer *leaf, + struct btrfs_inode_item *iitem; + u64 super_gen = btrfs_super_generation(fs_info->super_copy); + u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); ++ const u32 item_size = btrfs_item_size_nr(leaf, slot); + u32 mode; + int ret; + u32 flags; +@@ -1016,6 +1025,12 @@ static int check_inode_item(struct extent_buffer *leaf, + if (unlikely(ret < 0)) + return ret; + ++ if (unlikely(item_size != sizeof(*iitem))) { ++ generic_err(leaf, slot, "invalid item size: has %u expect %zu", ++ item_size, sizeof(*iitem)); ++ return -EUCLEAN; ++ } ++ + iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); + + /* Here we use super block generation + 1 to handle log tree */ +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index b415c5ec03ea0..8ef65073ce8ce 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1153,6 +1153,7 @@ again: + parent_objectid, victim_name, + victim_name_len); + if (ret < 0) { ++ kfree(victim_name); + return ret; + } else if (!ret) { + ret = -ENOENT; +@@ -1328,6 +1329,15 @@ again: + inode, name, namelen); + kfree(name); + iput(dir); ++ /* ++ * Whenever we need to check if a name exists or not, we ++ * check the subvolume tree. So after an unlink we must ++ * run delayed items, so that future checks for a name ++ * during log replay see that the name does not exists ++ * anymore. ++ */ ++ if (!ret) ++ ret = btrfs_run_delayed_items(trans); + if (ret) + goto out; + goto again; +@@ -1579,6 +1589,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, + */ + if (!ret && inode->i_nlink == 0) + inc_nlink(inode); ++ /* ++ * Whenever we need to check if a name exists or ++ * not, we check the subvolume tree. So after an ++ * unlink we must run delayed items, so that future ++ * checks for a name during log replay see that the ++ * name does not exists anymore. ++ */ ++ if (!ret) ++ ret = btrfs_run_delayed_items(trans); + } + if (ret < 0) + goto out; +@@ -2500,7 +2519,9 @@ again: + else { + ret = find_dir_range(log, path, dirid, key_type, + &range_start, &range_end); +- if (ret != 0) ++ if (ret < 0) ++ goto out; ++ else if (ret > 0) + break; + } + +@@ -2877,6 +2898,8 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, + path->nodes[*level]->len); + if (ret) + return ret; ++ btrfs_redirty_list_add(trans->transaction, ++ next); + } else { + if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) + clear_extent_buffer_dirty(next); +@@ -2957,6 +2980,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, + next->start, next->len); + if (ret) + goto out; ++ btrfs_redirty_list_add(trans->transaction, next); + } else { + if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) + clear_extent_buffer_dirty(next); +@@ -3410,8 +3434,6 @@ static void free_log_tree(struct btrfs_trans_handle *trans, + EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT); + extent_io_tree_release(&log->log_csum_range); + +- if (trans && log->node) +- btrfs_redirty_list_add(trans->transaction, log->node); + btrfs_put_root(log); + } + +@@ -4419,7 +4441,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, + + /* + * Log all prealloc extents beyond the inode's i_size to make sure we do not +- * lose them after doing a fast fsync and replaying the log. We scan the ++ * lose them after doing a full/fast fsync and replaying the log. We scan the + * subvolume's root instead of iterating the inode's extent map tree because + * otherwise we can log incorrect extent items based on extent map conversion. + * That can happen due to the fact that extent maps are merged when they +@@ -5204,6 +5226,7 @@ static int copy_inode_items_to_log(struct btrfs_trans_handle *trans, + struct btrfs_log_ctx *ctx, + bool *need_log_inode_item) + { ++ const u64 i_size = i_size_read(&inode->vfs_inode); + struct btrfs_root *root = inode->root; + int ins_start_slot = 0; + int ins_nr = 0; +@@ -5224,13 +5247,21 @@ again: + if (min_key->type > max_key->type) + break; + +- if (min_key->type == BTRFS_INODE_ITEM_KEY) ++ if (min_key->type == BTRFS_INODE_ITEM_KEY) { + *need_log_inode_item = false; +- +- if ((min_key->type == BTRFS_INODE_REF_KEY || +- min_key->type == BTRFS_INODE_EXTREF_KEY) && +- inode->generation == trans->transid && +- !recursive_logging) { ++ } else if (min_key->type == BTRFS_EXTENT_DATA_KEY && ++ min_key->offset >= i_size) { ++ /* ++ * Extents at and beyond eof are logged with ++ * btrfs_log_prealloc_extents(). ++ * Only regular files have BTRFS_EXTENT_DATA_KEY keys, ++ * and no keys greater than that, so bail out. ++ */ ++ break; ++ } else if ((min_key->type == BTRFS_INODE_REF_KEY || ++ min_key->type == BTRFS_INODE_EXTREF_KEY) && ++ inode->generation == trans->transid && ++ !recursive_logging) { + u64 other_ino = 0; + u64 other_parent = 0; + +@@ -5261,10 +5292,8 @@ again: + btrfs_release_path(path); + goto next_key; + } +- } +- +- /* Skip xattrs, we log them later with btrfs_log_all_xattrs() */ +- if (min_key->type == BTRFS_XATTR_ITEM_KEY) { ++ } else if (min_key->type == BTRFS_XATTR_ITEM_KEY) { ++ /* Skip xattrs, logged later with btrfs_log_all_xattrs() */ + if (ins_nr == 0) + goto next_slot; + ret = copy_items(trans, inode, dst_path, path, +@@ -5317,9 +5346,21 @@ next_key: + break; + } + } +- if (ins_nr) ++ if (ins_nr) { + ret = copy_items(trans, inode, dst_path, path, ins_start_slot, + ins_nr, inode_only, logged_isize); ++ if (ret) ++ return ret; ++ } ++ ++ if (inode_only == LOG_INODE_ALL && S_ISREG(inode->vfs_inode.i_mode)) { ++ /* ++ * Release the path because otherwise we might attempt to double ++ * lock the same leaf with btrfs_log_prealloc_extents() below. ++ */ ++ btrfs_release_path(path); ++ ret = btrfs_log_prealloc_extents(trans, inode, dst_path); ++ } + + return ret; + } +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index 2ec3b8ac8fa35..06a1a7c2254ce 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -14,6 +14,7 @@ + #include <linux/semaphore.h> + #include <linux/uuid.h> + #include <linux/list_sort.h> ++#include <linux/namei.h> + #include "misc.h" + #include "ctree.h" + #include "extent_map.h" +@@ -1091,7 +1092,7 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices) + list_for_each_entry(seed_dev, &fs_devices->seed_list, seed_list) + __btrfs_free_extra_devids(seed_dev, &latest_dev); + +- fs_devices->latest_bdev = latest_dev->bdev; ++ fs_devices->latest_dev = latest_dev; + + mutex_unlock(&uuid_mutex); + } +@@ -1122,8 +1123,10 @@ static void btrfs_close_one_device(struct btrfs_device *device) + if (device->devid == BTRFS_DEV_REPLACE_DEVID) + clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); + +- if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) ++ if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) { ++ clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); + fs_devices->missing_devices--; ++ } + + btrfs_close_bdev(device); + if (device->bdev) { +@@ -1222,7 +1225,7 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices, + return -EINVAL; + + fs_devices->opened = 1; +- fs_devices->latest_bdev = latest_dev->bdev; ++ fs_devices->latest_dev = latest_dev; + fs_devices->total_rw_bytes = 0; + fs_devices->chunk_alloc_policy = BTRFS_CHUNK_ALLOC_REGULAR; + fs_devices->read_policy = BTRFS_READ_POLICY_PID; +@@ -1363,8 +1366,10 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags, + + bytenr_orig = btrfs_sb_offset(0); + ret = btrfs_sb_log_location_bdev(bdev, 0, READ, &bytenr); +- if (ret) +- return ERR_PTR(ret); ++ if (ret) { ++ device = ERR_PTR(ret); ++ goto error_bdev_put; ++ } + + disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr_orig); + if (IS_ERR(disk_super)) { +@@ -1882,18 +1887,22 @@ out: + /* + * Function to update ctime/mtime for a given device path. + * Mainly used for ctime/mtime based probe like libblkid. ++ * ++ * We don't care about errors here, this is just to be kind to userspace. + */ +-static void update_dev_time(struct block_device *bdev) ++static void update_dev_time(const char *device_path) + { +- struct inode *inode = bdev->bd_inode; ++ struct path path; + struct timespec64 now; ++ int ret; + +- /* Shouldn't happen but just in case. */ +- if (!inode) ++ ret = kern_path(device_path, LOOKUP_FOLLOW, &path); ++ if (ret) + return; + +- now = current_time(inode); +- generic_update_time(inode, &now, S_MTIME | S_CTIME); ++ now = current_time(d_inode(path.dentry)); ++ inode_update_time(d_inode(path.dentry), &now, S_MTIME | S_CTIME); ++ path_put(&path); + } + + static int btrfs_rm_dev_item(struct btrfs_device *device) +@@ -1986,7 +1995,7 @@ static struct btrfs_device * btrfs_find_next_active_device( + } + + /* +- * Helper function to check if the given device is part of s_bdev / latest_bdev ++ * Helper function to check if the given device is part of s_bdev / latest_dev + * and replace it with the provided or the next active device, in the context + * where this function called, there should be always be another device (or + * this_dev) which is active. +@@ -2005,8 +2014,8 @@ void __cold btrfs_assign_next_active_device(struct btrfs_device *device, + (fs_info->sb->s_bdev == device->bdev)) + fs_info->sb->s_bdev = next_device->bdev; + +- if (fs_info->fs_devices->latest_bdev == device->bdev) +- fs_info->fs_devices->latest_bdev = next_device->bdev; ++ if (fs_info->fs_devices->latest_dev->bdev == device->bdev) ++ fs_info->fs_devices->latest_dev = next_device; + } + + /* +@@ -2069,7 +2078,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info, + btrfs_kobject_uevent(bdev, KOBJ_CHANGE); + + /* Update ctime/mtime for device path for libblkid */ +- update_dev_time(bdev); ++ update_dev_time(device_path); + } + + int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, +@@ -2081,8 +2090,11 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, + u64 num_devices; + int ret = 0; + +- mutex_lock(&uuid_mutex); +- ++ /* ++ * The device list in fs_devices is accessed without locks (neither ++ * uuid_mutex nor device_list_mutex) as it won't change on a mounted ++ * filesystem and another device rm cannot run. ++ */ + num_devices = btrfs_num_devices(fs_info); + + ret = btrfs_check_raid_min_devices(fs_info, num_devices - 1); +@@ -2126,11 +2138,9 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, + mutex_unlock(&fs_info->chunk_mutex); + } + +- mutex_unlock(&uuid_mutex); + ret = btrfs_shrink_device(device, 0); + if (!ret) + btrfs_reada_remove_dev(device); +- mutex_lock(&uuid_mutex); + if (ret) + goto error_undo; + +@@ -2217,7 +2227,6 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, + } + + out: +- mutex_unlock(&uuid_mutex); + return ret; + + error_undo: +@@ -2305,13 +2314,6 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev) + + mutex_unlock(&fs_devices->device_list_mutex); + +- /* +- * The update_dev_time() with in btrfs_scratch_superblocks() +- * may lead to a call to btrfs_show_devname() which will try +- * to hold device_list_mutex. And here this device +- * is already out of device list, so we don't have to hold +- * the device_list_mutex lock. +- */ + btrfs_scratch_superblocks(tgtdev->fs_info, tgtdev->bdev, + tgtdev->name->str); + +@@ -2594,7 +2596,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path + device->fs_info = fs_info; + device->bdev = bdev; + +- ret = btrfs_get_dev_zone_info(device); ++ ret = btrfs_get_dev_zone_info(device, false); + if (ret) + goto error_free_device; + +@@ -2627,6 +2629,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path + btrfs_abort_transaction(trans, ret); + goto error_trans; + } ++ btrfs_assign_next_active_device(fs_info->fs_devices->latest_dev, ++ device); + } + + device->fs_devices = fs_devices; +@@ -2733,7 +2737,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path + btrfs_forget_devices(device_path); + + /* Update ctime/mtime for blkid or udev */ +- update_dev_time(bdev); ++ update_dev_time(device_path); + + return ret; + +@@ -7481,6 +7485,19 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) + */ + fs_info->fs_devices->total_rw_bytes = 0; + ++ /* ++ * Lockdep complains about possible circular locking dependency between ++ * a disk's open_mutex (struct gendisk.open_mutex), the rw semaphores ++ * used for freeze procection of a fs (struct super_block.s_writers), ++ * which we take when starting a transaction, and extent buffers of the ++ * chunk tree if we call read_one_dev() while holding a lock on an ++ * extent buffer of the chunk tree. Since we are mounting the filesystem ++ * and at this point there can't be any concurrent task modifying the ++ * chunk tree, to keep it simple, just skip locking on the chunk tree. ++ */ ++ ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags)); ++ path->skip_locking = 1; ++ + /* + * Read all device items, and then all the chunk items. All + * device items are found before any chunk item (their object id +@@ -7506,10 +7523,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) + goto error; + break; + } +- /* +- * The nodes on level 1 are not locked but we don't need to do +- * that during mount time as nothing else can access the tree +- */ + node = path->nodes[1]; + if (node) { + if (last_ra_node != node->start) { +@@ -7537,7 +7550,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) + * requirement for chunk allocation, see the comment on + * top of btrfs_chunk_alloc() for details. + */ +- ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags)); + chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); + ret = read_one_chunk(&found_key, leaf, chunk); + if (ret) +diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h +index 2183361db614d..4db10d071d67f 100644 +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -246,7 +246,11 @@ struct btrfs_fs_devices { + /* Highest generation number of seen devices */ + u64 latest_generation; + +- struct block_device *latest_bdev; ++ /* ++ * The mount device or a device with highest generation after removal ++ * or replace. ++ */ ++ struct btrfs_device *latest_dev; + + /* all of the devices in the FS, protected by a mutex + * so we can safely walk it to write out the supers without +diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c +index 47af1ab3bf120..596b2148807d4 100644 +--- a/fs/btrfs/zoned.c ++++ b/fs/btrfs/zoned.c +@@ -4,6 +4,7 @@ + #include <linux/slab.h> + #include <linux/blkdev.h> + #include <linux/sched/mm.h> ++#include <linux/vmalloc.h> + #include "ctree.h" + #include "volumes.h" + #include "zoned.h" +@@ -195,6 +196,8 @@ static int emulate_report_zones(struct btrfs_device *device, u64 pos, + static int btrfs_get_dev_zones(struct btrfs_device *device, u64 pos, + struct blk_zone *zones, unsigned int *nr_zones) + { ++ struct btrfs_zoned_device_info *zinfo = device->zone_info; ++ u32 zno; + int ret; + + if (!*nr_zones) +@@ -206,6 +209,34 @@ static int btrfs_get_dev_zones(struct btrfs_device *device, u64 pos, + return 0; + } + ++ /* Check cache */ ++ if (zinfo->zone_cache) { ++ unsigned int i; ++ ++ ASSERT(IS_ALIGNED(pos, zinfo->zone_size)); ++ zno = pos >> zinfo->zone_size_shift; ++ /* ++ * We cannot report zones beyond the zone end. So, it is OK to ++ * cap *nr_zones to at the end. ++ */ ++ *nr_zones = min_t(u32, *nr_zones, zinfo->nr_zones - zno); ++ ++ for (i = 0; i < *nr_zones; i++) { ++ struct blk_zone *zone_info; ++ ++ zone_info = &zinfo->zone_cache[zno + i]; ++ if (!zone_info->len) ++ break; ++ } ++ ++ if (i == *nr_zones) { ++ /* Cache hit on all the zones */ ++ memcpy(zones, zinfo->zone_cache + zno, ++ sizeof(*zinfo->zone_cache) * *nr_zones); ++ return 0; ++ } ++ } ++ + ret = blkdev_report_zones(device->bdev, pos >> SECTOR_SHIFT, *nr_zones, + copy_zone_info_cb, zones); + if (ret < 0) { +@@ -219,6 +250,11 @@ static int btrfs_get_dev_zones(struct btrfs_device *device, u64 pos, + if (!ret) + return -EIO; + ++ /* Populate cache */ ++ if (zinfo->zone_cache) ++ memcpy(zinfo->zone_cache + zno, zones, ++ sizeof(*zinfo->zone_cache) * *nr_zones); ++ + return 0; + } + +@@ -282,7 +318,7 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) + if (!device->bdev) + continue; + +- ret = btrfs_get_dev_zone_info(device); ++ ret = btrfs_get_dev_zone_info(device, true); + if (ret) + break; + } +@@ -291,7 +327,7 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) + return ret; + } + +-int btrfs_get_dev_zone_info(struct btrfs_device *device) ++int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache) + { + struct btrfs_fs_info *fs_info = device->fs_info; + struct btrfs_zoned_device_info *zone_info = NULL; +@@ -318,6 +354,8 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) + if (!zone_info) + return -ENOMEM; + ++ device->zone_info = zone_info; ++ + if (!bdev_is_zoned(bdev)) { + if (!fs_info->zone_size) { + ret = calculate_emulated_zone_size(fs_info); +@@ -369,6 +407,23 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) + goto out; + } + ++ /* ++ * Enable zone cache only for a zoned device. On a non-zoned device, we ++ * fill the zone info with emulated CONVENTIONAL zones, so no need to ++ * use the cache. ++ */ ++ if (populate_cache && bdev_is_zoned(device->bdev)) { ++ zone_info->zone_cache = vzalloc(sizeof(struct blk_zone) * ++ zone_info->nr_zones); ++ if (!zone_info->zone_cache) { ++ btrfs_err_in_rcu(device->fs_info, ++ "zoned: failed to allocate zone cache for %s", ++ rcu_str_deref(device->name)); ++ ret = -ENOMEM; ++ goto out; ++ } ++ } ++ + /* Get zones type */ + while (sector < nr_sectors) { + nr_zones = BTRFS_REPORT_NR_ZONES; +@@ -444,8 +499,6 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) + + kfree(zones); + +- device->zone_info = zone_info; +- + switch (bdev_zoned_model(bdev)) { + case BLK_ZONED_HM: + model = "host-managed zoned"; +@@ -478,10 +531,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) + out: + kfree(zones); + out_free_zone_info: +- bitmap_free(zone_info->empty_zones); +- bitmap_free(zone_info->seq_zones); +- kfree(zone_info); +- device->zone_info = NULL; ++ btrfs_destroy_dev_zone_info(device); + + return ret; + } +@@ -495,6 +545,7 @@ void btrfs_destroy_dev_zone_info(struct btrfs_device *device) + + bitmap_free(zone_info->seq_zones); + bitmap_free(zone_info->empty_zones); ++ vfree(zone_info->zone_cache); + kfree(zone_info); + device->zone_info = NULL; + } +@@ -1304,6 +1355,17 @@ bool btrfs_use_zone_append(struct btrfs_inode *inode, u64 start) + if (!is_data_inode(&inode->vfs_inode)) + return false; + ++ /* ++ * Using REQ_OP_ZONE_APPNED for relocation can break assumptions on the ++ * extent layout the relocation code has. ++ * Furthermore we have set aside own block-group from which only the ++ * relocation "process" can allocate and make sure only one process at a ++ * time can add pages to an extent that gets relocated, so it's safe to ++ * use regular REQ_OP_WRITE for this special case. ++ */ ++ if (btrfs_is_data_reloc_root(inode->root)) ++ return false; ++ + cache = btrfs_lookup_block_group(fs_info, start); + ASSERT(cache); + if (!cache) +@@ -1530,3 +1592,31 @@ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info, + + return device; + } ++ ++void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) ++{ ++ struct btrfs_fs_info *fs_info = bg->fs_info; ++ ++ spin_lock(&fs_info->relocation_bg_lock); ++ if (fs_info->data_reloc_bg == bg->start) ++ fs_info->data_reloc_bg = 0; ++ spin_unlock(&fs_info->relocation_bg_lock); ++} ++ ++void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; ++ struct btrfs_device *device; ++ ++ if (!btrfs_is_zoned(fs_info)) ++ return; ++ ++ mutex_lock(&fs_devices->device_list_mutex); ++ list_for_each_entry(device, &fs_devices->devices, dev_list) { ++ if (device->zone_info) { ++ vfree(device->zone_info->zone_cache); ++ device->zone_info->zone_cache = NULL; ++ } ++ } ++ mutex_unlock(&fs_devices->device_list_mutex); ++} +diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h +index 4b299705bb12b..813aa3cddc11f 100644 +--- a/fs/btrfs/zoned.h ++++ b/fs/btrfs/zoned.h +@@ -25,6 +25,7 @@ struct btrfs_zoned_device_info { + u32 nr_zones; + unsigned long *seq_zones; + unsigned long *empty_zones; ++ struct blk_zone *zone_cache; + struct blk_zone sb_zones[2 * BTRFS_SUPER_MIRROR_MAX]; + }; + +@@ -32,7 +33,7 @@ struct btrfs_zoned_device_info { + int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, + struct blk_zone *zone); + int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info); +-int btrfs_get_dev_zone_info(struct btrfs_device *device); ++int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache); + void btrfs_destroy_dev_zone_info(struct btrfs_device *device); + int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info); + int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info); +@@ -66,6 +67,8 @@ int btrfs_sync_zone_write_pointer(struct btrfs_device *tgt_dev, u64 logical, + u64 physical_start, u64 physical_pos); + struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info, + u64 logical, u64 length); ++void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg); ++void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info); + #else /* CONFIG_BLK_DEV_ZONED */ + static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos, + struct blk_zone *zone) +@@ -78,7 +81,8 @@ static inline int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_i + return 0; + } + +-static inline int btrfs_get_dev_zone_info(struct btrfs_device *device) ++static inline int btrfs_get_dev_zone_info(struct btrfs_device *device, ++ bool populate_cache) + { + return 0; + } +@@ -199,6 +203,9 @@ static inline struct btrfs_device *btrfs_zoned_get_device( + return ERR_PTR(-EOPNOTSUPP); + } + ++static inline void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) { } ++ ++static inline void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info) { } + #endif + + static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos) +diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c +index 8f537f1d9d1d3..09900a9015ea6 100644 +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -2217,6 +2217,7 @@ static int unsafe_request_wait(struct inode *inode) + struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_request *req1 = NULL, *req2 = NULL; ++ unsigned int max_sessions; + int ret, err = 0; + + spin_lock(&ci->i_unsafe_lock); +@@ -2234,37 +2235,45 @@ static int unsafe_request_wait(struct inode *inode) + } + spin_unlock(&ci->i_unsafe_lock); + ++ /* ++ * The mdsc->max_sessions is unlikely to be changed ++ * mostly, here we will retry it by reallocating the ++ * sessions array memory to get rid of the mdsc->mutex ++ * lock. ++ */ ++retry: ++ max_sessions = mdsc->max_sessions; ++ + /* + * Trigger to flush the journal logs in all the relevant MDSes + * manually, or in the worst case we must wait at most 5 seconds + * to wait the journal logs to be flushed by the MDSes periodically. + */ +- if (req1 || req2) { ++ if ((req1 || req2) && likely(max_sessions)) { + struct ceph_mds_session **sessions = NULL; + struct ceph_mds_session *s; + struct ceph_mds_request *req; +- unsigned int max; + int i; + +- /* +- * The mdsc->max_sessions is unlikely to be changed +- * mostly, here we will retry it by reallocating the +- * sessions arrary memory to get rid of the mdsc->mutex +- * lock. +- */ +-retry: +- max = mdsc->max_sessions; +- sessions = krealloc(sessions, max * sizeof(s), __GFP_ZERO); +- if (!sessions) +- return -ENOMEM; ++ sessions = kzalloc(max_sessions * sizeof(s), GFP_KERNEL); ++ if (!sessions) { ++ err = -ENOMEM; ++ goto out; ++ } + + spin_lock(&ci->i_unsafe_lock); + if (req1) { + list_for_each_entry(req, &ci->i_unsafe_dirops, + r_unsafe_dir_item) { + s = req->r_session; +- if (unlikely(s->s_mds >= max)) { ++ if (unlikely(s->s_mds >= max_sessions)) { + spin_unlock(&ci->i_unsafe_lock); ++ for (i = 0; i < max_sessions; i++) { ++ s = sessions[i]; ++ if (s) ++ ceph_put_mds_session(s); ++ } ++ kfree(sessions); + goto retry; + } + if (!sessions[s->s_mds]) { +@@ -2277,8 +2286,14 @@ retry: + list_for_each_entry(req, &ci->i_unsafe_iops, + r_unsafe_target_item) { + s = req->r_session; +- if (unlikely(s->s_mds >= max)) { ++ if (unlikely(s->s_mds >= max_sessions)) { + spin_unlock(&ci->i_unsafe_lock); ++ for (i = 0; i < max_sessions; i++) { ++ s = sessions[i]; ++ if (s) ++ ceph_put_mds_session(s); ++ } ++ kfree(sessions); + goto retry; + } + if (!sessions[s->s_mds]) { +@@ -2299,7 +2314,7 @@ retry: + spin_unlock(&ci->i_ceph_lock); + + /* send flush mdlog request to MDSes */ +- for (i = 0; i < max; i++) { ++ for (i = 0; i < max_sessions; i++) { + s = sessions[i]; + if (s) { + send_flush_mdlog(s); +@@ -2316,15 +2331,19 @@ retry: + ceph_timeout_jiffies(req1->r_timeout)); + if (ret) + err = -EIO; +- ceph_mdsc_put_request(req1); + } + if (req2) { + ret = !wait_for_completion_timeout(&req2->r_safe_completion, + ceph_timeout_jiffies(req2->r_timeout)); + if (ret) + err = -EIO; +- ceph_mdsc_put_request(req2); + } ++ ++out: ++ if (req1) ++ ceph_mdsc_put_request(req1); ++ if (req2) ++ ceph_mdsc_put_request(req2); + return err; + } + +@@ -4349,7 +4368,7 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(ci->vfs_inode.i_sb); + int bits = (fmode << 1) | 1; +- bool is_opened = false; ++ bool already_opened = false; + int i; + + if (count == 1) +@@ -4357,19 +4376,19 @@ void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count) + + spin_lock(&ci->i_ceph_lock); + for (i = 0; i < CEPH_FILE_MODE_BITS; i++) { +- if (bits & (1 << i)) +- ci->i_nr_by_mode[i] += count; +- + /* +- * If any of the mode ref is larger than 1, ++ * If any of the mode ref is larger than 0, + * that means it has been already opened by + * others. Just skip checking the PIN ref. + */ +- if (i && ci->i_nr_by_mode[i] > 1) +- is_opened = true; ++ if (i && ci->i_nr_by_mode[i]) ++ already_opened = true; ++ ++ if (bits & (1 << i)) ++ ci->i_nr_by_mode[i] += count; + } + +- if (!is_opened) ++ if (!already_opened) + percpu_counter_inc(&mdsc->metric.opened_inodes); + spin_unlock(&ci->i_ceph_lock); + } +diff --git a/fs/ceph/file.c b/fs/ceph/file.c +index e61018d9764ee..6180df6f8e61e 100644 +--- a/fs/ceph/file.c ++++ b/fs/ceph/file.c +@@ -577,6 +577,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, + struct ceph_inode_info *ci = ceph_inode(dir); + struct inode *inode; + struct timespec64 now; ++ struct ceph_string *pool_ns; + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); + struct ceph_vino vino = { .ino = req->r_deleg_ino, + .snap = CEPH_NOSNAP }; +@@ -603,17 +604,35 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, + in.cap.realm = cpu_to_le64(ci->i_snap_realm->ino); + in.cap.flags = CEPH_CAP_FLAG_AUTH; + in.ctime = in.mtime = in.atime = iinfo.btime; +- in.mode = cpu_to_le32((u32)mode); + in.truncate_seq = cpu_to_le32(1); + in.truncate_size = cpu_to_le64(-1ULL); + in.xattr_version = cpu_to_le64(1); + in.uid = cpu_to_le32(from_kuid(&init_user_ns, current_fsuid())); +- in.gid = cpu_to_le32(from_kgid(&init_user_ns, dir->i_mode & S_ISGID ? +- dir->i_gid : current_fsgid())); ++ if (dir->i_mode & S_ISGID) { ++ in.gid = cpu_to_le32(from_kgid(&init_user_ns, dir->i_gid)); ++ ++ /* Directories always inherit the setgid bit. */ ++ if (S_ISDIR(mode)) ++ mode |= S_ISGID; ++ else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && ++ !in_group_p(dir->i_gid) && ++ !capable_wrt_inode_uidgid(&init_user_ns, dir, CAP_FSETID)) ++ mode &= ~S_ISGID; ++ } else { ++ in.gid = cpu_to_le32(from_kgid(&init_user_ns, current_fsgid())); ++ } ++ in.mode = cpu_to_le32((u32)mode); ++ + in.nlink = cpu_to_le32(1); + in.max_size = cpu_to_le64(lo->stripe_unit); + + ceph_file_layout_to_legacy(lo, &in.layout); ++ /* lo is private, so pool_ns can't change */ ++ pool_ns = rcu_dereference_raw(lo->pool_ns); ++ if (pool_ns) { ++ iinfo.pool_ns_len = pool_ns->len; ++ iinfo.pool_ns_data = pool_ns->str; ++ } + + down_read(&mdsc->snap_rwsem); + ret = ceph_fill_inode(inode, NULL, &iinfo, NULL, req->r_session, +@@ -732,8 +751,10 @@ retry: + restore_deleg_ino(dir, req->r_deleg_ino); + ceph_mdsc_put_request(req); + try_async = false; ++ ceph_put_string(rcu_dereference_raw(lo.pool_ns)); + goto retry; + } ++ ceph_put_string(rcu_dereference_raw(lo.pool_ns)); + goto out_req; + } + } +diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c +index d64413adc0fd2..e9409c460acd0 100644 +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -3772,7 +3772,7 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap, + struct ceph_pagelist *pagelist = recon_state->pagelist; + struct dentry *dentry; + char *path; +- int pathlen, err; ++ int pathlen = 0, err; + u64 pathbase; + u64 snap_follows; + +@@ -3792,7 +3792,6 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap, + } + } else { + path = NULL; +- pathlen = 0; + pathbase = 0; + } + +diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c +index 61d67cbcb3671..30387733765d5 100644 +--- a/fs/ceph/mdsmap.c ++++ b/fs/ceph/mdsmap.c +@@ -263,10 +263,6 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end, bool msgr2) + goto nomem; + for (j = 0; j < num_export_targets; j++) { + target = ceph_decode_32(&pexport_targets); +- if (target >= m->possible_max_rank) { +- err = -EIO; +- goto corrupt; +- } + info->export_targets[j] = target; + } + } else { +diff --git a/fs/ceph/super.c b/fs/ceph/super.c +index fd8742bae8471..202ddde3d62ad 100644 +--- a/fs/ceph/super.c ++++ b/fs/ceph/super.c +@@ -52,8 +52,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) + struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry)); + struct ceph_mon_client *monc = &fsc->client->monc; + struct ceph_statfs st; +- u64 fsid; +- int err; ++ int i, err; + u64 data_pool; + + if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) { +@@ -99,12 +98,14 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) + buf->f_namelen = NAME_MAX; + + /* Must convert the fsid, for consistent values across arches */ ++ buf->f_fsid.val[0] = 0; + mutex_lock(&monc->mutex); +- fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^ +- le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1)); ++ for (i = 0 ; i < sizeof(monc->monmap->fsid) / sizeof(__le32) ; ++i) ++ buf->f_fsid.val[0] ^= le32_to_cpu(((__le32 *)&monc->monmap->fsid)[i]); + mutex_unlock(&monc->mutex); + +- buf->f_fsid = u64_to_fsid(fsid); ++ /* fold the fs_cluster_id into the upper bits */ ++ buf->f_fsid.val[1] = monc->fs_cluster_id; + + return 0; + } +diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c +index de2c12bcfa4bc..248a8f973cf9c 100644 +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -358,6 +358,8 @@ skip_rdma: + seq_printf(m, " signed"); + if (server->posix_ext_supported) + seq_printf(m, " posix"); ++ if (server->nosharesock) ++ seq_printf(m, " nosharesock"); + + if (server->rdma) + seq_printf(m, "\nRDMA "); +@@ -412,12 +414,14 @@ skip_rdma: + from_kuid(&init_user_ns, ses->linux_uid), + from_kuid(&init_user_ns, ses->cred_uid)); + ++ spin_lock(&ses->chan_lock); + if (ses->chan_count > 1) { + seq_printf(m, "\n\n\tExtra Channels: %zu ", + ses->chan_count-1); + for (j = 1; j < ses->chan_count; j++) + cifs_dump_channel(m, j, &ses->chans[j]); + } ++ spin_unlock(&ses->chan_lock); + + seq_puts(m, "\n\n\tShares: "); + j = 0; +diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c +index ee3aab3dd4ac6..bf861fef2f0c3 100644 +--- a/fs/cifs/cifsacl.c ++++ b/fs/cifs/cifsacl.c +@@ -949,6 +949,9 @@ static void populate_new_aces(char *nacl_base, + pnntace = (struct cifs_ace *) (nacl_base + nsize); + nsize += setup_special_mode_ACE(pnntace, nmode); + num_aces++; ++ pnntace = (struct cifs_ace *) (nacl_base + nsize); ++ nsize += setup_authusers_ACE(pnntace); ++ num_aces++; + goto set_size; + } + +@@ -1297,7 +1300,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + + if (uid_valid(uid)) { /* chown */ + uid_t id; +- nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid), ++ nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid), + GFP_KERNEL); + if (!nowner_sid_ptr) { + rc = -ENOMEM; +@@ -1326,7 +1329,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, + } + if (gid_valid(gid)) { /* chgrp */ + gid_t id; +- ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid), ++ ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid), + GFP_KERNEL); + if (!ngroup_sid_ptr) { + rc = -ENOMEM; +@@ -1613,7 +1616,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode, + nsecdesclen = secdesclen; + if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */ + if (mode_from_sid) +- nsecdesclen += sizeof(struct cifs_ace); ++ nsecdesclen += 2 * sizeof(struct cifs_ace); + else /* cifsacl */ + nsecdesclen += 5 * sizeof(struct cifs_ace); + } else { /* chown */ +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index 9fa930dfd78d6..21bf82fc22783 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -909,6 +909,7 @@ cifs_smb3_do_mount(struct file_system_type *fs_type, + + out_super: + deactivate_locked_super(sb); ++ return root; + out: + if (cifs_sb) { + kfree(cifs_sb->prepath); +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index e916470468ea9..b33835b2943e9 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -74,7 +74,8 @@ + #define SMB_ECHO_INTERVAL_MAX 600 + #define SMB_ECHO_INTERVAL_DEFAULT 60 + +-/* dns resolution interval in seconds */ ++/* dns resolution intervals in seconds */ ++#define SMB_DNS_RESOLVE_INTERVAL_MIN 120 + #define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600 + + /* maximum number of PDUs in one compound */ +@@ -591,6 +592,7 @@ struct TCP_Server_Info { + struct list_head pending_mid_q; + bool noblocksnd; /* use blocking sendmsg */ + bool noautotune; /* do not autotune send buf sizes */ ++ bool nosharesock; + bool tcp_nodelay; + unsigned int credits; /* send no more requests at once */ + unsigned int max_credits; /* can override large 32000 default at mnt */ +@@ -932,16 +934,21 @@ struct cifs_ses { + * iface_lock should be taken when accessing any of these fields + */ + spinlock_t iface_lock; ++ /* ========= begin: protected by iface_lock ======== */ + struct cifs_server_iface *iface_list; + size_t iface_count; + unsigned long iface_last_update; /* jiffies */ ++ /* ========= end: protected by iface_lock ======== */ + ++ spinlock_t chan_lock; ++ /* ========= begin: protected by chan_lock ======== */ + #define CIFS_MAX_CHANNELS 16 + struct cifs_chan chans[CIFS_MAX_CHANNELS]; + struct cifs_chan *binding_chan; + size_t chan_count; + size_t chan_max; + atomic_t chan_seq; /* round robin state */ ++ /* ========= end: protected by chan_lock ======== */ + }; + + /* +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index c3b94c1e45913..70da1d27be3db 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -115,7 +115,7 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) + * To make sure we don't use the cached entry, retry 1s + * after expiry. + */ +- ttl = (expiry - now + 1); ++ ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1; + } + rc = !rc ? -1 : 0; + +@@ -794,7 +794,6 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) + */ + } + +- kfree(server->hostname); + kfree(server); + + length = atomic_dec_return(&tcpSesAllocCount); +@@ -1221,6 +1220,10 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context * + if (ctx->nosharesock) + return 0; + ++ /* this server does not share socket */ ++ if (server->nosharesock) ++ return 0; ++ + /* If multidialect negotiation see if existing sessions match one */ + if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { + if (server->vals->protocol_id < SMB30_PROT_ID) +@@ -1235,6 +1238,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context * + if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) + return 0; + ++ if (strcasecmp(server->hostname, ctx->server_hostname)) ++ return 0; ++ + if (!match_address(server, addr, + (struct sockaddr *)&ctx->srcaddr)) + return 0; +@@ -1336,6 +1342,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) + kfree(server->session_key.response); + server->session_key.response = NULL; + server->session_key.len = 0; ++ kfree(server->hostname); + + task = xchg(&server->tsk, NULL); + if (task) +@@ -1361,14 +1368,18 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx) + goto out_err; + } + ++ tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL); ++ if (!tcp_ses->hostname) { ++ rc = -ENOMEM; ++ goto out_err; ++ } ++ ++ if (ctx->nosharesock) ++ tcp_ses->nosharesock = true; ++ + tcp_ses->ops = ctx->ops; + tcp_ses->vals = ctx->vals; + cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); +- tcp_ses->hostname = extract_hostname(ctx->UNC); +- if (IS_ERR(tcp_ses->hostname)) { +- rc = PTR_ERR(tcp_ses->hostname); +- goto out_err_crypto_release; +- } + + tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId); + tcp_ses->noblockcnt = ctx->rootfs; +@@ -1497,8 +1508,7 @@ out_err_crypto_release: + + out_err: + if (tcp_ses) { +- if (!IS_ERR(tcp_ses->hostname)) +- kfree(tcp_ses->hostname); ++ kfree(tcp_ses->hostname); + if (tcp_ses->ssocket) + sock_release(tcp_ses->ssocket); + kfree(tcp_ses); +@@ -1516,8 +1526,12 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx) + * If an existing session is limited to less channels than + * requested, it should not be reused + */ +- if (ses->chan_max < ctx->max_channels) ++ spin_lock(&ses->chan_lock); ++ if (ses->chan_max < ctx->max_channels) { ++ spin_unlock(&ses->chan_lock); + return 0; ++ } ++ spin_unlock(&ses->chan_lock); + + switch (ses->sectype) { + case Kerberos: +@@ -1652,6 +1666,7 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) + void cifs_put_smb_ses(struct cifs_ses *ses) + { + unsigned int rc, xid; ++ unsigned int chan_count; + struct TCP_Server_Info *server = ses->server; + cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); + +@@ -1693,12 +1708,24 @@ void cifs_put_smb_ses(struct cifs_ses *ses) + list_del_init(&ses->smb_ses_list); + spin_unlock(&cifs_tcp_ses_lock); + ++ spin_lock(&ses->chan_lock); ++ chan_count = ses->chan_count; ++ spin_unlock(&ses->chan_lock); ++ + /* close any extra channels */ +- if (ses->chan_count > 1) { ++ if (chan_count > 1) { + int i; + +- for (i = 1; i < ses->chan_count; i++) ++ for (i = 1; i < chan_count; i++) { ++ /* ++ * note: for now, we're okay accessing ses->chans ++ * without chan_lock. But when chans can go away, we'll ++ * need to introduce ref counting to make sure that chan ++ * is not freed from under us. ++ */ + cifs_put_tcp_session(ses->chans[i].server, 0); ++ ses->chans[i].server = NULL; ++ } + } + + sesInfoFree(ses); +@@ -1949,9 +1976,11 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) + mutex_lock(&ses->session_mutex); + + /* add server as first channel */ ++ spin_lock(&ses->chan_lock); + ses->chans[0].server = server; + ses->chan_count = 1; + ses->chan_max = ctx->multichannel ? ctx->max_channels:1; ++ spin_unlock(&ses->chan_lock); + + rc = cifs_negotiate_protocol(xid, ses); + if (!rc) +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 13f3182cf7969..82bbaf8e92b79 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -2692,12 +2692,23 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, + tcon = tlink_tcon(smbfile->tlink); + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { + server = tcon->ses->server; +- if (server->ops->flush) +- rc = server->ops->flush(xid, tcon, &smbfile->fid); +- else ++ if (server->ops->flush == NULL) { + rc = -ENOSYS; ++ goto strict_fsync_exit; ++ } ++ ++ if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { ++ smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); ++ if (smbfile) { ++ rc = server->ops->flush(xid, tcon, &smbfile->fid); ++ cifsFileInfo_put(smbfile); ++ } else ++ cifs_dbg(FYI, "ignore fsync for file not open for write\n"); ++ } else ++ rc = server->ops->flush(xid, tcon, &smbfile->fid); + } + ++strict_fsync_exit: + free_xid(xid); + return rc; + } +@@ -2709,6 +2720,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) + struct cifs_tcon *tcon; + struct TCP_Server_Info *server; + struct cifsFileInfo *smbfile = file->private_data; ++ struct inode *inode = file_inode(file); + struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); + + rc = file_write_and_wait_range(file, start, end); +@@ -2725,12 +2737,23 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) + tcon = tlink_tcon(smbfile->tlink); + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { + server = tcon->ses->server; +- if (server->ops->flush) +- rc = server->ops->flush(xid, tcon, &smbfile->fid); +- else ++ if (server->ops->flush == NULL) { + rc = -ENOSYS; ++ goto fsync_exit; ++ } ++ ++ if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { ++ smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); ++ if (smbfile) { ++ rc = server->ops->flush(xid, tcon, &smbfile->fid); ++ cifsFileInfo_put(smbfile); ++ } else ++ cifs_dbg(FYI, "ignore fsync for file not open for write\n"); ++ } else ++ rc = server->ops->flush(xid, tcon, &smbfile->fid); + } + ++fsync_exit: + free_xid(xid); + return rc; + } +diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c +index 3109def8e1998..3b8ed36b37113 100644 +--- a/fs/cifs/fs_context.c ++++ b/fs/cifs/fs_context.c +@@ -146,7 +146,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { + fsparam_u32("echo_interval", Opt_echo_interval), + fsparam_u32("max_credits", Opt_max_credits), + fsparam_u32("handletimeout", Opt_handletimeout), +- fsparam_u32("snapshot", Opt_snapshot), ++ fsparam_u64("snapshot", Opt_snapshot), + fsparam_u32("max_channels", Opt_max_channels), + + /* Mount options which take string value */ +@@ -307,6 +307,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx + new_ctx->nodename = NULL; + new_ctx->username = NULL; + new_ctx->password = NULL; ++ new_ctx->server_hostname = NULL; + new_ctx->domainname = NULL; + new_ctx->UNC = NULL; + new_ctx->source = NULL; +@@ -318,6 +319,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx + DUP_CTX_STR(mount_options); + DUP_CTX_STR(username); + DUP_CTX_STR(password); ++ DUP_CTX_STR(server_hostname); + DUP_CTX_STR(UNC); + DUP_CTX_STR(source); + DUP_CTX_STR(domainname); +@@ -429,6 +431,42 @@ out: + return rc; + } + ++/* ++ * Remove duplicate path delimiters. Windows is supposed to do that ++ * but there are some bugs that prevent rename from working if there are ++ * multiple delimiters. ++ * ++ * Returns a sanitized duplicate of @path. The caller is responsible for ++ * cleaning up the original. ++ */ ++#define IS_DELIM(c) ((c) == '/' || (c) == '\\') ++static char *sanitize_path(char *path) ++{ ++ char *cursor1 = path, *cursor2 = path; ++ ++ /* skip all prepended delimiters */ ++ while (IS_DELIM(*cursor1)) ++ cursor1++; ++ ++ /* copy the first letter */ ++ *cursor2 = *cursor1; ++ ++ /* copy the remainder... */ ++ while (*(cursor1++)) { ++ /* ... skipping all duplicated delimiters */ ++ if (IS_DELIM(*cursor1) && IS_DELIM(*cursor2)) ++ continue; ++ *(++cursor2) = *cursor1; ++ } ++ ++ /* if the last character is a delimiter, skip it */ ++ if (IS_DELIM(*(cursor2 - 1))) ++ cursor2--; ++ ++ *(cursor2) = '\0'; ++ return kstrdup(path, GFP_KERNEL); ++} ++ + /* + * Parse a devname into substrings and populate the ctx->UNC and ctx->prepath + * fields with the result. Returns 0 on success and an error otherwise +@@ -456,6 +494,12 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) + if (!pos) + return -EINVAL; + ++ /* record the server hostname */ ++ kfree(ctx->server_hostname); ++ ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL); ++ if (!ctx->server_hostname) ++ return -ENOMEM; ++ + /* skip past delimiter */ + ++pos; + +@@ -482,7 +526,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) + if (!*pos) + return 0; + +- ctx->prepath = kstrdup(pos, GFP_KERNEL); ++ ctx->prepath = sanitize_path(pos); + if (!ctx->prepath) + return -ENOMEM; + +@@ -1018,7 +1062,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, + ctx->echo_interval = result.uint_32; + break; + case Opt_snapshot: +- ctx->snapshot_time = result.uint_32; ++ ctx->snapshot_time = result.uint_64; + break; + case Opt_max_credits: + if (result.uint_32 < 20 || result.uint_32 > 60000) { +@@ -1496,6 +1540,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) + ctx->username = NULL; + kfree_sensitive(ctx->password); + ctx->password = NULL; ++ kfree(ctx->server_hostname); ++ ctx->server_hostname = NULL; + kfree(ctx->UNC); + ctx->UNC = NULL; + kfree(ctx->source); +diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h +index a42ba71d7a81f..29601a4eb4116 100644 +--- a/fs/cifs/fs_context.h ++++ b/fs/cifs/fs_context.h +@@ -166,6 +166,7 @@ struct smb3_fs_context { + char *password; + char *domainname; + char *source; ++ char *server_hostname; + char *UNC; + char *nodename; + char *iocharset; /* local code page for mapping to and from Unicode */ +diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c +index bb1185fff8cc4..0a0d0724c4294 100644 +--- a/fs/cifs/misc.c ++++ b/fs/cifs/misc.c +@@ -75,6 +75,7 @@ sesInfoAlloc(void) + INIT_LIST_HEAD(&ret_buf->tcon_list); + mutex_init(&ret_buf->session_mutex); + spin_lock_init(&ret_buf->iface_lock); ++ spin_lock_init(&ret_buf->chan_lock); + } + return ret_buf; + } +diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c +index 23e02db7923f6..5500ea7837845 100644 +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -54,32 +54,43 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface) + { + int i; + ++ spin_lock(&ses->chan_lock); + for (i = 0; i < ses->chan_count; i++) { +- if (is_server_using_iface(ses->chans[i].server, iface)) ++ if (is_server_using_iface(ses->chans[i].server, iface)) { ++ spin_unlock(&ses->chan_lock); + return true; ++ } + } ++ spin_unlock(&ses->chan_lock); + return false; + } + + /* returns number of channels added */ + int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) + { +- int old_chan_count = ses->chan_count; +- int left = ses->chan_max - ses->chan_count; ++ int old_chan_count, new_chan_count; ++ int left; + int i = 0; + int rc = 0; + int tries = 0; + struct cifs_server_iface *ifaces = NULL; + size_t iface_count; + ++ spin_lock(&ses->chan_lock); ++ ++ new_chan_count = old_chan_count = ses->chan_count; ++ left = ses->chan_max - ses->chan_count; ++ + if (left <= 0) { + cifs_dbg(FYI, + "ses already at max_channels (%zu), nothing to open\n", + ses->chan_max); ++ spin_unlock(&ses->chan_lock); + return 0; + } + + if (ses->server->dialect < SMB30_PROT_ID) { ++ spin_unlock(&ses->chan_lock); + cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n"); + return 0; + } +@@ -87,8 +98,10 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) + if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { + cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname); + ses->chan_max = 1; ++ spin_unlock(&ses->chan_lock); + return 0; + } ++ spin_unlock(&ses->chan_lock); + + /* + * Make a copy of the iface list at the time and use that +@@ -142,10 +155,11 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) + cifs_dbg(FYI, "successfully opened new channel on iface#%d\n", + i); + left--; ++ new_chan_count++; + } + + kfree(ifaces); +- return ses->chan_count - old_chan_count; ++ return new_chan_count - old_chan_count; + } + + /* +@@ -157,10 +171,14 @@ cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server) + { + int i; + ++ spin_lock(&ses->chan_lock); + for (i = 0; i < ses->chan_count; i++) { +- if (ses->chans[i].server == server) ++ if (ses->chans[i].server == server) { ++ spin_unlock(&ses->chan_lock); + return &ses->chans[i]; ++ } + } ++ spin_unlock(&ses->chan_lock); + return NULL; + } + +@@ -168,6 +186,7 @@ static int + cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, + struct cifs_server_iface *iface) + { ++ struct TCP_Server_Info *chan_server; + struct cifs_chan *chan; + struct smb3_fs_context ctx = {NULL}; + static const char unc_fmt[] = "\\%s\\foo"; +@@ -240,15 +259,20 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, + SMB2_CLIENT_GUID_SIZE); + ctx.use_client_guid = true; + +- mutex_lock(&ses->session_mutex); ++ chan_server = cifs_get_tcp_session(&ctx); + ++ mutex_lock(&ses->session_mutex); ++ spin_lock(&ses->chan_lock); + chan = ses->binding_chan = &ses->chans[ses->chan_count]; +- chan->server = cifs_get_tcp_session(&ctx); ++ chan->server = chan_server; + if (IS_ERR(chan->server)) { + rc = PTR_ERR(chan->server); + chan->server = NULL; ++ spin_unlock(&ses->chan_lock); + goto out; + } ++ spin_unlock(&ses->chan_lock); ++ + spin_lock(&cifs_tcp_ses_lock); + chan->server->is_channel = true; + spin_unlock(&cifs_tcp_ses_lock); +@@ -283,8 +307,11 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, + * ses to the new server. + */ + ++ spin_lock(&ses->chan_lock); + ses->chan_count++; + atomic_set(&ses->chan_seq, 0); ++ spin_unlock(&ses->chan_lock); ++ + out: + ses->binding = false; + ses->binding_chan = NULL; +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index b7379329b741c..61ea3d3f95b4a 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -1044,14 +1044,17 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses) + if (!ses) + return NULL; + ++ spin_lock(&ses->chan_lock); + if (!ses->binding) { + /* round robin */ + if (ses->chan_count > 1) { + index = (uint)atomic_inc_return(&ses->chan_seq); + index %= ses->chan_count; + } ++ spin_unlock(&ses->chan_lock); + return ses->chans[index].server; + } else { ++ spin_unlock(&ses->chan_lock); + return cifs_ses_server(ses); + } + } +diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c +index 7d8b72d67c803..9d486fbbfbbde 100644 +--- a/fs/cifs/xattr.c ++++ b/fs/cifs/xattr.c +@@ -175,11 +175,13 @@ static int cifs_xattr_set(const struct xattr_handler *handler, + switch (handler->flags) { + case XATTR_CIFS_NTSD_FULL: + aclflags = (CIFS_ACL_OWNER | ++ CIFS_ACL_GROUP | + CIFS_ACL_DACL | + CIFS_ACL_SACL); + break; + case XATTR_CIFS_NTSD: + aclflags = (CIFS_ACL_OWNER | ++ CIFS_ACL_GROUP | + CIFS_ACL_DACL); + break; + case XATTR_CIFS_ACL: +diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c +index 1466b5d01cbb9..d1f9d26322027 100644 +--- a/fs/configfs/dir.c ++++ b/fs/configfs/dir.c +@@ -34,6 +34,14 @@ + */ + DEFINE_SPINLOCK(configfs_dirent_lock); + ++/* ++ * All of link_obj/unlink_obj/link_group/unlink_group require that ++ * subsys->su_mutex is held. ++ * But parent configfs_subsystem is NULL when config_item is root. ++ * Use this mutex when config_item is root. ++ */ ++static DEFINE_MUTEX(configfs_subsystem_mutex); ++ + static void configfs_d_iput(struct dentry * dentry, + struct inode * inode) + { +@@ -1780,8 +1788,8 @@ void configfs_unregister_group(struct config_group *group) + configfs_detach_group(&group->cg_item); + d_inode(dentry)->i_flags |= S_DEAD; + dont_mount(dentry); ++ d_drop(dentry); + fsnotify_rmdir(d_inode(parent), dentry); +- d_delete(dentry); + inode_unlock(d_inode(parent)); + + dput(dentry); +@@ -1859,7 +1867,9 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) + group->cg_item.ci_name = group->cg_item.ci_namebuf; + + sd = root->d_fsdata; ++ mutex_lock(&configfs_subsystem_mutex); + link_group(to_config_group(sd->s_element), group); ++ mutex_unlock(&configfs_subsystem_mutex); + + inode_lock_nested(d_inode(root), I_MUTEX_PARENT); + +@@ -1884,7 +1894,9 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) + inode_unlock(d_inode(root)); + + if (err) { ++ mutex_lock(&configfs_subsystem_mutex); + unlink_group(group); ++ mutex_unlock(&configfs_subsystem_mutex); + configfs_release_fs(); + } + put_fragment(frag); +@@ -1922,16 +1934,18 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys) + configfs_detach_group(&group->cg_item); + d_inode(dentry)->i_flags |= S_DEAD; + dont_mount(dentry); +- fsnotify_rmdir(d_inode(root), dentry); + inode_unlock(d_inode(dentry)); + +- d_delete(dentry); ++ d_drop(dentry); ++ fsnotify_rmdir(d_inode(root), dentry); + + inode_unlock(d_inode(root)); + + dput(dentry); + ++ mutex_lock(&configfs_subsystem_mutex); + unlink_group(group); ++ mutex_unlock(&configfs_subsystem_mutex); + configfs_release_fs(); + } + +diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h +index 3fa965eb3336d..cb25ef0cdf1f3 100644 +--- a/fs/crypto/fscrypt_private.h ++++ b/fs/crypto/fscrypt_private.h +@@ -549,8 +549,9 @@ int __init fscrypt_init_keyring(void); + struct fscrypt_mode { + const char *friendly_name; + const char *cipher_str; +- int keysize; +- int ivsize; ++ int keysize; /* key size in bytes */ ++ int security_strength; /* security strength in bytes */ ++ int ivsize; /* IV size in bytes */ + int logged_impl_name; + enum blk_crypto_mode_num blk_crypto_mode; + }; +diff --git a/fs/crypto/hkdf.c b/fs/crypto/hkdf.c +index e0ec210555053..7607d18b35fc0 100644 +--- a/fs/crypto/hkdf.c ++++ b/fs/crypto/hkdf.c +@@ -16,9 +16,14 @@ + + /* + * HKDF supports any unkeyed cryptographic hash algorithm, but fscrypt uses +- * SHA-512 because it is reasonably secure and efficient; and since it produces +- * a 64-byte digest, deriving an AES-256-XTS key preserves all 64 bytes of +- * entropy from the master key and requires only one iteration of HKDF-Expand. ++ * SHA-512 because it is well-established, secure, and reasonably efficient. ++ * ++ * HKDF-SHA256 was also considered, as its 256-bit security strength would be ++ * sufficient here. A 512-bit security strength is "nice to have", though. ++ * Also, on 64-bit CPUs, SHA-512 is usually just as fast as SHA-256. In the ++ * common case of deriving an AES-256-XTS key (512 bits), that can result in ++ * HKDF-SHA512 being much faster than HKDF-SHA256, as the longer digest size of ++ * SHA-512 causes HKDF-Expand to only need to do one iteration rather than two. + */ + #define HKDF_HMAC_ALG "hmac(sha512)" + #define HKDF_HASHLEN SHA512_DIGEST_SIZE +diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c +index bca9c6658a7c5..89cd533a88bff 100644 +--- a/fs/crypto/keysetup.c ++++ b/fs/crypto/keysetup.c +@@ -19,6 +19,7 @@ struct fscrypt_mode fscrypt_modes[] = { + .friendly_name = "AES-256-XTS", + .cipher_str = "xts(aes)", + .keysize = 64, ++ .security_strength = 32, + .ivsize = 16, + .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_256_XTS, + }, +@@ -26,12 +27,14 @@ struct fscrypt_mode fscrypt_modes[] = { + .friendly_name = "AES-256-CTS-CBC", + .cipher_str = "cts(cbc(aes))", + .keysize = 32, ++ .security_strength = 32, + .ivsize = 16, + }, + [FSCRYPT_MODE_AES_128_CBC] = { + .friendly_name = "AES-128-CBC-ESSIV", + .cipher_str = "essiv(cbc(aes),sha256)", + .keysize = 16, ++ .security_strength = 16, + .ivsize = 16, + .blk_crypto_mode = BLK_ENCRYPTION_MODE_AES_128_CBC_ESSIV, + }, +@@ -39,12 +42,14 @@ struct fscrypt_mode fscrypt_modes[] = { + .friendly_name = "AES-128-CTS-CBC", + .cipher_str = "cts(cbc(aes))", + .keysize = 16, ++ .security_strength = 16, + .ivsize = 16, + }, + [FSCRYPT_MODE_ADIANTUM] = { + .friendly_name = "Adiantum", + .cipher_str = "adiantum(xchacha12,aes)", + .keysize = 32, ++ .security_strength = 32, + .ivsize = 32, + .blk_crypto_mode = BLK_ENCRYPTION_MODE_ADIANTUM, + }, +@@ -357,6 +362,45 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, + return 0; + } + ++/* ++ * Check whether the size of the given master key (@mk) is appropriate for the ++ * encryption settings which a particular file will use (@ci). ++ * ++ * If the file uses a v1 encryption policy, then the master key must be at least ++ * as long as the derived key, as this is a requirement of the v1 KDF. ++ * ++ * Otherwise, the KDF can accept any size key, so we enforce a slightly looser ++ * requirement: we require that the size of the master key be at least the ++ * maximum security strength of any algorithm whose key will be derived from it ++ * (but in practice we only need to consider @ci->ci_mode, since any other ++ * possible subkeys such as DIRHASH and INODE_HASH will never increase the ++ * required key size over @ci->ci_mode). This allows AES-256-XTS keys to be ++ * derived from a 256-bit master key, which is cryptographically sufficient, ++ * rather than requiring a 512-bit master key which is unnecessarily long. (We ++ * still allow 512-bit master keys if the user chooses to use them, though.) ++ */ ++static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk, ++ const struct fscrypt_info *ci) ++{ ++ unsigned int min_keysize; ++ ++ if (ci->ci_policy.version == FSCRYPT_POLICY_V1) ++ min_keysize = ci->ci_mode->keysize; ++ else ++ min_keysize = ci->ci_mode->security_strength; ++ ++ if (mk->mk_secret.size < min_keysize) { ++ fscrypt_warn(NULL, ++ "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", ++ master_key_spec_type(&mk->mk_spec), ++ master_key_spec_len(&mk->mk_spec), ++ (u8 *)&mk->mk_spec.u, ++ mk->mk_secret.size, min_keysize); ++ return false; ++ } ++ return true; ++} ++ + /* + * Find the master key, then set up the inode's actual encryption key. + * +@@ -422,18 +466,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, + goto out_release_key; + } + +- /* +- * Require that the master key be at least as long as the derived key. +- * Otherwise, the derived key cannot possibly contain as much entropy as +- * that required by the encryption mode it will be used for. For v1 +- * policies it's also required for the KDF to work at all. +- */ +- if (mk->mk_secret.size < ci->ci_mode->keysize) { +- fscrypt_warn(NULL, +- "key with %s %*phN is too short (got %u bytes, need %u+ bytes)", +- master_key_spec_type(&mk_spec), +- master_key_spec_len(&mk_spec), (u8 *)&mk_spec.u, +- mk->mk_secret.size, ci->ci_mode->keysize); ++ if (!fscrypt_valid_master_key_size(mk, ci)) { + err = -ENOKEY; + goto out_release_key; + } +diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c +index 7d162b0efbf03..950c63fa4d0b2 100644 +--- a/fs/debugfs/file.c ++++ b/fs/debugfs/file.c +@@ -147,7 +147,7 @@ static int debugfs_locked_down(struct inode *inode, + struct file *filp, + const struct file_operations *real_fops) + { +- if ((inode->i_mode & 07777) == 0444 && ++ if ((inode->i_mode & 07777 & ~0444) == 0 && + !(filp->f_mode & FMODE_WRITE) && + !real_fops->unlocked_ioctl && + !real_fops->compat_ioctl && +diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c +index 42e5a766d33c7..4f25015aa5342 100644 +--- a/fs/devpts/inode.c ++++ b/fs/devpts/inode.c +@@ -621,8 +621,8 @@ void devpts_pty_kill(struct dentry *dentry) + + dentry->d_fsdata = NULL; + drop_nlink(dentry->d_inode); +- fsnotify_unlink(d_inode(dentry->d_parent), dentry); + d_drop(dentry); ++ fsnotify_unlink(d_inode(dentry->d_parent), dentry); + dput(dentry); /* d_alloc_name() in devpts_pty_new() */ + } + +diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c +index c502c065d0075..28d1f35b11a4d 100644 +--- a/fs/dlm/lock.c ++++ b/fs/dlm/lock.c +@@ -3973,6 +3973,14 @@ static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms) + int from = ms->m_header.h_nodeid; + int error = 0; + ++ /* currently mixing of user/kernel locks are not supported */ ++ if (ms->m_flags & DLM_IFL_USER && ~lkb->lkb_flags & DLM_IFL_USER) { ++ log_error(lkb->lkb_resource->res_ls, ++ "got user dlm message for a kernel lock"); ++ error = -EINVAL; ++ goto out; ++ } ++ + switch (ms->m_type) { + case DLM_MSG_CONVERT: + case DLM_MSG_UNLOCK: +@@ -4001,6 +4009,7 @@ static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms) + error = -EINVAL; + } + ++out: + if (error) + log_error(lkb->lkb_resource->res_ls, + "ignore invalid message %d from %d %x %x %x %d", +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index 8f715c620e1f8..7a8efce1c343e 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -592,8 +592,8 @@ int dlm_lowcomms_nodes_set_mark(int nodeid, unsigned int mark) + static void lowcomms_error_report(struct sock *sk) + { + struct connection *con; +- struct sockaddr_storage saddr; + void (*orig_report)(struct sock *) = NULL; ++ struct inet_sock *inet; + + read_lock_bh(&sk->sk_callback_lock); + con = sock2con(sk); +@@ -601,33 +601,33 @@ static void lowcomms_error_report(struct sock *sk) + goto out; + + orig_report = listen_sock.sk_error_report; +- if (kernel_getpeername(sk->sk_socket, (struct sockaddr *)&saddr) < 0) { +- printk_ratelimited(KERN_ERR "dlm: node %d: socket error " +- "sending to node %d, port %d, " +- "sk_err=%d/%d\n", dlm_our_nodeid(), +- con->nodeid, dlm_config.ci_tcp_port, +- sk->sk_err, sk->sk_err_soft); +- } else if (saddr.ss_family == AF_INET) { +- struct sockaddr_in *sin4 = (struct sockaddr_in *)&saddr; + ++ inet = inet_sk(sk); ++ switch (sk->sk_family) { ++ case AF_INET: + printk_ratelimited(KERN_ERR "dlm: node %d: socket error " +- "sending to node %d at %pI4, port %d, " ++ "sending to node %d at %pI4, dport %d, " + "sk_err=%d/%d\n", dlm_our_nodeid(), +- con->nodeid, &sin4->sin_addr.s_addr, +- dlm_config.ci_tcp_port, sk->sk_err, ++ con->nodeid, &inet->inet_daddr, ++ ntohs(inet->inet_dport), sk->sk_err, + sk->sk_err_soft); +- } else { +- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&saddr; +- ++ break; ++#if IS_ENABLED(CONFIG_IPV6) ++ case AF_INET6: + printk_ratelimited(KERN_ERR "dlm: node %d: socket error " +- "sending to node %d at %u.%u.%u.%u, " +- "port %d, sk_err=%d/%d\n", dlm_our_nodeid(), +- con->nodeid, sin6->sin6_addr.s6_addr32[0], +- sin6->sin6_addr.s6_addr32[1], +- sin6->sin6_addr.s6_addr32[2], +- sin6->sin6_addr.s6_addr32[3], +- dlm_config.ci_tcp_port, sk->sk_err, ++ "sending to node %d at %pI6c, " ++ "dport %d, sk_err=%d/%d\n", dlm_our_nodeid(), ++ con->nodeid, &sk->sk_v6_daddr, ++ ntohs(inet->inet_dport), sk->sk_err, + sk->sk_err_soft); ++ break; ++#endif ++ default: ++ printk_ratelimited(KERN_ERR "dlm: node %d: socket error " ++ "invalid socket family %d set, " ++ "sk_err=%d/%d\n", dlm_our_nodeid(), ++ sk->sk_family, sk->sk_err, sk->sk_err_soft); ++ goto out; + } + + /* below sendcon only handling */ +diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c +index a5bc4b1b7813e..ad3f31380e6b2 100644 +--- a/fs/erofs/decompressor.c ++++ b/fs/erofs/decompressor.c +@@ -233,7 +233,6 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) + erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", + ret, rq->inputsize, inputmargin, rq->outputsize); + +- WARN_ON(1); + print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, + 16, 1, src + inputmargin, rq->inputsize, true); + print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, +diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c +index bd86067a63f7f..3ca703cd5b24a 100644 +--- a/fs/erofs/utils.c ++++ b/fs/erofs/utils.c +@@ -141,7 +141,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, + * however in order to avoid some race conditions, add a + * DBG_BUGON to observe this in advance. + */ +- DBG_BUGON(xa_erase(&sbi->managed_pslots, grp->index) != grp); ++ DBG_BUGON(__xa_erase(&sbi->managed_pslots, grp->index) != grp); + + /* last refcount should be connected with its managed pslot. */ + erofs_workgroup_unfreeze(grp, 0); +@@ -156,15 +156,19 @@ static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned int freed = 0; + unsigned long index; + ++ xa_lock(&sbi->managed_pslots); + xa_for_each(&sbi->managed_pslots, index, grp) { + /* try to shrink each valid workgroup */ + if (!erofs_try_to_release_workgroup(sbi, grp)) + continue; ++ xa_unlock(&sbi->managed_pslots); + + ++freed; + if (!--nr_shrink) +- break; ++ return freed; ++ xa_lock(&sbi->managed_pslots); + } ++ xa_unlock(&sbi->managed_pslots); + return freed; + } + +diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c +index 11c7a1aaebade..eb51df4a9f770 100644 +--- a/fs/erofs/zdata.c ++++ b/fs/erofs/zdata.c +@@ -373,8 +373,8 @@ static bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, + + /* callers must be with collection lock held */ + static int z_erofs_attach_page(struct z_erofs_collector *clt, +- struct page *page, +- enum z_erofs_page_type type) ++ struct page *page, enum z_erofs_page_type type, ++ bool pvec_safereuse) + { + int ret; + +@@ -384,9 +384,9 @@ static int z_erofs_attach_page(struct z_erofs_collector *clt, + z_erofs_try_inplace_io(clt, page)) + return 0; + +- ret = z_erofs_pagevec_enqueue(&clt->vector, page, type); ++ ret = z_erofs_pagevec_enqueue(&clt->vector, page, type, ++ pvec_safereuse); + clt->cl->vcnt += (unsigned int)ret; +- + return ret ? 0 : -EAGAIN; + } + +@@ -729,7 +729,8 @@ hitted: + tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); + + retry: +- err = z_erofs_attach_page(clt, page, page_type); ++ err = z_erofs_attach_page(clt, page, page_type, ++ clt->mode >= COLLECT_PRIMARY_FOLLOWED); + /* should allocate an additional short-lived page for pagevec */ + if (err == -EAGAIN) { + struct page *const newpage = +@@ -737,7 +738,7 @@ retry: + + set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE); + err = z_erofs_attach_page(clt, newpage, +- Z_EROFS_PAGE_TYPE_EXCLUSIVE); ++ Z_EROFS_PAGE_TYPE_EXCLUSIVE, true); + if (!err) + goto retry; + } +diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h +index dfd7fe0503bb1..b05464f4a8083 100644 +--- a/fs/erofs/zpvec.h ++++ b/fs/erofs/zpvec.h +@@ -106,11 +106,18 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, + + static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, +- enum z_erofs_page_type type) ++ enum z_erofs_page_type type, ++ bool pvec_safereuse) + { +- if (!ctor->next && type) +- if (ctor->index + 1 == ctor->nr) ++ if (!ctor->next) { ++ /* some pages cannot be reused as pvec safely without I/O */ ++ if (type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && !pvec_safereuse) ++ type = Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED; ++ ++ if (type != Z_EROFS_PAGE_TYPE_EXCLUSIVE && ++ ctor->index + 1 == ctor->nr) + return false; ++ } + + if (ctor->index >= ctor->nr) + z_erofs_pagevec_ctor_pagedown(ctor, false); +diff --git a/fs/exec.c b/fs/exec.c +index a098c133d8d74..ac7b51b51f38a 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1852,7 +1852,7 @@ out: + * SIGSEGV. + */ + if (bprm->point_of_no_return && !fatal_signal_pending(current)) +- force_sigsegv(SIGSEGV); ++ force_fatal_sig(SIGSEGV); + + out_unmark: + current->fs->in_exec = 0; +diff --git a/fs/exfat/file.c b/fs/exfat/file.c +index 6af0191b648f1..d890fd34bb2d0 100644 +--- a/fs/exfat/file.c ++++ b/fs/exfat/file.c +@@ -110,8 +110,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) + exfat_set_volume_dirty(sb); + + num_clusters_new = EXFAT_B_TO_CLU_ROUND_UP(i_size_read(inode), sbi); +- num_clusters_phys = +- EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, sbi); ++ num_clusters_phys = EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi); + + exfat_chain_set(&clu, ei->start_clu, num_clusters_phys, ei->flags); + +@@ -228,12 +227,13 @@ void exfat_truncate(struct inode *inode, loff_t size) + { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); ++ struct exfat_inode_info *ei = EXFAT_I(inode); + unsigned int blocksize = i_blocksize(inode); + loff_t aligned_size; + int err; + + mutex_lock(&sbi->s_lock); +- if (EXFAT_I(inode)->start_clu == 0) { ++ if (ei->start_clu == 0) { + /* + * Empty start_clu != ~0 (not allocated) + */ +@@ -251,8 +251,8 @@ void exfat_truncate(struct inode *inode, loff_t size) + else + mark_inode_dirty(inode); + +- inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & +- ~(sbi->cluster_size - 1)) >> inode->i_blkbits; ++ inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> ++ inode->i_blkbits; + write_size: + aligned_size = i_size_read(inode); + if (aligned_size & (blocksize - 1)) { +@@ -260,11 +260,11 @@ write_size: + aligned_size++; + } + +- if (EXFAT_I(inode)->i_size_ondisk > i_size_read(inode)) +- EXFAT_I(inode)->i_size_ondisk = aligned_size; ++ if (ei->i_size_ondisk > i_size_read(inode)) ++ ei->i_size_ondisk = aligned_size; + +- if (EXFAT_I(inode)->i_size_aligned > i_size_read(inode)) +- EXFAT_I(inode)->i_size_aligned = aligned_size; ++ if (ei->i_size_aligned > i_size_read(inode)) ++ ei->i_size_aligned = aligned_size; + mutex_unlock(&sbi->s_lock); + } + +diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c +index ca37d43443612..72a0ccfb616c3 100644 +--- a/fs/exfat/inode.c ++++ b/fs/exfat/inode.c +@@ -114,10 +114,9 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, + unsigned int local_clu_offset = clu_offset; + unsigned int num_to_be_allocated = 0, num_clusters = 0; + +- if (EXFAT_I(inode)->i_size_ondisk > 0) ++ if (ei->i_size_ondisk > 0) + num_clusters = +- EXFAT_B_TO_CLU_ROUND_UP(EXFAT_I(inode)->i_size_ondisk, +- sbi); ++ EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi); + + if (clu_offset >= num_clusters) + num_to_be_allocated = clu_offset - num_clusters + 1; +@@ -416,10 +415,10 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + +- if (EXFAT_I(inode)->i_size_aligned < i_size_read(inode)) { ++ if (ei->i_size_aligned < i_size_read(inode)) { + exfat_fs_error(inode->i_sb, + "invalid size(size(%llu) > aligned(%llu)\n", +- i_size_read(inode), EXFAT_I(inode)->i_size_aligned); ++ i_size_read(inode), ei->i_size_aligned); + return -EIO; + } + +@@ -603,8 +602,8 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info) + + exfat_save_attr(inode, info->attr); + +- inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) & +- ~(sbi->cluster_size - 1)) >> inode->i_blkbits; ++ inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> ++ inode->i_blkbits; + inode->i_mtime = info->mtime; + inode->i_ctime = info->mtime; + ei->i_crtime = info->crtime; +diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c +index 24b41103d1cc0..9d8ada781250b 100644 +--- a/fs/exfat/namei.c ++++ b/fs/exfat/namei.c +@@ -395,9 +395,9 @@ static int exfat_find_empty_entry(struct inode *inode, + + /* directory inode should be updated in here */ + i_size_write(inode, size); +- EXFAT_I(inode)->i_size_ondisk += sbi->cluster_size; +- EXFAT_I(inode)->i_size_aligned += sbi->cluster_size; +- EXFAT_I(inode)->flags = p_dir->flags; ++ ei->i_size_ondisk += sbi->cluster_size; ++ ei->i_size_aligned += sbi->cluster_size; ++ ei->flags = p_dir->flags; + inode->i_blocks += 1 << sbi->sect_per_clus_bits; + } + +diff --git a/fs/exfat/super.c b/fs/exfat/super.c +index 5539ffc20d164..4b5d02b1df585 100644 +--- a/fs/exfat/super.c ++++ b/fs/exfat/super.c +@@ -364,11 +364,11 @@ static int exfat_read_root(struct inode *inode) + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + +- inode->i_blocks = ((i_size_read(inode) + (sbi->cluster_size - 1)) +- & ~(sbi->cluster_size - 1)) >> inode->i_blkbits; +- EXFAT_I(inode)->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff; +- EXFAT_I(inode)->i_size_aligned = i_size_read(inode); +- EXFAT_I(inode)->i_size_ondisk = i_size_read(inode); ++ inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> ++ inode->i_blkbits; ++ ei->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff; ++ ei->i_size_aligned = i_size_read(inode); ++ ei->i_size_ondisk = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime = +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 3825195539d74..db981619f6c8e 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1724,9 +1724,9 @@ struct ext4_sb_info { + */ + struct work_struct s_error_work; + +- /* Ext4 fast commit stuff */ ++ /* Ext4 fast commit sub transaction ID */ + atomic_t s_fc_subtid; +- atomic_t s_fc_ineligible_updates; ++ + /* + * After commit starts, the main queue gets locked, and the further + * updates get added in the staging queue. +@@ -1746,7 +1746,7 @@ struct ext4_sb_info { + spinlock_t s_fc_lock; + struct buffer_head *s_fc_bh; + struct ext4_fc_stats s_fc_stats; +- u64 s_fc_avg_commit_time; ++ tid_t s_fc_ineligible_tid; + #ifdef CONFIG_EXT4_DEBUG + int s_fc_debug_max_replay; + #endif +@@ -1792,10 +1792,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) + enum { + EXT4_MF_MNTDIR_SAMPLED, + EXT4_MF_FS_ABORTED, /* Fatal error detected */ +- EXT4_MF_FC_INELIGIBLE, /* Fast commit ineligible */ +- EXT4_MF_FC_COMMITTING /* File system underoing a fast +- * commit. +- */ ++ EXT4_MF_FC_INELIGIBLE /* Fast commit ineligible */ + }; + + static inline void ext4_set_mount_flag(struct super_block *sb, int bit) +@@ -2924,9 +2921,7 @@ void __ext4_fc_track_create(handle_t *handle, struct inode *inode, + struct dentry *dentry); + void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); + void ext4_fc_track_inode(handle_t *handle, struct inode *inode); +-void ext4_fc_mark_ineligible(struct super_block *sb, int reason); +-void ext4_fc_start_ineligible(struct super_block *sb, int reason); +-void ext4_fc_stop_ineligible(struct super_block *sb); ++void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t *handle); + void ext4_fc_start_update(struct inode *inode); + void ext4_fc_stop_update(struct inode *inode); + void ext4_fc_del(struct inode *inode); +@@ -2934,6 +2929,10 @@ bool ext4_fc_replay_check_excluded(struct super_block *sb, ext4_fsblk_t block); + void ext4_fc_replay_cleanup(struct super_block *sb); + int ext4_fc_commit(journal_t *journal, tid_t commit_tid); + int __init ext4_fc_init_dentry_cache(void); ++void ext4_fc_destroy_dentry_cache(void); ++int ext4_fc_record_regions(struct super_block *sb, int ino, ++ ext4_lblk_t lblk, ext4_fsblk_t pblk, ++ int len, int replay); + + /* mballoc.c */ + extern const struct seq_operations ext4_mb_seq_groups_ops; +diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index 6def7339056db..3477a16d08aee 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -162,6 +162,8 @@ int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, + { + if (!ext4_handle_valid(handle)) + return 0; ++ if (is_handle_aborted(handle)) ++ return -EROFS; + if (jbd2_handle_buffer_credits(handle) >= check_cred && + handle->h_revoke_credits >= revoke_cred) + return 0; +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 0e02571f2f828..b81c008e66755 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -136,15 +136,25 @@ int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode, + static int ext4_ext_get_access(handle_t *handle, struct inode *inode, + struct ext4_ext_path *path) + { ++ int err = 0; ++ + if (path->p_bh) { + /* path points to block */ + BUFFER_TRACE(path->p_bh, "get_write_access"); +- return ext4_journal_get_write_access(handle, inode->i_sb, +- path->p_bh, EXT4_JTR_NONE); ++ err = ext4_journal_get_write_access(handle, inode->i_sb, ++ path->p_bh, EXT4_JTR_NONE); ++ /* ++ * The extent buffer's verified bit will be set again in ++ * __ext4_ext_dirty(). We could leave an inconsistent ++ * buffer if the extents updating procudure break off du ++ * to some error happens, force to check it again. ++ */ ++ if (!err) ++ clear_buffer_verified(path->p_bh); + } + /* path points to leaf/index in inode body */ + /* we use in-core data, no need to protect them */ +- return 0; ++ return err; + } + + /* +@@ -165,6 +175,9 @@ static int __ext4_ext_dirty(const char *where, unsigned int line, + /* path points to block */ + err = __ext4_handle_dirty_metadata(where, line, handle, + inode, path->p_bh); ++ /* Extents updating done, re-set verified flag */ ++ if (!err) ++ set_buffer_verified(path->p_bh); + } else { + /* path points to leaf/index in inode body */ + err = ext4_mark_inode_dirty(handle, inode); +@@ -354,9 +367,13 @@ static int ext4_valid_extent_idx(struct inode *inode, + + static int ext4_valid_extent_entries(struct inode *inode, + struct ext4_extent_header *eh, +- ext4_fsblk_t *pblk, int depth) ++ ext4_lblk_t lblk, ext4_fsblk_t *pblk, ++ int depth) + { + unsigned short entries; ++ ext4_lblk_t lblock = 0; ++ ext4_lblk_t prev = 0; ++ + if (eh->eh_entries == 0) + return 1; + +@@ -365,31 +382,51 @@ static int ext4_valid_extent_entries(struct inode *inode, + if (depth == 0) { + /* leaf entries */ + struct ext4_extent *ext = EXT_FIRST_EXTENT(eh); +- ext4_lblk_t lblock = 0; +- ext4_lblk_t prev = 0; +- int len = 0; ++ ++ /* ++ * The logical block in the first entry should equal to ++ * the number in the index block. ++ */ ++ if (depth != ext_depth(inode) && ++ lblk != le32_to_cpu(ext->ee_block)) ++ return 0; + while (entries) { + if (!ext4_valid_extent(inode, ext)) + return 0; + + /* Check for overlapping extents */ + lblock = le32_to_cpu(ext->ee_block); +- len = ext4_ext_get_actual_len(ext); + if ((lblock <= prev) && prev) { + *pblk = ext4_ext_pblock(ext); + return 0; + } ++ prev = lblock + ext4_ext_get_actual_len(ext) - 1; + ext++; + entries--; +- prev = lblock + len - 1; + } + } else { + struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh); ++ ++ /* ++ * The logical block in the first entry should equal to ++ * the number in the parent index block. ++ */ ++ if (depth != ext_depth(inode) && ++ lblk != le32_to_cpu(ext_idx->ei_block)) ++ return 0; + while (entries) { + if (!ext4_valid_extent_idx(inode, ext_idx)) + return 0; ++ ++ /* Check for overlapping index extents */ ++ lblock = le32_to_cpu(ext_idx->ei_block); ++ if ((lblock <= prev) && prev) { ++ *pblk = ext4_idx_pblock(ext_idx); ++ return 0; ++ } + ext_idx++; + entries--; ++ prev = lblock; + } + } + return 1; +@@ -397,7 +434,7 @@ static int ext4_valid_extent_entries(struct inode *inode, + + static int __ext4_ext_check(const char *function, unsigned int line, + struct inode *inode, struct ext4_extent_header *eh, +- int depth, ext4_fsblk_t pblk) ++ int depth, ext4_fsblk_t pblk, ext4_lblk_t lblk) + { + const char *error_msg; + int max = 0, err = -EFSCORRUPTED; +@@ -423,7 +460,7 @@ static int __ext4_ext_check(const char *function, unsigned int line, + error_msg = "invalid eh_entries"; + goto corrupted; + } +- if (!ext4_valid_extent_entries(inode, eh, &pblk, depth)) { ++ if (!ext4_valid_extent_entries(inode, eh, lblk, &pblk, depth)) { + error_msg = "invalid extent entries"; + goto corrupted; + } +@@ -453,7 +490,7 @@ corrupted: + } + + #define ext4_ext_check(inode, eh, depth, pblk) \ +- __ext4_ext_check(__func__, __LINE__, (inode), (eh), (depth), (pblk)) ++ __ext4_ext_check(__func__, __LINE__, (inode), (eh), (depth), (pblk), 0) + + int ext4_ext_check_inode(struct inode *inode) + { +@@ -486,16 +523,18 @@ static void ext4_cache_extents(struct inode *inode, + + static struct buffer_head * + __read_extent_tree_block(const char *function, unsigned int line, +- struct inode *inode, ext4_fsblk_t pblk, int depth, +- int flags) ++ struct inode *inode, struct ext4_extent_idx *idx, ++ int depth, int flags) + { + struct buffer_head *bh; + int err; + gfp_t gfp_flags = __GFP_MOVABLE | GFP_NOFS; ++ ext4_fsblk_t pblk; + + if (flags & EXT4_EX_NOFAIL) + gfp_flags |= __GFP_NOFAIL; + ++ pblk = ext4_idx_pblock(idx); + bh = sb_getblk_gfp(inode->i_sb, pblk, gfp_flags); + if (unlikely(!bh)) + return ERR_PTR(-ENOMEM); +@@ -508,8 +547,8 @@ __read_extent_tree_block(const char *function, unsigned int line, + } + if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE)) + return bh; +- err = __ext4_ext_check(function, line, inode, +- ext_block_hdr(bh), depth, pblk); ++ err = __ext4_ext_check(function, line, inode, ext_block_hdr(bh), ++ depth, pblk, le32_to_cpu(idx->ei_block)); + if (err) + goto errout; + set_buffer_verified(bh); +@@ -527,8 +566,8 @@ errout: + + } + +-#define read_extent_tree_block(inode, pblk, depth, flags) \ +- __read_extent_tree_block(__func__, __LINE__, (inode), (pblk), \ ++#define read_extent_tree_block(inode, idx, depth, flags) \ ++ __read_extent_tree_block(__func__, __LINE__, (inode), (idx), \ + (depth), (flags)) + + /* +@@ -578,8 +617,7 @@ int ext4_ext_precache(struct inode *inode) + i--; + continue; + } +- bh = read_extent_tree_block(inode, +- ext4_idx_pblock(path[i].p_idx++), ++ bh = read_extent_tree_block(inode, path[i].p_idx++, + depth - i - 1, + EXT4_EX_FORCE_CACHE); + if (IS_ERR(bh)) { +@@ -884,8 +922,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, + path[ppos].p_depth = i; + path[ppos].p_ext = NULL; + +- bh = read_extent_tree_block(inode, path[ppos].p_block, --i, +- flags); ++ bh = read_extent_tree_block(inode, path[ppos].p_idx, --i, flags); + if (IS_ERR(bh)) { + ret = PTR_ERR(bh); + goto err; +@@ -1494,7 +1531,6 @@ static int ext4_ext_search_right(struct inode *inode, + struct ext4_extent_header *eh; + struct ext4_extent_idx *ix; + struct ext4_extent *ex; +- ext4_fsblk_t block; + int depth; /* Note, NOT eh_depth; depth from top of tree */ + int ee_len; + +@@ -1561,20 +1597,17 @@ got_index: + * follow it and find the closest allocated + * block to the right */ + ix++; +- block = ext4_idx_pblock(ix); + while (++depth < path->p_depth) { + /* subtract from p_depth to get proper eh_depth */ +- bh = read_extent_tree_block(inode, block, +- path->p_depth - depth, 0); ++ bh = read_extent_tree_block(inode, ix, path->p_depth - depth, 0); + if (IS_ERR(bh)) + return PTR_ERR(bh); + eh = ext_block_hdr(bh); + ix = EXT_FIRST_INDEX(eh); +- block = ext4_idx_pblock(ix); + put_bh(bh); + } + +- bh = read_extent_tree_block(inode, block, path->p_depth - depth, 0); ++ bh = read_extent_tree_block(inode, ix, path->p_depth - depth, 0); + if (IS_ERR(bh)) + return PTR_ERR(bh); + eh = ext_block_hdr(bh); +@@ -2953,9 +2986,9 @@ again: + ext_debug(inode, "move to level %d (block %llu)\n", + i + 1, ext4_idx_pblock(path[i].p_idx)); + memset(path + i + 1, 0, sizeof(*path)); +- bh = read_extent_tree_block(inode, +- ext4_idx_pblock(path[i].p_idx), depth - i - 1, +- EXT4_EX_NOCACHE); ++ bh = read_extent_tree_block(inode, path[i].p_idx, ++ depth - i - 1, ++ EXT4_EX_NOCACHE); + if (IS_ERR(bh)) { + /* should we reset i_size? */ + err = PTR_ERR(bh); +@@ -4612,8 +4645,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + ret = ext4_mark_inode_dirty(handle, inode); + if (unlikely(ret)) + goto out_handle; +- ext4_fc_track_range(handle, inode, offset >> inode->i_sb->s_blocksize_bits, +- (offset + len - 1) >> inode->i_sb->s_blocksize_bits); + /* Zero out partial block at the edges of the range */ + ret = ext4_zero_partial_blocks(handle, inode, offset, len); + if (ret >= 0) +@@ -4977,36 +5008,6 @@ int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo, + return ext4_fill_es_cache_info(inode, start_blk, len_blks, fieinfo); + } + +-/* +- * ext4_access_path: +- * Function to access the path buffer for marking it dirty. +- * It also checks if there are sufficient credits left in the journal handle +- * to update path. +- */ +-static int +-ext4_access_path(handle_t *handle, struct inode *inode, +- struct ext4_ext_path *path) +-{ +- int credits, err; +- +- if (!ext4_handle_valid(handle)) +- return 0; +- +- /* +- * Check if need to extend journal credits +- * 3 for leaf, sb, and inode plus 2 (bmap and group +- * descriptor) for each block group; assume two block +- * groups +- */ +- credits = ext4_writepage_trans_blocks(inode); +- err = ext4_datasem_ensure_credits(handle, inode, 7, credits, 0); +- if (err < 0) +- return err; +- +- err = ext4_ext_get_access(handle, inode, path); +- return err; +-} +- + /* + * ext4_ext_shift_path_extents: + * Shift the extents of a path structure lying between path[depth].p_ext +@@ -5021,6 +5022,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, + int depth, err = 0; + struct ext4_extent *ex_start, *ex_last; + bool update = false; ++ int credits, restart_credits; + depth = path->p_depth; + + while (depth >= 0) { +@@ -5030,13 +5032,26 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, + return -EFSCORRUPTED; + + ex_last = EXT_LAST_EXTENT(path[depth].p_hdr); ++ /* leaf + sb + inode */ ++ credits = 3; ++ if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr)) { ++ update = true; ++ /* extent tree + sb + inode */ ++ credits = depth + 2; ++ } + +- err = ext4_access_path(handle, inode, path + depth); +- if (err) ++ restart_credits = ext4_writepage_trans_blocks(inode); ++ err = ext4_datasem_ensure_credits(handle, inode, credits, ++ restart_credits, 0); ++ if (err) { ++ if (err > 0) ++ err = -EAGAIN; + goto out; ++ } + +- if (ex_start == EXT_FIRST_EXTENT(path[depth].p_hdr)) +- update = true; ++ err = ext4_ext_get_access(handle, inode, path + depth); ++ if (err) ++ goto out; + + while (ex_start <= ex_last) { + if (SHIFT == SHIFT_LEFT) { +@@ -5067,7 +5082,7 @@ ext4_ext_shift_path_extents(struct ext4_ext_path *path, ext4_lblk_t shift, + } + + /* Update index too */ +- err = ext4_access_path(handle, inode, path + depth); ++ err = ext4_ext_get_access(handle, inode, path + depth); + if (err) + goto out; + +@@ -5106,6 +5121,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, + int ret = 0, depth; + struct ext4_extent *extent; + ext4_lblk_t stop, *iterator, ex_start, ex_end; ++ ext4_lblk_t tmp = EXT_MAX_BLOCKS; + + /* Let path point to the last extent */ + path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, +@@ -5159,11 +5175,15 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, + * till we reach stop. In case of right shift, iterator points to stop + * and it is decreased till we reach start. + */ ++again: + if (SHIFT == SHIFT_LEFT) + iterator = &start; + else + iterator = &stop; + ++ if (tmp != EXT_MAX_BLOCKS) ++ *iterator = tmp; ++ + /* + * Its safe to start updating extents. Start and stop are unsigned, so + * in case of right shift if extent with 0 block is reached, iterator +@@ -5192,6 +5212,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, + } + } + ++ tmp = *iterator; + if (SHIFT == SHIFT_LEFT) { + extent = EXT_LAST_EXTENT(path[depth].p_hdr); + *iterator = le32_to_cpu(extent->ee_block) + +@@ -5210,6 +5231,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, + } + ret = ext4_ext_shift_path_extents(path, shift, inode, + handle, SHIFT); ++ /* iterator can be NULL which means we should break */ ++ if (ret == -EAGAIN) ++ goto again; + if (ret) + break; + } +@@ -5316,7 +5340,7 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + ret = PTR_ERR(handle); + goto out_mmap; + } +- ext4_fc_start_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE); ++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); + + down_write(&EXT4_I(inode)->i_data_sem); + ext4_discard_preallocations(inode, 0); +@@ -5355,7 +5379,6 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + + out_stop: + ext4_journal_stop(handle); +- ext4_fc_stop_ineligible(sb); + out_mmap: + filemap_invalidate_unlock(mapping); + out_mutex: +@@ -5457,7 +5480,7 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + ret = PTR_ERR(handle); + goto out_mmap; + } +- ext4_fc_start_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE); ++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); + + /* Expand file to avoid data loss if there is error while shifting */ + inode->i_size += len; +@@ -5532,7 +5555,6 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + + out_stop: + ext4_journal_stop(handle); +- ext4_fc_stop_ineligible(sb); + out_mmap: + filemap_invalidate_unlock(mapping); + out_mutex: +@@ -6072,11 +6094,15 @@ int ext4_ext_clear_bb(struct inode *inode) + + ext4_mb_mark_bb(inode->i_sb, + path[j].p_block, 1, 0); ++ ext4_fc_record_regions(inode->i_sb, inode->i_ino, ++ 0, path[j].p_block, 1, 1); + } + ext4_ext_drop_refs(path); + kfree(path); + } + ext4_mb_mark_bb(inode->i_sb, map.m_pblk, map.m_len, 0); ++ ext4_fc_record_regions(inode->i_sb, inode->i_ino, ++ map.m_lblk, map.m_pblk, map.m_len, 1); + } + cur = cur + map.m_len; + } +diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c +index 8ea5a81e65548..285c91b0166c0 100644 +--- a/fs/ext4/fast_commit.c ++++ b/fs/ext4/fast_commit.c +@@ -65,21 +65,11 @@ + * + * Fast Commit Ineligibility + * ------------------------- +- * Not all operations are supported by fast commits today (e.g extended +- * attributes). Fast commit ineligibility is marked by calling one of the +- * two following functions: +- * +- * - ext4_fc_mark_ineligible(): This makes next fast commit operation to fall +- * back to full commit. This is useful in case of transient errors. + * +- * - ext4_fc_start_ineligible() and ext4_fc_stop_ineligible() - This makes all +- * the fast commits happening between ext4_fc_start_ineligible() and +- * ext4_fc_stop_ineligible() and one fast commit after the call to +- * ext4_fc_stop_ineligible() to fall back to full commits. It is important to +- * make one more fast commit to fall back to full commit after stop call so +- * that it guaranteed that the fast commit ineligible operation contained +- * within ext4_fc_start_ineligible() and ext4_fc_stop_ineligible() is +- * followed by at least 1 full commit. ++ * Not all operations are supported by fast commits today (e.g extended ++ * attributes). Fast commit ineligibility is marked by calling ++ * ext4_fc_mark_ineligible(): This makes next fast commit operation to fall back ++ * to full commit. + * + * Atomicity of commits + * -------------------- +@@ -312,60 +302,36 @@ restart: + } + + /* +- * Mark file system as fast commit ineligible. This means that next commit +- * operation would result in a full jbd2 commit. ++ * Mark file system as fast commit ineligible, and record latest ++ * ineligible transaction tid. This means until the recorded ++ * transaction, commit operation would result in a full jbd2 commit. + */ +-void ext4_fc_mark_ineligible(struct super_block *sb, int reason) ++void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t *handle) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); ++ tid_t tid; + + if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || + (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) + return; + + ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); ++ if (handle && !IS_ERR(handle)) ++ tid = handle->h_transaction->t_tid; ++ else { ++ read_lock(&sbi->s_journal->j_state_lock); ++ tid = sbi->s_journal->j_running_transaction ? ++ sbi->s_journal->j_running_transaction->t_tid : 0; ++ read_unlock(&sbi->s_journal->j_state_lock); ++ } ++ spin_lock(&sbi->s_fc_lock); ++ if (sbi->s_fc_ineligible_tid < tid) ++ sbi->s_fc_ineligible_tid = tid; ++ spin_unlock(&sbi->s_fc_lock); + WARN_ON(reason >= EXT4_FC_REASON_MAX); + sbi->s_fc_stats.fc_ineligible_reason_count[reason]++; + } + +-/* +- * Start a fast commit ineligible update. Any commits that happen while +- * such an operation is in progress fall back to full commits. +- */ +-void ext4_fc_start_ineligible(struct super_block *sb, int reason) +-{ +- struct ext4_sb_info *sbi = EXT4_SB(sb); +- +- if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || +- (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) +- return; +- +- WARN_ON(reason >= EXT4_FC_REASON_MAX); +- sbi->s_fc_stats.fc_ineligible_reason_count[reason]++; +- atomic_inc(&sbi->s_fc_ineligible_updates); +-} +- +-/* +- * Stop a fast commit ineligible update. We set EXT4_MF_FC_INELIGIBLE flag here +- * to ensure that after stopping the ineligible update, at least one full +- * commit takes place. +- */ +-void ext4_fc_stop_ineligible(struct super_block *sb) +-{ +- if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || +- (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) +- return; +- +- ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); +- atomic_dec(&EXT4_SB(sb)->s_fc_ineligible_updates); +-} +- +-static inline int ext4_fc_is_ineligible(struct super_block *sb) +-{ +- return (ext4_test_mount_flag(sb, EXT4_MF_FC_INELIGIBLE) || +- atomic_read(&EXT4_SB(sb)->s_fc_ineligible_updates)); +-} +- + /* + * Generic fast commit tracking function. If this is the first time this we are + * called after a full commit, we initialize fast commit fields and then call +@@ -391,7 +357,7 @@ static int ext4_fc_track_template( + (sbi->s_mount_state & EXT4_FC_REPLAY)) + return -EOPNOTSUPP; + +- if (ext4_fc_is_ineligible(inode->i_sb)) ++ if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_INELIGIBLE)) + return -EINVAL; + + tid = handle->h_transaction->t_tid; +@@ -411,7 +377,8 @@ static int ext4_fc_track_template( + spin_lock(&sbi->s_fc_lock); + if (list_empty(&EXT4_I(inode)->i_fc_list)) + list_add_tail(&EXT4_I(inode)->i_fc_list, +- (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) ? ++ (sbi->s_journal->j_flags & JBD2_FULL_COMMIT_ONGOING || ++ sbi->s_journal->j_flags & JBD2_FAST_COMMIT_ONGOING) ? + &sbi->s_fc_q[FC_Q_STAGING] : + &sbi->s_fc_q[FC_Q_MAIN]); + spin_unlock(&sbi->s_fc_lock); +@@ -437,7 +404,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) + mutex_unlock(&ei->i_fc_lock); + node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS); + if (!node) { +- ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM); ++ ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); + mutex_lock(&ei->i_fc_lock); + return -ENOMEM; + } +@@ -450,7 +417,7 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) + if (!node->fcd_name.name) { + kmem_cache_free(ext4_fc_dentry_cachep, node); + ext4_fc_mark_ineligible(inode->i_sb, +- EXT4_FC_REASON_NOMEM); ++ EXT4_FC_REASON_NOMEM, NULL); + mutex_lock(&ei->i_fc_lock); + return -ENOMEM; + } +@@ -464,7 +431,8 @@ static int __track_dentry_update(struct inode *inode, void *arg, bool update) + node->fcd_name.len = dentry->d_name.len; + + spin_lock(&sbi->s_fc_lock); +- if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) ++ if (sbi->s_journal->j_flags & JBD2_FULL_COMMIT_ONGOING || ++ sbi->s_journal->j_flags & JBD2_FAST_COMMIT_ONGOING) + list_add_tail(&node->fcd_list, + &sbi->s_fc_dentry_q[FC_Q_STAGING]); + else +@@ -552,7 +520,7 @@ void ext4_fc_track_inode(handle_t *handle, struct inode *inode) + + if (ext4_should_journal_data(inode)) { + ext4_fc_mark_ineligible(inode->i_sb, +- EXT4_FC_REASON_INODE_JOURNAL_DATA); ++ EXT4_FC_REASON_INODE_JOURNAL_DATA, handle); + return; + } + +@@ -928,7 +896,6 @@ static int ext4_fc_submit_inode_data_all(journal_t *journal) + int ret = 0; + + spin_lock(&sbi->s_fc_lock); +- ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING); + list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) { + ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING); + while (atomic_read(&ei->i_fc_updates)) { +@@ -1121,6 +1088,32 @@ out: + return ret; + } + ++static void ext4_fc_update_stats(struct super_block *sb, int status, ++ u64 commit_time, int nblks) ++{ ++ struct ext4_fc_stats *stats = &EXT4_SB(sb)->s_fc_stats; ++ ++ jbd_debug(1, "Fast commit ended with status = %d", status); ++ if (status == EXT4_FC_STATUS_OK) { ++ stats->fc_num_commits++; ++ stats->fc_numblks += nblks; ++ if (likely(stats->s_fc_avg_commit_time)) ++ stats->s_fc_avg_commit_time = ++ (commit_time + ++ stats->s_fc_avg_commit_time * 3) / 4; ++ else ++ stats->s_fc_avg_commit_time = commit_time; ++ } else if (status == EXT4_FC_STATUS_FAILED || ++ status == EXT4_FC_STATUS_INELIGIBLE) { ++ if (status == EXT4_FC_STATUS_FAILED) ++ stats->fc_failed_commits++; ++ stats->fc_ineligible_commits++; ++ } else { ++ stats->fc_skipped_commits++; ++ } ++ trace_ext4_fc_commit_stop(sb, nblks, status); ++} ++ + /* + * The main commit entry point. Performs a fast commit for transaction + * commit_tid if needed. If it's not possible to perform a fast commit +@@ -1133,18 +1126,15 @@ int ext4_fc_commit(journal_t *journal, tid_t commit_tid) + struct ext4_sb_info *sbi = EXT4_SB(sb); + int nblks = 0, ret, bsize = journal->j_blocksize; + int subtid = atomic_read(&sbi->s_fc_subtid); +- int reason = EXT4_FC_REASON_OK, fc_bufs_before = 0; ++ int status = EXT4_FC_STATUS_OK, fc_bufs_before = 0; + ktime_t start_time, commit_time; + + trace_ext4_fc_commit_start(sb); + + start_time = ktime_get(); + +- if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || +- (ext4_fc_is_ineligible(sb))) { +- reason = EXT4_FC_REASON_INELIGIBLE; +- goto out; +- } ++ if (!test_opt2(sb, JOURNAL_FAST_COMMIT)) ++ return jbd2_complete_transaction(journal, commit_tid); + + restart_fc: + ret = jbd2_fc_begin_commit(journal, commit_tid); +@@ -1153,74 +1143,59 @@ restart_fc: + if (atomic_read(&sbi->s_fc_subtid) <= subtid && + commit_tid > journal->j_commit_sequence) + goto restart_fc; +- reason = EXT4_FC_REASON_ALREADY_COMMITTED; +- goto out; ++ ext4_fc_update_stats(sb, EXT4_FC_STATUS_SKIPPED, 0, 0); ++ return 0; + } else if (ret) { +- sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; +- reason = EXT4_FC_REASON_FC_START_FAILED; +- goto out; ++ /* ++ * Commit couldn't start. Just update stats and perform a ++ * full commit. ++ */ ++ ext4_fc_update_stats(sb, EXT4_FC_STATUS_FAILED, 0, 0); ++ return jbd2_complete_transaction(journal, commit_tid); ++ } ++ ++ /* ++ * After establishing journal barrier via jbd2_fc_begin_commit(), check ++ * if we are fast commit ineligible. ++ */ ++ if (ext4_test_mount_flag(sb, EXT4_MF_FC_INELIGIBLE)) { ++ status = EXT4_FC_STATUS_INELIGIBLE; ++ goto fallback; + } + + fc_bufs_before = (sbi->s_fc_bytes + bsize - 1) / bsize; + ret = ext4_fc_perform_commit(journal); + if (ret < 0) { +- sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; +- reason = EXT4_FC_REASON_FC_FAILED; +- goto out; ++ status = EXT4_FC_STATUS_FAILED; ++ goto fallback; + } + nblks = (sbi->s_fc_bytes + bsize - 1) / bsize - fc_bufs_before; + ret = jbd2_fc_wait_bufs(journal, nblks); + if (ret < 0) { +- sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; +- reason = EXT4_FC_REASON_FC_FAILED; +- goto out; ++ status = EXT4_FC_STATUS_FAILED; ++ goto fallback; + } + atomic_inc(&sbi->s_fc_subtid); +- jbd2_fc_end_commit(journal); +-out: +- /* Has any ineligible update happened since we started? */ +- if (reason == EXT4_FC_REASON_OK && ext4_fc_is_ineligible(sb)) { +- sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; +- reason = EXT4_FC_REASON_INELIGIBLE; +- } +- +- spin_lock(&sbi->s_fc_lock); +- if (reason != EXT4_FC_REASON_OK && +- reason != EXT4_FC_REASON_ALREADY_COMMITTED) { +- sbi->s_fc_stats.fc_ineligible_commits++; +- } else { +- sbi->s_fc_stats.fc_num_commits++; +- sbi->s_fc_stats.fc_numblks += nblks; +- } +- spin_unlock(&sbi->s_fc_lock); +- nblks = (reason == EXT4_FC_REASON_OK) ? nblks : 0; +- trace_ext4_fc_commit_stop(sb, nblks, reason); +- commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); ++ ret = jbd2_fc_end_commit(journal); + /* +- * weight the commit time higher than the average time so we don't +- * react too strongly to vast changes in the commit time ++ * weight the commit time higher than the average time so we ++ * don't react too strongly to vast changes in the commit time + */ +- if (likely(sbi->s_fc_avg_commit_time)) +- sbi->s_fc_avg_commit_time = (commit_time + +- sbi->s_fc_avg_commit_time * 3) / 4; +- else +- sbi->s_fc_avg_commit_time = commit_time; +- jbd_debug(1, +- "Fast commit ended with blks = %d, reason = %d, subtid - %d", +- nblks, reason, subtid); +- if (reason == EXT4_FC_REASON_FC_FAILED) +- return jbd2_fc_end_commit_fallback(journal); +- if (reason == EXT4_FC_REASON_FC_START_FAILED || +- reason == EXT4_FC_REASON_INELIGIBLE) +- return jbd2_complete_transaction(journal, commit_tid); +- return 0; ++ commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); ++ ext4_fc_update_stats(sb, status, commit_time, nblks); ++ return ret; ++ ++fallback: ++ ret = jbd2_fc_end_commit_fallback(journal); ++ ext4_fc_update_stats(sb, status, 0, 0); ++ return ret; + } + + /* + * Fast commit cleanup routine. This is called after every fast commit and + * full commit. full is true if we are called after a full commit. + */ +-static void ext4_fc_cleanup(journal_t *journal, int full) ++static void ext4_fc_cleanup(journal_t *journal, int full, tid_t tid) + { + struct super_block *sb = journal->j_private; + struct ext4_sb_info *sbi = EXT4_SB(sb); +@@ -1238,7 +1213,8 @@ static void ext4_fc_cleanup(journal_t *journal, int full) + list_del_init(&iter->i_fc_list); + ext4_clear_inode_state(&iter->vfs_inode, + EXT4_STATE_FC_COMMITTING); +- ext4_fc_reset_inode(&iter->vfs_inode); ++ if (iter->i_sync_tid <= tid) ++ ext4_fc_reset_inode(&iter->vfs_inode); + /* Make sure EXT4_STATE_FC_COMMITTING bit is clear */ + smp_mb(); + #if (BITS_PER_LONG < 64) +@@ -1267,8 +1243,10 @@ static void ext4_fc_cleanup(journal_t *journal, int full) + list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], + &sbi->s_fc_q[FC_Q_MAIN]); + +- ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); +- ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); ++ if (tid >= sbi->s_fc_ineligible_tid) { ++ sbi->s_fc_ineligible_tid = 0; ++ ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); ++ } + + if (full) + sbi->s_fc_bytes = 0; +@@ -1433,14 +1411,15 @@ static int ext4_fc_record_modified_inode(struct super_block *sb, int ino) + if (state->fc_modified_inodes[i] == ino) + return 0; + if (state->fc_modified_inodes_used == state->fc_modified_inodes_size) { +- state->fc_modified_inodes_size += +- EXT4_FC_REPLAY_REALLOC_INCREMENT; + state->fc_modified_inodes = krealloc( +- state->fc_modified_inodes, sizeof(int) * +- state->fc_modified_inodes_size, +- GFP_KERNEL); ++ state->fc_modified_inodes, ++ sizeof(int) * (state->fc_modified_inodes_size + ++ EXT4_FC_REPLAY_REALLOC_INCREMENT), ++ GFP_KERNEL); + if (!state->fc_modified_inodes) + return -ENOMEM; ++ state->fc_modified_inodes_size += ++ EXT4_FC_REPLAY_REALLOC_INCREMENT; + } + state->fc_modified_inodes[state->fc_modified_inodes_used++] = ino; + return 0; +@@ -1472,7 +1451,9 @@ static int ext4_fc_replay_inode(struct super_block *sb, struct ext4_fc_tl *tl, + } + inode = NULL; + +- ext4_fc_record_modified_inode(sb, ino); ++ ret = ext4_fc_record_modified_inode(sb, ino); ++ if (ret) ++ goto out; + + raw_fc_inode = (struct ext4_inode *) + (val + offsetof(struct ext4_fc_inode, fc_raw_inode)); +@@ -1603,16 +1584,23 @@ out: + } + + /* +- * Record physical disk regions which are in use as per fast commit area. Our +- * simple replay phase allocator excludes these regions from allocation. ++ * Record physical disk regions which are in use as per fast commit area, ++ * and used by inodes during replay phase. Our simple replay phase ++ * allocator excludes these regions from allocation. + */ +-static int ext4_fc_record_regions(struct super_block *sb, int ino, +- ext4_lblk_t lblk, ext4_fsblk_t pblk, int len) ++int ext4_fc_record_regions(struct super_block *sb, int ino, ++ ext4_lblk_t lblk, ext4_fsblk_t pblk, int len, int replay) + { + struct ext4_fc_replay_state *state; + struct ext4_fc_alloc_region *region; + + state = &EXT4_SB(sb)->s_fc_replay_state; ++ /* ++ * during replay phase, the fc_regions_valid may not same as ++ * fc_regions_used, update it when do new additions. ++ */ ++ if (replay && state->fc_regions_used != state->fc_regions_valid) ++ state->fc_regions_used = state->fc_regions_valid; + if (state->fc_regions_used == state->fc_regions_size) { + state->fc_regions_size += + EXT4_FC_REPLAY_REALLOC_INCREMENT; +@@ -1630,6 +1618,9 @@ static int ext4_fc_record_regions(struct super_block *sb, int ino, + region->pblk = pblk; + region->len = len; + ++ if (replay) ++ state->fc_regions_valid++; ++ + return 0; + } + +@@ -1661,6 +1652,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, + } + + ret = ext4_fc_record_modified_inode(sb, inode->i_ino); ++ if (ret) ++ goto out; + + start = le32_to_cpu(ex->ee_block); + start_pblk = ext4_ext_pblock(ex); +@@ -1678,18 +1671,14 @@ static int ext4_fc_replay_add_range(struct super_block *sb, + map.m_pblk = 0; + ret = ext4_map_blocks(NULL, inode, &map, 0); + +- if (ret < 0) { +- iput(inode); +- return 0; +- } ++ if (ret < 0) ++ goto out; + + if (ret == 0) { + /* Range is not mapped */ + path = ext4_find_extent(inode, cur, NULL, 0); +- if (IS_ERR(path)) { +- iput(inode); +- return 0; +- } ++ if (IS_ERR(path)) ++ goto out; + memset(&newex, 0, sizeof(newex)); + newex.ee_block = cpu_to_le32(cur); + ext4_ext_store_pblock( +@@ -1703,10 +1692,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, + up_write((&EXT4_I(inode)->i_data_sem)); + ext4_ext_drop_refs(path); + kfree(path); +- if (ret) { +- iput(inode); +- return 0; +- } ++ if (ret) ++ goto out; + goto next; + } + +@@ -1719,10 +1706,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, + ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, + ext4_ext_is_unwritten(ex), + start_pblk + cur - start); +- if (ret) { +- iput(inode); +- return 0; +- } ++ if (ret) ++ goto out; + /* + * Mark the old blocks as free since they aren't used + * anymore. We maintain an array of all the modified +@@ -1742,10 +1727,8 @@ static int ext4_fc_replay_add_range(struct super_block *sb, + ext4_ext_is_unwritten(ex), map.m_pblk); + ret = ext4_ext_replay_update_ex(inode, cur, map.m_len, + ext4_ext_is_unwritten(ex), map.m_pblk); +- if (ret) { +- iput(inode); +- return 0; +- } ++ if (ret) ++ goto out; + /* + * We may have split the extent tree while toggling the state. + * Try to shrink the extent tree now. +@@ -1757,6 +1740,7 @@ next: + } + ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >> + sb->s_blocksize_bits); ++out: + iput(inode); + return 0; + } +@@ -1786,6 +1770,8 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, + } + + ret = ext4_fc_record_modified_inode(sb, inode->i_ino); ++ if (ret) ++ goto out; + + jbd_debug(1, "DEL_RANGE, inode %ld, lblk %d, len %d\n", + inode->i_ino, le32_to_cpu(lrange.fc_lblk), +@@ -1795,10 +1781,8 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, + map.m_len = remaining; + + ret = ext4_map_blocks(NULL, inode, &map, 0); +- if (ret < 0) { +- iput(inode); +- return 0; +- } ++ if (ret < 0) ++ goto out; + if (ret > 0) { + remaining -= ret; + cur += ret; +@@ -1809,16 +1793,18 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl, + } + } + +- ret = ext4_punch_hole(inode, +- le32_to_cpu(lrange.fc_lblk) << sb->s_blocksize_bits, +- le32_to_cpu(lrange.fc_len) << sb->s_blocksize_bits); ++ down_write(&EXT4_I(inode)->i_data_sem); ++ ret = ext4_ext_remove_space(inode, le32_to_cpu(lrange.fc_lblk), ++ le32_to_cpu(lrange.fc_lblk) + ++ le32_to_cpu(lrange.fc_len) - 1); ++ up_write(&EXT4_I(inode)->i_data_sem); + if (ret) +- jbd_debug(1, "ext4_punch_hole returned %d", ret); ++ goto out; + ext4_ext_replay_shrink_inode(inode, + i_size_read(inode) >> sb->s_blocksize_bits); + ext4_mark_inode_dirty(NULL, inode); ++out: + iput(inode); +- + return 0; + } + +@@ -1970,7 +1956,7 @@ static int ext4_fc_replay_scan(journal_t *journal, + ret = ext4_fc_record_regions(sb, + le32_to_cpu(ext.fc_ino), + le32_to_cpu(ex->ee_block), ext4_ext_pblock(ex), +- ext4_ext_get_actual_len(ex)); ++ ext4_ext_get_actual_len(ex), 0); + if (ret < 0) + break; + ret = JBD2_FC_REPLAY_CONTINUE; +@@ -2166,7 +2152,7 @@ int ext4_fc_info_show(struct seq_file *seq, void *v) + "fc stats:\n%ld commits\n%ld ineligible\n%ld numblks\n%lluus avg_commit_time\n", + stats->fc_num_commits, stats->fc_ineligible_commits, + stats->fc_numblks, +- div_u64(sbi->s_fc_avg_commit_time, 1000)); ++ div_u64(stats->s_fc_avg_commit_time, 1000)); + seq_puts(seq, "Ineligible reasons:\n"); + for (i = 0; i < EXT4_FC_REASON_MAX; i++) + seq_printf(seq, "\"%s\":\t%d\n", fc_ineligible_reasons[i], +@@ -2185,3 +2171,8 @@ int __init ext4_fc_init_dentry_cache(void) + + return 0; + } ++ ++void ext4_fc_destroy_dentry_cache(void) ++{ ++ kmem_cache_destroy(ext4_fc_dentry_cachep); ++} +diff --git a/fs/ext4/fast_commit.h b/fs/ext4/fast_commit.h +index 937c381b4c85e..083ad1cb705a7 100644 +--- a/fs/ext4/fast_commit.h ++++ b/fs/ext4/fast_commit.h +@@ -71,21 +71,19 @@ struct ext4_fc_tail { + }; + + /* +- * Fast commit reason codes ++ * Fast commit status codes ++ */ ++enum { ++ EXT4_FC_STATUS_OK = 0, ++ EXT4_FC_STATUS_INELIGIBLE, ++ EXT4_FC_STATUS_SKIPPED, ++ EXT4_FC_STATUS_FAILED, ++}; ++ ++/* ++ * Fast commit ineligiblity reasons: + */ + enum { +- /* +- * Commit status codes: +- */ +- EXT4_FC_REASON_OK = 0, +- EXT4_FC_REASON_INELIGIBLE, +- EXT4_FC_REASON_ALREADY_COMMITTED, +- EXT4_FC_REASON_FC_START_FAILED, +- EXT4_FC_REASON_FC_FAILED, +- +- /* +- * Fast commit ineligiblity reasons: +- */ + EXT4_FC_REASON_XATTR = 0, + EXT4_FC_REASON_CROSS_RENAME, + EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, +@@ -117,7 +115,10 @@ struct ext4_fc_stats { + unsigned int fc_ineligible_reason_count[EXT4_FC_REASON_MAX]; + unsigned long fc_num_commits; + unsigned long fc_ineligible_commits; ++ unsigned long fc_failed_commits; ++ unsigned long fc_skipped_commits; + unsigned long fc_numblks; ++ u64 s_fc_avg_commit_time; + }; + + #define EXT4_FC_REPLAY_REALLOC_INCREMENT 4 +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 39a1ab129fdc9..d091133a4b460 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1133,7 +1133,15 @@ static void ext4_restore_inline_data(handle_t *handle, struct inode *inode, + struct ext4_iloc *iloc, + void *buf, int inline_size) + { +- ext4_create_inline_data(handle, inode, inline_size); ++ int ret; ++ ++ ret = ext4_create_inline_data(handle, inode, inline_size); ++ if (ret) { ++ ext4_msg(inode->i_sb, KERN_EMERG, ++ "error restoring inline_data for inode -- potential data loss! (inode %lu, error %d)", ++ inode->i_ino, ret); ++ return; ++ } + ext4_write_inline_data(inode, iloc, buf, 0, inline_size); + ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); + } +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 0f06305167d5a..22a5140546fb6 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -337,7 +337,7 @@ stop_handle: + return; + no_delete: + if (!list_empty(&EXT4_I(inode)->i_fc_list)) +- ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM); ++ ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); + ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ + } + +@@ -741,10 +741,11 @@ out_sem: + if (ret) + return ret; + } +- ext4_fc_track_range(handle, inode, map->m_lblk, +- map->m_lblk + map->m_len - 1); + } +- ++ if (retval > 0 && (map->m_flags & EXT4_MAP_UNWRITTEN || ++ map->m_flags & EXT4_MAP_MAPPED)) ++ ext4_fc_track_range(handle, inode, map->m_lblk, ++ map->m_lblk + map->m_len - 1); + if (retval < 0) + ext_debug(inode, "failed with err %d\n", retval); + return retval; +@@ -1711,16 +1712,13 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, + } + + /* +- * the buffer head associated with a delayed and not unwritten +- * block found in the extent status cache must contain an +- * invalid block number and have its BH_New and BH_Delay bits +- * set, reflecting the state assigned when the block was +- * initially delayed allocated ++ * Delayed extent could be allocated by fallocate. ++ * So we need to check it. + */ +- if (ext4_es_is_delonly(&es)) { +- BUG_ON(bh->b_blocknr != invalid_block); +- BUG_ON(!buffer_new(bh)); +- BUG_ON(!buffer_delay(bh)); ++ if (ext4_es_is_delayed(&es) && !ext4_es_is_unwritten(&es)) { ++ map_bh(bh, inode->i_sb, invalid_block); ++ set_buffer_new(bh); ++ set_buffer_delay(bh); + return 0; + } + +@@ -1847,30 +1845,16 @@ int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, + return 0; + } + +-static int bget_one(handle_t *handle, struct inode *inode, +- struct buffer_head *bh) +-{ +- get_bh(bh); +- return 0; +-} +- +-static int bput_one(handle_t *handle, struct inode *inode, +- struct buffer_head *bh) +-{ +- put_bh(bh); +- return 0; +-} +- + static int __ext4_journalled_writepage(struct page *page, + unsigned int len) + { + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; +- struct buffer_head *page_bufs = NULL; + handle_t *handle = NULL; + int ret = 0, err = 0; + int inline_data = ext4_has_inline_data(inode); + struct buffer_head *inode_bh = NULL; ++ loff_t size; + + ClearPageChecked(page); + +@@ -1880,14 +1864,6 @@ static int __ext4_journalled_writepage(struct page *page, + inode_bh = ext4_journalled_write_inline_data(inode, len, page); + if (inode_bh == NULL) + goto out; +- } else { +- page_bufs = page_buffers(page); +- if (!page_bufs) { +- BUG(); +- goto out; +- } +- ext4_walk_page_buffers(handle, inode, page_bufs, 0, len, +- NULL, bget_one); + } + /* + * We need to release the page lock before we start the +@@ -1908,7 +1884,8 @@ static int __ext4_journalled_writepage(struct page *page, + + lock_page(page); + put_page(page); +- if (page->mapping != mapping) { ++ size = i_size_read(inode); ++ if (page->mapping != mapping || page_offset(page) > size) { + /* The page got truncated from under us */ + ext4_journal_stop(handle); + ret = 0; +@@ -1918,6 +1895,13 @@ static int __ext4_journalled_writepage(struct page *page, + if (inline_data) { + ret = ext4_mark_inode_dirty(handle, inode); + } else { ++ struct buffer_head *page_bufs = page_buffers(page); ++ ++ if (page->index == size >> PAGE_SHIFT) ++ len = size & ~PAGE_MASK; ++ else ++ len = PAGE_SIZE; ++ + ret = ext4_walk_page_buffers(handle, inode, page_bufs, 0, len, + NULL, do_journal_get_write_access); + +@@ -1938,9 +1922,6 @@ static int __ext4_journalled_writepage(struct page *page, + out: + unlock_page(page); + out_no_pagelock: +- if (!inline_data && page_bufs) +- ext4_walk_page_buffers(NULL, inode, page_bufs, 0, len, +- NULL, bput_one); + brelse(inode_bh); + return ret; + } +@@ -4374,7 +4355,7 @@ has_buffer: + static int __ext4_get_inode_loc_noinmem(struct inode *inode, + struct ext4_iloc *iloc) + { +- ext4_fsblk_t err_blk; ++ ext4_fsblk_t err_blk = 0; + int ret; + + ret = __ext4_get_inode_loc(inode->i_sb, inode->i_ino, iloc, 0, +@@ -4389,7 +4370,7 @@ static int __ext4_get_inode_loc_noinmem(struct inode *inode, + + int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc) + { +- ext4_fsblk_t err_blk; ++ ext4_fsblk_t err_blk = 0; + int ret; + + /* We have all inode data except xattrs in memory here. */ +@@ -5416,8 +5397,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, + ext4_fc_track_range(handle, inode, + (attr->ia_size > 0 ? attr->ia_size - 1 : 0) >> + inode->i_sb->s_blocksize_bits, +- (oldsize > 0 ? oldsize - 1 : 0) >> +- inode->i_sb->s_blocksize_bits); ++ EXT_MAX_BLOCKS - 1); + else + ext4_fc_track_range( + handle, inode, +@@ -5989,7 +5969,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val) + return PTR_ERR(handle); + + ext4_fc_mark_ineligible(inode->i_sb, +- EXT4_FC_REASON_JOURNAL_FLAG_CHANGE); ++ EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, handle); + err = ext4_mark_inode_dirty(handle, inode); + ext4_handle_sync(handle); + ext4_journal_stop(handle); +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index 606dee9e08a32..f61b59045c6d3 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -169,7 +169,7 @@ static long swap_inode_boot_loader(struct super_block *sb, + err = -EINVAL; + goto err_out; + } +- ext4_fc_start_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT); ++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT, handle); + + /* Protect extent tree against block allocations via delalloc */ + ext4_double_down_write_data_sem(inode, inode_bl); +@@ -252,7 +252,6 @@ revert: + + err_out1: + ext4_journal_stop(handle); +- ext4_fc_stop_ineligible(sb); + ext4_double_up_write_data_sem(inode, inode_bl); + + err_out: +@@ -1076,7 +1075,7 @@ mext_out: + + err = ext4_resize_fs(sb, n_blocks_count); + if (EXT4_SB(sb)->s_journal) { +- ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE); ++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, NULL); + jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); + err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); + jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); +@@ -1117,8 +1116,6 @@ resizefs_out: + sizeof(range))) + return -EFAULT; + +- range.minlen = max((unsigned int)range.minlen, +- q->limits.discard_granularity); + ret = ext4_trim_fs(sb, &range); + if (ret < 0) + return ret; +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 72bfac2d6dce9..74e3286d0e262 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -4814,7 +4814,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b, + */ + static noinline_for_stack int + ext4_mb_discard_group_preallocations(struct super_block *sb, +- ext4_group_t group, int needed) ++ ext4_group_t group, int *busy) + { + struct ext4_group_info *grp = ext4_get_group_info(sb, group); + struct buffer_head *bitmap_bh = NULL; +@@ -4822,8 +4822,7 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, + struct list_head list; + struct ext4_buddy e4b; + int err; +- int busy = 0; +- int free, free_total = 0; ++ int free = 0; + + mb_debug(sb, "discard preallocation for group %u\n", group); + if (list_empty(&grp->bb_prealloc_list)) +@@ -4846,19 +4845,14 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, + goto out_dbg; + } + +- if (needed == 0) +- needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1; +- + INIT_LIST_HEAD(&list); +-repeat: +- free = 0; + ext4_lock_group(sb, group); + list_for_each_entry_safe(pa, tmp, + &grp->bb_prealloc_list, pa_group_list) { + spin_lock(&pa->pa_lock); + if (atomic_read(&pa->pa_count)) { + spin_unlock(&pa->pa_lock); +- busy = 1; ++ *busy = 1; + continue; + } + if (pa->pa_deleted) { +@@ -4898,22 +4892,13 @@ repeat: + call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback); + } + +- free_total += free; +- +- /* if we still need more blocks and some PAs were used, try again */ +- if (free_total < needed && busy) { +- ext4_unlock_group(sb, group); +- cond_resched(); +- busy = 0; +- goto repeat; +- } + ext4_unlock_group(sb, group); + ext4_mb_unload_buddy(&e4b); + put_bh(bitmap_bh); + out_dbg: + mb_debug(sb, "discarded (%d) blocks preallocated for group %u bb_free (%d)\n", +- free_total, group, grp->bb_free); +- return free_total; ++ free, group, grp->bb_free); ++ return free; + } + + /* +@@ -5455,13 +5440,24 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed) + { + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + int ret; +- int freed = 0; ++ int freed = 0, busy = 0; ++ int retry = 0; + + trace_ext4_mb_discard_preallocations(sb, needed); ++ ++ if (needed == 0) ++ needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1; ++ repeat: + for (i = 0; i < ngroups && needed > 0; i++) { +- ret = ext4_mb_discard_group_preallocations(sb, i, needed); ++ ret = ext4_mb_discard_group_preallocations(sb, i, &busy); + freed += ret; + needed -= ret; ++ cond_resched(); ++ } ++ ++ if (needed > 0 && busy && ++retry < 3) { ++ busy = 0; ++ goto repeat; + } + + return freed; +@@ -5757,7 +5753,8 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle, + struct super_block *sb = ar->inode->i_sb; + ext4_group_t group; + ext4_grpblk_t blkoff; +- int i = sb->s_blocksize; ++ ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb); ++ ext4_grpblk_t i = 0; + ext4_fsblk_t goal, block; + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + +@@ -5779,19 +5776,26 @@ static ext4_fsblk_t ext4_mb_new_blocks_simple(handle_t *handle, + ext4_get_group_no_and_offset(sb, + max(ext4_group_first_block_no(sb, group), goal), + NULL, &blkoff); +- i = mb_find_next_zero_bit(bitmap_bh->b_data, sb->s_blocksize, ++ while (1) { ++ i = mb_find_next_zero_bit(bitmap_bh->b_data, max, + blkoff); ++ if (i >= max) ++ break; ++ if (ext4_fc_replay_check_excluded(sb, ++ ext4_group_first_block_no(sb, group) + i)) { ++ blkoff = i + 1; ++ } else ++ break; ++ } + brelse(bitmap_bh); +- if (i >= sb->s_blocksize) +- continue; +- if (ext4_fc_replay_check_excluded(sb, +- ext4_group_first_block_no(sb, group) + i)) +- continue; +- break; ++ if (i < max) ++ break; + } + +- if (group >= ext4_get_groups_count(sb) && i >= sb->s_blocksize) ++ if (group >= ext4_get_groups_count(sb) || i >= max) { ++ *errp = -ENOSPC; + return 0; ++ } + + block = ext4_group_first_block_no(sb, group) + i; + ext4_mb_mark_bb(sb, block, 1, 1); +@@ -6405,6 +6409,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + */ + int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + { ++ struct request_queue *q = bdev_get_queue(sb->s_bdev); + struct ext4_group_info *grp; + ext4_group_t group, first_group, last_group; + ext4_grpblk_t cnt = 0, first_cluster, last_cluster; +@@ -6423,6 +6428,13 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + start >= max_blks || + range->len < sb->s_blocksize) + return -EINVAL; ++ /* No point to try to trim less than discard granularity */ ++ if (range->minlen < q->limits.discard_granularity) { ++ minlen = EXT4_NUM_B2C(EXT4_SB(sb), ++ q->limits.discard_granularity >> sb->s_blocksize_bits); ++ if (minlen > EXT4_CLUSTERS_PER_GROUP(sb)) ++ goto out; ++ } + if (end >= max_blks) + end = max_blks - 1; + if (end <= first_data_blk) +diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c +index 7e0b4f81c6c06..ff8916e1d38e9 100644 +--- a/fs/ext4/migrate.c ++++ b/fs/ext4/migrate.c +@@ -437,12 +437,12 @@ int ext4_ext_migrate(struct inode *inode) + percpu_down_write(&sbi->s_writepages_rwsem); + + /* +- * Worst case we can touch the allocation bitmaps, a bgd +- * block, and a block to link in the orphan list. We do need +- * need to worry about credits for modifying the quota inode. ++ * Worst case we can touch the allocation bitmaps and a block ++ * group descriptor block. We do need need to worry about ++ * credits for modifying the quota inode. + */ + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, +- 4 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb)); ++ 3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb)); + + if (IS_ERR(handle)) { + retval = PTR_ERR(handle); +@@ -459,6 +459,13 @@ int ext4_ext_migrate(struct inode *inode) + ext4_journal_stop(handle); + goto out_unlock; + } ++ /* ++ * Use the correct seed for checksum (i.e. the seed from 'inode'). This ++ * is so that the metadata blocks will have the correct checksum after ++ * the migration. ++ */ ++ ei = EXT4_I(inode); ++ EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed; + i_size_write(tmp_inode, i_size_read(inode)); + /* + * Set the i_nlink to zero so it will be deleted later +@@ -467,7 +474,6 @@ int ext4_ext_migrate(struct inode *inode) + clear_nlink(tmp_inode); + + ext4_ext_tree_init(handle, tmp_inode); +- ext4_orphan_add(handle, tmp_inode); + ext4_journal_stop(handle); + + /* +@@ -492,17 +498,10 @@ int ext4_ext_migrate(struct inode *inode) + + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); + if (IS_ERR(handle)) { +- /* +- * It is impossible to update on-disk structures without +- * a handle, so just rollback in-core changes and live other +- * work to orphan_list_cleanup() +- */ +- ext4_orphan_del(NULL, tmp_inode); + retval = PTR_ERR(handle); + goto out_tmp_inode; + } + +- ei = EXT4_I(inode); + i_data = ei->i_data; + memset(&lb, 0, sizeof(lb)); + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index da7698341d7d3..192ea90e757cc 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3889,7 +3889,7 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + * dirents in directories. + */ + ext4_fc_mark_ineligible(old.inode->i_sb, +- EXT4_FC_REASON_RENAME_DIR); ++ EXT4_FC_REASON_RENAME_DIR, handle); + } else { + if (new.inode) + ext4_fc_track_unlink(handle, new.dentry); +@@ -4049,7 +4049,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, + if (unlikely(retval)) + goto end_rename; + ext4_fc_mark_ineligible(new.inode->i_sb, +- EXT4_FC_REASON_CROSS_RENAME); ++ EXT4_FC_REASON_CROSS_RENAME, handle); + if (old.dir_bh) { + retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino); + if (retval) +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 88d5d274a8684..fd4d34deb9fc6 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3263,9 +3263,9 @@ static int ext4_run_li_request(struct ext4_li_request *elr) + struct super_block *sb = elr->lr_super; + ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; + ext4_group_t group = elr->lr_next_group; +- unsigned long timeout = 0; + unsigned int prefetch_ios = 0; + int ret = 0; ++ u64 start_time; + + if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) { + elr->lr_next_group = ext4_mb_prefetch(sb, group, +@@ -3302,14 +3302,13 @@ static int ext4_run_li_request(struct ext4_li_request *elr) + ret = 1; + + if (!ret) { +- timeout = jiffies; ++ start_time = ktime_get_real_ns(); + ret = ext4_init_inode_table(sb, group, + elr->lr_timeout ? 0 : 1); + trace_ext4_lazy_itable_init(sb, group); + if (elr->lr_timeout == 0) { +- timeout = (jiffies - timeout) * +- EXT4_SB(elr->lr_super)->s_li_wait_mult; +- elr->lr_timeout = timeout; ++ elr->lr_timeout = nsecs_to_jiffies((ktime_get_real_ns() - start_time) * ++ EXT4_SB(elr->lr_super)->s_li_wait_mult); + } + elr->lr_next_sched = jiffies + elr->lr_timeout; + elr->lr_next_group = group + 1; +@@ -4614,14 +4613,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + + /* Initialize fast commit stuff */ + atomic_set(&sbi->s_fc_subtid, 0); +- atomic_set(&sbi->s_fc_ineligible_updates, 0); + INIT_LIST_HEAD(&sbi->s_fc_q[FC_Q_MAIN]); + INIT_LIST_HEAD(&sbi->s_fc_q[FC_Q_STAGING]); + INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_MAIN]); + INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]); + sbi->s_fc_bytes = 0; + ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); +- ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); ++ sbi->s_fc_ineligible_tid = 0; + spin_lock_init(&sbi->s_fc_lock); + memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats)); + sbi->s_fc_replay_state.fc_regions = NULL; +@@ -6267,10 +6265,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, + + lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA); + err = dquot_quota_on(sb, type, format_id, path); +- if (err) { +- lockdep_set_quota_inode(path->dentry->d_inode, +- I_DATA_SEM_NORMAL); +- } else { ++ if (!err) { + struct inode *inode = d_inode(path->dentry); + handle_t *handle; + +@@ -6290,7 +6285,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, + ext4_journal_stop(handle); + unlock_inode: + inode_unlock(inode); ++ if (err) ++ dquot_quota_off(sb, type); + } ++ if (err) ++ lockdep_set_quota_inode(path->dentry->d_inode, ++ I_DATA_SEM_NORMAL); + return err; + } + +@@ -6353,8 +6353,19 @@ int ext4_enable_quotas(struct super_block *sb) + "Failed to enable quota tracking " + "(type=%d, err=%d). Please run " + "e2fsck to fix.", type, err); +- for (type--; type >= 0; type--) ++ for (type--; type >= 0; type--) { ++ struct inode *inode; ++ ++ inode = sb_dqopt(sb)->files[type]; ++ if (inode) ++ inode = igrab(inode); + dquot_quota_off(sb, type); ++ if (inode) { ++ lockdep_set_quota_inode(inode, ++ I_DATA_SEM_NORMAL); ++ iput(inode); ++ } ++ } + + return err; + } +@@ -6458,7 +6469,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, + struct buffer_head *bh; + handle_t *handle = journal_current_handle(); + +- if (EXT4_SB(sb)->s_journal && !handle) { ++ if (!handle) { + ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)" + " cancelled because transaction is not started", + (unsigned long long)off, (unsigned long long)len); +@@ -6641,6 +6652,7 @@ static int __init ext4_init_fs(void) + out: + unregister_as_ext2(); + unregister_as_ext3(); ++ ext4_fc_destroy_dentry_cache(); + out05: + destroy_inodecache(); + out1: +@@ -6667,6 +6679,7 @@ static void __exit ext4_exit_fs(void) + unregister_as_ext2(); + unregister_as_ext3(); + unregister_filesystem(&ext4_fs_type); ++ ext4_fc_destroy_dentry_cache(); + destroy_inodecache(); + ext4_exit_mballoc(); + ext4_exit_sysfs(); +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 1e0fc1ed845bf..0423253490986 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2408,7 +2408,7 @@ retry_inode: + if (IS_SYNC(inode)) + ext4_handle_sync(handle); + } +- ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); ++ ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle); + + cleanup: + brelse(is.iloc.bh); +@@ -2486,7 +2486,7 @@ retry: + if (error == 0) + error = error2; + } +- ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); ++ ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, NULL); + + return error; + } +@@ -2920,7 +2920,7 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, + error); + goto cleanup; + } +- ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); ++ ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle); + } + error = 0; + cleanup: +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index 83e9bc0f91ffd..99fced979718e 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -1162,7 +1162,8 @@ static bool __need_flush_quota(struct f2fs_sb_info *sbi) + if (!is_journalled_quota(sbi)) + return false; + +- down_write(&sbi->quota_sem); ++ if (!down_write_trylock(&sbi->quota_sem)) ++ return true; + if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) { + ret = false; + } else if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) { +@@ -1304,8 +1305,8 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) + unsigned long flags; + + if (cpc->reason & CP_UMOUNT) { +- if (le32_to_cpu(ckpt->cp_pack_total_block_count) > +- sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks) { ++ if (le32_to_cpu(ckpt->cp_pack_total_block_count) + ++ NM_I(sbi)->nat_bits_blocks > sbi->blocks_per_seg) { + clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG); + f2fs_notice(sbi, "Disable nat_bits due to no space"); + } else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) && +diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c +index c1bf9ad4c2207..58d255d3a518a 100644 +--- a/fs/f2fs/compress.c ++++ b/fs/f2fs/compress.c +@@ -1448,25 +1448,38 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc, + enum iostat_type io_type) + { + struct address_space *mapping = cc->inode->i_mapping; +- int _submitted, compr_blocks, ret; +- int i = -1, err = 0; ++ int _submitted, compr_blocks, ret, i; + + compr_blocks = f2fs_compressed_blocks(cc); +- if (compr_blocks < 0) { +- err = compr_blocks; +- goto out_err; ++ ++ for (i = 0; i < cc->cluster_size; i++) { ++ if (!cc->rpages[i]) ++ continue; ++ ++ redirty_page_for_writepage(wbc, cc->rpages[i]); ++ unlock_page(cc->rpages[i]); + } + ++ if (compr_blocks < 0) ++ return compr_blocks; ++ + for (i = 0; i < cc->cluster_size; i++) { + if (!cc->rpages[i]) + continue; + retry_write: ++ lock_page(cc->rpages[i]); ++ + if (cc->rpages[i]->mapping != mapping) { ++continue_unlock: + unlock_page(cc->rpages[i]); + continue; + } + +- BUG_ON(!PageLocked(cc->rpages[i])); ++ if (!PageDirty(cc->rpages[i])) ++ goto continue_unlock; ++ ++ if (!clear_page_dirty_for_io(cc->rpages[i])) ++ goto continue_unlock; + + ret = f2fs_write_single_data_page(cc->rpages[i], &_submitted, + NULL, NULL, wbc, io_type, +@@ -1481,26 +1494,15 @@ retry_write: + * avoid deadlock caused by cluster update race + * from foreground operation. + */ +- if (IS_NOQUOTA(cc->inode)) { +- err = 0; +- goto out_err; +- } ++ if (IS_NOQUOTA(cc->inode)) ++ return 0; + ret = 0; + cond_resched(); + congestion_wait(BLK_RW_ASYNC, + DEFAULT_IO_TIMEOUT); +- lock_page(cc->rpages[i]); +- +- if (!PageDirty(cc->rpages[i])) { +- unlock_page(cc->rpages[i]); +- continue; +- } +- +- clear_page_dirty_for_io(cc->rpages[i]); + goto retry_write; + } +- err = ret; +- goto out_err; ++ return ret; + } + + *submitted += _submitted; +@@ -1509,14 +1511,6 @@ retry_write: + f2fs_balance_fs(F2FS_M_SB(mapping), true); + + return 0; +-out_err: +- for (++i; i < cc->cluster_size; i++) { +- if (!cc->rpages[i]) +- continue; +- redirty_page_for_writepage(wbc, cc->rpages[i]); +- unlock_page(cc->rpages[i]); +- } +- return err; + } + + int f2fs_write_multi_pages(struct compress_ctx *cc, +@@ -1530,6 +1524,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc, + if (cluster_may_compress(cc)) { + err = f2fs_compress_pages(cc); + if (err == -EAGAIN) { ++ add_compr_block_stat(cc->inode, cc->cluster_size); + goto write; + } else if (err) { + f2fs_put_rpages_wbc(cc, wbc, true, 1); +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index f4fd6c246c9a9..e662355cf8c9b 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -2564,6 +2564,11 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) + { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + ++ /* The below cases were checked when setting it. */ ++ if (f2fs_is_pinned_file(inode)) ++ return false; ++ if (fio && is_sbi_flag_set(sbi, SBI_NEED_FSCK)) ++ return true; + if (f2fs_lfs_mode(sbi)) + return true; + if (S_ISDIR(inode->i_mode)) +@@ -2572,8 +2577,6 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) + return true; + if (f2fs_is_atomic_file(inode)) + return true; +- if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) +- return true; + + /* swap file is migrating in aligned write mode */ + if (is_inode_flag_set(inode, FI_ALIGNED_WRITE)) +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index b339ae89c1ad1..c68817d83a53b 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -1012,6 +1012,7 @@ struct f2fs_sm_info { + unsigned int segment_count; /* total # of segments */ + unsigned int main_segments; /* # of segments in main area */ + unsigned int reserved_segments; /* # of reserved segments */ ++ unsigned int additional_reserved_segments;/* reserved segs for IO align feature */ + unsigned int ovp_segments; /* # of overprovision segments */ + + /* a threshold to reclaim prefree segments */ +@@ -2184,6 +2185,11 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, + + if (!__allow_reserved_blocks(sbi, inode, true)) + avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks; ++ ++ if (F2FS_IO_ALIGNED(sbi)) ++ avail_user_block_count -= sbi->blocks_per_seg * ++ SM_I(sbi)->additional_reserved_segments; ++ + if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { + if (avail_user_block_count > sbi->unusable_block_count) + avail_user_block_count -= sbi->unusable_block_count; +@@ -2430,6 +2436,11 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, + + if (!__allow_reserved_blocks(sbi, inode, false)) + valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks; ++ ++ if (F2FS_IO_ALIGNED(sbi)) ++ valid_block_count += sbi->blocks_per_seg * ++ SM_I(sbi)->additional_reserved_segments; ++ + user_block_count = sbi->user_block_count; + if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) + user_block_count -= sbi->unusable_block_count; +@@ -4152,8 +4163,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode) + + if (!f2fs_compressed_file(inode)) + return true; +- if (S_ISREG(inode->i_mode) && +- (get_dirty_pages(inode) || atomic_read(&fi->i_compr_blocks))) ++ if (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode)) + return false; + + fi->i_flags &= ~F2FS_COMPR_FL; +diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c +index 9c8ef33bd8d32..7ed44752c7580 100644 +--- a/fs/f2fs/file.c ++++ b/fs/f2fs/file.c +@@ -3143,17 +3143,17 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg) + + inode_lock(inode); + +- if (f2fs_should_update_outplace(inode, NULL)) { +- ret = -EINVAL; +- goto out; +- } +- + if (!pin) { + clear_inode_flag(inode, FI_PIN_FILE); + f2fs_i_gc_failures_write(inode, 0); + goto done; + } + ++ if (f2fs_should_update_outplace(inode, NULL)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + if (f2fs_pin_file_control(inode, false)) { + ret = -EAGAIN; + goto out; +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 77391e3b7d68f..264821df0add1 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1023,6 +1023,9 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + set_sbi_flag(sbi, SBI_NEED_FSCK); + } + ++ if (f2fs_check_nid_range(sbi, dni->ino)) ++ return false; ++ + *nofs = ofs_of_node(node_page); + source_blkaddr = data_blkaddr(NULL, node_page, ofs_in_node); + f2fs_put_page(node_page, 1); +@@ -1036,7 +1039,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + if (!test_and_set_bit(segno, SIT_I(sbi)->invalid_segmap)) { + f2fs_err(sbi, "mismatched blkaddr %u (source_blkaddr %u) in seg %u", + blkaddr, source_blkaddr, segno); +- f2fs_bug_on(sbi, 1); ++ set_sbi_flag(sbi, SBI_NEED_FSCK); + } + } + #endif +@@ -1454,7 +1457,8 @@ next_step: + + if (phase == 3) { + inode = f2fs_iget(sb, dni.ino); +- if (IS_ERR(inode) || is_bad_inode(inode)) ++ if (IS_ERR(inode) || is_bad_inode(inode) || ++ special_file(inode->i_mode)) + continue; + + if (!down_write_trylock( +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index 9141147b5bb00..4557de37a9119 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -516,6 +516,11 @@ make_now: + } else if (ino == F2FS_COMPRESS_INO(sbi)) { + #ifdef CONFIG_F2FS_FS_COMPRESSION + inode->i_mapping->a_ops = &f2fs_compress_aops; ++ /* ++ * generic_error_remove_page only truncates pages of regular ++ * inode ++ */ ++ inode->i_mode |= S_IFREG; + #endif + mapping_set_gfp_mask(inode->i_mapping, + GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE); +@@ -527,7 +532,7 @@ make_now: + inode->i_op = &f2fs_dir_inode_operations; + inode->i_fop = &f2fs_dir_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; +- inode_nohighmem(inode); ++ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); + } else if (S_ISLNK(inode->i_mode)) { + if (file_is_encrypt(inode)) + inode->i_op = &f2fs_encrypted_symlink_inode_operations; +diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c +index 9c528e583c9d5..ae0838001480a 100644 +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -757,7 +757,7 @@ static int f2fs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, + inode->i_op = &f2fs_dir_inode_operations; + inode->i_fop = &f2fs_dir_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; +- inode_nohighmem(inode); ++ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); + + set_inode_flag(inode, FI_INC_LINK); + f2fs_lock_op(sbi); +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index e863136081b47..556fcd8457f3f 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1443,6 +1443,7 @@ page_hit: + nid, nid_of_node(page), ino_of_node(page), + ofs_of_node(page), cpver_of_node(page), + next_blkaddr_of_node(page)); ++ set_sbi_flag(sbi, SBI_NEED_FSCK); + err = -EINVAL; + out_err: + ClearPageUptodate(page); +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index a135d22474154..d716553bdc025 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -561,7 +561,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg) + goto do_sync; + + /* checkpoint is the only way to shrink partial cached entries */ +- if (f2fs_available_free_memory(sbi, NAT_ENTRIES) || ++ if (f2fs_available_free_memory(sbi, NAT_ENTRIES) && + f2fs_available_free_memory(sbi, INO_ENTRIES)) + return; + +diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h +index 89fff258727d1..b2d82c9f5a16d 100644 +--- a/fs/f2fs/segment.h ++++ b/fs/f2fs/segment.h +@@ -537,7 +537,8 @@ static inline unsigned int free_segments(struct f2fs_sb_info *sbi) + + static inline unsigned int reserved_segments(struct f2fs_sb_info *sbi) + { +- return SM_I(sbi)->reserved_segments; ++ return SM_I(sbi)->reserved_segments + ++ SM_I(sbi)->additional_reserved_segments; + } + + static inline unsigned int free_sections(struct f2fs_sb_info *sbi) +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 78ebc306ee2b5..6174c4f4cee7f 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -327,6 +327,46 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi) + F2FS_OPTION(sbi).s_resgid)); + } + ++static inline int adjust_reserved_segment(struct f2fs_sb_info *sbi) ++{ ++ unsigned int sec_blks = sbi->blocks_per_seg * sbi->segs_per_sec; ++ unsigned int avg_vblocks; ++ unsigned int wanted_reserved_segments; ++ block_t avail_user_block_count; ++ ++ if (!F2FS_IO_ALIGNED(sbi)) ++ return 0; ++ ++ /* average valid block count in section in worst case */ ++ avg_vblocks = sec_blks / F2FS_IO_SIZE(sbi); ++ ++ /* ++ * we need enough free space when migrating one section in worst case ++ */ ++ wanted_reserved_segments = (F2FS_IO_SIZE(sbi) / avg_vblocks) * ++ reserved_segments(sbi); ++ wanted_reserved_segments -= reserved_segments(sbi); ++ ++ avail_user_block_count = sbi->user_block_count - ++ sbi->current_reserved_blocks - ++ F2FS_OPTION(sbi).root_reserved_blocks; ++ ++ if (wanted_reserved_segments * sbi->blocks_per_seg > ++ avail_user_block_count) { ++ f2fs_err(sbi, "IO align feature can't grab additional reserved segment: %u, available segments: %u", ++ wanted_reserved_segments, ++ avail_user_block_count >> sbi->log_blocks_per_seg); ++ return -ENOSPC; ++ } ++ ++ SM_I(sbi)->additional_reserved_segments = wanted_reserved_segments; ++ ++ f2fs_info(sbi, "IO align feature needs additional reserved segment: %u", ++ wanted_reserved_segments); ++ ++ return 0; ++} ++ + static inline void adjust_unusable_cap_perc(struct f2fs_sb_info *sbi) + { + if (!F2FS_OPTION(sbi).unusable_cap_perc) +@@ -1292,7 +1332,7 @@ default_check: + /* Not pass down write hints if the number of active logs is lesser + * than NR_CURSEG_PERSIST_TYPE. + */ +- if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE) ++ if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_PERSIST_TYPE) + F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF; + + if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) { +@@ -3487,7 +3527,7 @@ skip_cross: + NR_CURSEG_PERSIST_TYPE + nat_bits_blocks >= blocks_per_seg)) { + f2fs_warn(sbi, "Insane cp_payload: %u, nat_bits_blocks: %u)", + cp_payload, nat_bits_blocks); +- return -EFSCORRUPTED; ++ return 1; + } + + if (unlikely(f2fs_cp_error(sbi))) { +@@ -4148,6 +4188,10 @@ try_onemore: + goto free_nm; + } + ++ err = adjust_reserved_segment(sbi); ++ if (err) ++ goto free_nm; ++ + /* For write statistics */ + sbi->sectors_written_start = f2fs_get_sectors_written(sbi); + +@@ -4352,6 +4396,8 @@ free_node_inode: + free_stats: + f2fs_destroy_stats(sbi); + free_nm: ++ /* stop discard thread before destroying node manager */ ++ f2fs_stop_discard_thread(sbi); + f2fs_destroy_node_manager(sbi); + free_sm: + f2fs_destroy_segment_manager(sbi); +diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c +index a32fe31c33b8e..abc4344fba394 100644 +--- a/fs/f2fs/sysfs.c ++++ b/fs/f2fs/sysfs.c +@@ -415,7 +415,9 @@ out: + if (a->struct_type == RESERVED_BLOCKS) { + spin_lock(&sbi->stat_lock); + if (t > (unsigned long)(sbi->user_block_count - +- F2FS_OPTION(sbi).root_reserved_blocks)) { ++ F2FS_OPTION(sbi).root_reserved_blocks - ++ sbi->blocks_per_seg * ++ SM_I(sbi)->additional_reserved_segments)) { + spin_unlock(&sbi->stat_lock); + return -EINVAL; + } +diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c +index 1d2d29dcd41ce..6a3b3bec7989d 100644 +--- a/fs/f2fs/xattr.c ++++ b/fs/f2fs/xattr.c +@@ -684,8 +684,17 @@ static int __f2fs_setxattr(struct inode *inode, int index, + } + + last = here; +- while (!IS_XATTR_LAST_ENTRY(last)) ++ while (!IS_XATTR_LAST_ENTRY(last)) { ++ if ((void *)(last) + sizeof(__u32) > last_base_addr || ++ (void *)XATTR_NEXT_ENTRY(last) > last_base_addr) { ++ f2fs_err(F2FS_I_SB(inode), "inode (%lu) has invalid last xattr entry, entry_size: %zu", ++ inode->i_ino, ENTRY_SIZE(last)); ++ set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); ++ error = -EFSCORRUPTED; ++ goto exit; ++ } + last = XATTR_NEXT_ENTRY(last); ++ } + + newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size); + +diff --git a/fs/file.c b/fs/file.c +index 8627dacfc4246..97d212a9b8144 100644 +--- a/fs/file.c ++++ b/fs/file.c +@@ -841,24 +841,68 @@ void do_close_on_exec(struct files_struct *files) + spin_unlock(&files->file_lock); + } + ++static inline struct file *__fget_files_rcu(struct files_struct *files, ++ unsigned int fd, fmode_t mask, unsigned int refs) ++{ ++ for (;;) { ++ struct file *file; ++ struct fdtable *fdt = rcu_dereference_raw(files->fdt); ++ struct file __rcu **fdentry; ++ ++ if (unlikely(fd >= fdt->max_fds)) ++ return NULL; ++ ++ fdentry = fdt->fd + array_index_nospec(fd, fdt->max_fds); ++ file = rcu_dereference_raw(*fdentry); ++ if (unlikely(!file)) ++ return NULL; ++ ++ if (unlikely(file->f_mode & mask)) ++ return NULL; ++ ++ /* ++ * Ok, we have a file pointer. However, because we do ++ * this all locklessly under RCU, we may be racing with ++ * that file being closed. ++ * ++ * Such a race can take two forms: ++ * ++ * (a) the file ref already went down to zero, ++ * and get_file_rcu_many() fails. Just try ++ * again: ++ */ ++ if (unlikely(!get_file_rcu_many(file, refs))) ++ continue; ++ ++ /* ++ * (b) the file table entry has changed under us. ++ * Note that we don't need to re-check the 'fdt->fd' ++ * pointer having changed, because it always goes ++ * hand-in-hand with 'fdt'. ++ * ++ * If so, we need to put our refs and try again. ++ */ ++ if (unlikely(rcu_dereference_raw(files->fdt) != fdt) || ++ unlikely(rcu_dereference_raw(*fdentry) != file)) { ++ fput_many(file, refs); ++ continue; ++ } ++ ++ /* ++ * Ok, we have a ref to the file, and checked that it ++ * still exists. ++ */ ++ return file; ++ } ++} ++ + static struct file *__fget_files(struct files_struct *files, unsigned int fd, + fmode_t mask, unsigned int refs) + { + struct file *file; + + rcu_read_lock(); +-loop: +- file = files_lookup_fd_rcu(files, fd); +- if (file) { +- /* File object ref couldn't be taken. +- * dup2() atomicity guarantee is the reason +- * we loop to catch the new file (or NULL pointer) +- */ +- if (file->f_mode & mask) +- file = NULL; +- else if (!get_file_rcu_many(file, refs)) +- goto loop; +- } ++ file = __fget_files_rcu(files, fd, mask, refs); + rcu_read_unlock(); + + return file; +diff --git a/fs/fs_context.c b/fs/fs_context.c +index b7e43a780a625..24ce12f0db32e 100644 +--- a/fs/fs_context.c ++++ b/fs/fs_context.c +@@ -548,7 +548,7 @@ static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) + param->key); + } + +- if (len > PAGE_SIZE - 2 - size) ++ if (size + len + 2 > PAGE_SIZE) + return invalf(fc, "VFS: Legacy: Cumulative options too large"); + if (strchr(param->key, ',') || + (param->type == fs_value_is_string && +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index dde341a6388a1..a9d21b33da9c4 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -852,6 +852,12 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) + if (!(buf->flags & PIPE_BUF_FLAG_LRU)) + lru_cache_add(newpage); + ++ /* ++ * Release while we have extra ref on stolen page. Otherwise ++ * anon_pipe_buf_release() might think the page can be reused. ++ */ ++ pipe_buf_release(cs->pipe, buf); ++ + err = 0; + spin_lock(&cs->req->waitq.lock); + if (test_bit(FR_ABORTED, &cs->req->flags)) +@@ -2031,8 +2037,12 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, + + pipe_lock(pipe); + out_free: +- for (idx = 0; idx < nbuf; idx++) +- pipe_buf_release(pipe, &bufs[idx]); ++ for (idx = 0; idx < nbuf; idx++) { ++ struct pipe_buffer *buf = &bufs[idx]; ++ ++ if (buf->ops) ++ pipe_buf_release(pipe, buf); ++ } + pipe_unlock(pipe); + + kvfree(bufs); +diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c +index d9b977c0f38dc..80a2181b402b2 100644 +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -738,11 +738,19 @@ static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir, + return create_new_entry(fm, &args, dir, entry, S_IFLNK); + } + ++void fuse_flush_time_update(struct inode *inode) ++{ ++ int err = sync_inode_metadata(inode, 1); ++ ++ mapping_set_error(inode->i_mapping, err); ++} ++ + void fuse_update_ctime(struct inode *inode) + { + if (!IS_NOCMTIME(inode)) { + inode->i_ctime = current_time(inode); + mark_inode_dirty_sync(inode); ++ fuse_flush_time_update(inode); + } + } + +@@ -1071,7 +1079,7 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, + if (!parent) + return -ENOENT; + +- inode_lock(parent); ++ inode_lock_nested(parent, I_MUTEX_PARENT); + if (!S_ISDIR(parent->i_mode)) + goto unlock; + +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index 11404f8c21c75..2004d362361e1 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1848,6 +1848,17 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc) + struct fuse_file *ff; + int err; + ++ /* ++ * Inode is always written before the last reference is dropped and ++ * hence this should not be reached from reclaim. ++ * ++ * Writing back the inode from reclaim can deadlock if the request ++ * processing itself needs an allocation. Allocations triggering ++ * reclaim while serving a request can't be prevented, because it can ++ * involve any number of unrelated userspace processes. ++ */ ++ WARN_ON(wbc->for_reclaim); ++ + ff = __fuse_write_file_get(fi); + err = fuse_flush_times(inode, ff); + if (ff) +@@ -2902,7 +2913,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + + static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end) + { +- int err = filemap_write_and_wait_range(inode->i_mapping, start, -1); ++ int err = filemap_write_and_wait_range(inode->i_mapping, start, LLONG_MAX); + + if (!err) + fuse_sync_writes(inode); +@@ -3002,6 +3013,8 @@ out: + if (lock_inode) + inode_unlock(inode); + ++ fuse_flush_time_update(inode); ++ + return err; + } + +@@ -3111,6 +3124,8 @@ out: + inode_unlock(inode_out); + file_accessed(file_in); + ++ fuse_flush_time_update(inode_out); ++ + return err; + } + +diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h +index f55f9f94b1a4f..a59e36c7deaea 100644 +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -1148,6 +1148,7 @@ int fuse_allow_current_process(struct fuse_conn *fc); + + u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); + ++void fuse_flush_time_update(struct inode *inode); + void fuse_update_ctime(struct inode *inode); + + int fuse_update_attributes(struct inode *inode, struct file *file); +diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c +index 12d49a1914e84..2f999d38c9b4a 100644 +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -118,6 +118,9 @@ static void fuse_evict_inode(struct inode *inode) + { + struct fuse_inode *fi = get_fuse_inode(inode); + ++ /* Will write inode on close/munmap and in all other dirtiers */ ++ WARN_ON(inode->i_state & I_DIRTY_INODE); ++ + truncate_inode_pages_final(&inode->i_data); + clear_inode(inode); + if (inode->i_sb->s_flags & SB_ACTIVE) { +diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c +index 5414c2c335809..fba32141a651b 100644 +--- a/fs/gfs2/bmap.c ++++ b/fs/gfs2/bmap.c +@@ -940,7 +940,7 @@ do_alloc: + else if (height == ip->i_height) + ret = gfs2_hole_size(inode, lblock, len, mp, iomap); + else +- iomap->length = size - pos; ++ iomap->length = size - iomap->offset; + } else if (flags & IOMAP_WRITE) { + u64 alloc_size; + +diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c +index c559827cb6f91..f6d3b3e13d72f 100644 +--- a/fs/gfs2/file.c ++++ b/fs/gfs2/file.c +@@ -711,10 +711,11 @@ static int gfs2_release(struct inode *inode, struct file *file) + kfree(file->private_data); + file->private_data = NULL; + +- if (gfs2_rs_active(&ip->i_res)) +- gfs2_rs_delete(ip, &inode->i_writecount); +- if (file->f_mode & FMODE_WRITE) ++ if (file->f_mode & FMODE_WRITE) { ++ if (gfs2_rs_active(&ip->i_res)) ++ gfs2_rs_delete(ip, &inode->i_writecount); + gfs2_qa_put(ip); ++ } + return 0; + } + +diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c +index e0eaa9cf9fb6f..02cd0ae98208d 100644 +--- a/fs/gfs2/glock.c ++++ b/fs/gfs2/glock.c +@@ -1893,10 +1893,10 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) + do { + rhashtable_walk_start(&iter); + +- while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl)) +- if (gl->gl_name.ln_sbd == sdp && +- lockref_get_not_dead(&gl->gl_lockref)) ++ while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl)) { ++ if (gl->gl_name.ln_sbd == sdp) + examiner(gl); ++ } + + rhashtable_walk_stop(&iter); + } while (cond_resched(), gl == ERR_PTR(-EAGAIN)); +@@ -1919,7 +1919,7 @@ bool gfs2_queue_delete_work(struct gfs2_glock *gl, unsigned long delay) + + void gfs2_cancel_delete_work(struct gfs2_glock *gl) + { +- if (cancel_delayed_work_sync(&gl->gl_delete)) { ++ if (cancel_delayed_work(&gl->gl_delete)) { + clear_bit(GLF_PENDING_DELETE, &gl->gl_flags); + gfs2_glock_put(gl); + } +@@ -1938,7 +1938,6 @@ static void flush_delete_work(struct gfs2_glock *gl) + &gl->gl_delete, 0); + } + } +- gfs2_glock_queue_work(gl, 0); + } + + void gfs2_flush_delete_work(struct gfs2_sbd *sdp) +@@ -1955,10 +1954,10 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp) + + static void thaw_glock(struct gfs2_glock *gl) + { +- if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) { +- gfs2_glock_put(gl); ++ if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) ++ return; ++ if (!lockref_get_not_dead(&gl->gl_lockref)) + return; +- } + set_bit(GLF_REPLY_PENDING, &gl->gl_flags); + gfs2_glock_queue_work(gl, 0); + } +@@ -1974,9 +1973,12 @@ static void clear_glock(struct gfs2_glock *gl) + gfs2_glock_remove_from_lru(gl); + + spin_lock(&gl->gl_lockref.lock); +- if (gl->gl_state != LM_ST_UNLOCKED) +- handle_callback(gl, LM_ST_UNLOCKED, 0, false); +- __gfs2_glock_queue_work(gl, 0); ++ if (!__lockref_is_dead(&gl->gl_lockref)) { ++ gl->gl_lockref.count++; ++ if (gl->gl_state != LM_ST_UNLOCKED) ++ handle_callback(gl, LM_ST_UNLOCKED, 0, false); ++ __gfs2_glock_queue_work(gl, 0); ++ } + spin_unlock(&gl->gl_lockref.lock); + } + +diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c +index 6e00d15ef0a82..cc51b5f5f52d8 100644 +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -1402,13 +1402,6 @@ out: + gfs2_ordered_del_inode(ip); + clear_inode(inode); + gfs2_dir_hash_inval(ip); +- if (ip->i_gl) { +- glock_clear_object(ip->i_gl, ip); +- wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); +- gfs2_glock_add_to_lru(ip->i_gl); +- gfs2_glock_put_eventually(ip->i_gl); +- ip->i_gl = NULL; +- } + if (gfs2_holder_initialized(&ip->i_iopen_gh)) { + struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; + +@@ -1421,6 +1414,13 @@ out: + gfs2_holder_uninit(&ip->i_iopen_gh); + gfs2_glock_put_eventually(gl); + } ++ if (ip->i_gl) { ++ glock_clear_object(ip->i_gl, ip); ++ wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); ++ gfs2_glock_add_to_lru(ip->i_gl); ++ gfs2_glock_put_eventually(ip->i_gl); ++ ip->i_gl = NULL; ++ } + } + + static struct inode *gfs2_alloc_inode(struct super_block *sb) +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index cdfb1ae78a3f8..54c4e0b0dda4a 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -409,10 +409,11 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end) + struct vm_area_struct *vma; + + /* +- * end == 0 indicates that the entire range after +- * start should be unmapped. ++ * end == 0 indicates that the entire range after start should be ++ * unmapped. Note, end is exclusive, whereas the interval tree takes ++ * an inclusive "last". + */ +- vma_interval_tree_foreach(vma, root, start, end ? end : ULONG_MAX) { ++ vma_interval_tree_foreach(vma, root, start, end ? end - 1 : ULONG_MAX) { + unsigned long v_offset; + unsigned long v_end; + +diff --git a/fs/inode.c b/fs/inode.c +index ed0cab8a32db1..9abc88d7959cb 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1782,12 +1782,13 @@ EXPORT_SYMBOL(generic_update_time); + * This does the actual work of updating an inodes time or version. Must have + * had called mnt_want_write() before calling this. + */ +-static int update_time(struct inode *inode, struct timespec64 *time, int flags) ++int inode_update_time(struct inode *inode, struct timespec64 *time, int flags) + { + if (inode->i_op->update_time) + return inode->i_op->update_time(inode, time, flags); + return generic_update_time(inode, time, flags); + } ++EXPORT_SYMBOL(inode_update_time); + + /** + * atime_needs_update - update the access time +@@ -1857,7 +1858,7 @@ void touch_atime(const struct path *path) + * of the fs read only, e.g. subvolumes in Btrfs. + */ + now = current_time(inode); +- update_time(inode, &now, S_ATIME); ++ inode_update_time(inode, &now, S_ATIME); + __mnt_drop_write(mnt); + skip_update: + sb_end_write(inode->i_sb); +@@ -2002,7 +2003,7 @@ int file_update_time(struct file *file) + if (__mnt_want_write_file(file)) + return 0; + +- ret = update_time(inode, &now, sync_it); ++ ret = inode_update_time(inode, &now, sync_it); + __mnt_drop_write_file(file); + + return ret; +diff --git a/fs/io-wq.c b/fs/io-wq.c +index 422a7ed6a9bdb..01d4e3ff3170d 100644 +--- a/fs/io-wq.c ++++ b/fs/io-wq.c +@@ -140,6 +140,8 @@ static void io_wqe_dec_running(struct io_worker *worker); + static bool io_acct_cancel_pending_work(struct io_wqe *wqe, + struct io_wqe_acct *acct, + struct io_cb_cancel_data *match); ++static void create_worker_cb(struct callback_head *cb); ++static void io_wq_cancel_tw_create(struct io_wq *wq); + + static bool io_worker_get(struct io_worker *worker) + { +@@ -174,9 +176,44 @@ static void io_worker_ref_put(struct io_wq *wq) + complete(&wq->worker_done); + } + ++static void io_worker_cancel_cb(struct io_worker *worker) ++{ ++ struct io_wqe_acct *acct = io_wqe_get_acct(worker); ++ struct io_wqe *wqe = worker->wqe; ++ struct io_wq *wq = wqe->wq; ++ ++ atomic_dec(&acct->nr_running); ++ raw_spin_lock(&worker->wqe->lock); ++ acct->nr_workers--; ++ raw_spin_unlock(&worker->wqe->lock); ++ io_worker_ref_put(wq); ++ clear_bit_unlock(0, &worker->create_state); ++ io_worker_release(worker); ++} ++ ++static bool io_task_worker_match(struct callback_head *cb, void *data) ++{ ++ struct io_worker *worker; ++ ++ if (cb->func != create_worker_cb) ++ return false; ++ worker = container_of(cb, struct io_worker, create_work); ++ return worker == data; ++} ++ + static void io_worker_exit(struct io_worker *worker) + { + struct io_wqe *wqe = worker->wqe; ++ struct io_wq *wq = wqe->wq; ++ ++ while (1) { ++ struct callback_head *cb = task_work_cancel_match(wq->task, ++ io_task_worker_match, worker); ++ ++ if (!cb) ++ break; ++ io_worker_cancel_cb(worker); ++ } + + if (refcount_dec_and_test(&worker->ref)) + complete(&worker->ref_done); +@@ -321,10 +358,22 @@ static bool io_queue_worker_create(struct io_worker *worker, + test_and_set_bit_lock(0, &worker->create_state)) + goto fail_release; + ++ atomic_inc(&wq->worker_refs); + init_task_work(&worker->create_work, func); + worker->create_index = acct->index; +- if (!task_work_add(wq->task, &worker->create_work, TWA_SIGNAL)) ++ if (!task_work_add(wq->task, &worker->create_work, TWA_SIGNAL)) { ++ /* ++ * EXIT may have been set after checking it above, check after ++ * adding the task_work and remove any creation item if it is ++ * now set. wq exit does that too, but we can have added this ++ * work item after we canceled in io_wq_exit_workers(). ++ */ ++ if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) ++ io_wq_cancel_tw_create(wq); ++ io_worker_ref_put(wq); + return true; ++ } ++ io_worker_ref_put(wq); + clear_bit_unlock(0, &worker->create_state); + fail_release: + io_worker_release(worker); +@@ -346,7 +395,9 @@ static void io_wqe_dec_running(struct io_worker *worker) + if (atomic_dec_and_test(&acct->nr_running) && io_acct_run_queue(acct)) { + atomic_inc(&acct->nr_running); + atomic_inc(&wqe->wq->worker_refs); ++ raw_spin_unlock(&wqe->lock); + io_queue_worker_create(worker, acct, create_worker_cb); ++ raw_spin_lock(&wqe->lock); + } + } + +@@ -385,9 +436,10 @@ static inline unsigned int io_get_work_hash(struct io_wq_work *work) + return work->flags >> IO_WQ_HASH_SHIFT; + } + +-static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) ++static bool io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) + { + struct io_wq *wq = wqe->wq; ++ bool ret = false; + + spin_lock_irq(&wq->hash->wait.lock); + if (list_empty(&wqe->wait.entry)) { +@@ -395,9 +447,11 @@ static void io_wait_on_hash(struct io_wqe *wqe, unsigned int hash) + if (!test_bit(hash, &wq->hash->map)) { + __set_current_state(TASK_RUNNING); + list_del_init(&wqe->wait.entry); ++ ret = true; + } + } + spin_unlock_irq(&wq->hash->wait.lock); ++ return ret; + } + + static struct io_wq_work *io_get_next_work(struct io_wqe_acct *acct, +@@ -437,14 +491,21 @@ static struct io_wq_work *io_get_next_work(struct io_wqe_acct *acct, + } + + if (stall_hash != -1U) { ++ bool unstalled; ++ + /* + * Set this before dropping the lock to avoid racing with new + * work being added and clearing the stalled bit. + */ + set_bit(IO_ACCT_STALLED_BIT, &acct->flags); + raw_spin_unlock(&wqe->lock); +- io_wait_on_hash(wqe, stall_hash); ++ unstalled = io_wait_on_hash(wqe, stall_hash); + raw_spin_lock(&wqe->lock); ++ if (unstalled) { ++ clear_bit(IO_ACCT_STALLED_BIT, &acct->flags); ++ if (wq_has_sleeper(&wqe->wq->hash->wait)) ++ wake_up(&wqe->wq->hash->wait); ++ } + } + + return NULL; +@@ -526,8 +587,11 @@ get_next: + io_wqe_enqueue(wqe, linked); + + if (hash != -1U && !next_hashed) { ++ /* serialize hash clear with wake_up() */ ++ spin_lock_irq(&wq->hash->wait.lock); + clear_bit(hash, &wq->hash->map); + clear_bit(IO_ACCT_STALLED_BIT, &acct->flags); ++ spin_unlock_irq(&wq->hash->wait.lock); + if (wq_has_sleeper(&wq->hash->wait)) + wake_up(&wq->hash->wait); + raw_spin_lock(&wqe->lock); +@@ -660,6 +724,13 @@ static bool io_wq_work_match_all(struct io_wq_work *work, void *data) + + static inline bool io_should_retry_thread(long err) + { ++ /* ++ * Prevent perpetual task_work retry, if the task (or its group) is ++ * exiting. ++ */ ++ if (fatal_signal_pending(current)) ++ return false; ++ + switch (err) { + case -EAGAIN: + case -ERESTARTSYS: +@@ -716,11 +787,8 @@ static void io_workqueue_create(struct work_struct *work) + struct io_worker *worker = container_of(work, struct io_worker, work); + struct io_wqe_acct *acct = io_wqe_get_acct(worker); + +- if (!io_queue_worker_create(worker, acct, create_worker_cont)) { +- clear_bit_unlock(0, &worker->create_state); +- io_worker_release(worker); ++ if (!io_queue_worker_create(worker, acct, create_worker_cont)) + kfree(worker); +- } + } + + static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index) +@@ -1140,28 +1208,26 @@ void io_wq_exit_start(struct io_wq *wq) + set_bit(IO_WQ_BIT_EXIT, &wq->state); + } + +-static void io_wq_exit_workers(struct io_wq *wq) ++static void io_wq_cancel_tw_create(struct io_wq *wq) + { + struct callback_head *cb; +- int node; +- +- if (!wq->task) +- return; + + while ((cb = task_work_cancel_match(wq->task, io_task_work_match, wq)) != NULL) { + struct io_worker *worker; +- struct io_wqe_acct *acct; + + worker = container_of(cb, struct io_worker, create_work); +- acct = io_wqe_get_acct(worker); +- atomic_dec(&acct->nr_running); +- raw_spin_lock(&worker->wqe->lock); +- acct->nr_workers--; +- raw_spin_unlock(&worker->wqe->lock); +- io_worker_ref_put(wq); +- clear_bit_unlock(0, &worker->create_state); +- io_worker_release(worker); ++ io_worker_cancel_cb(worker); + } ++} ++ ++static void io_wq_exit_workers(struct io_wq *wq) ++{ ++ int node; ++ ++ if (!wq->task) ++ return; ++ ++ io_wq_cancel_tw_create(wq); + + rcu_read_lock(); + for_each_node(node) { +@@ -1278,7 +1344,9 @@ int io_wq_cpu_affinity(struct io_wq *wq, cpumask_var_t mask) + */ + int io_wq_max_workers(struct io_wq *wq, int *new_count) + { +- int i, node, prev = 0; ++ int prev[IO_WQ_ACCT_NR]; ++ bool first_node = true; ++ int i, node; + + BUILD_BUG_ON((int) IO_WQ_ACCT_BOUND != (int) IO_WQ_BOUND); + BUILD_BUG_ON((int) IO_WQ_ACCT_UNBOUND != (int) IO_WQ_UNBOUND); +@@ -1289,6 +1357,9 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count) + new_count[i] = task_rlimit(current, RLIMIT_NPROC); + } + ++ for (i = 0; i < IO_WQ_ACCT_NR; i++) ++ prev[i] = 0; ++ + rcu_read_lock(); + for_each_node(node) { + struct io_wqe *wqe = wq->wqes[node]; +@@ -1297,14 +1368,19 @@ int io_wq_max_workers(struct io_wq *wq, int *new_count) + raw_spin_lock(&wqe->lock); + for (i = 0; i < IO_WQ_ACCT_NR; i++) { + acct = &wqe->acct[i]; +- prev = max_t(int, acct->max_workers, prev); ++ if (first_node) ++ prev[i] = max_t(int, acct->max_workers, prev[i]); + if (new_count[i]) + acct->max_workers = new_count[i]; +- new_count[i] = prev; + } + raw_spin_unlock(&wqe->lock); ++ first_node = false; + } + rcu_read_unlock(); ++ ++ for (i = 0; i < IO_WQ_ACCT_NR; i++) ++ new_count[i] = prev[i]; ++ + return 0; + } + +diff --git a/fs/io_uring.c b/fs/io_uring.c +index bc18af5e0a934..156c54ebb62b7 100644 +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -1204,6 +1204,7 @@ static void io_refs_resurrect(struct percpu_ref *ref, struct completion *compl) + + static bool io_match_task(struct io_kiocb *head, struct task_struct *task, + bool cancel_all) ++ __must_hold(&req->ctx->timeout_lock) + { + struct io_kiocb *req; + +@@ -1219,6 +1220,44 @@ static bool io_match_task(struct io_kiocb *head, struct task_struct *task, + return false; + } + ++static bool io_match_linked(struct io_kiocb *head) ++{ ++ struct io_kiocb *req; ++ ++ io_for_each_link(req, head) { ++ if (req->flags & REQ_F_INFLIGHT) ++ return true; ++ } ++ return false; ++} ++ ++/* ++ * As io_match_task() but protected against racing with linked timeouts. ++ * User must not hold timeout_lock. ++ */ ++static bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task, ++ bool cancel_all) ++{ ++ bool matched; ++ ++ if (task && head->task != task) ++ return false; ++ if (cancel_all) ++ return true; ++ ++ if (head->flags & REQ_F_LINK_TIMEOUT) { ++ struct io_ring_ctx *ctx = head->ctx; ++ ++ /* protect against races with linked timeouts */ ++ spin_lock_irq(&ctx->timeout_lock); ++ matched = io_match_linked(head); ++ spin_unlock_irq(&ctx->timeout_lock); ++ } else { ++ matched = io_match_linked(head); ++ } ++ return matched; ++} ++ + static inline void req_set_fail(struct io_kiocb *req) + { + req->flags |= REQ_F_FAIL; +@@ -1430,10 +1469,10 @@ static void io_prep_async_link(struct io_kiocb *req) + if (req->flags & REQ_F_LINK_TIMEOUT) { + struct io_ring_ctx *ctx = req->ctx; + +- spin_lock(&ctx->completion_lock); ++ spin_lock_irq(&ctx->timeout_lock); + io_for_each_link(cur, req) + io_prep_async_work(cur); +- spin_unlock(&ctx->completion_lock); ++ spin_unlock_irq(&ctx->timeout_lock); + } else { + io_for_each_link(cur, req) + io_prep_async_work(cur); +@@ -1721,6 +1760,18 @@ static inline void io_get_task_refs(int nr) + io_task_refs_refill(tctx); + } + ++static __cold void io_uring_drop_tctx_refs(struct task_struct *task) ++{ ++ struct io_uring_task *tctx = task->io_uring; ++ unsigned int refs = tctx->cached_refs; ++ ++ if (refs) { ++ tctx->cached_refs = 0; ++ percpu_counter_sub(&tctx->inflight, refs); ++ put_task_struct_many(task, refs); ++ } ++} ++ + static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, u64 user_data, + long res, unsigned int cflags) + { +@@ -2161,6 +2212,10 @@ static void tctx_task_work(struct callback_head *cb) + } + + ctx_flush_and_put(ctx, &locked); ++ ++ /* relaxed read is enough as only the task itself sets ->in_idle */ ++ if (unlikely(atomic_read(&tctx->in_idle))) ++ io_uring_drop_tctx_refs(current); + } + + static void io_req_task_work_add(struct io_kiocb *req) +@@ -2840,9 +2895,13 @@ static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe, + req->flags |= REQ_F_ISREG; + + kiocb->ki_pos = READ_ONCE(sqe->off); +- if (kiocb->ki_pos == -1 && !(file->f_mode & FMODE_STREAM)) { +- req->flags |= REQ_F_CUR_POS; +- kiocb->ki_pos = file->f_pos; ++ if (kiocb->ki_pos == -1) { ++ if (!(file->f_mode & FMODE_STREAM)) { ++ req->flags |= REQ_F_CUR_POS; ++ kiocb->ki_pos = file->f_pos; ++ } else { ++ kiocb->ki_pos = 0; ++ } + } + kiocb->ki_hint = ki_hint_validate(file_write_hint(kiocb->ki_filp)); + kiocb->ki_flags = iocb_flags(kiocb->ki_filp); +@@ -4304,6 +4363,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf, + kfree(nxt); + if (++i == nbufs) + return i; ++ cond_resched(); + } + i++; + kfree(buf); +@@ -4394,6 +4454,7 @@ static int io_add_buffers(struct io_provide_buf *pbuf, struct io_buffer **head) + } else { + list_add_tail(&buf->list, &(*head)->list); + } ++ cond_resched(); + } + + return i ? i : -ENOMEM; +@@ -5702,7 +5763,7 @@ static bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk, + + list = &ctx->cancel_hash[i]; + hlist_for_each_entry_safe(req, tmp, list, hash_node) { +- if (io_match_task(req, tsk, cancel_all)) ++ if (io_match_task_safe(req, tsk, cancel_all)) + posted += io_poll_remove_one(req); + } + } +@@ -5881,6 +5942,7 @@ static int io_poll_update(struct io_kiocb *req, unsigned int issue_flags) + * update those. For multishot, if we're racing with completion, just + * let completion re-add it. + */ ++ io_poll_remove_double(preq); + completing = !__io_poll_remove_one(preq, &preq->poll, false); + if (completing && (preq->poll.events & EPOLLONESHOT)) { + ret = -EALREADY; +@@ -6511,11 +6573,14 @@ static bool io_drain_req(struct io_kiocb *req) + } + + /* Still need defer if there is pending req in defer list. */ ++ spin_lock(&ctx->completion_lock); + if (likely(list_empty_careful(&ctx->defer_list) && + !(req->flags & REQ_F_IO_DRAIN))) { ++ spin_unlock(&ctx->completion_lock); + ctx->drain_active = false; + return false; + } ++ spin_unlock(&ctx->completion_lock); + + seq = io_get_sequence(req); + /* Still a chance to pass the sequence check */ +@@ -6884,10 +6949,11 @@ static inline struct file *io_file_get(struct io_ring_ctx *ctx, + static void io_req_task_link_timeout(struct io_kiocb *req, bool *locked) + { + struct io_kiocb *prev = req->timeout.prev; +- int ret; ++ int ret = -ENOENT; + + if (prev) { +- ret = io_try_cancel_userdata(req, prev->user_data); ++ if (!(req->task->flags & PF_EXITING)) ++ ret = io_try_cancel_userdata(req, prev->user_data); + io_req_complete_post(req, ret ?: -ETIME, 0); + io_put_req(prev); + } else { +@@ -7528,7 +7594,7 @@ static int io_run_task_work_sig(void) + /* when returns >0, the caller should retry */ + static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, + struct io_wait_queue *iowq, +- signed long *timeout) ++ ktime_t timeout) + { + int ret; + +@@ -7540,8 +7606,9 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, + if (test_bit(0, &ctx->check_cq_overflow)) + return 1; + +- *timeout = schedule_timeout(*timeout); +- return !*timeout ? -ETIME : 1; ++ if (!schedule_hrtimeout(&timeout, HRTIMER_MODE_ABS)) ++ return -ETIME; ++ return 1; + } + + /* +@@ -7554,7 +7621,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, + { + struct io_wait_queue iowq; + struct io_rings *rings = ctx->rings; +- signed long timeout = MAX_SCHEDULE_TIMEOUT; ++ ktime_t timeout = KTIME_MAX; + int ret; + + do { +@@ -7570,7 +7637,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, + + if (get_timespec64(&ts, uts)) + return -EFAULT; +- timeout = timespec64_to_jiffies(&ts); ++ timeout = ktime_add_ns(timespec64_to_ktime(ts), ktime_get_ns()); + } + + if (sig) { +@@ -7602,7 +7669,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, + } + prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq, + TASK_INTERRUPTIBLE); +- ret = io_cqring_wait_schedule(ctx, &iowq, &timeout); ++ ret = io_cqring_wait_schedule(ctx, &iowq, timeout); + finish_wait(&ctx->cq_wait, &iowq.wq); + cond_resched(); + } while (ret > 0); +@@ -7656,10 +7723,15 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref) + struct io_ring_ctx *ctx = node->rsrc_data->ctx; + unsigned long flags; + bool first_add = false; ++ unsigned long delay = HZ; + + spin_lock_irqsave(&ctx->rsrc_ref_lock, flags); + node->done = true; + ++ /* if we are mid-quiesce then do not delay */ ++ if (node->rsrc_data->quiesce) ++ delay = 0; ++ + while (!list_empty(&ctx->rsrc_ref_list)) { + node = list_first_entry(&ctx->rsrc_ref_list, + struct io_rsrc_node, node); +@@ -7672,7 +7744,7 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref) + spin_unlock_irqrestore(&ctx->rsrc_ref_lock, flags); + + if (first_add) +- mod_delayed_work(system_wq, &ctx->rsrc_put_work, HZ); ++ mod_delayed_work(system_wq, &ctx->rsrc_put_work, delay); + } + + static struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx) +@@ -7750,7 +7822,15 @@ static int io_rsrc_ref_quiesce(struct io_rsrc_data *data, struct io_ring_ctx *ct + ret = wait_for_completion_interruptible(&data->done); + if (!ret) { + mutex_lock(&ctx->uring_lock); +- break; ++ if (atomic_read(&data->refs) > 0) { ++ /* ++ * it has been revived by another thread while ++ * we were unlocked ++ */ ++ mutex_unlock(&ctx->uring_lock); ++ } else { ++ break; ++ } + } + + atomic_inc(&data->refs); +@@ -8753,10 +8833,9 @@ static void io_mem_free(void *ptr) + + static void *io_mem_alloc(size_t size) + { +- gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_COMP | +- __GFP_NORETRY | __GFP_ACCOUNT; ++ gfp_t gfp = GFP_KERNEL_ACCOUNT | __GFP_ZERO | __GFP_NOWARN | __GFP_COMP; + +- return (void *) __get_free_pages(gfp_flags, get_order(size)); ++ return (void *) __get_free_pages(gfp, get_order(size)); + } + + static unsigned long rings_size(unsigned sq_entries, unsigned cq_entries, +@@ -9209,10 +9288,8 @@ static void io_destroy_buffers(struct io_ring_ctx *ctx) + struct io_buffer *buf; + unsigned long index; + +- xa_for_each(&ctx->io_buffers, index, buf) { ++ xa_for_each(&ctx->io_buffers, index, buf) + __io_remove_buffers(ctx, buf, index, -1U); +- cond_resched(); +- } + } + + static void io_req_cache_free(struct list_head *list) +@@ -9517,19 +9594,8 @@ static bool io_cancel_task_cb(struct io_wq_work *work, void *data) + { + struct io_kiocb *req = container_of(work, struct io_kiocb, work); + struct io_task_cancel *cancel = data; +- bool ret; +- +- if (!cancel->all && (req->flags & REQ_F_LINK_TIMEOUT)) { +- struct io_ring_ctx *ctx = req->ctx; + +- /* protect against races with linked timeouts */ +- spin_lock(&ctx->completion_lock); +- ret = io_match_task(req, cancel->task, cancel->all); +- spin_unlock(&ctx->completion_lock); +- } else { +- ret = io_match_task(req, cancel->task, cancel->all); +- } +- return ret; ++ return io_match_task_safe(req, cancel->task, cancel->all); + } + + static bool io_cancel_defer_files(struct io_ring_ctx *ctx, +@@ -9540,7 +9606,7 @@ static bool io_cancel_defer_files(struct io_ring_ctx *ctx, + + spin_lock(&ctx->completion_lock); + list_for_each_entry_reverse(de, &ctx->defer_list, list) { +- if (io_match_task(de->req, task, cancel_all)) { ++ if (io_match_task_safe(de->req, task, cancel_all)) { + list_cut_position(&list, &ctx->defer_list, &de->list); + break; + } +@@ -9733,21 +9799,9 @@ static s64 tctx_inflight(struct io_uring_task *tctx, bool tracked) + return percpu_counter_sum(&tctx->inflight); + } + +-static void io_uring_drop_tctx_refs(struct task_struct *task) +-{ +- struct io_uring_task *tctx = task->io_uring; +- unsigned int refs = tctx->cached_refs; +- +- if (refs) { +- tctx->cached_refs = 0; +- percpu_counter_sub(&tctx->inflight, refs); +- put_task_struct_many(task, refs); +- } +-} +- + /* + * Find any io_uring ctx that this task has registered or done IO on, and cancel +- * requests. @sqd should be not-null IIF it's an SQPOLL thread cancellation. ++ * requests. @sqd should be not-null IFF it's an SQPOLL thread cancellation. + */ + static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) + { +@@ -9788,8 +9842,10 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) + cancel_all); + } + +- prepare_to_wait(&tctx->wait, &wait, TASK_UNINTERRUPTIBLE); ++ prepare_to_wait(&tctx->wait, &wait, TASK_INTERRUPTIBLE); ++ io_run_task_work(); + io_uring_drop_tctx_refs(current); ++ + /* + * If we've seen completions, retry without waiting. This + * avoids a race where a completion comes in before we did +@@ -9799,10 +9855,14 @@ static void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) + schedule(); + finish_wait(&tctx->wait, &wait); + } while (1); +- atomic_dec(&tctx->in_idle); + + io_uring_clean_tctx(tctx); + if (cancel_all) { ++ /* ++ * We shouldn't run task_works after cancel, so just leave ++ * ->in_idle set for normal exit. ++ */ ++ atomic_dec(&tctx->in_idle); + /* for exec all current's requests should be gone, kill tctx */ + __io_uring_free(current); + } +@@ -10684,7 +10744,9 @@ static int io_register_iowq_max_workers(struct io_ring_ctx *ctx, + + BUILD_BUG_ON(sizeof(new_count) != sizeof(ctx->iowq_limits)); + +- memcpy(ctx->iowq_limits, new_count, sizeof(new_count)); ++ for (i = 0; i < ARRAY_SIZE(new_count); i++) ++ if (new_count[i]) ++ ctx->iowq_limits[i] = new_count[i]; + ctx->iowq_limits_set = true; + + ret = -EINVAL; +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 9cc5798423d12..97119ec3b8503 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -256,8 +256,13 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, + unsigned poff, plen; + sector_t sector; + +- if (iomap->type == IOMAP_INLINE) +- return min(iomap_read_inline_data(iter, page), length); ++ if (iomap->type == IOMAP_INLINE) { ++ loff_t ret = iomap_read_inline_data(iter, page); ++ ++ if (ret < 0) ++ return ret; ++ return 0; ++ } + + /* zero post-eof blocks as the page may be mapped */ + iop = iomap_page_create(iter->inode, page); +@@ -370,6 +375,8 @@ static loff_t iomap_readahead_iter(const struct iomap_iter *iter, + ctx->cur_page_in_bio = false; + } + ret = iomap_readpage_iter(iter, ctx, done); ++ if (ret <= 0) ++ return ret; + } + + return done; +diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c +index 678e2c51b855c..0c6eacfcbeef1 100644 +--- a/fs/isofs/inode.c ++++ b/fs/isofs/inode.c +@@ -1322,6 +1322,8 @@ static int isofs_read_inode(struct inode *inode, int relocated) + + de = (struct iso_directory_record *) (bh->b_data + offset); + de_len = *(unsigned char *) de; ++ if (de_len < sizeof(struct iso_directory_record)) ++ goto fail; + + if (offset + de_len > bufsize) { + int frag1 = bufsize - offset; +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index 3cc4ab2ba7f4f..d188fa913a075 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -1170,7 +1170,7 @@ restart_loop: + if (journal->j_commit_callback) + journal->j_commit_callback(journal, commit_transaction); + if (journal->j_fc_cleanup_callback) +- journal->j_fc_cleanup_callback(journal, 1); ++ journal->j_fc_cleanup_callback(journal, 1, commit_transaction->t_tid); + + trace_jbd2_end_commit(journal, commit_transaction); + jbd_debug(1, "JBD2: commit %d complete, head %d\n", +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 35302bc192eb9..1f8493ef181d6 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -769,7 +769,7 @@ EXPORT_SYMBOL(jbd2_fc_begin_commit); + static int __jbd2_fc_end_commit(journal_t *journal, tid_t tid, bool fallback) + { + if (journal->j_fc_cleanup_callback) +- journal->j_fc_cleanup_callback(journal, 0); ++ journal->j_fc_cleanup_callback(journal, 0, tid); + write_lock(&journal->j_state_lock); + journal->j_flags &= ~JBD2_FAST_COMMIT_ONGOING; + if (fallback) +@@ -2970,6 +2970,7 @@ struct journal_head *jbd2_journal_grab_journal_head(struct buffer_head *bh) + jbd_unlock_bh_journal_head(bh); + return jh; + } ++EXPORT_SYMBOL(jbd2_journal_grab_journal_head); + + static void __journal_remove_journal_head(struct buffer_head *bh) + { +@@ -3022,6 +3023,7 @@ void jbd2_journal_put_journal_head(struct journal_head *jh) + jbd_unlock_bh_journal_head(bh); + } + } ++EXPORT_SYMBOL(jbd2_journal_put_journal_head); + + /* + * Initialize jbd inode head +diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c +index 4fc8cd698d1a4..bd7d58d27bfc6 100644 +--- a/fs/jffs2/file.c ++++ b/fs/jffs2/file.c +@@ -136,20 +136,15 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + struct page *pg; + struct inode *inode = mapping->host; + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); ++ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + pgoff_t index = pos >> PAGE_SHIFT; + uint32_t pageofs = index << PAGE_SHIFT; + int ret = 0; + +- pg = grab_cache_page_write_begin(mapping, index, flags); +- if (!pg) +- return -ENOMEM; +- *pagep = pg; +- + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { + /* Make new hole frag from old EOF to new page */ +- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; + struct jffs2_full_dnode *fn; + uint32_t alloc_len; +@@ -160,7 +155,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) +- goto out_page; ++ goto out_err; + + mutex_lock(&f->sem); + memset(&ri, 0, sizeof(ri)); +@@ -190,7 +185,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + ret = PTR_ERR(fn); + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); +- goto out_page; ++ goto out_err; + } + ret = jffs2_add_full_dnode_to_inode(c, f, fn); + if (f->metadata) { +@@ -205,13 +200,26 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + jffs2_free_full_dnode(fn); + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); +- goto out_page; ++ goto out_err; + } + jffs2_complete_reservation(c); + inode->i_size = pageofs; + mutex_unlock(&f->sem); + } + ++ /* ++ * While getting a page and reading data in, lock c->alloc_sem until ++ * the page is Uptodate. Otherwise GC task may attempt to read the same ++ * page in read_cache_page(), which causes a deadlock. ++ */ ++ mutex_lock(&c->alloc_sem); ++ pg = grab_cache_page_write_begin(mapping, index, flags); ++ if (!pg) { ++ ret = -ENOMEM; ++ goto release_sem; ++ } ++ *pagep = pg; ++ + /* + * Read in the page if it wasn't already present. Cannot optimize away + * the whole page write case until jffs2_write_end can handle the +@@ -221,15 +229,17 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, + mutex_lock(&f->sem); + ret = jffs2_do_readpage_nolock(inode, pg); + mutex_unlock(&f->sem); +- if (ret) +- goto out_page; ++ if (ret) { ++ unlock_page(pg); ++ put_page(pg); ++ goto release_sem; ++ } + } + jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); +- return ret; + +-out_page: +- unlock_page(pg); +- put_page(pg); ++release_sem: ++ mutex_unlock(&c->alloc_sem); ++out_err: + return ret; + } + +diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c +index 5d7d7170c03c0..aa4ff7bcaff23 100644 +--- a/fs/jfs/jfs_mount.c ++++ b/fs/jfs/jfs_mount.c +@@ -81,14 +81,14 @@ int jfs_mount(struct super_block *sb) + * (initialize mount inode from the superblock) + */ + if ((rc = chkSuper(sb))) { +- goto errout20; ++ goto out; + } + + ipaimap = diReadSpecial(sb, AGGREGATE_I, 0); + if (ipaimap == NULL) { + jfs_err("jfs_mount: Failed to read AGGREGATE_I"); + rc = -EIO; +- goto errout20; ++ goto out; + } + sbi->ipaimap = ipaimap; + +@@ -99,7 +99,7 @@ int jfs_mount(struct super_block *sb) + */ + if ((rc = diMount(ipaimap))) { + jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc); +- goto errout21; ++ goto err_ipaimap; + } + + /* +@@ -108,7 +108,7 @@ int jfs_mount(struct super_block *sb) + ipbmap = diReadSpecial(sb, BMAP_I, 0); + if (ipbmap == NULL) { + rc = -EIO; +- goto errout22; ++ goto err_umount_ipaimap; + } + + jfs_info("jfs_mount: ipbmap:0x%p", ipbmap); +@@ -120,7 +120,7 @@ int jfs_mount(struct super_block *sb) + */ + if ((rc = dbMount(ipbmap))) { + jfs_err("jfs_mount: dbMount failed w/rc = %d", rc); +- goto errout22; ++ goto err_ipbmap; + } + + /* +@@ -139,7 +139,7 @@ int jfs_mount(struct super_block *sb) + if (!ipaimap2) { + jfs_err("jfs_mount: Failed to read AGGREGATE_I"); + rc = -EIO; +- goto errout35; ++ goto err_umount_ipbmap; + } + sbi->ipaimap2 = ipaimap2; + +@@ -151,7 +151,7 @@ int jfs_mount(struct super_block *sb) + if ((rc = diMount(ipaimap2))) { + jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d", + rc); +- goto errout35; ++ goto err_ipaimap2; + } + } else + /* Secondary aggregate inode table is not valid */ +@@ -168,7 +168,7 @@ int jfs_mount(struct super_block *sb) + jfs_err("jfs_mount: Failed to read FILESYSTEM_I"); + /* open fileset secondary inode allocation map */ + rc = -EIO; +- goto errout40; ++ goto err_umount_ipaimap2; + } + jfs_info("jfs_mount: ipimap:0x%p", ipimap); + +@@ -178,41 +178,34 @@ int jfs_mount(struct super_block *sb) + /* initialize fileset inode allocation map */ + if ((rc = diMount(ipimap))) { + jfs_err("jfs_mount: diMount failed w/rc = %d", rc); +- goto errout41; ++ goto err_ipimap; + } + +- goto out; ++ return rc; + + /* + * unwind on error + */ +- errout41: /* close fileset inode allocation map inode */ ++err_ipimap: ++ /* close fileset inode allocation map inode */ + diFreeSpecial(ipimap); +- +- errout40: /* fileset closed */ +- ++err_umount_ipaimap2: + /* close secondary aggregate inode allocation map */ +- if (ipaimap2) { ++ if (ipaimap2) + diUnmount(ipaimap2, 1); ++err_ipaimap2: ++ /* close aggregate inodes */ ++ if (ipaimap2) + diFreeSpecial(ipaimap2); +- } +- +- errout35: +- +- /* close aggregate block allocation map */ ++err_umount_ipbmap: /* close aggregate block allocation map */ + dbUnmount(ipbmap, 1); ++err_ipbmap: /* close aggregate inodes */ + diFreeSpecial(ipbmap); +- +- errout22: /* close aggregate inode allocation map */ +- ++err_umount_ipaimap: /* close aggregate inode allocation map */ + diUnmount(ipaimap, 1); +- +- errout21: /* close aggregate inodes */ ++err_ipaimap: /* close aggregate inodes */ + diFreeSpecial(ipaimap); +- errout20: /* aggregate closed */ +- +- out: +- ++out: + if (rc) + jfs_err("Mount JFS Failure: %d", rc); + +diff --git a/fs/ksmbd/Kconfig b/fs/ksmbd/Kconfig +index b83cbd756ae50..6af339cfdc041 100644 +--- a/fs/ksmbd/Kconfig ++++ b/fs/ksmbd/Kconfig +@@ -19,6 +19,7 @@ config SMB_SERVER + select CRYPTO_GCM + select ASN1 + select OID_REGISTRY ++ select CRC32 + default n + help + Choose Y here if you want to allow SMB3 compliant clients +diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c +index b57a0d8a392ff..f7d5e8b7bef77 100644 +--- a/fs/ksmbd/connection.c ++++ b/fs/ksmbd/connection.c +@@ -62,6 +62,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) + atomic_set(&conn->req_running, 0); + atomic_set(&conn->r_count, 0); + conn->total_credits = 1; ++ conn->outstanding_credits = 1; + + init_waitqueue_head(&conn->req_running_q); + INIT_LIST_HEAD(&conn->conns_list); +diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h +index e5403c587a58c..8694aef482c1a 100644 +--- a/fs/ksmbd/connection.h ++++ b/fs/ksmbd/connection.h +@@ -61,8 +61,8 @@ struct ksmbd_conn { + atomic_t req_running; + /* References which are made for this Server object*/ + atomic_t r_count; +- unsigned short total_credits; +- unsigned short max_credits; ++ unsigned int total_credits; ++ unsigned int outstanding_credits; + spinlock_t credits_lock; + wait_queue_head_t req_running_q; + /* Lock to protect requests list*/ +diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h +index c6718a05d347f..71bfb7de44725 100644 +--- a/fs/ksmbd/ksmbd_netlink.h ++++ b/fs/ksmbd/ksmbd_netlink.h +@@ -103,6 +103,8 @@ struct ksmbd_startup_request { + * we set the SPARSE_FILES bit (0x40). + */ + __u32 sub_auth[3]; /* Subauth value for Security ID */ ++ __u32 smb2_max_credits; /* MAX credits */ ++ __u32 reserved[128]; /* Reserved room */ + __u32 ifc_list_sz; /* interfaces list size */ + __s8 ____payload[]; + }; +@@ -113,7 +115,7 @@ struct ksmbd_startup_request { + * IPC request to shutdown ksmbd server. + */ + struct ksmbd_shutdown_request { +- __s32 reserved; ++ __s32 reserved[16]; + }; + + /* +@@ -122,6 +124,7 @@ struct ksmbd_shutdown_request { + struct ksmbd_login_request { + __u32 handle; + __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */ ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +@@ -135,6 +138,7 @@ struct ksmbd_login_response { + __u16 status; + __u16 hash_sz; /* hash size */ + __s8 hash[KSMBD_REQ_MAX_HASH_SZ]; /* password hash */ ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +@@ -143,6 +147,7 @@ struct ksmbd_login_response { + struct ksmbd_share_config_request { + __u32 handle; + __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME]; /* share name */ ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +@@ -157,6 +162,7 @@ struct ksmbd_share_config_response { + __u16 force_directory_mode; + __u16 force_uid; + __u16 force_gid; ++ __u32 reserved[128]; /* Reserved room */ + __u32 veto_list_sz; + __s8 ____payload[]; + }; +@@ -187,6 +193,7 @@ struct ksmbd_tree_connect_request { + __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; + __s8 share[KSMBD_REQ_MAX_SHARE_NAME]; + __s8 peer_addr[64]; ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +@@ -196,6 +203,7 @@ struct ksmbd_tree_connect_response { + __u32 handle; + __u16 status; + __u16 connection_flags; ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +@@ -204,6 +212,7 @@ struct ksmbd_tree_connect_response { + struct ksmbd_tree_disconnect_request { + __u64 session_id; /* session id */ + __u64 connect_id; /* tree connection id */ ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +@@ -212,6 +221,7 @@ struct ksmbd_tree_disconnect_request { + struct ksmbd_logout_request { + __s8 account[KSMBD_REQ_MAX_ACCOUNT_NAME_SZ]; /* user account name */ + __u32 account_flags; ++ __u32 reserved[16]; /* Reserved room */ + }; + + /* +diff --git a/fs/ksmbd/ndr.c b/fs/ksmbd/ndr.c +index 8317f7ca402b4..5052be9261d91 100644 +--- a/fs/ksmbd/ndr.c ++++ b/fs/ksmbd/ndr.c +@@ -148,7 +148,7 @@ static int ndr_read_int16(struct ndr *n, __u16 *value) + static int ndr_read_int32(struct ndr *n, __u32 *value) + { + if (n->offset + sizeof(__u32) > n->length) +- return 0; ++ return -EINVAL; + + if (value) + *value = le32_to_cpu(*(__le32 *)ndr_get_field(n)); +diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c +index 2a2b2135bfded..36d368e59a640 100644 +--- a/fs/ksmbd/server.c ++++ b/fs/ksmbd/server.c +@@ -632,5 +632,6 @@ MODULE_SOFTDEP("pre: sha512"); + MODULE_SOFTDEP("pre: aead2"); + MODULE_SOFTDEP("pre: ccm"); + MODULE_SOFTDEP("pre: gcm"); ++MODULE_SOFTDEP("pre: crc32"); + module_init(ksmbd_server_init) + module_exit(ksmbd_server_exit) +diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c +index 030ca57c37849..cc1c38686ecd7 100644 +--- a/fs/ksmbd/smb2misc.c ++++ b/fs/ksmbd/smb2misc.c +@@ -290,7 +290,7 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn, + unsigned int req_len = 0, expect_resp_len = 0, calc_credit_num, max_len; + unsigned short credit_charge = le16_to_cpu(hdr->CreditCharge); + void *__hdr = hdr; +- int ret; ++ int ret = 0; + + switch (hdr->Command) { + case SMB2_QUERY_INFO: +@@ -327,21 +327,27 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn, + ksmbd_debug(SMB, "Insufficient credit charge, given: %d, needed: %d\n", + credit_charge, calc_credit_num); + return 1; +- } else if (credit_charge > conn->max_credits) { ++ } else if (credit_charge > conn->vals->max_credits) { + ksmbd_debug(SMB, "Too large credit charge: %d\n", credit_charge); + return 1; + } + + spin_lock(&conn->credits_lock); +- if (credit_charge <= conn->total_credits) { +- conn->total_credits -= credit_charge; +- ret = 0; +- } else { ++ if (credit_charge > conn->total_credits) { + ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n", + credit_charge, conn->total_credits); + ret = 1; + } ++ ++ if ((u64)conn->outstanding_credits + credit_charge > conn->vals->max_credits) { ++ ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n", ++ credit_charge, conn->outstanding_credits); ++ ret = 1; ++ } else ++ conn->outstanding_credits += credit_charge; ++ + spin_unlock(&conn->credits_lock); ++ + return ret; + } + +@@ -358,12 +364,10 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + hdr = &pdu->hdr; + } + +- if (le32_to_cpu(hdr->NextCommand) > 0) { ++ if (le32_to_cpu(hdr->NextCommand) > 0) + len = le32_to_cpu(hdr->NextCommand); +- } else if (work->next_smb2_rcv_hdr_off) { ++ else if (work->next_smb2_rcv_hdr_off) + len -= work->next_smb2_rcv_hdr_off; +- len = round_up(len, 8); +- } + + if (check_smb2_hdr(hdr)) + return 1; +diff --git a/fs/ksmbd/smb2ops.c b/fs/ksmbd/smb2ops.c +index fb6a65d231391..f0a5b704f301c 100644 +--- a/fs/ksmbd/smb2ops.c ++++ b/fs/ksmbd/smb2ops.c +@@ -20,6 +20,7 @@ static struct smb_version_values smb21_server_values = { + .max_read_size = SMB21_DEFAULT_IOSIZE, + .max_write_size = SMB21_DEFAULT_IOSIZE, + .max_trans_size = SMB21_DEFAULT_IOSIZE, ++ .max_credits = SMB2_MAX_CREDITS, + .large_lock_type = 0, + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, + .shared_lock_type = SMB2_LOCKFLAG_SHARED, +@@ -45,6 +46,7 @@ static struct smb_version_values smb30_server_values = { + .max_read_size = SMB3_DEFAULT_IOSIZE, + .max_write_size = SMB3_DEFAULT_IOSIZE, + .max_trans_size = SMB3_DEFAULT_TRANS_SIZE, ++ .max_credits = SMB2_MAX_CREDITS, + .large_lock_type = 0, + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, + .shared_lock_type = SMB2_LOCKFLAG_SHARED, +@@ -71,6 +73,7 @@ static struct smb_version_values smb302_server_values = { + .max_read_size = SMB3_DEFAULT_IOSIZE, + .max_write_size = SMB3_DEFAULT_IOSIZE, + .max_trans_size = SMB3_DEFAULT_TRANS_SIZE, ++ .max_credits = SMB2_MAX_CREDITS, + .large_lock_type = 0, + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, + .shared_lock_type = SMB2_LOCKFLAG_SHARED, +@@ -97,6 +100,7 @@ static struct smb_version_values smb311_server_values = { + .max_read_size = SMB3_DEFAULT_IOSIZE, + .max_write_size = SMB3_DEFAULT_IOSIZE, + .max_trans_size = SMB3_DEFAULT_TRANS_SIZE, ++ .max_credits = SMB2_MAX_CREDITS, + .large_lock_type = 0, + .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE, + .shared_lock_type = SMB2_LOCKFLAG_SHARED, +@@ -198,7 +202,6 @@ void init_smb2_1_server(struct ksmbd_conn *conn) + conn->ops = &smb2_0_server_ops; + conn->cmds = smb2_0_server_cmds; + conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds); +- conn->max_credits = SMB2_MAX_CREDITS; + conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) +@@ -216,7 +219,6 @@ void init_smb3_0_server(struct ksmbd_conn *conn) + conn->ops = &smb3_0_server_ops; + conn->cmds = smb2_0_server_cmds; + conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds); +- conn->max_credits = SMB2_MAX_CREDITS; + conn->signing_algorithm = SIGNING_ALG_AES_CMAC; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) +@@ -241,7 +243,6 @@ void init_smb3_02_server(struct ksmbd_conn *conn) + conn->ops = &smb3_0_server_ops; + conn->cmds = smb2_0_server_cmds; + conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds); +- conn->max_credits = SMB2_MAX_CREDITS; + conn->signing_algorithm = SIGNING_ALG_AES_CMAC; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) +@@ -266,15 +267,11 @@ int init_smb3_11_server(struct ksmbd_conn *conn) + conn->ops = &smb3_11_server_ops; + conn->cmds = smb2_0_server_cmds; + conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds); +- conn->max_credits = SMB2_MAX_CREDITS; + conn->signing_algorithm = SIGNING_ALG_AES_CMAC; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) + conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; + +- if (conn->cipher_type) +- conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; +- + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) + conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; + +@@ -308,3 +305,11 @@ void init_smb2_max_trans_size(unsigned int sz) + smb302_server_values.max_trans_size = sz; + smb311_server_values.max_trans_size = sz; + } ++ ++void init_smb2_max_credits(unsigned int sz) ++{ ++ smb21_server_values.max_credits = sz; ++ smb30_server_values.max_credits = sz; ++ smb302_server_values.max_credits = sz; ++ smb311_server_values.max_credits = sz; ++} +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 7e448df3f8474..192d8308afc27 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -301,16 +301,15 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) + struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work); + struct smb2_hdr *hdr = ksmbd_resp_buf_next(work); + struct ksmbd_conn *conn = work->conn; +- unsigned short credits_requested; ++ unsigned short credits_requested, aux_max; + unsigned short credit_charge, credits_granted = 0; +- unsigned short aux_max, aux_credits; + + if (work->send_no_response) + return 0; + + hdr->CreditCharge = req_hdr->CreditCharge; + +- if (conn->total_credits > conn->max_credits) { ++ if (conn->total_credits > conn->vals->max_credits) { + hdr->CreditRequest = 0; + pr_err("Total credits overflow: %d\n", conn->total_credits); + return -EINVAL; +@@ -318,6 +317,14 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) + + credit_charge = max_t(unsigned short, + le16_to_cpu(req_hdr->CreditCharge), 1); ++ if (credit_charge > conn->total_credits) { ++ ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n", ++ credit_charge, conn->total_credits); ++ return -EINVAL; ++ } ++ ++ conn->total_credits -= credit_charge; ++ conn->outstanding_credits -= credit_charge; + credits_requested = max_t(unsigned short, + le16_to_cpu(req_hdr->CreditRequest), 1); + +@@ -327,16 +334,14 @@ int smb2_set_rsp_credits(struct ksmbd_work *work) + * TODO: Need to adjuct CreditRequest value according to + * current cpu load + */ +- aux_credits = credits_requested - 1; + if (hdr->Command == SMB2_NEGOTIATE) +- aux_max = 0; ++ aux_max = 1; + else +- aux_max = conn->max_credits - credit_charge; +- aux_credits = min_t(unsigned short, aux_credits, aux_max); +- credits_granted = credit_charge + aux_credits; ++ aux_max = conn->vals->max_credits - credit_charge; ++ credits_granted = min_t(unsigned short, credits_requested, aux_max); + +- if (conn->max_credits - conn->total_credits < credits_granted) +- credits_granted = conn->max_credits - ++ if (conn->vals->max_credits - conn->total_credits < credits_granted) ++ credits_granted = conn->vals->max_credits - + conn->total_credits; + + conn->total_credits += credits_granted; +@@ -917,6 +922,25 @@ static void decode_encrypt_ctxt(struct ksmbd_conn *conn, + } + } + ++/** ++ * smb3_encryption_negotiated() - checks if server and client agreed on enabling encryption ++ * @conn: smb connection ++ * ++ * Return: true if connection should be encrypted, else false ++ */ ++static bool smb3_encryption_negotiated(struct ksmbd_conn *conn) ++{ ++ if (!conn->ops->generate_encryptionkey) ++ return false; ++ ++ /* ++ * SMB 3.0 and 3.0.2 dialects use the SMB2_GLOBAL_CAP_ENCRYPTION flag. ++ * SMB 3.1.1 uses the cipher_type field. ++ */ ++ return (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) || ++ conn->cipher_type; ++} ++ + static void decode_compress_ctxt(struct ksmbd_conn *conn, + struct smb2_compression_ctx *pneg_ctxt) + { +@@ -1438,11 +1462,6 @@ static int ntlm_authenticate(struct ksmbd_work *work) + + sess->user = user; + if (user_guest(sess->user)) { +- if (conn->sign) { +- ksmbd_debug(SMB, "Guest login not allowed when signing enabled\n"); +- return -EPERM; +- } +- + rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE; + } else { + struct authenticate_message *authblob; +@@ -1455,39 +1474,39 @@ static int ntlm_authenticate(struct ksmbd_work *work) + ksmbd_debug(SMB, "authentication failed\n"); + return -EPERM; + } ++ } + +- /* +- * If session state is SMB2_SESSION_VALID, We can assume +- * that it is reauthentication. And the user/password +- * has been verified, so return it here. +- */ +- if (sess->state == SMB2_SESSION_VALID) { +- if (conn->binding) +- goto binding_session; +- return 0; +- } ++ /* ++ * If session state is SMB2_SESSION_VALID, We can assume ++ * that it is reauthentication. And the user/password ++ * has been verified, so return it here. ++ */ ++ if (sess->state == SMB2_SESSION_VALID) { ++ if (conn->binding) ++ goto binding_session; ++ return 0; ++ } + +- if ((conn->sign || server_conf.enforced_signing) || +- (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) +- sess->sign = true; ++ if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE && ++ (conn->sign || server_conf.enforced_signing)) || ++ (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) ++ sess->sign = true; + +- if (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION && +- conn->ops->generate_encryptionkey && +- !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { +- rc = conn->ops->generate_encryptionkey(sess); +- if (rc) { +- ksmbd_debug(SMB, +- "SMB3 encryption key generation failed\n"); +- return -EINVAL; +- } +- sess->enc = true; +- rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; +- /* +- * signing is disable if encryption is enable +- * on this session +- */ +- sess->sign = false; ++ if (smb3_encryption_negotiated(conn) && ++ !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { ++ rc = conn->ops->generate_encryptionkey(sess); ++ if (rc) { ++ ksmbd_debug(SMB, ++ "SMB3 encryption key generation failed\n"); ++ return -EINVAL; + } ++ sess->enc = true; ++ rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; ++ /* ++ * signing is disable if encryption is enable ++ * on this session ++ */ ++ sess->sign = false; + } + + binding_session: +@@ -1562,8 +1581,7 @@ static int krb5_authenticate(struct ksmbd_work *work) + (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) + sess->sign = true; + +- if ((conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) && +- conn->ops->generate_encryptionkey) { ++ if (smb3_encryption_negotiated(conn)) { + retval = conn->ops->generate_encryptionkey(sess); + if (retval) { + ksmbd_debug(SMB, +@@ -1700,8 +1718,10 @@ int smb2_sess_setup(struct ksmbd_work *work) + negblob_off = le16_to_cpu(req->SecurityBufferOffset); + negblob_len = le16_to_cpu(req->SecurityBufferLength); + if (negblob_off < (offsetof(struct smb2_sess_setup_req, Buffer) - 4) || +- negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) +- return -EINVAL; ++ negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { ++ rc = -EINVAL; ++ goto out_err; ++ } + + negblob = (struct negotiate_message *)((char *)&req->hdr.ProtocolId + + negblob_off); +@@ -2670,7 +2690,7 @@ int smb2_open(struct ksmbd_work *work) + (struct create_posix *)context; + if (le16_to_cpu(context->DataOffset) + + le32_to_cpu(context->DataLength) < +- sizeof(struct create_posix)) { ++ sizeof(struct create_posix) - 4) { + rc = -EINVAL; + goto err_out1; + } +@@ -2962,6 +2982,10 @@ int smb2_open(struct ksmbd_work *work) + &pntsd_size, &fattr); + posix_acl_release(fattr.cf_acls); + posix_acl_release(fattr.cf_dacls); ++ if (rc) { ++ kfree(pntsd); ++ goto err_out; ++ } + + rc = ksmbd_vfs_set_sd_xattr(conn, + user_ns, +@@ -3398,9 +3422,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level, + goto free_conv_name; + } + +- struct_sz = readdir_info_level_struct_sz(info_level); +- next_entry_offset = ALIGN(struct_sz - 1 + conv_len, +- KSMBD_DIR_INFO_ALIGNMENT); ++ struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len; ++ next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT); ++ d_info->last_entry_off_align = next_entry_offset - struct_sz; + + if (next_entry_offset > d_info->out_buf_len) { + d_info->out_buf_len = 0; +@@ -3952,6 +3976,7 @@ int smb2_query_dir(struct ksmbd_work *work) + ((struct file_directory_info *) + ((char *)rsp->Buffer + d_info.last_entry_offset)) + ->NextEntryOffset = 0; ++ d_info.data_count -= d_info.last_entry_off_align; + + rsp->StructureSize = cpu_to_le16(9); + rsp->OutputBufferOffset = cpu_to_le16(72); +@@ -4450,6 +4475,12 @@ static void get_file_stream_info(struct ksmbd_work *work, + &stat); + file_info = (struct smb2_file_stream_info *)rsp->Buffer; + ++ buf_free_len = ++ smb2_calc_max_out_buf_len(work, 8, ++ le32_to_cpu(req->OutputBufferLength)); ++ if (buf_free_len < 0) ++ goto out; ++ + xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); + if (xattr_list_len < 0) { + goto out; +@@ -4458,12 +4489,6 @@ static void get_file_stream_info(struct ksmbd_work *work, + goto out; + } + +- buf_free_len = +- smb2_calc_max_out_buf_len(work, 8, +- le32_to_cpu(req->OutputBufferLength)); +- if (buf_free_len < 0) +- goto out; +- + while (idx < xattr_list_len) { + stream_name = xattr_list + idx; + streamlen = strlen(stream_name); +@@ -4489,8 +4514,10 @@ static void get_file_stream_info(struct ksmbd_work *work, + ":%s", &stream_name[XATTR_NAME_STREAM_LEN]); + + next = sizeof(struct smb2_file_stream_info) + streamlen * 2; +- if (next > buf_free_len) ++ if (next > buf_free_len) { ++ kfree(stream_buf); + break; ++ } + + file_info = (struct smb2_file_stream_info *)&rsp->Buffer[nbytes]; + streamlen = smbConvertToUTF16((__le16 *)file_info->StreamName, +@@ -4507,6 +4534,7 @@ static void get_file_stream_info(struct ksmbd_work *work, + file_info->NextEntryOffset = cpu_to_le32(next); + } + ++out: + if (!S_ISDIR(stat.mode) && + buf_free_len >= sizeof(struct smb2_file_stream_info) + 7 * 2) { + file_info = (struct smb2_file_stream_info *) +@@ -4515,14 +4543,13 @@ static void get_file_stream_info(struct ksmbd_work *work, + "::$DATA", 7, conn->local_nls, 0); + streamlen *= 2; + file_info->StreamNameLength = cpu_to_le32(streamlen); +- file_info->StreamSize = 0; +- file_info->StreamAllocationSize = 0; ++ file_info->StreamSize = cpu_to_le64(stat.size); ++ file_info->StreamAllocationSize = cpu_to_le64(stat.blocks << 9); + nbytes += sizeof(struct smb2_file_stream_info) + streamlen; + } + + /* last entry offset should be 0 */ + file_info->NextEntryOffset = 0; +-out: + kvfree(xattr_list); + + rsp->OutputBufferLength = cpu_to_le32(nbytes); +@@ -4891,11 +4918,18 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, + { + struct filesystem_vol_info *info; + size_t sz; ++ unsigned int serial_crc = 0; + + info = (struct filesystem_vol_info *)(rsp->Buffer); + info->VolumeCreationTime = 0; ++ serial_crc = crc32_le(serial_crc, share->name, ++ strlen(share->name)); ++ serial_crc = crc32_le(serial_crc, share->path, ++ strlen(share->path)); ++ serial_crc = crc32_le(serial_crc, ksmbd_netbios_name(), ++ strlen(ksmbd_netbios_name())); + /* Taking dummy value of serial number*/ +- info->SerialNumber = cpu_to_le32(0xbc3ac512); ++ info->SerialNumber = cpu_to_le32(serial_crc); + len = smbConvertToUTF16((__le16 *)info->VolumeLabel, + share->name, PATH_MAX, + conn->local_nls, 0); +@@ -5053,7 +5087,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work, + if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | + PROTECTED_DACL_SECINFO | + UNPROTECTED_DACL_SECINFO)) { +- pr_err("Unsupported addition info: 0x%x)\n", ++ ksmbd_debug(SMB, "Unsupported addition info: 0x%x)\n", + addition_info); + + pntsd->revision = cpu_to_le16(1); +@@ -7312,7 +7346,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn, + int ret = 0; + int dialect; + +- if (in_buf_len < sizeof(struct validate_negotiate_info_req) + ++ if (in_buf_len < offsetof(struct validate_negotiate_info_req, Dialects) + + le16_to_cpu(neg_req->DialectCount) * sizeof(__le16)) + return -EINVAL; + +diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h +index ff5a2f01d34ae..4f8574944ac19 100644 +--- a/fs/ksmbd/smb2pdu.h ++++ b/fs/ksmbd/smb2pdu.h +@@ -1647,6 +1647,7 @@ int init_smb3_11_server(struct ksmbd_conn *conn); + void init_smb2_max_read_size(unsigned int sz); + void init_smb2_max_write_size(unsigned int sz); + void init_smb2_max_trans_size(unsigned int sz); ++void init_smb2_max_credits(unsigned int sz); + + bool is_smb2_neg_cmd(struct ksmbd_work *work); + bool is_smb2_rsp(struct ksmbd_work *work); +diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c +index 707490ab1f4c4..f2e7e3a654b34 100644 +--- a/fs/ksmbd/smb_common.c ++++ b/fs/ksmbd/smb_common.c +@@ -308,14 +308,17 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, + for (i = 0; i < 2; i++) { + struct kstat kstat; + struct ksmbd_kstat ksmbd_kstat; ++ struct dentry *dentry; + + if (!dir->dot_dotdot[i]) { /* fill dot entry info */ + if (i == 0) { + d_info->name = "."; + d_info->name_len = 1; ++ dentry = dir->filp->f_path.dentry; + } else { + d_info->name = ".."; + d_info->name_len = 2; ++ dentry = dir->filp->f_path.dentry->d_parent; + } + + if (!match_pattern(d_info->name, d_info->name_len, +@@ -327,7 +330,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, + ksmbd_kstat.kstat = &kstat; + ksmbd_vfs_fill_dentry_attrs(work, + user_ns, +- dir->filp->f_path.dentry->d_parent, ++ dentry, + &ksmbd_kstat); + rc = fn(conn, info_level, d_info, &ksmbd_kstat); + if (rc) +diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h +index 6e79e7577f6b7..1eba8dabaf317 100644 +--- a/fs/ksmbd/smb_common.h ++++ b/fs/ksmbd/smb_common.h +@@ -412,6 +412,7 @@ struct smb_version_values { + __u32 max_read_size; + __u32 max_write_size; + __u32 max_trans_size; ++ __u32 max_credits; + __u32 large_lock_type; + __u32 exclusive_lock_type; + __u32 shared_lock_type; +diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c +index 1acf1892a466c..3ad6881e0f7ed 100644 +--- a/fs/ksmbd/transport_ipc.c ++++ b/fs/ksmbd/transport_ipc.c +@@ -301,6 +301,8 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req) + init_smb2_max_write_size(req->smb2_max_write); + if (req->smb2_max_trans) + init_smb2_max_trans_size(req->smb2_max_trans); ++ if (req->smb2_max_credits) ++ init_smb2_max_credits(req->smb2_max_credits); + + ret = ksmbd_set_netbios_name(req->netbios_name); + ret |= ksmbd_set_server_string(req->server_string); +diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c +index c14320e03b698..82a1429bbe127 100644 +--- a/fs/ksmbd/transport_tcp.c ++++ b/fs/ksmbd/transport_tcp.c +@@ -404,7 +404,7 @@ static int create_socket(struct interface *iface) + &ksmbd_socket); + if (ret) { + pr_err("Can't create socket for ipv4: %d\n", ret); +- goto out_error; ++ goto out_clear; + } + + sin.sin_family = PF_INET; +@@ -462,6 +462,7 @@ static int create_socket(struct interface *iface) + + out_error: + tcp_destroy_socket(ksmbd_socket); ++out_clear: + iface->ksmbd_socket = NULL; + return ret; + } +diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h +index b0d5b8feb4a36..432c947731779 100644 +--- a/fs/ksmbd/vfs.h ++++ b/fs/ksmbd/vfs.h +@@ -86,6 +86,7 @@ struct ksmbd_dir_info { + int last_entry_offset; + bool hide_dot_file; + int flags; ++ int last_entry_off_align; + }; + + struct ksmbd_readdir_data { +diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c +index cb3a7512c33ec..0a22a2faf5522 100644 +--- a/fs/lockd/svcsubs.c ++++ b/fs/lockd/svcsubs.c +@@ -179,19 +179,21 @@ nlm_delete_file(struct nlm_file *file) + static int nlm_unlock_files(struct nlm_file *file) + { + struct file_lock lock; +- struct file *f; + ++ locks_init_lock(&lock); + lock.fl_type = F_UNLCK; + lock.fl_start = 0; + lock.fl_end = OFFSET_MAX; +- for (f = file->f_file[0]; f <= file->f_file[1]; f++) { +- if (f && vfs_lock_file(f, F_SETLK, &lock, NULL) < 0) { +- pr_warn("lockd: unlock failure in %s:%d\n", +- __FILE__, __LINE__); +- return 1; +- } +- } ++ if (file->f_file[O_RDONLY] && ++ vfs_lock_file(file->f_file[O_RDONLY], F_SETLK, &lock, NULL)) ++ goto out_err; ++ if (file->f_file[O_WRONLY] && ++ vfs_lock_file(file->f_file[O_WRONLY], F_SETLK, &lock, NULL)) ++ goto out_err; + return 0; ++out_err: ++ pr_warn("lockd: unlock failure in %s:%d\n", __FILE__, __LINE__); ++ return 1; + } + + /* +diff --git a/fs/namei.c b/fs/namei.c +index 1946d96677908..3bb65f48fe1da 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -3975,13 +3975,12 @@ int vfs_rmdir(struct user_namespace *mnt_userns, struct inode *dir, + dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); + detach_mounts(dentry); +- fsnotify_rmdir(dir, dentry); + + out: + inode_unlock(dentry->d_inode); + dput(dentry); + if (!error) +- d_delete(dentry); ++ d_delete_notify(dir, dentry); + return error; + } + EXPORT_SYMBOL(vfs_rmdir); +@@ -4103,7 +4102,6 @@ int vfs_unlink(struct user_namespace *mnt_userns, struct inode *dir, + if (!error) { + dont_mount(dentry); + detach_mounts(dentry); +- fsnotify_unlink(dir, dentry); + } + } + } +@@ -4111,9 +4109,11 @@ out: + inode_unlock(target); + + /* We don't d_delete() NFS sillyrenamed files--they still exist. */ +- if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { ++ if (!error && dentry->d_flags & DCACHE_NFSFS_RENAMED) { ++ fsnotify_unlink(dir, dentry); ++ } else if (!error) { + fsnotify_link_count(target); +- d_delete(dentry); ++ d_delete_notify(dir, dentry); + } + + return error; +diff --git a/fs/namespace.c b/fs/namespace.c +index 659a8f39c61af..b696543adab84 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -4263,12 +4263,11 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, + return err; + + err = user_path_at(dfd, path, kattr.lookup_flags, &target); +- if (err) +- return err; +- +- err = do_mount_setattr(&target, &kattr); ++ if (!err) { ++ err = do_mount_setattr(&target, &kattr); ++ path_put(&target); ++ } + finish_mount_kattr(&kattr); +- path_put(&target); + return err; + } + +diff --git a/fs/netfs/read_helper.c b/fs/netfs/read_helper.c +index 994ec22d40402..242f8bcb34a4c 100644 +--- a/fs/netfs/read_helper.c ++++ b/fs/netfs/read_helper.c +@@ -354,16 +354,11 @@ static void netfs_rreq_write_to_cache_work(struct work_struct *work) + netfs_rreq_do_write_to_cache(rreq); + } + +-static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq, +- bool was_async) ++static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq) + { +- if (was_async) { +- rreq->work.func = netfs_rreq_write_to_cache_work; +- if (!queue_work(system_unbound_wq, &rreq->work)) +- BUG(); +- } else { +- netfs_rreq_do_write_to_cache(rreq); +- } ++ rreq->work.func = netfs_rreq_write_to_cache_work; ++ if (!queue_work(system_unbound_wq, &rreq->work)) ++ BUG(); + } + + /* +@@ -560,7 +555,7 @@ again: + wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); + + if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags)) +- return netfs_rreq_write_to_cache(rreq, was_async); ++ return netfs_rreq_write_to_cache(rreq); + + netfs_rreq_completed(rreq, was_async); + } +@@ -963,7 +958,7 @@ int netfs_readpage(struct file *file, + rreq = netfs_alloc_read_request(ops, netfs_priv, file); + if (!rreq) { + if (netfs_priv) +- ops->cleanup(netfs_priv, page_file_mapping(page)); ++ ops->cleanup(page_file_mapping(page), netfs_priv); + unlock_page(page); + return -ENOMEM; + } +@@ -1190,7 +1185,7 @@ have_page: + goto error; + have_page_no_wait: + if (netfs_priv) +- ops->cleanup(netfs_priv, mapping); ++ ops->cleanup(mapping, netfs_priv); + *_page = page; + _leave(" = 0"); + return 0; +@@ -1201,7 +1196,7 @@ error: + unlock_page(page); + put_page(page); + if (netfs_priv) +- ops->cleanup(netfs_priv, mapping); ++ ops->cleanup(mapping, netfs_priv); + _leave(" = %d", ret); + return ret; + } +diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h +index 6a2033131c068..ccd4f245cae24 100644 +--- a/fs/nfs/callback.h ++++ b/fs/nfs/callback.h +@@ -170,7 +170,7 @@ struct cb_devicenotifyitem { + }; + + struct cb_devicenotifyargs { +- int ndevs; ++ uint32_t ndevs; + struct cb_devicenotifyitem *devs; + }; + +diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c +index ed9d580826f5a..f2bc5b5b764b7 100644 +--- a/fs/nfs/callback_proc.c ++++ b/fs/nfs/callback_proc.c +@@ -358,7 +358,7 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp, + struct cb_process_state *cps) + { + struct cb_devicenotifyargs *args = argp; +- int i; ++ uint32_t i; + __be32 res = 0; + struct nfs_client *clp = cps->clp; + struct nfs_server *server = NULL; +diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c +index 4c48d85f65170..ce3d1d5b1291f 100644 +--- a/fs/nfs/callback_xdr.c ++++ b/fs/nfs/callback_xdr.c +@@ -258,11 +258,9 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp, + void *argp) + { + struct cb_devicenotifyargs *args = argp; ++ uint32_t tmp, n, i; + __be32 *p; + __be32 status = 0; +- u32 tmp; +- int n, i; +- args->ndevs = 0; + + /* Num of device notifications */ + p = xdr_inline_decode(xdr, sizeof(uint32_t)); +@@ -271,7 +269,7 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp, + goto out; + } + n = ntohl(*p++); +- if (n <= 0) ++ if (n == 0) + goto out; + if (n > ULONG_MAX / sizeof(*args->devs)) { + status = htonl(NFS4ERR_BADXDR); +@@ -330,19 +328,21 @@ __be32 decode_devicenotify_args(struct svc_rqst *rqstp, + dev->cbd_immediate = 0; + } + +- args->ndevs++; +- + dprintk("%s: type %d layout 0x%x immediate %d\n", + __func__, dev->cbd_notify_type, dev->cbd_layout_type, + dev->cbd_immediate); + } ++ args->ndevs = n; ++ dprintk("%s: ndevs %d\n", __func__, args->ndevs); ++ return 0; ++err: ++ kfree(args->devs); + out: ++ args->devs = NULL; ++ args->ndevs = 0; + dprintk("%s: status %d ndevs %d\n", + __func__, ntohl(status), args->ndevs); + return status; +-err: +- kfree(args->devs); +- goto out; + } + + static __be32 decode_sessionid(struct xdr_stream *xdr, +diff --git a/fs/nfs/client.c b/fs/nfs/client.c +index 23e165d5ec9ca..090b16890e3d6 100644 +--- a/fs/nfs/client.c ++++ b/fs/nfs/client.c +@@ -177,6 +177,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) + INIT_LIST_HEAD(&clp->cl_superblocks); + clp->cl_rpcclient = ERR_PTR(-EINVAL); + ++ clp->cl_flags = cl_init->init_flags; + clp->cl_proto = cl_init->proto; + clp->cl_nconnect = cl_init->nconnect; + clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1; +@@ -427,7 +428,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init) + list_add_tail(&new->cl_share_link, + &nn->nfs_client_list); + spin_unlock(&nn->nfs_client_lock); +- new->cl_flags = cl_init->init_flags; + return rpc_ops->init_client(new, cl_init); + } + +@@ -860,6 +860,13 @@ int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs + server->namelen = pathinfo.max_namelen; + } + ++ if (clp->rpc_ops->discover_trunking != NULL && ++ (server->caps & NFS_CAP_FS_LOCATIONS)) { ++ error = clp->rpc_ops->discover_trunking(server, mntfh); ++ if (error < 0) ++ return error; ++ } ++ + return 0; + } + EXPORT_SYMBOL_GPL(nfs_probe_fsinfo); +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index 1a6d2867fba4f..9adc6f57a0083 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -870,7 +870,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc, + + status = nfs_readdir_page_filler(desc, entry, pages, pglen, + arrays, narrays); +- } while (!status && nfs_readdir_page_needs_filling(page)); ++ } while (!status && nfs_readdir_page_needs_filling(page) && ++ page_mapping(page)); + + nfs_readdir_free_pages(pages, array_size); + out_release_label: +@@ -1048,6 +1049,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc) + goto out; + + desc->page_index = 0; ++ desc->cache_entry_index = 0; + desc->last_cookie = desc->dir_cookie; + desc->duped = 0; + +@@ -1269,13 +1271,12 @@ static bool nfs_verifier_is_delegated(struct dentry *dentry) + static void nfs_set_verifier_locked(struct dentry *dentry, unsigned long verf) + { + struct inode *inode = d_inode(dentry); ++ struct inode *dir = d_inode(dentry->d_parent); + +- if (!nfs_verifier_is_delegated(dentry) && +- !nfs_verify_change_attribute(d_inode(dentry->d_parent), verf)) +- goto out; ++ if (!nfs_verify_change_attribute(dir, verf)) ++ return; + if (inode && NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) + nfs_set_verifier_delegated(&verf); +-out: + dentry->d_time = verf; + } + +@@ -1413,7 +1414,7 @@ out_force: + static void nfs_mark_dir_for_revalidate(struct inode *inode) + { + spin_lock(&inode->i_lock); +- nfs_set_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE); ++ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE); + spin_unlock(&inode->i_lock); + } + +@@ -1983,6 +1984,24 @@ out: + + no_open: + res = nfs_lookup(dir, dentry, lookup_flags); ++ if (!res) { ++ inode = d_inode(dentry); ++ if ((lookup_flags & LOOKUP_DIRECTORY) && inode && ++ !(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) ++ res = ERR_PTR(-ENOTDIR); ++ else if (inode && S_ISREG(inode->i_mode)) ++ res = ERR_PTR(-EOPENSTALE); ++ } else if (!IS_ERR(res)) { ++ inode = d_inode(res); ++ if ((lookup_flags & LOOKUP_DIRECTORY) && inode && ++ !(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) { ++ dput(res); ++ res = ERR_PTR(-ENOTDIR); ++ } else if (inode && S_ISREG(inode->i_mode)) { ++ dput(res); ++ res = ERR_PTR(-EOPENSTALE); ++ } ++ } + if (switched) { + d_lookup_done(dentry); + if (!res) +@@ -2383,6 +2402,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) + + trace_nfs_link_enter(inode, dir, dentry); + d_drop(dentry); ++ if (S_ISREG(inode->i_mode)) ++ nfs_sync_inode(inode); + error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); + if (error == 0) { + ihold(inode); +@@ -2471,6 +2492,8 @@ int nfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + } + } + ++ if (S_ISREG(old_inode->i_mode)) ++ nfs_sync_inode(old_inode); + task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL); + if (IS_ERR(task)) { + error = PTR_ERR(task); +@@ -2676,7 +2699,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co + return NULL; + } + +-static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, bool may_block) ++static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block) + { + struct nfs_inode *nfsi = NFS_I(inode); + struct nfs_access_entry *cache; +@@ -2706,8 +2729,7 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred * + spin_lock(&inode->i_lock); + retry = false; + } +- res->cred = cache->cred; +- res->mask = cache->mask; ++ *mask = cache->mask; + list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru); + err = 0; + out: +@@ -2719,7 +2741,7 @@ out_zap: + return -ENOENT; + } + +-static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res) ++static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, u32 *mask) + { + /* Only check the most recently returned cache entry, + * but do it without locking. +@@ -2741,22 +2763,21 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre + goto out; + if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) + goto out; +- res->cred = cache->cred; +- res->mask = cache->mask; ++ *mask = cache->mask; + err = 0; + out: + rcu_read_unlock(); + return err; + } + +-int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct +-nfs_access_entry *res, bool may_block) ++int nfs_access_get_cached(struct inode *inode, const struct cred *cred, ++ u32 *mask, bool may_block) + { + int status; + +- status = nfs_access_get_cached_rcu(inode, cred, res); ++ status = nfs_access_get_cached_rcu(inode, cred, mask); + if (status != 0) +- status = nfs_access_get_cached_locked(inode, cred, res, ++ status = nfs_access_get_cached_locked(inode, cred, mask, + may_block); + + return status; +@@ -2877,7 +2898,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask) + + trace_nfs_access_enter(inode); + +- status = nfs_access_get_cached(inode, cred, &cache, may_block); ++ status = nfs_access_get_cached(inode, cred, &cache.mask, may_block); + if (status == 0) + goto out_cached; + +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index 2e894fec036b0..3c0335c15a730 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -620,7 +620,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data) + nfs_unlock_and_release_request(req); + } + +- if (atomic_dec_and_test(&cinfo.mds->rpcs_out)) ++ if (nfs_commit_end(cinfo.mds)) + nfs_direct_write_complete(dreq); + } + +diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c +index c9b61b818ec11..bfa7202ca7be1 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c ++++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c +@@ -378,10 +378,10 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, + goto noconnect; + + ds = mirror->mirror_ds->ds; ++ if (READ_ONCE(ds->ds_clp)) ++ goto out; + /* matching smp_wmb() in _nfs4_pnfs_v3/4_ds_connect */ + smp_rmb(); +- if (ds->ds_clp) +- goto out; + + /* FIXME: For now we assume the server sent only one version of NFS + * to use for the DS. +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 853213b3a2095..410f87bc48cca 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -210,10 +210,15 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) + flags &= ~NFS_INO_INVALID_XATTR; + if (flags & NFS_INO_INVALID_DATA) + nfs_fscache_invalidate(inode); +- if (inode->i_mapping->nrpages == 0) +- flags &= ~(NFS_INO_INVALID_DATA|NFS_INO_DATA_INVAL_DEFER); + flags &= ~(NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED); ++ + nfsi->cache_validity |= flags; ++ ++ if (inode->i_mapping->nrpages == 0) ++ nfsi->cache_validity &= ~(NFS_INO_INVALID_DATA | ++ NFS_INO_DATA_INVAL_DEFER); ++ else if (nfsi->cache_validity & NFS_INO_INVALID_DATA) ++ nfsi->cache_validity &= ~NFS_INO_DATA_INVAL_DEFER; + } + EXPORT_SYMBOL_GPL(nfs_set_cache_invalid); + +@@ -835,12 +840,9 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path, + } + + /* Flush out writes to the server in order to update c/mtime. */ +- if ((request_mask & (STATX_CTIME|STATX_MTIME)) && +- S_ISREG(inode->i_mode)) { +- err = filemap_write_and_wait(inode->i_mapping); +- if (err) +- goto out; +- } ++ if ((request_mask & (STATX_CTIME | STATX_MTIME)) && ++ S_ISREG(inode->i_mode)) ++ filemap_write_and_wait(inode->i_mapping); + + /* + * We may force a getattr if the user cares about atime. +@@ -1777,8 +1779,10 @@ static int nfs_inode_finish_partial_attr_update(const struct nfs_fattr *fattr, + NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_OTHER | + NFS_INO_INVALID_NLINK; + unsigned long cache_validity = NFS_I(inode)->cache_validity; ++ enum nfs4_change_attr_type ctype = NFS_SERVER(inode)->change_attr_type; + +- if (!(cache_validity & NFS_INO_INVALID_CHANGE) && ++ if (ctype != NFS4_CHANGE_TYPE_IS_UNDEFINED && ++ !(cache_validity & NFS_INO_INVALID_CHANGE) && + (cache_validity & check_valid) != 0 && + (fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && + nfs_inode_attrs_cmp_monotonic(fattr, inode) == 0) +diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c +index e6eca1d7481b8..9274c9c5efea6 100644 +--- a/fs/nfs/nfs3xdr.c ++++ b/fs/nfs/nfs3xdr.c +@@ -2227,7 +2227,7 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr, + + /* ignore properties */ + result->lease_time = 0; +- result->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA; ++ result->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED; + return 0; + } + +diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c +index a24349512ffe9..9865b5c37d889 100644 +--- a/fs/nfs/nfs42proc.c ++++ b/fs/nfs/nfs42proc.c +@@ -285,7 +285,9 @@ static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len) + loff_t newsize = pos + len; + loff_t end = newsize - 1; + +- truncate_pagecache_range(inode, pos, end); ++ WARN_ON_ONCE(invalidate_inode_pages2_range(inode->i_mapping, ++ pos >> PAGE_SHIFT, end >> PAGE_SHIFT)); ++ + spin_lock(&inode->i_lock); + if (newsize > i_size_read(inode)) + i_size_write(inode, newsize); +diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c +index c8bad735e4c19..271e5f92ed019 100644 +--- a/fs/nfs/nfs42xdr.c ++++ b/fs/nfs/nfs42xdr.c +@@ -1434,8 +1434,7 @@ static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, + status = decode_clone(xdr); + if (status) + goto out; +- status = decode_getfattr(xdr, res->dst_fattr, res->server); +- ++ decode_getfattr(xdr, res->dst_fattr, res->server); + out: + res->rpc_status = status; + return status; +diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h +index ba78df4b13d94..f8672a34fd635 100644 +--- a/fs/nfs/nfs4_fs.h ++++ b/fs/nfs/nfs4_fs.h +@@ -261,8 +261,8 @@ struct nfs4_state_maintenance_ops { + }; + + struct nfs4_mig_recovery_ops { +- int (*get_locations)(struct inode *, struct nfs4_fs_locations *, +- struct page *, const struct cred *); ++ int (*get_locations)(struct nfs_server *, struct nfs_fh *, ++ struct nfs4_fs_locations *, struct page *, const struct cred *); + int (*fsid_present)(struct inode *, const struct cred *); + }; + +@@ -281,7 +281,8 @@ struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *, + int nfs4_submount(struct fs_context *, struct nfs_server *); + int nfs4_replace_transport(struct nfs_server *server, + const struct nfs4_fs_locations *locations); +- ++size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa, ++ size_t salen, struct net *net, int port); + /* nfs4proc.c */ + extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *); + extern int nfs4_async_handle_error(struct rpc_task *task, +@@ -303,8 +304,9 @@ extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait); + extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); + extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *, + struct nfs4_fs_locations *, struct page *); +-extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *, +- struct page *page, const struct cred *); ++extern int nfs4_proc_get_locations(struct nfs_server *, struct nfs_fh *, ++ struct nfs4_fs_locations *, ++ struct page *page, const struct cred *); + extern int nfs4_proc_fsid_present(struct inode *, const struct cred *); + extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, + struct dentry *, +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index af57332503bed..ed06b68b2b4e9 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -1368,8 +1368,11 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname, + } + nfs_put_client(clp); + +- if (server->nfs_client->cl_hostname == NULL) ++ if (server->nfs_client->cl_hostname == NULL) { + server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL); ++ if (server->nfs_client->cl_hostname == NULL) ++ return -ENOMEM; ++ } + nfs_server_insert_lists(server); + + return nfs_probe_destination(server); +diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c +index 8d8aba305ecca..f331866dd4182 100644 +--- a/fs/nfs/nfs4idmap.c ++++ b/fs/nfs/nfs4idmap.c +@@ -487,7 +487,7 @@ nfs_idmap_new(struct nfs_client *clp) + err_destroy_pipe: + rpc_destroy_pipe_data(idmap->idmap_pipe); + err: +- get_user_ns(idmap->user_ns); ++ put_user_ns(idmap->user_ns); + kfree(idmap); + return error; + } +diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c +index 873342308dc0d..3680c8da510c9 100644 +--- a/fs/nfs/nfs4namespace.c ++++ b/fs/nfs/nfs4namespace.c +@@ -164,16 +164,21 @@ static int nfs4_validate_fspath(struct dentry *dentry, + return 0; + } + +-static size_t nfs_parse_server_name(char *string, size_t len, +- struct sockaddr *sa, size_t salen, struct net *net) ++size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa, ++ size_t salen, struct net *net, int port) + { + ssize_t ret; + + ret = rpc_pton(net, string, len, sa, salen); + if (ret == 0) { +- ret = nfs_dns_resolve_name(net, string, len, sa, salen); +- if (ret < 0) +- ret = 0; ++ ret = rpc_uaddr2sockaddr(net, string, len, sa, salen); ++ if (ret == 0) { ++ ret = nfs_dns_resolve_name(net, string, len, sa, salen); ++ if (ret < 0) ++ ret = 0; ++ } ++ } else if (port) { ++ rpc_set_port(sa, port); + } + return ret; + } +@@ -328,7 +333,7 @@ static int try_location(struct fs_context *fc, + nfs_parse_server_name(buf->data, buf->len, + &ctx->nfs_server.address, + sizeof(ctx->nfs_server._address), +- fc->net_ns); ++ fc->net_ns, 0); + if (ctx->nfs_server.addrlen == 0) + continue; + +@@ -496,7 +501,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, + continue; + + salen = nfs_parse_server_name(buf->data, buf->len, +- sap, addr_bufsize, net); ++ sap, addr_bufsize, net, 0); + if (salen == 0) + continue; + rpc_set_port(sap, NFS_PORT); +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index e1214bb6b7ee5..53be03681f69e 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -1232,8 +1232,7 @@ nfs4_update_changeattr_locked(struct inode *inode, + NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL | + NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER | + NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK | +- NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR | +- NFS_INO_REVAL_PAGECACHE; ++ NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR; + nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); + } + nfsi->attrtimeo_timestamp = jiffies; +@@ -1609,15 +1608,16 @@ static bool nfs_stateid_is_sequential(struct nfs4_state *state, + { + if (test_bit(NFS_OPEN_STATE, &state->flags)) { + /* The common case - we're updating to a new sequence number */ +- if (nfs4_stateid_match_other(stateid, &state->open_stateid) && +- nfs4_stateid_is_next(&state->open_stateid, stateid)) { +- return true; ++ if (nfs4_stateid_match_other(stateid, &state->open_stateid)) { ++ if (nfs4_stateid_is_next(&state->open_stateid, stateid)) ++ return true; ++ return false; + } +- } else { +- /* This is the first OPEN in this generation */ +- if (stateid->seqid == cpu_to_be32(1)) +- return true; ++ /* The server returned a new stateid */ + } ++ /* This is the first OPEN in this generation */ ++ if (stateid->seqid == cpu_to_be32(1)) ++ return true; + return false; + } + +@@ -3893,6 +3893,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f + if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL) + server->caps |= NFS_CAP_SECURITY_LABEL; + #endif ++ if (res.attr_bitmask[0] & FATTR4_WORD0_FS_LOCATIONS) ++ server->caps |= NFS_CAP_FS_LOCATIONS; + if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID)) + server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID; + if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE)) +@@ -3949,6 +3951,60 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) + return err; + } + ++static int _nfs4_discover_trunking(struct nfs_server *server, ++ struct nfs_fh *fhandle) ++{ ++ struct nfs4_fs_locations *locations = NULL; ++ struct page *page; ++ const struct cred *cred; ++ struct nfs_client *clp = server->nfs_client; ++ const struct nfs4_state_maintenance_ops *ops = ++ clp->cl_mvops->state_renewal_ops; ++ int status = -ENOMEM; ++ ++ cred = ops->get_state_renewal_cred(clp); ++ if (cred == NULL) { ++ cred = nfs4_get_clid_cred(clp); ++ if (cred == NULL) ++ return -ENOKEY; ++ } ++ ++ page = alloc_page(GFP_KERNEL); ++ locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); ++ if (page == NULL || locations == NULL) ++ goto out; ++ ++ status = nfs4_proc_get_locations(server, fhandle, locations, page, ++ cred); ++ if (status) ++ goto out; ++out: ++ if (page) ++ __free_page(page); ++ kfree(locations); ++ return status; ++} ++ ++static int nfs4_discover_trunking(struct nfs_server *server, ++ struct nfs_fh *fhandle) ++{ ++ struct nfs4_exception exception = { ++ .interruptible = true, ++ }; ++ struct nfs_client *clp = server->nfs_client; ++ int err = 0; ++ ++ if (!nfs4_has_session(clp)) ++ goto out; ++ do { ++ err = nfs4_handle_exception(server, ++ _nfs4_discover_trunking(server, fhandle), ++ &exception); ++ } while (exception.retry); ++out: ++ return err; ++} ++ + static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fsinfo *info) + { +@@ -7676,7 +7732,7 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler, + const char *key, const void *buf, + size_t buflen, int flags) + { +- struct nfs_access_entry cache; ++ u32 mask; + int ret; + + if (!nfs_server_capable(inode, NFS_CAP_XATTR)) +@@ -7691,8 +7747,8 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler, + * do a cached access check for the XA* flags to possibly avoid + * doing an RPC and getting EACCES back. + */ +- if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) { +- if (!(cache.mask & NFS_ACCESS_XAWRITE)) ++ if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) { ++ if (!(mask & NFS_ACCESS_XAWRITE)) + return -EACCES; + } + +@@ -7713,14 +7769,14 @@ static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *key, void *buf, size_t buflen) + { +- struct nfs_access_entry cache; ++ u32 mask; + ssize_t ret; + + if (!nfs_server_capable(inode, NFS_CAP_XATTR)) + return -EOPNOTSUPP; + +- if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) { +- if (!(cache.mask & NFS_ACCESS_XAREAD)) ++ if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) { ++ if (!(mask & NFS_ACCESS_XAREAD)) + return -EACCES; + } + +@@ -7745,13 +7801,13 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len) + ssize_t ret, size; + char *buf; + size_t buflen; +- struct nfs_access_entry cache; ++ u32 mask; + + if (!nfs_server_capable(inode, NFS_CAP_XATTR)) + return 0; + +- if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) { +- if (!(cache.mask & NFS_ACCESS_XALIST)) ++ if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) { ++ if (!(mask & NFS_ACCESS_XALIST)) + return 0; + } + +@@ -7883,18 +7939,18 @@ int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, + * appended to this compound to identify the client ID which is + * performing recovery. + */ +-static int _nfs40_proc_get_locations(struct inode *inode, ++static int _nfs40_proc_get_locations(struct nfs_server *server, ++ struct nfs_fh *fhandle, + struct nfs4_fs_locations *locations, + struct page *page, const struct cred *cred) + { +- struct nfs_server *server = NFS_SERVER(inode); + struct rpc_clnt *clnt = server->client; + u32 bitmask[2] = { + [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, + }; + struct nfs4_fs_locations_arg args = { + .clientid = server->nfs_client->cl_clientid, +- .fh = NFS_FH(inode), ++ .fh = fhandle, + .page = page, + .bitmask = bitmask, + .migration = 1, /* skip LOOKUP */ +@@ -7940,17 +7996,17 @@ static int _nfs40_proc_get_locations(struct inode *inode, + * When the client supports GETATTR(fs_locations_info), it can + * be plumbed in here. + */ +-static int _nfs41_proc_get_locations(struct inode *inode, ++static int _nfs41_proc_get_locations(struct nfs_server *server, ++ struct nfs_fh *fhandle, + struct nfs4_fs_locations *locations, + struct page *page, const struct cred *cred) + { +- struct nfs_server *server = NFS_SERVER(inode); + struct rpc_clnt *clnt = server->client; + u32 bitmask[2] = { + [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, + }; + struct nfs4_fs_locations_arg args = { +- .fh = NFS_FH(inode), ++ .fh = fhandle, + .page = page, + .bitmask = bitmask, + .migration = 1, /* skip LOOKUP */ +@@ -7999,11 +8055,11 @@ static int _nfs41_proc_get_locations(struct inode *inode, + * -NFS4ERR_LEASE_MOVED is returned if the server still has leases + * from this client that require migration recovery. + */ +-int nfs4_proc_get_locations(struct inode *inode, ++int nfs4_proc_get_locations(struct nfs_server *server, ++ struct nfs_fh *fhandle, + struct nfs4_fs_locations *locations, + struct page *page, const struct cred *cred) + { +- struct nfs_server *server = NFS_SERVER(inode); + struct nfs_client *clp = server->nfs_client; + const struct nfs4_mig_recovery_ops *ops = + clp->cl_mvops->mig_recovery_ops; +@@ -8016,10 +8072,11 @@ int nfs4_proc_get_locations(struct inode *inode, + (unsigned long long)server->fsid.major, + (unsigned long long)server->fsid.minor, + clp->cl_hostname); +- nfs_display_fhandle(NFS_FH(inode), __func__); ++ nfs_display_fhandle(fhandle, __func__); + + do { +- status = ops->get_locations(inode, locations, page, cred); ++ status = ops->get_locations(server, fhandle, locations, page, ++ cred); + if (status != -NFS4ERR_DELAY) + break; + nfs4_handle_exception(server, status, &exception); +@@ -10513,6 +10570,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { + .free_client = nfs4_free_client, + .create_server = nfs4_create_server, + .clone_server = nfs_clone_server, ++ .discover_trunking = nfs4_discover_trunking, + }; + + static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index f22818a80c2c7..51f5cb41e87a4 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2097,7 +2097,8 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred + } + + inode = d_inode(server->super->s_root); +- result = nfs4_proc_get_locations(inode, locations, page, cred); ++ result = nfs4_proc_get_locations(server, NFS_FH(inode), locations, ++ page, cred); + if (result) { + dprintk("<-- %s: failed to retrieve fs_locations: %d\n", + __func__, result); +@@ -2105,6 +2106,9 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred + } + + result = -NFS4ERR_NXIO; ++ if (!locations->nlocations) ++ goto out; ++ + if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) { + dprintk("<-- %s: No fs_locations data, migration skipped\n", + __func__); +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index a8cff19c6f00c..2a1bf0a72d5bf 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -3693,8 +3693,6 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st + if (unlikely(!p)) + goto out_eio; + n = be32_to_cpup(p); +- if (n <= 0) +- goto out_eio; + for (res->nlocations = 0; res->nlocations < n; res->nlocations++) { + u32 m; + struct nfs4_fs_location *loc; +@@ -4197,10 +4195,11 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, + } else + printk(KERN_WARNING "%s: label too long (%u)!\n", + __func__, len); ++ if (label && label->label) ++ dprintk("%s: label=%.*s, len=%d, PI=%d, LFS=%d\n", ++ __func__, label->len, (char *)label->label, ++ label->len, label->pi, label->lfs); + } +- if (label && label->label) +- dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, +- (char *)label->label, label->len, label->pi, label->lfs); + return status; + } + +diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h +index d810ae674f4e8..a0f6ff094b3a4 100644 +--- a/fs/nfs/pnfs.h ++++ b/fs/nfs/pnfs.h +@@ -517,7 +517,7 @@ pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg, + { + struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; + +- if (!lseg || !fl_cinfo->ops->mark_request_commit) ++ if (!lseg || !fl_cinfo->ops || !fl_cinfo->ops->mark_request_commit) + return false; + fl_cinfo->ops->mark_request_commit(req, lseg, cinfo, ds_commit_idx); + return true; +diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c +index cf19914fec817..316f68f96e573 100644 +--- a/fs/nfs/pnfs_nfs.c ++++ b/fs/nfs/pnfs_nfs.c +@@ -468,7 +468,6 @@ pnfs_bucket_alloc_ds_commits(struct list_head *list, + goto out_error; + data->ds_commit_index = i; + list_add_tail(&data->list, list); +- atomic_inc(&cinfo->mds->rpcs_out); + nreq++; + } + mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex); +@@ -520,7 +519,6 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages, + data->ds_commit_index = -1; + list_splice_init(mds_pages, &data->pages); + list_add_tail(&data->list, &list); +- atomic_inc(&cinfo->mds->rpcs_out); + nreq++; + } + +@@ -895,7 +893,7 @@ static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv, + } + + smp_wmb(); +- ds->ds_clp = clp; ++ WRITE_ONCE(ds->ds_clp, clp); + dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); + out: + return status; +@@ -973,7 +971,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv, + } + + smp_wmb(); +- ds->ds_clp = clp; ++ WRITE_ONCE(ds->ds_clp, clp); + dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); + out: + return status; +diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c +index ea19dbf123014..ecc4e717808c4 100644 +--- a/fs/nfs/proc.c ++++ b/fs/nfs/proc.c +@@ -91,7 +91,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, + info->dtpref = fsinfo.tsize; + info->maxfilesize = 0x7FFFFFFF; + info->lease_time = 0; +- info->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA; ++ info->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED; + return 0; + } + +diff --git a/fs/nfs/write.c b/fs/nfs/write.c +index eae9bf1140417..7dce3e735fc53 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -1038,25 +1038,11 @@ nfs_scan_commit_list(struct list_head *src, struct list_head *dst, + struct nfs_page *req, *tmp; + int ret = 0; + +-restart: + list_for_each_entry_safe(req, tmp, src, wb_list) { + kref_get(&req->wb_kref); + if (!nfs_lock_request(req)) { +- int status; +- +- /* Prevent deadlock with nfs_lock_and_join_requests */ +- if (!list_empty(dst)) { +- nfs_release_request(req); +- continue; +- } +- /* Ensure we make progress to prevent livelock */ +- mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex); +- status = nfs_wait_on_request(req); + nfs_release_request(req); +- mutex_lock(&NFS_I(cinfo->inode)->commit_mutex); +- if (status < 0) +- break; +- goto restart; ++ continue; + } + nfs_request_remove_commit_list(req, cinfo); + clear_bit(PG_COMMIT_TO_DS, &req->wb_flags); +@@ -1671,10 +1657,13 @@ static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo) + atomic_inc(&cinfo->rpcs_out); + } + +-static void nfs_commit_end(struct nfs_mds_commit_info *cinfo) ++bool nfs_commit_end(struct nfs_mds_commit_info *cinfo) + { +- if (atomic_dec_and_test(&cinfo->rpcs_out)) ++ if (atomic_dec_and_test(&cinfo->rpcs_out)) { + wake_up_var(&cinfo->rpcs_out); ++ return true; ++ } ++ return false; + } + + void nfs_commitdata_release(struct nfs_commit_data *data) +@@ -1774,6 +1763,7 @@ void nfs_init_commit(struct nfs_commit_data *data, + data->res.fattr = &data->fattr; + data->res.verf = &data->verf; + nfs_fattr_init(&data->fattr); ++ nfs_commit_begin(cinfo->mds); + } + EXPORT_SYMBOL_GPL(nfs_init_commit); + +@@ -1820,7 +1810,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how, + + /* Set up the argument struct */ + nfs_init_commit(data, head, NULL, cinfo); +- atomic_inc(&cinfo->mds->rpcs_out); + if (NFS_SERVER(inode)->nfs_client->cl_minorversion) + task_flags = RPC_TASK_MOVEABLE; + return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode), +@@ -1936,6 +1925,7 @@ static int __nfs_commit_inode(struct inode *inode, int how, + int may_wait = how & FLUSH_SYNC; + int ret, nscan; + ++ how &= ~FLUSH_SYNC; + nfs_init_cinfo_from_inode(&cinfo, inode); + nfs_commit_begin(cinfo.mds); + for (;;) { +diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c +index 17715a6c7a409..b540489ea240d 100644 +--- a/fs/nfsd/nfs3proc.c ++++ b/fs/nfsd/nfs3proc.c +@@ -150,13 +150,17 @@ nfsd3_proc_read(struct svc_rqst *rqstp) + unsigned int len; + int v; + +- argp->count = min_t(u32, argp->count, max_blocksize); +- + dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", + SVCFH_fmt(&argp->fh), + (unsigned long) argp->count, + (unsigned long long) argp->offset); + ++ argp->count = min_t(u32, argp->count, max_blocksize); ++ if (argp->offset > (u64)OFFSET_MAX) ++ argp->offset = (u64)OFFSET_MAX; ++ if (argp->offset + argp->count > (u64)OFFSET_MAX) ++ argp->count = (u64)OFFSET_MAX - argp->offset; ++ + v = 0; + len = argp->count; + resp->pages = rqstp->rq_next_page; +@@ -199,19 +203,19 @@ nfsd3_proc_write(struct svc_rqst *rqstp) + (unsigned long long) argp->offset, + argp->stable? " stable" : ""); + ++ resp->status = nfserr_fbig; ++ if (argp->offset > (u64)OFFSET_MAX || ++ argp->offset + argp->len > (u64)OFFSET_MAX) ++ return rpc_success; ++ + fh_copy(&resp->fh, &argp->fh); + resp->committed = argp->stable; +- nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages, +- &argp->first, cnt); +- if (!nvecs) { +- resp->status = nfserr_io; +- goto out; +- } ++ nvecs = svc_fill_write_vector(rqstp, &argp->payload); ++ + resp->status = nfsd_write(rqstp, &resp->fh, argp->offset, + rqstp->rq_vec, nvecs, &cnt, + resp->committed, resp->verf); + resp->count = cnt; +-out: + return rpc_success; + } + +@@ -439,22 +443,19 @@ nfsd3_proc_link(struct svc_rqst *rqstp) + + static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp, + struct nfsd3_readdirres *resp, +- int count) ++ u32 count) + { + struct xdr_buf *buf = &resp->dirlist; + struct xdr_stream *xdr = &resp->xdr; + +- count = min_t(u32, count, svc_max_payload(rqstp)); ++ count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); + + memset(buf, 0, sizeof(*buf)); + + /* Reserve room for the NULL ptr & eof flag (-2 words) */ + buf->buflen = count - XDR_UNIT * 2; + buf->pages = rqstp->rq_next_page; +- while (count > 0) { +- rqstp->rq_next_page++; +- count -= PAGE_SIZE; +- } ++ rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; + + /* This is xdr_init_encode(), but it assumes that + * the head kvec has already been consumed. */ +@@ -463,7 +464,7 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp, + xdr->page_ptr = buf->pages; + xdr->iov = NULL; + xdr->p = page_address(*buf->pages); +- xdr->end = xdr->p + (PAGE_SIZE >> 2); ++ xdr->end = (void *)xdr->p + min_t(u32, buf->buflen, PAGE_SIZE); + xdr->rqst = NULL; + } + +diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c +index 0a5ebc52e6a9c..48d4f99b7f901 100644 +--- a/fs/nfsd/nfs3xdr.c ++++ b/fs/nfsd/nfs3xdr.c +@@ -254,7 +254,7 @@ svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, + if (xdr_stream_decode_u64(xdr, &newsize) < 0) + return false; + iap->ia_valid |= ATTR_SIZE; +- iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX); ++ iap->ia_size = newsize; + } + if (xdr_stream_decode_u32(xdr, &set_it) < 0) + return false; +@@ -487,11 +487,6 @@ neither: + return true; + } + +-static bool fs_supports_change_attribute(struct super_block *sb) +-{ +- return sb->s_flags & SB_I_VERSION || sb->s_export_op->fetch_iversion; +-} +- + /* + * Fill in the pre_op attr for the wcc data + */ +@@ -500,26 +495,24 @@ void fill_pre_wcc(struct svc_fh *fhp) + struct inode *inode; + struct kstat stat; + bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE); ++ __be32 err; + + if (fhp->fh_no_wcc || fhp->fh_pre_saved) + return; + inode = d_inode(fhp->fh_dentry); +- if (fs_supports_change_attribute(inode->i_sb) || !v4) { +- __be32 err = fh_getattr(fhp, &stat); +- +- if (err) { +- /* Grab the times from inode anyway */ +- stat.mtime = inode->i_mtime; +- stat.ctime = inode->i_ctime; +- stat.size = inode->i_size; +- } +- fhp->fh_pre_mtime = stat.mtime; +- fhp->fh_pre_ctime = stat.ctime; +- fhp->fh_pre_size = stat.size; ++ err = fh_getattr(fhp, &stat); ++ if (err) { ++ /* Grab the times from inode anyway */ ++ stat.mtime = inode->i_mtime; ++ stat.ctime = inode->i_ctime; ++ stat.size = inode->i_size; + } + if (v4) + fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode); + ++ fhp->fh_pre_mtime = stat.mtime; ++ fhp->fh_pre_ctime = stat.ctime; ++ fhp->fh_pre_size = stat.size; + fhp->fh_pre_saved = true; + } + +@@ -530,6 +523,7 @@ void fill_post_wcc(struct svc_fh *fhp) + { + bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE); + struct inode *inode = d_inode(fhp->fh_dentry); ++ __be32 err; + + if (fhp->fh_no_wcc) + return; +@@ -537,16 +531,12 @@ void fill_post_wcc(struct svc_fh *fhp) + if (fhp->fh_post_saved) + printk("nfsd: inode locked twice during operation.\n"); + +- fhp->fh_post_saved = true; +- +- if (fs_supports_change_attribute(inode->i_sb) || !v4) { +- __be32 err = fh_getattr(fhp, &fhp->fh_post_attr); +- +- if (err) { +- fhp->fh_post_saved = false; +- fhp->fh_post_attr.ctime = inode->i_ctime; +- } +- } ++ err = fh_getattr(fhp, &fhp->fh_post_attr); ++ if (err) { ++ fhp->fh_post_saved = false; ++ fhp->fh_post_attr.ctime = inode->i_ctime; ++ } else ++ fhp->fh_post_saved = true; + if (v4) + fhp->fh_post_change = + nfsd4_change_attribute(&fhp->fh_post_attr, inode); +@@ -621,9 +611,6 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) + struct xdr_stream *xdr = &rqstp->rq_arg_stream; + struct nfsd3_writeargs *args = rqstp->rq_argp; + u32 max_blocksize = svc_max_payload(rqstp); +- struct kvec *head = rqstp->rq_arg.head; +- struct kvec *tail = rqstp->rq_arg.tail; +- size_t remaining; + + if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) + return 0; +@@ -641,17 +628,12 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) + /* request sanity */ + if (args->count != args->len) + return 0; +- remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; +- remaining -= xdr_stream_pos(xdr); +- if (remaining < xdr_align_size(args->len)) +- return 0; + if (args->count > max_blocksize) { + args->count = max_blocksize; + args->len = max_blocksize; + } +- +- args->first.iov_base = xdr->p; +- args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); ++ if (!xdr_stream_subsegment(xdr, &args->payload, args->count)) ++ return 0; + + return 1; + } +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 486c5dba4b650..65200910107f3 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -782,12 +782,16 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + __be32 status; + + read->rd_nf = NULL; +- if (read->rd_offset >= OFFSET_MAX) +- return nfserr_inval; + + trace_nfsd_read_start(rqstp, &cstate->current_fh, + read->rd_offset, read->rd_length); + ++ read->rd_length = min_t(u32, read->rd_length, svc_max_payload(rqstp)); ++ if (read->rd_offset > (u64)OFFSET_MAX) ++ read->rd_offset = (u64)OFFSET_MAX; ++ if (read->rd_offset + read->rd_length > (u64)OFFSET_MAX) ++ read->rd_length = (u64)OFFSET_MAX - read->rd_offset; ++ + /* + * If we do a zero copy read, then a client will see read data + * that reflects the state of the file *after* performing the +@@ -1018,8 +1022,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + unsigned long cnt; + int nvecs; + +- if (write->wr_offset >= OFFSET_MAX) +- return nfserr_inval; ++ if (write->wr_offset > (u64)OFFSET_MAX || ++ write->wr_offset + write->wr_buflen > (u64)OFFSET_MAX) ++ return nfserr_fbig; + + cnt = write->wr_buflen; + trace_nfsd_write_start(rqstp, &cstate->current_fh, +@@ -1033,8 +1038,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, + + write->wr_how_written = write->wr_stable_how; + +- nvecs = svc_fill_write_vector(rqstp, write->wr_payload.pages, +- write->wr_payload.head, write->wr_buflen); ++ nvecs = svc_fill_write_vector(rqstp, &write->wr_payload); + WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec)); + + status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf, +diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c +index 6fedc49726bf7..c634483d85d2a 100644 +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -2156,6 +2156,7 @@ static struct notifier_block nfsd4_cld_block = { + int + register_cld_notifier(void) + { ++ WARN_ON(!nfsd_net_id); + return rpc_pipefs_notifier_register(&nfsd4_cld_block); + } + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 3f4027a5de883..db4a47a280dc5 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1207,6 +1207,11 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) + return 0; + } + ++static bool delegation_hashed(struct nfs4_delegation *dp) ++{ ++ return !(list_empty(&dp->dl_perfile)); ++} ++ + static bool + unhash_delegation_locked(struct nfs4_delegation *dp) + { +@@ -1214,7 +1219,7 @@ unhash_delegation_locked(struct nfs4_delegation *dp) + + lockdep_assert_held(&state_lock); + +- if (list_empty(&dp->dl_perfile)) ++ if (!delegation_hashed(dp)) + return false; + + dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID; +@@ -4107,8 +4112,10 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, + status = nfserr_clid_inuse; + if (client_has_state(old) + && !same_creds(&unconf->cl_cred, +- &old->cl_cred)) ++ &old->cl_cred)) { ++ old = NULL; + goto out; ++ } + status = mark_client_expired_locked(old); + if (status) { + old = NULL; +@@ -4598,7 +4605,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) + * queued for a lease break. Don't queue it again. + */ + spin_lock(&state_lock); +- if (dp->dl_time == 0) { ++ if (delegation_hashed(dp) && dp->dl_time == 0) { + dp->dl_time = ktime_get_boottime_seconds(); + list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru); + } +@@ -6035,7 +6042,11 @@ nfs4_preprocess_stateid_op(struct svc_rqst *rqstp, + *nfp = NULL; + + if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { +- status = check_special_stateids(net, fhp, stateid, flags); ++ if (cstid) ++ status = nfserr_bad_stateid; ++ else ++ status = check_special_stateids(net, fhp, stateid, ++ flags); + goto done; + } + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index cf030ebe28275..f6d385e0efece 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -288,11 +288,8 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen) + p = xdr_inline_decode(argp->xdr, count << 2); + if (!p) + return nfserr_bad_xdr; +- i = 0; +- while (i < count) +- bmval[i++] = be32_to_cpup(p++); +- while (i < bmlen) +- bmval[i++] = 0; ++ for (i = 0; i < bmlen; i++) ++ bmval[i] = (i < count) ? be32_to_cpup(p++) : 0; + + return nfs_ok; + } +@@ -4000,10 +3997,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, + } + xdr_commit_encode(xdr); + +- maxcount = svc_max_payload(resp->rqstp); +- maxcount = min_t(unsigned long, maxcount, ++ maxcount = min_t(unsigned long, read->rd_length, + (xdr->buf->buflen - xdr->buf->len)); +- maxcount = min_t(unsigned long, maxcount, read->rd_length); + + if (file->f_op->splice_read && + test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) +@@ -4840,10 +4835,8 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, + return nfserr_resource; + xdr_commit_encode(xdr); + +- maxcount = svc_max_payload(resp->rqstp); +- maxcount = min_t(unsigned long, maxcount, ++ maxcount = min_t(unsigned long, read->rd_length, + (xdr->buf->buflen - xdr->buf->len)); +- maxcount = min_t(unsigned long, maxcount, read->rd_length); + count = maxcount; + + eof = read->rd_offset >= i_size_read(file_inode(file)); +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index 070e5dd03e26f..cb73c12925629 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -1249,7 +1249,8 @@ static void nfsdfs_remove_file(struct inode *dir, struct dentry *dentry) + clear_ncl(d_inode(dentry)); + dget(dentry); + ret = simple_unlink(dir, dentry); +- d_delete(dentry); ++ d_drop(dentry); ++ fsnotify_unlink(dir, dentry); + dput(dentry); + WARN_ON_ONCE(ret); + } +@@ -1340,8 +1341,8 @@ void nfsd_client_rmdir(struct dentry *dentry) + dget(dentry); + ret = simple_rmdir(dir, dentry); + WARN_ON_ONCE(ret); ++ d_drop(dentry); + fsnotify_rmdir(dir, dentry); +- d_delete(dentry); + dput(dentry); + inode_unlock(dir); + } +@@ -1521,12 +1522,9 @@ static int __init init_nfsd(void) + int retval; + printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); + +- retval = register_cld_notifier(); +- if (retval) +- return retval; + retval = nfsd4_init_slabs(); + if (retval) +- goto out_unregister_notifier; ++ return retval; + retval = nfsd4_init_pnfs(); + if (retval) + goto out_free_slabs; +@@ -1545,9 +1543,14 @@ static int __init init_nfsd(void) + goto out_free_exports; + retval = register_pernet_subsys(&nfsd_net_ops); + if (retval < 0) ++ goto out_free_filesystem; ++ retval = register_cld_notifier(); ++ if (retval) + goto out_free_all; + return 0; + out_free_all: ++ unregister_pernet_subsys(&nfsd_net_ops); ++out_free_filesystem: + unregister_filesystem(&nfsd_fs_type); + out_free_exports: + remove_proc_entry("fs/nfs/exports", NULL); +@@ -1561,13 +1564,12 @@ out_free_pnfs: + nfsd4_exit_pnfs(); + out_free_slabs: + nfsd4_free_slabs(); +-out_unregister_notifier: +- unregister_cld_notifier(); + return retval; + } + + static void __exit exit_nfsd(void) + { ++ unregister_cld_notifier(); + unregister_pernet_subsys(&nfsd_net_ops); + nfsd_drc_slab_free(); + remove_proc_entry("fs/nfs/exports", NULL); +@@ -1577,7 +1579,6 @@ static void __exit exit_nfsd(void) + nfsd4_free_slabs(); + nfsd4_exit_pnfs(); + unregister_filesystem(&nfsd_fs_type); +- unregister_cld_notifier(); + } + + MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); +diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c +index 90fcd6178823b..312fd289be583 100644 +--- a/fs/nfsd/nfsproc.c ++++ b/fs/nfsd/nfsproc.c +@@ -234,12 +234,7 @@ nfsd_proc_write(struct svc_rqst *rqstp) + SVCFH_fmt(&argp->fh), + argp->len, argp->offset); + +- nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages, +- &argp->first, cnt); +- if (!nvecs) { +- resp->status = nfserr_io; +- goto out; +- } ++ nvecs = svc_fill_write_vector(rqstp, &argp->payload); + + resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), + argp->offset, rqstp->rq_vec, nvecs, +@@ -248,7 +243,6 @@ nfsd_proc_write(struct svc_rqst *rqstp) + resp->status = fh_getattr(&resp->fh, &resp->stat); + else if (resp->status == nfserr_jukebox) + return rpc_drop_reply; +-out: + return rpc_success; + } + +@@ -557,17 +551,17 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp) + + static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp, + struct nfsd_readdirres *resp, +- int count) ++ u32 count) + { + struct xdr_buf *buf = &resp->dirlist; + struct xdr_stream *xdr = &resp->xdr; + +- count = min_t(u32, count, PAGE_SIZE); ++ count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); + + memset(buf, 0, sizeof(*buf)); + + /* Reserve room for the NULL ptr & eof flag (-2 words) */ +- buf->buflen = count - sizeof(__be32) * 2; ++ buf->buflen = count - XDR_UNIT * 2; + buf->pages = rqstp->rq_next_page; + rqstp->rq_next_page++; + +@@ -578,7 +572,7 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp, + xdr->page_ptr = buf->pages; + xdr->iov = NULL; + xdr->p = page_address(*buf->pages); +- xdr->end = xdr->p + (PAGE_SIZE >> 2); ++ xdr->end = (void *)xdr->p + min_t(u32, buf->buflen, PAGE_SIZE); + xdr->rqst = NULL; + } + +diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c +index a06c05fe3b421..26a42f87c2409 100644 +--- a/fs/nfsd/nfsxdr.c ++++ b/fs/nfsd/nfsxdr.c +@@ -325,10 +325,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) + { + struct xdr_stream *xdr = &rqstp->rq_arg_stream; + struct nfsd_writeargs *args = rqstp->rq_argp; +- struct kvec *head = rqstp->rq_arg.head; +- struct kvec *tail = rqstp->rq_arg.tail; + u32 beginoffset, totalcount; +- size_t remaining; + + if (!svcxdr_decode_fhandle(xdr, &args->fh)) + return 0; +@@ -346,12 +343,8 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) + return 0; + if (args->len > NFSSVC_MAXBLKSIZE_V2) + return 0; +- remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; +- remaining -= xdr_stream_pos(xdr); +- if (remaining < xdr_align_size(args->len)) ++ if (!xdr_stream_subsegment(xdr, &args->payload, args->len)) + return 0; +- args->first.iov_base = xdr->p; +- args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); + + return 1; + } +diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h +index 538520957a815..b302836c7fdf9 100644 +--- a/fs/nfsd/trace.h ++++ b/fs/nfsd/trace.h +@@ -319,14 +319,14 @@ TRACE_EVENT(nfsd_export_update, + DECLARE_EVENT_CLASS(nfsd_io_class, + TP_PROTO(struct svc_rqst *rqstp, + struct svc_fh *fhp, +- loff_t offset, +- unsigned long len), ++ u64 offset, ++ u32 len), + TP_ARGS(rqstp, fhp, offset, len), + TP_STRUCT__entry( + __field(u32, xid) + __field(u32, fh_hash) +- __field(loff_t, offset) +- __field(unsigned long, len) ++ __field(u64, offset) ++ __field(u32, len) + ), + TP_fast_assign( + __entry->xid = be32_to_cpu(rqstp->rq_xid); +@@ -334,7 +334,7 @@ DECLARE_EVENT_CLASS(nfsd_io_class, + __entry->offset = offset; + __entry->len = len; + ), +- TP_printk("xid=0x%08x fh_hash=0x%08x offset=%lld len=%lu", ++ TP_printk("xid=0x%08x fh_hash=0x%08x offset=%llu len=%u", + __entry->xid, __entry->fh_hash, + __entry->offset, __entry->len) + ) +@@ -343,8 +343,8 @@ DECLARE_EVENT_CLASS(nfsd_io_class, + DEFINE_EVENT(nfsd_io_class, nfsd_##name, \ + TP_PROTO(struct svc_rqst *rqstp, \ + struct svc_fh *fhp, \ +- loff_t offset, \ +- unsigned long len), \ ++ u64 offset, \ ++ u32 len), \ + TP_ARGS(rqstp, fhp, offset, len)) + + DEFINE_NFSD_IO_EVENT(read_start); +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index 738d564ca4ce3..271f7c15d6e52 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -433,6 +433,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, + .ia_size = iap->ia_size, + }; + ++ host_err = -EFBIG; ++ if (iap->ia_size < 0) ++ goto out_unlock; ++ + host_err = notify_change(&init_user_ns, dentry, &size_attr, NULL); + if (host_err) + goto out_unlock; +@@ -989,6 +993,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, + iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt); + if (flags & RWF_SYNC) { + down_write(&nf->nf_rwsem); ++ if (verf) ++ nfsd_copy_boot_verifier(verf, ++ net_generic(SVC_NET(rqstp), ++ nfsd_net_id)); + host_err = vfs_iter_write(file, &iter, &pos, flags); + if (host_err < 0) + nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp), +diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h +index f45b4bc93f527..80fd6d7f3404a 100644 +--- a/fs/nfsd/xdr.h ++++ b/fs/nfsd/xdr.h +@@ -33,7 +33,7 @@ struct nfsd_writeargs { + svc_fh fh; + __u32 offset; + int len; +- struct kvec first; ++ struct xdr_buf payload; + }; + + struct nfsd_createargs { +diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h +index 933008382bbeb..712c117300cb7 100644 +--- a/fs/nfsd/xdr3.h ++++ b/fs/nfsd/xdr3.h +@@ -40,7 +40,7 @@ struct nfsd3_writeargs { + __u32 count; + int stable; + __u32 len; +- struct kvec first; ++ struct xdr_buf payload; + }; + + struct nfsd3_createargs { +diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c +index 6facdf476255d..84ec851211d91 100644 +--- a/fs/notify/fanotify/fanotify_user.c ++++ b/fs/notify/fanotify/fanotify_user.c +@@ -611,9 +611,6 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, + if (fanotify_is_perm_event(event->mask)) + FANOTIFY_PERM(event)->fd = fd; + +- if (f) +- fd_install(fd, f); +- + if (info_mode) { + ret = copy_info_records_to_user(event, info, info_mode, pidfd, + buf, count); +@@ -621,6 +618,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, + goto out_close_fd; + } + ++ if (f) ++ fd_install(fd, f); ++ + return metadata.event_len; + + out_close_fd: +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 54d7843c02114..fc5f780fa2355 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -476,10 +476,11 @@ int ocfs2_truncate_file(struct inode *inode, + * greater than page size, so we have to truncate them + * anyway. + */ +- unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); +- truncate_inode_pages(inode->i_mapping, new_i_size); + + if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { ++ unmap_mapping_range(inode->i_mapping, ++ new_i_size + PAGE_SIZE - 1, 0, 1); ++ truncate_inode_pages(inode->i_mapping, new_i_size); + status = ocfs2_truncate_inline(inode, di_bh, new_i_size, + i_size_read(inode), 1); + if (status) +@@ -498,6 +499,9 @@ int ocfs2_truncate_file(struct inode *inode, + goto bail_unlock_sem; + } + ++ unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); ++ truncate_inode_pages(inode->i_mapping, new_i_size); ++ + status = ocfs2_commit_truncate(osb, inode, di_bh); + if (status < 0) { + mlog_errno(status); +diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c +index 481017e1dac5a..166c8918c825a 100644 +--- a/fs/ocfs2/suballoc.c ++++ b/fs/ocfs2/suballoc.c +@@ -1251,26 +1251,23 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, + { + struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; + struct journal_head *jh; +- int ret = 1; ++ int ret; + + if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap)) + return 0; + +- if (!buffer_jbd(bg_bh)) ++ jh = jbd2_journal_grab_journal_head(bg_bh); ++ if (!jh) + return 1; + +- jbd_lock_bh_journal_head(bg_bh); +- if (buffer_jbd(bg_bh)) { +- jh = bh2jh(bg_bh); +- spin_lock(&jh->b_state_lock); +- bg = (struct ocfs2_group_desc *) jh->b_committed_data; +- if (bg) +- ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); +- else +- ret = 1; +- spin_unlock(&jh->b_state_lock); +- } +- jbd_unlock_bh_journal_head(bg_bh); ++ spin_lock(&jh->b_state_lock); ++ bg = (struct ocfs2_group_desc *) jh->b_committed_data; ++ if (bg) ++ ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); ++ else ++ ret = 1; ++ spin_unlock(&jh->b_state_lock); ++ jbd2_journal_put_journal_head(jh); + + return ret; + } +diff --git a/fs/open.c b/fs/open.c +index daa324606a41f..e0df1536eb69f 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -856,8 +856,20 @@ static int do_dentry_open(struct file *f, + * of THPs into the page cache will fail. + */ + smp_mb(); +- if (filemap_nr_thps(inode->i_mapping)) +- truncate_pagecache(inode, 0); ++ if (filemap_nr_thps(inode->i_mapping)) { ++ struct address_space *mapping = inode->i_mapping; ++ ++ filemap_invalidate_lock(inode->i_mapping); ++ /* ++ * unmap_mapping_range just need to be called once ++ * here, because the private pages is not need to be ++ * unmapped mapping (e.g. data segment of dynamic ++ * shared libraries here). ++ */ ++ unmap_mapping_range(mapping, 0, 0, 0); ++ truncate_inode_pages(mapping, 0); ++ filemap_invalidate_unlock(inode->i_mapping); ++ } + } + + return 0; +diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c +index fe484cf93e5cd..8bbe9486e3a62 100644 +--- a/fs/orangefs/dcache.c ++++ b/fs/orangefs/dcache.c +@@ -26,8 +26,10 @@ static int orangefs_revalidate_lookup(struct dentry *dentry) + gossip_debug(GOSSIP_DCACHE_DEBUG, "%s: attempting lookup.\n", __func__); + + new_op = op_alloc(ORANGEFS_VFS_OP_LOOKUP); +- if (!new_op) ++ if (!new_op) { ++ ret = -ENOMEM; + goto out_put_parent; ++ } + + new_op->upcall.req.lookup.sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW; + new_op->upcall.req.lookup.parent_refn = parent->refn; +diff --git a/fs/orangefs/orangefs-bufmap.c b/fs/orangefs/orangefs-bufmap.c +index 538e839590ef5..b501dc07f9222 100644 +--- a/fs/orangefs/orangefs-bufmap.c ++++ b/fs/orangefs/orangefs-bufmap.c +@@ -176,7 +176,7 @@ orangefs_bufmap_free(struct orangefs_bufmap *bufmap) + { + kfree(bufmap->page_array); + kfree(bufmap->desc_array); +- kfree(bufmap->buffer_index_array); ++ bitmap_free(bufmap->buffer_index_array); + kfree(bufmap); + } + +@@ -226,8 +226,7 @@ orangefs_bufmap_alloc(struct ORANGEFS_dev_map_desc *user_desc) + bufmap->desc_size = user_desc->size; + bufmap->desc_shift = ilog2(bufmap->desc_size); + +- bufmap->buffer_index_array = +- kzalloc(DIV_ROUND_UP(bufmap->desc_count, BITS_PER_LONG), GFP_KERNEL); ++ bufmap->buffer_index_array = bitmap_zalloc(bufmap->desc_count, GFP_KERNEL); + if (!bufmap->buffer_index_array) + goto out_free_bufmap; + +@@ -250,7 +249,7 @@ orangefs_bufmap_alloc(struct ORANGEFS_dev_map_desc *user_desc) + out_free_desc_array: + kfree(bufmap->desc_array); + out_free_index_array: +- kfree(bufmap->buffer_index_array); ++ bitmap_free(bufmap->buffer_index_array); + out_free_bufmap: + kfree(bufmap); + out: +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index 4e7d5bfa2949f..e040970408d4f 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -140,12 +140,14 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old, + int err; + + err = ovl_real_fileattr_get(old, &oldfa); +- if (err) +- return err; +- +- err = ovl_real_fileattr_get(new, &newfa); +- if (err) ++ if (err) { ++ /* Ntfs-3g returns -EINVAL for "no fileattr support" */ ++ if (err == -ENOTTY || err == -EINVAL) ++ return 0; ++ pr_warn("failed to retrieve lower fileattr (%pd2, err=%i)\n", ++ old->dentry, err); + return err; ++ } + + /* + * We cannot set immutable and append-only flags on upper inode, +@@ -155,10 +157,31 @@ static int ovl_copy_fileattr(struct inode *inode, struct path *old, + */ + if (oldfa.flags & OVL_PROT_FS_FLAGS_MASK) { + err = ovl_set_protattr(inode, new->dentry, &oldfa); +- if (err) ++ if (err == -EPERM) ++ pr_warn_once("copying fileattr: no xattr on upper\n"); ++ else if (err) + return err; + } + ++ /* Don't bother copying flags if none are set */ ++ if (!(oldfa.flags & OVL_COPY_FS_FLAGS_MASK)) ++ return 0; ++ ++ err = ovl_real_fileattr_get(new, &newfa); ++ if (err) { ++ /* ++ * Returning an error if upper doesn't support fileattr will ++ * result in a regression, so revert to the old behavior. ++ */ ++ if (err == -ENOTTY || err == -EINVAL) { ++ pr_warn_once("copying fileattr: no support on upper\n"); ++ return 0; ++ } ++ pr_warn("failed to retrieve upper fileattr (%pd2, err=%i)\n", ++ new->dentry, err); ++ return err; ++ } ++ + BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL); + newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK; + newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK); +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 93c7c267de934..f18490813170a 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -137,8 +137,7 @@ kill_whiteout: + goto out; + } + +-static int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, +- umode_t mode) ++int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) + { + int err; + struct dentry *d, *dentry = *newdentry; +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index c88ac571593dc..44fea16751f1d 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -17,6 +17,7 @@ + + struct ovl_aio_req { + struct kiocb iocb; ++ refcount_t ref; + struct kiocb *orig_iocb; + struct fd fd; + }; +@@ -252,6 +253,14 @@ static rwf_t ovl_iocb_to_rwf(int ifl) + return flags; + } + ++static inline void ovl_aio_put(struct ovl_aio_req *aio_req) ++{ ++ if (refcount_dec_and_test(&aio_req->ref)) { ++ fdput(aio_req->fd); ++ kmem_cache_free(ovl_aio_request_cachep, aio_req); ++ } ++} ++ + static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + { + struct kiocb *iocb = &aio_req->iocb; +@@ -268,8 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + } + + orig_iocb->ki_pos = iocb->ki_pos; +- fdput(aio_req->fd); +- kmem_cache_free(ovl_aio_request_cachep, aio_req); ++ ovl_aio_put(aio_req); + } + + static void ovl_aio_rw_complete(struct kiocb *iocb, long res, long res2) +@@ -319,7 +327,9 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) + aio_req->orig_iocb = iocb; + kiocb_clone(&aio_req->iocb, iocb, real.file); + aio_req->iocb.ki_complete = ovl_aio_rw_complete; ++ refcount_set(&aio_req->ref, 2); + ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter); ++ ovl_aio_put(aio_req); + if (ret != -EIOCBQUEUED) + ovl_aio_cleanup_handler(aio_req); + } +@@ -390,7 +400,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) + kiocb_clone(&aio_req->iocb, iocb, real.file); + aio_req->iocb.ki_flags = ifl; + aio_req->iocb.ki_complete = ovl_aio_rw_complete; ++ refcount_set(&aio_req->ref, 2); + ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter); ++ ovl_aio_put(aio_req); + if (ret != -EIOCBQUEUED) + ovl_aio_cleanup_handler(aio_req); + } +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index 832b17589733a..1f36158c7dbe2 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -610,7 +610,10 @@ int ovl_real_fileattr_get(struct path *realpath, struct fileattr *fa) + if (err) + return err; + +- return vfs_fileattr_get(realpath->dentry, fa); ++ err = vfs_fileattr_get(realpath->dentry, fa); ++ if (err == -ENOIOCTLCMD) ++ err = -ENOTTY; ++ return err; + } + + int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa) +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index 3894f33479552..2cd5741c873b6 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -570,6 +570,7 @@ struct ovl_cattr { + + #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) }) + ++int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode); + struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, + struct ovl_cattr *attr); + int ovl_cleanup(struct inode *dir, struct dentry *dentry); +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 178daa5e82c9d..265181c110ae2 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -787,10 +787,14 @@ retry: + goto retry; + } + +- work = ovl_create_real(dir, work, OVL_CATTR(attr.ia_mode)); +- err = PTR_ERR(work); +- if (IS_ERR(work)) +- goto out_err; ++ err = ovl_mkdir_real(dir, &work, attr.ia_mode); ++ if (err) ++ goto out_dput; ++ ++ /* Weird filesystem returning with hashed negative (kernfs)? */ ++ err = -EINVAL; ++ if (d_really_is_negative(work)) ++ goto out_dput; + + /* + * Try to remove POSIX ACL xattrs from workdir. We are good if: +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 533d5836eb9a4..1f394095eb880 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -67,6 +67,7 @@ + #include <linux/mm.h> + #include <linux/swap.h> + #include <linux/rcupdate.h> ++#include <linux/kallsyms.h> + #include <linux/stacktrace.h> + #include <linux/resource.h> + #include <linux/module.h> +@@ -386,17 +387,19 @@ static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) + { + unsigned long wchan; ++ char symname[KSYM_NAME_LEN]; + +- if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) +- wchan = get_wchan(task); +- else +- wchan = 0; ++ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) ++ goto print0; + +- if (wchan) +- seq_printf(m, "%ps", (void *) wchan); +- else +- seq_putc(m, '0'); ++ wchan = get_wchan(task); ++ if (wchan && !lookup_symbol_name(wchan, symname)) { ++ seq_puts(m, symname); ++ return 0; ++ } + ++print0: ++ seq_putc(m, '0'); + return 0; + } + #endif /* CONFIG_KALLSYMS */ +diff --git a/fs/proc/stat.c b/fs/proc/stat.c +index 6561a06ef9059..4fb8729a68d4e 100644 +--- a/fs/proc/stat.c ++++ b/fs/proc/stat.c +@@ -24,7 +24,7 @@ + + #ifdef arch_idle_time + +-static u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) ++u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) + { + u64 idle; + +@@ -46,7 +46,7 @@ static u64 get_iowait_time(struct kernel_cpustat *kcs, int cpu) + + #else + +-static u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) ++u64 get_idle_time(struct kernel_cpustat *kcs, int cpu) + { + u64 idle, idle_usecs = -1ULL; + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index cf25be3e03212..79ca4d69dfd6b 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -430,7 +430,8 @@ static void smaps_page_accumulate(struct mem_size_stats *mss, + } + + static void smaps_account(struct mem_size_stats *mss, struct page *page, +- bool compound, bool young, bool dirty, bool locked) ++ bool compound, bool young, bool dirty, bool locked, ++ bool migration) + { + int i, nr = compound ? compound_nr(page) : 1; + unsigned long size = nr * PAGE_SIZE; +@@ -457,8 +458,15 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page, + * page_count(page) == 1 guarantees the page is mapped exactly once. + * If any subpage of the compound page mapped with PTE it would elevate + * page_count(). ++ * ++ * The page_mapcount() is called to get a snapshot of the mapcount. ++ * Without holding the page lock this snapshot can be slightly wrong as ++ * we cannot always read the mapcount atomically. It is not safe to ++ * call page_mapcount() even with PTL held if the page is not mapped, ++ * especially for migration entries. Treat regular migration entries ++ * as mapcount == 1. + */ +- if (page_count(page) == 1) { ++ if ((page_count(page) == 1) || migration) { + smaps_page_accumulate(mss, page, size, size << PSS_SHIFT, dirty, + locked, true); + return; +@@ -495,6 +503,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, + struct vm_area_struct *vma = walk->vma; + bool locked = !!(vma->vm_flags & VM_LOCKED); + struct page *page = NULL; ++ bool migration = false; + + if (pte_present(*pte)) { + page = vm_normal_page(vma, addr, *pte); +@@ -514,8 +523,11 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, + } else { + mss->swap_pss += (u64)PAGE_SIZE << PSS_SHIFT; + } +- } else if (is_pfn_swap_entry(swpent)) ++ } else if (is_pfn_swap_entry(swpent)) { ++ if (is_migration_entry(swpent)) ++ migration = true; + page = pfn_swap_entry_to_page(swpent); ++ } + } else if (unlikely(IS_ENABLED(CONFIG_SHMEM) && mss->check_shmem_swap + && pte_none(*pte))) { + page = xa_load(&vma->vm_file->f_mapping->i_pages, +@@ -528,7 +540,8 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, + if (!page) + return; + +- smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked); ++ smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), ++ locked, migration); + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +@@ -539,6 +552,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, + struct vm_area_struct *vma = walk->vma; + bool locked = !!(vma->vm_flags & VM_LOCKED); + struct page *page = NULL; ++ bool migration = false; + + if (pmd_present(*pmd)) { + /* FOLL_DUMP will return -EFAULT on huge zero page */ +@@ -546,8 +560,10 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, + } else if (unlikely(thp_migration_supported() && is_swap_pmd(*pmd))) { + swp_entry_t entry = pmd_to_swp_entry(*pmd); + +- if (is_migration_entry(entry)) ++ if (is_migration_entry(entry)) { ++ migration = true; + page = pfn_swap_entry_to_page(entry); ++ } + } + if (IS_ERR_OR_NULL(page)) + return; +@@ -559,7 +575,9 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, + /* pass */; + else + mss->file_thp += HPAGE_PMD_SIZE; +- smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked); ++ ++ smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), ++ locked, migration); + } + #else + static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, +@@ -1363,6 +1381,7 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm, + { + u64 frame = 0, flags = 0; + struct page *page = NULL; ++ bool migration = false; + + if (pte_present(pte)) { + if (pm->show_pfn) +@@ -1384,13 +1403,14 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm, + frame = swp_type(entry) | + (swp_offset(entry) << MAX_SWAPFILES_SHIFT); + flags |= PM_SWAP; ++ migration = is_migration_entry(entry); + if (is_pfn_swap_entry(entry)) + page = pfn_swap_entry_to_page(entry); + } + + if (page && !PageAnon(page)) + flags |= PM_FILE; +- if (page && page_mapcount(page) == 1) ++ if (page && !migration && page_mapcount(page) == 1) + flags |= PM_MMAP_EXCLUSIVE; + if (vma->vm_flags & VM_SOFTDIRTY) + flags |= PM_SOFT_DIRTY; +@@ -1406,8 +1426,9 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, + spinlock_t *ptl; + pte_t *pte, *orig_pte; + int err = 0; +- + #ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ bool migration = false; ++ + ptl = pmd_trans_huge_lock(pmdp, vma); + if (ptl) { + u64 flags = 0, frame = 0; +@@ -1446,11 +1467,12 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, + if (pmd_swp_uffd_wp(pmd)) + flags |= PM_UFFD_WP; + VM_BUG_ON(!is_pmd_migration_entry(pmd)); ++ migration = is_migration_entry(entry); + page = pfn_swap_entry_to_page(entry); + } + #endif + +- if (page && page_mapcount(page) == 1) ++ if (page && !migration && page_mapcount(page) == 1) + flags |= PM_MMAP_EXCLUSIVE; + + for (; addr != end; addr += PAGE_SIZE) { +@@ -1560,7 +1582,8 @@ static const struct mm_walk_ops pagemap_ops = { + * Bits 5-54 swap offset if swapped + * Bit 55 pte is soft-dirty (see Documentation/admin-guide/mm/soft-dirty.rst) + * Bit 56 page exclusively mapped +- * Bits 57-60 zero ++ * Bit 57 pte is uffd-wp write-protected ++ * Bits 58-60 zero + * Bit 61 page is file-page or shared-anon + * Bit 62 page swapped + * Bit 63 page present +diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c +index 5a1b228964fb7..deb99bc9b7e6b 100644 +--- a/fs/proc/uptime.c ++++ b/fs/proc/uptime.c +@@ -12,18 +12,22 @@ static int uptime_proc_show(struct seq_file *m, void *v) + { + struct timespec64 uptime; + struct timespec64 idle; +- u64 nsec; ++ u64 idle_nsec; + u32 rem; + int i; + +- nsec = 0; +- for_each_possible_cpu(i) +- nsec += (__force u64) kcpustat_cpu(i).cpustat[CPUTIME_IDLE]; ++ idle_nsec = 0; ++ for_each_possible_cpu(i) { ++ struct kernel_cpustat kcs; ++ ++ kcpustat_cpu_fetch(&kcs, i); ++ idle_nsec += get_idle_time(&kcs, i); ++ } + + ktime_get_boottime_ts64(&uptime); + timens_add_boottime(&uptime); + +- idle.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem); ++ idle.tv_sec = div_u64_rem(idle_nsec, NSEC_PER_SEC, &rem); + idle.tv_nsec = rem; + seq_printf(m, "%lu.%02lu %lu.%02lu\n", + (unsigned long) uptime.tv_sec, +diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c +index 9a15334da2086..e5730986758fa 100644 +--- a/fs/proc/vmcore.c ++++ b/fs/proc/vmcore.c +@@ -124,9 +124,13 @@ ssize_t read_from_oldmem(char *buf, size_t count, + nr_bytes = count; + + /* If pfn is not ram, return zeros for sparse dump files */ +- if (pfn_is_ram(pfn) == 0) +- memset(buf, 0, nr_bytes); +- else { ++ if (pfn_is_ram(pfn) == 0) { ++ tmp = 0; ++ if (!userbuf) ++ memset(buf, 0, nr_bytes); ++ else if (clear_user(buf, nr_bytes)) ++ tmp = -EFAULT; ++ } else { + if (encrypted) + tmp = copy_oldmem_page_encrypted(pfn, buf, + nr_bytes, +@@ -135,10 +139,10 @@ ssize_t read_from_oldmem(char *buf, size_t count, + else + tmp = copy_oldmem_page(pfn, buf, nr_bytes, + offset, userbuf); +- +- if (tmp < 0) +- return tmp; + } ++ if (tmp < 0) ++ return tmp; ++ + *ppos += nr_bytes; + count -= nr_bytes; + buf += nr_bytes; +diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig +index 328da35da3908..8adabde685f13 100644 +--- a/fs/pstore/Kconfig ++++ b/fs/pstore/Kconfig +@@ -173,7 +173,6 @@ config PSTORE_BLK + tristate "Log panic/oops to a block device" + depends on PSTORE + depends on BLOCK +- depends on BROKEN + select PSTORE_ZONE + default n + help +diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c +index 04ce58c939a0b..6093088de49fd 100644 +--- a/fs/pstore/blk.c ++++ b/fs/pstore/blk.c +@@ -311,7 +311,7 @@ static int __init __best_effort_init(void) + if (ret) + kfree(best_effort_dev); + else +- pr_info("attached %s (%zu) (no dedicated panic_write!)\n", ++ pr_info("attached %s (%lu) (no dedicated panic_write!)\n", + blkdev, best_effort_dev->zone.total_size); + + return ret; +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index 22d904bde6ab9..a74aef99bd3d6 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -690,9 +690,14 @@ int dquot_quota_sync(struct super_block *sb, int type) + /* This is not very clever (and fast) but currently I don't know about + * any other simple way of getting quota data to disk and we must get + * them there for userspace to be visible... */ +- if (sb->s_op->sync_fs) +- sb->s_op->sync_fs(sb, 1); +- sync_blockdev(sb->s_bdev); ++ if (sb->s_op->sync_fs) { ++ ret = sb->s_op->sync_fs(sb, 1); ++ if (ret) ++ return ret; ++ } ++ ret = sync_blockdev(sb->s_bdev); ++ if (ret) ++ return ret; + + /* + * Now when everything is written we can discard the pagecache so +diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c +index d3e995e1046fb..5f2405994280a 100644 +--- a/fs/quota/quota_tree.c ++++ b/fs/quota/quota_tree.c +@@ -414,6 +414,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, + quota_error(dquot->dq_sb, "Quota structure has offset to " + "other block (%u) than it should (%u)", blk, + (uint)(dquot->dq_off >> info->dqi_blocksize_bits)); ++ ret = -EIO; + goto out_buf; + } + ret = read_blk(info, blk, buf); +@@ -479,6 +480,13 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, + goto out_buf; + } + newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); ++ if (newblk < QT_TREEOFF || newblk >= info->dqi_blocks) { ++ quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)", ++ newblk, info->dqi_blocks); ++ ret = -EUCLEAN; ++ goto out_buf; ++ } ++ + if (depth == info->dqi_qtree_depth - 1) { + ret = free_dqentry(info, dquot, newblk); + newblk = 0; +@@ -578,6 +586,13 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, + blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); + if (!blk) /* No reference? */ + goto out_buf; ++ if (blk < QT_TREEOFF || blk >= info->dqi_blocks) { ++ quota_error(dquot->dq_sb, "Getting block too big (%u >= %u)", ++ blk, info->dqi_blocks); ++ ret = -EUCLEAN; ++ goto out_buf; ++ } ++ + if (depth < info->dqi_qtree_depth - 1) + ret = find_tree_dqentry(info, dquot, blk, depth+1); + else +diff --git a/fs/select.c b/fs/select.c +index 945896d0ac9e7..5edffee1162c2 100644 +--- a/fs/select.c ++++ b/fs/select.c +@@ -458,9 +458,11 @@ get_max: + return max; + } + +-#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR) +-#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR) +-#define POLLEX_SET (EPOLLPRI) ++#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR |\ ++ EPOLLNVAL) ++#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR |\ ++ EPOLLNVAL) ++#define POLLEX_SET (EPOLLPRI | EPOLLNVAL) + + static inline void wait_key_set(poll_table *wait, unsigned long in, + unsigned long out, unsigned long bit, +@@ -527,6 +529,7 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) + break; + if (!(bit & all_bits)) + continue; ++ mask = EPOLLNVAL; + f = fdget(i); + if (f.file) { + wait_key_set(wait, in, out, bit, +@@ -534,34 +537,34 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time) + mask = vfs_poll(f.file, wait); + + fdput(f); +- if ((mask & POLLIN_SET) && (in & bit)) { +- res_in |= bit; +- retval++; +- wait->_qproc = NULL; +- } +- if ((mask & POLLOUT_SET) && (out & bit)) { +- res_out |= bit; +- retval++; +- wait->_qproc = NULL; +- } +- if ((mask & POLLEX_SET) && (ex & bit)) { +- res_ex |= bit; +- retval++; +- wait->_qproc = NULL; +- } +- /* got something, stop busy polling */ +- if (retval) { +- can_busy_loop = false; +- busy_flag = 0; +- +- /* +- * only remember a returned +- * POLL_BUSY_LOOP if we asked for it +- */ +- } else if (busy_flag & mask) +- can_busy_loop = true; +- + } ++ if ((mask & POLLIN_SET) && (in & bit)) { ++ res_in |= bit; ++ retval++; ++ wait->_qproc = NULL; ++ } ++ if ((mask & POLLOUT_SET) && (out & bit)) { ++ res_out |= bit; ++ retval++; ++ wait->_qproc = NULL; ++ } ++ if ((mask & POLLEX_SET) && (ex & bit)) { ++ res_ex |= bit; ++ retval++; ++ wait->_qproc = NULL; ++ } ++ /* got something, stop busy polling */ ++ if (retval) { ++ can_busy_loop = false; ++ busy_flag = 0; ++ ++ /* ++ * only remember a returned ++ * POLL_BUSY_LOOP if we asked for it ++ */ ++ } else if (busy_flag & mask) ++ can_busy_loop = true; ++ + } + if (res_in) + *rinp = res_in; +diff --git a/fs/signalfd.c b/fs/signalfd.c +index 040e1cf905282..65ce0e72e7b95 100644 +--- a/fs/signalfd.c ++++ b/fs/signalfd.c +@@ -35,17 +35,7 @@ + + void signalfd_cleanup(struct sighand_struct *sighand) + { +- wait_queue_head_t *wqh = &sighand->signalfd_wqh; +- /* +- * The lockless check can race with remove_wait_queue() in progress, +- * but in this case its caller should run under rcu_read_lock() and +- * sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return. +- */ +- if (likely(!waitqueue_active(wqh))) +- return; +- +- /* wait_queue_entry_t->func(POLLFREE) should do remove_wait_queue() */ +- wake_up_poll(wqh, EPOLLHUP | POLLFREE); ++ wake_up_pollfree(&sighand->signalfd_wqh); + } + + struct signalfd_ctx { +diff --git a/fs/smbfs_common/cifs_arc4.c b/fs/smbfs_common/cifs_arc4.c +index 85ba15a60b13b..043e4cb839fa2 100644 +--- a/fs/smbfs_common/cifs_arc4.c ++++ b/fs/smbfs_common/cifs_arc4.c +@@ -72,16 +72,3 @@ void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int l + ctx->y = y; + } + EXPORT_SYMBOL_GPL(cifs_arc4_crypt); +- +-static int __init +-init_smbfs_common(void) +-{ +- return 0; +-} +-static void __init +-exit_smbfs_common(void) +-{ +-} +- +-module_init(init_smbfs_common) +-module_exit(exit_smbfs_common) +diff --git a/fs/super.c b/fs/super.c +index bcef3a6f4c4b5..87379bb1f7a30 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -1421,8 +1421,8 @@ struct dentry *mount_nodev(struct file_system_type *fs_type, + } + EXPORT_SYMBOL(mount_nodev); + +-static int reconfigure_single(struct super_block *s, +- int flags, void *data) ++int reconfigure_single(struct super_block *s, ++ int flags, void *data) + { + struct fs_context *fc; + int ret; +@@ -1616,11 +1616,9 @@ static void lockdep_sb_freeze_acquire(struct super_block *sb) + percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_); + } + +-static void sb_freeze_unlock(struct super_block *sb) ++static void sb_freeze_unlock(struct super_block *sb, int level) + { +- int level; +- +- for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--) ++ for (level--; level >= 0; level--) + percpu_up_write(sb->s_writers.rw_sem + level); + } + +@@ -1691,7 +1689,14 @@ int freeze_super(struct super_block *sb) + sb_wait_write(sb, SB_FREEZE_PAGEFAULT); + + /* All writers are done so after syncing there won't be dirty data */ +- sync_filesystem(sb); ++ ret = sync_filesystem(sb); ++ if (ret) { ++ sb->s_writers.frozen = SB_UNFROZEN; ++ sb_freeze_unlock(sb, SB_FREEZE_PAGEFAULT); ++ wake_up(&sb->s_writers.wait_unfrozen); ++ deactivate_locked_super(sb); ++ return ret; ++ } + + /* Now wait for internal filesystem counter */ + sb->s_writers.frozen = SB_FREEZE_FS; +@@ -1703,7 +1708,7 @@ int freeze_super(struct super_block *sb) + printk(KERN_ERR + "VFS:Filesystem freeze failed\n"); + sb->s_writers.frozen = SB_UNFROZEN; +- sb_freeze_unlock(sb); ++ sb_freeze_unlock(sb, SB_FREEZE_FS); + wake_up(&sb->s_writers.wait_unfrozen); + deactivate_locked_super(sb); + return ret; +@@ -1748,7 +1753,7 @@ static int thaw_super_locked(struct super_block *sb) + } + + sb->s_writers.frozen = SB_UNFROZEN; +- sb_freeze_unlock(sb); ++ sb_freeze_unlock(sb, SB_FREEZE_FS); + out: + wake_up(&sb->s_writers.wait_unfrozen); + deactivate_locked_super(sb); +diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c +index 1261e8b41edb4..f2625a372a3ae 100644 +--- a/fs/tracefs/inode.c ++++ b/fs/tracefs/inode.c +@@ -161,6 +161,77 @@ struct tracefs_fs_info { + struct tracefs_mount_opts mount_opts; + }; + ++static void change_gid(struct dentry *dentry, kgid_t gid) ++{ ++ if (!dentry->d_inode) ++ return; ++ dentry->d_inode->i_gid = gid; ++} ++ ++/* ++ * Taken from d_walk, but without he need for handling renames. ++ * Nothing can be renamed while walking the list, as tracefs ++ * does not support renames. This is only called when mounting ++ * or remounting the file system, to set all the files to ++ * the given gid. ++ */ ++static void set_gid(struct dentry *parent, kgid_t gid) ++{ ++ struct dentry *this_parent; ++ struct list_head *next; ++ ++ this_parent = parent; ++ spin_lock(&this_parent->d_lock); ++ ++ change_gid(this_parent, gid); ++repeat: ++ next = this_parent->d_subdirs.next; ++resume: ++ while (next != &this_parent->d_subdirs) { ++ struct list_head *tmp = next; ++ struct dentry *dentry = list_entry(tmp, struct dentry, d_child); ++ next = tmp->next; ++ ++ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); ++ ++ change_gid(dentry, gid); ++ ++ if (!list_empty(&dentry->d_subdirs)) { ++ spin_unlock(&this_parent->d_lock); ++ spin_release(&dentry->d_lock.dep_map, _RET_IP_); ++ this_parent = dentry; ++ spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_); ++ goto repeat; ++ } ++ spin_unlock(&dentry->d_lock); ++ } ++ /* ++ * All done at this level ... ascend and resume the search. ++ */ ++ rcu_read_lock(); ++ascend: ++ if (this_parent != parent) { ++ struct dentry *child = this_parent; ++ this_parent = child->d_parent; ++ ++ spin_unlock(&child->d_lock); ++ spin_lock(&this_parent->d_lock); ++ ++ /* go into the first sibling still alive */ ++ do { ++ next = child->d_child.next; ++ if (next == &this_parent->d_subdirs) ++ goto ascend; ++ child = list_entry(next, struct dentry, d_child); ++ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); ++ rcu_read_unlock(); ++ goto resume; ++ } ++ rcu_read_unlock(); ++ spin_unlock(&this_parent->d_lock); ++ return; ++} ++ + static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) + { + substring_t args[MAX_OPT_ARGS]; +@@ -219,7 +290,9 @@ static int tracefs_apply_options(struct super_block *sb) + inode->i_mode |= opts->mode; + + inode->i_uid = opts->uid; +- inode->i_gid = opts->gid; ++ ++ /* Set all the group ids to the mount option */ ++ set_gid(sb->s_root, opts->gid); + + return 0; + } +@@ -414,6 +487,8 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode, + inode->i_mode = mode; + inode->i_fop = fops ? fops : &tracefs_file_operations; + inode->i_private = data; ++ inode->i_uid = d_inode(dentry->d_parent)->i_uid; ++ inode->i_gid = d_inode(dentry->d_parent)->i_gid; + d_instantiate(dentry, inode); + fsnotify_create(dentry->d_parent->d_inode, dentry); + return end_creating(dentry); +@@ -432,9 +507,12 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent, + if (unlikely(!inode)) + return failed_creating(dentry); + +- inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; ++ /* Do not set bits for OTH */ ++ inode->i_mode = S_IFDIR | S_IRWXU | S_IRUSR| S_IRGRP | S_IXUSR | S_IXGRP; + inode->i_op = ops; + inode->i_fop = &simple_dir_operations; ++ inode->i_uid = d_inode(dentry->d_parent)->i_uid; ++ inode->i_gid = d_inode(dentry->d_parent)->i_gid; + + /* directory inodes start off with i_nlink == 2 (for "." entry) */ + inc_nlink(inode); +diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c +index f0fb25727d961..eb05038b71911 100644 +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1853,7 +1853,6 @@ out: + kthread_stop(c->bgt); + c->bgt = NULL; + } +- free_wbufs(c); + kfree(c->write_reserve_buf); + c->write_reserve_buf = NULL; + vfree(c->ileb_buf); +diff --git a/fs/udf/dir.c b/fs/udf/dir.c +index 70abdfad2df17..42e3e551fa4c3 100644 +--- a/fs/udf/dir.c ++++ b/fs/udf/dir.c +@@ -31,6 +31,7 @@ + #include <linux/mm.h> + #include <linux/slab.h> + #include <linux/bio.h> ++#include <linux/iversion.h> + + #include "udf_i.h" + #include "udf_sb.h" +@@ -43,7 +44,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) + struct fileIdentDesc *fi = NULL; + struct fileIdentDesc cfi; + udf_pblk_t block, iblock; +- loff_t nf_pos; ++ loff_t nf_pos, emit_pos = 0; + int flen; + unsigned char *fname = NULL, *copy_name = NULL; + unsigned char *nameptr; +@@ -57,6 +58,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) + int i, num, ret = 0; + struct extent_position epos = { NULL, 0, {0, 0} }; + struct super_block *sb = dir->i_sb; ++ bool pos_valid = false; + + if (ctx->pos == 0) { + if (!dir_emit_dot(file, ctx)) +@@ -67,6 +69,21 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) + if (nf_pos >= size) + goto out; + ++ /* ++ * Something changed since last readdir (either lseek was called or dir ++ * changed)? We need to verify the position correctly points at the ++ * beginning of some dir entry so that the directory parsing code does ++ * not get confused. Since UDF does not have any reliable way of ++ * identifying beginning of dir entry (names are under user control), ++ * we need to scan the directory from the beginning. ++ */ ++ if (!inode_eq_iversion(dir, file->f_version)) { ++ emit_pos = nf_pos; ++ nf_pos = 0; ++ } else { ++ pos_valid = true; ++ } ++ + fname = kmalloc(UDF_NAME_LEN, GFP_NOFS); + if (!fname) { + ret = -ENOMEM; +@@ -122,13 +139,21 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) + + while (nf_pos < size) { + struct kernel_lb_addr tloc; ++ loff_t cur_pos = nf_pos; + +- ctx->pos = (nf_pos >> 2) + 1; ++ /* Update file position only if we got past the current one */ ++ if (nf_pos >= emit_pos) { ++ ctx->pos = (nf_pos >> 2) + 1; ++ pos_valid = true; ++ } + + fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, + &elen, &offset); + if (!fi) + goto out; ++ /* Still not at offset where user asked us to read from? */ ++ if (cur_pos < emit_pos) ++ continue; + + liu = le16_to_cpu(cfi.lengthOfImpUse); + lfi = cfi.lengthFileIdent; +@@ -186,8 +211,11 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) + } /* end while */ + + ctx->pos = (nf_pos >> 2) + 1; ++ pos_valid = true; + + out: ++ if (pos_valid) ++ file->f_version = inode_query_iversion(dir); + if (fibh.sbh != fibh.ebh) + brelse(fibh.ebh); + brelse(fibh.sbh); +diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c +index 2ecf0e87660e3..b5d611cee749c 100644 +--- a/fs/udf/ialloc.c ++++ b/fs/udf/ialloc.c +@@ -77,6 +77,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) + GFP_KERNEL); + } + if (!iinfo->i_data) { ++ make_bad_inode(inode); + iput(inode); + return ERR_PTR(-ENOMEM); + } +@@ -86,6 +87,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode) + dinfo->i_location.partitionReferenceNum, + start, &err); + if (err) { ++ make_bad_inode(inode); + iput(inode); + return ERR_PTR(err); + } +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index 1d6b7a50736ba..ea8f6cd01f501 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -258,10 +258,6 @@ int udf_expand_file_adinicb(struct inode *inode) + char *kaddr; + struct udf_inode_info *iinfo = UDF_I(inode); + int err; +- struct writeback_control udf_wbc = { +- .sync_mode = WB_SYNC_NONE, +- .nr_to_write = 1, +- }; + + WARN_ON_ONCE(!inode_is_locked(inode)); + if (!iinfo->i_lenAlloc) { +@@ -305,8 +301,10 @@ int udf_expand_file_adinicb(struct inode *inode) + iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; + /* from now on we have normal address_space methods */ + inode->i_data.a_ops = &udf_aops; ++ set_page_dirty(page); ++ unlock_page(page); + up_write(&iinfo->i_data_sem); +- err = inode->i_data.a_ops->writepage(page, &udf_wbc); ++ err = filemap_fdatawrite(inode->i_mapping); + if (err) { + /* Restore everything back so that we don't lose data... */ + lock_page(page); +@@ -317,6 +315,7 @@ int udf_expand_file_adinicb(struct inode *inode) + unlock_page(page); + iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; + inode->i_data.a_ops = &udf_adinicb_aops; ++ iinfo->i_lenAlloc = inode->i_size; + up_write(&iinfo->i_data_sem); + } + put_page(page); +diff --git a/fs/udf/namei.c b/fs/udf/namei.c +index caeef08efed23..0ed4861b038f6 100644 +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -30,6 +30,7 @@ + #include <linux/sched.h> + #include <linux/crc-itu-t.h> + #include <linux/exportfs.h> ++#include <linux/iversion.h> + + static inline int udf_match(int len1, const unsigned char *name1, int len2, + const unsigned char *name2) +@@ -134,6 +135,8 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, + mark_buffer_dirty_inode(fibh->ebh, inode); + mark_buffer_dirty_inode(fibh->sbh, inode); + } ++ inode_inc_iversion(inode); ++ + return 0; + } + +diff --git a/fs/udf/super.c b/fs/udf/super.c +index b2d7c57d06881..aa2f6093d3f6f 100644 +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -57,6 +57,7 @@ + #include <linux/crc-itu-t.h> + #include <linux/log2.h> + #include <asm/byteorder.h> ++#include <linux/iversion.h> + + #include "udf_sb.h" + #include "udf_i.h" +@@ -149,6 +150,7 @@ static struct inode *udf_alloc_inode(struct super_block *sb) + init_rwsem(&ei->i_data_sem); + ei->cached_extent.lstart = -1; + spin_lock_init(&ei->i_extent_cache_lock); ++ inode_set_iversion(&ei->vfs_inode, 1); + + return &ei->vfs_inode; + } +diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c +index 0c795dc093efa..09269f478df9c 100644 +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -687,7 +687,8 @@ xfs_ioc_space( + + if (bf->l_start > XFS_ISIZE(ip)) { + error = xfs_alloc_file_space(ip, XFS_ISIZE(ip), +- bf->l_start - XFS_ISIZE(ip), 0); ++ bf->l_start - XFS_ISIZE(ip), ++ XFS_BMAPI_PREALLOC); + if (error) + goto out_unlock; + } +diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c +index ddc346a9df9ba..807f33553a8eb 100644 +--- a/fs/zonefs/super.c ++++ b/fs/zonefs/super.c +@@ -1787,5 +1787,6 @@ static void __exit zonefs_exit(void) + MODULE_AUTHOR("Damien Le Moal"); + MODULE_DESCRIPTION("Zone file system for zoned block devices"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS_FS("zonefs"); + module_init(zonefs_init); + module_exit(zonefs_exit); +diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h +index 13d93371790ec..e9c7d7b270e73 100644 +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -613,9 +613,10 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); + int acpi_disable_wakeup_device_power(struct acpi_device *dev); + + #ifdef CONFIG_X86 +-bool acpi_device_always_present(struct acpi_device *adev); ++bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status); + #else +-static inline bool acpi_device_always_present(struct acpi_device *adev) ++static inline bool acpi_device_override_status(struct acpi_device *adev, ++ unsigned long long *status) + { + return false; + } +diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h +index 92c71dfce0d5d..cefbb7ad253e0 100644 +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -536,8 +536,14 @@ typedef u64 acpi_integer; + * Can be used with access_width of struct acpi_generic_address and access_size of + * struct acpi_resource_generic_register. + */ +-#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2)) +-#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1)) ++#define ACPI_ACCESS_BIT_SHIFT 2 ++#define ACPI_ACCESS_BYTE_SHIFT -1 ++#define ACPI_ACCESS_BIT_MAX (31 - ACPI_ACCESS_BIT_SHIFT) ++#define ACPI_ACCESS_BYTE_MAX (31 - ACPI_ACCESS_BYTE_SHIFT) ++#define ACPI_ACCESS_BIT_DEFAULT (8 - ACPI_ACCESS_BIT_SHIFT) ++#define ACPI_ACCESS_BYTE_DEFAULT (8 - ACPI_ACCESS_BYTE_SHIFT) ++#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BIT_SHIFT)) ++#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BYTE_SHIFT)) + + /******************************************************************************* + * +diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h +index 0d132ee2a2913..835f959a25f25 100644 +--- a/include/asm-generic/bitops/find.h ++++ b/include/asm-generic/bitops/find.h +@@ -97,6 +97,7 @@ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + + #ifdef CONFIG_GENERIC_FIND_FIRST_BIT + ++#ifndef find_first_bit + /** + * find_first_bit - find the first set bit in a memory region + * @addr: The address to start the search at +@@ -116,7 +117,9 @@ unsigned long find_first_bit(const unsigned long *addr, unsigned long size) + + return _find_first_bit(addr, size); + } ++#endif + ++#ifndef find_first_zero_bit + /** + * find_first_zero_bit - find the first cleared bit in a memory region + * @addr: The address to start the search at +@@ -136,6 +139,8 @@ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) + + return _find_first_zero_bit(addr, size); + } ++#endif ++ + #else /* CONFIG_GENERIC_FIND_FIRST_BIT */ + + #ifndef find_first_bit +diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h +index f681bbdbc6982..36f7eb9d06639 100644 +--- a/include/drm/ttm/ttm_bo_api.h ++++ b/include/drm/ttm/ttm_bo_api.h +@@ -594,8 +594,7 @@ vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, + + vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, + pgprot_t prot, +- pgoff_t num_prefault, +- pgoff_t fault_page_size); ++ pgoff_t num_prefault); + + vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf); + +diff --git a/include/linux/acpi.h b/include/linux/acpi.h +index 974d497a897dc..6224b1e32681c 100644 +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -976,6 +976,15 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr) + return -ENODEV; + } + ++static inline int acpi_register_wakeup_handler(int wake_irq, ++ bool (*wakeup)(void *context), void *context) ++{ ++ return -ENXIO; ++} ++ ++static inline void acpi_unregister_wakeup_handler( ++ bool (*wakeup)(void *context), void *context) { } ++ + #endif /* !CONFIG_ACPI */ + + #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index 63ccb52521902..220c8c60e021a 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -92,6 +92,11 @@ + ARM_SMCCC_SMC_32, \ + 0, 0x7fff) + ++#define ARM_SMCCC_ARCH_WORKAROUND_3 \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 0x3fff) ++ + #define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ +diff --git a/include/linux/blk-pm.h b/include/linux/blk-pm.h +index b80c65aba2493..2580e05a8ab67 100644 +--- a/include/linux/blk-pm.h ++++ b/include/linux/blk-pm.h +@@ -14,7 +14,7 @@ extern void blk_pm_runtime_init(struct request_queue *q, struct device *dev); + extern int blk_pre_runtime_suspend(struct request_queue *q); + extern void blk_post_runtime_suspend(struct request_queue *q, int err); + extern void blk_pre_runtime_resume(struct request_queue *q); +-extern void blk_post_runtime_resume(struct request_queue *q, int err); ++extern void blk_post_runtime_resume(struct request_queue *q); + extern void blk_set_runtime_active(struct request_queue *q); + #else + static inline void blk_pm_runtime_init(struct request_queue *q, +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 12b9dbcc980ee..413c0148c0ce5 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -235,6 +235,14 @@ struct request { + void *end_io_data; + }; + ++static inline int blk_validate_block_size(unsigned int bsize) ++{ ++ if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize)) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static inline bool blk_op_is_passthrough(unsigned int op) + { + op &= REQ_OP_MASK; +@@ -1176,7 +1184,8 @@ extern void blk_dump_rq_flags(struct request *, char *); + + bool __must_check blk_get_queue(struct request_queue *); + extern void blk_put_queue(struct request_queue *); +-extern void blk_set_queue_dying(struct request_queue *); ++ ++void blk_mark_disk_dead(struct gendisk *disk); + + #ifdef CONFIG_BLOCK + /* +@@ -1198,8 +1207,6 @@ struct blk_plug { + bool multiple_queues; + bool nowait; + }; +-#define BLK_MAX_REQUEST_COUNT 16 +-#define BLK_PLUG_FLUSH_SIZE (128 * 1024) + + struct blk_plug_cb; + typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *, bool); +@@ -1941,6 +1948,7 @@ unsigned long disk_start_io_acct(struct gendisk *disk, unsigned int sectors, + void disk_end_io_acct(struct gendisk *disk, unsigned int op, + unsigned long start_time); + ++void bio_start_io_acct_time(struct bio *bio, unsigned long start_time); + unsigned long bio_start_io_acct(struct bio *bio); + void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time, + struct block_device *orig_bdev); +diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h +index 2746fd8042162..3536ab432b30c 100644 +--- a/include/linux/bpf-cgroup.h ++++ b/include/linux/bpf-cgroup.h +@@ -517,6 +517,7 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map, + + #define cgroup_bpf_enabled(atype) (0) + #define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) ({ 0; }) ++#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) ({ 0; }) + #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0) + #define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) + #define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; }) +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 3db6f6c95489e..15b690a0cecb0 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -190,7 +190,7 @@ struct bpf_map { + atomic64_t usercnt; + struct work_struct work; + struct mutex freeze_mutex; +- u64 writecnt; /* writable mmap cnt; protected by freeze_mutex */ ++ atomic64_t writecnt; + }; + + static inline bool map_value_has_spin_lock(const struct bpf_map *map) +@@ -206,11 +206,9 @@ static inline bool map_value_has_timer(const struct bpf_map *map) + static inline void check_and_init_map_value(struct bpf_map *map, void *dst) + { + if (unlikely(map_value_has_spin_lock(map))) +- *(struct bpf_spin_lock *)(dst + map->spin_lock_off) = +- (struct bpf_spin_lock){}; ++ memset(dst + map->spin_lock_off, 0, sizeof(struct bpf_spin_lock)); + if (unlikely(map_value_has_timer(map))) +- *(struct bpf_timer *)(dst + map->timer_off) = +- (struct bpf_timer){}; ++ memset(dst + map->timer_off, 0, sizeof(struct bpf_timer)); + } + + /* copy everything but bpf_spin_lock and bpf_timer. There could be one of each. */ +@@ -221,7 +219,8 @@ static inline void copy_map_value(struct bpf_map *map, void *dst, void *src) + if (unlikely(map_value_has_spin_lock(map))) { + s_off = map->spin_lock_off; + s_sz = sizeof(struct bpf_spin_lock); +- } else if (unlikely(map_value_has_timer(map))) { ++ } ++ if (unlikely(map_value_has_timer(map))) { + t_off = map->timer_off; + t_sz = sizeof(struct bpf_timer); + } +@@ -723,6 +722,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr) + struct bpf_trampoline *bpf_trampoline_get(u64 key, + struct bpf_attach_target_info *tgt_info); + void bpf_trampoline_put(struct bpf_trampoline *tr); ++int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs); + #define BPF_DISPATCHER_INIT(_name) { \ + .mutex = __MUTEX_INITIALIZER(_name.mutex), \ + .func = &_name##_func, \ +@@ -1320,28 +1320,16 @@ extern struct mutex bpf_stats_enabled_mutex; + * kprobes, tracepoints) to prevent deadlocks on map operations as any of + * these events can happen inside a region which holds a map bucket lock + * and can deadlock on it. +- * +- * Use the preemption safe inc/dec variants on RT because migrate disable +- * is preemptible on RT and preemption in the middle of the RMW operation +- * might lead to inconsistent state. Use the raw variants for non RT +- * kernels as migrate_disable() maps to preempt_disable() so the slightly +- * more expensive save operation can be avoided. + */ + static inline void bpf_disable_instrumentation(void) + { + migrate_disable(); +- if (IS_ENABLED(CONFIG_PREEMPT_RT)) +- this_cpu_inc(bpf_prog_active); +- else +- __this_cpu_inc(bpf_prog_active); ++ this_cpu_inc(bpf_prog_active); + } + + static inline void bpf_enable_instrumentation(void) + { +- if (IS_ENABLED(CONFIG_PREEMPT_RT)) +- this_cpu_dec(bpf_prog_active); +- else +- __this_cpu_dec(bpf_prog_active); ++ this_cpu_dec(bpf_prog_active); + migrate_enable(); + } + +@@ -1387,6 +1375,7 @@ void bpf_map_put(struct bpf_map *map); + void *bpf_map_area_alloc(u64 size, int numa_node); + void *bpf_map_area_mmapable_alloc(u64 size, int numa_node); + void bpf_map_area_free(void *base); ++bool bpf_map_write_active(const struct bpf_map *map); + void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr); + int generic_map_lookup_batch(struct bpf_map *map, + const union bpf_attr *attr, +@@ -1677,6 +1666,12 @@ bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog); + const struct btf_func_model * + bpf_jit_find_kfunc_model(const struct bpf_prog *prog, + const struct bpf_insn *insn); ++ ++static inline bool unprivileged_ebpf_enabled(void) ++{ ++ return !sysctl_unprivileged_bpf_disabled; ++} ++ + #else /* !CONFIG_BPF_SYSCALL */ + static inline struct bpf_prog *bpf_prog_get(u32 ufd) + { +@@ -1895,6 +1890,12 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog, + { + return NULL; + } ++ ++static inline bool unprivileged_ebpf_enabled(void) ++{ ++ return false; ++} ++ + #endif /* CONFIG_BPF_SYSCALL */ + + void __bpf_free_used_btfs(struct bpf_prog_aux *aux, +diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h +index 5424124dbe365..364550dd19c4a 100644 +--- a/include/linux/bpf_verifier.h ++++ b/include/linux/bpf_verifier.h +@@ -396,6 +396,13 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) + log->level == BPF_LOG_KERNEL); + } + ++static inline bool ++bpf_verifier_log_attr_valid(const struct bpf_verifier_log *log) ++{ ++ return log->len_total >= 128 && log->len_total <= UINT_MAX >> 2 && ++ log->level && log->ubuf && !(log->level & ~BPF_LOG_MASK); ++} ++ + #define BPF_MAX_SUBPROGS 256 + + struct bpf_subprog_info { +diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h +new file mode 100644 +index 0000000000000..a075b70b9a70c +--- /dev/null ++++ b/include/linux/cc_platform.h +@@ -0,0 +1,88 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Confidential Computing Platform Capability checks ++ * ++ * Copyright (C) 2021 Advanced Micro Devices, Inc. ++ * ++ * Author: Tom Lendacky <thomas.lendacky@amd.com> ++ */ ++ ++#ifndef _LINUX_CC_PLATFORM_H ++#define _LINUX_CC_PLATFORM_H ++ ++#include <linux/types.h> ++#include <linux/stddef.h> ++ ++/** ++ * enum cc_attr - Confidential computing attributes ++ * ++ * These attributes represent confidential computing features that are ++ * currently active. ++ */ ++enum cc_attr { ++ /** ++ * @CC_ATTR_MEM_ENCRYPT: Memory encryption is active ++ * ++ * The platform/OS is running with active memory encryption. This ++ * includes running either as a bare-metal system or a hypervisor ++ * and actively using memory encryption or as a guest/virtual machine ++ * and actively using memory encryption. ++ * ++ * Examples include SME, SEV and SEV-ES. ++ */ ++ CC_ATTR_MEM_ENCRYPT, ++ ++ /** ++ * @CC_ATTR_HOST_MEM_ENCRYPT: Host memory encryption is active ++ * ++ * The platform/OS is running as a bare-metal system or a hypervisor ++ * and actively using memory encryption. ++ * ++ * Examples include SME. ++ */ ++ CC_ATTR_HOST_MEM_ENCRYPT, ++ ++ /** ++ * @CC_ATTR_GUEST_MEM_ENCRYPT: Guest memory encryption is active ++ * ++ * The platform/OS is running as a guest/virtual machine and actively ++ * using memory encryption. ++ * ++ * Examples include SEV and SEV-ES. ++ */ ++ CC_ATTR_GUEST_MEM_ENCRYPT, ++ ++ /** ++ * @CC_ATTR_GUEST_STATE_ENCRYPT: Guest state encryption is active ++ * ++ * The platform/OS is running as a guest/virtual machine and actively ++ * using memory encryption and register state encryption. ++ * ++ * Examples include SEV-ES. ++ */ ++ CC_ATTR_GUEST_STATE_ENCRYPT, ++}; ++ ++#ifdef CONFIG_ARCH_HAS_CC_PLATFORM ++ ++/** ++ * cc_platform_has() - Checks if the specified cc_attr attribute is active ++ * @attr: Confidential computing attribute to check ++ * ++ * The cc_platform_has() function will return an indicator as to whether the ++ * specified Confidential Computing attribute is currently active. ++ * ++ * Context: Any context ++ * Return: ++ * * TRUE - Specified Confidential Computing attribute is active ++ * * FALSE - Specified Confidential Computing attribute is not active ++ */ ++bool cc_platform_has(enum cc_attr attr); ++ ++#else /* !CONFIG_ARCH_HAS_CC_PLATFORM */ ++ ++static inline bool cc_platform_has(enum cc_attr attr) { return false; } ++ ++#endif /* CONFIG_ARCH_HAS_CC_PLATFORM */ ++ ++#endif /* _LINUX_CC_PLATFORM_H */ +diff --git a/include/linux/compiler.h b/include/linux/compiler.h +index 3d5af56337bdb..0f7fd205ab7ea 100644 +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -117,40 +117,29 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, + */ + #define __stringify_label(n) #n + +-#define __annotate_reachable(c) ({ \ +- asm volatile(__stringify_label(c) ":\n\t" \ +- ".pushsection .discard.reachable\n\t" \ +- ".long " __stringify_label(c) "b - .\n\t" \ +- ".popsection\n\t"); \ +-}) +-#define annotate_reachable() __annotate_reachable(__COUNTER__) +- + #define __annotate_unreachable(c) ({ \ + asm volatile(__stringify_label(c) ":\n\t" \ + ".pushsection .discard.unreachable\n\t" \ + ".long " __stringify_label(c) "b - .\n\t" \ +- ".popsection\n\t"); \ ++ ".popsection\n\t" : : "i" (c)); \ + }) + #define annotate_unreachable() __annotate_unreachable(__COUNTER__) + +-#define ASM_UNREACHABLE \ +- "999:\n\t" \ +- ".pushsection .discard.unreachable\n\t" \ +- ".long 999b - .\n\t" \ ++#define ASM_REACHABLE \ ++ "998:\n\t" \ ++ ".pushsection .discard.reachable\n\t" \ ++ ".long 998b - .\n\t" \ + ".popsection\n\t" + + /* Annotate a C jump table to allow objtool to follow the code flow */ + #define __annotate_jump_table __section(".rodata..c_jump_table") + + #else +-#define annotate_reachable() + #define annotate_unreachable() ++# define ASM_REACHABLE + #define __annotate_jump_table + #endif + +-#ifndef ASM_UNREACHABLE +-# define ASM_UNREACHABLE +-#endif + #ifndef unreachable + # define unreachable() do { \ + annotate_unreachable(); \ +diff --git a/include/linux/console.h b/include/linux/console.h +index 20874db50bc8a..a97f277cfdfa3 100644 +--- a/include/linux/console.h ++++ b/include/linux/console.h +@@ -149,6 +149,8 @@ struct console { + short flags; + short index; + int cflag; ++ uint ispeed; ++ uint ospeed; + void *data; + struct console *next; + }; +diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h +index ff88bb3e44fca..66a1f495f01a6 100644 +--- a/include/linux/cpufreq.h ++++ b/include/linux/cpufreq.h +@@ -1041,7 +1041,7 @@ static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_ + if (cpu == pcpu) + continue; + +- ret = parse_perf_domain(pcpu, list_name, cell_name); ++ ret = parse_perf_domain(cpu, list_name, cell_name); + if (ret < 0) + continue; + +diff --git a/include/linux/delay.h b/include/linux/delay.h +index 1d0e2ce6b6d9f..e8607992c68a5 100644 +--- a/include/linux/delay.h ++++ b/include/linux/delay.h +@@ -20,6 +20,7 @@ + */ + + #include <linux/kernel.h> ++#include <linux/sched.h> + + extern unsigned long loops_per_jiffy; + +@@ -58,7 +59,18 @@ void calibrate_delay(void); + void __attribute__((weak)) calibration_delay_done(void); + void msleep(unsigned int msecs); + unsigned long msleep_interruptible(unsigned int msecs); +-void usleep_range(unsigned long min, unsigned long max); ++void usleep_range_state(unsigned long min, unsigned long max, ++ unsigned int state); ++ ++static inline void usleep_range(unsigned long min, unsigned long max) ++{ ++ usleep_range_state(min, max, TASK_UNINTERRUPTIBLE); ++} ++ ++static inline void usleep_idle_range(unsigned long min, unsigned long max) ++{ ++ usleep_range_state(min, max, TASK_IDLE); ++} + + static inline void ssleep(unsigned int seconds) + { +diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h +index 8b32b4bdd5908..3ad636a13b8e9 100644 +--- a/include/linux/dma-buf.h ++++ b/include/linux/dma-buf.h +@@ -433,7 +433,7 @@ struct dma_buf { + wait_queue_head_t *poll; + + __poll_t active; +- } cb_excl, cb_shared; ++ } cb_in, cb_out; + #ifdef CONFIG_DMABUF_SYSFS_STATS + /** + * @sysfs_entry: +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index e5c2c9e71bf10..9000f3ffce8b3 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -944,10 +944,8 @@ struct dma_device { + void (*device_issue_pending)(struct dma_chan *chan); + void (*device_release)(struct dma_device *dev); + /* debugfs support */ +-#ifdef CONFIG_DEBUG_FS + void (*dbg_summary_show)(struct seq_file *s, struct dma_device *dev); + struct dentry *dbg_dev_root; +-#endif + }; + + static inline int dmaengine_slave_config(struct dma_chan *chan, +diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h +index 8ae999f587c48..289064b51fa9a 100644 +--- a/include/linux/dsa/ocelot.h ++++ b/include/linux/dsa/ocelot.h +@@ -12,6 +12,7 @@ + struct ocelot_skb_cb { + struct sk_buff *clone; + unsigned int ptp_class; /* valid only for clones */ ++ u32 tstamp_lo; + u8 ptp_cmd; + u8 ts_id; + }; +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 6b5d36babfcc4..3d8ddc5eca8ca 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -1282,4 +1282,10 @@ static inline struct efi_mokvar_table_entry *efi_mokvar_entry_find( + } + #endif + ++#ifdef CONFIG_SYSFB ++extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); ++#else ++static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) { } ++#endif ++ + #endif /* _LINUX_EFI_H */ +diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h +index 849524b55d89a..3fad741df53ef 100644 +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -94,7 +94,7 @@ struct ethtool_link_ext_state_info { + enum ethtool_link_ext_substate_link_logical_mismatch link_logical_mismatch; + enum ethtool_link_ext_substate_bad_signal_integrity bad_signal_integrity; + enum ethtool_link_ext_substate_cable_issue cable_issue; +- u8 __link_ext_substate; ++ u32 __link_ext_substate; + }; + }; + +diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h +index 1e7bf78cb3829..aba348d58ff61 100644 +--- a/include/linux/ethtool_netlink.h ++++ b/include/linux/ethtool_netlink.h +@@ -10,6 +10,9 @@ + #define __ETHTOOL_LINK_MODE_MASK_NWORDS \ + DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32) + ++#define ETHTOOL_PAUSE_STAT_CNT (__ETHTOOL_A_PAUSE_STAT_CNT - \ ++ ETHTOOL_A_PAUSE_STAT_TX_FRAMES) ++ + enum ethtool_multicast_groups { + ETHNL_MCGRP_MONITOR, + }; +diff --git a/include/linux/fb.h b/include/linux/fb.h +index 5950f8f5dc74d..02f362c661c80 100644 +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -610,6 +610,7 @@ extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, + const char *name); + extern int remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary); ++extern bool is_firmware_framebuffer(struct apertures_struct *a); + extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); + extern int fb_show_logo(struct fb_info *fb_info, int rotate); + extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); +diff --git a/include/linux/filter.h b/include/linux/filter.h +index ef03ff34234d8..a9956b681f090 100644 +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -554,9 +554,9 @@ struct bpf_binary_header { + }; + + struct bpf_prog_stats { +- u64 cnt; +- u64 nsecs; +- u64 misses; ++ u64_stats_t cnt; ++ u64_stats_t nsecs; ++ u64_stats_t misses; + struct u64_stats_sync syncp; + } __aligned(2 * sizeof(u64)); + +@@ -613,13 +613,14 @@ static __always_inline u32 __bpf_prog_run(const struct bpf_prog *prog, + if (static_branch_unlikely(&bpf_stats_enabled_key)) { + struct bpf_prog_stats *stats; + u64 start = sched_clock(); ++ unsigned long flags; + + ret = dfunc(ctx, prog->insnsi, prog->bpf_func); + stats = this_cpu_ptr(prog->stats); +- u64_stats_update_begin(&stats->syncp); +- stats->cnt++; +- stats->nsecs += sched_clock() - start; +- u64_stats_update_end(&stats->syncp); ++ flags = u64_stats_update_begin_irqsave(&stats->syncp); ++ u64_stats_inc(&stats->cnt); ++ u64_stats_add(&stats->nsecs, sched_clock() - start); ++ u64_stats_update_end_irqrestore(&stats->syncp, flags); + } else { + ret = dfunc(ctx, prog->insnsi, prog->bpf_func); + } +@@ -638,9 +639,6 @@ static __always_inline u32 bpf_prog_run(const struct bpf_prog *prog, const void + * This uses migrate_disable/enable() explicitly to document that the + * invocation of a BPF program does not require reentrancy protection + * against a BPF program which is invoked from a preempting task. +- * +- * For non RT enabled kernels migrate_disable/enable() maps to +- * preempt_disable/enable(), i.e. it disables also preemption. + */ + static inline u32 bpf_prog_run_pin_on_cpu(const struct bpf_prog *prog, + const void *ctx) +diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h +index c1be37437e778..0c70febd03e95 100644 +--- a/include/linux/fortify-string.h ++++ b/include/linux/fortify-string.h +@@ -280,7 +280,10 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) + if (p_size == (size_t)-1 && q_size == (size_t)-1) + return __underlying_strcpy(p, q); + size = strlen(q) + 1; +- /* test here to use the more stringent object size */ ++ /* Compile-time check for const size overflow. */ ++ if (__builtin_constant_p(size) && p_size < size) ++ __write_overflow(); ++ /* Run-time check for dynamic size overflow. */ + if (p_size < size) + fortify_panic(__func__); + memcpy(p, q, size); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index e7a633353fd20..56eba723477e3 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2498,6 +2498,8 @@ enum file_time_flags { + + extern bool atime_needs_update(const struct path *, struct inode *); + extern void touch_atime(const struct path *); ++int inode_update_time(struct inode *inode, struct timespec64 *time, int flags); ++ + static inline void file_accessed(struct file *file) + { + if (!(file->f_flags & O_NOATIME)) +diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h +index 6b54982fc5f37..13fa6f3df8e46 100644 +--- a/include/linux/fs_context.h ++++ b/include/linux/fs_context.h +@@ -142,6 +142,8 @@ extern void put_fs_context(struct fs_context *fc); + extern int vfs_parse_fs_param_source(struct fs_context *fc, + struct fs_parameter *param); + extern void fc_drop_locked(struct fs_context *fc); ++int reconfigure_single(struct super_block *s, ++ int flags, void *data); + + /* + * sget() wrappers to be called from the ->get_tree() op. +diff --git a/include/linux/fscache.h b/include/linux/fscache.h +index a4dab59986137..3b2282c157f79 100644 +--- a/include/linux/fscache.h ++++ b/include/linux/fscache.h +@@ -167,7 +167,7 @@ struct fscache_cookie { + + static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie) + { +- return test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); ++ return fscache_cookie_valid(cookie) && test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); + } + + /* +diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h +index 12d3a7d308ab9..a9477c14fad5c 100644 +--- a/include/linux/fsnotify.h ++++ b/include/linux/fsnotify.h +@@ -212,6 +212,42 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, + fsnotify_name(dir, FS_CREATE, inode, &new_dentry->d_name, 0); + } + ++/* ++ * fsnotify_delete - @dentry was unlinked and unhashed ++ * ++ * Caller must make sure that dentry->d_name is stable. ++ * ++ * Note: unlike fsnotify_unlink(), we have to pass also the unlinked inode ++ * as this may be called after d_delete() and old_dentry may be negative. ++ */ ++static inline void fsnotify_delete(struct inode *dir, struct inode *inode, ++ struct dentry *dentry) ++{ ++ __u32 mask = FS_DELETE; ++ ++ if (S_ISDIR(inode->i_mode)) ++ mask |= FS_ISDIR; ++ ++ fsnotify_name(dir, mask, inode, &dentry->d_name, 0); ++} ++ ++/** ++ * d_delete_notify - delete a dentry and call fsnotify_delete() ++ * @dentry: The dentry to delete ++ * ++ * This helper is used to guaranty that the unlinked inode cannot be found ++ * by lookup of this name after fsnotify_delete() event has been delivered. ++ */ ++static inline void d_delete_notify(struct inode *dir, struct dentry *dentry) ++{ ++ struct inode *inode = d_inode(dentry); ++ ++ ihold(inode); ++ d_delete(dentry); ++ fsnotify_delete(dir, inode, dentry); ++ iput(inode); ++} ++ + /* + * fsnotify_unlink - 'name' was unlinked + * +@@ -219,10 +255,10 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, + */ + static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry) + { +- /* Expected to be called before d_delete() */ +- WARN_ON_ONCE(d_is_negative(dentry)); ++ if (WARN_ON_ONCE(d_is_negative(dentry))) ++ return; + +- fsnotify_dirent(dir, dentry, FS_DELETE); ++ fsnotify_delete(dir, d_inode(dentry), dentry); + } + + /* +@@ -242,10 +278,10 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) + */ + static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry) + { +- /* Expected to be called before d_delete() */ +- WARN_ON_ONCE(d_is_negative(dentry)); ++ if (WARN_ON_ONCE(d_is_negative(dentry))) ++ return; + +- fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR); ++ fsnotify_delete(dir, d_inode(dentry), dentry); + } + + /* +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 9e067f937dbc2..26742ca14609a 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -349,6 +349,8 @@ struct hid_item { + /* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */ + #define HID_QUIRK_ALWAYS_POLL BIT(10) + #define HID_QUIRK_INPUT_PER_APP BIT(11) ++#define HID_QUIRK_X_INVERT BIT(12) ++#define HID_QUIRK_Y_INVERT BIT(13) + #define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16) + #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17) + #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18) +@@ -840,6 +842,11 @@ static inline bool hid_is_using_ll_driver(struct hid_device *hdev, + return hdev->ll_driver == driver; + } + ++static inline bool hid_is_usb(struct hid_device *hdev) ++{ ++ return hid_is_using_ll_driver(hdev, &usb_hid_driver); ++} ++ + #define PM_HINT_FULLON 1<<5 + #define PM_HINT_NORMAL 1<<1 + +diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h +index 096f68dd2e0ca..4c69b144677b1 100644 +--- a/include/linux/iio/trigger.h ++++ b/include/linux/iio/trigger.h +@@ -55,6 +55,7 @@ struct iio_trigger_ops { + * @attached_own_device:[INTERN] if we are using our own device as trigger, + * i.e. if we registered a poll function to the same + * device as the one providing the trigger. ++ * @reenable_work: [INTERN] work item used to ensure reenable can sleep. + **/ + struct iio_trigger { + const struct iio_trigger_ops *ops; +@@ -74,6 +75,7 @@ struct iio_trigger { + unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; + struct mutex pool_lock; + bool attached_own_device; ++ struct work_struct reenable_work; + }; + + +diff --git a/include/linux/instrumentation.h b/include/linux/instrumentation.h +index fa2cd8c63dcc9..24359b4a96053 100644 +--- a/include/linux/instrumentation.h ++++ b/include/linux/instrumentation.h +@@ -11,7 +11,7 @@ + asm volatile(__stringify(c) ": nop\n\t" \ + ".pushsection .discard.instr_begin\n\t" \ + ".long " __stringify(c) "b - .\n\t" \ +- ".popsection\n\t"); \ ++ ".popsection\n\t" : : "i" (c)); \ + }) + #define instrumentation_begin() __instrumentation_begin(__COUNTER__) + +@@ -50,7 +50,7 @@ + asm volatile(__stringify(c) ": nop\n\t" \ + ".pushsection .discard.instr_end\n\t" \ + ".long " __stringify(c) "b - .\n\t" \ +- ".popsection\n\t"); \ ++ ".popsection\n\t" : : "i" (c)); \ + }) + #define instrumentation_end() __instrumentation_end(__COUNTER__) + #else +diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h +index 05e22770af517..b75395ec8d521 100644 +--- a/include/linux/ipc_namespace.h ++++ b/include/linux/ipc_namespace.h +@@ -131,6 +131,16 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) + return ns; + } + ++static inline struct ipc_namespace *get_ipc_ns_not_zero(struct ipc_namespace *ns) ++{ ++ if (ns) { ++ if (refcount_inc_not_zero(&ns->ns.count)) ++ return ns; ++ } ++ ++ return NULL; ++} ++ + extern void put_ipc_ns(struct ipc_namespace *ns); + #else + static inline struct ipc_namespace *copy_ipcs(unsigned long flags, +@@ -147,6 +157,11 @@ static inline struct ipc_namespace *get_ipc_ns(struct ipc_namespace *ns) + return ns; + } + ++static inline struct ipc_namespace *get_ipc_ns_not_zero(struct ipc_namespace *ns) ++{ ++ return ns; ++} ++ + static inline void put_ipc_ns(struct ipc_namespace *ns) + { + } +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h +index ef4a69865737c..07cba0b3496d5 100644 +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -132,6 +132,7 @@ struct inet6_skb_parm { + __u16 dsthao; + #endif + __u16 frag_max_size; ++ __u16 srhoff; + + #define IP6SKB_XFRM_TRANSFORMED 1 + #define IP6SKB_FORWARDED 2 +@@ -141,6 +142,7 @@ struct inet6_skb_parm { + #define IP6SKB_HOPBYHOP 32 + #define IP6SKB_L3SLAVE 64 + #define IP6SKB_JUMBOGRAM 128 ++#define IP6SKB_SEG6 256 + }; + + #if defined(CONFIG_NET_L3_MASTER_DEV) +@@ -282,7 +284,6 @@ struct ipv6_pinfo { + __be32 rcv_flowinfo; + + __u32 dst_cookie; +- __u32 rx_dst_cookie; + + struct ipv6_mc_socklist __rcu *ipv6_mc_list; + struct ipv6_ac_socklist *ipv6_ac_list; +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index fd933c45281af..d63b8106796e2 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1295,7 +1295,7 @@ struct journal_s + * Clean-up after fast commit or full commit. JBD2 calls this function + * after every commit operation. + */ +- void (*j_fc_cleanup_callback)(struct journal_s *journal, int); ++ void (*j_fc_cleanup_callback)(struct journal_s *journal, int full, tid_t tid); + + /** + * @j_fc_replay_callback: +diff --git a/include/linux/kasan.h b/include/linux/kasan.h +index dd874a1ee862a..f407e937241af 100644 +--- a/include/linux/kasan.h ++++ b/include/linux/kasan.h +@@ -461,12 +461,12 @@ static inline void kasan_release_vmalloc(unsigned long start, + * allocations with real shadow memory. With KASAN vmalloc, the special + * case is unnecessary, as the work is handled in the generic case. + */ +-int kasan_module_alloc(void *addr, size_t size); ++int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask); + void kasan_free_shadow(const struct vm_struct *vm); + + #else /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */ + +-static inline int kasan_module_alloc(void *addr, size_t size) { return 0; } ++static inline int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask) { return 0; } + static inline void kasan_free_shadow(const struct vm_struct *vm) {} + + #endif /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */ +diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h +index 44ae1a7eb9e39..69ae6b2784645 100644 +--- a/include/linux/kernel_stat.h ++++ b/include/linux/kernel_stat.h +@@ -102,6 +102,7 @@ extern void account_system_index_time(struct task_struct *, u64, + enum cpu_usage_stat); + extern void account_steal_time(u64); + extern void account_idle_time(u64); ++extern u64 get_idle_time(struct kernel_cpustat *kcs, int cpu); + + #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE + static inline void account_process_tick(struct task_struct *tsk, int user) +diff --git a/include/linux/kfence.h b/include/linux/kfence.h +index 3fe6dd8a18c19..4b5e3679a72c7 100644 +--- a/include/linux/kfence.h ++++ b/include/linux/kfence.h +@@ -14,6 +14,9 @@ + + #ifdef CONFIG_KFENCE + ++#include <linux/atomic.h> ++#include <linux/static_key.h> ++ + /* + * We allocate an even number of pages, as it simplifies calculations to map + * address to metadata indices; effectively, the very first page serves as an +@@ -22,13 +25,8 @@ + #define KFENCE_POOL_SIZE ((CONFIG_KFENCE_NUM_OBJECTS + 1) * 2 * PAGE_SIZE) + extern char *__kfence_pool; + +-#ifdef CONFIG_KFENCE_STATIC_KEYS +-#include <linux/static_key.h> + DECLARE_STATIC_KEY_FALSE(kfence_allocation_key); +-#else +-#include <linux/atomic.h> + extern atomic_t kfence_allocation_gate; +-#endif + + /** + * is_kfence_address() - check if an address belongs to KFENCE pool +@@ -116,13 +114,16 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags); + */ + static __always_inline void *kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) + { +-#ifdef CONFIG_KFENCE_STATIC_KEYS +- if (static_branch_unlikely(&kfence_allocation_key)) ++#if defined(CONFIG_KFENCE_STATIC_KEYS) || CONFIG_KFENCE_SAMPLE_INTERVAL == 0 ++ if (!static_branch_unlikely(&kfence_allocation_key)) ++ return NULL; + #else +- if (unlikely(!atomic_read(&kfence_allocation_gate))) ++ if (!static_branch_likely(&kfence_allocation_key)) ++ return NULL; + #endif +- return __kfence_alloc(s, size, flags); +- return NULL; ++ if (likely(atomic_read(&kfence_allocation_gate))) ++ return NULL; ++ return __kfence_alloc(s, size, flags); + } + + /** +diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h +index e4f3bfe087570..ef8c7accbc689 100644 +--- a/include/linux/kprobes.h ++++ b/include/linux/kprobes.h +@@ -154,6 +154,8 @@ struct kretprobe { + struct kretprobe_holder *rph; + }; + ++#define KRETPROBE_MAX_DATA_SIZE 4096 ++ + struct kretprobe_instance { + union { + struct freelist_node freelist; +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 0f18df7fe8749..926f60499c347 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -15,6 +15,8 @@ + #include <linux/minmax.h> + #include <linux/mm.h> + #include <linux/mmu_notifier.h> ++#include <linux/ftrace.h> ++#include <linux/instrumentation.h> + #include <linux/preempt.h> + #include <linux/msi.h> + #include <linux/slab.h> +@@ -363,8 +365,11 @@ struct kvm_vcpu { + int last_used_slot; + }; + +-/* must be called with irqs disabled */ +-static __always_inline void guest_enter_irqoff(void) ++/* ++ * Start accounting time towards a guest. ++ * Must be called before entering guest context. ++ */ ++static __always_inline void guest_timing_enter_irqoff(void) + { + /* + * This is running in ioctl context so its safe to assume that it's the +@@ -373,7 +378,18 @@ static __always_inline void guest_enter_irqoff(void) + instrumentation_begin(); + vtime_account_guest_enter(); + instrumentation_end(); ++} + ++/* ++ * Enter guest context and enter an RCU extended quiescent state. ++ * ++ * Between guest_context_enter_irqoff() and guest_context_exit_irqoff() it is ++ * unsafe to use any code which may directly or indirectly use RCU, tracing ++ * (including IRQ flag tracing), or lockdep. All code in this period must be ++ * non-instrumentable. ++ */ ++static __always_inline void guest_context_enter_irqoff(void) ++{ + /* + * KVM does not hold any references to rcu protected data when it + * switches CPU into a guest mode. In fact switching to a guest mode +@@ -389,16 +405,79 @@ static __always_inline void guest_enter_irqoff(void) + } + } + +-static __always_inline void guest_exit_irqoff(void) ++/* ++ * Deprecated. Architectures should move to guest_timing_enter_irqoff() and ++ * guest_state_enter_irqoff(). ++ */ ++static __always_inline void guest_enter_irqoff(void) ++{ ++ guest_timing_enter_irqoff(); ++ guest_context_enter_irqoff(); ++} ++ ++/** ++ * guest_state_enter_irqoff - Fixup state when entering a guest ++ * ++ * Entry to a guest will enable interrupts, but the kernel state is interrupts ++ * disabled when this is invoked. Also tell RCU about it. ++ * ++ * 1) Trace interrupts on state ++ * 2) Invoke context tracking if enabled to adjust RCU state ++ * 3) Tell lockdep that interrupts are enabled ++ * ++ * Invoked from architecture specific code before entering a guest. ++ * Must be called with interrupts disabled and the caller must be ++ * non-instrumentable. ++ * The caller has to invoke guest_timing_enter_irqoff() before this. ++ * ++ * Note: this is analogous to exit_to_user_mode(). ++ */ ++static __always_inline void guest_state_enter_irqoff(void) ++{ ++ instrumentation_begin(); ++ trace_hardirqs_on_prepare(); ++ lockdep_hardirqs_on_prepare(CALLER_ADDR0); ++ instrumentation_end(); ++ ++ guest_context_enter_irqoff(); ++ lockdep_hardirqs_on(CALLER_ADDR0); ++} ++ ++/* ++ * Exit guest context and exit an RCU extended quiescent state. ++ * ++ * Between guest_context_enter_irqoff() and guest_context_exit_irqoff() it is ++ * unsafe to use any code which may directly or indirectly use RCU, tracing ++ * (including IRQ flag tracing), or lockdep. All code in this period must be ++ * non-instrumentable. ++ */ ++static __always_inline void guest_context_exit_irqoff(void) + { + context_tracking_guest_exit(); ++} + ++/* ++ * Stop accounting time towards a guest. ++ * Must be called after exiting guest context. ++ */ ++static __always_inline void guest_timing_exit_irqoff(void) ++{ + instrumentation_begin(); + /* Flush the guest cputime we spent on the guest */ + vtime_account_guest_exit(); + instrumentation_end(); + } + ++/* ++ * Deprecated. Architectures should move to guest_state_exit_irqoff() and ++ * guest_timing_exit_irqoff(). ++ */ ++static __always_inline void guest_exit_irqoff(void) ++{ ++ guest_context_exit_irqoff(); ++ guest_timing_exit_irqoff(); ++} ++ + static inline void guest_exit(void) + { + unsigned long flags; +@@ -408,6 +487,33 @@ static inline void guest_exit(void) + local_irq_restore(flags); + } + ++/** ++ * guest_state_exit_irqoff - Establish state when returning from guest mode ++ * ++ * Entry from a guest disables interrupts, but guest mode is traced as ++ * interrupts enabled. Also with NO_HZ_FULL RCU might be idle. ++ * ++ * 1) Tell lockdep that interrupts are disabled ++ * 2) Invoke context tracking if enabled to reactivate RCU ++ * 3) Trace interrupts off state ++ * ++ * Invoked from architecture specific code after exiting a guest. ++ * Must be invoked with interrupts disabled and the caller must be ++ * non-instrumentable. ++ * The caller has to invoke guest_timing_exit_irqoff() after this. ++ * ++ * Note: this is analogous to enter_from_user_mode(). ++ */ ++static __always_inline void guest_state_exit_irqoff(void) ++{ ++ lockdep_hardirqs_off(CALLER_ADDR0); ++ guest_context_exit_irqoff(); ++ ++ instrumentation_begin(); ++ trace_hardirqs_off_finish(); ++ instrumentation_end(); ++} ++ + static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu) + { + /* +diff --git a/include/linux/libata.h b/include/linux/libata.h +index c0c64f03e1074..a64e12605d31d 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -394,7 +394,7 @@ enum { + /* This should match the actual table size of + * ata_eh_cmd_timeout_table in libata-eh.c. + */ +- ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 6, ++ ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 7, + + /* Horkage types. May be set by libata or controller on drives + (some horkage may be drive/controller pair dependent */ +diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h +index 2adeea44c0d53..61590c1f2d333 100644 +--- a/include/linux/lsm_hook_defs.h ++++ b/include/linux/lsm_hook_defs.h +@@ -26,13 +26,13 @@ + * #undef LSM_HOOK + * }; + */ +-LSM_HOOK(int, 0, binder_set_context_mgr, struct task_struct *mgr) +-LSM_HOOK(int, 0, binder_transaction, struct task_struct *from, +- struct task_struct *to) +-LSM_HOOK(int, 0, binder_transfer_binder, struct task_struct *from, +- struct task_struct *to) +-LSM_HOOK(int, 0, binder_transfer_file, struct task_struct *from, +- struct task_struct *to, struct file *file) ++LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) ++LSM_HOOK(int, 0, binder_transaction, const struct cred *from, ++ const struct cred *to) ++LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from, ++ const struct cred *to) ++LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from, ++ const struct cred *to, struct file *file) + LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child, + unsigned int mode) + LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent) +diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h +index 5c4c5c0602cb7..59024618554e2 100644 +--- a/include/linux/lsm_hooks.h ++++ b/include/linux/lsm_hooks.h +@@ -1313,22 +1313,22 @@ + * + * @binder_set_context_mgr: + * Check whether @mgr is allowed to be the binder context manager. +- * @mgr contains the task_struct for the task being registered. ++ * @mgr contains the struct cred for the current binder process. + * Return 0 if permission is granted. + * @binder_transaction: + * Check whether @from is allowed to invoke a binder transaction call + * to @to. +- * @from contains the task_struct for the sending task. +- * @to contains the task_struct for the receiving task. ++ * @from contains the struct cred for the sending process. ++ * @to contains the struct cred for the receiving process. + * @binder_transfer_binder: + * Check whether @from is allowed to transfer a binder reference to @to. +- * @from contains the task_struct for the sending task. +- * @to contains the task_struct for the receiving task. ++ * @from contains the struct cred for the sending process. ++ * @to contains the struct cred for the receiving process. + * @binder_transfer_file: + * Check whether @from is allowed to transfer @file to @to. +- * @from contains the task_struct for the sending task. ++ * @from contains the struct cred for the sending process. + * @file contains the struct file being transferred. +- * @to contains the task_struct for the receiving task. ++ * @to contains the struct cred for the receiving process. + * + * @ptrace_access_check: + * Check permission before allowing the current process to trace the +diff --git a/include/linux/memblock.h b/include/linux/memblock.h +index 34de69b3b8bad..5df38332e4139 100644 +--- a/include/linux/memblock.h ++++ b/include/linux/memblock.h +@@ -388,8 +388,8 @@ phys_addr_t memblock_alloc_range_nid(phys_addr_t size, + phys_addr_t end, int nid, bool exact_nid); + phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid); + +-static inline phys_addr_t memblock_phys_alloc(phys_addr_t size, +- phys_addr_t align) ++static __always_inline phys_addr_t memblock_phys_alloc(phys_addr_t size, ++ phys_addr_t align) + { + return memblock_phys_alloc_range(size, align, 0, + MEMBLOCK_ALLOC_ACCESSIBLE); +diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h +index 3096c9a0ee014..d9b8df5ef212f 100644 +--- a/include/linux/memcontrol.h ++++ b/include/linux/memcontrol.h +@@ -223,7 +223,7 @@ struct obj_cgroup { + struct mem_cgroup *memcg; + atomic_t nr_charged_bytes; + union { +- struct list_head list; ++ struct list_head list; /* protected by objcg_lock */ + struct rcu_head rcu; + }; + }; +@@ -320,7 +320,8 @@ struct mem_cgroup { + int kmemcg_id; + enum memcg_kmem_state kmem_state; + struct obj_cgroup __rcu *objcg; +- struct list_head objcg_list; /* list of inherited objcgs */ ++ /* list of inherited objcgs, protected by objcg_lock */ ++ struct list_head objcg_list; + #endif + + MEMCG_PADDING(_pad2_); +diff --git a/include/linux/mhi.h b/include/linux/mhi.h +index 7239858790353..a5cc4cdf9cc86 100644 +--- a/include/linux/mhi.h ++++ b/include/linux/mhi.h +@@ -663,6 +663,19 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); + */ + int mhi_pm_resume(struct mhi_controller *mhi_cntrl); + ++/** ++ * mhi_pm_resume_force - Force resume MHI from suspended state ++ * @mhi_cntrl: MHI controller ++ * ++ * Resume the device irrespective of its MHI state. As per the MHI spec, devices ++ * has to be in M3 state during resume. But some devices seem to be in a ++ * different MHI state other than M3 but they continue working fine if allowed. ++ * This API is intented to be used for such devices. ++ * ++ * Return: 0 if the resume succeeds, a negative error code otherwise ++ */ ++int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl); ++ + /** + * mhi_download_rddm_image - Download ramdump image from device for + * debugging purpose. +diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h +index 4ab5c1fc1270d..a09ed4c8361b6 100644 +--- a/include/linux/mlx5/eswitch.h ++++ b/include/linux/mlx5/eswitch.h +@@ -136,13 +136,13 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw, + ESW_TUN_OPTS_SLOW_TABLE_GOTO_VPORT) + #define ESW_TUN_SLOW_TABLE_GOTO_VPORT_MARK ESW_TUN_OPTS_MASK + +-u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev); ++u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev); + u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); + struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw); + + #else /* CONFIG_MLX5_ESWITCH */ + +-static inline u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev) ++static inline u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev) + { + return MLX5_ESWITCH_NONE; + } +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 993204a6c1a13..25d775764a5ac 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -3309,8 +3309,8 @@ enum { + }; + + enum { +- MLX5_TIRC_LRO_ENABLE_MASK_IPV4_LRO = 0x1, +- MLX5_TIRC_LRO_ENABLE_MASK_IPV6_LRO = 0x2, ++ MLX5_TIRC_PACKET_MERGE_MASK_IPV4_LRO = BIT(0), ++ MLX5_TIRC_PACKET_MERGE_MASK_IPV6_LRO = BIT(1), + }; + + enum { +@@ -3335,7 +3335,7 @@ struct mlx5_ifc_tirc_bits { + + u8 reserved_at_80[0x4]; + u8 lro_timeout_period_usecs[0x10]; +- u8 lro_enable_mask[0x4]; ++ u8 packet_merge_mask[0x4]; + u8 lro_max_ip_payload_size[0x8]; + + u8 reserved_at_a0[0x40]; +@@ -6369,7 +6369,7 @@ struct mlx5_ifc_modify_tir_bitmask_bits { + u8 reserved_at_3c[0x1]; + u8 hash[0x1]; + u8 reserved_at_3e[0x1]; +- u8 lro[0x1]; ++ u8 packet_merge[0x1]; + }; + + struct mlx5_ifc_modify_tir_out_bits { +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 73a52aba448f9..90c2d7f3c7a88 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1511,11 +1511,18 @@ static inline u8 page_kasan_tag(const struct page *page) + + static inline void page_kasan_tag_set(struct page *page, u8 tag) + { +- if (kasan_enabled()) { +- tag ^= 0xff; +- page->flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT); +- page->flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT; +- } ++ unsigned long old_flags, flags; ++ ++ if (!kasan_enabled()) ++ return; ++ ++ tag ^= 0xff; ++ old_flags = READ_ONCE(page->flags); ++ do { ++ flags = old_flags; ++ flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT); ++ flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT; ++ } while (unlikely(!try_cmpxchg(&page->flags, &old_flags, flags))); + } + + static inline void page_kasan_tag_reset(struct page *page) +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index 6a1d79d84675a..fa1ef98614bcb 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -1031,6 +1031,15 @@ static inline int is_highmem_idx(enum zone_type idx) + #endif + } + ++#ifdef CONFIG_ZONE_DMA ++bool has_managed_dma(void); ++#else ++static inline bool has_managed_dma(void) ++{ ++ return false; ++} ++#endif ++ + /** + * is_highmem - helper function to quickly check if a struct zone is a + * highmem zone or not. This is an attempt to keep references +diff --git a/include/linux/msi.h b/include/linux/msi.h +index 49cf6eb222e76..e616f94c7c585 100644 +--- a/include/linux/msi.h ++++ b/include/linux/msi.h +@@ -148,7 +148,7 @@ struct msi_desc { + u8 is_msix : 1; + u8 multiple : 3; + u8 multi_cap : 3; +- u8 maskbit : 1; ++ u8 can_mask : 1; + u8 is_64 : 1; + u8 is_virtual : 1; + u16 entry_nr; +diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h +index b2f9dd3cbd695..5b88cd51fadb5 100644 +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, + bool force_8bit, bool check_only); + int nand_write_data_op(struct nand_chip *chip, const void *buf, + unsigned int len, bool force_8bit); ++int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf, ++ int oob_required, int page); + + /* Scan and identify a NAND device */ + int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips, +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index d79163208dfdb..62ff094677762 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2149,7 +2149,7 @@ struct net_device { + struct netdev_queue *_tx ____cacheline_aligned_in_smp; + unsigned int num_tx_queues; + unsigned int real_num_tx_queues; +- struct Qdisc *qdisc; ++ struct Qdisc __rcu *qdisc; + unsigned int tx_queue_len; + spinlock_t tx_global_lock; + +@@ -2636,6 +2636,7 @@ struct packet_type { + struct net_device *); + bool (*id_match)(struct packet_type *ptype, + struct sock *sk); ++ struct net *af_packet_net; + void *af_packet_priv; + struct list_head list; + }; +@@ -4403,7 +4404,8 @@ static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) + static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu) + { + spin_lock(&txq->_xmit_lock); +- txq->xmit_lock_owner = cpu; ++ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ ++ WRITE_ONCE(txq->xmit_lock_owner, cpu); + } + + static inline bool __netif_tx_acquire(struct netdev_queue *txq) +@@ -4420,26 +4422,32 @@ static inline void __netif_tx_release(struct netdev_queue *txq) + static inline void __netif_tx_lock_bh(struct netdev_queue *txq) + { + spin_lock_bh(&txq->_xmit_lock); +- txq->xmit_lock_owner = smp_processor_id(); ++ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ ++ WRITE_ONCE(txq->xmit_lock_owner, smp_processor_id()); + } + + static inline bool __netif_tx_trylock(struct netdev_queue *txq) + { + bool ok = spin_trylock(&txq->_xmit_lock); +- if (likely(ok)) +- txq->xmit_lock_owner = smp_processor_id(); ++ ++ if (likely(ok)) { ++ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ ++ WRITE_ONCE(txq->xmit_lock_owner, smp_processor_id()); ++ } + return ok; + } + + static inline void __netif_tx_unlock(struct netdev_queue *txq) + { +- txq->xmit_lock_owner = -1; ++ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ ++ WRITE_ONCE(txq->xmit_lock_owner, -1); + spin_unlock(&txq->_xmit_lock); + } + + static inline void __netif_tx_unlock_bh(struct netdev_queue *txq) + { +- txq->xmit_lock_owner = -1; ++ /* Pairs with READ_ONCE() in __dev_queue_xmit() */ ++ WRITE_ONCE(txq->xmit_lock_owner, -1); + spin_unlock_bh(&txq->_xmit_lock); + } + +diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h +index b9a8b925db430..4a733f1409397 100644 +--- a/include/linux/nfs_fs.h ++++ b/include/linux/nfs_fs.h +@@ -517,8 +517,8 @@ extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, + struct nfs_fattr *fattr, struct nfs4_label *label); + extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags); + extern void nfs_access_zap_cache(struct inode *inode); +-extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, +- bool may_block); ++extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred, ++ u32 *mask, bool may_block); + + /* + * linux/fs/nfs/symlink.c +@@ -569,6 +569,7 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); + extern int nfs_commit_inode(struct inode *, int); + extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail); + extern void nfs_commit_free(struct nfs_commit_data *data); ++bool nfs_commit_end(struct nfs_mds_commit_info *cinfo); + + static inline int + nfs_have_writebacks(struct inode *inode) +diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h +index 2a9acbfe00f0f..9a6e70ccde56e 100644 +--- a/include/linux/nfs_fs_sb.h ++++ b/include/linux/nfs_fs_sb.h +@@ -287,5 +287,5 @@ struct nfs_server { + #define NFS_CAP_COPY_NOTIFY (1U << 27) + #define NFS_CAP_XATTR (1U << 28) + #define NFS_CAP_READ_PLUS (1U << 29) +- ++#define NFS_CAP_FS_LOCATIONS (1U << 30) + #endif +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index e9698b6278a52..ecd74cc347974 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -1805,6 +1805,7 @@ struct nfs_rpc_ops { + struct nfs_server *(*create_server)(struct fs_context *); + struct nfs_server *(*clone_server)(struct nfs_server *, struct nfs_fh *, + struct nfs_fattr *, rpc_authflavor_t); ++ int (*discover_trunking)(struct nfs_server *, struct nfs_fh *); + }; + + /* +diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h +index 104505e9028f7..87932bdb25d7b 100644 +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -66,7 +66,8 @@ struct nvmem_keepout { + * @word_size: Minimum read/write access granularity. + * @stride: Minimum read/write access stride. + * @priv: User context passed to read/write callbacks. +- * @wp-gpio: Write protect pin ++ * @wp-gpio: Write protect pin ++ * @ignore_wp: Write Protect pin is managed by the provider. + * + * Note: A default "nvmem<id>" name will be assigned to the device if + * no name is specified in its configuration. In such case "<id>" is +@@ -88,6 +89,7 @@ struct nvmem_config { + enum nvmem_type type; + bool read_only; + bool root_only; ++ bool ignore_wp; + struct device_node *of_node; + bool no_of_node; + nvmem_reg_read_t reg_read; +diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h +index cf6a65b94d40e..6508b97dbf1d2 100644 +--- a/include/linux/of_fdt.h ++++ b/include/linux/of_fdt.h +@@ -62,6 +62,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, + int depth, void *data); + extern int early_init_dt_scan_memory(unsigned long node, const char *uname, + int depth, void *data); ++extern void early_init_dt_check_for_usable_mem_range(void); + extern int early_init_dt_scan_chosen_stdout(void); + extern void early_init_fdt_scan_reserved_mem(void); + extern void early_init_fdt_reserve_self(void); +@@ -87,6 +88,7 @@ extern void unflatten_and_copy_device_tree(void); + extern void early_init_devtree(void *); + extern void early_get_first_memblock_info(void *, phys_addr_t *); + #else /* CONFIG_OF_EARLY_FLATTREE */ ++static inline void early_init_dt_check_for_usable_mem_range(void) {} + static inline int early_init_dt_scan_chosen_stdout(void) { return -ENODEV; } + static inline void early_init_fdt_scan_reserved_mem(void) {} + static inline void early_init_fdt_reserve_self(void) {} +diff --git a/include/linux/of_net.h b/include/linux/of_net.h +index daef3b0d9270d..55460ecfa50ad 100644 +--- a/include/linux/of_net.h ++++ b/include/linux/of_net.h +@@ -8,7 +8,7 @@ + + #include <linux/phy.h> + +-#ifdef CONFIG_OF_NET ++#if defined(CONFIG_OF) && defined(CONFIG_NET) + #include <linux/of.h> + + struct net_device; +diff --git a/include/linux/pci.h b/include/linux/pci.h +index cd8aa6fce2041..152a4d74f87f0 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -233,6 +233,8 @@ enum pci_dev_flags { + PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), + /* Don't use Relaxed Ordering for TLPs directed at this device */ + PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11), ++ /* Device does honor MSI masking despite saying otherwise */ ++ PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12), + }; + + enum pci_irq_reroute_variant { +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 9b60bb89d86ab..6cce33e7e7acc 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -680,18 +680,6 @@ struct perf_event { + u64 total_time_running; + u64 tstamp; + +- /* +- * timestamp shadows the actual context timing but it can +- * be safely used in NMI interrupt context. It reflects the +- * context time as it was when the event was last scheduled in, +- * or when ctx_sched_in failed to schedule the event because we +- * run out of PMC. +- * +- * ctx_time already accounts for ctx->timestamp. Therefore to +- * compute ctx_time for a sample, simply add perf_clock(). +- */ +- u64 shadow_ctx_time; +- + struct perf_event_attr attr; + u16 header_size; + u16 id_header_size; +@@ -838,6 +826,7 @@ struct perf_event_context { + */ + u64 time; + u64 timestamp; ++ u64 timeoffset; + + /* + * These fields let us detect when two contexts have both +@@ -920,6 +909,8 @@ struct bpf_perf_event_data_kern { + struct perf_cgroup_info { + u64 time; + u64 timestamp; ++ u64 timeoffset; ++ int active; + }; + + struct perf_cgroup { +@@ -1239,7 +1230,18 @@ extern void perf_event_bpf_event(struct bpf_prog *prog, + enum perf_bpf_event_type type, + u16 flags); + +-extern struct perf_guest_info_callbacks *perf_guest_cbs; ++extern struct perf_guest_info_callbacks __rcu *perf_guest_cbs; ++static inline struct perf_guest_info_callbacks *perf_get_guest_cbs(void) ++{ ++ /* ++ * Callbacks are RCU-protected and must be READ_ONCE to avoid reloading ++ * the callbacks between a !NULL check and dereferences, to ensure ++ * pending stores/changes to the callback pointers are visible before a ++ * non-NULL perf_guest_cbs is visible to readers, and to prevent a ++ * module from unloading callbacks while readers are active. ++ */ ++ return rcu_dereference(perf_guest_cbs); ++} + extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); + extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); + +diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h +index e24d2c992b112..d468efcf48f45 100644 +--- a/include/linux/pgtable.h ++++ b/include/linux/pgtable.h +@@ -62,6 +62,7 @@ static inline unsigned long pte_index(unsigned long address) + { + return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + } ++#define pte_index pte_index + + #ifndef pmd_index + static inline unsigned long pmd_index(unsigned long address) +diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h +index 9837fb011f2fb..989aa30c598dc 100644 +--- a/include/linux/platform_data/ti-sysc.h ++++ b/include/linux/platform_data/ti-sysc.h +@@ -50,6 +50,7 @@ struct sysc_regbits { + s8 emufree_shift; + }; + ++#define SYSC_QUIRK_REINIT_ON_CTX_LOST BIT(28) + #define SYSC_QUIRK_REINIT_ON_RESUME BIT(27) + #define SYSC_QUIRK_GPMC_DEBUG BIT(26) + #define SYSC_MODULE_QUIRK_ENA_RESETDONE BIT(25) +diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h +index 222da43b7096d..016de5776b6db 100644 +--- a/include/linux/pm_runtime.h ++++ b/include/linux/pm_runtime.h +@@ -58,6 +58,7 @@ extern void pm_runtime_get_suppliers(struct device *dev); + extern void pm_runtime_put_suppliers(struct device *dev); + extern void pm_runtime_new_link(struct device *dev); + extern void pm_runtime_drop_link(struct device_link *link); ++extern void pm_runtime_release_supplier(struct device_link *link, bool check_idle); + + extern int devm_pm_runtime_enable(struct device *dev); + +@@ -129,7 +130,7 @@ static inline bool pm_runtime_suspended(struct device *dev) + * pm_runtime_active - Check whether or not a device is runtime-active. + * @dev: Target device. + * +- * Return %true if runtime PM is enabled for @dev and its runtime PM status is ++ * Return %true if runtime PM is disabled for @dev or its runtime PM status is + * %RPM_ACTIVE, or %false otherwise. + * + * Note that the return value of this function can only be trusted if it is +@@ -283,6 +284,8 @@ static inline void pm_runtime_get_suppliers(struct device *dev) {} + static inline void pm_runtime_put_suppliers(struct device *dev) {} + static inline void pm_runtime_new_link(struct device *dev) {} + static inline void pm_runtime_drop_link(struct device_link *link) {} ++static inline void pm_runtime_release_supplier(struct device_link *link, ++ bool check_idle) {} + + #endif /* !CONFIG_PM */ + +diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h +index 00fef0064355f..5bbcd280bfd26 100644 +--- a/include/linux/posix-timers.h ++++ b/include/linux/posix-timers.h +@@ -184,8 +184,10 @@ static inline void posix_cputimers_group_init(struct posix_cputimers *pct, + #endif + + #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK ++void clear_posix_cputimers_work(struct task_struct *p); + void posix_cputimers_init_work(void); + #else ++static inline void clear_posix_cputimers_work(struct task_struct *p) { } + static inline void posix_cputimers_init_work(void) { } + #endif + +diff --git a/include/linux/printk.h b/include/linux/printk.h +index 85b656f82d752..9497f6b983399 100644 +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -198,6 +198,7 @@ void dump_stack_print_info(const char *log_lvl); + void show_regs_print_info(const char *log_lvl); + extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold; + extern asmlinkage void dump_stack(void) __cold; ++void printk_trigger_flush(void); + #else + static inline __printf(1, 0) + int vprintk(const char *s, va_list args) +@@ -274,6 +275,9 @@ static inline void dump_stack_lvl(const char *log_lvl) + static inline void dump_stack(void) + { + } ++static inline void printk_trigger_flush(void) ++{ ++} + #endif + + #ifdef CONFIG_SMP +diff --git a/include/linux/psi.h b/include/linux/psi.h +index 65eb1476ac705..57823b30c2d3d 100644 +--- a/include/linux/psi.h ++++ b/include/linux/psi.h +@@ -24,18 +24,17 @@ void psi_memstall_enter(unsigned long *flags); + void psi_memstall_leave(unsigned long *flags); + + int psi_show(struct seq_file *s, struct psi_group *group, enum psi_res res); +- +-#ifdef CONFIG_CGROUPS +-int psi_cgroup_alloc(struct cgroup *cgrp); +-void psi_cgroup_free(struct cgroup *cgrp); +-void cgroup_move_task(struct task_struct *p, struct css_set *to); +- + struct psi_trigger *psi_trigger_create(struct psi_group *group, + char *buf, size_t nbytes, enum psi_res res); +-void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *t); ++void psi_trigger_destroy(struct psi_trigger *t); + + __poll_t psi_trigger_poll(void **trigger_ptr, struct file *file, + poll_table *wait); ++ ++#ifdef CONFIG_CGROUPS ++int psi_cgroup_alloc(struct cgroup *cgrp); ++void psi_cgroup_free(struct cgroup *cgrp); ++void cgroup_move_task(struct task_struct *p, struct css_set *to); + #endif + + #else /* CONFIG_PSI */ +diff --git a/include/linux/psi_types.h b/include/linux/psi_types.h +index 0a23300d49af7..6f190002a2022 100644 +--- a/include/linux/psi_types.h ++++ b/include/linux/psi_types.h +@@ -21,7 +21,17 @@ enum psi_task_count { + * don't have to special case any state tracking for it. + */ + NR_ONCPU, +- NR_PSI_TASK_COUNTS = 4, ++ /* ++ * For IO and CPU stalls the presence of running/oncpu tasks ++ * in the domain means a partial rather than a full stall. ++ * For memory it's not so simple because of page reclaimers: ++ * they are running/oncpu while representing a stall. To tell ++ * whether a domain has productivity left or not, we need to ++ * distinguish between regular running (i.e. productive) ++ * threads and memstall ones. ++ */ ++ NR_MEMSTALL_RUNNING, ++ NR_PSI_TASK_COUNTS = 5, + }; + + /* Task state bitmasks */ +@@ -29,6 +39,7 @@ enum psi_task_count { + #define TSK_MEMSTALL (1 << NR_MEMSTALL) + #define TSK_RUNNING (1 << NR_RUNNING) + #define TSK_ONCPU (1 << NR_ONCPU) ++#define TSK_MEMSTALL_RUNNING (1 << NR_MEMSTALL_RUNNING) + + /* Resources that workloads could be stalled on */ + enum psi_res { +@@ -129,9 +140,6 @@ struct psi_trigger { + * events to one per window + */ + u64 last_event_time; +- +- /* Refcounting to prevent premature destruction */ +- struct kref refcount; + }; + + struct psi_group { +diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h +index 2e5565067355b..554454cb86931 100644 +--- a/include/linux/ptp_clock_kernel.h ++++ b/include/linux/ptp_clock_kernel.h +@@ -351,15 +351,17 @@ int ptp_get_vclocks_index(int pclock_index, int **vclock_index); + * + * @hwtstamps: skb_shared_hwtstamps structure pointer + * @vclock_index: phc index of ptp vclock. ++ * ++ * Returns converted timestamp, or 0 on error. + */ +-void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps, +- int vclock_index); ++ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps, ++ int vclock_index); + #else + static inline int ptp_get_vclocks_index(int pclock_index, int **vclock_index) + { return 0; } +-static inline void ptp_convert_timestamp(struct skb_shared_hwtstamps *hwtstamps, +- int vclock_index) +-{ } ++static inline ktime_t ptp_convert_timestamp(const struct skb_shared_hwtstamps *hwtstamps, ++ int vclock_index) ++{ return 0; } + + #endif + +diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h +index d97dcd049f18f..a8dcf8a9ae885 100644 +--- a/include/linux/rpmsg.h ++++ b/include/linux/rpmsg.h +@@ -231,7 +231,7 @@ static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev + /* This shouldn't be possible */ + WARN_ON(1); + +- return ERR_PTR(-ENXIO); ++ return NULL; + } + + static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) +diff --git a/include/linux/sched.h b/include/linux/sched.h +index c1a927ddec646..76e8695506465 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1675,7 +1675,6 @@ extern struct pid *cad_pid; + #define PF_MEMALLOC 0x00000800 /* Allocating memory */ + #define PF_NPROC_EXCEEDED 0x00001000 /* set_user() noticed that RLIMIT_NPROC was exceeded */ + #define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */ +-#define PF_USED_ASYNC 0x00004000 /* Used async_schedule*(), used by module init */ + #define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */ + #define PF_FROZEN 0x00010000 /* Frozen for system suspend */ + #define PF_KSWAPD 0x00020000 /* I am kswapd */ +diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h +index e5f4ce622ee61..9a707b555b0a0 100644 +--- a/include/linux/sched/signal.h ++++ b/include/linux/sched/signal.h +@@ -338,6 +338,8 @@ extern int kill_pid(struct pid *pid, int sig, int priv); + extern __must_check bool do_notify_parent(struct task_struct *, int); + extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); + extern void force_sig(int); ++extern void force_fatal_sig(int); ++extern void force_exit_sig(int); + extern int send_sig(int, struct task_struct *, int); + extern int zap_other_threads(struct task_struct *p); + extern struct sigqueue *sigqueue_alloc(void); +diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h +index ef02be869cf28..8db25fcc1eba7 100644 +--- a/include/linux/sched/task.h ++++ b/include/linux/sched/task.h +@@ -54,6 +54,7 @@ extern asmlinkage void schedule_tail(struct task_struct *prev); + extern void init_idle(struct task_struct *idle, int cpu); + + extern int sched_fork(unsigned long clone_flags, struct task_struct *p); ++extern void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs); + extern void sched_post_fork(struct task_struct *p); + extern void sched_dead(struct task_struct *p); + +@@ -157,7 +158,7 @@ static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) + * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring + * subscriptions and synchronises with wait4(). Also used in procfs. Also + * pins the final release of task.io_context. Also protects ->cpuset and +- * ->cgroup.subsys[]. And ->vfork_done. ++ * ->cgroup.subsys[]. And ->vfork_done. And ->sysvshm.shm_clist. + * + * Nests both inside and outside of read_lock(&tasklist_lock). + * It must not be nested with write_lock_irq(&tasklist_lock), +diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h +index 2413427e439c7..d10150587d819 100644 +--- a/include/linux/sched/task_stack.h ++++ b/include/linux/sched/task_stack.h +@@ -25,7 +25,11 @@ static inline void *task_stack_page(const struct task_struct *task) + + static inline unsigned long *end_of_stack(const struct task_struct *task) + { ++#ifdef CONFIG_STACK_GROWSUP ++ return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1; ++#else + return task->stack; ++#endif + } + + #elif !defined(__HAVE_THREAD_FUNCTIONS) +diff --git a/include/linux/security.h b/include/linux/security.h +index 5b7288521300b..46a02ce34d00b 100644 +--- a/include/linux/security.h ++++ b/include/linux/security.h +@@ -258,13 +258,13 @@ extern int security_init(void); + extern int early_security_init(void); + + /* Security operations */ +-int security_binder_set_context_mgr(struct task_struct *mgr); +-int security_binder_transaction(struct task_struct *from, +- struct task_struct *to); +-int security_binder_transfer_binder(struct task_struct *from, +- struct task_struct *to); +-int security_binder_transfer_file(struct task_struct *from, +- struct task_struct *to, struct file *file); ++int security_binder_set_context_mgr(const struct cred *mgr); ++int security_binder_transaction(const struct cred *from, ++ const struct cred *to); ++int security_binder_transfer_binder(const struct cred *from, ++ const struct cred *to); ++int security_binder_transfer_file(const struct cred *from, ++ const struct cred *to, struct file *file); + int security_ptrace_access_check(struct task_struct *child, unsigned int mode); + int security_ptrace_traceme(struct task_struct *parent); + int security_capget(struct task_struct *target, +@@ -508,25 +508,25 @@ static inline int early_security_init(void) + return 0; + } + +-static inline int security_binder_set_context_mgr(struct task_struct *mgr) ++static inline int security_binder_set_context_mgr(const struct cred *mgr) + { + return 0; + } + +-static inline int security_binder_transaction(struct task_struct *from, +- struct task_struct *to) ++static inline int security_binder_transaction(const struct cred *from, ++ const struct cred *to) + { + return 0; + } + +-static inline int security_binder_transfer_binder(struct task_struct *from, +- struct task_struct *to) ++static inline int security_binder_transfer_binder(const struct cred *from, ++ const struct cred *to) + { + return 0; + } + +-static inline int security_binder_transfer_file(struct task_struct *from, +- struct task_struct *to, ++static inline int security_binder_transfer_file(const struct cred *from, ++ const struct cred *to, + struct file *file) + { + return 0; +@@ -1041,6 +1041,11 @@ static inline void security_transfer_creds(struct cred *new, + { + } + ++static inline void security_cred_getsecid(const struct cred *c, u32 *secid) ++{ ++ *secid = 0; ++} ++ + static inline int security_kernel_act_as(struct cred *cred, u32 secid) + { + return 0; +diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h +index dd99569595fd3..5733890df64f5 100644 +--- a/include/linux/seq_file.h ++++ b/include/linux/seq_file.h +@@ -194,7 +194,7 @@ static const struct file_operations __name ## _fops = { \ + #define DEFINE_PROC_SHOW_ATTRIBUTE(__name) \ + static int __name ## _open(struct inode *inode, struct file *file) \ + { \ +- return single_open(file, __name ## _show, inode->i_private); \ ++ return single_open(file, __name ## _show, PDE_DATA(inode)); \ + } \ + \ + static const struct proc_ops __name ## _proc_ops = { \ +diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h +index 34cb28b8f16ca..a70b2bdbf4d96 100644 +--- a/include/linux/signal_types.h ++++ b/include/linux/signal_types.h +@@ -70,6 +70,9 @@ struct ksignal { + int sig; + }; + ++/* Used to kill the race between sigaction and forced signals */ ++#define SA_IMMUTABLE 0x00800000 ++ + #ifndef __ARCH_UAPI_SA_FLAGS + #ifdef SA_RESTORER + #define __ARCH_UAPI_SA_FLAGS SA_RESTORER +diff --git a/include/linux/siphash.h b/include/linux/siphash.h +index bf21591a9e5e6..0cda61855d907 100644 +--- a/include/linux/siphash.h ++++ b/include/linux/siphash.h +@@ -27,9 +27,7 @@ static inline bool siphash_key_is_zero(const siphash_key_t *key) + } + + u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key); +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key); +-#endif + + u64 siphash_1u64(const u64 a, const siphash_key_t *key); + u64 siphash_2u64(const u64 a, const u64 b, const siphash_key_t *key); +@@ -82,10 +80,9 @@ static inline u64 ___siphash_aligned(const __le64 *data, size_t len, + static inline u64 siphash(const void *data, size_t len, + const siphash_key_t *key) + { +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +- if (!IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) ++ if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || ++ !IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) + return __siphash_unaligned(data, len, key); +-#endif + return ___siphash_aligned(data, len, key); + } + +@@ -96,10 +93,8 @@ typedef struct { + + u32 __hsiphash_aligned(const void *data, size_t len, + const hsiphash_key_t *key); +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u32 __hsiphash_unaligned(const void *data, size_t len, + const hsiphash_key_t *key); +-#endif + + u32 hsiphash_1u32(const u32 a, const hsiphash_key_t *key); + u32 hsiphash_2u32(const u32 a, const u32 b, const hsiphash_key_t *key); +@@ -135,10 +130,9 @@ static inline u32 ___hsiphash_aligned(const __le32 *data, size_t len, + static inline u32 hsiphash(const void *data, size_t len, + const hsiphash_key_t *key) + { +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +- if (!IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) ++ if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || ++ !IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) + return __hsiphash_unaligned(data, len, key); +-#endif + return ___hsiphash_aligned(data, len, key); + } + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 841e2f0f5240b..532f5d402f060 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -286,7 +286,10 @@ struct nf_bridge_info { + struct tc_skb_ext { + __u32 chain; + __u16 mru; +- bool post_ct; ++ __u16 zone; ++ u8 post_ct:1; ++ u8 post_ct_snat:1; ++ u8 post_ct_dnat:1; + }; + #endif + +@@ -1370,7 +1373,7 @@ skb_flow_dissect_ct(const struct sk_buff *skb, + struct flow_dissector *flow_dissector, + void *target_container, + u16 *ctinfo_map, size_t mapsize, +- bool post_ct); ++ bool post_ct, u16 zone); + void + skb_flow_dissect_tunnel_info(const struct sk_buff *skb, + struct flow_dissector *flow_dissector, +@@ -1671,6 +1674,22 @@ static inline int skb_unclone(struct sk_buff *skb, gfp_t pri) + return 0; + } + ++/* This variant of skb_unclone() makes sure skb->truesize is not changed */ ++static inline int skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri) ++{ ++ might_sleep_if(gfpflags_allow_blocking(pri)); ++ ++ if (skb_cloned(skb)) { ++ unsigned int save = skb->truesize; ++ int res; ++ ++ res = pskb_expand_head(skb, 0, 0, pri); ++ skb->truesize = save; ++ return res; ++ } ++ return 0; ++} ++ + /** + * skb_header_cloned - is the header a clone + * @skb: buffer to check +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 1ce9a9eb223b6..b4256847c7079 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -509,8 +509,22 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock) + + #if IS_ENABLED(CONFIG_NET_SOCK_MSG) + +-/* We only have one bit so far. */ +-#define BPF_F_PTR_MASK ~(BPF_F_INGRESS) ++#define BPF_F_STRPARSER (1UL << 1) ++ ++/* We only have two bits so far. */ ++#define BPF_F_PTR_MASK ~(BPF_F_INGRESS | BPF_F_STRPARSER) ++ ++static inline bool skb_bpf_strparser(const struct sk_buff *skb) ++{ ++ unsigned long sk_redir = skb->_sk_redir; ++ ++ return sk_redir & BPF_F_STRPARSER; ++} ++ ++static inline void skb_bpf_set_strparser(struct sk_buff *skb) ++{ ++ skb->_sk_redir |= BPF_F_STRPARSER; ++} + + static inline bool skb_bpf_ingress(const struct sk_buff *skb) + { +diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h +index a6f03b36fc4f7..1450397fc0bcd 100644 +--- a/include/linux/stmmac.h ++++ b/include/linux/stmmac.h +@@ -233,6 +233,7 @@ struct plat_stmmacenet_data { + int (*clks_config)(void *priv, bool enabled); + int (*crosststamp)(ktime_t *device, struct system_counterval_t *system, + void *ctx); ++ void (*dump_debug_regs)(void *priv); + void *bsp_priv; + struct clk *stmmac_clk; + struct clk *pclk; +diff --git a/include/linux/string.h b/include/linux/string.h +index 5e96d656be7ae..d68097b4f600b 100644 +--- a/include/linux/string.h ++++ b/include/linux/string.h +@@ -262,23 +262,8 @@ void __write_overflow(void) __compiletime_error("detected write beyond size of o + #include <linux/fortify-string.h> + #endif + +-/** +- * memcpy_and_pad - Copy one buffer to another with padding +- * @dest: Where to copy to +- * @dest_len: The destination buffer size +- * @src: Where to copy from +- * @count: The number of bytes to copy +- * @pad: Character to use for padding if space is left in destination. +- */ +-static inline void memcpy_and_pad(void *dest, size_t dest_len, +- const void *src, size_t count, int pad) +-{ +- if (dest_len > count) { +- memcpy(dest, src, count); +- memset(dest + count, pad, dest_len - count); +- } else +- memcpy(dest, src, dest_len); +-} ++void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, ++ int pad); + + /** + * str_has_prefix - Test if a string has a given prefix +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index 064c96157d1f0..6263410c948a0 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -532,8 +532,7 @@ int svc_encode_result_payload(struct svc_rqst *rqstp, + unsigned int offset, + unsigned int length); + unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, +- struct page **pages, +- struct kvec *first, size_t total); ++ struct xdr_buf *payload); + char *svc_fill_symlink_pathname(struct svc_rqst *rqstp, + struct kvec *first, void *p, + size_t total); +diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h +index 068e1982ad371..74bfdffaf7b0e 100644 +--- a/include/linux/surface_aggregator/controller.h ++++ b/include/linux/surface_aggregator/controller.h +@@ -792,8 +792,8 @@ enum ssam_event_mask { + #define SSAM_EVENT_REGISTRY_KIP \ + SSAM_EVENT_REGISTRY(SSAM_SSH_TC_KIP, 0x02, 0x27, 0x28) + +-#define SSAM_EVENT_REGISTRY_REG \ +- SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02) ++#define SSAM_EVENT_REGISTRY_REG(tid)\ ++ SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, tid, 0x01, 0x02) + + /** + * enum ssam_event_notifier_flags - Flags for event notifiers. +diff --git a/include/linux/suspend.h b/include/linux/suspend.h +index 8af13ba60c7e4..4bcd65679cee0 100644 +--- a/include/linux/suspend.h ++++ b/include/linux/suspend.h +@@ -430,15 +430,7 @@ struct platform_hibernation_ops { + + #ifdef CONFIG_HIBERNATION + /* kernel/power/snapshot.c */ +-extern void __register_nosave_region(unsigned long b, unsigned long e, int km); +-static inline void __init register_nosave_region(unsigned long b, unsigned long e) +-{ +- __register_nosave_region(b, e, 0); +-} +-static inline void __init register_nosave_region_late(unsigned long b, unsigned long e) +-{ +- __register_nosave_region(b, e, 1); +-} ++extern void register_nosave_region(unsigned long b, unsigned long e); + extern int swsusp_page_is_forbidden(struct page *); + extern void swsusp_set_page_free(struct page *); + extern void swsusp_unset_page_free(struct page *); +@@ -457,7 +449,6 @@ int pfn_is_nosave(unsigned long pfn); + int hibernate_quiet_exec(int (*func)(void *data), void *data); + #else /* CONFIG_HIBERNATION */ + static inline void register_nosave_region(unsigned long b, unsigned long e) {} +-static inline void register_nosave_region_late(unsigned long b, unsigned long e) {} + static inline int swsusp_page_is_forbidden(struct page *p) { return 0; } + static inline void swsusp_set_page_free(struct page *p) {} + static inline void swsusp_unset_page_free(struct page *p) {} +@@ -505,14 +496,14 @@ extern void ksys_sync_helper(void); + + /* drivers/base/power/wakeup.c */ + extern bool events_check_enabled; +-extern unsigned int pm_wakeup_irq; + extern suspend_state_t pm_suspend_target_state; + + extern bool pm_wakeup_pending(void); + extern void pm_system_wakeup(void); + extern void pm_system_cancel_wakeup(void); +-extern void pm_wakeup_clear(bool reset); ++extern void pm_wakeup_clear(unsigned int irq_number); + extern void pm_system_irq_wakeup(unsigned int irq_number); ++extern unsigned int pm_wakeup_irq(void); + extern bool pm_get_wakeup_count(unsigned int *count, bool block); + extern bool pm_save_wakeup_count(unsigned int count); + extern void pm_wakep_autosleep_enabled(bool set); +diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h +index 3ebfea0781f10..38b701b7af4cf 100644 +--- a/include/linux/tee_drv.h ++++ b/include/linux/tee_drv.h +@@ -195,7 +195,7 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, + * @offset: offset of buffer in user space + * @pages: locked pages from userspace + * @num_pages: number of locked pages +- * @dmabuf: dmabuf used to for exporting to user space ++ * @refcount: reference counter + * @flags: defined by TEE_SHM_* in tee_drv.h + * @id: unique id of a shared memory object on this device + * +@@ -210,7 +210,7 @@ struct tee_shm { + unsigned int offset; + struct page **pages; + size_t num_pages; +- struct dma_buf *dmabuf; ++ refcount_t refcount; + u32 flags; + int id; + }; +@@ -582,4 +582,18 @@ struct tee_client_driver { + #define to_tee_client_driver(d) \ + container_of(d, struct tee_client_driver, driver) + ++/** ++ * teedev_open() - Open a struct tee_device ++ * @teedev: Device to open ++ * ++ * @return a pointer to struct tee_context on success or an ERR_PTR on failure. ++ */ ++struct tee_context *teedev_open(struct tee_device *teedev); ++ ++/** ++ * teedev_close_context() - closes a struct tee_context ++ * @ctx: The struct tee_context to close ++ */ ++void teedev_close_context(struct tee_context *ctx); ++ + #endif /*__TEE_DRV_H*/ +diff --git a/include/linux/tpm.h b/include/linux/tpm.h +index aa11fe323c56b..12d827734686d 100644 +--- a/include/linux/tpm.h ++++ b/include/linux/tpm.h +@@ -269,6 +269,7 @@ enum tpm2_cc_attrs { + #define TPM_VID_INTEL 0x8086 + #define TPM_VID_WINBOND 0x1050 + #define TPM_VID_STM 0x104A ++#define TPM_VID_ATML 0x1114 + + enum tpm_chip_flags { + TPM_CHIP_FLAG_TPM2 = BIT(1), +diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h +index 3e475eeb5a995..57113190448c6 100644 +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -673,7 +673,7 @@ struct trace_event_file { + + #define PERF_MAX_TRACE_SIZE 2048 + +-#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ ++#define MAX_FILTER_STR_VAL 256U /* Should handle KSYM_SYMBOL_LEN */ + + enum event_trigger_type { + ETT_NONE = (0), +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index 2c1fc9212cf28..548a028f2dabb 100644 +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -124,7 +124,6 @@ struct usb_hcd { + #define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ + #define HCD_FLAG_DEAD 6 /* controller has died? */ + #define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */ +-#define HCD_FLAG_DEFER_RH_REGISTER 8 /* Defer roothub registration */ + + /* The flags can be tested using these macros; they are likely to + * be slightly faster than test_bit(). +@@ -135,7 +134,6 @@ struct usb_hcd { + #define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING)) + #define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING)) + #define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD)) +-#define HCD_DEFER_RH_REGISTER(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEFER_RH_REGISTER)) + + /* + * Specifies if interfaces are authorized by default +diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h +index 031f148ab3734..b5deafd91f67b 100644 +--- a/include/linux/usb/role.h ++++ b/include/linux/usb/role.h +@@ -91,6 +91,12 @@ fwnode_usb_role_switch_get(struct fwnode_handle *node) + + static inline void usb_role_switch_put(struct usb_role_switch *sw) { } + ++static inline struct usb_role_switch * ++usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode) ++{ ++ return NULL; ++} ++ + static inline struct usb_role_switch * + usb_role_switch_register(struct device *parent, + const struct usb_role_switch_desc *desc) +diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h +index b465f8f3e554f..a960de68ac69e 100644 +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -7,9 +7,27 @@ + #include <uapi/linux/udp.h> + #include <uapi/linux/virtio_net.h> + ++static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type) ++{ ++ switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { ++ case VIRTIO_NET_HDR_GSO_TCPV4: ++ return protocol == cpu_to_be16(ETH_P_IP); ++ case VIRTIO_NET_HDR_GSO_TCPV6: ++ return protocol == cpu_to_be16(ETH_P_IPV6); ++ case VIRTIO_NET_HDR_GSO_UDP: ++ return protocol == cpu_to_be16(ETH_P_IP) || ++ protocol == cpu_to_be16(ETH_P_IPV6); ++ default: ++ return false; ++ } ++} ++ + static inline int virtio_net_hdr_set_proto(struct sk_buff *skb, + const struct virtio_net_hdr *hdr) + { ++ if (skb->protocol) ++ return 0; ++ + switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { + case VIRTIO_NET_HDR_GSO_TCPV4: + case VIRTIO_NET_HDR_GSO_UDP: +@@ -88,9 +106,12 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + if (!skb->protocol) { + __be16 protocol = dev_parse_header_protocol(skb); + +- virtio_net_hdr_set_proto(skb, hdr); +- if (protocol && protocol != skb->protocol) ++ if (!protocol) ++ virtio_net_hdr_set_proto(skb, hdr); ++ else if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type)) + return -EINVAL; ++ else ++ skb->protocol = protocol; + } + retry: + if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys, +@@ -120,10 +141,15 @@ retry: + + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); ++ unsigned int nh_off = p_off; + struct skb_shared_info *shinfo = skb_shinfo(skb); + ++ /* UFO may not include transport header in gso_size. */ ++ if (gso_type & SKB_GSO_UDP) ++ nh_off -= thlen; ++ + /* Too small packets are not really GSO ones. */ +- if (skb->len - p_off > gso_size) { ++ if (skb->len - nh_off > gso_size) { + shinfo->gso_size = gso_size; + shinfo->gso_type = gso_type; + +diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h +index 671d402c3778f..4fe9e885bbfac 100644 +--- a/include/linux/vmalloc.h ++++ b/include/linux/vmalloc.h +@@ -28,6 +28,13 @@ struct notifier_block; /* in notifier.h */ + #define VM_MAP_PUT_PAGES 0x00000200 /* put pages and free array in vfree */ + #define VM_NO_HUGE_VMAP 0x00000400 /* force PAGE_SIZE pte mapping */ + ++#if (defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) && \ ++ !defined(CONFIG_KASAN_VMALLOC) ++#define VM_DEFER_KMEMLEAK 0x00000800 /* defer kmemleak object creation */ ++#else ++#define VM_DEFER_KMEMLEAK 0 ++#endif ++ + /* + * VM_KASAN is used slightly differently depending on CONFIG_KASAN_VMALLOC. + * +diff --git a/include/linux/wait.h b/include/linux/wait.h +index 93dab0e9580f8..d22cf2985b8fd 100644 +--- a/include/linux/wait.h ++++ b/include/linux/wait.h +@@ -217,6 +217,7 @@ void __wake_up_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void + void __wake_up_locked_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void *key); + void __wake_up_locked(struct wait_queue_head *wq_head, unsigned int mode, int nr); + void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); ++void __wake_up_pollfree(struct wait_queue_head *wq_head); + + #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) + #define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL) +@@ -245,6 +246,31 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); + #define wake_up_interruptible_sync_poll_locked(x, m) \ + __wake_up_locked_sync_key((x), TASK_INTERRUPTIBLE, poll_to_key(m)) + ++/** ++ * wake_up_pollfree - signal that a polled waitqueue is going away ++ * @wq_head: the wait queue head ++ * ++ * In the very rare cases where a ->poll() implementation uses a waitqueue whose ++ * lifetime is tied to a task rather than to the 'struct file' being polled, ++ * this function must be called before the waitqueue is freed so that ++ * non-blocking polls (e.g. epoll) are notified that the queue is going away. ++ * ++ * The caller must also RCU-delay the freeing of the wait_queue_head, e.g. via ++ * an explicit synchronize_rcu() or call_rcu(), or via SLAB_TYPESAFE_BY_RCU. ++ */ ++static inline void wake_up_pollfree(struct wait_queue_head *wq_head) ++{ ++ /* ++ * For performance reasons, we don't always take the queue lock here. ++ * Therefore, we might race with someone removing the last entry from ++ * the queue, and proceed while they still hold the queue lock. ++ * However, rcu_read_lock() is required to be held in such cases, so we ++ * can safely proceed with an RCU-delayed free. ++ */ ++ if (waitqueue_active(wq_head)) ++ __wake_up_pollfree(wq_head); ++} ++ + #define ___wait_cond_timeout(condition) \ + ({ \ + bool __cond = (condition); \ +diff --git a/include/media/cec.h b/include/media/cec.h +index 208c9613c07eb..77346f757036d 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -26,13 +26,17 @@ + * @dev: cec device + * @cdev: cec character device + * @minor: device node minor number ++ * @lock: lock to serialize open/release and registration + * @registered: the device was correctly registered + * @unregistered: the device was unregistered ++ * @lock_fhs: lock to control access to @fhs + * @fhs: the list of open filehandles (cec_fh) +- * @lock: lock to control access to this structure + * + * This structure represents a cec-related device node. + * ++ * To add or remove filehandles from @fhs the @lock must be taken first, ++ * followed by @lock_fhs. It is safe to access @fhs if either lock is held. ++ * + * The @parent is a physical device. It must be set by core or device drivers + * before registering the node. + */ +@@ -43,10 +47,13 @@ struct cec_devnode { + + /* device info */ + int minor; ++ /* serialize open/release and registration */ ++ struct mutex lock; + bool registered; + bool unregistered; ++ /* protect access to fhs */ ++ struct mutex lock_fhs; + struct list_head fhs; +- struct mutex lock; + }; + + struct cec_adapter; +diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h +index 12955cb460d23..3b5986cee0739 100644 +--- a/include/media/videobuf2-core.h ++++ b/include/media/videobuf2-core.h +@@ -46,6 +46,7 @@ enum vb2_memory { + + struct vb2_fileio_data; + struct vb2_threadio_data; ++struct vb2_buffer; + + /** + * struct vb2_mem_ops - memory handling/memory allocator operations. +@@ -53,10 +54,8 @@ struct vb2_threadio_data; + * return ERR_PTR() on failure or a pointer to allocator private, + * per-buffer data on success; the returned private structure + * will then be passed as @buf_priv argument to other ops in this +- * structure. Additional gfp_flags to use when allocating the +- * are also passed to this operation. These flags are from the +- * gfp_flags field of vb2_queue. The size argument to this function +- * shall be *page aligned*. ++ * structure. The size argument to this function shall be ++ * *page aligned*. + * @put: inform the allocator that the buffer will no longer be used; + * usually will result in the allocator freeing the buffer (if + * no other users of this buffer are present); the @buf_priv +@@ -117,31 +116,33 @@ struct vb2_threadio_data; + * map_dmabuf, unmap_dmabuf. + */ + struct vb2_mem_ops { +- void *(*alloc)(struct device *dev, unsigned long attrs, +- unsigned long size, +- enum dma_data_direction dma_dir, +- gfp_t gfp_flags); ++ void *(*alloc)(struct vb2_buffer *vb, ++ struct device *dev, ++ unsigned long size); + void (*put)(void *buf_priv); +- struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags); +- +- void *(*get_userptr)(struct device *dev, unsigned long vaddr, +- unsigned long size, +- enum dma_data_direction dma_dir); ++ struct dma_buf *(*get_dmabuf)(struct vb2_buffer *vb, ++ void *buf_priv, ++ unsigned long flags); ++ ++ void *(*get_userptr)(struct vb2_buffer *vb, ++ struct device *dev, ++ unsigned long vaddr, ++ unsigned long size); + void (*put_userptr)(void *buf_priv); + + void (*prepare)(void *buf_priv); + void (*finish)(void *buf_priv); + +- void *(*attach_dmabuf)(struct device *dev, ++ void *(*attach_dmabuf)(struct vb2_buffer *vb, ++ struct device *dev, + struct dma_buf *dbuf, +- unsigned long size, +- enum dma_data_direction dma_dir); ++ unsigned long size); + void (*detach_dmabuf)(void *buf_priv); + int (*map_dmabuf)(void *buf_priv); + void (*unmap_dmabuf)(void *buf_priv); + +- void *(*vaddr)(void *buf_priv); +- void *(*cookie)(void *buf_priv); ++ void *(*vaddr)(struct vb2_buffer *vb, void *buf_priv); ++ void *(*cookie)(struct vb2_buffer *vb, void *buf_priv); + + unsigned int (*num_users)(void *buf_priv); + +diff --git a/include/memory/renesas-rpc-if.h b/include/memory/renesas-rpc-if.h +index e3e770f76f349..77c694a19149d 100644 +--- a/include/memory/renesas-rpc-if.h ++++ b/include/memory/renesas-rpc-if.h +@@ -59,6 +59,7 @@ struct rpcif_op { + + struct rpcif { + struct device *dev; ++ void __iomem *base; + void __iomem *dirmap; + struct regmap *regmap; + struct reset_control *rstc; +diff --git a/include/net/addrconf.h b/include/net/addrconf.h +index 78ea3e332688f..59940e230b782 100644 +--- a/include/net/addrconf.h ++++ b/include/net/addrconf.h +@@ -6,6 +6,8 @@ + #define RTR_SOLICITATION_INTERVAL (4*HZ) + #define RTR_SOLICITATION_MAX_INTERVAL (3600*HZ) /* 1 hour */ + ++#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */ ++ + #define TEMP_VALID_LIFETIME (7*86400) + #define TEMP_PREFERRED_LIFETIME (86400) + #define REGEN_MAX_RETRY (3) +@@ -107,8 +109,6 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, + int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev, + const struct in6_addr *daddr, unsigned int srcprefs, + struct in6_addr *saddr); +-int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, +- u32 banned_flags); + int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, + u32 banned_flags); + bool inet_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index b80415011dcd5..9ce46cb8564d6 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -246,6 +246,15 @@ enum { + * HCI after resume. + */ + HCI_QUIRK_NO_SUSPEND_NOTIFIER, ++ ++ /* ++ * When this quirk is set, LE tx power is not queried on startup ++ * and the min/max tx power values default to HCI_TX_POWER_INVALID. ++ * ++ * This quirk can be set before hci_register_dev is called or ++ * during the hdev->setup vendor callback. ++ */ ++ HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, + }; + + /* HCI device flags */ +diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h +index 38785d48baff9..184105d682942 100644 +--- a/include/net/bond_3ad.h ++++ b/include/net/bond_3ad.h +@@ -262,7 +262,7 @@ struct ad_system { + struct ad_bond_info { + struct ad_system system; /* 802.3ad system structure */ + struct bond_3ad_stats stats; +- u32 agg_select_timer; /* Timer to select aggregator after all adapter's hand shakes */ ++ atomic_t agg_select_timer; /* Timer to select aggregator after all adapter's hand shakes */ + u16 aggregator_identifier; + }; + +diff --git a/include/net/bond_alb.h b/include/net/bond_alb.h +index f6af76c87a6c3..191c36afa1f4a 100644 +--- a/include/net/bond_alb.h ++++ b/include/net/bond_alb.h +@@ -126,7 +126,7 @@ struct tlb_slave_info { + struct alb_bond_info { + struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */ + u32 unbalanced_load; +- int tx_rebalance_counter; ++ atomic_t tx_rebalance_counter; + int lp_counter; + /* -------- rlb parameters -------- */ + int rlb_enabled; +diff --git a/include/net/checksum.h b/include/net/checksum.h +index 5b96d5bd6e545..d3b5d368a0caa 100644 +--- a/include/net/checksum.h ++++ b/include/net/checksum.h +@@ -22,7 +22,7 @@ + #include <asm/checksum.h> + + #ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER +-static inline ++static __always_inline + __wsum csum_and_copy_from_user (const void __user *src, void *dst, + int len) + { +@@ -33,7 +33,7 @@ __wsum csum_and_copy_from_user (const void __user *src, void *dst, + #endif + + #ifndef HAVE_CSUM_COPY_USER +-static __inline__ __wsum csum_and_copy_to_user ++static __always_inline __wsum csum_and_copy_to_user + (const void *src, void __user *dst, int len) + { + __wsum sum = csum_partial(src, len, ~0U); +@@ -45,7 +45,7 @@ static __inline__ __wsum csum_and_copy_to_user + #endif + + #ifndef _HAVE_ARCH_CSUM_AND_COPY +-static inline __wsum ++static __always_inline __wsum + csum_partial_copy_nocheck(const void *src, void *dst, int len) + { + memcpy(dst, src, len); +@@ -54,7 +54,7 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len) + #endif + + #ifndef HAVE_ARCH_CSUM_ADD +-static inline __wsum csum_add(__wsum csum, __wsum addend) ++static __always_inline __wsum csum_add(__wsum csum, __wsum addend) + { + u32 res = (__force u32)csum; + res += (__force u32)addend; +@@ -62,12 +62,12 @@ static inline __wsum csum_add(__wsum csum, __wsum addend) + } + #endif + +-static inline __wsum csum_sub(__wsum csum, __wsum addend) ++static __always_inline __wsum csum_sub(__wsum csum, __wsum addend) + { + return csum_add(csum, ~addend); + } + +-static inline __sum16 csum16_add(__sum16 csum, __be16 addend) ++static __always_inline __sum16 csum16_add(__sum16 csum, __be16 addend) + { + u16 res = (__force u16)csum; + +@@ -75,12 +75,12 @@ static inline __sum16 csum16_add(__sum16 csum, __be16 addend) + return (__force __sum16)(res + (res < (__force u16)addend)); + } + +-static inline __sum16 csum16_sub(__sum16 csum, __be16 addend) ++static __always_inline __sum16 csum16_sub(__sum16 csum, __be16 addend) + { + return csum16_add(csum, ~addend); + } + +-static inline __wsum csum_shift(__wsum sum, int offset) ++static __always_inline __wsum csum_shift(__wsum sum, int offset) + { + /* rotate sum to align it with a 16b boundary */ + if (offset & 1) +@@ -88,42 +88,43 @@ static inline __wsum csum_shift(__wsum sum, int offset) + return sum; + } + +-static inline __wsum ++static __always_inline __wsum + csum_block_add(__wsum csum, __wsum csum2, int offset) + { + return csum_add(csum, csum_shift(csum2, offset)); + } + +-static inline __wsum ++static __always_inline __wsum + csum_block_add_ext(__wsum csum, __wsum csum2, int offset, int len) + { + return csum_block_add(csum, csum2, offset); + } + +-static inline __wsum ++static __always_inline __wsum + csum_block_sub(__wsum csum, __wsum csum2, int offset) + { + return csum_block_add(csum, ~csum2, offset); + } + +-static inline __wsum csum_unfold(__sum16 n) ++static __always_inline __wsum csum_unfold(__sum16 n) + { + return (__force __wsum)n; + } + +-static inline __wsum csum_partial_ext(const void *buff, int len, __wsum sum) ++static __always_inline ++__wsum csum_partial_ext(const void *buff, int len, __wsum sum) + { + return csum_partial(buff, len, sum); + } + + #define CSUM_MANGLED_0 ((__force __sum16)0xffff) + +-static inline void csum_replace_by_diff(__sum16 *sum, __wsum diff) ++static __always_inline void csum_replace_by_diff(__sum16 *sum, __wsum diff) + { + *sum = csum_fold(csum_add(diff, ~csum_unfold(*sum))); + } + +-static inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to) ++static __always_inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to) + { + __wsum tmp = csum_sub(~csum_unfold(*sum), (__force __wsum)from); + +@@ -136,11 +137,16 @@ static inline void csum_replace4(__sum16 *sum, __be32 from, __be32 to) + * m : old value of a 16bit field + * m' : new value of a 16bit field + */ +-static inline void csum_replace2(__sum16 *sum, __be16 old, __be16 new) ++static __always_inline void csum_replace2(__sum16 *sum, __be16 old, __be16 new) + { + *sum = ~csum16_add(csum16_sub(~(*sum), old), new); + } + ++static inline void csum_replace(__wsum *csum, __wsum old, __wsum new) ++{ ++ *csum = csum_add(csum_sub(*csum, old), new); ++} ++ + struct sk_buff; + void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, + __be32 from, __be32 to, bool pseudohdr); +@@ -150,16 +156,16 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, + void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb, + __wsum diff, bool pseudohdr); + +-static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb, +- __be16 from, __be16 to, +- bool pseudohdr) ++static __always_inline ++void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb, ++ __be16 from, __be16 to, bool pseudohdr) + { + inet_proto_csum_replace4(sum, skb, (__force __be32)from, + (__force __be32)to, pseudohdr); + } + +-static inline __wsum remcsum_adjust(void *ptr, __wsum csum, +- int start, int offset) ++static __always_inline __wsum remcsum_adjust(void *ptr, __wsum csum, ++ int start, int offset) + { + __sum16 *psum = (__sum16 *)(ptr + offset); + __wsum delta; +@@ -175,7 +181,7 @@ static inline __wsum remcsum_adjust(void *ptr, __wsum csum, + return delta; + } + +-static inline void remcsum_unadjust(__sum16 *psum, __wsum delta) ++static __always_inline void remcsum_unadjust(__sum16 *psum, __wsum delta) + { + *psum = csum_fold(csum_sub(delta, (__force __wsum)*psum)); + } +diff --git a/include/net/dsa.h b/include/net/dsa.h +index d784e76113b8d..49e5ece9361c6 100644 +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -1056,6 +1056,7 @@ void dsa_unregister_switch(struct dsa_switch *ds); + int dsa_register_switch(struct dsa_switch *ds); + void dsa_switch_shutdown(struct dsa_switch *ds); + struct dsa_switch *dsa_switch_find(int tree_index, int sw_index); ++void dsa_flush_workqueue(void); + #ifdef CONFIG_PM_SLEEP + int dsa_switch_suspend(struct dsa_switch *ds); + int dsa_switch_resume(struct dsa_switch *ds); +diff --git a/include/net/dst_cache.h b/include/net/dst_cache.h +index 67634675e9197..df6622a5fe98f 100644 +--- a/include/net/dst_cache.h ++++ b/include/net/dst_cache.h +@@ -79,6 +79,17 @@ static inline void dst_cache_reset(struct dst_cache *dst_cache) + dst_cache->reset_ts = jiffies; + } + ++/** ++ * dst_cache_reset_now - invalidate the cache contents immediately ++ * @dst_cache: the cache ++ * ++ * The caller must be sure there are no concurrent users, as this frees ++ * all dst_cache users immediately, rather than waiting for the next ++ * per-cpu usage like dst_cache_reset does. Most callers should use the ++ * higher speed lazily-freed dst_cache_reset function instead. ++ */ ++void dst_cache_reset_now(struct dst_cache *dst_cache); ++ + /** + * dst_cache_init - initialize the cache, allocating the required storage + * @dst_cache: the cache +diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h +index 14efa0ded75dd..adab27ba1ecbf 100644 +--- a/include/net/dst_metadata.h ++++ b/include/net/dst_metadata.h +@@ -123,8 +123,20 @@ static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb) + + memcpy(&new_md->u.tun_info, &md_dst->u.tun_info, + sizeof(struct ip_tunnel_info) + md_size); ++#ifdef CONFIG_DST_CACHE ++ /* Unclone the dst cache if there is one */ ++ if (new_md->u.tun_info.dst_cache.cache) { ++ int ret; ++ ++ ret = dst_cache_init(&new_md->u.tun_info.dst_cache, GFP_ATOMIC); ++ if (ret) { ++ metadata_dst_free(new_md); ++ return ERR_PTR(ret); ++ } ++ } ++#endif ++ + skb_dst_drop(skb); +- dst_hold(&new_md->dst); + skb_dst_set(skb, &new_md->dst); + return new_md; + } +diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h +index 4b10676c69d19..bd07484ab9dd5 100644 +--- a/include/net/fib_rules.h ++++ b/include/net/fib_rules.h +@@ -69,7 +69,7 @@ struct fib_rules_ops { + int (*action)(struct fib_rule *, + struct flowi *, int, + struct fib_lookup_arg *); +- bool (*suppress)(struct fib_rule *, ++ bool (*suppress)(struct fib_rule *, int, + struct fib_lookup_arg *); + int (*match)(struct fib_rule *, + struct flowi *, int); +@@ -218,7 +218,9 @@ INDIRECT_CALLABLE_DECLARE(int fib4_rule_action(struct fib_rule *rule, + struct fib_lookup_arg *arg)); + + INDIRECT_CALLABLE_DECLARE(bool fib6_rule_suppress(struct fib_rule *rule, ++ int flags, + struct fib_lookup_arg *arg)); + INDIRECT_CALLABLE_DECLARE(bool fib4_rule_suppress(struct fib_rule *rule, ++ int flags, + struct fib_lookup_arg *arg)); + #endif +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index b06c2d02ec84e..fa6a87246a7b8 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -289,7 +289,7 @@ static inline void inet_csk_prepare_for_destroy_sock(struct sock *sk) + { + /* The below has to be done to allow calling inet_csk_destroy_sock */ + sock_set_flag(sk, SOCK_DEAD); +- percpu_counter_inc(sk->sk_prot->orphan_count); ++ this_cpu_inc(*sk->sk_prot->orphan_count); + } + + void inet_csk_destroy_sock(struct sock *sk); +diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h +index 48cc5795ceda6..63540be0fc34a 100644 +--- a/include/net/inet_frag.h ++++ b/include/net/inet_frag.h +@@ -117,8 +117,15 @@ int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net); + + static inline void fqdir_pre_exit(struct fqdir *fqdir) + { +- fqdir->high_thresh = 0; /* prevent creation of new frags */ +- fqdir->dead = true; ++ /* Prevent creation of new frags. ++ * Pairs with READ_ONCE() in inet_frag_find(). ++ */ ++ WRITE_ONCE(fqdir->high_thresh, 0); ++ ++ /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire() ++ * and ip6frag_expire_frag_queue(). ++ */ ++ WRITE_ONCE(fqdir->dead, true); + } + void fqdir_exit(struct fqdir *fqdir); + +diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h +index 89163ef8cf4be..9e1111f5915bd 100644 +--- a/include/net/inet_sock.h ++++ b/include/net/inet_sock.h +@@ -207,11 +207,10 @@ struct inet_sock { + __be32 inet_saddr; + __s16 uc_ttl; + __u16 cmsg_flags; ++ struct ip_options_rcu __rcu *inet_opt; + __be16 inet_sport; + __u16 inet_id; + +- struct ip_options_rcu __rcu *inet_opt; +- int rx_dst_ifindex; + __u8 tos; + __u8 min_ttl; + __u8 mc_ttl; +diff --git a/include/net/ip.h b/include/net/ip.h +index 9192444f2964e..0106c6590ee7b 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -520,19 +520,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, + { + struct iphdr *iph = ip_hdr(skb); + ++ /* We had many attacks based on IPID, use the private ++ * generator as much as we can. ++ */ ++ if (sk && inet_sk(sk)->inet_daddr) { ++ iph->id = htons(inet_sk(sk)->inet_id); ++ inet_sk(sk)->inet_id += segs; ++ return; ++ } + if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) { +- /* This is only to work around buggy Windows95/2000 +- * VJ compression implementations. If the ID field +- * does not change, they drop every other packet in +- * a TCP stream using header compression. +- */ +- if (sk && inet_sk(sk)->inet_daddr) { +- iph->id = htons(inet_sk(sk)->inet_id); +- inet_sk(sk)->inet_id += segs; +- } else { +- iph->id = 0; +- } ++ iph->id = 0; + } else { ++ /* Unfortunately we need the big hammer to get a suitable IPID */ + __ip_select_ident(net, iph, segs); + } + } +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index c412dde4d67dc..bbb27639f2933 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -189,14 +189,16 @@ struct fib6_info { + u32 fib6_metric; + u8 fib6_protocol; + u8 fib6_type; ++ ++ u8 offload; ++ u8 trap; ++ u8 offload_failed; ++ + u8 should_flush:1, + dst_nocount:1, + dst_nopolicy:1, + fib6_destroying:1, +- offload:1, +- trap:1, +- offload_failed:1, +- unused:1; ++ unused:4; + + struct rcu_head rcu; + struct nexthop *nh; +@@ -281,7 +283,7 @@ static inline bool fib6_get_cookie_safe(const struct fib6_info *f6i, + fn = rcu_dereference(f6i->fib6_node); + + if (fn) { +- *cookie = fn->fn_sernum; ++ *cookie = READ_ONCE(fn->fn_sernum); + /* pairs with smp_wmb() in __fib6_update_sernum_upto_root() */ + smp_rmb(); + status = true; +@@ -485,6 +487,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, + struct fib6_config *cfg, gfp_t gfp_flags, + struct netlink_ext_ack *extack); + void fib6_nh_release(struct fib6_nh *fib6_nh); ++void fib6_nh_release_dsts(struct fib6_nh *fib6_nh); + + int call_fib6_entry_notifiers(struct net *net, + enum fib_event_type event_type, +diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h +index ab5348e57db1a..3417ba2d27ad6 100644 +--- a/include/net/ip_fib.h ++++ b/include/net/ip_fib.h +@@ -438,7 +438,7 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, + #ifdef CONFIG_IP_ROUTE_CLASSID + static inline int fib_num_tclassid_users(struct net *net) + { +- return net->ipv4.fib_num_tclassid_users; ++ return atomic_read(&net->ipv4.fib_num_tclassid_users); + } + #else + static inline int fib_num_tclassid_users(struct net *net) +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index f2d0ecc257bb2..359540dfc0339 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -391,17 +391,20 @@ static inline void txopt_put(struct ipv6_txoptions *opt) + kfree_rcu(opt, rcu); + } + ++#if IS_ENABLED(CONFIG_IPV6) + struct ip6_flowlabel *__fl6_sock_lookup(struct sock *sk, __be32 label); + + extern struct static_key_false_deferred ipv6_flowlabel_exclusive; + static inline struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, + __be32 label) + { +- if (static_branch_unlikely(&ipv6_flowlabel_exclusive.key)) ++ if (static_branch_unlikely(&ipv6_flowlabel_exclusive.key) && ++ READ_ONCE(sock_net(sk)->ipv6.flowlabel_has_excl)) + return __fl6_sock_lookup(sk, label) ? : ERR_PTR(-ENOENT); + + return NULL; + } ++#endif + + struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, + struct ip6_flowlabel *fl, +diff --git a/include/net/ipv6_frag.h b/include/net/ipv6_frag.h +index 851029ecff13c..0a4779175a523 100644 +--- a/include/net/ipv6_frag.h ++++ b/include/net/ipv6_frag.h +@@ -67,7 +67,8 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq) + struct sk_buff *head; + + rcu_read_lock(); +- if (fq->q.fqdir->dead) ++ /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */ ++ if (READ_ONCE(fq->q.fqdir->dead)) + goto out_rcu_unlock; + spin_lock(&fq->q.lock); + +diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h +index afbce90c44808..45e0339be6fa4 100644 +--- a/include/net/ipv6_stubs.h ++++ b/include/net/ipv6_stubs.h +@@ -47,6 +47,7 @@ struct ipv6_stub { + struct fib6_config *cfg, gfp_t gfp_flags, + struct netlink_ext_ack *extack); + void (*fib6_nh_release)(struct fib6_nh *fib6_nh); ++ void (*fib6_nh_release_dsts)(struct fib6_nh *fib6_nh); + void (*fib6_update_sernum)(struct net *net, struct fib6_info *rt); + int (*ip6_del_rt)(struct net *net, struct fib6_info *rt, bool skip_notify); + void (*fib6_rt_update)(struct net *net, struct fib6_info *rt, +diff --git a/include/net/llc.h b/include/net/llc.h +index df282d9b40170..9c10b121b49b0 100644 +--- a/include/net/llc.h ++++ b/include/net/llc.h +@@ -72,7 +72,9 @@ struct llc_sap { + static inline + struct hlist_head *llc_sk_dev_hash(struct llc_sap *sap, int ifindex) + { +- return &sap->sk_dev_hash[ifindex % LLC_SK_DEV_HASH_ENTRIES]; ++ u32 bucket = hash_32(ifindex, LLC_SK_DEV_HASH_BITS); ++ ++ return &sap->sk_dev_hash[bucket]; + } + + static inline +diff --git a/include/net/ndisc.h b/include/net/ndisc.h +index 38e4094960cee..e97ef508664f4 100644 +--- a/include/net/ndisc.h ++++ b/include/net/ndisc.h +@@ -487,9 +487,9 @@ int igmp6_late_init(void); + void igmp6_cleanup(void); + void igmp6_late_cleanup(void); + +-int igmp6_event_query(struct sk_buff *skb); ++void igmp6_event_query(struct sk_buff *skb); + +-int igmp6_event_report(struct sk_buff *skb); ++void igmp6_event_report(struct sk_buff *skb); + + + #ifdef CONFIG_SYSCTL +diff --git a/include/net/neighbour.h b/include/net/neighbour.h +index 22ced1381ede5..d5767e25509cc 100644 +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -253,6 +253,7 @@ static inline void *neighbour_priv(const struct neighbour *n) + #define NEIGH_UPDATE_F_OVERRIDE 0x00000001 + #define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002 + #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004 ++#define NEIGH_UPDATE_F_USE 0x10000000 + #define NEIGH_UPDATE_F_EXT_LEARNED 0x20000000 + #define NEIGH_UPDATE_F_ISROUTER 0x40000000 + #define NEIGH_UPDATE_F_ADMIN 0x80000000 +@@ -504,10 +505,15 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, + { + const struct hh_cache *hh = &n->hh; + +- if ((n->nud_state & NUD_CONNECTED) && hh->hh_len && !skip_cache) ++ /* n->nud_state and hh->hh_len could be changed under us. ++ * neigh_hh_output() is taking care of the race later. ++ */ ++ if (!skip_cache && ++ (READ_ONCE(n->nud_state) & NUD_CONNECTED) && ++ READ_ONCE(hh->hh_len)) + return neigh_hh_output(hh, skb); +- else +- return n->output(n, skb); ++ ++ return n->output(n, skb); + } + + static inline struct neighbour * +diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h +index cc663c68ddc4b..d24b0a34c8f0c 100644 +--- a/include/net/netfilter/nf_conntrack.h ++++ b/include/net/netfilter/nf_conntrack.h +@@ -276,14 +276,14 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) + /* jiffies until ct expires, 0 if already expired */ + static inline unsigned long nf_ct_expires(const struct nf_conn *ct) + { +- s32 timeout = ct->timeout - nfct_time_stamp; ++ s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; + + return timeout > 0 ? timeout : 0; + } + + static inline bool nf_ct_is_expired(const struct nf_conn *ct) + { +- return (__s32)(ct->timeout - nfct_time_stamp) <= 0; ++ return (__s32)(READ_ONCE(ct->timeout) - nfct_time_stamp) <= 0; + } + + /* use after obtaining a reference count */ +@@ -302,7 +302,7 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct) + static inline void nf_ct_offload_timeout(struct nf_conn *ct) + { + if (nf_ct_expires(ct) < NF_CT_DAY / 2) +- ct->timeout = nfct_time_stamp + NF_CT_DAY; ++ WRITE_ONCE(ct->timeout, nfct_time_stamp + NF_CT_DAY); + } + + struct kernel_param; +diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h +index 9eed51e920e87..980daa6e1e3aa 100644 +--- a/include/net/netfilter/nf_queue.h ++++ b/include/net/netfilter/nf_queue.h +@@ -37,7 +37,7 @@ void nf_register_queue_handler(const struct nf_queue_handler *qh); + void nf_unregister_queue_handler(void); + void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); + +-void nf_queue_entry_get_refs(struct nf_queue_entry *entry); ++bool nf_queue_entry_get_refs(struct nf_queue_entry *entry); + void nf_queue_entry_free(struct nf_queue_entry *entry); + + static inline void init_hashrandom(u32 *jhash_initval) +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index a16171c5fd9eb..d52a5d776e764 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -883,9 +883,9 @@ struct nft_expr_ops { + int (*offload)(struct nft_offload_ctx *ctx, + struct nft_flow_rule *flow, + const struct nft_expr *expr); ++ bool (*offload_action)(const struct nft_expr *expr); + void (*offload_stats)(struct nft_expr *expr, + const struct flow_stats *stats); +- u32 offload_flags; + const struct nft_expr_type *type; + void *data; + }; +diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h +index f9d95ff82df83..7971478439580 100644 +--- a/include/net/netfilter/nf_tables_offload.h ++++ b/include/net/netfilter/nf_tables_offload.h +@@ -67,8 +67,6 @@ struct nft_flow_rule { + struct flow_rule *rule; + }; + +-#define NFT_OFFLOAD_F_ACTION (1 << 0) +- + void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow, + enum flow_dissector_key_id addr_type); + +diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h +index 2f65701a43c95..6c5b2efc4f17d 100644 +--- a/include/net/netns/ipv4.h ++++ b/include/net/netns/ipv4.h +@@ -65,7 +65,7 @@ struct netns_ipv4 { + bool fib_has_custom_local_routes; + bool fib_offload_disabled; + #ifdef CONFIG_IP_ROUTE_CLASSID +- int fib_num_tclassid_users; ++ atomic_t fib_num_tclassid_users; + #endif + struct hlist_head *fib_table_hash; + struct sock *fibnl; +diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h +index a4b5503803165..6bd7e5a85ce76 100644 +--- a/include/net/netns/ipv6.h ++++ b/include/net/netns/ipv6.h +@@ -77,9 +77,10 @@ struct netns_ipv6 { + spinlock_t fib6_gc_lock; + unsigned int ip6_rt_gc_expire; + unsigned long ip6_rt_last_gc; ++ unsigned char flowlabel_has_excl; + #ifdef CONFIG_IPV6_MULTIPLE_TABLES +- unsigned int fib6_rules_require_fldissect; + bool fib6_has_custom_rules; ++ unsigned int fib6_rules_require_fldissect; + #ifdef CONFIG_IPV6_SUBTREES + unsigned int fib6_routes_require_src; + #endif +diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h +index a964daedc17b6..ea8595651c384 100644 +--- a/include/net/nfc/nci_core.h ++++ b/include/net/nfc/nci_core.h +@@ -30,6 +30,7 @@ enum nci_flag { + NCI_UP, + NCI_DATA_EXCHANGE, + NCI_DATA_EXCHANGE_TO, ++ NCI_UNREG, + }; + + /* NCI device states */ +diff --git a/include/net/nl802154.h b/include/net/nl802154.h +index ddcee128f5d9a..145acb8f25095 100644 +--- a/include/net/nl802154.h ++++ b/include/net/nl802154.h +@@ -19,6 +19,8 @@ + * + */ + ++#include <linux/types.h> ++ + #define NL802154_GENL_NAME "nl802154" + + enum nl802154_commands { +@@ -150,10 +152,9 @@ enum nl802154_attrs { + }; + + enum nl802154_iftype { +- /* for backwards compatibility TODO */ +- NL802154_IFTYPE_UNSPEC = -1, ++ NL802154_IFTYPE_UNSPEC = (~(__u32)0), + +- NL802154_IFTYPE_NODE, ++ NL802154_IFTYPE_NODE = 0, + NL802154_IFTYPE_MONITOR, + NL802154_IFTYPE_COORD, + +diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h +index bf79f3a890af2..9e7b21c0b3a6d 100644 +--- a/include/net/pkt_sched.h ++++ b/include/net/pkt_sched.h +@@ -193,4 +193,22 @@ static inline void skb_txtime_consumed(struct sk_buff *skb) + skb->tstamp = ktime_set(0, 0); + } + ++struct tc_skb_cb { ++ struct qdisc_skb_cb qdisc_cb; ++ ++ u16 mru; ++ u8 post_ct:1; ++ u8 post_ct_snat:1; ++ u8 post_ct_dnat:1; ++ u16 zone; /* Only valid if post_ct = true */ ++}; ++ ++static inline struct tc_skb_cb *tc_skb_cb(const struct sk_buff *skb) ++{ ++ struct tc_skb_cb *cb = (struct tc_skb_cb *)skb->cb; ++ ++ BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb)); ++ return cb; ++} ++ + #endif +diff --git a/include/net/route.h b/include/net/route.h +index 2e6c0e153e3a5..2551f3f03b37e 100644 +--- a/include/net/route.h ++++ b/include/net/route.h +@@ -369,7 +369,7 @@ static inline struct neighbour *ip_neigh_gw4(struct net_device *dev, + { + struct neighbour *neigh; + +- neigh = __ipv4_neigh_lookup_noref(dev, daddr); ++ neigh = __ipv4_neigh_lookup_noref(dev, (__force u32)daddr); + if (unlikely(!neigh)) + neigh = __neigh_create(&arp_tbl, &daddr, dev, false); + +diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h +index c0069ac00e62d..4121ffd0faf8f 100644 +--- a/include/net/sch_generic.h ++++ b/include/net/sch_generic.h +@@ -308,6 +308,8 @@ struct Qdisc_ops { + struct netlink_ext_ack *extack); + void (*attach)(struct Qdisc *sch); + int (*change_tx_queue_len)(struct Qdisc *, unsigned int); ++ void (*change_real_num_tx)(struct Qdisc *sch, ++ unsigned int new_real_tx); + + int (*dump)(struct Qdisc *, struct sk_buff *); + int (*dump_stats)(struct Qdisc *, struct gnet_dump *); +@@ -438,8 +440,6 @@ struct qdisc_skb_cb { + }; + #define QDISC_CB_PRIV_LEN 20 + unsigned char data[QDISC_CB_PRIV_LEN]; +- u16 mru; +- bool post_ct; + }; + + typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv); +@@ -684,6 +684,8 @@ void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); + void qdisc_class_hash_destroy(struct Qdisc_class_hash *); + + int dev_qdisc_change_tx_queue_len(struct net_device *dev); ++void dev_qdisc_change_real_num_tx(struct net_device *dev, ++ unsigned int new_real_tx); + void dev_init_scheduler(struct net_device *dev); + void dev_shutdown(struct net_device *dev); + void dev_activate(struct net_device *dev); +@@ -1258,6 +1260,7 @@ struct psched_ratecfg { + u64 rate_bytes_ps; /* bytes per second */ + u32 mult; + u16 overhead; ++ u16 mpu; + u8 linklayer; + u8 shift; + }; +@@ -1267,6 +1270,9 @@ static inline u64 psched_l2t_ns(const struct psched_ratecfg *r, + { + len += r->overhead; + ++ if (len < r->mpu) ++ len = r->mpu; ++ + if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) + return ((u64)(DIV_ROUND_UP(len,48)*53) * r->mult) >> r->shift; + +@@ -1289,6 +1295,7 @@ static inline void psched_ratecfg_getrate(struct tc_ratespec *res, + res->rate = min_t(u64, r->rate_bytes_ps, ~0U); + + res->overhead = r->overhead; ++ res->mpu = r->mpu; + res->linklayer = (r->linklayer & TC_LINKLAYER_MASK); + } + +diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h +index 69bab88ad66b1..3ae61ce2eabd0 100644 +--- a/include/net/sctp/sctp.h ++++ b/include/net/sctp/sctp.h +@@ -105,19 +105,18 @@ extern struct percpu_counter sctp_sockets_allocated; + int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); + struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); + ++typedef int (*sctp_callback_t)(struct sctp_endpoint *, struct sctp_transport *, void *); + void sctp_transport_walk_start(struct rhashtable_iter *iter); + void sctp_transport_walk_stop(struct rhashtable_iter *iter); + struct sctp_transport *sctp_transport_get_next(struct net *net, + struct rhashtable_iter *iter); + struct sctp_transport *sctp_transport_get_idx(struct net *net, + struct rhashtable_iter *iter, int pos); +-int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), +- struct net *net, ++int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net, + const union sctp_addr *laddr, + const union sctp_addr *paddr, void *p); +-int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), +- int (*cb_done)(struct sctp_transport *, void *), +- struct net *net, int *pos, void *p); ++int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done, ++ struct net *net, int *pos, void *p); + int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p); + int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc, + struct sctp_info *info); +@@ -626,7 +625,8 @@ static inline __u32 sctp_min_frag_point(struct sctp_sock *sp, __u16 datasize) + + static inline int sctp_transport_pl_hlen(struct sctp_transport *t) + { +- return __sctp_mtu_payload(sctp_sk(t->asoc->base.sk), t, 0, 0); ++ return __sctp_mtu_payload(sctp_sk(t->asoc->base.sk), t, 0, 0) - ++ sizeof(struct sctphdr); + } + + static inline void sctp_transport_pl_reset(struct sctp_transport *t) +@@ -653,12 +653,10 @@ static inline void sctp_transport_pl_update(struct sctp_transport *t) + if (t->pl.state == SCTP_PL_DISABLED) + return; + +- if (del_timer(&t->probe_timer)) +- sctp_transport_put(t); +- + t->pl.state = SCTP_PL_BASE; + t->pl.pmtu = SCTP_BASE_PLPMTU; + t->pl.probe_size = SCTP_BASE_PLPMTU; ++ sctp_transport_reset_probe_timer(t); + } + + static inline bool sctp_transport_pl_enabled(struct sctp_transport *t) +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 651bba654d77d..8d2c3dd9f5953 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -1365,6 +1365,7 @@ struct sctp_endpoint { + + u32 secid; + u32 peer_secid; ++ struct rcu_head rcu; + }; + + /* Recover the outter endpoint structure. */ +@@ -1380,7 +1381,7 @@ static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base) + struct sctp_endpoint *sctp_endpoint_new(struct sock *, gfp_t); + void sctp_endpoint_free(struct sctp_endpoint *); + void sctp_endpoint_put(struct sctp_endpoint *); +-void sctp_endpoint_hold(struct sctp_endpoint *); ++int sctp_endpoint_hold(struct sctp_endpoint *ep); + void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *); + struct sctp_association *sctp_endpoint_lookup_assoc( + const struct sctp_endpoint *ep, +diff --git a/include/net/seg6.h b/include/net/seg6.h +index 9d19c15e8545c..af668f17b3988 100644 +--- a/include/net/seg6.h ++++ b/include/net/seg6.h +@@ -58,9 +58,30 @@ extern int seg6_local_init(void); + extern void seg6_local_exit(void); + + extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced); ++extern struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags); ++extern void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt); + extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, + int proto); + extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh); + extern int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr, + u32 tbl_id); ++ ++/* If the packet which invoked an ICMP error contains an SRH return ++ * the true destination address from within the SRH, otherwise use the ++ * destination address in the IP header. ++ */ ++static inline const struct in6_addr *seg6_get_daddr(struct sk_buff *skb, ++ struct inet6_skb_parm *opt) ++{ ++ struct ipv6_sr_hdr *srh; ++ ++ if (opt->flags & IP6SKB_SEG6) { ++ srh = (struct ipv6_sr_hdr *)(skb->data + opt->srhoff); ++ return &srh->segments[0]; ++ } ++ ++ return NULL; ++} ++ ++ + #endif +diff --git a/include/net/sock.h b/include/net/sock.h +index 463f390d90b3e..7d49196a3880e 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -259,6 +259,8 @@ struct bpf_local_storage; + * @sk_rcvbuf: size of receive buffer in bytes + * @sk_wq: sock wait queue and async head + * @sk_rx_dst: receive input route used by early demux ++ * @sk_rx_dst_ifindex: ifindex for @sk_rx_dst ++ * @sk_rx_dst_cookie: cookie for @sk_rx_dst + * @sk_dst_cache: destination cache + * @sk_dst_pending_confirm: need to confirm neighbour + * @sk_policy: flow policy +@@ -430,7 +432,10 @@ struct sock { + #ifdef CONFIG_XFRM + struct xfrm_policy __rcu *sk_policy[2]; + #endif +- struct dst_entry *sk_rx_dst; ++ struct dst_entry __rcu *sk_rx_dst; ++ int sk_rx_dst_ifindex; ++ u32 sk_rx_dst_cookie; ++ + struct dst_entry __rcu *sk_dst_cache; + atomic_t sk_omem_alloc; + int sk_sndbuf; +@@ -501,7 +506,7 @@ struct sock { + u16 sk_tsflags; + int sk_bind_phc; + u8 sk_shutdown; +- u32 sk_tskey; ++ atomic_t sk_tskey; + atomic_t sk_zckey; + + u8 sk_clockid; +@@ -1237,7 +1242,7 @@ struct proto { + unsigned int useroffset; /* Usercopy region offset */ + unsigned int usersize; /* Usercopy region size */ + +- struct percpu_counter *orphan_count; ++ unsigned int __percpu *orphan_count; + + struct request_sock_ops *rsk_prot; + struct timewait_sock_ops *twsk_prot; +@@ -2400,19 +2405,22 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, + * @sk: socket + * + * Use the per task page_frag instead of the per socket one for +- * optimization when we know that we're in the normal context and owns ++ * optimization when we know that we're in process context and own + * everything that's associated with %current. + * +- * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest +- * inside other socket operations and end up recursing into sk_page_frag() +- * while it's already in use. ++ * Both direct reclaim and page faults can nest inside other ++ * socket operations and end up recursing into sk_page_frag() ++ * while it's already in use: explicitly avoid task page_frag ++ * usage if the caller is potentially doing any of them. ++ * This assumes that page fault handlers use the GFP_NOFS flags. + * + * Return: a per task page_frag if context allows that, + * otherwise a per socket one. + */ + static inline struct page_frag *sk_page_frag(struct sock *sk) + { +- if (gfpflags_normal_context(sk->sk_allocation)) ++ if ((sk->sk_allocation & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC | __GFP_FS)) == ++ (__GFP_DIRECT_RECLAIM | __GFP_FS)) + return ¤t->task_frag; + + return &sk->sk_frag; +@@ -2590,7 +2598,7 @@ static inline void _sock_tx_timestamp(struct sock *sk, __u16 tsflags, + __sock_tx_timestamp(tsflags, tx_flags); + if (tsflags & SOF_TIMESTAMPING_OPT_ID && tskey && + tsflags & SOF_TIMESTAMPING_TX_RECORD_MASK) +- *tskey = sk->sk_tskey++; ++ *tskey = atomic_inc_return(&sk->sk_tskey) - 1; + } + if (unlikely(sock_flag(sk, SOCK_WIFI_STATUS))) + *tx_flags |= SKBTX_WIFI_STATUS; +diff --git a/include/net/strparser.h b/include/net/strparser.h +index 1d20b98493a10..732b7097d78e4 100644 +--- a/include/net/strparser.h ++++ b/include/net/strparser.h +@@ -54,10 +54,28 @@ struct strp_msg { + int offset; + }; + ++struct _strp_msg { ++ /* Internal cb structure. struct strp_msg must be first for passing ++ * to upper layer. ++ */ ++ struct strp_msg strp; ++ int accum_len; ++}; ++ ++struct sk_skb_cb { ++#define SK_SKB_CB_PRIV_LEN 20 ++ unsigned char data[SK_SKB_CB_PRIV_LEN]; ++ struct _strp_msg strp; ++ /* temp_reg is a temporary register used for bpf_convert_data_end_access ++ * when dst_reg == src_reg. ++ */ ++ u64 temp_reg; ++}; ++ + static inline struct strp_msg *strp_msg(struct sk_buff *skb) + { + return (struct strp_msg *)((void *)skb->cb + +- offsetof(struct qdisc_skb_cb, data)); ++ offsetof(struct sk_skb_cb, strp)); + } + + /* Structure for an attached lower socket */ +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 60c384569e9cd..31d384c3778a1 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -48,7 +48,9 @@ + + extern struct inet_hashinfo tcp_hashinfo; + +-extern struct percpu_counter tcp_orphan_count; ++DECLARE_PER_CPU(unsigned int, tcp_orphan_count); ++int tcp_orphan_count_sum(void); ++ + void tcp_time_wait(struct sock *sk, int state, int timeo); + + #define MAX_TCP_HEADER L1_CACHE_ALIGN(128 + MAX_HEADER) +@@ -290,19 +292,6 @@ static inline bool tcp_out_of_memory(struct sock *sk) + + void sk_forced_mem_schedule(struct sock *sk, int size); + +-static inline bool tcp_too_many_orphans(struct sock *sk, int shift) +-{ +- struct percpu_counter *ocp = sk->sk_prot->orphan_count; +- int orphans = percpu_counter_read_positive(ocp); +- +- if (orphans << shift > sysctl_tcp_max_orphans) { +- orphans = percpu_counter_sum_positive(ocp); +- if (orphans << shift > sysctl_tcp_max_orphans) +- return true; +- } +- return false; +-} +- + bool tcp_check_oom(struct sock *sk, int shift); + + +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index 2308210793a01..301a164f17e9f 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -200,6 +200,11 @@ struct xfrm_state { + struct xfrm_algo_aead *aead; + const char *geniv; + ++ /* mapping change rate limiting */ ++ __be16 new_mapping_sport; ++ u32 new_mapping; /* seconds */ ++ u32 mapping_maxage; /* seconds for input SA */ ++ + /* Data for encapsulator */ + struct xfrm_encap_tmpl *encap; + struct sock __rcu *encap_sk; +@@ -1162,7 +1167,7 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) + { + struct net *net = dev_net(skb->dev); + +- if (xfrm_default_allow(net, XFRM_POLICY_FWD)) ++ if (xfrm_default_allow(net, XFRM_POLICY_OUT)) + return !net->xfrm.policy_count[XFRM_POLICY_OUT] || + (skb_dst(skb)->flags & DST_NOXFRM) || + __xfrm_route_forward(skb, family); +@@ -1562,7 +1567,6 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); + void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); + u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); + int xfrm_init_replay(struct xfrm_state *x); +-u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu); + u32 xfrm_state_mtu(struct xfrm_state *x, int mtu); + int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload); + int xfrm_init_state(struct xfrm_state *x); +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index 4b50d9a3018a6..4ba642fc8a19a 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -4097,8 +4097,13 @@ static inline int ib_dma_map_sgtable_attrs(struct ib_device *dev, + enum dma_data_direction direction, + unsigned long dma_attrs) + { ++ int nents; ++ + if (ib_uses_virt_dma(dev)) { +- ib_dma_virt_map_sg(dev, sgt->sgl, sgt->orig_nents); ++ nents = ib_dma_virt_map_sg(dev, sgt->sgl, sgt->orig_nents); ++ if (!nents) ++ return -EIO; ++ sgt->nents = nents; + return 0; + } + return dma_map_sgtable(dev->dma_device, sgt, direction, dma_attrs); +diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h +index 2758d9df71ee9..c2a79aeee113c 100644 +--- a/include/rdma/rdma_netlink.h ++++ b/include/rdma/rdma_netlink.h +@@ -30,7 +30,7 @@ enum rdma_nl_flags { + * constant as well and the compiler checks they are the same. + */ + #define MODULE_ALIAS_RDMA_NETLINK(_index, _val) \ +- static inline void __chk_##_index(void) \ ++ static inline void __maybe_unused __chk_##_index(void) \ + { \ + BUILD_BUG_ON(_index != _val); \ + } \ +diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h +index eaf04c9a1dfcb..59afe8787cf7c 100644 +--- a/include/scsi/scsi_cmnd.h ++++ b/include/scsi/scsi_cmnd.h +@@ -68,7 +68,7 @@ struct scsi_pointer { + struct scsi_cmnd { + struct scsi_request req; + struct scsi_device *device; +- struct list_head eh_entry; /* entry for the host eh_cmd_q */ ++ struct list_head eh_entry; /* entry for the host eh_abort_list/eh_cmd_q */ + struct delayed_work abort_work; + + struct rcu_head rcu; +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index 75363707b73f9..1a02e58eb4e44 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -556,6 +556,7 @@ struct Scsi_Host { + + struct mutex scan_mutex;/* serialize scanning activity */ + ++ struct list_head eh_abort_list; + struct list_head eh_cmd_q; + struct task_struct * ehandler; /* Error recovery thread. */ + struct completion * eh_action; /* Wait for specific actions on the +diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h +index 0e45963bb767f..82d9daa178517 100644 +--- a/include/sound/hda_codec.h ++++ b/include/sound/hda_codec.h +@@ -8,7 +8,7 @@ + #ifndef __SOUND_HDA_CODEC_H + #define __SOUND_HDA_CODEC_H + +-#include <linux/kref.h> ++#include <linux/refcount.h> + #include <linux/mod_devicetable.h> + #include <sound/info.h> + #include <sound/control.h> +@@ -166,8 +166,8 @@ struct hda_pcm { + bool own_chmap; /* codec driver provides own channel maps */ + /* private: */ + struct hda_codec *codec; +- struct kref kref; + struct list_head list; ++ unsigned int disconnected:1; + }; + + /* codec information */ +@@ -187,6 +187,8 @@ struct hda_codec { + + /* PCM to create, set by patch_ops.build_pcms callback */ + struct list_head pcm_list_head; ++ refcount_t pcm_ref; ++ wait_queue_head_t remove_sleep; + + /* codec specific info */ + void *spec; +@@ -420,7 +422,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); + + static inline void snd_hda_codec_pcm_get(struct hda_pcm *pcm) + { +- kref_get(&pcm->kref); ++ refcount_inc(&pcm->codec->pcm_ref); + } + void snd_hda_codec_pcm_put(struct hda_pcm *pcm); + +diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h +index 375581634143c..d4e31ea16aba3 100644 +--- a/include/sound/hdaudio_ext.h ++++ b/include/sound/hdaudio_ext.h +@@ -88,6 +88,8 @@ struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, + struct snd_pcm_substream *substream, + int type); + void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type); ++void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, ++ struct hdac_ext_stream *azx_dev, bool decouple); + void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, + struct hdac_ext_stream *azx_dev, bool decouple); + void snd_hdac_ext_stop_streams(struct hdac_bus *bus); +diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h +index 4afd667e124c2..3e8a85e1e8094 100644 +--- a/include/sound/soc-topology.h ++++ b/include/sound/soc-topology.h +@@ -188,8 +188,7 @@ int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, + + #else + +-static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp, +- u32 index) ++static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp) + { + return 0; + } +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index fb11c7693b257..2121a323fd6c3 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -812,8 +812,9 @@ struct se_device { + atomic_long_t read_bytes; + atomic_long_t write_bytes; + /* Active commands on this virtual SE device */ +- atomic_t simple_cmds; +- atomic_t dev_ordered_sync; ++ atomic_t non_ordered; ++ bool ordered_sync_in_progress; ++ atomic_t delayed_cmd_count; + atomic_t dev_qf_count; + u32 export_count; + spinlock_t delayed_cmd_lock; +@@ -834,6 +835,7 @@ struct se_device { + struct list_head dev_sep_list; + struct list_head dev_tmr_list; + struct work_struct qf_work_queue; ++ struct work_struct delayed_cmd_work; + struct list_head delayed_cmd_list; + struct list_head qf_cmd_list; + /* Pointer to associated SE HBA */ +diff --git a/include/trace/events/cgroup.h b/include/trace/events/cgroup.h +index 7f42a3de59e6b..dd7d7c9efecdf 100644 +--- a/include/trace/events/cgroup.h ++++ b/include/trace/events/cgroup.h +@@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(cgroup, + + TP_STRUCT__entry( + __field( int, root ) +- __field( int, id ) + __field( int, level ) ++ __field( u64, id ) + __string( path, path ) + ), + +@@ -71,7 +71,7 @@ DECLARE_EVENT_CLASS(cgroup, + __assign_str(path, path); + ), + +- TP_printk("root=%d id=%d level=%d path=%s", ++ TP_printk("root=%d id=%llu level=%d path=%s", + __entry->root, __entry->id, __entry->level, __get_str(path)) + ); + +@@ -126,8 +126,8 @@ DECLARE_EVENT_CLASS(cgroup_migrate, + + TP_STRUCT__entry( + __field( int, dst_root ) +- __field( int, dst_id ) + __field( int, dst_level ) ++ __field( u64, dst_id ) + __field( int, pid ) + __string( dst_path, path ) + __string( comm, task->comm ) +@@ -142,7 +142,7 @@ DECLARE_EVENT_CLASS(cgroup_migrate, + __assign_str(comm, task->comm); + ), + +- TP_printk("dst_root=%d dst_id=%d dst_level=%d dst_path=%s pid=%d comm=%s", ++ TP_printk("dst_root=%d dst_id=%llu dst_level=%d dst_path=%s pid=%d comm=%s", + __entry->dst_root, __entry->dst_id, __entry->dst_level, + __get_str(dst_path), __entry->pid, __get_str(comm)) + ); +@@ -171,8 +171,8 @@ DECLARE_EVENT_CLASS(cgroup_event, + + TP_STRUCT__entry( + __field( int, root ) +- __field( int, id ) + __field( int, level ) ++ __field( u64, id ) + __string( path, path ) + __field( int, val ) + ), +@@ -185,7 +185,7 @@ DECLARE_EVENT_CLASS(cgroup_event, + __entry->val = val; + ), + +- TP_printk("root=%d id=%d level=%d path=%s val=%d", ++ TP_printk("root=%d id=%llu level=%d path=%s val=%d", + __entry->root, __entry->id, __entry->level, __get_str(path), + __entry->val) + ); +diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h +index 4e881d91c8744..4cb055af1ec0b 100644 +--- a/include/trace/events/f2fs.h ++++ b/include/trace/events/f2fs.h +@@ -807,20 +807,20 @@ TRACE_EVENT(f2fs_lookup_start, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) +- __field(const char *, name) ++ __string(name, dentry->d_name.name) + __field(unsigned int, flags) + ), + + TP_fast_assign( + __entry->dev = dir->i_sb->s_dev; + __entry->ino = dir->i_ino; +- __entry->name = dentry->d_name.name; ++ __assign_str(name, dentry->d_name.name); + __entry->flags = flags; + ), + + TP_printk("dev = (%d,%d), pino = %lu, name:%s, flags:%u", + show_dev_ino(__entry), +- __entry->name, ++ __get_str(name), + __entry->flags) + ); + +@@ -834,7 +834,7 @@ TRACE_EVENT(f2fs_lookup_end, + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) +- __field(const char *, name) ++ __string(name, dentry->d_name.name) + __field(nid_t, cino) + __field(int, err) + ), +@@ -842,14 +842,14 @@ TRACE_EVENT(f2fs_lookup_end, + TP_fast_assign( + __entry->dev = dir->i_sb->s_dev; + __entry->ino = dir->i_ino; +- __entry->name = dentry->d_name.name; ++ __assign_str(name, dentry->d_name.name); + __entry->cino = ino; + __entry->err = err; + ), + + TP_printk("dev = (%d,%d), pino = %lu, name:%s, ino:%u, err:%d", + show_dev_ino(__entry), +- __entry->name, ++ __get_str(name), + __entry->cino, + __entry->err) + ); +diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h +index 2d04eb96d4183..7c48613c18304 100644 +--- a/include/trace/events/sunrpc.h ++++ b/include/trace/events/sunrpc.h +@@ -925,18 +925,19 @@ TRACE_EVENT(rpc_socket_nospace, + + #define rpc_show_xprt_state(x) \ + __print_flags(x, "|", \ +- { (1UL << XPRT_LOCKED), "LOCKED"}, \ +- { (1UL << XPRT_CONNECTED), "CONNECTED"}, \ +- { (1UL << XPRT_CONNECTING), "CONNECTING"}, \ +- { (1UL << XPRT_CLOSE_WAIT), "CLOSE_WAIT"}, \ +- { (1UL << XPRT_BOUND), "BOUND"}, \ +- { (1UL << XPRT_BINDING), "BINDING"}, \ +- { (1UL << XPRT_CLOSING), "CLOSING"}, \ +- { (1UL << XPRT_OFFLINE), "OFFLINE"}, \ +- { (1UL << XPRT_REMOVE), "REMOVE"}, \ +- { (1UL << XPRT_CONGESTED), "CONGESTED"}, \ +- { (1UL << XPRT_CWND_WAIT), "CWND_WAIT"}, \ +- { (1UL << XPRT_WRITE_SPACE), "WRITE_SPACE"}) ++ { BIT(XPRT_LOCKED), "LOCKED" }, \ ++ { BIT(XPRT_CONNECTED), "CONNECTED" }, \ ++ { BIT(XPRT_CONNECTING), "CONNECTING" }, \ ++ { BIT(XPRT_CLOSE_WAIT), "CLOSE_WAIT" }, \ ++ { BIT(XPRT_BOUND), "BOUND" }, \ ++ { BIT(XPRT_BINDING), "BINDING" }, \ ++ { BIT(XPRT_CLOSING), "CLOSING" }, \ ++ { BIT(XPRT_OFFLINE), "OFFLINE" }, \ ++ { BIT(XPRT_REMOVE), "REMOVE" }, \ ++ { BIT(XPRT_CONGESTED), "CONGESTED" }, \ ++ { BIT(XPRT_CWND_WAIT), "CWND_WAIT" }, \ ++ { BIT(XPRT_WRITE_SPACE), "WRITE_SPACE" }, \ ++ { BIT(XPRT_SND_IS_COOKIE), "SND_IS_COOKIE" }) + + DECLARE_EVENT_CLASS(rpc_xprt_lifetime_class, + TP_PROTO( +@@ -1133,8 +1134,11 @@ DECLARE_EVENT_CLASS(xprt_writelock_event, + __entry->task_id = -1; + __entry->client_id = -1; + } +- __entry->snd_task_id = xprt->snd_task ? +- xprt->snd_task->tk_pid : -1; ++ if (xprt->snd_task && ++ !test_bit(XPRT_SND_IS_COOKIE, &xprt->state)) ++ __entry->snd_task_id = xprt->snd_task->tk_pid; ++ else ++ __entry->snd_task_id = -1; + ), + + TP_printk("task:%u@%u snd_task:%u", +@@ -1178,8 +1182,12 @@ DECLARE_EVENT_CLASS(xprt_cong_event, + __entry->task_id = -1; + __entry->client_id = -1; + } +- __entry->snd_task_id = xprt->snd_task ? +- xprt->snd_task->tk_pid : -1; ++ if (xprt->snd_task && ++ !test_bit(XPRT_SND_IS_COOKIE, &xprt->state)) ++ __entry->snd_task_id = xprt->snd_task->tk_pid; ++ else ++ __entry->snd_task_id = -1; ++ + __entry->cong = xprt->cong; + __entry->cwnd = xprt->cwnd; + __entry->wait = test_bit(XPRT_CWND_WAIT, &xprt->state); +@@ -1719,10 +1727,11 @@ TRACE_EVENT(svc_xprt_create_err, + const char *program, + const char *protocol, + struct sockaddr *sap, ++ size_t salen, + const struct svc_xprt *xprt + ), + +- TP_ARGS(program, protocol, sap, xprt), ++ TP_ARGS(program, protocol, sap, salen, xprt), + + TP_STRUCT__entry( + __field(long, error) +@@ -1735,7 +1744,7 @@ TRACE_EVENT(svc_xprt_create_err, + __entry->error = PTR_ERR(xprt); + __assign_str(program, program); + __assign_str(protocol, protocol); +- memcpy(__entry->addr, sap, sizeof(__entry->addr)); ++ memcpy(__entry->addr, sap, min(salen, sizeof(__entry->addr))); + ), + + TP_printk("addr=%pISpc program=%s protocol=%s error=%ld", +@@ -2103,17 +2112,17 @@ DECLARE_EVENT_CLASS(svcsock_accept_class, + TP_STRUCT__entry( + __field(long, status) + __string(service, service) +- __array(unsigned char, addr, sizeof(struct sockaddr_in6)) ++ __field(unsigned int, netns_ino) + ), + + TP_fast_assign( + __entry->status = status; + __assign_str(service, service); +- memcpy(__entry->addr, &xprt->xpt_local, sizeof(__entry->addr)); ++ __entry->netns_ino = xprt->xpt_net->ns.inum; + ), + +- TP_printk("listener=%pISpc service=%s status=%ld", +- __entry->addr, __get_str(service), __entry->status ++ TP_printk("addr=listener service=%s status=%ld", ++ __get_str(service), __entry->status + ) + ); + +diff --git a/include/uapi/asm-generic/poll.h b/include/uapi/asm-generic/poll.h +index 41b509f410bf9..f9c520ce4bf4e 100644 +--- a/include/uapi/asm-generic/poll.h ++++ b/include/uapi/asm-generic/poll.h +@@ -29,7 +29,7 @@ + #define POLLRDHUP 0x2000 + #endif + +-#define POLLFREE (__force __poll_t)0x4000 /* currently only for epoll */ ++#define POLLFREE (__force __poll_t)0x4000 + + #define POLL_BUSY_LOOP (__force __poll_t)0x8000 + +diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h +index fe929e7b77ca1..7572f2f46ee89 100644 +--- a/include/uapi/asm-generic/signal-defs.h ++++ b/include/uapi/asm-generic/signal-defs.h +@@ -45,6 +45,7 @@ + #define SA_UNSUPPORTED 0x00000400 + #define SA_EXPOSE_TAGBITS 0x00000800 + /* 0x00010000 used on mips */ ++/* 0x00800000 used for internal SA_IMMUTABLE */ + /* 0x01000000 used on x86 */ + /* 0x02000000 used on x86 */ + /* +diff --git a/include/uapi/linux/byteorder/big_endian.h b/include/uapi/linux/byteorder/big_endian.h +index 2199adc6a6c20..80aa5c41a7636 100644 +--- a/include/uapi/linux/byteorder/big_endian.h ++++ b/include/uapi/linux/byteorder/big_endian.h +@@ -9,6 +9,7 @@ + #define __BIG_ENDIAN_BITFIELD + #endif + ++#include <linux/stddef.h> + #include <linux/types.h> + #include <linux/swab.h> + +diff --git a/include/uapi/linux/byteorder/little_endian.h b/include/uapi/linux/byteorder/little_endian.h +index 601c904fd5cd9..cd98982e7523e 100644 +--- a/include/uapi/linux/byteorder/little_endian.h ++++ b/include/uapi/linux/byteorder/little_endian.h +@@ -9,6 +9,7 @@ + #define __LITTLE_ENDIAN_BITFIELD + #endif + ++#include <linux/stddef.h> + #include <linux/types.h> + #include <linux/swab.h> + +diff --git a/include/uapi/linux/cyclades.h b/include/uapi/linux/cyclades.h +new file mode 100644 +index 0000000000000..6225c5aebe06a +--- /dev/null ++++ b/include/uapi/linux/cyclades.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++ ++#ifndef _UAPI_LINUX_CYCLADES_H ++#define _UAPI_LINUX_CYCLADES_H ++ ++#warning "Support for features provided by this header has been removed" ++#warning "Please consider updating your code" ++ ++struct cyclades_monitor { ++ unsigned long int_count; ++ unsigned long char_count; ++ unsigned long char_max; ++ unsigned long char_last; ++}; ++ ++#define CYGETMON 0x435901 ++#define CYGETTHRESH 0x435902 ++#define CYSETTHRESH 0x435903 ++#define CYGETDEFTHRESH 0x435904 ++#define CYSETDEFTHRESH 0x435905 ++#define CYGETTIMEOUT 0x435906 ++#define CYSETTIMEOUT 0x435907 ++#define CYGETDEFTIMEOUT 0x435908 ++#define CYSETDEFTIMEOUT 0x435909 ++#define CYSETRFLOW 0x43590a ++#define CYGETRFLOW 0x43590b ++#define CYSETRTSDTR_INV 0x43590c ++#define CYGETRTSDTR_INV 0x43590d ++#define CYZSETPOLLCYCLE 0x43590e ++#define CYZGETPOLLCYCLE 0x43590f ++#define CYGETCD1400VER 0x435910 ++#define CYSETWAIT 0x435912 ++#define CYGETWAIT 0x435913 ++ ++#endif /* _UAPI_LINUX_CYCLADES_H */ +diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h +index 5545f1ca9237c..f7204bdfe8db1 100644 +--- a/include/uapi/linux/ethtool_netlink.h ++++ b/include/uapi/linux/ethtool_netlink.h +@@ -407,7 +407,9 @@ enum { + ETHTOOL_A_PAUSE_STAT_TX_FRAMES, + ETHTOOL_A_PAUSE_STAT_RX_FRAMES, + +- /* add new constants above here */ ++ /* add new constants above here ++ * adjust ETHTOOL_PAUSE_STAT_CNT if adding non-stats! ++ */ + __ETHTOOL_A_PAUSE_STAT_CNT, + ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1) + }; +diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h +index 225ec87d4f228..7989d9483ea75 100644 +--- a/include/uapi/linux/input-event-codes.h ++++ b/include/uapi/linux/input-event-codes.h +@@ -278,7 +278,8 @@ + #define KEY_PAUSECD 201 + #define KEY_PROG3 202 + #define KEY_PROG4 203 +-#define KEY_DASHBOARD 204 /* AL Dashboard */ ++#define KEY_ALL_APPLICATIONS 204 /* AC Desktop Show All Applications */ ++#define KEY_DASHBOARD KEY_ALL_APPLICATIONS + #define KEY_SUSPEND 205 + #define KEY_CLOSE 206 /* AC Close */ + #define KEY_PLAY 207 +@@ -612,6 +613,7 @@ + #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ + #define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */ + #define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */ ++#define KEY_DICTATE 0x24a /* Start or Stop Voice Dictation Session (HUTRR99) */ + + #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ + #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ +diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h +index f66038b9551fa..80c40194e2977 100644 +--- a/include/uapi/linux/mptcp.h ++++ b/include/uapi/linux/mptcp.h +@@ -129,19 +129,21 @@ struct mptcp_info { + * MPTCP_EVENT_REMOVED: token, rem_id + * An address has been lost by the peer. + * +- * MPTCP_EVENT_SUB_ESTABLISHED: token, family, saddr4 | saddr6, +- * daddr4 | daddr6, sport, dport, backup, +- * if_idx [, error] ++ * MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id, ++ * saddr4 | saddr6, daddr4 | daddr6, sport, ++ * dport, backup, if_idx [, error] + * A new subflow has been established. 'error' should not be set. + * +- * MPTCP_EVENT_SUB_CLOSED: token, family, saddr4 | saddr6, daddr4 | daddr6, +- * sport, dport, backup, if_idx [, error] ++ * MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6, ++ * daddr4 | daddr6, sport, dport, backup, if_idx ++ * [, error] + * A subflow has been closed. An error (copy of sk_err) could be set if an + * error has been detected for this subflow. + * +- * MPTCP_EVENT_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6, +- * sport, dport, backup, if_idx [, error] +- * The priority of a subflow has changed. 'error' should not be set. ++ * MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6, ++ * daddr4 | daddr6, sport, dport, backup, if_idx ++ * [, error] ++ * The priority of a subflow has changed. 'error' should not be set. + */ + enum mptcp_event_type { + MPTCP_EVENT_UNSPEC = 0, +diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h +index 4b3395082d15c..26071021e986f 100644 +--- a/include/uapi/linux/netfilter/nf_conntrack_common.h ++++ b/include/uapi/linux/netfilter/nf_conntrack_common.h +@@ -106,7 +106,7 @@ enum ip_conntrack_status { + IPS_NAT_CLASH = IPS_UNTRACKED, + #endif + +- /* Conntrack got a helper explicitly attached via CT target. */ ++ /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */ + IPS_HELPER_BIT = 13, + IPS_HELPER = (1 << IPS_HELPER_BIT), + +diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h +index f6e3c8c9c7449..4fa4e979e948a 100644 +--- a/include/uapi/linux/nfc.h ++++ b/include/uapi/linux/nfc.h +@@ -263,7 +263,7 @@ enum nfc_sdp_attr { + #define NFC_SE_ENABLED 0x1 + + struct sockaddr_nfc { +- sa_family_t sa_family; ++ __kernel_sa_family_t sa_family; + __u32 dev_idx; + __u32 target_idx; + __u32 nfc_protocol; +@@ -271,14 +271,14 @@ struct sockaddr_nfc { + + #define NFC_LLCP_MAX_SERVICE_NAME 63 + struct sockaddr_nfc_llcp { +- sa_family_t sa_family; ++ __kernel_sa_family_t sa_family; + __u32 dev_idx; + __u32 target_idx; + __u32 nfc_protocol; + __u8 dsap; /* Destination SAP, if known */ + __u8 ssap; /* Source SAP to be bound to */ + char service_name[NFC_LLCP_MAX_SERVICE_NAME]; /* Service name URI */; +- size_t service_name_len; ++ __kernel_size_t service_name_len; + }; + + /* NFC socket protocols */ +diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h +index e709ae8235e7f..ff6ccbc6efe96 100644 +--- a/include/uapi/linux/pci_regs.h ++++ b/include/uapi/linux/pci_regs.h +@@ -504,6 +504,12 @@ + #define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */ + #define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ + #define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ ++#define PCI_EXP_DEVCTL_PAYLOAD_128B 0x0000 /* 128 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_256B 0x0020 /* 256 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_512B 0x0040 /* 512 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_1024B 0x0060 /* 1024 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_2048B 0x0080 /* 2048 Bytes */ ++#define PCI_EXP_DEVCTL_PAYLOAD_4096B 0x00a0 /* 4096 Bytes */ + #define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ + #define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */ + #define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */ +diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h +index eda0426ec4c2b..65e13a099b1a0 100644 +--- a/include/uapi/linux/xfrm.h ++++ b/include/uapi/linux/xfrm.h +@@ -313,6 +313,7 @@ enum xfrm_attr_type_t { + XFRMA_SET_MARK, /* __u32 */ + XFRMA_SET_MARK_MASK, /* __u32 */ + XFRMA_IF_ID, /* __u32 */ ++ XFRMA_MTIMER_THRESH, /* __u32 in seconds for input SA */ + __XFRMA_MAX + + #define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */ +@@ -510,6 +511,12 @@ struct xfrm_user_offload { + int ifindex; + __u8 flags; + }; ++/* This flag was exposed without any kernel code that supporting it. ++ * Unfortunately, strongswan has the code that uses sets this flag, ++ * which makes impossible to reuse this bit. ++ * ++ * So leave it here to make sure that it won't be reused by mistake. ++ */ + #define XFRM_OFFLOAD_IPV6 1 + #define XFRM_OFFLOAD_INBOUND 2 + +diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h +index 5859ca0a1439b..93e40f91bd49a 100644 +--- a/include/uapi/sound/asound.h ++++ b/include/uapi/sound/asound.h +@@ -56,8 +56,10 @@ + * * + ****************************************************************************/ + ++#define AES_IEC958_STATUS_SIZE 24 ++ + struct snd_aes_iec958 { +- unsigned char status[24]; /* AES/IEC958 channel status bits */ ++ unsigned char status[AES_IEC958_STATUS_SIZE]; /* AES/IEC958 channel status bits */ + unsigned char subcode[147]; /* AES/IEC958 subcode bits */ + unsigned char pad; /* nothing */ + unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ +diff --git a/include/xen/events.h b/include/xen/events.h +index c204262d9fc24..344081e71584b 100644 +--- a/include/xen/events.h ++++ b/include/xen/events.h +@@ -17,6 +17,7 @@ struct xenbus_device; + unsigned xen_evtchn_nr_channels(void); + + int bind_evtchn_to_irq(evtchn_port_t evtchn); ++int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn); + int bind_evtchn_to_irqhandler(evtchn_port_t evtchn, + irq_handler_t handler, + unsigned long irqflags, const char *devname, +diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h +index cb854df031ce0..c9fea9389ebec 100644 +--- a/include/xen/grant_table.h ++++ b/include/xen/grant_table.h +@@ -104,17 +104,32 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly); + * access has been ended, free the given page too. Access will be ended + * immediately iff the grant entry is not in use, otherwise it will happen + * some time later. page may be 0, in which case no freeing will occur. ++ * Note that the granted page might still be accessed (read or write) by the ++ * other side after gnttab_end_foreign_access() returns, so even if page was ++ * specified as 0 it is not allowed to just reuse the page for other ++ * purposes immediately. gnttab_end_foreign_access() will take an additional ++ * reference to the granted page in this case, which is dropped only after ++ * the grant is no longer in use. ++ * This requires that multi page allocations for areas subject to ++ * gnttab_end_foreign_access() are done via alloc_pages_exact() (and freeing ++ * via free_pages_exact()) in order to avoid high order pages. + */ + void gnttab_end_foreign_access(grant_ref_t ref, int readonly, + unsigned long page); + ++/* ++ * End access through the given grant reference, iff the grant entry is ++ * no longer in use. In case of success ending foreign access, the ++ * grant reference is deallocated. ++ * Return 1 if the grant entry was freed, 0 if it is still in use. ++ */ ++int gnttab_try_end_foreign_access(grant_ref_t ref); ++ + int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn); + + unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref); + unsigned long gnttab_end_foreign_transfer(grant_ref_t ref); + +-int gnttab_query_foreign_access(grant_ref_t ref); +- + /* + * operations on reserved batches of grant references + */ +diff --git a/init/main.c b/init/main.c +index 3c4054a955458..bcd132d4e7bdd 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -924,7 +924,9 @@ static void __init print_unknown_bootoptions(void) + for (p = &envp_init[2]; *p; p++) + end += sprintf(end, " %s", *p); + +- pr_notice("Unknown command line parameters:%s\n", unknown_options); ++ /* Start at unknown_options[1] to skip the initial space */ ++ pr_notice("Unknown kernel command line parameters \"%s\", will be passed to user space.\n", ++ &unknown_options[1]); + memblock_free_ptr(unknown_options, len); + } + +diff --git a/ipc/sem.c b/ipc/sem.c +index 6693daf4fe112..0dbdb98fdf2d9 100644 +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -1964,6 +1964,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) + */ + un = lookup_undo(ulp, semid); + if (un) { ++ spin_unlock(&ulp->lock); + kvfree(new); + goto success; + } +@@ -1976,9 +1977,8 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid) + ipc_assert_locked_object(&sma->sem_perm); + list_add(&new->list_id, &sma->list_id); + un = new; +- +-success: + spin_unlock(&ulp->lock); ++success: + sem_unlock(sma, -1); + out: + return un; +diff --git a/ipc/shm.c b/ipc/shm.c +index ab749be6d8b71..048eb183b24b9 100644 +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -62,9 +62,18 @@ struct shmid_kernel /* private to the kernel */ + struct pid *shm_lprid; + struct ucounts *mlock_ucounts; + +- /* The task created the shm object. NULL if the task is dead. */ ++ /* ++ * The task created the shm object, for ++ * task_lock(shp->shm_creator) ++ */ + struct task_struct *shm_creator; +- struct list_head shm_clist; /* list by creator */ ++ ++ /* ++ * List by creator. task_lock(->shm_creator) required for read/write. ++ * If list_empty(), then the creator is dead already. ++ */ ++ struct list_head shm_clist; ++ struct ipc_namespace *ns; + } __randomize_layout; + + /* shm_mode upper byte flags */ +@@ -115,6 +124,7 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) + struct shmid_kernel *shp; + + shp = container_of(ipcp, struct shmid_kernel, shm_perm); ++ WARN_ON(ns != shp->ns); + + if (shp->shm_nattch) { + shp->shm_perm.mode |= SHM_DEST; +@@ -225,10 +235,43 @@ static void shm_rcu_free(struct rcu_head *head) + kfree(shp); + } + +-static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) ++/* ++ * It has to be called with shp locked. ++ * It must be called before ipc_rmid() ++ */ ++static inline void shm_clist_rm(struct shmid_kernel *shp) + { +- list_del(&s->shm_clist); +- ipc_rmid(&shm_ids(ns), &s->shm_perm); ++ struct task_struct *creator; ++ ++ /* ensure that shm_creator does not disappear */ ++ rcu_read_lock(); ++ ++ /* ++ * A concurrent exit_shm may do a list_del_init() as well. ++ * Just do nothing if exit_shm already did the work ++ */ ++ if (!list_empty(&shp->shm_clist)) { ++ /* ++ * shp->shm_creator is guaranteed to be valid *only* ++ * if shp->shm_clist is not empty. ++ */ ++ creator = shp->shm_creator; ++ ++ task_lock(creator); ++ /* ++ * list_del_init() is a nop if the entry was already removed ++ * from the list. ++ */ ++ list_del_init(&shp->shm_clist); ++ task_unlock(creator); ++ } ++ rcu_read_unlock(); ++} ++ ++static inline void shm_rmid(struct shmid_kernel *s) ++{ ++ shm_clist_rm(s); ++ ipc_rmid(&shm_ids(s->ns), &s->shm_perm); + } + + +@@ -283,7 +326,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) + shm_file = shp->shm_file; + shp->shm_file = NULL; + ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; +- shm_rmid(ns, shp); ++ shm_rmid(shp); + shm_unlock(shp); + if (!is_file_hugepages(shm_file)) + shmem_lock(shm_file, 0, shp->mlock_ucounts); +@@ -306,10 +349,10 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) + * + * 2) sysctl kernel.shm_rmid_forced is set to 1. + */ +-static bool shm_may_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) ++static bool shm_may_destroy(struct shmid_kernel *shp) + { + return (shp->shm_nattch == 0) && +- (ns->shm_rmid_forced || ++ (shp->ns->shm_rmid_forced || + (shp->shm_perm.mode & SHM_DEST)); + } + +@@ -340,7 +383,7 @@ static void shm_close(struct vm_area_struct *vma) + ipc_update_pid(&shp->shm_lprid, task_tgid(current)); + shp->shm_dtim = ktime_get_real_seconds(); + shp->shm_nattch--; +- if (shm_may_destroy(ns, shp)) ++ if (shm_may_destroy(shp)) + shm_destroy(ns, shp); + else + shm_unlock(shp); +@@ -361,10 +404,10 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data) + * + * As shp->* are changed under rwsem, it's safe to skip shp locking. + */ +- if (shp->shm_creator != NULL) ++ if (!list_empty(&shp->shm_clist)) + return 0; + +- if (shm_may_destroy(ns, shp)) { ++ if (shm_may_destroy(shp)) { + shm_lock_by_ptr(shp); + shm_destroy(ns, shp); + } +@@ -382,48 +425,97 @@ void shm_destroy_orphaned(struct ipc_namespace *ns) + /* Locking assumes this will only be called with task == current */ + void exit_shm(struct task_struct *task) + { +- struct ipc_namespace *ns = task->nsproxy->ipc_ns; +- struct shmid_kernel *shp, *n; ++ for (;;) { ++ struct shmid_kernel *shp; ++ struct ipc_namespace *ns; + +- if (list_empty(&task->sysvshm.shm_clist)) +- return; ++ task_lock(task); ++ ++ if (list_empty(&task->sysvshm.shm_clist)) { ++ task_unlock(task); ++ break; ++ } ++ ++ shp = list_first_entry(&task->sysvshm.shm_clist, struct shmid_kernel, ++ shm_clist); + +- /* +- * If kernel.shm_rmid_forced is not set then only keep track of +- * which shmids are orphaned, so that a later set of the sysctl +- * can clean them up. +- */ +- if (!ns->shm_rmid_forced) { +- down_read(&shm_ids(ns).rwsem); +- list_for_each_entry(shp, &task->sysvshm.shm_clist, shm_clist) +- shp->shm_creator = NULL; + /* +- * Only under read lock but we are only called on current +- * so no entry on the list will be shared. ++ * 1) Get pointer to the ipc namespace. It is worth to say ++ * that this pointer is guaranteed to be valid because ++ * shp lifetime is always shorter than namespace lifetime ++ * in which shp lives. ++ * We taken task_lock it means that shp won't be freed. + */ +- list_del(&task->sysvshm.shm_clist); +- up_read(&shm_ids(ns).rwsem); +- return; +- } ++ ns = shp->ns; + +- /* +- * Destroy all already created segments, that were not yet mapped, +- * and mark any mapped as orphan to cover the sysctl toggling. +- * Destroy is skipped if shm_may_destroy() returns false. +- */ +- down_write(&shm_ids(ns).rwsem); +- list_for_each_entry_safe(shp, n, &task->sysvshm.shm_clist, shm_clist) { +- shp->shm_creator = NULL; ++ /* ++ * 2) If kernel.shm_rmid_forced is not set then only keep track of ++ * which shmids are orphaned, so that a later set of the sysctl ++ * can clean them up. ++ */ ++ if (!ns->shm_rmid_forced) ++ goto unlink_continue; + +- if (shm_may_destroy(ns, shp)) { +- shm_lock_by_ptr(shp); +- shm_destroy(ns, shp); ++ /* ++ * 3) get a reference to the namespace. ++ * The refcount could be already 0. If it is 0, then ++ * the shm objects will be free by free_ipc_work(). ++ */ ++ ns = get_ipc_ns_not_zero(ns); ++ if (!ns) { ++unlink_continue: ++ list_del_init(&shp->shm_clist); ++ task_unlock(task); ++ continue; + } +- } + +- /* Remove the list head from any segments still attached. */ +- list_del(&task->sysvshm.shm_clist); +- up_write(&shm_ids(ns).rwsem); ++ /* ++ * 4) get a reference to shp. ++ * This cannot fail: shm_clist_rm() is called before ++ * ipc_rmid(), thus the refcount cannot be 0. ++ */ ++ WARN_ON(!ipc_rcu_getref(&shp->shm_perm)); ++ ++ /* ++ * 5) unlink the shm segment from the list of segments ++ * created by current. ++ * This must be done last. After unlinking, ++ * only the refcounts obtained above prevent IPC_RMID ++ * from destroying the segment or the namespace. ++ */ ++ list_del_init(&shp->shm_clist); ++ ++ task_unlock(task); ++ ++ /* ++ * 6) we have all references ++ * Thus lock & if needed destroy shp. ++ */ ++ down_write(&shm_ids(ns).rwsem); ++ shm_lock_by_ptr(shp); ++ /* ++ * rcu_read_lock was implicitly taken in shm_lock_by_ptr, it's ++ * safe to call ipc_rcu_putref here ++ */ ++ ipc_rcu_putref(&shp->shm_perm, shm_rcu_free); ++ ++ if (ipc_valid_object(&shp->shm_perm)) { ++ if (shm_may_destroy(shp)) ++ shm_destroy(ns, shp); ++ else ++ shm_unlock(shp); ++ } else { ++ /* ++ * Someone else deleted the shp from namespace ++ * idr/kht while we have waited. ++ * Just unlock and continue. ++ */ ++ shm_unlock(shp); ++ } ++ ++ up_write(&shm_ids(ns).rwsem); ++ put_ipc_ns(ns); /* paired with get_ipc_ns_not_zero */ ++ } + } + + static vm_fault_t shm_fault(struct vm_fault *vmf) +@@ -680,7 +772,11 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) + if (error < 0) + goto no_id; + ++ shp->ns = ns; ++ ++ task_lock(current); + list_add(&shp->shm_clist, ¤t->sysvshm.shm_clist); ++ task_unlock(current); + + /* + * shmid gets reported as "inode#" in /proc/pid/maps. +@@ -1573,7 +1669,8 @@ out_nattch: + down_write(&shm_ids(ns).rwsem); + shp = shm_lock(ns, shmid); + shp->shm_nattch--; +- if (shm_may_destroy(ns, shp)) ++ ++ if (shm_may_destroy(shp)) + shm_destroy(ns, shp); + else + shm_unlock(shp); +diff --git a/ipc/util.c b/ipc/util.c +index d48d8cfa1f3fa..fa2d86ef3fb80 100644 +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -447,8 +447,8 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, + static void ipc_kht_remove(struct ipc_ids *ids, struct kern_ipc_perm *ipcp) + { + if (ipcp->key != IPC_PRIVATE) +- rhashtable_remove_fast(&ids->key_ht, &ipcp->khtnode, +- ipc_kht_params); ++ WARN_ON_ONCE(rhashtable_remove_fast(&ids->key_ht, &ipcp->khtnode, ++ ipc_kht_params)); + } + + /** +@@ -498,7 +498,7 @@ void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp) + { + int idx = ipcid_to_idx(ipcp->id); + +- idr_remove(&ids->ipcs_idr, idx); ++ WARN_ON_ONCE(idr_remove(&ids->ipcs_idr, idx) != ipcp); + ipc_kht_remove(ids, ipcp); + ids->in_use--; + ipcp->deleted = true; +diff --git a/kernel/async.c b/kernel/async.c +index b8d7a663497f9..b2c4ba5686ee4 100644 +--- a/kernel/async.c ++++ b/kernel/async.c +@@ -205,9 +205,6 @@ async_cookie_t async_schedule_node_domain(async_func_t func, void *data, + atomic_inc(&entry_count); + spin_unlock_irqrestore(&async_lock, flags); + +- /* mark that this task has queued an async job, used by module init */ +- current->flags |= PF_USED_ASYNC; +- + /* schedule for execution */ + queue_work_node(node, system_unbound_wq, &entry->work); + +diff --git a/kernel/audit.c b/kernel/audit.c +index 121d37e700a62..94ded5de91317 100644 +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -541,20 +541,22 @@ static void kauditd_printk_skb(struct sk_buff *skb) + /** + * kauditd_rehold_skb - Handle a audit record send failure in the hold queue + * @skb: audit record ++ * @error: error code (unused) + * + * Description: + * This should only be used by the kauditd_thread when it fails to flush the + * hold queue. + */ +-static void kauditd_rehold_skb(struct sk_buff *skb) ++static void kauditd_rehold_skb(struct sk_buff *skb, __always_unused int error) + { +- /* put the record back in the queue at the same place */ +- skb_queue_head(&audit_hold_queue, skb); ++ /* put the record back in the queue */ ++ skb_queue_tail(&audit_hold_queue, skb); + } + + /** + * kauditd_hold_skb - Queue an audit record, waiting for auditd + * @skb: audit record ++ * @error: error code + * + * Description: + * Queue the audit record, waiting for an instance of auditd. When this +@@ -564,19 +566,31 @@ static void kauditd_rehold_skb(struct sk_buff *skb) + * and queue it, if we have room. If we want to hold on to the record, but we + * don't have room, record a record lost message. + */ +-static void kauditd_hold_skb(struct sk_buff *skb) ++static void kauditd_hold_skb(struct sk_buff *skb, int error) + { + /* at this point it is uncertain if we will ever send this to auditd so + * try to send the message via printk before we go any further */ + kauditd_printk_skb(skb); + + /* can we just silently drop the message? */ +- if (!audit_default) { +- kfree_skb(skb); +- return; ++ if (!audit_default) ++ goto drop; ++ ++ /* the hold queue is only for when the daemon goes away completely, ++ * not -EAGAIN failures; if we are in a -EAGAIN state requeue the ++ * record on the retry queue unless it's full, in which case drop it ++ */ ++ if (error == -EAGAIN) { ++ if (!audit_backlog_limit || ++ skb_queue_len(&audit_retry_queue) < audit_backlog_limit) { ++ skb_queue_tail(&audit_retry_queue, skb); ++ return; ++ } ++ audit_log_lost("kauditd retry queue overflow"); ++ goto drop; + } + +- /* if we have room, queue the message */ ++ /* if we have room in the hold queue, queue the message */ + if (!audit_backlog_limit || + skb_queue_len(&audit_hold_queue) < audit_backlog_limit) { + skb_queue_tail(&audit_hold_queue, skb); +@@ -585,24 +599,32 @@ static void kauditd_hold_skb(struct sk_buff *skb) + + /* we have no other options - drop the message */ + audit_log_lost("kauditd hold queue overflow"); ++drop: + kfree_skb(skb); + } + + /** + * kauditd_retry_skb - Queue an audit record, attempt to send again to auditd + * @skb: audit record ++ * @error: error code (unused) + * + * Description: + * Not as serious as kauditd_hold_skb() as we still have a connected auditd, + * but for some reason we are having problems sending it audit records so + * queue the given record and attempt to resend. + */ +-static void kauditd_retry_skb(struct sk_buff *skb) ++static void kauditd_retry_skb(struct sk_buff *skb, __always_unused int error) + { +- /* NOTE: because records should only live in the retry queue for a +- * short period of time, before either being sent or moved to the hold +- * queue, we don't currently enforce a limit on this queue */ +- skb_queue_tail(&audit_retry_queue, skb); ++ if (!audit_backlog_limit || ++ skb_queue_len(&audit_retry_queue) < audit_backlog_limit) { ++ skb_queue_tail(&audit_retry_queue, skb); ++ return; ++ } ++ ++ /* we have to drop the record, send it via printk as a last effort */ ++ kauditd_printk_skb(skb); ++ audit_log_lost("kauditd retry queue overflow"); ++ kfree_skb(skb); + } + + /** +@@ -640,7 +662,7 @@ static void auditd_reset(const struct auditd_connection *ac) + /* flush the retry queue to the hold queue, but don't touch the main + * queue since we need to process that normally for multicast */ + while ((skb = skb_dequeue(&audit_retry_queue))) +- kauditd_hold_skb(skb); ++ kauditd_hold_skb(skb, -ECONNREFUSED); + } + + /** +@@ -714,16 +736,18 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, + struct sk_buff_head *queue, + unsigned int retry_limit, + void (*skb_hook)(struct sk_buff *skb), +- void (*err_hook)(struct sk_buff *skb)) ++ void (*err_hook)(struct sk_buff *skb, int error)) + { + int rc = 0; +- struct sk_buff *skb; +- static unsigned int failed = 0; ++ struct sk_buff *skb = NULL; ++ struct sk_buff *skb_tail; ++ unsigned int failed = 0; + + /* NOTE: kauditd_thread takes care of all our locking, we just use + * the netlink info passed to us (e.g. sk and portid) */ + +- while ((skb = skb_dequeue(queue))) { ++ skb_tail = skb_peek_tail(queue); ++ while ((skb != skb_tail) && (skb = skb_dequeue(queue))) { + /* call the skb_hook for each skb we touch */ + if (skb_hook) + (*skb_hook)(skb); +@@ -731,36 +755,34 @@ static int kauditd_send_queue(struct sock *sk, u32 portid, + /* can we send to anyone via unicast? */ + if (!sk) { + if (err_hook) +- (*err_hook)(skb); ++ (*err_hook)(skb, -ECONNREFUSED); + continue; + } + ++retry: + /* grab an extra skb reference in case of error */ + skb_get(skb); + rc = netlink_unicast(sk, skb, portid, 0); + if (rc < 0) { +- /* fatal failure for our queue flush attempt? */ ++ /* send failed - try a few times unless fatal error */ + if (++failed >= retry_limit || + rc == -ECONNREFUSED || rc == -EPERM) { +- /* yes - error processing for the queue */ + sk = NULL; + if (err_hook) +- (*err_hook)(skb); +- if (!skb_hook) +- goto out; +- /* keep processing with the skb_hook */ ++ (*err_hook)(skb, rc); ++ if (rc == -EAGAIN) ++ rc = 0; ++ /* continue to drain the queue */ + continue; + } else +- /* no - requeue to preserve ordering */ +- skb_queue_head(queue, skb); ++ goto retry; + } else { +- /* it worked - drop the extra reference and continue */ ++ /* skb sent - drop the extra reference and continue */ + consume_skb(skb); + failed = 0; + } + } + +-out: + return (rc >= 0 ? 0 : rc); + } + +@@ -1542,6 +1564,20 @@ static void audit_receive(struct sk_buff *skb) + nlh = nlmsg_next(nlh, &len); + } + audit_ctl_unlock(); ++ ++ /* can't block with the ctrl lock, so penalize the sender now */ ++ if (audit_backlog_limit && ++ (skb_queue_len(&audit_queue) > audit_backlog_limit)) { ++ DECLARE_WAITQUEUE(wait, current); ++ ++ /* wake kauditd to try and flush the queue */ ++ wake_up_interruptible(&kauditd_wait); ++ ++ add_wait_queue_exclusive(&audit_backlog_wait, &wait); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(audit_backlog_wait_time); ++ remove_wait_queue(&audit_backlog_wait, &wait); ++ } + } + + /* Log information about who is connecting to the audit multicast socket */ +@@ -1609,7 +1645,8 @@ static int __net_init audit_net_init(struct net *net) + audit_panic("cannot initialize netlink socket in namespace"); + return -ENOMEM; + } +- aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; ++ /* limit the timeout in case auditd is blocked/stopped */ ++ aunet->sk->sk_sndtimeo = HZ / 10; + + return 0; + } +@@ -1825,7 +1862,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, + * task_tgid_vnr() since auditd_pid is set in audit_receive_msg() + * using a PID anchored in the caller's namespace + * 2. generator holding the audit_cmd_mutex - we don't want to block +- * while holding the mutex */ ++ * while holding the mutex, although we do penalize the sender ++ * later in audit_receive() when it is safe to block ++ */ + if (!(auditd_test_task(current) || audit_ctl_owner_current())) { + long stime = audit_backlog_wait_time; + +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index dfe61df4f974d..b8ed4da63bc8c 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -4332,8 +4332,7 @@ static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size, + log->len_total = log_size; + + /* log attributes have to be sane */ +- if (log->len_total < 128 || log->len_total > UINT_MAX >> 8 || +- !log->level || !log->ubuf) { ++ if (!bpf_verifier_log_attr_valid(log)) { + err = -EINVAL; + goto errout; + } +diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c +index 03145d45e3d5b..7dbd68195a2b0 100644 +--- a/kernel/bpf/cgroup.c ++++ b/kernel/bpf/cgroup.c +@@ -1773,6 +1773,8 @@ sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) + return &bpf_sysctl_get_new_value_proto; + case BPF_FUNC_sysctl_set_new_value: + return &bpf_sysctl_set_new_value_proto; ++ case BPF_FUNC_ktime_get_coarse_ns: ++ return &bpf_ktime_get_coarse_ns_proto; + default: + return cgroup_base_func_proto(func_id, prog); + } +diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c +index 9aabf84afd4b2..6f600cc95ccda 100644 +--- a/kernel/bpf/helpers.c ++++ b/kernel/bpf/helpers.c +@@ -1367,8 +1367,6 @@ bpf_base_func_proto(enum bpf_func_id func_id) + return &bpf_ktime_get_ns_proto; + case BPF_FUNC_ktime_get_boot_ns: + return &bpf_ktime_get_boot_ns_proto; +- case BPF_FUNC_ktime_get_coarse_ns: +- return &bpf_ktime_get_coarse_ns_proto; + case BPF_FUNC_ringbuf_output: + return &bpf_ringbuf_output_proto; + case BPF_FUNC_ringbuf_reserve: +diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c +index 80da1db47c686..5a8d9f7467bf4 100644 +--- a/kernel/bpf/inode.c ++++ b/kernel/bpf/inode.c +@@ -648,12 +648,22 @@ static int bpf_parse_param(struct fs_context *fc, struct fs_parameter *param) + int opt; + + opt = fs_parse(fc, bpf_fs_parameters, param, &result); +- if (opt < 0) ++ if (opt < 0) { + /* We might like to report bad mount options here, but + * traditionally we've ignored all mount options, so we'd + * better continue to ignore non-existing options for bpf. + */ +- return opt == -ENOPARAM ? 0 : opt; ++ if (opt == -ENOPARAM) { ++ opt = vfs_parse_fs_param_source(fc, param); ++ if (opt != -ENOPARAM) ++ return opt; ++ ++ return 0; ++ } ++ ++ if (opt < 0) ++ return opt; ++ } + + switch (opt) { + case OPT_MODE: +diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c +index 9e0c10c6892ad..f1c51c45667d3 100644 +--- a/kernel/bpf/ringbuf.c ++++ b/kernel/bpf/ringbuf.c +@@ -104,7 +104,7 @@ static struct bpf_ringbuf *bpf_ringbuf_area_alloc(size_t data_sz, int numa_node) + } + + rb = vmap(pages, nr_meta_pages + 2 * nr_data_pages, +- VM_ALLOC | VM_USERMAP, PAGE_KERNEL); ++ VM_MAP | VM_USERMAP, PAGE_KERNEL); + if (rb) { + kmemleak_not_leak(pages); + rb->pages = pages; +diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c +index 6e75bbee39f0b..0dcaed4d3f4ce 100644 +--- a/kernel/bpf/stackmap.c ++++ b/kernel/bpf/stackmap.c +@@ -525,13 +525,14 @@ BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf, + u32, size, u64, flags) + { + struct pt_regs *regs; +- long res; ++ long res = -EINVAL; + + if (!try_get_task_stack(task)) + return -EFAULT; + + regs = task_pt_regs(task); +- res = __bpf_get_stack(regs, task, NULL, buf, size, flags); ++ if (regs) ++ res = __bpf_get_stack(regs, task, NULL, buf, size, flags); + put_task_stack(task); + + return res; +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 1cad6979a0d0f..42490c39dfbf5 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -132,6 +132,21 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) + return map; + } + ++static void bpf_map_write_active_inc(struct bpf_map *map) ++{ ++ atomic64_inc(&map->writecnt); ++} ++ ++static void bpf_map_write_active_dec(struct bpf_map *map) ++{ ++ atomic64_dec(&map->writecnt); ++} ++ ++bool bpf_map_write_active(const struct bpf_map *map) ++{ ++ return atomic64_read(&map->writecnt) != 0; ++} ++ + static u32 bpf_map_value_size(const struct bpf_map *map) + { + if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || +@@ -596,11 +611,8 @@ static void bpf_map_mmap_open(struct vm_area_struct *vma) + { + struct bpf_map *map = vma->vm_file->private_data; + +- if (vma->vm_flags & VM_MAYWRITE) { +- mutex_lock(&map->freeze_mutex); +- map->writecnt++; +- mutex_unlock(&map->freeze_mutex); +- } ++ if (vma->vm_flags & VM_MAYWRITE) ++ bpf_map_write_active_inc(map); + } + + /* called for all unmapped memory region (including initial) */ +@@ -608,11 +620,8 @@ static void bpf_map_mmap_close(struct vm_area_struct *vma) + { + struct bpf_map *map = vma->vm_file->private_data; + +- if (vma->vm_flags & VM_MAYWRITE) { +- mutex_lock(&map->freeze_mutex); +- map->writecnt--; +- mutex_unlock(&map->freeze_mutex); +- } ++ if (vma->vm_flags & VM_MAYWRITE) ++ bpf_map_write_active_dec(map); + } + + static const struct vm_operations_struct bpf_map_default_vmops = { +@@ -663,7 +672,7 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) + goto out; + + if (vma->vm_flags & VM_MAYWRITE) +- map->writecnt++; ++ bpf_map_write_active_inc(map); + out: + mutex_unlock(&map->freeze_mutex); + return err; +@@ -1122,6 +1131,7 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr) + map = __bpf_map_get(f); + if (IS_ERR(map)) + return PTR_ERR(map); ++ bpf_map_write_active_inc(map); + if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { + err = -EPERM; + goto err_put; +@@ -1157,6 +1167,7 @@ free_value: + free_key: + kvfree(key); + err_put: ++ bpf_map_write_active_dec(map); + fdput(f); + return err; + } +@@ -1179,6 +1190,7 @@ static int map_delete_elem(union bpf_attr *attr) + map = __bpf_map_get(f); + if (IS_ERR(map)) + return PTR_ERR(map); ++ bpf_map_write_active_inc(map); + if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { + err = -EPERM; + goto err_put; +@@ -1209,6 +1221,7 @@ static int map_delete_elem(union bpf_attr *attr) + out: + kvfree(key); + err_put: ++ bpf_map_write_active_dec(map); + fdput(f); + return err; + } +@@ -1324,6 +1337,7 @@ int generic_map_delete_batch(struct bpf_map *map, + maybe_wait_bpf_programs(map); + if (err) + break; ++ cond_resched(); + } + if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp))) + err = -EFAULT; +@@ -1381,6 +1395,7 @@ int generic_map_update_batch(struct bpf_map *map, + + if (err) + break; ++ cond_resched(); + } + + if (copy_to_user(&uattr->batch.count, &cp, sizeof(cp))) +@@ -1478,6 +1493,7 @@ int generic_map_lookup_batch(struct bpf_map *map, + swap(prev_key, key); + retry = MAP_LOOKUP_RETRIES; + cp++; ++ cond_resched(); + } + + if (err == -EFAULT) +@@ -1516,6 +1532,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr) + map = __bpf_map_get(f); + if (IS_ERR(map)) + return PTR_ERR(map); ++ bpf_map_write_active_inc(map); + if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) || + !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { + err = -EPERM; +@@ -1580,6 +1597,7 @@ free_value: + free_key: + kvfree(key); + err_put: ++ bpf_map_write_active_dec(map); + fdput(f); + return err; + } +@@ -1607,8 +1625,7 @@ static int map_freeze(const union bpf_attr *attr) + } + + mutex_lock(&map->freeze_mutex); +- +- if (map->writecnt) { ++ if (bpf_map_write_active(map)) { + err = -EBUSY; + goto err_put; + } +@@ -1807,8 +1824,14 @@ static int bpf_prog_release(struct inode *inode, struct file *filp) + return 0; + } + ++struct bpf_prog_kstats { ++ u64 nsecs; ++ u64 cnt; ++ u64 misses; ++}; ++ + static void bpf_prog_get_stats(const struct bpf_prog *prog, +- struct bpf_prog_stats *stats) ++ struct bpf_prog_kstats *stats) + { + u64 nsecs = 0, cnt = 0, misses = 0; + int cpu; +@@ -1821,9 +1844,9 @@ static void bpf_prog_get_stats(const struct bpf_prog *prog, + st = per_cpu_ptr(prog->stats, cpu); + do { + start = u64_stats_fetch_begin_irq(&st->syncp); +- tnsecs = st->nsecs; +- tcnt = st->cnt; +- tmisses = st->misses; ++ tnsecs = u64_stats_read(&st->nsecs); ++ tcnt = u64_stats_read(&st->cnt); ++ tmisses = u64_stats_read(&st->misses); + } while (u64_stats_fetch_retry_irq(&st->syncp, start)); + nsecs += tnsecs; + cnt += tcnt; +@@ -1839,7 +1862,7 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp) + { + const struct bpf_prog *prog = filp->private_data; + char prog_tag[sizeof(prog->tag) * 2 + 1] = { }; +- struct bpf_prog_stats stats; ++ struct bpf_prog_kstats stats; + + bpf_prog_get_stats(prog, &stats); + bin2hex(prog_tag, prog->tag, sizeof(prog->tag)); +@@ -3578,7 +3601,7 @@ static int bpf_prog_get_info_by_fd(struct file *file, + struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info); + struct bpf_prog_info info; + u32 info_len = attr->info.info_len; +- struct bpf_prog_stats stats; ++ struct bpf_prog_kstats stats; + char __user *uinsns; + u32 ulen; + int err; +@@ -4143,6 +4166,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr, + union bpf_attr __user *uattr, + int cmd) + { ++ bool has_read = cmd == BPF_MAP_LOOKUP_BATCH || ++ cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH; ++ bool has_write = cmd != BPF_MAP_LOOKUP_BATCH; + struct bpf_map *map; + int err, ufd; + struct fd f; +@@ -4155,16 +4181,13 @@ static int bpf_map_do_batch(const union bpf_attr *attr, + map = __bpf_map_get(f); + if (IS_ERR(map)) + return PTR_ERR(map); +- +- if ((cmd == BPF_MAP_LOOKUP_BATCH || +- cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH) && +- !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { ++ if (has_write) ++ bpf_map_write_active_inc(map); ++ if (has_read && !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { + err = -EPERM; + goto err_put; + } +- +- if (cmd != BPF_MAP_LOOKUP_BATCH && +- !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { ++ if (has_write && !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { + err = -EPERM; + goto err_put; + } +@@ -4177,8 +4200,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr, + BPF_DO_BATCH(map->ops->map_update_batch); + else + BPF_DO_BATCH(map->ops->map_delete_batch); +- + err_put: ++ if (has_write) ++ bpf_map_write_active_dec(map); + fdput(f); + return err; + } +diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c +index fe1e857324e66..2660fbced9ad4 100644 +--- a/kernel/bpf/trampoline.c ++++ b/kernel/bpf/trampoline.c +@@ -541,11 +541,12 @@ static u64 notrace bpf_prog_start_time(void) + static void notrace inc_misses_counter(struct bpf_prog *prog) + { + struct bpf_prog_stats *stats; ++ unsigned int flags; + + stats = this_cpu_ptr(prog->stats); +- u64_stats_update_begin(&stats->syncp); +- stats->misses++; +- u64_stats_update_end(&stats->syncp); ++ flags = u64_stats_update_begin_irqsave(&stats->syncp); ++ u64_stats_inc(&stats->misses); ++ u64_stats_update_end_irqrestore(&stats->syncp, flags); + } + + /* The logic is similar to bpf_prog_run(), but with an explicit +@@ -585,11 +586,13 @@ static void notrace update_prog_stats(struct bpf_prog *prog, + * Hence check that 'start' is valid. + */ + start > NO_START_TIME) { ++ unsigned long flags; ++ + stats = this_cpu_ptr(prog->stats); +- u64_stats_update_begin(&stats->syncp); +- stats->cnt++; +- stats->nsecs += sched_clock() - start; +- u64_stats_update_end(&stats->syncp); ++ flags = u64_stats_update_begin_irqsave(&stats->syncp); ++ u64_stats_inc(&stats->cnt); ++ u64_stats_add(&stats->nsecs, sched_clock() - start); ++ u64_stats_update_end_irqrestore(&stats->syncp, flags); + } + } + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index e76b559179054..670721e39c0e8 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1143,7 +1143,8 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg) + /* transfer reg's id which is unique for every map_lookup_elem + * as UID of the inner map. + */ +- reg->map_uid = reg->id; ++ if (map_value_has_timer(map->inner_map_meta)) ++ reg->map_uid = reg->id; + } else if (map->map_type == BPF_MAP_TYPE_XSKMAP) { + reg->type = PTR_TO_XDP_SOCK; + } else if (map->map_type == BPF_MAP_TYPE_SOCKMAP || +@@ -1357,22 +1358,28 @@ static void __reg_bound_offset(struct bpf_reg_state *reg) + reg->var_off = tnum_or(tnum_clear_subreg(var64_off), var32_off); + } + ++static bool __reg32_bound_s64(s32 a) ++{ ++ return a >= 0 && a <= S32_MAX; ++} ++ + static void __reg_assign_32_into_64(struct bpf_reg_state *reg) + { + reg->umin_value = reg->u32_min_value; + reg->umax_value = reg->u32_max_value; +- /* Attempt to pull 32-bit signed bounds into 64-bit bounds +- * but must be positive otherwise set to worse case bounds +- * and refine later from tnum. ++ ++ /* Attempt to pull 32-bit signed bounds into 64-bit bounds but must ++ * be positive otherwise set to worse case bounds and refine later ++ * from tnum. + */ +- if (reg->s32_min_value >= 0 && reg->s32_max_value >= 0) +- reg->smax_value = reg->s32_max_value; +- else +- reg->smax_value = U32_MAX; +- if (reg->s32_min_value >= 0) ++ if (__reg32_bound_s64(reg->s32_min_value) && ++ __reg32_bound_s64(reg->s32_max_value)) { + reg->smin_value = reg->s32_min_value; +- else ++ reg->smax_value = reg->s32_max_value; ++ } else { + reg->smin_value = 0; ++ reg->smax_value = U32_MAX; ++ } + } + + static void __reg_combine_32_into_64(struct bpf_reg_state *reg) +@@ -1406,12 +1413,12 @@ static void __reg_combine_32_into_64(struct bpf_reg_state *reg) + + static bool __reg64_bound_s32(s64 a) + { +- return a > S32_MIN && a < S32_MAX; ++ return a >= S32_MIN && a <= S32_MAX; + } + + static bool __reg64_bound_u32(u64 a) + { +- return a > U32_MIN && a < U32_MAX; ++ return a >= U32_MIN && a <= U32_MAX; + } + + static void __reg_combine_64_into_32(struct bpf_reg_state *reg) +@@ -3884,7 +3891,22 @@ static void coerce_reg_to_size(struct bpf_reg_state *reg, int size) + + static bool bpf_map_is_rdonly(const struct bpf_map *map) + { +- return (map->map_flags & BPF_F_RDONLY_PROG) && map->frozen; ++ /* A map is considered read-only if the following condition are true: ++ * ++ * 1) BPF program side cannot change any of the map content. The ++ * BPF_F_RDONLY_PROG flag is throughout the lifetime of a map ++ * and was set at map creation time. ++ * 2) The map value(s) have been initialized from user space by a ++ * loader and then "frozen", such that no new map update/delete ++ * operations from syscall side are possible for the rest of ++ * the map's lifetime from that point onwards. ++ * 3) Any parallel/pending map update/delete operations from syscall ++ * side have been completed. Only after that point, it's safe to ++ * assume that map value(s) are immutable. ++ */ ++ return (map->map_flags & BPF_F_RDONLY_PROG) && ++ READ_ONCE(map->frozen) && ++ !bpf_map_write_active(map); + } + + static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val) +@@ -4364,9 +4386,16 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i + + if (insn->imm == BPF_CMPXCHG) { + /* Check comparison of R0 with memory location */ +- err = check_reg_arg(env, BPF_REG_0, SRC_OP); ++ const u32 aux_reg = BPF_REG_0; ++ ++ err = check_reg_arg(env, aux_reg, SRC_OP); + if (err) + return err; ++ ++ if (is_pointer_value(env, aux_reg)) { ++ verbose(env, "R%d leaks addr into mem\n", aux_reg); ++ return -EACCES; ++ } + } + + if (is_pointer_value(env, insn->src_reg)) { +@@ -4401,13 +4430,19 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i + load_reg = -1; + } + +- /* check whether we can read the memory */ ++ /* Check whether we can read the memory, with second call for fetch ++ * case to simulate the register fill. ++ */ + err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, +- BPF_SIZE(insn->code), BPF_READ, load_reg, true); ++ BPF_SIZE(insn->code), BPF_READ, -1, true); ++ if (!err && load_reg >= 0) ++ err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, ++ BPF_SIZE(insn->code), BPF_READ, load_reg, ++ true); + if (err) + return err; + +- /* check whether we can write into the same memory */ ++ /* Check whether we can write into the same memory. */ + err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, + BPF_SIZE(insn->code), BPF_WRITE, -1, true); + if (err) +@@ -5750,6 +5785,7 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn + } + + if (insn->code == (BPF_JMP | BPF_CALL) && ++ insn->src_reg == 0 && + insn->imm == BPF_FUNC_timer_set_callback) { + struct bpf_verifier_state *async_cb; + +@@ -7004,16 +7040,16 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + fallthrough; + case PTR_TO_PACKET_END: + case PTR_TO_SOCKET: +- case PTR_TO_SOCKET_OR_NULL: + case PTR_TO_SOCK_COMMON: +- case PTR_TO_SOCK_COMMON_OR_NULL: + case PTR_TO_TCP_SOCK: +- case PTR_TO_TCP_SOCK_OR_NULL: + case PTR_TO_XDP_SOCK: ++reject: + verbose(env, "R%d pointer arithmetic on %s prohibited\n", + dst, reg_type_str[ptr_reg->type]); + return -EACCES; + default: ++ if (reg_type_may_be_null(ptr_reg->type)) ++ goto reject; + break; + } + +@@ -8098,6 +8134,10 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) + insn->dst_reg); + } + zext_32_to_64(dst_reg); ++ ++ __update_reg_bounds(dst_reg); ++ __reg_deduce_bounds(dst_reg); ++ __reg_bound_offset(dst_reg); + } + } else { + /* case: R = imm +@@ -8212,7 +8252,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate, + + new_range = dst_reg->off; + if (range_right_open) +- new_range--; ++ new_range++; + + /* Examples for register markings: + * +@@ -8732,15 +8772,15 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state, + { + if (reg_type_may_be_null(reg->type) && reg->id == id && + !WARN_ON_ONCE(!reg->id)) { +- /* Old offset (both fixed and variable parts) should +- * have been known-zero, because we don't allow pointer +- * arithmetic on pointers that might be NULL. +- */ + if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || + !tnum_equals_const(reg->var_off, 0) || + reg->off)) { +- __mark_reg_known_zero(reg); +- reg->off = 0; ++ /* Old offset (both fixed and variable parts) should ++ * have been known-zero, because we don't allow pointer ++ * arithmetic on pointers that might be NULL. If we ++ * see this happening, don't convert the register. ++ */ ++ return; + } + if (is_null) { + reg->type = SCALAR_VALUE; +@@ -9159,9 +9199,13 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) + return 0; + } + +- if (insn->src_reg == BPF_PSEUDO_BTF_ID) { +- mark_reg_known_zero(env, regs, insn->dst_reg); ++ /* All special src_reg cases are listed below. From this point onwards ++ * we either succeed and assign a corresponding dst_reg->type after ++ * zeroing the offset, or fail and reject the program. ++ */ ++ mark_reg_known_zero(env, regs, insn->dst_reg); + ++ if (insn->src_reg == BPF_PSEUDO_BTF_ID) { + dst_reg->type = aux->btf_var.reg_type; + switch (dst_reg->type) { + case PTR_TO_MEM: +@@ -9198,7 +9242,6 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn) + } + + map = env->used_maps[aux->map_index]; +- mark_reg_known_zero(env, regs, insn->dst_reg); + dst_reg->map_ptr = map; + + if (insn->src_reg == BPF_PSEUDO_MAP_VALUE || +@@ -11435,6 +11478,13 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env, + } + } + ++ if (map_value_has_timer(map)) { ++ if (is_tracing_prog_type(prog_type)) { ++ verbose(env, "tracing progs cannot use bpf_timer yet\n"); ++ return -EINVAL; ++ } ++ } ++ + if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) && + !bpf_offload_prog_map_match(prog, map)) { + verbose(env, "offload device mismatch between prog and map\n"); +@@ -13713,11 +13763,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr) + log->ubuf = (char __user *) (unsigned long) attr->log_buf; + log->len_total = attr->log_size; + +- ret = -EINVAL; + /* log attributes have to be sane */ +- if (log->len_total < 128 || log->len_total > UINT_MAX >> 2 || +- !log->level || !log->ubuf || log->level & ~BPF_LOG_MASK) ++ if (!bpf_verifier_log_attr_valid(log)) { ++ ret = -EINVAL; + goto err_unlock; ++ } + } + + if (IS_ERR(btf_vmlinux)) { +diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h +index bfbeabc17a9df..6e36e854b5124 100644 +--- a/kernel/cgroup/cgroup-internal.h ++++ b/kernel/cgroup/cgroup-internal.h +@@ -65,6 +65,25 @@ static inline struct cgroup_fs_context *cgroup_fc2context(struct fs_context *fc) + return container_of(kfc, struct cgroup_fs_context, kfc); + } + ++struct cgroup_pidlist; ++ ++struct cgroup_file_ctx { ++ struct cgroup_namespace *ns; ++ ++ struct { ++ void *trigger; ++ } psi; ++ ++ struct { ++ bool started; ++ struct css_task_iter iter; ++ } procs; ++ ++ struct { ++ struct cgroup_pidlist *pidlist; ++ } procs1; ++}; ++ + /* + * A cgroup can be associated with multiple css_sets as different tasks may + * belong to different cgroups on different hierarchies. In the other +diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c +index 35b9203283447..58900dc92ac98 100644 +--- a/kernel/cgroup/cgroup-v1.c ++++ b/kernel/cgroup/cgroup-v1.c +@@ -397,6 +397,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos) + * next pid to display, if any + */ + struct kernfs_open_file *of = s->private; ++ struct cgroup_file_ctx *ctx = of->priv; + struct cgroup *cgrp = seq_css(s)->cgroup; + struct cgroup_pidlist *l; + enum cgroup_filetype type = seq_cft(s)->private; +@@ -406,25 +407,24 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos) + mutex_lock(&cgrp->pidlist_mutex); + + /* +- * !NULL @of->priv indicates that this isn't the first start() +- * after open. If the matching pidlist is around, we can use that. +- * Look for it. Note that @of->priv can't be used directly. It +- * could already have been destroyed. ++ * !NULL @ctx->procs1.pidlist indicates that this isn't the first ++ * start() after open. If the matching pidlist is around, we can use ++ * that. Look for it. Note that @ctx->procs1.pidlist can't be used ++ * directly. It could already have been destroyed. + */ +- if (of->priv) +- of->priv = cgroup_pidlist_find(cgrp, type); ++ if (ctx->procs1.pidlist) ++ ctx->procs1.pidlist = cgroup_pidlist_find(cgrp, type); + + /* + * Either this is the first start() after open or the matching + * pidlist has been destroyed inbetween. Create a new one. + */ +- if (!of->priv) { +- ret = pidlist_array_load(cgrp, type, +- (struct cgroup_pidlist **)&of->priv); ++ if (!ctx->procs1.pidlist) { ++ ret = pidlist_array_load(cgrp, type, &ctx->procs1.pidlist); + if (ret) + return ERR_PTR(ret); + } +- l = of->priv; ++ l = ctx->procs1.pidlist; + + if (pid) { + int end = l->length; +@@ -452,7 +452,8 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos) + static void cgroup_pidlist_stop(struct seq_file *s, void *v) + { + struct kernfs_open_file *of = s->private; +- struct cgroup_pidlist *l = of->priv; ++ struct cgroup_file_ctx *ctx = of->priv; ++ struct cgroup_pidlist *l = ctx->procs1.pidlist; + + if (l) + mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork, +@@ -463,7 +464,8 @@ static void cgroup_pidlist_stop(struct seq_file *s, void *v) + static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) + { + struct kernfs_open_file *of = s->private; +- struct cgroup_pidlist *l = of->priv; ++ struct cgroup_file_ctx *ctx = of->priv; ++ struct cgroup_pidlist *l = ctx->procs1.pidlist; + pid_t *p = v; + pid_t *end = l->list + l->length; + /* +@@ -507,10 +509,11 @@ static ssize_t __cgroup1_procs_write(struct kernfs_open_file *of, + goto out_unlock; + + /* +- * Even if we're attaching all tasks in the thread group, we only +- * need to check permissions on one of them. ++ * Even if we're attaching all tasks in the thread group, we only need ++ * to check permissions on one of them. Check permissions using the ++ * credentials from file open to protect against inherited fd attacks. + */ +- cred = current_cred(); ++ cred = of->file->f_cred; + tcred = get_task_cred(task); + if (!uid_eq(cred->euid, GLOBAL_ROOT_UID) && + !uid_eq(cred->euid, tcred->uid) && +@@ -546,9 +549,19 @@ static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, loff_t off) + { + struct cgroup *cgrp; ++ struct cgroup_file_ctx *ctx; + + BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); + ++ /* ++ * Release agent gets called with all capabilities, ++ * require capabilities to set release agent. ++ */ ++ ctx = of->priv; ++ if ((ctx->ns->user_ns != &init_user_ns) || ++ !file_ns_capable(of->file, &init_user_ns, CAP_SYS_ADMIN)) ++ return -EPERM; ++ + cgrp = cgroup_kn_lock_live(of->kn, false); + if (!cgrp) + return -ENODEV; +@@ -960,6 +973,12 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param) + /* Specifying two release agents is forbidden */ + if (ctx->release_agent) + return invalfc(fc, "release_agent respecified"); ++ /* ++ * Release agent gets called with all capabilities, ++ * require capabilities to set release agent. ++ */ ++ if ((fc->user_ns != &init_user_ns) || !capable(CAP_SYS_ADMIN)) ++ return invalfc(fc, "Setting release_agent not allowed"); + ctx->release_agent = param->string; + param->string = NULL; + break; +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index ea08f01d0111a..de8b4fa1e1fd6 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -1740,6 +1740,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) + struct cgroup *dcgrp = &dst_root->cgrp; + struct cgroup_subsys *ss; + int ssid, i, ret; ++ u16 dfl_disable_ss_mask = 0; + + lockdep_assert_held(&cgroup_mutex); + +@@ -1756,8 +1757,28 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) + /* can't move between two non-dummy roots either */ + if (ss->root != &cgrp_dfl_root && dst_root != &cgrp_dfl_root) + return -EBUSY; ++ ++ /* ++ * Collect ssid's that need to be disabled from default ++ * hierarchy. ++ */ ++ if (ss->root == &cgrp_dfl_root) ++ dfl_disable_ss_mask |= 1 << ssid; ++ + } while_each_subsys_mask(); + ++ if (dfl_disable_ss_mask) { ++ struct cgroup *scgrp = &cgrp_dfl_root.cgrp; ++ ++ /* ++ * Controllers from default hierarchy that need to be rebound ++ * are all disabled together in one go. ++ */ ++ cgrp_dfl_root.subsys_mask &= ~dfl_disable_ss_mask; ++ WARN_ON(cgroup_apply_control(scgrp)); ++ cgroup_finalize_control(scgrp, 0); ++ } ++ + do_each_subsys_mask(ss, ssid, ss_mask) { + struct cgroup_root *src_root = ss->root; + struct cgroup *scgrp = &src_root->cgrp; +@@ -1766,10 +1787,12 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask) + + WARN_ON(!css || cgroup_css(dcgrp, ss)); + +- /* disable from the source */ +- src_root->subsys_mask &= ~(1 << ssid); +- WARN_ON(cgroup_apply_control(scgrp)); +- cgroup_finalize_control(scgrp, 0); ++ if (src_root != &cgrp_dfl_root) { ++ /* disable from the source */ ++ src_root->subsys_mask &= ~(1 << ssid); ++ WARN_ON(cgroup_apply_control(scgrp)); ++ cgroup_finalize_control(scgrp, 0); ++ } + + /* rebind */ + RCU_INIT_POINTER(scgrp->subsys[ssid], NULL); +@@ -3607,6 +3630,7 @@ static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v) + static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf, + size_t nbytes, enum psi_res res) + { ++ struct cgroup_file_ctx *ctx = of->priv; + struct psi_trigger *new; + struct cgroup *cgrp; + struct psi_group *psi; +@@ -3618,6 +3642,12 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf, + cgroup_get(cgrp); + cgroup_kn_unlock(of->kn); + ++ /* Allow only one trigger per file descriptor */ ++ if (ctx->psi.trigger) { ++ cgroup_put(cgrp); ++ return -EBUSY; ++ } ++ + psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi; + new = psi_trigger_create(psi, buf, nbytes, res); + if (IS_ERR(new)) { +@@ -3625,8 +3655,7 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf, + return PTR_ERR(new); + } + +- psi_trigger_replace(&of->priv, new); +- ++ smp_store_release(&ctx->psi.trigger, new); + cgroup_put(cgrp); + + return nbytes; +@@ -3656,12 +3685,16 @@ static ssize_t cgroup_cpu_pressure_write(struct kernfs_open_file *of, + static __poll_t cgroup_pressure_poll(struct kernfs_open_file *of, + poll_table *pt) + { +- return psi_trigger_poll(&of->priv, of->file, pt); ++ struct cgroup_file_ctx *ctx = of->priv; ++ ++ return psi_trigger_poll(&ctx->psi.trigger, of->file, pt); + } + + static void cgroup_pressure_release(struct kernfs_open_file *of) + { +- psi_trigger_replace(&of->priv, NULL); ++ struct cgroup_file_ctx *ctx = of->priv; ++ ++ psi_trigger_destroy(ctx->psi.trigger); + } + + bool cgroup_psi_enabled(void) +@@ -3788,24 +3821,43 @@ static ssize_t cgroup_kill_write(struct kernfs_open_file *of, char *buf, + static int cgroup_file_open(struct kernfs_open_file *of) + { + struct cftype *cft = of_cft(of); ++ struct cgroup_file_ctx *ctx; ++ int ret; + +- if (cft->open) +- return cft->open(of); +- return 0; ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ ctx->ns = current->nsproxy->cgroup_ns; ++ get_cgroup_ns(ctx->ns); ++ of->priv = ctx; ++ ++ if (!cft->open) ++ return 0; ++ ++ ret = cft->open(of); ++ if (ret) { ++ put_cgroup_ns(ctx->ns); ++ kfree(ctx); ++ } ++ return ret; + } + + static void cgroup_file_release(struct kernfs_open_file *of) + { + struct cftype *cft = of_cft(of); ++ struct cgroup_file_ctx *ctx = of->priv; + + if (cft->release) + cft->release(of); ++ put_cgroup_ns(ctx->ns); ++ kfree(ctx); + } + + static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, + size_t nbytes, loff_t off) + { +- struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; ++ struct cgroup_file_ctx *ctx = of->priv; + struct cgroup *cgrp = of->kn->parent->priv; + struct cftype *cft = of_cft(of); + struct cgroup_subsys_state *css; +@@ -3822,7 +3874,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, + */ + if ((cgrp->root->flags & CGRP_ROOT_NS_DELEGATE) && + !(cft->flags & CFTYPE_NS_DELEGATABLE) && +- ns != &init_cgroup_ns && ns->root_cset->dfl_cgrp == cgrp) ++ ctx->ns != &init_cgroup_ns && ctx->ns->root_cset->dfl_cgrp == cgrp) + return -EPERM; + + if (cft->write) +@@ -4728,21 +4780,21 @@ void css_task_iter_end(struct css_task_iter *it) + + static void cgroup_procs_release(struct kernfs_open_file *of) + { +- if (of->priv) { +- css_task_iter_end(of->priv); +- kfree(of->priv); +- } ++ struct cgroup_file_ctx *ctx = of->priv; ++ ++ if (ctx->procs.started) ++ css_task_iter_end(&ctx->procs.iter); + } + + static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos) + { + struct kernfs_open_file *of = s->private; +- struct css_task_iter *it = of->priv; ++ struct cgroup_file_ctx *ctx = of->priv; + + if (pos) + (*pos)++; + +- return css_task_iter_next(it); ++ return css_task_iter_next(&ctx->procs.iter); + } + + static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos, +@@ -4750,21 +4802,18 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos, + { + struct kernfs_open_file *of = s->private; + struct cgroup *cgrp = seq_css(s)->cgroup; +- struct css_task_iter *it = of->priv; ++ struct cgroup_file_ctx *ctx = of->priv; ++ struct css_task_iter *it = &ctx->procs.iter; + + /* + * When a seq_file is seeked, it's always traversed sequentially + * from position 0, so we can simply keep iterating on !0 *pos. + */ +- if (!it) { ++ if (!ctx->procs.started) { + if (WARN_ON_ONCE((*pos))) + return ERR_PTR(-EINVAL); +- +- it = kzalloc(sizeof(*it), GFP_KERNEL); +- if (!it) +- return ERR_PTR(-ENOMEM); +- of->priv = it; + css_task_iter_start(&cgrp->self, iter_flags, it); ++ ctx->procs.started = true; + } else if (!(*pos)) { + css_task_iter_end(it); + css_task_iter_start(&cgrp->self, iter_flags, it); +@@ -4815,9 +4864,9 @@ static int cgroup_may_write(const struct cgroup *cgrp, struct super_block *sb) + + static int cgroup_procs_write_permission(struct cgroup *src_cgrp, + struct cgroup *dst_cgrp, +- struct super_block *sb) ++ struct super_block *sb, ++ struct cgroup_namespace *ns) + { +- struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; + struct cgroup *com_cgrp = src_cgrp; + int ret; + +@@ -4846,11 +4895,12 @@ static int cgroup_procs_write_permission(struct cgroup *src_cgrp, + + static int cgroup_attach_permissions(struct cgroup *src_cgrp, + struct cgroup *dst_cgrp, +- struct super_block *sb, bool threadgroup) ++ struct super_block *sb, bool threadgroup, ++ struct cgroup_namespace *ns) + { + int ret = 0; + +- ret = cgroup_procs_write_permission(src_cgrp, dst_cgrp, sb); ++ ret = cgroup_procs_write_permission(src_cgrp, dst_cgrp, sb, ns); + if (ret) + return ret; + +@@ -4867,8 +4917,10 @@ static int cgroup_attach_permissions(struct cgroup *src_cgrp, + static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf, + bool threadgroup) + { ++ struct cgroup_file_ctx *ctx = of->priv; + struct cgroup *src_cgrp, *dst_cgrp; + struct task_struct *task; ++ const struct cred *saved_cred; + ssize_t ret; + bool locked; + +@@ -4886,9 +4938,16 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf, + src_cgrp = task_cgroup_from_root(task, &cgrp_dfl_root); + spin_unlock_irq(&css_set_lock); + +- /* process and thread migrations follow same delegation rule */ ++ /* ++ * Process and thread migrations follow same delegation rule. Check ++ * permissions using the credentials from file open to protect against ++ * inherited fd attacks. ++ */ ++ saved_cred = override_creds(of->file->f_cred); + ret = cgroup_attach_permissions(src_cgrp, dst_cgrp, +- of->file->f_path.dentry->d_sb, threadgroup); ++ of->file->f_path.dentry->d_sb, ++ threadgroup, ctx->ns); ++ revert_creds(saved_cred); + if (ret) + goto out_finish; + +@@ -6104,7 +6163,8 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs) + goto err; + + ret = cgroup_attach_permissions(cset->dfl_cgrp, dst_cgrp, sb, +- !(kargs->flags & CLONE_THREAD)); ++ !(kargs->flags & CLONE_THREAD), ++ current->nsproxy->cgroup_ns); + if (ret) + goto err; + +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index 2a9695ccb65f5..f6794602ab10c 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -1512,10 +1512,15 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs, + struct cpuset *sibling; + struct cgroup_subsys_state *pos_css; + ++ percpu_rwsem_assert_held(&cpuset_rwsem); ++ + /* + * Check all its siblings and call update_cpumasks_hier() + * if their use_parent_ecpus flag is set in order for them + * to use the right effective_cpus value. ++ * ++ * The update_cpumasks_hier() function may sleep. So we have to ++ * release the RCU read lock before calling it. + */ + rcu_read_lock(); + cpuset_for_each_child(sibling, pos_css, parent) { +@@ -1523,8 +1528,13 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs, + continue; + if (!sibling->use_parent_ecpus) + continue; ++ if (!css_tryget_online(&sibling->css)) ++ continue; + ++ rcu_read_unlock(); + update_cpumasks_hier(sibling, tmp); ++ rcu_read_lock(); ++ css_put(&sibling->css); + } + rcu_read_unlock(); + } +@@ -1597,8 +1607,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, + * Make sure that subparts_cpus is a subset of cpus_allowed. + */ + if (cs->nr_subparts_cpus) { +- cpumask_andnot(cs->subparts_cpus, cs->subparts_cpus, +- cs->cpus_allowed); ++ cpumask_and(cs->subparts_cpus, cs->subparts_cpus, cs->cpus_allowed); + cs->nr_subparts_cpus = cpumask_weight(cs->subparts_cpus); + } + spin_unlock_irq(&callback_lock); +@@ -2240,6 +2249,7 @@ static void cpuset_attach(struct cgroup_taskset *tset) + cgroup_taskset_first(tset, &css); + cs = css_cs(css); + ++ cpus_read_lock(); + percpu_down_write(&cpuset_rwsem); + + guarantee_online_mems(cs, &cpuset_attach_nodemask_to); +@@ -2293,6 +2303,7 @@ static void cpuset_attach(struct cgroup_taskset *tset) + wake_up(&cpuset_attach_wq); + + percpu_up_write(&cpuset_rwsem); ++ cpus_read_unlock(); + } + + /* The various types of files and directories in a cpuset file system */ +diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c +index b264ab5652ba9..1486768f23185 100644 +--- a/kernel/cgroup/rstat.c ++++ b/kernel/cgroup/rstat.c +@@ -433,8 +433,6 @@ static void root_cgroup_cputime(struct task_cputime *cputime) + cputime->sum_exec_runtime += user; + cputime->sum_exec_runtime += sys; + cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL]; +- cputime->sum_exec_runtime += cpustat[CPUTIME_GUEST]; +- cputime->sum_exec_runtime += cpustat[CPUTIME_GUEST_NICE]; + } + } + +diff --git a/kernel/cpu.c b/kernel/cpu.c +index 192e43a874076..407a2568f35eb 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -31,6 +31,7 @@ + #include <linux/smpboot.h> + #include <linux/relay.h> + #include <linux/slab.h> ++#include <linux/scs.h> + #include <linux/percpu-rwsem.h> + #include <linux/cpuset.h> + +@@ -587,6 +588,12 @@ static int bringup_cpu(unsigned int cpu) + struct task_struct *idle = idle_thread_get(cpu); + int ret; + ++ /* ++ * Reset stale stack state from the last time this CPU was online. ++ */ ++ scs_task_reset(idle); ++ kasan_unpoison_task_stack(idle); ++ + /* + * Some architectures have to walk the irq descriptors to + * setup the vector space for the cpu which comes online. +diff --git a/kernel/crash_core.c b/kernel/crash_core.c +index eb53f5ec62c90..256cf6db573cd 100644 +--- a/kernel/crash_core.c ++++ b/kernel/crash_core.c +@@ -6,6 +6,7 @@ + + #include <linux/buildid.h> + #include <linux/crash_core.h> ++#include <linux/init.h> + #include <linux/utsname.h> + #include <linux/vmalloc.h> + +@@ -295,6 +296,16 @@ int __init parse_crashkernel_low(char *cmdline, + "crashkernel=", suffix_tbl[SUFFIX_LOW]); + } + ++/* ++ * Add a dummy early_param handler to mark crashkernel= as a known command line ++ * parameter and suppress incorrect warnings in init/main.c. ++ */ ++static int __init parse_crashkernel_dummy(char *arg) ++{ ++ return 0; ++} ++early_param("crashkernel", parse_crashkernel_dummy); ++ + Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type, + void *data, size_t data_len) + { +diff --git a/kernel/cred.c b/kernel/cred.c +index 1ae0b4948a5a8..933155c969227 100644 +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -665,26 +665,20 @@ EXPORT_SYMBOL(cred_fscmp); + + int set_cred_ucounts(struct cred *new) + { +- struct task_struct *task = current; +- const struct cred *old = task->real_cred; + struct ucounts *new_ucounts, *old_ucounts = new->ucounts; + +- if (new->user == old->user && new->user_ns == old->user_ns) +- return 0; +- + /* + * This optimization is needed because alloc_ucounts() uses locks + * for table lookups. + */ +- if (old_ucounts && old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid)) ++ if (old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->uid)) + return 0; + +- if (!(new_ucounts = alloc_ucounts(new->user_ns, new->euid))) ++ if (!(new_ucounts = alloc_ucounts(new->user_ns, new->uid))) + return -EAGAIN; + + new->ucounts = new_ucounts; +- if (old_ucounts) +- put_ucounts(old_ucounts); ++ put_ucounts(old_ucounts); + + return 0; + } +diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c +index 1f9f0e47aedaa..10b454554ab03 100644 +--- a/kernel/debug/kdb/kdb_bt.c ++++ b/kernel/debug/kdb/kdb_bt.c +@@ -46,7 +46,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr) + * btp <pid> Kernel stack for <pid> + * btt <address-expression> Kernel stack for task structure at + * <address-expression> +- * bta [DRSTCZEUIMA] All useful processes, optionally ++ * bta [state_chars>|A] All useful processes, optionally + * filtered by state + * btc [<cpu>] The current process on one cpu, + * default is all cpus +@@ -74,7 +74,7 @@ static void kdb_show_stack(struct task_struct *p, void *addr) + */ + + static int +-kdb_bt1(struct task_struct *p, unsigned long mask, bool btaprompt) ++kdb_bt1(struct task_struct *p, const char *mask, bool btaprompt) + { + char ch; + +@@ -120,7 +120,7 @@ kdb_bt_cpu(unsigned long cpu) + return; + } + +- kdb_bt1(kdb_tsk, ~0UL, false); ++ kdb_bt1(kdb_tsk, "A", false); + } + + int +@@ -138,8 +138,8 @@ kdb_bt(int argc, const char **argv) + if (strcmp(argv[0], "bta") == 0) { + struct task_struct *g, *p; + unsigned long cpu; +- unsigned long mask = kdb_task_state_string(argc ? argv[1] : +- NULL); ++ const char *mask = argc ? argv[1] : kdbgetenv("PS"); ++ + if (argc == 0) + kdb_ps_suppressed(); + /* Run the active tasks first */ +@@ -167,7 +167,7 @@ kdb_bt(int argc, const char **argv) + return diag; + p = find_task_by_pid_ns(pid, &init_pid_ns); + if (p) +- return kdb_bt1(p, ~0UL, false); ++ return kdb_bt1(p, "A", false); + kdb_printf("No process with pid == %ld found\n", pid); + return 0; + } else if (strcmp(argv[0], "btt") == 0) { +@@ -176,7 +176,7 @@ kdb_bt(int argc, const char **argv) + diag = kdbgetularg((char *)argv[1], &addr); + if (diag) + return diag; +- return kdb_bt1((struct task_struct *)addr, ~0UL, false); ++ return kdb_bt1((struct task_struct *)addr, "A", false); + } else if (strcmp(argv[0], "btc") == 0) { + unsigned long cpu = ~0; + if (argc > 1) +@@ -212,7 +212,7 @@ kdb_bt(int argc, const char **argv) + kdb_show_stack(kdb_current_task, (void *)addr); + return 0; + } else { +- return kdb_bt1(kdb_current_task, ~0UL, false); ++ return kdb_bt1(kdb_current_task, "A", false); + } + } + +diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c +index fa6deda894a17..0852a537dad4c 100644 +--- a/kernel/debug/kdb/kdb_main.c ++++ b/kernel/debug/kdb/kdb_main.c +@@ -2203,8 +2203,8 @@ static void kdb_cpu_status(void) + state = 'D'; /* cpu is online but unresponsive */ + } else { + state = ' '; /* cpu is responding to kdb */ +- if (kdb_task_state_char(KDB_TSK(i)) == 'I') +- state = 'I'; /* idle task */ ++ if (kdb_task_state_char(KDB_TSK(i)) == '-') ++ state = '-'; /* idle task */ + } + if (state != prev_state) { + if (prev_state != '?') { +@@ -2271,37 +2271,30 @@ static int kdb_cpu(int argc, const char **argv) + void kdb_ps_suppressed(void) + { + int idle = 0, daemon = 0; +- unsigned long mask_I = kdb_task_state_string("I"), +- mask_M = kdb_task_state_string("M"); + unsigned long cpu; + const struct task_struct *p, *g; + for_each_online_cpu(cpu) { + p = kdb_curr_task(cpu); +- if (kdb_task_state(p, mask_I)) ++ if (kdb_task_state(p, "-")) + ++idle; + } + for_each_process_thread(g, p) { +- if (kdb_task_state(p, mask_M)) ++ if (kdb_task_state(p, "ims")) + ++daemon; + } + if (idle || daemon) { + if (idle) +- kdb_printf("%d idle process%s (state I)%s\n", ++ kdb_printf("%d idle process%s (state -)%s\n", + idle, idle == 1 ? "" : "es", + daemon ? " and " : ""); + if (daemon) +- kdb_printf("%d sleeping system daemon (state M) " ++ kdb_printf("%d sleeping system daemon (state [ims]) " + "process%s", daemon, + daemon == 1 ? "" : "es"); + kdb_printf(" suppressed,\nuse 'ps A' to see all.\n"); + } + } + +-/* +- * kdb_ps - This function implements the 'ps' command which shows a +- * list of the active processes. +- * ps [DRSTCZEUIMA] All processes, optionally filtered by state +- */ + void kdb_ps1(const struct task_struct *p) + { + int cpu; +@@ -2330,17 +2323,25 @@ void kdb_ps1(const struct task_struct *p) + } + } + ++/* ++ * kdb_ps - This function implements the 'ps' command which shows a ++ * list of the active processes. ++ * ++ * ps [<state_chars>] Show processes, optionally selecting only those whose ++ * state character is found in <state_chars>. ++ */ + static int kdb_ps(int argc, const char **argv) + { + struct task_struct *g, *p; +- unsigned long mask, cpu; ++ const char *mask; ++ unsigned long cpu; + + if (argc == 0) + kdb_ps_suppressed(); + kdb_printf("%-*s Pid Parent [*] cpu State %-*s Command\n", + (int)(2*sizeof(void *))+2, "Task Addr", + (int)(2*sizeof(void *))+2, "Thread"); +- mask = kdb_task_state_string(argc ? argv[1] : NULL); ++ mask = argc ? argv[1] : kdbgetenv("PS"); + /* Run the active tasks first */ + for_each_online_cpu(cpu) { + if (KDB_FLAG(CMD_INTERRUPT)) +@@ -2742,8 +2743,8 @@ static kdbtab_t maintab[] = { + }, + { .name = "bta", + .func = kdb_bt, +- .usage = "[D|R|S|T|C|Z|E|U|I|M|A]", +- .help = "Backtrace all processes matching state flag", ++ .usage = "[<state_chars>|A]", ++ .help = "Backtrace all processes whose state matches", + .flags = KDB_ENABLE_INSPECT, + }, + { .name = "btc", +@@ -2797,7 +2798,7 @@ static kdbtab_t maintab[] = { + }, + { .name = "ps", + .func = kdb_ps, +- .usage = "[<flags>|A]", ++ .usage = "[<state_chars>|A]", + .help = "Display active task list", + .flags = KDB_ENABLE_INSPECT, + }, +diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h +index 629590084a0dc..0d2f9feea0a46 100644 +--- a/kernel/debug/kdb/kdb_private.h ++++ b/kernel/debug/kdb/kdb_private.h +@@ -190,10 +190,8 @@ extern char kdb_grep_string[]; + extern int kdb_grep_leading; + extern int kdb_grep_trailing; + extern char *kdb_cmds[]; +-extern unsigned long kdb_task_state_string(const char *); + extern char kdb_task_state_char (const struct task_struct *); +-extern unsigned long kdb_task_state(const struct task_struct *p, +- unsigned long mask); ++extern bool kdb_task_state(const struct task_struct *p, const char *mask); + extern void kdb_ps_suppressed(void); + extern void kdb_ps1(const struct task_struct *p); + extern void kdb_send_sig(struct task_struct *p, int sig); +diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c +index 7507d9a8dc6ac..df2bface866ef 100644 +--- a/kernel/debug/kdb/kdb_support.c ++++ b/kernel/debug/kdb/kdb_support.c +@@ -24,6 +24,7 @@ + #include <linux/uaccess.h> + #include <linux/kdb.h> + #include <linux/slab.h> ++#include <linux/ctype.h> + #include "kdb_private.h" + + /* +@@ -473,82 +474,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size) + return diag; + } + +-/* +- * kdb_task_state_string - Convert a string containing any of the +- * letters DRSTCZEUIMA to a mask for the process state field and +- * return the value. If no argument is supplied, return the mask +- * that corresponds to environment variable PS, DRSTCZEU by +- * default. +- * Inputs: +- * s String to convert +- * Returns: +- * Mask for process state. +- * Notes: +- * The mask folds data from several sources into a single long value, so +- * be careful not to overlap the bits. TASK_* bits are in the LSB, +- * special cases like UNRUNNABLE are in the MSB. As of 2.6.10-rc1 there +- * is no overlap between TASK_* and EXIT_* but that may not always be +- * true, so EXIT_* bits are shifted left 16 bits before being stored in +- * the mask. +- */ +- +-/* unrunnable is < 0 */ +-#define UNRUNNABLE (1UL << (8*sizeof(unsigned long) - 1)) +-#define RUNNING (1UL << (8*sizeof(unsigned long) - 2)) +-#define IDLE (1UL << (8*sizeof(unsigned long) - 3)) +-#define DAEMON (1UL << (8*sizeof(unsigned long) - 4)) + +-unsigned long kdb_task_state_string(const char *s) +-{ +- long res = 0; +- if (!s) { +- s = kdbgetenv("PS"); +- if (!s) +- s = "DRSTCZEU"; /* default value for ps */ +- } +- while (*s) { +- switch (*s) { +- case 'D': +- res |= TASK_UNINTERRUPTIBLE; +- break; +- case 'R': +- res |= RUNNING; +- break; +- case 'S': +- res |= TASK_INTERRUPTIBLE; +- break; +- case 'T': +- res |= TASK_STOPPED; +- break; +- case 'C': +- res |= TASK_TRACED; +- break; +- case 'Z': +- res |= EXIT_ZOMBIE << 16; +- break; +- case 'E': +- res |= EXIT_DEAD << 16; +- break; +- case 'U': +- res |= UNRUNNABLE; +- break; +- case 'I': +- res |= IDLE; +- break; +- case 'M': +- res |= DAEMON; +- break; +- case 'A': +- res = ~0UL; +- break; +- default: +- kdb_func_printf("unknown flag '%c' ignored\n", *s); +- break; +- } +- ++s; +- } +- return res; +-} + + /* + * kdb_task_state_char - Return the character that represents the task state. +@@ -559,7 +485,6 @@ unsigned long kdb_task_state_string(const char *s) + */ + char kdb_task_state_char (const struct task_struct *p) + { +- unsigned int p_state; + unsigned long tmp; + char state; + int cpu; +@@ -568,25 +493,18 @@ char kdb_task_state_char (const struct task_struct *p) + copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long))) + return 'E'; + +- cpu = kdb_process_cpu(p); +- p_state = READ_ONCE(p->__state); +- state = (p_state == 0) ? 'R' : +- (p_state < 0) ? 'U' : +- (p_state & TASK_UNINTERRUPTIBLE) ? 'D' : +- (p_state & TASK_STOPPED) ? 'T' : +- (p_state & TASK_TRACED) ? 'C' : +- (p->exit_state & EXIT_ZOMBIE) ? 'Z' : +- (p->exit_state & EXIT_DEAD) ? 'E' : +- (p_state & TASK_INTERRUPTIBLE) ? 'S' : '?'; ++ state = task_state_to_char((struct task_struct *) p); ++ + if (is_idle_task(p)) { + /* Idle task. Is it really idle, apart from the kdb + * interrupt? */ ++ cpu = kdb_process_cpu(p); + if (!kdb_task_has_cpu(p) || kgdb_info[cpu].irq_depth == 1) { + if (cpu != kdb_initial_cpu) +- state = 'I'; /* idle task */ ++ state = '-'; /* idle task */ + } +- } else if (!p->mm && state == 'S') { +- state = 'M'; /* sleeping system daemon */ ++ } else if (!p->mm && strchr("IMS", state)) { ++ state = tolower(state); /* sleeping system daemon */ + } + return state; + } +@@ -596,14 +514,28 @@ char kdb_task_state_char (const struct task_struct *p) + * given by the mask. + * Inputs: + * p struct task for the process +- * mask mask from kdb_task_state_string to select processes ++ * mask set of characters used to select processes; both NULL ++ * and the empty string mean adopt a default filter, which ++ * is to suppress sleeping system daemons and the idle tasks + * Returns: + * True if the process matches at least one criteria defined by the mask. + */ +-unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask) ++bool kdb_task_state(const struct task_struct *p, const char *mask) + { +- char state[] = { kdb_task_state_char(p), '\0' }; +- return (mask & kdb_task_state_string(state)) != 0; ++ char state = kdb_task_state_char(p); ++ ++ /* If there is no mask, then we will filter code that runs when the ++ * scheduler is idling and any system daemons that are currently ++ * sleeping. ++ */ ++ if (!mask || mask[0] == '\0') ++ return !strchr("-ims", state); ++ ++ /* A is a special case that matches all states */ ++ if (strchr(mask, 'A')) ++ return true; ++ ++ return strchr(mask, state); + } + + /* Maintain a small stack of kdb_flags to allow recursion without disturbing +diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c +index 5f84e6cdb78ea..4d40dcce7604b 100644 +--- a/kernel/dma/pool.c ++++ b/kernel/dma/pool.c +@@ -203,7 +203,7 @@ static int __init dma_atomic_pool_init(void) + GFP_KERNEL); + if (!atomic_pool_kernel) + ret = -ENOMEM; +- if (IS_ENABLED(CONFIG_ZONE_DMA)) { ++ if (has_managed_dma()) { + atomic_pool_dma = __dma_atomic_pool_init(atomic_pool_size, + GFP_KERNEL | GFP_DMA); + if (!atomic_pool_dma) +@@ -226,7 +226,7 @@ static inline struct gen_pool *dma_guess_pool(struct gen_pool *prev, gfp_t gfp) + if (prev == NULL) { + if (IS_ENABLED(CONFIG_ZONE_DMA32) && (gfp & GFP_DMA32)) + return atomic_pool_dma32; +- if (IS_ENABLED(CONFIG_ZONE_DMA) && (gfp & GFP_DMA)) ++ if (atomic_pool_dma && (gfp & GFP_DMA)) + return atomic_pool_dma; + return atomic_pool_kernel; + } +diff --git a/kernel/entry/syscall_user_dispatch.c b/kernel/entry/syscall_user_dispatch.c +index c240302f56e23..0b6379adff6bd 100644 +--- a/kernel/entry/syscall_user_dispatch.c ++++ b/kernel/entry/syscall_user_dispatch.c +@@ -47,14 +47,18 @@ bool syscall_user_dispatch(struct pt_regs *regs) + * access_ok() is performed once, at prctl time, when + * the selector is loaded by userspace. + */ +- if (unlikely(__get_user(state, sd->selector))) +- do_exit(SIGSEGV); ++ if (unlikely(__get_user(state, sd->selector))) { ++ force_exit_sig(SIGSEGV); ++ return true; ++ } + + if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW)) + return false; + +- if (state != SYSCALL_DISPATCH_FILTER_BLOCK) +- do_exit(SIGSYS); ++ if (state != SYSCALL_DISPATCH_FILTER_BLOCK) { ++ force_exit_sig(SIGSYS); ++ return true; ++ } + } + + sd->on_dispatch = true; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index f23ca260307f0..b81652fc2cdd9 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -674,6 +674,23 @@ perf_event_set_state(struct perf_event *event, enum perf_event_state state) + WRITE_ONCE(event->state, state); + } + ++/* ++ * UP store-release, load-acquire ++ */ ++ ++#define __store_release(ptr, val) \ ++do { \ ++ barrier(); \ ++ WRITE_ONCE(*(ptr), (val)); \ ++} while (0) ++ ++#define __load_acquire(ptr) \ ++({ \ ++ __unqual_scalar_typeof(*(ptr)) ___p = READ_ONCE(*(ptr)); \ ++ barrier(); \ ++ ___p; \ ++}) ++ + #ifdef CONFIG_CGROUP_PERF + + static inline bool +@@ -719,34 +736,51 @@ static inline u64 perf_cgroup_event_time(struct perf_event *event) + return t->time; + } + +-static inline void __update_cgrp_time(struct perf_cgroup *cgrp) ++static inline u64 perf_cgroup_event_time_now(struct perf_event *event, u64 now) + { +- struct perf_cgroup_info *info; +- u64 now; +- +- now = perf_clock(); ++ struct perf_cgroup_info *t; + +- info = this_cpu_ptr(cgrp->info); ++ t = per_cpu_ptr(event->cgrp->info, event->cpu); ++ if (!__load_acquire(&t->active)) ++ return t->time; ++ now += READ_ONCE(t->timeoffset); ++ return now; ++} + +- info->time += now - info->timestamp; ++static inline void __update_cgrp_time(struct perf_cgroup_info *info, u64 now, bool adv) ++{ ++ if (adv) ++ info->time += now - info->timestamp; + info->timestamp = now; ++ /* ++ * see update_context_time() ++ */ ++ WRITE_ONCE(info->timeoffset, info->time - info->timestamp); + } + +-static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx) ++static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx, bool final) + { + struct perf_cgroup *cgrp = cpuctx->cgrp; + struct cgroup_subsys_state *css; ++ struct perf_cgroup_info *info; + + if (cgrp) { ++ u64 now = perf_clock(); ++ + for (css = &cgrp->css; css; css = css->parent) { + cgrp = container_of(css, struct perf_cgroup, css); +- __update_cgrp_time(cgrp); ++ info = this_cpu_ptr(cgrp->info); ++ ++ __update_cgrp_time(info, now, true); ++ if (final) ++ __store_release(&info->active, 0); + } + } + } + + static inline void update_cgrp_time_from_event(struct perf_event *event) + { ++ struct perf_cgroup_info *info; + struct perf_cgroup *cgrp; + + /* +@@ -760,8 +794,10 @@ static inline void update_cgrp_time_from_event(struct perf_event *event) + /* + * Do not update time when cgroup is not active + */ +- if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup)) +- __update_cgrp_time(event->cgrp); ++ if (cgroup_is_descendant(cgrp->css.cgroup, event->cgrp->css.cgroup)) { ++ info = this_cpu_ptr(event->cgrp->info); ++ __update_cgrp_time(info, perf_clock(), true); ++ } + } + + static inline void +@@ -785,7 +821,8 @@ perf_cgroup_set_timestamp(struct task_struct *task, + for (css = &cgrp->css; css; css = css->parent) { + cgrp = container_of(css, struct perf_cgroup, css); + info = this_cpu_ptr(cgrp->info); +- info->timestamp = ctx->timestamp; ++ __update_cgrp_time(info, ctx->timestamp, false); ++ __store_release(&info->active, 1); + } + } + +@@ -802,7 +839,7 @@ static DEFINE_PER_CPU(struct list_head, cgrp_cpuctx_list); + */ + static void perf_cgroup_switch(struct task_struct *task, int mode) + { +- struct perf_cpu_context *cpuctx; ++ struct perf_cpu_context *cpuctx, *tmp; + struct list_head *list; + unsigned long flags; + +@@ -813,7 +850,7 @@ static void perf_cgroup_switch(struct task_struct *task, int mode) + local_irq_save(flags); + + list = this_cpu_ptr(&cgrp_cpuctx_list); +- list_for_each_entry(cpuctx, list, cgrp_cpuctx_entry) { ++ list_for_each_entry_safe(cpuctx, tmp, list, cgrp_cpuctx_entry) { + WARN_ON_ONCE(cpuctx->ctx.nr_cgroups == 0); + + perf_ctx_lock(cpuctx, cpuctx->task_ctx); +@@ -981,14 +1018,6 @@ out: + return ret; + } + +-static inline void +-perf_cgroup_set_shadow_time(struct perf_event *event, u64 now) +-{ +- struct perf_cgroup_info *t; +- t = per_cpu_ptr(event->cgrp->info, event->cpu); +- event->shadow_ctx_time = now - t->timestamp; +-} +- + static inline void + perf_cgroup_event_enable(struct perf_event *event, struct perf_event_context *ctx) + { +@@ -1066,7 +1095,8 @@ static inline void update_cgrp_time_from_event(struct perf_event *event) + { + } + +-static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx) ++static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx, ++ bool final) + { + } + +@@ -1098,12 +1128,12 @@ perf_cgroup_switch(struct task_struct *task, struct task_struct *next) + { + } + +-static inline void +-perf_cgroup_set_shadow_time(struct perf_event *event, u64 now) ++static inline u64 perf_cgroup_event_time(struct perf_event *event) + { ++ return 0; + } + +-static inline u64 perf_cgroup_event_time(struct perf_event *event) ++static inline u64 perf_cgroup_event_time_now(struct perf_event *event, u64 now) + { + return 0; + } +@@ -1525,22 +1555,59 @@ static void perf_unpin_context(struct perf_event_context *ctx) + /* + * Update the record of the current time in a context. + */ +-static void update_context_time(struct perf_event_context *ctx) ++static void __update_context_time(struct perf_event_context *ctx, bool adv) + { + u64 now = perf_clock(); + +- ctx->time += now - ctx->timestamp; ++ if (adv) ++ ctx->time += now - ctx->timestamp; + ctx->timestamp = now; ++ ++ /* ++ * The above: time' = time + (now - timestamp), can be re-arranged ++ * into: time` = now + (time - timestamp), which gives a single value ++ * offset to compute future time without locks on. ++ * ++ * See perf_event_time_now(), which can be used from NMI context where ++ * it's (obviously) not possible to acquire ctx->lock in order to read ++ * both the above values in a consistent manner. ++ */ ++ WRITE_ONCE(ctx->timeoffset, ctx->time - ctx->timestamp); ++} ++ ++static void update_context_time(struct perf_event_context *ctx) ++{ ++ __update_context_time(ctx, true); + } + + static u64 perf_event_time(struct perf_event *event) + { + struct perf_event_context *ctx = event->ctx; + ++ if (unlikely(!ctx)) ++ return 0; ++ + if (is_cgroup_event(event)) + return perf_cgroup_event_time(event); + +- return ctx ? ctx->time : 0; ++ return ctx->time; ++} ++ ++static u64 perf_event_time_now(struct perf_event *event, u64 now) ++{ ++ struct perf_event_context *ctx = event->ctx; ++ ++ if (unlikely(!ctx)) ++ return 0; ++ ++ if (is_cgroup_event(event)) ++ return perf_cgroup_event_time_now(event, now); ++ ++ if (!(__load_acquire(&ctx->is_active) & EVENT_TIME)) ++ return ctx->time; ++ ++ now += READ_ONCE(ctx->timeoffset); ++ return now; + } + + static enum event_type_t get_event_type(struct perf_event *event) +@@ -2346,7 +2413,7 @@ __perf_remove_from_context(struct perf_event *event, + + if (ctx->is_active & EVENT_TIME) { + update_context_time(ctx); +- update_cgrp_time_from_cpuctx(cpuctx); ++ update_cgrp_time_from_cpuctx(cpuctx, false); + } + + event_sched_out(event, cpuctx, ctx); +@@ -2357,6 +2424,9 @@ __perf_remove_from_context(struct perf_event *event, + list_del_event(event, ctx); + + if (!ctx->nr_events && ctx->is_active) { ++ if (ctx == &cpuctx->ctx) ++ update_cgrp_time_from_cpuctx(cpuctx, true); ++ + ctx->is_active = 0; + ctx->rotate_necessary = 0; + if (ctx->task) { +@@ -2388,7 +2458,11 @@ static void perf_remove_from_context(struct perf_event *event, unsigned long fla + * event_function_call() user. + */ + raw_spin_lock_irq(&ctx->lock); +- if (!ctx->is_active) { ++ /* ++ * Cgroup events are per-cpu events, and must IPI because of ++ * cgrp_cpuctx_list. ++ */ ++ if (!ctx->is_active && !is_cgroup_event(event)) { + __perf_remove_from_context(event, __get_cpu_context(ctx), + ctx, (void *)flags); + raw_spin_unlock_irq(&ctx->lock); +@@ -2478,40 +2552,6 @@ void perf_event_disable_inatomic(struct perf_event *event) + irq_work_queue(&event->pending); + } + +-static void perf_set_shadow_time(struct perf_event *event, +- struct perf_event_context *ctx) +-{ +- /* +- * use the correct time source for the time snapshot +- * +- * We could get by without this by leveraging the +- * fact that to get to this function, the caller +- * has most likely already called update_context_time() +- * and update_cgrp_time_xx() and thus both timestamp +- * are identical (or very close). Given that tstamp is, +- * already adjusted for cgroup, we could say that: +- * tstamp - ctx->timestamp +- * is equivalent to +- * tstamp - cgrp->timestamp. +- * +- * Then, in perf_output_read(), the calculation would +- * work with no changes because: +- * - event is guaranteed scheduled in +- * - no scheduled out in between +- * - thus the timestamp would be the same +- * +- * But this is a bit hairy. +- * +- * So instead, we have an explicit cgroup call to remain +- * within the time source all along. We believe it +- * is cleaner and simpler to understand. +- */ +- if (is_cgroup_event(event)) +- perf_cgroup_set_shadow_time(event, event->tstamp); +- else +- event->shadow_ctx_time = event->tstamp - ctx->timestamp; +-} +- + #define MAX_INTERRUPTS (~0ULL) + + static void perf_log_throttle(struct perf_event *event, int enable); +@@ -2552,8 +2592,6 @@ event_sched_in(struct perf_event *event, + + perf_pmu_disable(event->pmu); + +- perf_set_shadow_time(event, ctx); +- + perf_log_itrace_start(event); + + if (event->pmu->add(event, PERF_EF_START)) { +@@ -2857,11 +2895,14 @@ perf_install_in_context(struct perf_event_context *ctx, + * perf_event_attr::disabled events will not run and can be initialized + * without IPI. Except when this is the first event for the context, in + * that case we need the magic of the IPI to set ctx->is_active. ++ * Similarly, cgroup events for the context also needs the IPI to ++ * manipulate the cgrp_cpuctx_list. + * + * The IOC_ENABLE that is sure to follow the creation of a disabled + * event will issue the IPI and reprogram the hardware. + */ +- if (__perf_effective_state(event) == PERF_EVENT_STATE_OFF && ctx->nr_events) { ++ if (__perf_effective_state(event) == PERF_EVENT_STATE_OFF && ++ ctx->nr_events && !is_cgroup_event(event)) { + raw_spin_lock_irq(&ctx->lock); + if (ctx->task == TASK_TOMBSTONE) { + raw_spin_unlock_irq(&ctx->lock); +@@ -3193,6 +3234,15 @@ static int perf_event_modify_breakpoint(struct perf_event *bp, + return err; + } + ++/* ++ * Copy event-type-independent attributes that may be modified. ++ */ ++static void perf_event_modify_copy_attr(struct perf_event_attr *to, ++ const struct perf_event_attr *from) ++{ ++ to->sig_data = from->sig_data; ++} ++ + static int perf_event_modify_attr(struct perf_event *event, + struct perf_event_attr *attr) + { +@@ -3215,10 +3265,17 @@ static int perf_event_modify_attr(struct perf_event *event, + WARN_ON_ONCE(event->ctx->parent_ctx); + + mutex_lock(&event->child_mutex); ++ /* ++ * Event-type-independent attributes must be copied before event-type ++ * modification, which will validate that final attributes match the ++ * source attributes after all relevant attributes have been copied. ++ */ ++ perf_event_modify_copy_attr(&event->attr, attr); + err = func(event, attr); + if (err) + goto out; + list_for_each_entry(child, &event->child_list, child_list) { ++ perf_event_modify_copy_attr(&child->attr, attr); + err = func(child, attr); + if (err) + goto out; +@@ -3247,16 +3304,6 @@ static void ctx_sched_out(struct perf_event_context *ctx, + return; + } + +- ctx->is_active &= ~event_type; +- if (!(ctx->is_active & EVENT_ALL)) +- ctx->is_active = 0; +- +- if (ctx->task) { +- WARN_ON_ONCE(cpuctx->task_ctx != ctx); +- if (!ctx->is_active) +- cpuctx->task_ctx = NULL; +- } +- + /* + * Always update time if it was set; not only when it changes. + * Otherwise we can 'forget' to update time for any but the last +@@ -3270,7 +3317,22 @@ static void ctx_sched_out(struct perf_event_context *ctx, + if (is_active & EVENT_TIME) { + /* update (and stop) ctx time */ + update_context_time(ctx); +- update_cgrp_time_from_cpuctx(cpuctx); ++ update_cgrp_time_from_cpuctx(cpuctx, ctx == &cpuctx->ctx); ++ /* ++ * CPU-release for the below ->is_active store, ++ * see __load_acquire() in perf_event_time_now() ++ */ ++ barrier(); ++ } ++ ++ ctx->is_active &= ~event_type; ++ if (!(ctx->is_active & EVENT_ALL)) ++ ctx->is_active = 0; ++ ++ if (ctx->task) { ++ WARN_ON_ONCE(cpuctx->task_ctx != ctx); ++ if (!ctx->is_active) ++ cpuctx->task_ctx = NULL; + } + + is_active ^= ctx->is_active; /* changed bits */ +@@ -3707,13 +3769,19 @@ static noinline int visit_groups_merge(struct perf_cpu_context *cpuctx, + return 0; + } + ++/* ++ * Because the userpage is strictly per-event (there is no concept of context, ++ * so there cannot be a context indirection), every userpage must be updated ++ * when context time starts :-( ++ * ++ * IOW, we must not miss EVENT_TIME edges. ++ */ + static inline bool event_update_userpage(struct perf_event *event) + { + if (likely(!atomic_read(&event->mmap_count))) + return false; + + perf_event_update_time(event); +- perf_set_shadow_time(event, event->ctx); + perf_event_update_userpage(event); + + return true; +@@ -3797,13 +3865,23 @@ ctx_sched_in(struct perf_event_context *ctx, + struct task_struct *task) + { + int is_active = ctx->is_active; +- u64 now; + + lockdep_assert_held(&ctx->lock); + + if (likely(!ctx->nr_events)) + return; + ++ if (is_active ^ EVENT_TIME) { ++ /* start ctx time */ ++ __update_context_time(ctx, false); ++ perf_cgroup_set_timestamp(task, ctx); ++ /* ++ * CPU-release for the below ->is_active store, ++ * see __load_acquire() in perf_event_time_now() ++ */ ++ barrier(); ++ } ++ + ctx->is_active |= (event_type | EVENT_TIME); + if (ctx->task) { + if (!is_active) +@@ -3814,13 +3892,6 @@ ctx_sched_in(struct perf_event_context *ctx, + + is_active ^= ctx->is_active; /* changed bits */ + +- if (is_active & EVENT_TIME) { +- /* start ctx time */ +- now = perf_clock(); +- ctx->timestamp = now; +- perf_cgroup_set_timestamp(task, ctx); +- } +- + /* + * First go through the list and put on any pinned groups + * in order to give them the best chance of going on. +@@ -4414,6 +4485,18 @@ static inline u64 perf_event_count(struct perf_event *event) + return local64_read(&event->count) + atomic64_read(&event->child_count); + } + ++static void calc_timer_values(struct perf_event *event, ++ u64 *now, ++ u64 *enabled, ++ u64 *running) ++{ ++ u64 ctx_time; ++ ++ *now = perf_clock(); ++ ctx_time = perf_event_time_now(event, *now); ++ __perf_update_times(event, ctx_time, enabled, running); ++} ++ + /* + * NMI-safe method to read a local event, that is an event that + * is: +@@ -4473,10 +4556,9 @@ int perf_event_read_local(struct perf_event *event, u64 *value, + + *value = local64_read(&event->count); + if (enabled || running) { +- u64 now = event->shadow_ctx_time + perf_clock(); +- u64 __enabled, __running; ++ u64 __enabled, __running, __now;; + +- __perf_update_times(event, now, &__enabled, &__running); ++ calc_timer_values(event, &__now, &__enabled, &__running); + if (enabled) + *enabled = __enabled; + if (running) +@@ -5798,18 +5880,6 @@ static int perf_event_index(struct perf_event *event) + return event->pmu->event_idx(event); + } + +-static void calc_timer_values(struct perf_event *event, +- u64 *now, +- u64 *enabled, +- u64 *running) +-{ +- u64 ctx_time; +- +- *now = perf_clock(); +- ctx_time = event->shadow_ctx_time + *now; +- __perf_update_times(event, ctx_time, enabled, running); +-} +- + static void perf_event_init_userpage(struct perf_event *event) + { + struct perf_event_mmap_page *userpg; +@@ -5934,6 +6004,8 @@ static void ring_buffer_attach(struct perf_event *event, + struct perf_buffer *old_rb = NULL; + unsigned long flags; + ++ WARN_ON_ONCE(event->parent); ++ + if (event->rb) { + /* + * Should be impossible, we set this when removing +@@ -5991,6 +6063,9 @@ static void ring_buffer_wakeup(struct perf_event *event) + { + struct perf_buffer *rb; + ++ if (event->parent) ++ event = event->parent; ++ + rcu_read_lock(); + rb = rcu_dereference(event->rb); + if (rb) { +@@ -6004,6 +6079,9 @@ struct perf_buffer *ring_buffer_get(struct perf_event *event) + { + struct perf_buffer *rb; + ++ if (event->parent) ++ event = event->parent; ++ + rcu_read_lock(); + rb = rcu_dereference(event->rb); + if (rb) { +@@ -6349,7 +6427,6 @@ accounting: + ring_buffer_attach(event, rb); + + perf_event_update_time(event); +- perf_set_shadow_time(event, event->ctx); + perf_event_init_userpage(event); + perf_event_update_userpage(event); + } else { +@@ -6526,18 +6603,25 @@ static void perf_pending_event(struct irq_work *entry) + * Later on, we might change it to a list if there is + * another virtualization implementation supporting the callbacks. + */ +-struct perf_guest_info_callbacks *perf_guest_cbs; ++struct perf_guest_info_callbacks __rcu *perf_guest_cbs; + + int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) + { +- perf_guest_cbs = cbs; ++ if (WARN_ON_ONCE(rcu_access_pointer(perf_guest_cbs))) ++ return -EBUSY; ++ ++ rcu_assign_pointer(perf_guest_cbs, cbs); + return 0; + } + EXPORT_SYMBOL_GPL(perf_register_guest_info_callbacks); + + int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) + { +- perf_guest_cbs = NULL; ++ if (WARN_ON_ONCE(rcu_access_pointer(perf_guest_cbs) != cbs)) ++ return -EINVAL; ++ ++ rcu_assign_pointer(perf_guest_cbs, NULL); ++ synchronize_rcu(); + return 0; + } + EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); +@@ -6696,7 +6780,7 @@ static unsigned long perf_prepare_sample_aux(struct perf_event *event, + if (WARN_ON_ONCE(READ_ONCE(sampler->oncpu) != smp_processor_id())) + goto out; + +- rb = ring_buffer_get(sampler->parent ? sampler->parent : sampler); ++ rb = ring_buffer_get(sampler); + if (!rb) + goto out; + +@@ -6762,7 +6846,7 @@ static void perf_aux_sample_output(struct perf_event *event, + if (WARN_ON_ONCE(!sampler || !data->aux_size)) + return; + +- rb = ring_buffer_get(sampler->parent ? sampler->parent : sampler); ++ rb = ring_buffer_get(sampler); + if (!rb) + return; + +@@ -7154,7 +7238,6 @@ void perf_output_sample(struct perf_output_handle *handle, + static u64 perf_virt_to_phys(u64 virt) + { + u64 phys_addr = 0; +- struct page *p = NULL; + + if (!virt) + return 0; +@@ -7173,14 +7256,15 @@ static u64 perf_virt_to_phys(u64 virt) + * If failed, leave phys_addr as 0. + */ + if (current->mm != NULL) { ++ struct page *p; ++ + pagefault_disable(); +- if (get_user_page_fast_only(virt, 0, &p)) ++ if (get_user_page_fast_only(virt, 0, &p)) { + phys_addr = page_to_phys(p) + virt % PAGE_SIZE; ++ put_page(p); ++ } + pagefault_enable(); + } +- +- if (p) +- put_page(p); + } + + return phys_addr; +@@ -9729,6 +9813,9 @@ void perf_tp_event(u16 event_type, u64 count, void *record, int entry_size, + continue; + if (event->attr.config != entry->type) + continue; ++ /* Cannot deliver synchronous signal to other task. */ ++ if (event->attr.sigtrap) ++ continue; + if (perf_tp_event_match(event, &data, regs)) + perf_swevent_event(event, count, &data, regs); + } +diff --git a/kernel/fork.c b/kernel/fork.c +index 38681ad44c76b..89475c994ca91 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2055,18 +2055,18 @@ static __latent_entropy struct task_struct *copy_process( + #ifdef CONFIG_PROVE_LOCKING + DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); + #endif ++ retval = copy_creds(p, clone_flags); ++ if (retval < 0) ++ goto bad_fork_free; ++ + retval = -EAGAIN; + if (is_ucounts_overlimit(task_ucounts(p), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) { + if (p->real_cred->user != INIT_USER && + !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) +- goto bad_fork_free; ++ goto bad_fork_cleanup_count; + } + current->flags &= ~PF_NPROC_EXCEEDED; + +- retval = copy_creds(p, clone_flags); +- if (retval < 0) +- goto bad_fork_free; +- + /* + * If multiple threads are within copy_process(), then this check + * triggers too late. This doesn't hurt, the check is only there +@@ -2280,6 +2280,7 @@ static __latent_entropy struct task_struct *copy_process( + p->pdeath_signal = 0; + INIT_LIST_HEAD(&p->thread_group); + p->task_works = NULL; ++ clear_posix_cputimers_work(p); + + #ifdef CONFIG_KRETPROBES + p->kretprobe_instances.first = NULL; +@@ -2295,6 +2296,17 @@ static __latent_entropy struct task_struct *copy_process( + if (retval) + goto bad_fork_put_pidfd; + ++ /* ++ * Now that the cgroups are pinned, re-clone the parent cgroup and put ++ * the new task on the correct runqueue. All this *before* the task ++ * becomes visible. ++ * ++ * This isn't part of ->can_fork() because while the re-cloning is ++ * cgroup specific, it unconditionally needs to place the task on a ++ * runqueue. ++ */ ++ sched_cgroup_fork(p, args); ++ + /* + * From this point on we must avoid any synchronous user-space + * communication until we take the tasklist-lock. In particular, we do +@@ -2352,10 +2364,6 @@ static __latent_entropy struct task_struct *copy_process( + goto bad_fork_cancel_cgroup; + } + +- /* past the last point of failure */ +- if (pidfile) +- fd_install(pidfd, pidfile); +- + init_task_pid_links(p); + if (likely(p->pid)) { + ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); +@@ -2404,6 +2412,9 @@ static __latent_entropy struct task_struct *copy_process( + syscall_tracepoint_update(p); + write_unlock_irq(&tasklist_lock); + ++ if (pidfile) ++ fd_install(pidfd, pidfile); ++ + proc_fork_connector(p); + sched_post_fork(p); + cgroup_post_fork(p, args); +diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c +index 6a5ecee6e5674..7f350ae59c5fd 100644 +--- a/kernel/irq/msi.c ++++ b/kernel/irq/msi.c +@@ -529,10 +529,10 @@ static bool msi_check_reservation_mode(struct irq_domain *domain, + + /* + * Checking the first MSI descriptor is sufficient. MSIX supports +- * masking and MSI does so when the maskbit is set. ++ * masking and MSI does so when the can_mask attribute is set. + */ + desc = first_msi_entry(dev); +- return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit; ++ return desc->msi_attrib.is_msix || desc->msi_attrib.can_mask; + } + + int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, +diff --git a/kernel/kprobes.c b/kernel/kprobes.c +index 790a573bbe00c..2ef90d15699fb 100644 +--- a/kernel/kprobes.c ++++ b/kernel/kprobes.c +@@ -2006,6 +2006,9 @@ int register_kretprobe(struct kretprobe *rp) + } + } + ++ if (rp->data_size > KRETPROBE_MAX_DATA_SIZE) ++ return -E2BIG; ++ + rp->kp.pre_handler = pre_handler_kretprobe; + rp->kp.post_handler = NULL; + +@@ -2809,13 +2812,12 @@ static const struct file_operations fops_kp = { + static int __init debugfs_kprobe_init(void) + { + struct dentry *dir; +- unsigned int value = 1; + + dir = debugfs_create_dir("kprobes", NULL); + + debugfs_create_file("list", 0400, dir, NULL, &kprobes_fops); + +- debugfs_create_file("enabled", 0600, dir, &value, &fops_kp); ++ debugfs_create_file("enabled", 0600, dir, NULL, &fops_kp); + + debugfs_create_file("blacklist", 0400, dir, NULL, + &kprobe_blacklist_fops); +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index bf1c00c881e48..92127296cf2bf 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -888,7 +888,7 @@ look_up_lock_class(const struct lockdep_map *lock, unsigned int subclass) + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return NULL; + +- hlist_for_each_entry_rcu(class, hash_head, hash_entry) { ++ hlist_for_each_entry_rcu_notrace(class, hash_head, hash_entry) { + if (class->key == key) { + /* + * Huh! same key, different name? Did someone trample +@@ -3450,7 +3450,7 @@ struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i) + u16 chain_hlock = chain_hlocks[chain->base + i]; + unsigned int class_idx = chain_hlock_class_idx(chain_hlock); + +- return lock_classes + class_idx - 1; ++ return lock_classes + class_idx; + } + + /* +@@ -3518,7 +3518,7 @@ static void print_chain_keys_chain(struct lock_chain *chain) + hlock_id = chain_hlocks[chain->base + i]; + chain_key = print_chain_key_iteration(hlock_id, chain_key); + +- print_lock_name(lock_classes + chain_hlock_class_idx(hlock_id) - 1); ++ print_lock_name(lock_classes + chain_hlock_class_idx(hlock_id)); + printk("\n"); + } + } +@@ -5366,7 +5366,7 @@ int __lock_is_held(const struct lockdep_map *lock, int read) + struct held_lock *hlock = curr->held_locks + i; + + if (match_held_lock(hlock, lock)) { +- if (read == -1 || hlock->read == read) ++ if (read == -1 || !!hlock->read == read) + return LOCK_STATE_HELD; + + return LOCK_STATE_NOT_HELD; +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index 6bb116c559b4a..ea5a701ab2408 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -1373,7 +1373,7 @@ static bool rtmutex_spin_on_owner(struct rt_mutex_base *lock, + * - the VCPU on which owner runs is preempted + */ + if (!owner->on_cpu || need_resched() || +- rt_mutex_waiter_is_top_waiter(lock, waiter) || ++ !rt_mutex_waiter_is_top_waiter(lock, waiter) || + vcpu_is_preempted(task_cpu(owner))) { + res = false; + break; +diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c +index 000e8d5a28841..e63f740c2cc84 100644 +--- a/kernel/locking/rwsem.c ++++ b/kernel/locking/rwsem.c +@@ -106,9 +106,9 @@ + * atomic_long_cmpxchg() will be used to obtain writer lock. + * + * There are three places where the lock handoff bit may be set or cleared. +- * 1) rwsem_mark_wake() for readers. +- * 2) rwsem_try_write_lock() for writers. +- * 3) Error path of rwsem_down_write_slowpath(). ++ * 1) rwsem_mark_wake() for readers -- set, clear ++ * 2) rwsem_try_write_lock() for writers -- set, clear ++ * 3) rwsem_del_waiter() -- clear + * + * For all the above cases, wait_lock will be held. A writer must also + * be the first one in the wait_list to be eligible for setting the handoff +@@ -335,6 +335,9 @@ struct rwsem_waiter { + struct task_struct *task; + enum rwsem_waiter_type type; + unsigned long timeout; ++ ++ /* Writer only, not initialized in reader */ ++ bool handoff_set; + }; + #define rwsem_first_waiter(sem) \ + list_first_entry(&sem->wait_list, struct rwsem_waiter, list) +@@ -345,12 +348,6 @@ enum rwsem_wake_type { + RWSEM_WAKE_READ_OWNED /* Waker thread holds the read lock */ + }; + +-enum writer_wait_state { +- WRITER_NOT_FIRST, /* Writer is not first in wait list */ +- WRITER_FIRST, /* Writer is first in wait list */ +- WRITER_HANDOFF /* Writer is first & handoff needed */ +-}; +- + /* + * The typical HZ value is either 250 or 1000. So set the minimum waiting + * time to at least 4ms or 1 jiffy (if it is higher than 4ms) in the wait +@@ -366,6 +363,31 @@ enum writer_wait_state { + */ + #define MAX_READERS_WAKEUP 0x100 + ++static inline void ++rwsem_add_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter) ++{ ++ lockdep_assert_held(&sem->wait_lock); ++ list_add_tail(&waiter->list, &sem->wait_list); ++ /* caller will set RWSEM_FLAG_WAITERS */ ++} ++ ++/* ++ * Remove a waiter from the wait_list and clear flags. ++ * ++ * Both rwsem_mark_wake() and rwsem_try_write_lock() contain a full 'copy' of ++ * this function. Modify with care. ++ */ ++static inline void ++rwsem_del_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter) ++{ ++ lockdep_assert_held(&sem->wait_lock); ++ list_del(&waiter->list); ++ if (likely(!list_empty(&sem->wait_list))) ++ return; ++ ++ atomic_long_andnot(RWSEM_FLAG_HANDOFF | RWSEM_FLAG_WAITERS, &sem->count); ++} ++ + /* + * handle the lock release when processes blocked on it that can now run + * - if we come here from up_xxxx(), then the RWSEM_FLAG_WAITERS bit must +@@ -377,6 +399,8 @@ enum writer_wait_state { + * preferably when the wait_lock is released + * - woken process blocks are discarded from the list after having task zeroed + * - writers are only marked woken if downgrading is false ++ * ++ * Implies rwsem_del_waiter() for all woken readers. + */ + static void rwsem_mark_wake(struct rw_semaphore *sem, + enum rwsem_wake_type wake_type, +@@ -491,18 +515,25 @@ static void rwsem_mark_wake(struct rw_semaphore *sem, + + adjustment = woken * RWSEM_READER_BIAS - adjustment; + lockevent_cond_inc(rwsem_wake_reader, woken); ++ ++ oldcount = atomic_long_read(&sem->count); + if (list_empty(&sem->wait_list)) { +- /* hit end of list above */ ++ /* ++ * Combined with list_move_tail() above, this implies ++ * rwsem_del_waiter(). ++ */ + adjustment -= RWSEM_FLAG_WAITERS; ++ if (oldcount & RWSEM_FLAG_HANDOFF) ++ adjustment -= RWSEM_FLAG_HANDOFF; ++ } else if (woken) { ++ /* ++ * When we've woken a reader, we no longer need to force ++ * writers to give up the lock and we can clear HANDOFF. ++ */ ++ if (oldcount & RWSEM_FLAG_HANDOFF) ++ adjustment -= RWSEM_FLAG_HANDOFF; + } + +- /* +- * When we've woken a reader, we no longer need to force writers +- * to give up the lock and we can clear HANDOFF. +- */ +- if (woken && (atomic_long_read(&sem->count) & RWSEM_FLAG_HANDOFF)) +- adjustment -= RWSEM_FLAG_HANDOFF; +- + if (adjustment) + atomic_long_add(adjustment, &sem->count); + +@@ -533,12 +564,12 @@ static void rwsem_mark_wake(struct rw_semaphore *sem, + * race conditions between checking the rwsem wait list and setting the + * sem->count accordingly. + * +- * If wstate is WRITER_HANDOFF, it will make sure that either the handoff +- * bit is set or the lock is acquired with handoff bit cleared. ++ * Implies rwsem_del_waiter() on success. + */ + static inline bool rwsem_try_write_lock(struct rw_semaphore *sem, +- enum writer_wait_state wstate) ++ struct rwsem_waiter *waiter) + { ++ bool first = rwsem_first_waiter(sem) == waiter; + long count, new; + + lockdep_assert_held(&sem->wait_lock); +@@ -547,13 +578,19 @@ static inline bool rwsem_try_write_lock(struct rw_semaphore *sem, + do { + bool has_handoff = !!(count & RWSEM_FLAG_HANDOFF); + +- if (has_handoff && wstate == WRITER_NOT_FIRST) +- return false; ++ if (has_handoff) { ++ if (!first) ++ return false; ++ ++ /* First waiter inherits a previously set handoff bit */ ++ waiter->handoff_set = true; ++ } + + new = count; + + if (count & RWSEM_LOCK_MASK) { +- if (has_handoff || (wstate != WRITER_HANDOFF)) ++ if (has_handoff || (!rt_task(waiter->task) && ++ !time_after(jiffies, waiter->timeout))) + return false; + + new |= RWSEM_FLAG_HANDOFF; +@@ -570,13 +607,39 @@ static inline bool rwsem_try_write_lock(struct rw_semaphore *sem, + * We have either acquired the lock with handoff bit cleared or + * set the handoff bit. + */ +- if (new & RWSEM_FLAG_HANDOFF) ++ if (new & RWSEM_FLAG_HANDOFF) { ++ waiter->handoff_set = true; ++ lockevent_inc(rwsem_wlock_handoff); + return false; ++ } + ++ /* ++ * Have rwsem_try_write_lock() fully imply rwsem_del_waiter() on ++ * success. ++ */ ++ list_del(&waiter->list); + rwsem_set_owner(sem); + return true; + } + ++/* ++ * The rwsem_spin_on_owner() function returns the following 4 values ++ * depending on the lock owner state. ++ * OWNER_NULL : owner is currently NULL ++ * OWNER_WRITER: when owner changes and is a writer ++ * OWNER_READER: when owner changes and the new owner may be a reader. ++ * OWNER_NONSPINNABLE: ++ * when optimistic spinning has to stop because either the ++ * owner stops running, is unknown, or its timeslice has ++ * been used up. ++ */ ++enum owner_state { ++ OWNER_NULL = 1 << 0, ++ OWNER_WRITER = 1 << 1, ++ OWNER_READER = 1 << 2, ++ OWNER_NONSPINNABLE = 1 << 3, ++}; ++ + #ifdef CONFIG_RWSEM_SPIN_ON_OWNER + /* + * Try to acquire write lock before the writer has been put on wait queue. +@@ -632,23 +695,6 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) + return ret; + } + +-/* +- * The rwsem_spin_on_owner() function returns the following 4 values +- * depending on the lock owner state. +- * OWNER_NULL : owner is currently NULL +- * OWNER_WRITER: when owner changes and is a writer +- * OWNER_READER: when owner changes and the new owner may be a reader. +- * OWNER_NONSPINNABLE: +- * when optimistic spinning has to stop because either the +- * owner stops running, is unknown, or its timeslice has +- * been used up. +- */ +-enum owner_state { +- OWNER_NULL = 1 << 0, +- OWNER_WRITER = 1 << 1, +- OWNER_READER = 1 << 2, +- OWNER_NONSPINNABLE = 1 << 3, +-}; + #define OWNER_SPINNABLE (OWNER_NULL | OWNER_WRITER | OWNER_READER) + + static inline enum owner_state +@@ -878,12 +924,11 @@ static inline bool rwsem_optimistic_spin(struct rw_semaphore *sem) + + static inline void clear_nonspinnable(struct rw_semaphore *sem) { } + +-static inline int ++static inline enum owner_state + rwsem_spin_on_owner(struct rw_semaphore *sem) + { +- return 0; ++ return OWNER_NONSPINNABLE; + } +-#define OWNER_NULL 1 + #endif + + /* +@@ -953,7 +998,7 @@ queue: + } + adjustment += RWSEM_FLAG_WAITERS; + } +- list_add_tail(&waiter.list, &sem->wait_list); ++ rwsem_add_waiter(sem, &waiter); + + /* we're now waiting on the lock, but no longer actively locking */ + count = atomic_long_add_return(adjustment, &sem->count); +@@ -999,11 +1044,7 @@ queue: + return sem; + + out_nolock: +- list_del(&waiter.list); +- if (list_empty(&sem->wait_list)) { +- atomic_long_andnot(RWSEM_FLAG_WAITERS|RWSEM_FLAG_HANDOFF, +- &sem->count); +- } ++ rwsem_del_waiter(sem, &waiter); + raw_spin_unlock_irq(&sem->wait_lock); + __set_current_state(TASK_RUNNING); + lockevent_inc(rwsem_rlock_fail); +@@ -1017,9 +1058,7 @@ static struct rw_semaphore * + rwsem_down_write_slowpath(struct rw_semaphore *sem, int state) + { + long count; +- enum writer_wait_state wstate; + struct rwsem_waiter waiter; +- struct rw_semaphore *ret = sem; + DEFINE_WAKE_Q(wake_q); + + /* do optimistic spinning and steal lock if possible */ +@@ -1035,16 +1074,13 @@ rwsem_down_write_slowpath(struct rw_semaphore *sem, int state) + waiter.task = current; + waiter.type = RWSEM_WAITING_FOR_WRITE; + waiter.timeout = jiffies + RWSEM_WAIT_TIMEOUT; ++ waiter.handoff_set = false; + + raw_spin_lock_irq(&sem->wait_lock); +- +- /* account for this before adding a new element to the list */ +- wstate = list_empty(&sem->wait_list) ? WRITER_FIRST : WRITER_NOT_FIRST; +- +- list_add_tail(&waiter.list, &sem->wait_list); ++ rwsem_add_waiter(sem, &waiter); + + /* we're now waiting on the lock */ +- if (wstate == WRITER_NOT_FIRST) { ++ if (rwsem_first_waiter(sem) != &waiter) { + count = atomic_long_read(&sem->count); + + /* +@@ -1080,13 +1116,16 @@ wait: + /* wait until we successfully acquire the lock */ + set_current_state(state); + for (;;) { +- if (rwsem_try_write_lock(sem, wstate)) { ++ if (rwsem_try_write_lock(sem, &waiter)) { + /* rwsem_try_write_lock() implies ACQUIRE on success */ + break; + } + + raw_spin_unlock_irq(&sem->wait_lock); + ++ if (signal_pending_state(state, current)) ++ goto out_nolock; ++ + /* + * After setting the handoff bit and failing to acquire + * the lock, attempt to spin on owner to accelerate lock +@@ -1095,70 +1134,37 @@ wait: + * In this case, we attempt to acquire the lock again + * without sleeping. + */ +- if (wstate == WRITER_HANDOFF && +- rwsem_spin_on_owner(sem) == OWNER_NULL) +- goto trylock_again; +- +- /* Block until there are no active lockers. */ +- for (;;) { +- if (signal_pending_state(state, current)) +- goto out_nolock; +- +- schedule(); +- lockevent_inc(rwsem_sleep_writer); +- set_current_state(state); +- /* +- * If HANDOFF bit is set, unconditionally do +- * a trylock. +- */ +- if (wstate == WRITER_HANDOFF) +- break; +- +- if ((wstate == WRITER_NOT_FIRST) && +- (rwsem_first_waiter(sem) == &waiter)) +- wstate = WRITER_FIRST; ++ if (waiter.handoff_set) { ++ enum owner_state owner_state; + +- count = atomic_long_read(&sem->count); +- if (!(count & RWSEM_LOCK_MASK)) +- break; ++ preempt_disable(); ++ owner_state = rwsem_spin_on_owner(sem); ++ preempt_enable(); + +- /* +- * The setting of the handoff bit is deferred +- * until rwsem_try_write_lock() is called. +- */ +- if ((wstate == WRITER_FIRST) && (rt_task(current) || +- time_after(jiffies, waiter.timeout))) { +- wstate = WRITER_HANDOFF; +- lockevent_inc(rwsem_wlock_handoff); +- break; +- } ++ if (owner_state == OWNER_NULL) ++ goto trylock_again; + } ++ ++ schedule(); ++ lockevent_inc(rwsem_sleep_writer); ++ set_current_state(state); + trylock_again: + raw_spin_lock_irq(&sem->wait_lock); + } + __set_current_state(TASK_RUNNING); +- list_del(&waiter.list); + raw_spin_unlock_irq(&sem->wait_lock); + lockevent_inc(rwsem_wlock); +- +- return ret; ++ return sem; + + out_nolock: + __set_current_state(TASK_RUNNING); + raw_spin_lock_irq(&sem->wait_lock); +- list_del(&waiter.list); +- +- if (unlikely(wstate == WRITER_HANDOFF)) +- atomic_long_add(-RWSEM_FLAG_HANDOFF, &sem->count); +- +- if (list_empty(&sem->wait_list)) +- atomic_long_andnot(RWSEM_FLAG_WAITERS, &sem->count); +- else ++ rwsem_del_waiter(sem, &waiter); ++ if (!list_empty(&sem->wait_list)) + rwsem_mark_wake(sem, RWSEM_WAKE_ANY, &wake_q); + raw_spin_unlock_irq(&sem->wait_lock); + wake_up_q(&wake_q); + lockevent_inc(rwsem_wlock_fail); +- + return ERR_PTR(-EINTR); + } + +diff --git a/kernel/module.c b/kernel/module.c +index 5c26a76e800b5..83991c2d5af9e 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -3683,12 +3683,6 @@ static noinline int do_init_module(struct module *mod) + } + freeinit->module_init = mod->init_layout.base; + +- /* +- * We want to find out whether @mod uses async during init. Clear +- * PF_USED_ASYNC. async_schedule*() will set it. +- */ +- current->flags &= ~PF_USED_ASYNC; +- + do_mod_ctors(mod); + /* Start the module */ + if (mod->init != NULL) +@@ -3714,22 +3708,13 @@ static noinline int do_init_module(struct module *mod) + + /* + * We need to finish all async code before the module init sequence +- * is done. This has potential to deadlock. For example, a newly +- * detected block device can trigger request_module() of the +- * default iosched from async probing task. Once userland helper +- * reaches here, async_synchronize_full() will wait on the async +- * task waiting on request_module() and deadlock. +- * +- * This deadlock is avoided by perfomring async_synchronize_full() +- * iff module init queued any async jobs. This isn't a full +- * solution as it will deadlock the same if module loading from +- * async jobs nests more than once; however, due to the various +- * constraints, this hack seems to be the best option for now. +- * Please refer to the following thread for details. ++ * is done. This has potential to deadlock if synchronous module ++ * loading is requested from async (which is not allowed!). + * +- * http://thread.gmane.org/gmane.linux.kernel/1420814 ++ * See commit 0fdff3ec6d87 ("async, kmod: warn on synchronous ++ * request_module() from async workers") for more details. + */ +- if (!mod->async_probe_requested && (current->flags & PF_USED_ASYNC)) ++ if (!mod->async_probe_requested) + async_synchronize_full(); + + ftrace_free_mem(mod, mod->init_layout.base, mod->init_layout.base + +diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c +index a332ccd829e24..97e62469a6b32 100644 +--- a/kernel/power/energy_model.c ++++ b/kernel/power/energy_model.c +@@ -107,8 +107,7 @@ static void em_debug_remove_pd(struct device *dev) {} + static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd, + int nr_states, struct em_data_callback *cb) + { +- unsigned long opp_eff, prev_opp_eff = ULONG_MAX; +- unsigned long power, freq, prev_freq = 0; ++ unsigned long power, freq, prev_freq = 0, prev_cost = ULONG_MAX; + struct em_perf_state *table; + int i, ret; + u64 fmax; +@@ -153,27 +152,21 @@ static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd, + + table[i].power = power; + table[i].frequency = prev_freq = freq; +- +- /* +- * The hertz/watts efficiency ratio should decrease as the +- * frequency grows on sane platforms. But this isn't always +- * true in practice so warn the user if a higher OPP is more +- * power efficient than a lower one. +- */ +- opp_eff = freq / power; +- if (opp_eff >= prev_opp_eff) +- dev_dbg(dev, "EM: hertz/watts ratio non-monotonically decreasing: em_perf_state %d >= em_perf_state%d\n", +- i, i - 1); +- prev_opp_eff = opp_eff; + } + + /* Compute the cost of each performance state. */ + fmax = (u64) table[nr_states - 1].frequency; +- for (i = 0; i < nr_states; i++) { ++ for (i = nr_states - 1; i >= 0; i--) { + unsigned long power_res = em_scale_power(table[i].power); + + table[i].cost = div64_u64(fmax * power_res, + table[i].frequency); ++ if (table[i].cost >= prev_cost) { ++ dev_dbg(dev, "EM: OPP:%lu is inefficient\n", ++ table[i].frequency); ++ } else { ++ prev_cost = table[i].cost; ++ } + } + + pd->table = table; +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index 559acef3fddb8..b0888e9224da3 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c +@@ -691,7 +691,7 @@ static int load_image_and_restore(void) + goto Unlock; + + error = swsusp_read(&flags); +- swsusp_close(FMODE_READ); ++ swsusp_close(FMODE_READ | FMODE_EXCL); + if (!error) + error = hibernation_restore(flags & SF_PLATFORM_MODE); + +@@ -981,7 +981,7 @@ static int software_resume(void) + /* The snapshot device should not be opened while we're running */ + if (!hibernate_acquire()) { + error = -EBUSY; +- swsusp_close(FMODE_READ); ++ swsusp_close(FMODE_READ | FMODE_EXCL); + goto Unlock; + } + +@@ -1016,7 +1016,7 @@ static int software_resume(void) + pm_pr_dbg("Hibernation image not present or could not be loaded.\n"); + return error; + Close_Finish: +- swsusp_close(FMODE_READ); ++ swsusp_close(FMODE_READ | FMODE_EXCL); + goto Finish; + } + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 44169f3081fdc..7e646079fbeb2 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -504,7 +504,10 @@ static ssize_t pm_wakeup_irq_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) + { +- return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA; ++ if (!pm_wakeup_irq()) ++ return -ENODATA; ++ ++ return sprintf(buf, "%u\n", pm_wakeup_irq()); + } + + power_attr_ro(pm_wakeup_irq); +diff --git a/kernel/power/process.c b/kernel/power/process.c +index 37401c99b7d7d..ee78a39463e63 100644 +--- a/kernel/power/process.c ++++ b/kernel/power/process.c +@@ -134,7 +134,7 @@ int freeze_processes(void) + if (!pm_freezing) + atomic_inc(&system_freezing_cnt); + +- pm_wakeup_clear(true); ++ pm_wakeup_clear(0); + pr_info("Freezing user space processes ... "); + pm_freezing = true; + error = try_to_freeze_tasks(true); +diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c +index f7a9860782135..330d499376924 100644 +--- a/kernel/power/snapshot.c ++++ b/kernel/power/snapshot.c +@@ -978,8 +978,7 @@ static void memory_bm_recycle(struct memory_bitmap *bm) + * Register a range of page frames the contents of which should not be saved + * during hibernation (to be used in the early initialization code). + */ +-void __init __register_nosave_region(unsigned long start_pfn, +- unsigned long end_pfn, int use_kmalloc) ++void __init register_nosave_region(unsigned long start_pfn, unsigned long end_pfn) + { + struct nosave_region *region; + +@@ -995,18 +994,12 @@ void __init __register_nosave_region(unsigned long start_pfn, + goto Report; + } + } +- if (use_kmalloc) { +- /* During init, this shouldn't fail */ +- region = kmalloc(sizeof(struct nosave_region), GFP_KERNEL); +- BUG_ON(!region); +- } else { +- /* This allocation cannot fail */ +- region = memblock_alloc(sizeof(struct nosave_region), +- SMP_CACHE_BYTES); +- if (!region) +- panic("%s: Failed to allocate %zu bytes\n", __func__, +- sizeof(struct nosave_region)); +- } ++ /* This allocation cannot fail */ ++ region = memblock_alloc(sizeof(struct nosave_region), ++ SMP_CACHE_BYTES); ++ if (!region) ++ panic("%s: Failed to allocate %zu bytes\n", __func__, ++ sizeof(struct nosave_region)); + region->start_pfn = start_pfn; + region->end_pfn = end_pfn; + list_add_tail(®ion->list, &nosave_regions); +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index eb75f394a0590..13d905dd32675 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -138,8 +138,6 @@ static void s2idle_loop(void) + break; + } + +- pm_wakeup_clear(false); +- + s2idle_enter(); + } + +diff --git a/kernel/power/swap.c b/kernel/power/swap.c +index 3cb89baebc796..f3a1086f7cdb2 100644 +--- a/kernel/power/swap.c ++++ b/kernel/power/swap.c +@@ -299,7 +299,7 @@ static int hib_submit_io(int op, int op_flags, pgoff_t page_off, void *addr, + return error; + } + +-static blk_status_t hib_wait_io(struct hib_bio_batch *hb) ++static int hib_wait_io(struct hib_bio_batch *hb) + { + /* + * We are relying on the behavior of blk_plug that a thread with +@@ -1521,9 +1521,10 @@ end: + int swsusp_check(void) + { + int error; ++ void *holder; + + hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device, +- FMODE_READ, NULL); ++ FMODE_READ | FMODE_EXCL, &holder); + if (!IS_ERR(hib_resume_bdev)) { + set_blocksize(hib_resume_bdev, PAGE_SIZE); + clear_page(swsusp_header); +@@ -1545,7 +1546,7 @@ int swsusp_check(void) + + put: + if (error) +- blkdev_put(hib_resume_bdev, FMODE_READ); ++ blkdev_put(hib_resume_bdev, FMODE_READ | FMODE_EXCL); + else + pr_debug("Image signature found, resuming\n"); + } else { +diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c +index 105df4dfc7839..52571dcad768b 100644 +--- a/kernel/power/wakelock.c ++++ b/kernel/power/wakelock.c +@@ -39,23 +39,20 @@ ssize_t pm_show_wakelocks(char *buf, bool show_active) + { + struct rb_node *node; + struct wakelock *wl; +- char *str = buf; +- char *end = buf + PAGE_SIZE; ++ int len = 0; + + mutex_lock(&wakelocks_lock); + + for (node = rb_first(&wakelocks_tree); node; node = rb_next(node)) { + wl = rb_entry(node, struct wakelock, node); + if (wl->ws->active == show_active) +- str += scnprintf(str, end - str, "%s ", wl->name); ++ len += sysfs_emit_at(buf, len, "%s ", wl->name); + } +- if (str > buf) +- str--; + +- str += scnprintf(str, end - str, "\n"); ++ len += sysfs_emit_at(buf, len, "\n"); + + mutex_unlock(&wakelocks_lock); +- return (str - buf); ++ return len; + } + + #if CONFIG_PM_WAKELOCKS_LIMIT > 0 +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index a8d0a58deebc7..99221b016c68b 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3252,6 +3252,11 @@ void defer_console_output(void) + preempt_enable(); + } + ++void printk_trigger_flush(void) ++{ ++ defer_console_output(); ++} ++ + int vprintk_deferred(const char *fmt, va_list args) + { + int r; +diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c +index ab4215266ebee..f922937eb39ad 100644 +--- a/kernel/rcu/rcutorture.c ++++ b/kernel/rcu/rcutorture.c +@@ -46,6 +46,7 @@ + #include <linux/oom.h> + #include <linux/tick.h> + #include <linux/rcupdate_trace.h> ++#include <linux/nmi.h> + + #include "rcu.h" + +@@ -109,6 +110,8 @@ torture_param(int, shutdown_secs, 0, "Shutdown time (s), <= zero to disable."); + torture_param(int, stall_cpu, 0, "Stall duration (s), zero to disable."); + torture_param(int, stall_cpu_holdoff, 10, + "Time to wait before starting stall (s)."); ++torture_param(bool, stall_no_softlockup, false, ++ "Avoid softlockup warning during cpu stall."); + torture_param(int, stall_cpu_irqsoff, 0, "Disable interrupts while stalling."); + torture_param(int, stall_cpu_block, 0, "Sleep while stalling."); + torture_param(int, stall_gp_kthread, 0, +@@ -1432,28 +1435,34 @@ static void rcutorture_one_extend(int *readstate, int newstate, + /* First, put new protection in place to avoid critical-section gap. */ + if (statesnew & RCUTORTURE_RDR_BH) + local_bh_disable(); ++ if (statesnew & RCUTORTURE_RDR_RBH) ++ rcu_read_lock_bh(); + if (statesnew & RCUTORTURE_RDR_IRQ) + local_irq_disable(); + if (statesnew & RCUTORTURE_RDR_PREEMPT) + preempt_disable(); +- if (statesnew & RCUTORTURE_RDR_RBH) +- rcu_read_lock_bh(); + if (statesnew & RCUTORTURE_RDR_SCHED) + rcu_read_lock_sched(); + if (statesnew & RCUTORTURE_RDR_RCU) + idxnew = cur_ops->readlock() << RCUTORTURE_RDR_SHIFT; + +- /* Next, remove old protection, irq first due to bh conflict. */ ++ /* ++ * Next, remove old protection, in decreasing order of strength ++ * to avoid unlock paths that aren't safe in the stronger ++ * context. Namely: BH can not be enabled with disabled interrupts. ++ * Additionally PREEMPT_RT requires that BH is enabled in preemptible ++ * context. ++ */ + if (statesold & RCUTORTURE_RDR_IRQ) + local_irq_enable(); +- if (statesold & RCUTORTURE_RDR_BH) +- local_bh_enable(); + if (statesold & RCUTORTURE_RDR_PREEMPT) + preempt_enable(); +- if (statesold & RCUTORTURE_RDR_RBH) +- rcu_read_unlock_bh(); + if (statesold & RCUTORTURE_RDR_SCHED) + rcu_read_unlock_sched(); ++ if (statesold & RCUTORTURE_RDR_BH) ++ local_bh_enable(); ++ if (statesold & RCUTORTURE_RDR_RBH) ++ rcu_read_unlock_bh(); + if (statesold & RCUTORTURE_RDR_RCU) { + bool lockit = !statesnew && !(torture_random(trsp) & 0xffff); + +@@ -1496,6 +1505,9 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp) + int mask = rcutorture_extend_mask_max(); + unsigned long randmask1 = torture_random(trsp) >> 8; + unsigned long randmask2 = randmask1 >> 3; ++ unsigned long preempts = RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED; ++ unsigned long preempts_irq = preempts | RCUTORTURE_RDR_IRQ; ++ unsigned long bhs = RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH; + + WARN_ON_ONCE(mask >> RCUTORTURE_RDR_SHIFT); + /* Mostly only one bit (need preemption!), sometimes lots of bits. */ +@@ -1503,11 +1515,26 @@ rcutorture_extend_mask(int oldmask, struct torture_random_state *trsp) + mask = mask & randmask2; + else + mask = mask & (1 << (randmask2 % RCUTORTURE_RDR_NBITS)); +- /* Can't enable bh w/irq disabled. */ +- if ((mask & RCUTORTURE_RDR_IRQ) && +- ((!(mask & RCUTORTURE_RDR_BH) && (oldmask & RCUTORTURE_RDR_BH)) || +- (!(mask & RCUTORTURE_RDR_RBH) && (oldmask & RCUTORTURE_RDR_RBH)))) +- mask |= RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH; ++ ++ /* ++ * Can't enable bh w/irq disabled. ++ */ ++ if (mask & RCUTORTURE_RDR_IRQ) ++ mask |= oldmask & bhs; ++ ++ /* ++ * Ideally these sequences would be detected in debug builds ++ * (regardless of RT), but until then don't stop testing ++ * them on non-RT. ++ */ ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ /* Can't modify BH in atomic context */ ++ if (oldmask & preempts_irq) ++ mask &= ~bhs; ++ if ((oldmask | mask) & preempts_irq) ++ mask |= oldmask & bhs; ++ } ++ + return mask ?: RCUTORTURE_RDR_RCU; + } + +@@ -2028,6 +2055,8 @@ static int rcu_torture_stall(void *args) + #else + schedule_timeout_uninterruptible(HZ); + #endif ++ } else if (stall_no_softlockup) { ++ touch_softlockup_watchdog(); + } + if (stall_cpu_irqsoff) + local_irq_enable(); +diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h +index 806160c44b172..6591914af4864 100644 +--- a/kernel/rcu/tasks.h ++++ b/kernel/rcu/tasks.h +@@ -197,6 +197,7 @@ static int __noreturn rcu_tasks_kthread(void *arg) + * This loop is terminated by the system going down. ;-) + */ + for (;;) { ++ set_tasks_gp_state(rtp, RTGS_WAIT_CBS); + + /* Pick up any new callbacks. */ + raw_spin_lock_irqsave(&rtp->cbs_lock, flags); +@@ -236,8 +237,6 @@ static int __noreturn rcu_tasks_kthread(void *arg) + } + /* Paranoid sleep to keep this from entering a tight loop */ + schedule_timeout_idle(rtp->gp_sleep); +- +- set_tasks_gp_state(rtp, RTGS_WAIT_CBS); + } + } + +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index bce848e50512e..4ca6d5b199e8e 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -327,7 +327,7 @@ static void rcu_dynticks_eqs_online(void) + */ + static __always_inline bool rcu_dynticks_curr_cpu_in_eqs(void) + { +- return !(atomic_read(this_cpu_ptr(&rcu_data.dynticks)) & 0x1); ++ return !(arch_atomic_read(this_cpu_ptr(&rcu_data.dynticks)) & 0x1); + } + + /* +@@ -1594,10 +1594,11 @@ static void __maybe_unused rcu_advance_cbs_nowake(struct rcu_node *rnp, + struct rcu_data *rdp) + { + rcu_lockdep_assert_cblist_protected(rdp); +- if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || +- !raw_spin_trylock_rcu_node(rnp)) ++ if (!rcu_seq_state(rcu_seq_current(&rnp->gp_seq)) || !raw_spin_trylock_rcu_node(rnp)) + return; +- WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp)); ++ // The grace period cannot end while we hold the rcu_node lock. ++ if (rcu_seq_state(rcu_seq_current(&rnp->gp_seq))) ++ WARN_ON_ONCE(rcu_advance_cbs(rnp, rdp)); + raw_spin_unlock_rcu_node(rnp); + } + +@@ -1907,7 +1908,7 @@ static void rcu_gp_fqs(bool first_time) + struct rcu_node *rnp = rcu_get_root(); + + WRITE_ONCE(rcu_state.gp_activity, jiffies); +- rcu_state.n_force_qs++; ++ WRITE_ONCE(rcu_state.n_force_qs, rcu_state.n_force_qs + 1); + if (first_time) { + /* Collect dyntick-idle snapshots. */ + force_qs_rnp(dyntick_save_progress_counter); +@@ -2550,7 +2551,7 @@ static void rcu_do_batch(struct rcu_data *rdp) + /* Reset ->qlen_last_fqs_check trigger if enough CBs have drained. */ + if (count == 0 && rdp->qlen_last_fqs_check != 0) { + rdp->qlen_last_fqs_check = 0; +- rdp->n_force_qs_snap = rcu_state.n_force_qs; ++ rdp->n_force_qs_snap = READ_ONCE(rcu_state.n_force_qs); + } else if (count < rdp->qlen_last_fqs_check - qhimark) + rdp->qlen_last_fqs_check = count; + +@@ -2898,10 +2899,10 @@ static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head, + } else { + /* Give the grace period a kick. */ + rdp->blimit = DEFAULT_MAX_RCU_BLIMIT; +- if (rcu_state.n_force_qs == rdp->n_force_qs_snap && ++ if (READ_ONCE(rcu_state.n_force_qs) == rdp->n_force_qs_snap && + rcu_segcblist_first_pend_cb(&rdp->cblist) != head) + rcu_force_quiescent_state(); +- rdp->n_force_qs_snap = rcu_state.n_force_qs; ++ rdp->n_force_qs_snap = READ_ONCE(rcu_state.n_force_qs); + rdp->qlen_last_fqs_check = rcu_segcblist_n_cbs(&rdp->cblist); + } + } +@@ -4128,7 +4129,7 @@ int rcutree_prepare_cpu(unsigned int cpu) + /* Set up local state, ensuring consistent view of global state. */ + raw_spin_lock_irqsave_rcu_node(rnp, flags); + rdp->qlen_last_fqs_check = 0; +- rdp->n_force_qs_snap = rcu_state.n_force_qs; ++ rdp->n_force_qs_snap = READ_ONCE(rcu_state.n_force_qs); + rdp->blimit = blimit; + rdp->dynticks_nesting = 1; /* CPU not up, no tearing. */ + rcu_dynticks_eqs_online(); +diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h +index 2796084ef85a5..16f94118ca34b 100644 +--- a/kernel/rcu/tree_exp.h ++++ b/kernel/rcu/tree_exp.h +@@ -387,6 +387,7 @@ retry_ipi: + continue; + } + if (get_cpu() == cpu) { ++ mask_ofl_test |= mask; + put_cpu(); + continue; + } +@@ -760,7 +761,7 @@ static void sync_sched_exp_online_cleanup(int cpu) + my_cpu = get_cpu(); + /* Quiescent state either not needed or already requested, leave. */ + if (!(READ_ONCE(rnp->expmask) & rdp->grpmask) || +- __this_cpu_read(rcu_data.cpu_no_qs.b.exp)) { ++ rdp->cpu_no_qs.b.exp) { + put_cpu(); + return; + } +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index d070059163d70..0d21a5cdc7247 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -1480,7 +1480,7 @@ static void rcu_bind_gp_kthread(void) + } + + /* Record the current task on dyntick-idle entry. */ +-static void noinstr rcu_dynticks_task_enter(void) ++static __always_inline void rcu_dynticks_task_enter(void) + { + #if defined(CONFIG_TASKS_RCU) && defined(CONFIG_NO_HZ_FULL) + WRITE_ONCE(current->rcu_tasks_idle_cpu, smp_processor_id()); +@@ -1488,7 +1488,7 @@ static void noinstr rcu_dynticks_task_enter(void) + } + + /* Record no current task on dyntick-idle exit. */ +-static void noinstr rcu_dynticks_task_exit(void) ++static __always_inline void rcu_dynticks_task_exit(void) + { + #if defined(CONFIG_TASKS_RCU) && defined(CONFIG_NO_HZ_FULL) + WRITE_ONCE(current->rcu_tasks_idle_cpu, -1); +@@ -1496,7 +1496,7 @@ static void noinstr rcu_dynticks_task_exit(void) + } + + /* Turn on heavyweight RCU tasks trace readers on idle/user entry. */ +-static void rcu_dynticks_task_trace_enter(void) ++static __always_inline void rcu_dynticks_task_trace_enter(void) + { + #ifdef CONFIG_TASKS_TRACE_RCU + if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB)) +@@ -1505,7 +1505,7 @@ static void rcu_dynticks_task_trace_enter(void) + } + + /* Turn off heavyweight RCU tasks trace readers on idle/user exit. */ +-static void rcu_dynticks_task_trace_exit(void) ++static __always_inline void rcu_dynticks_task_trace_exit(void) + { + #ifdef CONFIG_TASKS_TRACE_RCU + if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB)) +diff --git a/kernel/sched/autogroup.c b/kernel/sched/autogroup.c +index 2067080bb2358..8629b37d118e7 100644 +--- a/kernel/sched/autogroup.c ++++ b/kernel/sched/autogroup.c +@@ -31,7 +31,7 @@ static inline void autogroup_destroy(struct kref *kref) + ag->tg->rt_se = NULL; + ag->tg->rt_rq = NULL; + #endif +- sched_offline_group(ag->tg); ++ sched_release_group(ag->tg); + sched_destroy_group(ag->tg); + } + +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index f21714ea3db85..a0747eaa2dba7 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1914,7 +1914,7 @@ static void __init init_uclamp_rq(struct rq *rq) + }; + } + +- rq->uclamp_flags = 0; ++ rq->uclamp_flags = UCLAMP_FLAG_IDLE; + } + + static void __init init_uclamp(void) +@@ -3707,6 +3707,9 @@ out: + + bool cpus_share_cache(int this_cpu, int that_cpu) + { ++ if (this_cpu == that_cpu) ++ return true; ++ + return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); + } + +@@ -4328,8 +4331,6 @@ int sysctl_schedstats(struct ctl_table *table, int write, void *buffer, + */ + int sched_fork(unsigned long clone_flags, struct task_struct *p) + { +- unsigned long flags; +- + __sched_fork(clone_flags, p); + /* + * We mark the process as NEW here. This guarantees that +@@ -4375,23 +4376,6 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) + + init_entity_runnable_average(&p->se); + +- /* +- * The child is not yet in the pid-hash so no cgroup attach races, +- * and the cgroup is pinned to this child due to cgroup_fork() +- * is ran before sched_fork(). +- * +- * Silence PROVE_RCU. +- */ +- raw_spin_lock_irqsave(&p->pi_lock, flags); +- rseq_migrate(p); +- /* +- * We're setting the CPU for the first time, we don't migrate, +- * so use __set_task_cpu(). +- */ +- __set_task_cpu(p, smp_processor_id()); +- if (p->sched_class->task_fork) +- p->sched_class->task_fork(p); +- raw_spin_unlock_irqrestore(&p->pi_lock, flags); + + #ifdef CONFIG_SCHED_INFO + if (likely(sched_info_on())) +@@ -4408,6 +4392,35 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) + return 0; + } + ++void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs) ++{ ++ unsigned long flags; ++ ++ /* ++ * Because we're not yet on the pid-hash, p->pi_lock isn't strictly ++ * required yet, but lockdep gets upset if rules are violated. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++#ifdef CONFIG_CGROUP_SCHED ++ if (1) { ++ struct task_group *tg; ++ tg = container_of(kargs->cset->subsys[cpu_cgrp_id], ++ struct task_group, css); ++ tg = autogroup_task_group(p, tg); ++ p->sched_task_group = tg; ++ } ++#endif ++ rseq_migrate(p); ++ /* ++ * We're setting the CPU for the first time, we don't migrate, ++ * so use __set_task_cpu(). ++ */ ++ __set_task_cpu(p, smp_processor_id()); ++ if (p->sched_class->task_fork) ++ p->sched_class->task_fork(p); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++ + void sched_post_fork(struct task_struct *p) + { + uclamp_post_fork(p); +@@ -6656,11 +6669,11 @@ static int __init setup_preempt_mode(char *str) + int mode = sched_dynamic_mode(str); + if (mode < 0) { + pr_warn("Dynamic Preempt: unsupported mode: %s\n", str); +- return 1; ++ return 0; + } + + sched_dynamic_update(mode); +- return 0; ++ return 1; + } + __setup("preempt=", setup_preempt_mode); + +@@ -8195,9 +8208,7 @@ int __cond_resched_lock(spinlock_t *lock) + + if (spin_needbreak(lock) || resched) { + spin_unlock(lock); +- if (resched) +- preempt_schedule_common(); +- else ++ if (!_cond_resched()) + cpu_relax(); + ret = 1; + spin_lock(lock); +@@ -8215,9 +8226,7 @@ int __cond_resched_rwlock_read(rwlock_t *lock) + + if (rwlock_needbreak(lock) || resched) { + read_unlock(lock); +- if (resched) +- preempt_schedule_common(); +- else ++ if (!_cond_resched()) + cpu_relax(); + ret = 1; + read_lock(lock); +@@ -8235,9 +8244,7 @@ int __cond_resched_rwlock_write(rwlock_t *lock) + + if (rwlock_needbreak(lock) || resched) { + write_unlock(lock); +- if (resched) +- preempt_schedule_common(); +- else ++ if (!_cond_resched()) + cpu_relax(); + ret = 1; + write_lock(lock); +@@ -8637,9 +8644,6 @@ void __init init_idle(struct task_struct *idle, int cpu) + idle->flags |= PF_IDLE | PF_KTHREAD | PF_NO_SETAFFINITY; + kthread_set_per_cpu(idle, cpu); + +- scs_task_reset(idle); +- kasan_unpoison_task_stack(idle); +- + #ifdef CONFIG_SMP + /* + * It's possible that init_idle() gets called multiple times on a task, +@@ -8795,7 +8799,6 @@ void idle_task_exit(void) + finish_arch_post_lock_switch(); + } + +- scs_task_reset(current); + /* finish_cpu(), as ran on the BP, will clean up the active_mm state */ + } + +@@ -9716,6 +9719,22 @@ static void sched_free_group(struct task_group *tg) + kmem_cache_free(task_group_cache, tg); + } + ++static void sched_free_group_rcu(struct rcu_head *rcu) ++{ ++ sched_free_group(container_of(rcu, struct task_group, rcu)); ++} ++ ++static void sched_unregister_group(struct task_group *tg) ++{ ++ unregister_fair_sched_group(tg); ++ unregister_rt_sched_group(tg); ++ /* ++ * We have to wait for yet another RCU grace period to expire, as ++ * print_cfs_stats() might run concurrently. ++ */ ++ call_rcu(&tg->rcu, sched_free_group_rcu); ++} ++ + /* allocate runqueue etc for a new task group */ + struct task_group *sched_create_group(struct task_group *parent) + { +@@ -9759,25 +9778,35 @@ void sched_online_group(struct task_group *tg, struct task_group *parent) + } + + /* rcu callback to free various structures associated with a task group */ +-static void sched_free_group_rcu(struct rcu_head *rhp) ++static void sched_unregister_group_rcu(struct rcu_head *rhp) + { + /* Now it should be safe to free those cfs_rqs: */ +- sched_free_group(container_of(rhp, struct task_group, rcu)); ++ sched_unregister_group(container_of(rhp, struct task_group, rcu)); + } + + void sched_destroy_group(struct task_group *tg) + { + /* Wait for possible concurrent references to cfs_rqs complete: */ +- call_rcu(&tg->rcu, sched_free_group_rcu); ++ call_rcu(&tg->rcu, sched_unregister_group_rcu); + } + +-void sched_offline_group(struct task_group *tg) ++void sched_release_group(struct task_group *tg) + { + unsigned long flags; + +- /* End participation in shares distribution: */ +- unregister_fair_sched_group(tg); +- ++ /* ++ * Unlink first, to avoid walk_tg_tree_from() from finding us (via ++ * sched_cfs_period_timer()). ++ * ++ * For this to be effective, we have to wait for all pending users of ++ * this task group to leave their RCU critical section to ensure no new ++ * user will see our dying task group any more. Specifically ensure ++ * that tg_unthrottle_up() won't add decayed cfs_rq's to it. ++ * ++ * We therefore defer calling unregister_fair_sched_group() to ++ * sched_unregister_group() which is guarantied to get called only after the ++ * current RCU grace period has expired. ++ */ + spin_lock_irqsave(&task_group_lock, flags); + list_del_rcu(&tg->list); + list_del_rcu(&tg->siblings); +@@ -9896,7 +9925,7 @@ static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) + { + struct task_group *tg = css_tg(css); + +- sched_offline_group(tg); ++ sched_release_group(tg); + } + + static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) +@@ -9906,7 +9935,7 @@ static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) + /* + * Relies on the RCU grace period between css_released() and this. + */ +- sched_free_group(tg); ++ sched_unregister_group(tg); + } + + /* +diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c +index 893eece65bfda..ab67d97a84428 100644 +--- a/kernel/sched/cpuacct.c ++++ b/kernel/sched/cpuacct.c +@@ -21,15 +21,11 @@ static const char * const cpuacct_stat_desc[] = { + [CPUACCT_STAT_SYSTEM] = "system", + }; + +-struct cpuacct_usage { +- u64 usages[CPUACCT_STAT_NSTATS]; +-}; +- + /* track CPU usage of a group of tasks and its child groups */ + struct cpuacct { + struct cgroup_subsys_state css; + /* cpuusage holds pointer to a u64-type object on every CPU */ +- struct cpuacct_usage __percpu *cpuusage; ++ u64 __percpu *cpuusage; + struct kernel_cpustat __percpu *cpustat; + }; + +@@ -49,7 +45,7 @@ static inline struct cpuacct *parent_ca(struct cpuacct *ca) + return css_ca(ca->css.parent); + } + +-static DEFINE_PER_CPU(struct cpuacct_usage, root_cpuacct_cpuusage); ++static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage); + static struct cpuacct root_cpuacct = { + .cpustat = &kernel_cpustat, + .cpuusage = &root_cpuacct_cpuusage, +@@ -68,7 +64,7 @@ cpuacct_css_alloc(struct cgroup_subsys_state *parent_css) + if (!ca) + goto out; + +- ca->cpuusage = alloc_percpu(struct cpuacct_usage); ++ ca->cpuusage = alloc_percpu(u64); + if (!ca->cpuusage) + goto out_free_ca; + +@@ -99,7 +95,8 @@ static void cpuacct_css_free(struct cgroup_subsys_state *css) + static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu, + enum cpuacct_stat_index index) + { +- struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); ++ u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); ++ u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat; + u64 data; + + /* +@@ -115,14 +112,17 @@ static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu, + raw_spin_rq_lock_irq(cpu_rq(cpu)); + #endif + +- if (index == CPUACCT_STAT_NSTATS) { +- int i = 0; +- +- data = 0; +- for (i = 0; i < CPUACCT_STAT_NSTATS; i++) +- data += cpuusage->usages[i]; +- } else { +- data = cpuusage->usages[index]; ++ switch (index) { ++ case CPUACCT_STAT_USER: ++ data = cpustat[CPUTIME_USER] + cpustat[CPUTIME_NICE]; ++ break; ++ case CPUACCT_STAT_SYSTEM: ++ data = cpustat[CPUTIME_SYSTEM] + cpustat[CPUTIME_IRQ] + ++ cpustat[CPUTIME_SOFTIRQ]; ++ break; ++ case CPUACCT_STAT_NSTATS: ++ data = *cpuusage; ++ break; + } + + #ifndef CONFIG_64BIT +@@ -132,10 +132,14 @@ static u64 cpuacct_cpuusage_read(struct cpuacct *ca, int cpu, + return data; + } + +-static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) ++static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu) + { +- struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); +- int i; ++ u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); ++ u64 *cpustat = per_cpu_ptr(ca->cpustat, cpu)->cpustat; ++ ++ /* Don't allow to reset global kernel_cpustat */ ++ if (ca == &root_cpuacct) ++ return; + + #ifndef CONFIG_64BIT + /* +@@ -143,9 +147,10 @@ static void cpuacct_cpuusage_write(struct cpuacct *ca, int cpu, u64 val) + */ + raw_spin_rq_lock_irq(cpu_rq(cpu)); + #endif +- +- for (i = 0; i < CPUACCT_STAT_NSTATS; i++) +- cpuusage->usages[i] = val; ++ *cpuusage = 0; ++ cpustat[CPUTIME_USER] = cpustat[CPUTIME_NICE] = 0; ++ cpustat[CPUTIME_SYSTEM] = cpustat[CPUTIME_IRQ] = 0; ++ cpustat[CPUTIME_SOFTIRQ] = 0; + + #ifndef CONFIG_64BIT + raw_spin_rq_unlock_irq(cpu_rq(cpu)); +@@ -196,7 +201,7 @@ static int cpuusage_write(struct cgroup_subsys_state *css, struct cftype *cft, + return -EINVAL; + + for_each_possible_cpu(cpu) +- cpuacct_cpuusage_write(ca, cpu, 0); ++ cpuacct_cpuusage_write(ca, cpu); + + return 0; + } +@@ -243,25 +248,10 @@ static int cpuacct_all_seq_show(struct seq_file *m, void *V) + seq_puts(m, "\n"); + + for_each_possible_cpu(cpu) { +- struct cpuacct_usage *cpuusage = per_cpu_ptr(ca->cpuusage, cpu); +- + seq_printf(m, "%d", cpu); +- +- for (index = 0; index < CPUACCT_STAT_NSTATS; index++) { +-#ifndef CONFIG_64BIT +- /* +- * Take rq->lock to make 64-bit read safe on 32-bit +- * platforms. +- */ +- raw_spin_rq_lock_irq(cpu_rq(cpu)); +-#endif +- +- seq_printf(m, " %llu", cpuusage->usages[index]); +- +-#ifndef CONFIG_64BIT +- raw_spin_rq_unlock_irq(cpu_rq(cpu)); +-#endif +- } ++ for (index = 0; index < CPUACCT_STAT_NSTATS; index++) ++ seq_printf(m, " %llu", ++ cpuacct_cpuusage_read(ca, cpu, index)); + seq_puts(m, "\n"); + } + return 0; +@@ -339,16 +329,11 @@ static struct cftype files[] = { + void cpuacct_charge(struct task_struct *tsk, u64 cputime) + { + struct cpuacct *ca; +- int index = CPUACCT_STAT_SYSTEM; +- struct pt_regs *regs = get_irq_regs() ? : task_pt_regs(tsk); +- +- if (regs && user_mode(regs)) +- index = CPUACCT_STAT_USER; + + rcu_read_lock(); + + for (ca = task_ca(tsk); ca; ca = parent_ca(ca)) +- __this_cpu_add(ca->cpuusage->usages[index], cputime); ++ __this_cpu_add(*ca->cpuusage, cputime); + + rcu_read_unlock(); + } +diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c +index 872e481d5098c..042a6dbce8f32 100644 +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -148,10 +148,10 @@ void account_guest_time(struct task_struct *p, u64 cputime) + + /* Add guest time to cpustat. */ + if (task_nice(p) > 0) { +- cpustat[CPUTIME_NICE] += cputime; ++ task_group_account_field(p, CPUTIME_NICE, cputime); + cpustat[CPUTIME_GUEST_NICE] += cputime; + } else { +- cpustat[CPUTIME_USER] += cputime; ++ task_group_account_field(p, CPUTIME_USER, cputime); + cpustat[CPUTIME_GUEST] += cputime; + } + } +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index f6a05d9b54436..6420580f2730b 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -3422,7 +3422,6 @@ void set_task_rq_fair(struct sched_entity *se, + se->avg.last_update_time = n_last_update_time; + } + +- + /* + * When on migration a sched_entity joins/leaves the PELT hierarchy, we need to + * propagate its contribution. The key to this propagation is the invariant +@@ -3490,7 +3489,6 @@ void set_task_rq_fair(struct sched_entity *se, + * XXX: only do this for the part of runnable > running ? + * + */ +- + static inline void + update_tg_cfs_util(struct cfs_rq *cfs_rq, struct sched_entity *se, struct cfs_rq *gcfs_rq) + { +@@ -3722,7 +3720,19 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) + + r = removed_util; + sub_positive(&sa->util_avg, r); +- sa->util_sum = sa->util_avg * divider; ++ sub_positive(&sa->util_sum, r * divider); ++ /* ++ * Because of rounding, se->util_sum might ends up being +1 more than ++ * cfs->util_sum. Although this is not a problem by itself, detaching ++ * a lot of tasks with the rounding problem between 2 updates of ++ * util_avg (~1ms) can make cfs->util_sum becoming null whereas ++ * cfs_util_avg is not. ++ * Check that util_sum is still above its lower bound for the new ++ * util_avg. Given that period_contrib might have moved since the last ++ * sync, we are only sure that util_sum must be above or equal to ++ * util_avg * minimum possible divider ++ */ ++ sa->util_sum = max_t(u32, sa->util_sum, sa->util_avg * PELT_MIN_DIVIDER); + + r = removed_runnable; + sub_positive(&sa->runnable_avg, r); +@@ -6429,8 +6439,10 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + * pattern is IO completions. + */ + if (is_per_cpu_kthread(current) && ++ in_task() && + prev == smp_processor_id() && +- this_rq()->nr_running <= 1) { ++ this_rq()->nr_running <= 1 && ++ asym_fits_capacity(task_util, prev)) { + return prev; + } + +@@ -11358,8 +11370,6 @@ void free_fair_sched_group(struct task_group *tg) + { + int i; + +- destroy_cfs_bandwidth(tg_cfs_bandwidth(tg)); +- + for_each_possible_cpu(i) { + if (tg->cfs_rq) + kfree(tg->cfs_rq[i]); +@@ -11436,6 +11446,8 @@ void unregister_fair_sched_group(struct task_group *tg) + struct rq *rq; + int cpu; + ++ destroy_cfs_bandwidth(tg_cfs_bandwidth(tg)); ++ + for_each_possible_cpu(cpu) { + if (tg->se[cpu]) + remove_entity_load_avg(tg->se[cpu]); +diff --git a/kernel/sched/membarrier.c b/kernel/sched/membarrier.c +index b5add64d9698c..3d2825408e3a2 100644 +--- a/kernel/sched/membarrier.c ++++ b/kernel/sched/membarrier.c +@@ -147,11 +147,11 @@ + #endif + + #ifdef CONFIG_RSEQ +-#define MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ_BITMASK \ ++#define MEMBARRIER_PRIVATE_EXPEDITED_RSEQ_BITMASK \ + (MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ \ +- | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ_BITMASK) ++ | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ) + #else +-#define MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ_BITMASK 0 ++#define MEMBARRIER_PRIVATE_EXPEDITED_RSEQ_BITMASK 0 + #endif + + #define MEMBARRIER_CMD_BITMASK \ +@@ -159,7 +159,8 @@ + | MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED \ + | MEMBARRIER_CMD_PRIVATE_EXPEDITED \ + | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED \ +- | MEMBARRIER_PRIVATE_EXPEDITED_SYNC_CORE_BITMASK) ++ | MEMBARRIER_PRIVATE_EXPEDITED_SYNC_CORE_BITMASK \ ++ | MEMBARRIER_PRIVATE_EXPEDITED_RSEQ_BITMASK) + + static void ipi_mb(void *info) + { +diff --git a/kernel/sched/pelt.h b/kernel/sched/pelt.h +index e06071bf3472c..c336f5f481bca 100644 +--- a/kernel/sched/pelt.h ++++ b/kernel/sched/pelt.h +@@ -37,9 +37,11 @@ update_irq_load_avg(struct rq *rq, u64 running) + } + #endif + ++#define PELT_MIN_DIVIDER (LOAD_AVG_MAX - 1024) ++ + static inline u32 get_pelt_divider(struct sched_avg *avg) + { +- return LOAD_AVG_MAX - 1024 + avg->period_contrib; ++ return PELT_MIN_DIVIDER + avg->period_contrib; + } + + static inline void cfs_se_util_change(struct sched_avg *avg) +diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c +index 1652f2bb54b79..422f3b0445cf1 100644 +--- a/kernel/sched/psi.c ++++ b/kernel/sched/psi.c +@@ -34,13 +34,19 @@ + * delayed on that resource such that nobody is advancing and the CPU + * goes idle. This leaves both workload and CPU unproductive. + * +- * Naturally, the FULL state doesn't exist for the CPU resource at the +- * system level, but exist at the cgroup level, means all non-idle tasks +- * in a cgroup are delayed on the CPU resource which used by others outside +- * of the cgroup or throttled by the cgroup cpu.max configuration. +- * + * SOME = nr_delayed_tasks != 0 +- * FULL = nr_delayed_tasks != 0 && nr_running_tasks == 0 ++ * FULL = nr_delayed_tasks != 0 && nr_productive_tasks == 0 ++ * ++ * What it means for a task to be productive is defined differently ++ * for each resource. For IO, productive means a running task. For ++ * memory, productive means a running task that isn't a reclaimer. For ++ * CPU, productive means an oncpu task. ++ * ++ * Naturally, the FULL state doesn't exist for the CPU resource at the ++ * system level, but exist at the cgroup level. At the cgroup level, ++ * FULL means all non-idle tasks in the cgroup are delayed on the CPU ++ * resource which is being used by others outside of the cgroup or ++ * throttled by the cgroup cpu.max configuration. + * + * The percentage of wallclock time spent in those compound stall + * states gives pressure numbers between 0 and 100 for each resource, +@@ -81,13 +87,13 @@ + * + * threads = min(nr_nonidle_tasks, nr_cpus) + * SOME = min(nr_delayed_tasks / threads, 1) +- * FULL = (threads - min(nr_running_tasks, threads)) / threads ++ * FULL = (threads - min(nr_productive_tasks, threads)) / threads + * + * For the 257 number crunchers on 256 CPUs, this yields: + * + * threads = min(257, 256) + * SOME = min(1 / 256, 1) = 0.4% +- * FULL = (256 - min(257, 256)) / 256 = 0% ++ * FULL = (256 - min(256, 256)) / 256 = 0% + * + * For the 1 out of 4 memory-delayed tasks, this yields: + * +@@ -112,7 +118,7 @@ + * For each runqueue, we track: + * + * tSOME[cpu] = time(nr_delayed_tasks[cpu] != 0) +- * tFULL[cpu] = time(nr_delayed_tasks[cpu] && !nr_running_tasks[cpu]) ++ * tFULL[cpu] = time(nr_delayed_tasks[cpu] && !nr_productive_tasks[cpu]) + * tNONIDLE[cpu] = time(nr_nonidle_tasks[cpu] != 0) + * + * and then periodically aggregate: +@@ -233,7 +239,8 @@ static bool test_state(unsigned int *tasks, enum psi_states state) + case PSI_MEM_SOME: + return unlikely(tasks[NR_MEMSTALL]); + case PSI_MEM_FULL: +- return unlikely(tasks[NR_MEMSTALL] && !tasks[NR_RUNNING]); ++ return unlikely(tasks[NR_MEMSTALL] && ++ tasks[NR_RUNNING] == tasks[NR_MEMSTALL_RUNNING]); + case PSI_CPU_SOME: + return unlikely(tasks[NR_RUNNING] > tasks[NR_ONCPU]); + case PSI_CPU_FULL: +@@ -710,10 +717,11 @@ static void psi_group_change(struct psi_group *group, int cpu, + if (groupc->tasks[t]) { + groupc->tasks[t]--; + } else if (!psi_bug) { +- printk_deferred(KERN_ERR "psi: task underflow! cpu=%d t=%d tasks=[%u %u %u %u] clear=%x set=%x\n", ++ printk_deferred(KERN_ERR "psi: task underflow! cpu=%d t=%d tasks=[%u %u %u %u %u] clear=%x set=%x\n", + cpu, t, groupc->tasks[0], + groupc->tasks[1], groupc->tasks[2], +- groupc->tasks[3], clear, set); ++ groupc->tasks[3], groupc->tasks[4], ++ clear, set); + psi_bug = 1; + } + } +@@ -854,12 +862,15 @@ void psi_task_switch(struct task_struct *prev, struct task_struct *next, + int clear = TSK_ONCPU, set = 0; + + /* +- * When we're going to sleep, psi_dequeue() lets us handle +- * TSK_RUNNING and TSK_IOWAIT here, where we can combine it +- * with TSK_ONCPU and save walking common ancestors twice. ++ * When we're going to sleep, psi_dequeue() lets us ++ * handle TSK_RUNNING, TSK_MEMSTALL_RUNNING and ++ * TSK_IOWAIT here, where we can combine it with ++ * TSK_ONCPU and save walking common ancestors twice. + */ + if (sleep) { + clear |= TSK_RUNNING; ++ if (prev->in_memstall) ++ clear |= TSK_MEMSTALL_RUNNING; + if (prev->in_iowait) + set |= TSK_IOWAIT; + } +@@ -908,7 +919,7 @@ void psi_memstall_enter(unsigned long *flags) + rq = this_rq_lock_irq(&rf); + + current->in_memstall = 1; +- psi_task_change(current, 0, TSK_MEMSTALL); ++ psi_task_change(current, 0, TSK_MEMSTALL | TSK_MEMSTALL_RUNNING); + + rq_unlock_irq(rq, &rf); + } +@@ -937,7 +948,7 @@ void psi_memstall_leave(unsigned long *flags) + rq = this_rq_lock_irq(&rf); + + current->in_memstall = 0; +- psi_task_change(current, TSK_MEMSTALL, 0); ++ psi_task_change(current, TSK_MEMSTALL | TSK_MEMSTALL_RUNNING, 0); + + rq_unlock_irq(rq, &rf); + } +@@ -1071,44 +1082,6 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res) + return 0; + } + +-static int psi_io_show(struct seq_file *m, void *v) +-{ +- return psi_show(m, &psi_system, PSI_IO); +-} +- +-static int psi_memory_show(struct seq_file *m, void *v) +-{ +- return psi_show(m, &psi_system, PSI_MEM); +-} +- +-static int psi_cpu_show(struct seq_file *m, void *v) +-{ +- return psi_show(m, &psi_system, PSI_CPU); +-} +- +-static int psi_open(struct file *file, int (*psi_show)(struct seq_file *, void *)) +-{ +- if (file->f_mode & FMODE_WRITE && !capable(CAP_SYS_RESOURCE)) +- return -EPERM; +- +- return single_open(file, psi_show, NULL); +-} +- +-static int psi_io_open(struct inode *inode, struct file *file) +-{ +- return psi_open(file, psi_io_show); +-} +- +-static int psi_memory_open(struct inode *inode, struct file *file) +-{ +- return psi_open(file, psi_memory_show); +-} +- +-static int psi_cpu_open(struct inode *inode, struct file *file) +-{ +- return psi_open(file, psi_cpu_show); +-} +- + struct psi_trigger *psi_trigger_create(struct psi_group *group, + char *buf, size_t nbytes, enum psi_res res) + { +@@ -1151,7 +1124,6 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, + t->event = 0; + t->last_event_time = 0; + init_waitqueue_head(&t->event_wait); +- kref_init(&t->refcount); + + mutex_lock(&group->trigger_lock); + +@@ -1180,15 +1152,19 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, + return t; + } + +-static void psi_trigger_destroy(struct kref *ref) ++void psi_trigger_destroy(struct psi_trigger *t) + { +- struct psi_trigger *t = container_of(ref, struct psi_trigger, refcount); +- struct psi_group *group = t->group; ++ struct psi_group *group; + struct task_struct *task_to_destroy = NULL; + +- if (static_branch_likely(&psi_disabled)) ++ /* ++ * We do not check psi_disabled since it might have been disabled after ++ * the trigger got created. ++ */ ++ if (!t) + return; + ++ group = t->group; + /* + * Wakeup waiters to stop polling. Can happen if cgroup is deleted + * from under a polling process. +@@ -1224,9 +1200,9 @@ static void psi_trigger_destroy(struct kref *ref) + mutex_unlock(&group->trigger_lock); + + /* +- * Wait for both *trigger_ptr from psi_trigger_replace and +- * poll_task RCUs to complete their read-side critical sections +- * before destroying the trigger and optionally the poll_task ++ * Wait for psi_schedule_poll_work RCU to complete its read-side ++ * critical section before destroying the trigger and optionally the ++ * poll_task. + */ + synchronize_rcu(); + /* +@@ -1243,18 +1219,6 @@ static void psi_trigger_destroy(struct kref *ref) + kfree(t); + } + +-void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *new) +-{ +- struct psi_trigger *old = *trigger_ptr; +- +- if (static_branch_likely(&psi_disabled)) +- return; +- +- rcu_assign_pointer(*trigger_ptr, new); +- if (old) +- kref_put(&old->refcount, psi_trigger_destroy); +-} +- + __poll_t psi_trigger_poll(void **trigger_ptr, + struct file *file, poll_table *wait) + { +@@ -1264,27 +1228,57 @@ __poll_t psi_trigger_poll(void **trigger_ptr, + if (static_branch_likely(&psi_disabled)) + return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI; + +- rcu_read_lock(); +- +- t = rcu_dereference(*(void __rcu __force **)trigger_ptr); +- if (!t) { +- rcu_read_unlock(); ++ t = smp_load_acquire(trigger_ptr); ++ if (!t) + return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI; +- } +- kref_get(&t->refcount); +- +- rcu_read_unlock(); + + poll_wait(file, &t->event_wait, wait); + + if (cmpxchg(&t->event, 1, 0) == 1) + ret |= EPOLLPRI; + +- kref_put(&t->refcount, psi_trigger_destroy); +- + return ret; + } + ++#ifdef CONFIG_PROC_FS ++static int psi_io_show(struct seq_file *m, void *v) ++{ ++ return psi_show(m, &psi_system, PSI_IO); ++} ++ ++static int psi_memory_show(struct seq_file *m, void *v) ++{ ++ return psi_show(m, &psi_system, PSI_MEM); ++} ++ ++static int psi_cpu_show(struct seq_file *m, void *v) ++{ ++ return psi_show(m, &psi_system, PSI_CPU); ++} ++ ++static int psi_open(struct file *file, int (*psi_show)(struct seq_file *, void *)) ++{ ++ if (file->f_mode & FMODE_WRITE && !capable(CAP_SYS_RESOURCE)) ++ return -EPERM; ++ ++ return single_open(file, psi_show, NULL); ++} ++ ++static int psi_io_open(struct inode *inode, struct file *file) ++{ ++ return psi_open(file, psi_io_show); ++} ++ ++static int psi_memory_open(struct inode *inode, struct file *file) ++{ ++ return psi_open(file, psi_memory_show); ++} ++ ++static int psi_cpu_open(struct inode *inode, struct file *file) ++{ ++ return psi_open(file, psi_cpu_show); ++} ++ + static ssize_t psi_write(struct file *file, const char __user *user_buf, + size_t nbytes, enum psi_res res) + { +@@ -1305,14 +1299,24 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf, + + buf[buf_size - 1] = '\0'; + +- new = psi_trigger_create(&psi_system, buf, nbytes, res); +- if (IS_ERR(new)) +- return PTR_ERR(new); +- + seq = file->private_data; ++ + /* Take seq->lock to protect seq->private from concurrent writes */ + mutex_lock(&seq->lock); +- psi_trigger_replace(&seq->private, new); ++ ++ /* Allow only one trigger per file descriptor */ ++ if (seq->private) { ++ mutex_unlock(&seq->lock); ++ return -EBUSY; ++ } ++ ++ new = psi_trigger_create(&psi_system, buf, nbytes, res); ++ if (IS_ERR(new)) { ++ mutex_unlock(&seq->lock); ++ return PTR_ERR(new); ++ } ++ ++ smp_store_release(&seq->private, new); + mutex_unlock(&seq->lock); + + return nbytes; +@@ -1347,7 +1351,7 @@ static int psi_fop_release(struct inode *inode, struct file *file) + { + struct seq_file *seq = file->private_data; + +- psi_trigger_replace(&seq->private, NULL); ++ psi_trigger_destroy(seq->private); + return single_release(inode, file); + } + +@@ -1389,3 +1393,5 @@ static int __init psi_proc_init(void) + return 0; + } + module_init(psi_proc_init); ++ ++#endif /* CONFIG_PROC_FS */ +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 3daf42a0f4623..54f9bb3f15605 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -52,11 +52,8 @@ void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime) + rt_b->rt_period_timer.function = sched_rt_period_timer; + } + +-static void start_rt_bandwidth(struct rt_bandwidth *rt_b) ++static inline void do_start_rt_bandwidth(struct rt_bandwidth *rt_b) + { +- if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF) +- return; +- + raw_spin_lock(&rt_b->rt_runtime_lock); + if (!rt_b->rt_period_active) { + rt_b->rt_period_active = 1; +@@ -75,6 +72,14 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b) + raw_spin_unlock(&rt_b->rt_runtime_lock); + } + ++static void start_rt_bandwidth(struct rt_bandwidth *rt_b) ++{ ++ if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF) ++ return; ++ ++ do_start_rt_bandwidth(rt_b); ++} ++ + void init_rt_rq(struct rt_rq *rt_rq) + { + struct rt_prio_array *array; +@@ -137,13 +142,17 @@ static inline struct rq *rq_of_rt_se(struct sched_rt_entity *rt_se) + return rt_rq->rq; + } + +-void free_rt_sched_group(struct task_group *tg) ++void unregister_rt_sched_group(struct task_group *tg) + { +- int i; +- + if (tg->rt_se) + destroy_rt_bandwidth(&tg->rt_bandwidth); + ++} ++ ++void free_rt_sched_group(struct task_group *tg) ++{ ++ int i; ++ + for_each_possible_cpu(i) { + if (tg->rt_rq) + kfree(tg->rt_rq[i]); +@@ -250,6 +259,8 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se) + return &rq->rt; + } + ++void unregister_rt_sched_group(struct task_group *tg) { } ++ + void free_rt_sched_group(struct task_group *tg) { } + + int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) +@@ -1023,13 +1034,17 @@ static void update_curr_rt(struct rq *rq) + + for_each_sched_rt_entity(rt_se) { + struct rt_rq *rt_rq = rt_rq_of_se(rt_se); ++ int exceeded; + + if (sched_rt_runtime(rt_rq) != RUNTIME_INF) { + raw_spin_lock(&rt_rq->rt_runtime_lock); + rt_rq->rt_time += delta_exec; +- if (sched_rt_runtime_exceeded(rt_rq)) ++ exceeded = sched_rt_runtime_exceeded(rt_rq); ++ if (exceeded) + resched_curr(rq); + raw_spin_unlock(&rt_rq->rt_runtime_lock); ++ if (exceeded) ++ do_start_rt_bandwidth(sched_rt_bandwidth(rt_rq)); + } + } + } +@@ -2779,8 +2794,12 @@ static int sched_rt_global_validate(void) + + static void sched_rt_do_global(void) + { ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags); + def_rt_bandwidth.rt_runtime = global_rt_runtime(); + def_rt_bandwidth.rt_period = ns_to_ktime(global_rt_period()); ++ raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags); + } + + int sched_rt_handler(struct ctl_table *table, int write, void *buffer, +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 3d3e5793e1172..4f432826933da 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -486,6 +486,7 @@ extern void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b); + extern void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b); + extern void unthrottle_cfs_rq(struct cfs_rq *cfs_rq); + ++extern void unregister_rt_sched_group(struct task_group *tg); + extern void free_rt_sched_group(struct task_group *tg); + extern int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent); + extern void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, +@@ -501,7 +502,7 @@ extern struct task_group *sched_create_group(struct task_group *parent); + extern void sched_online_group(struct task_group *tg, + struct task_group *parent); + extern void sched_destroy_group(struct task_group *tg); +-extern void sched_offline_group(struct task_group *tg); ++extern void sched_release_group(struct task_group *tg); + + extern void sched_move_task(struct task_struct *tsk); + +diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h +index d8f8eb0c655ba..606a3982d13a5 100644 +--- a/kernel/sched/stats.h ++++ b/kernel/sched/stats.h +@@ -69,6 +69,9 @@ static inline void psi_enqueue(struct task_struct *p, bool wakeup) + if (static_branch_likely(&psi_disabled)) + return; + ++ if (p->in_memstall) ++ set |= TSK_MEMSTALL_RUNNING; ++ + if (!wakeup || p->sched_psi_wake_requeue) { + if (p->in_memstall) + set |= TSK_MEMSTALL; +@@ -99,7 +102,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep) + return; + + if (p->in_memstall) +- clear |= TSK_MEMSTALL; ++ clear |= (TSK_MEMSTALL | TSK_MEMSTALL_RUNNING); + + psi_task_change(p, clear, 0); + } +diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c +index 76577d1642a5d..eca38107b32f1 100644 +--- a/kernel/sched/wait.c ++++ b/kernel/sched/wait.c +@@ -238,6 +238,13 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode) + } + EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ + ++void __wake_up_pollfree(struct wait_queue_head *wq_head) ++{ ++ __wake_up(wq_head, TASK_NORMAL, 0, poll_to_key(EPOLLHUP | POLLFREE)); ++ /* POLLFREE must have cleared the queue. */ ++ WARN_ON_ONCE(waitqueue_active(wq_head)); ++} ++ + /* + * Note: we use "set_current_state()" _after_ the wait-queue add, + * because we need a memory barrier there on SMP, so that any +diff --git a/kernel/scs.c b/kernel/scs.c +index e2a71fc82fa06..579841be88646 100644 +--- a/kernel/scs.c ++++ b/kernel/scs.c +@@ -78,6 +78,7 @@ void scs_free(void *s) + if (this_cpu_cmpxchg(scs_cache[i], 0, s) == NULL) + return; + ++ kasan_unpoison_vmalloc(s, SCS_SIZE); + vfree_atomic(s); + } + +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index 4d8f44a177274..db10e73d06e02 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -29,6 +29,9 @@ + #include <linux/syscalls.h> + #include <linux/sysctl.h> + ++/* Not exposed in headers: strictly internal use only. */ ++#define SECCOMP_MODE_DEAD (SECCOMP_MODE_FILTER + 1) ++ + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + #include <asm/syscall.h> + #endif +@@ -1010,6 +1013,7 @@ static void __secure_computing_strict(int this_syscall) + #ifdef SECCOMP_DEBUG + dump_stack(); + #endif ++ current->seccomp.mode = SECCOMP_MODE_DEAD; + seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true); + do_exit(SIGKILL); + } +@@ -1261,6 +1265,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, + case SECCOMP_RET_KILL_THREAD: + case SECCOMP_RET_KILL_PROCESS: + default: ++ current->seccomp.mode = SECCOMP_MODE_DEAD; + seccomp_log(this_syscall, SIGSYS, action, true); + /* Dump core only if this is the last remaining thread. */ + if (action != SECCOMP_RET_KILL_THREAD || +@@ -1309,6 +1314,11 @@ int __secure_computing(const struct seccomp_data *sd) + return 0; + case SECCOMP_MODE_FILTER: + return __seccomp_filter(this_syscall, sd, false); ++ /* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */ ++ case SECCOMP_MODE_DEAD: ++ WARN_ON_ONCE(1); ++ do_exit(SIGKILL); ++ return -1; + default: + BUG(); + } +diff --git a/kernel/signal.c b/kernel/signal.c +index 487bf4f5dadf4..6e3dbb3d12170 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1298,6 +1298,12 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p + return ret; + } + ++enum sig_handler { ++ HANDLER_CURRENT, /* If reachable use the current handler */ ++ HANDLER_SIG_DFL, /* Always use SIG_DFL handler semantics */ ++ HANDLER_EXIT, /* Only visible as the process exit code */ ++}; ++ + /* + * Force a signal that the process can't ignore: if necessary + * we unblock the signal and change any SIG_IGN to SIG_DFL. +@@ -1310,7 +1316,8 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p + * that is why we also clear SIGNAL_UNKILLABLE. + */ + static int +-force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl) ++force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, ++ enum sig_handler handler) + { + unsigned long int flags; + int ret, blocked, ignored; +@@ -1321,8 +1328,10 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool + action = &t->sighand->action[sig-1]; + ignored = action->sa.sa_handler == SIG_IGN; + blocked = sigismember(&t->blocked, sig); +- if (blocked || ignored || sigdfl) { ++ if (blocked || ignored || (handler != HANDLER_CURRENT)) { + action->sa.sa_handler = SIG_DFL; ++ if (handler == HANDLER_EXIT) ++ action->sa.sa_flags |= SA_IMMUTABLE; + if (blocked) { + sigdelset(&t->blocked, sig); + recalc_sigpending_and_wake(t); +@@ -1330,9 +1339,10 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool + } + /* + * Don't clear SIGNAL_UNKILLABLE for traced tasks, users won't expect +- * debugging to leave init killable. ++ * debugging to leave init killable. But HANDLER_EXIT is always fatal. + */ +- if (action->sa.sa_handler == SIG_DFL && !t->ptrace) ++ if (action->sa.sa_handler == SIG_DFL && ++ (!t->ptrace || (handler == HANDLER_EXIT))) + t->signal->flags &= ~SIGNAL_UNKILLABLE; + ret = send_signal(sig, info, t, PIDTYPE_PID); + spin_unlock_irqrestore(&t->sighand->siglock, flags); +@@ -1342,7 +1352,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool + + int force_sig_info(struct kernel_siginfo *info) + { +- return force_sig_info_to_task(info, current, false); ++ return force_sig_info_to_task(info, current, HANDLER_CURRENT); + } + + /* +@@ -1649,6 +1659,32 @@ void force_sig(int sig) + } + EXPORT_SYMBOL(force_sig); + ++void force_fatal_sig(int sig) ++{ ++ struct kernel_siginfo info; ++ ++ clear_siginfo(&info); ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = SI_KERNEL; ++ info.si_pid = 0; ++ info.si_uid = 0; ++ force_sig_info_to_task(&info, current, HANDLER_SIG_DFL); ++} ++ ++void force_exit_sig(int sig) ++{ ++ struct kernel_siginfo info; ++ ++ clear_siginfo(&info); ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = SI_KERNEL; ++ info.si_pid = 0; ++ info.si_uid = 0; ++ force_sig_info_to_task(&info, current, HANDLER_EXIT); ++} ++ + /* + * When things go south during signal handling, we + * will force a SIGSEGV. And if the signal that caused +@@ -1657,15 +1693,10 @@ EXPORT_SYMBOL(force_sig); + */ + void force_sigsegv(int sig) + { +- struct task_struct *p = current; +- +- if (sig == SIGSEGV) { +- unsigned long flags; +- spin_lock_irqsave(&p->sighand->siglock, flags); +- p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; +- spin_unlock_irqrestore(&p->sighand->siglock, flags); +- } +- force_sig(SIGSEGV); ++ if (sig == SIGSEGV) ++ force_fatal_sig(SIGSEGV); ++ else ++ force_sig(SIGSEGV); + } + + int force_sig_fault_to_task(int sig, int code, void __user *addr +@@ -1684,7 +1715,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr + info.si_flags = flags; + info.si_isr = isr; + #endif +- return force_sig_info_to_task(&info, t, false); ++ return force_sig_info_to_task(&info, t, HANDLER_CURRENT); + } + + int force_sig_fault(int sig, int code, void __user *addr +@@ -1804,7 +1835,8 @@ int force_sig_seccomp(int syscall, int reason, bool force_coredump) + info.si_errno = reason; + info.si_arch = syscall_get_arch(current); + info.si_syscall = syscall; +- return force_sig_info_to_task(&info, current, force_coredump); ++ return force_sig_info_to_task(&info, current, ++ force_coredump ? HANDLER_EXIT : HANDLER_CURRENT); + } + + /* For the crazy architectures that include trap information in +@@ -2169,15 +2201,6 @@ static inline bool may_ptrace_stop(void) + return true; + } + +-/* +- * Return non-zero if there is a SIGKILL that should be waking us up. +- * Called with the siglock held. +- */ +-static bool sigkill_pending(struct task_struct *tsk) +-{ +- return sigismember(&tsk->pending.signal, SIGKILL) || +- sigismember(&tsk->signal->shared_pending.signal, SIGKILL); +-} + + /* + * This must be called with current->sighand->siglock held. +@@ -2204,17 +2227,16 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t + * calling arch_ptrace_stop, so we must release it now. + * To preserve proper semantics, we must do this before + * any signal bookkeeping like checking group_stop_count. +- * Meanwhile, a SIGKILL could come in before we retake the +- * siglock. That must prevent us from sleeping in TASK_TRACED. +- * So after regaining the lock, we must check for SIGKILL. + */ + spin_unlock_irq(¤t->sighand->siglock); + arch_ptrace_stop(exit_code, info); + spin_lock_irq(¤t->sighand->siglock); +- if (sigkill_pending(current)) +- return; + } + ++ /* ++ * schedule() will not sleep if there is a pending signal that ++ * can awaken the task. ++ */ + set_special_state(TASK_TRACED); + + /* +@@ -2688,19 +2710,19 @@ relock: + goto relock; + } + +- /* Has this task already been marked for death? */ +- if (signal_group_exit(signal)) { +- ksig->info.si_signo = signr = SIGKILL; +- sigdelset(¤t->pending.signal, SIGKILL); +- trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO, +- &sighand->action[SIGKILL - 1]); +- recalc_sigpending(); +- goto fatal; +- } +- + for (;;) { + struct k_sigaction *ka; + ++ /* Has this task already been marked for death? */ ++ if (signal_group_exit(signal)) { ++ ksig->info.si_signo = signr = SIGKILL; ++ sigdelset(¤t->pending.signal, SIGKILL); ++ trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO, ++ &sighand->action[SIGKILL - 1]); ++ recalc_sigpending(); ++ goto fatal; ++ } ++ + if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && + do_signal_stop(0)) + goto relock; +@@ -2739,7 +2761,8 @@ relock: + if (!signr) + break; /* will return 0 */ + +- if (unlikely(current->ptrace) && signr != SIGKILL) { ++ if (unlikely(current->ptrace) && (signr != SIGKILL) && ++ !(sighand->action[signr -1].sa.sa_flags & SA_IMMUTABLE)) { + signr = ptrace_signal(signr, &ksig->info); + if (!signr) + continue; +@@ -4089,6 +4112,10 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) + k = &p->sighand->action[sig-1]; + + spin_lock_irq(&p->sighand->siglock); ++ if (k->sa.sa_flags & SA_IMMUTABLE) { ++ spin_unlock_irq(&p->sighand->siglock); ++ return -EINVAL; ++ } + if (oact) + *oact = *k; + +diff --git a/kernel/stackleak.c b/kernel/stackleak.c +index ce161a8e8d975..dd07239ddff9f 100644 +--- a/kernel/stackleak.c ++++ b/kernel/stackleak.c +@@ -48,7 +48,7 @@ int stack_erasing_sysctl(struct ctl_table *table, int write, + #define skip_erasing() false + #endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */ + +-asmlinkage void notrace stackleak_erase(void) ++asmlinkage void noinstr stackleak_erase(void) + { + /* It would be nice not to have 'kstack_ptr' and 'boundary' on stack */ + unsigned long kstack_ptr = current->lowest_stack; +@@ -102,9 +102,8 @@ asmlinkage void notrace stackleak_erase(void) + /* Reset the 'lowest_stack' value for the next syscall */ + current->lowest_stack = current_top_of_stack() - THREAD_SIZE/64; + } +-NOKPROBE_SYMBOL(stackleak_erase); + +-void __used __no_caller_saved_registers notrace stackleak_track_stack(void) ++void __used __no_caller_saved_registers noinstr stackleak_track_stack(void) + { + unsigned long sp = current_stack_pointer; + +diff --git a/kernel/sys.c b/kernel/sys.c +index 8fdac0d90504a..3e4e8930fafc6 100644 +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -472,6 +472,16 @@ static int set_user(struct cred *new) + if (!new_user) + return -EAGAIN; + ++ free_uid(new->user); ++ new->user = new_user; ++ return 0; ++} ++ ++static void flag_nproc_exceeded(struct cred *new) ++{ ++ if (new->ucounts == current_ucounts()) ++ return; ++ + /* + * We don't fail in case of NPROC limit excess here because too many + * poorly written programs don't check set*uid() return code, assuming +@@ -480,15 +490,10 @@ static int set_user(struct cred *new) + * failure to the execve() stage. + */ + if (is_ucounts_overlimit(new->ucounts, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)) && +- new_user != INIT_USER && +- !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) ++ new->user != INIT_USER) + current->flags |= PF_NPROC_EXCEEDED; + else + current->flags &= ~PF_NPROC_EXCEEDED; +- +- free_uid(new->user); +- new->user = new_user; +- return 0; + } + + /* +@@ -563,6 +568,7 @@ long __sys_setreuid(uid_t ruid, uid_t euid) + if (retval < 0) + goto error; + ++ flag_nproc_exceeded(new); + return commit_creds(new); + + error: +@@ -625,6 +631,7 @@ long __sys_setuid(uid_t uid) + if (retval < 0) + goto error; + ++ flag_nproc_exceeded(new); + return commit_creds(new); + + error: +@@ -704,6 +711,7 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) + if (retval < 0) + goto error; + ++ flag_nproc_exceeded(new); + return commit_creds(new); + + error: +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 083be6af29d70..0586047f73234 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -228,6 +228,10 @@ static int bpf_stats_handler(struct ctl_table *table, int write, + return ret; + } + ++void __weak unpriv_ebpf_notify(int new_state) ++{ ++} ++ + static int bpf_unpriv_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +@@ -245,6 +249,9 @@ static int bpf_unpriv_handler(struct ctl_table *table, int write, + return -EPERM; + *(int *)table->data = unpriv_enable; + } ++ ++ unpriv_ebpf_notify(unpriv_enable); ++ + return ret; + } + #endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */ +diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c +index b8a14d2fb5ba6..bcad1a1e5dcf1 100644 +--- a/kernel/time/clocksource.c ++++ b/kernel/time/clocksource.c +@@ -107,7 +107,7 @@ static u64 suspend_start; + * This delay could be due to SMIs, NMIs, or to VCPU preemptions. Used as + * a lower bound for cs->uncertainty_margin values when registering clocks. + */ +-#define WATCHDOG_MAX_SKEW (50 * NSEC_PER_USEC) ++#define WATCHDOG_MAX_SKEW (100 * NSEC_PER_USEC) + + #ifdef CONFIG_CLOCKSOURCE_WATCHDOG + static void clocksource_watchdog_work(struct work_struct *work); +@@ -205,17 +205,24 @@ EXPORT_SYMBOL_GPL(max_cswd_read_retries); + static int verify_n_cpus = 8; + module_param(verify_n_cpus, int, 0644); + +-static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) ++enum wd_read_status { ++ WD_READ_SUCCESS, ++ WD_READ_UNSTABLE, ++ WD_READ_SKIP ++}; ++ ++static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) + { + unsigned int nretries; +- u64 wd_end, wd_delta; +- int64_t wd_delay; ++ u64 wd_end, wd_end2, wd_delta; ++ int64_t wd_delay, wd_seq_delay; + + for (nretries = 0; nretries <= max_cswd_read_retries; nretries++) { + local_irq_disable(); + *wdnow = watchdog->read(watchdog); + *csnow = cs->read(cs); + wd_end = watchdog->read(watchdog); ++ wd_end2 = watchdog->read(watchdog); + local_irq_enable(); + + wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask); +@@ -226,13 +233,34 @@ static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) + pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n", + smp_processor_id(), watchdog->name, nretries); + } +- return true; ++ return WD_READ_SUCCESS; + } ++ ++ /* ++ * Now compute delay in consecutive watchdog read to see if ++ * there is too much external interferences that cause ++ * significant delay in reading both clocksource and watchdog. ++ * ++ * If consecutive WD read-back delay > WATCHDOG_MAX_SKEW/2, ++ * report system busy, reinit the watchdog and skip the current ++ * watchdog test. ++ */ ++ wd_delta = clocksource_delta(wd_end2, wd_end, watchdog->mask); ++ wd_seq_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, watchdog->shift); ++ if (wd_seq_delay > WATCHDOG_MAX_SKEW/2) ++ goto skip_test; + } + + pr_warn("timekeeping watchdog on CPU%d: %s read-back delay of %lldns, attempt %d, marking unstable\n", + smp_processor_id(), watchdog->name, wd_delay, nretries); +- return false; ++ return WD_READ_UNSTABLE; ++ ++skip_test: ++ pr_info("timekeeping watchdog on CPU%d: %s wd-wd read-back delay of %lldns\n", ++ smp_processor_id(), watchdog->name, wd_seq_delay); ++ pr_info("wd-%s-wd read-back delay of %lldns, clock-skew test skipped!\n", ++ cs->name, wd_delay); ++ return WD_READ_SKIP; + } + + static u64 csnow_mid; +@@ -356,6 +384,7 @@ static void clocksource_watchdog(struct timer_list *unused) + int next_cpu, reset_pending; + int64_t wd_nsec, cs_nsec; + struct clocksource *cs; ++ enum wd_read_status read_ret; + u32 md; + + spin_lock(&watchdog_lock); +@@ -373,9 +402,12 @@ static void clocksource_watchdog(struct timer_list *unused) + continue; + } + +- if (!cs_watchdog_read(cs, &csnow, &wdnow)) { +- /* Clock readout unreliable, so give it up. */ +- __clocksource_unstable(cs); ++ read_ret = cs_watchdog_read(cs, &csnow, &wdnow); ++ ++ if (read_ret != WD_READ_SUCCESS) { ++ if (read_ret == WD_READ_UNSTABLE) ++ /* Clock readout unreliable, so give it up. */ ++ __clocksource_unstable(cs); + continue; + } + +diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c +index 643d412ac6235..96b4e78104266 100644 +--- a/kernel/time/posix-cpu-timers.c ++++ b/kernel/time/posix-cpu-timers.c +@@ -1158,14 +1158,29 @@ static void posix_cpu_timers_work(struct callback_head *work) + handle_posix_cpu_timers(current); + } + ++/* ++ * Clear existing posix CPU timers task work. ++ */ ++void clear_posix_cputimers_work(struct task_struct *p) ++{ ++ /* ++ * A copied work entry from the old task is not meaningful, clear it. ++ * N.B. init_task_work will not do this. ++ */ ++ memset(&p->posix_cputimers_work.work, 0, ++ sizeof(p->posix_cputimers_work.work)); ++ init_task_work(&p->posix_cputimers_work.work, ++ posix_cpu_timers_work); ++ p->posix_cputimers_work.scheduled = false; ++} ++ + /* + * Initialize posix CPU timers task work in init task. Out of line to + * keep the callback static and to avoid header recursion hell. + */ + void __init posix_cputimers_init_work(void) + { +- init_task_work(¤t->posix_cputimers_work.work, +- posix_cpu_timers_work); ++ clear_posix_cputimers_work(current); + } + + /* +diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c +index b348749a9fc62..dcdcb85121e40 100644 +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -1306,8 +1306,7 @@ int do_settimeofday64(const struct timespec64 *ts) + timekeeping_forward_now(tk); + + xt = tk_xtime(tk); +- ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; +- ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; ++ ts_delta = timespec64_sub(*ts, xt); + + if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { + ret = -EINVAL; +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index e3d2c23c413d4..85f1021ad4595 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -2054,26 +2054,28 @@ unsigned long msleep_interruptible(unsigned int msecs) + EXPORT_SYMBOL(msleep_interruptible); + + /** +- * usleep_range - Sleep for an approximate time +- * @min: Minimum time in usecs to sleep +- * @max: Maximum time in usecs to sleep ++ * usleep_range_state - Sleep for an approximate time in a given state ++ * @min: Minimum time in usecs to sleep ++ * @max: Maximum time in usecs to sleep ++ * @state: State of the current task that will be while sleeping + * + * In non-atomic context where the exact wakeup time is flexible, use +- * usleep_range() instead of udelay(). The sleep improves responsiveness ++ * usleep_range_state() instead of udelay(). The sleep improves responsiveness + * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces + * power usage by allowing hrtimers to take advantage of an already- + * scheduled interrupt instead of scheduling a new one just for this sleep. + */ +-void __sched usleep_range(unsigned long min, unsigned long max) ++void __sched usleep_range_state(unsigned long min, unsigned long max, ++ unsigned int state) + { + ktime_t exp = ktime_add_us(ktime_get(), min); + u64 delta = (u64)(max - min) * NSEC_PER_USEC; + + for (;;) { +- __set_current_state(TASK_UNINTERRUPTIBLE); ++ __set_current_state(state); + /* Do not return before the requested sleep time has elapsed */ + if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS)) + break; + } + } +-EXPORT_SYMBOL(usleep_range); ++EXPORT_SYMBOL(usleep_range_state); +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index fa91f398f28b7..c42ff77eb6ccc 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -310,10 +310,20 @@ record_it: + local_irq_restore(flags); + } + +-static void blk_trace_free(struct blk_trace *bt) ++static void blk_trace_free(struct request_queue *q, struct blk_trace *bt) + { + relay_close(bt->rchan); +- debugfs_remove(bt->dir); ++ ++ /* ++ * If 'bt->dir' is not set, then both 'dropped' and 'msg' are created ++ * under 'q->debugfs_dir', thus lookup and remove them. ++ */ ++ if (!bt->dir) { ++ debugfs_remove(debugfs_lookup("dropped", q->debugfs_dir)); ++ debugfs_remove(debugfs_lookup("msg", q->debugfs_dir)); ++ } else { ++ debugfs_remove(bt->dir); ++ } + free_percpu(bt->sequence); + free_percpu(bt->msg_data); + kfree(bt); +@@ -335,10 +345,10 @@ static void put_probe_ref(void) + mutex_unlock(&blk_probe_mutex); + } + +-static void blk_trace_cleanup(struct blk_trace *bt) ++static void blk_trace_cleanup(struct request_queue *q, struct blk_trace *bt) + { + synchronize_rcu(); +- blk_trace_free(bt); ++ blk_trace_free(q, bt); + put_probe_ref(); + } + +@@ -352,7 +362,7 @@ static int __blk_trace_remove(struct request_queue *q) + return -EINVAL; + + if (bt->trace_state != Blktrace_running) +- blk_trace_cleanup(bt); ++ blk_trace_cleanup(q, bt); + + return 0; + } +@@ -572,7 +582,7 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, + ret = 0; + err: + if (ret) +- blk_trace_free(bt); ++ blk_trace_free(q, bt); + return ret; + } + +@@ -1615,7 +1625,7 @@ static int blk_trace_remove_queue(struct request_queue *q) + + put_probe_ref(); + synchronize_rcu(); +- blk_trace_free(bt); ++ blk_trace_free(q, bt); + return 0; + } + +@@ -1646,7 +1656,7 @@ static int blk_trace_setup_queue(struct request_queue *q, + return 0; + + free_bt: +- blk_trace_free(bt); ++ blk_trace_free(q, bt); + return ret; + } + +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index 8e2eb950aa829..5a18b861fcf75 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -1037,8 +1037,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) + return &bpf_ktime_get_ns_proto; + case BPF_FUNC_ktime_get_boot_ns: + return &bpf_ktime_get_boot_ns_proto; +- case BPF_FUNC_ktime_get_coarse_ns: +- return &bpf_ktime_get_coarse_ns_proto; + case BPF_FUNC_tail_call: + return &bpf_tail_call_proto; + case BPF_FUNC_get_current_pid_tgid: +@@ -1324,9 +1322,6 @@ static const struct bpf_func_proto bpf_perf_prog_read_value_proto = { + BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx, + void *, buf, u32, size, u64, flags) + { +-#ifndef CONFIG_X86 +- return -ENOENT; +-#else + static const u32 br_entry_size = sizeof(struct perf_branch_entry); + struct perf_branch_stack *br_stack = ctx->data->br_stack; + u32 to_copy; +@@ -1335,7 +1330,7 @@ BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx, + return -EINVAL; + + if (unlikely(!br_stack)) +- return -EINVAL; ++ return -ENOENT; + + if (flags & BPF_F_GET_BRANCH_RECORDS_SIZE) + return br_stack->nr * br_entry_size; +@@ -1347,7 +1342,6 @@ BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx, + memcpy(buf, br_stack->entries, to_copy); + + return to_copy; +-#endif + } + + static const struct bpf_func_proto bpf_read_branch_records_proto = { +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index feebf57c64588..c672040142e98 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -988,8 +988,9 @@ static __init void ftrace_profile_tracefs(struct dentry *d_tracer) + } + } + +- entry = tracefs_create_file("function_profile_enabled", 0644, +- d_tracer, NULL, &ftrace_profile_fops); ++ entry = tracefs_create_file("function_profile_enabled", ++ TRACE_MODE_WRITE, d_tracer, NULL, ++ &ftrace_profile_fops); + if (!entry) + pr_warn("Could not create tracefs 'function_profile_enabled' entry\n"); + } +@@ -6109,10 +6110,10 @@ void ftrace_create_filter_files(struct ftrace_ops *ops, + struct dentry *parent) + { + +- trace_create_file("set_ftrace_filter", 0644, parent, ++ trace_create_file("set_ftrace_filter", TRACE_MODE_WRITE, parent, + ops, &ftrace_filter_fops); + +- trace_create_file("set_ftrace_notrace", 0644, parent, ++ trace_create_file("set_ftrace_notrace", TRACE_MODE_WRITE, parent, + ops, &ftrace_notrace_fops); + } + +@@ -6139,19 +6140,19 @@ void ftrace_destroy_filter_files(struct ftrace_ops *ops) + static __init int ftrace_init_dyn_tracefs(struct dentry *d_tracer) + { + +- trace_create_file("available_filter_functions", 0444, ++ trace_create_file("available_filter_functions", TRACE_MODE_READ, + d_tracer, NULL, &ftrace_avail_fops); + +- trace_create_file("enabled_functions", 0444, ++ trace_create_file("enabled_functions", TRACE_MODE_READ, + d_tracer, NULL, &ftrace_enabled_fops); + + ftrace_create_filter_files(&global_ops, d_tracer); + + #ifdef CONFIG_FUNCTION_GRAPH_TRACER +- trace_create_file("set_graph_function", 0644, d_tracer, ++ trace_create_file("set_graph_function", TRACE_MODE_WRITE, d_tracer, + NULL, + &ftrace_graph_fops); +- trace_create_file("set_graph_notrace", 0644, d_tracer, ++ trace_create_file("set_graph_notrace", TRACE_MODE_WRITE, d_tracer, + NULL, + &ftrace_graph_notrace_fops); + #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +@@ -7494,10 +7495,10 @@ static const struct file_operations ftrace_no_pid_fops = { + + void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer) + { +- trace_create_file("set_ftrace_pid", 0644, d_tracer, ++ trace_create_file("set_ftrace_pid", TRACE_MODE_WRITE, d_tracer, + tr, &ftrace_pid_fops); +- trace_create_file("set_ftrace_notrace_pid", 0644, d_tracer, +- tr, &ftrace_no_pid_fops); ++ trace_create_file("set_ftrace_notrace_pid", TRACE_MODE_WRITE, ++ d_tracer, tr, &ftrace_no_pid_fops); + } + + void __init ftrace_init_tracefs_toplevel(struct trace_array *tr, +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index c5a3fbf19617e..46ae72095c1e2 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -5233,6 +5233,9 @@ void ring_buffer_reset(struct trace_buffer *buffer) + struct ring_buffer_per_cpu *cpu_buffer; + int cpu; + ++ /* prevent another thread from changing buffer sizes */ ++ mutex_lock(&buffer->mutex); ++ + for_each_buffer_cpu(buffer, cpu) { + cpu_buffer = buffer->buffers[cpu]; + +@@ -5251,6 +5254,8 @@ void ring_buffer_reset(struct trace_buffer *buffer) + atomic_dec(&cpu_buffer->record_disabled); + atomic_dec(&cpu_buffer->resize_disabled); + } ++ ++ mutex_unlock(&buffer->mutex); + } + EXPORT_SYMBOL_GPL(ring_buffer_reset); + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index bc677cd642240..86fb77c2ace5b 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -235,7 +235,7 @@ static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata; + static int __init set_trace_boot_options(char *str) + { + strlcpy(trace_boot_options_buf, str, MAX_TRACER_SIZE); +- return 0; ++ return 1; + } + __setup("trace_options=", set_trace_boot_options); + +@@ -246,12 +246,16 @@ static int __init set_trace_boot_clock(char *str) + { + strlcpy(trace_boot_clock_buf, str, MAX_TRACER_SIZE); + trace_boot_clock = trace_boot_clock_buf; +- return 0; ++ return 1; + } + __setup("trace_clock=", set_trace_boot_clock); + + static int __init set_tracepoint_printk(char *str) + { ++ /* Ignore the "tp_printk_stop_on_boot" param */ ++ if (*str == '_') ++ return 0; ++ + if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0)) + tracepoint_printk = 1; + return 1; +@@ -1714,7 +1718,8 @@ static void trace_create_maxlat_file(struct trace_array *tr, + { + INIT_WORK(&tr->fsnotify_work, latency_fsnotify_workfn); + init_irq_work(&tr->fsnotify_irqwork, latency_fsnotify_workfn_irq); +- tr->d_max_latency = trace_create_file("tracing_max_latency", 0644, ++ tr->d_max_latency = trace_create_file("tracing_max_latency", ++ TRACE_MODE_WRITE, + d_tracer, &tr->max_latency, + &tracing_max_lat_fops); + } +@@ -1748,8 +1753,8 @@ void latency_fsnotify(struct trace_array *tr) + || defined(CONFIG_OSNOISE_TRACER) + + #define trace_create_maxlat_file(tr, d_tracer) \ +- trace_create_file("tracing_max_latency", 0644, d_tracer, \ +- &tr->max_latency, &tracing_max_lat_fops) ++ trace_create_file("tracing_max_latency", TRACE_MODE_WRITE, \ ++ d_tracer, &tr->max_latency, &tracing_max_lat_fops) + + #else + #define trace_create_maxlat_file(tr, d_tracer) do { } while (0) +@@ -3230,7 +3235,7 @@ struct trace_buffer_struct { + char buffer[4][TRACE_BUF_SIZE]; + }; + +-static struct trace_buffer_struct *trace_percpu_buffer; ++static struct trace_buffer_struct __percpu *trace_percpu_buffer; + + /* + * This allows for lockless recording. If we're nested too deeply, then +@@ -3240,7 +3245,7 @@ static char *get_trace_buf(void) + { + struct trace_buffer_struct *buffer = this_cpu_ptr(trace_percpu_buffer); + +- if (!buffer || buffer->nesting >= 4) ++ if (!trace_percpu_buffer || buffer->nesting >= 4) + return NULL; + + buffer->nesting++; +@@ -3259,7 +3264,7 @@ static void put_trace_buf(void) + + static int alloc_percpu_trace_buffer(void) + { +- struct trace_buffer_struct *buffers; ++ struct trace_buffer_struct __percpu *buffers; + + if (trace_percpu_buffer) + return 0; +@@ -3835,6 +3840,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, + iter->fmt[i] = '\0'; + trace_seq_vprintf(&iter->seq, iter->fmt, ap); + ++ /* ++ * If iter->seq is full, the above call no longer guarantees ++ * that ap is in sync with fmt processing, and further calls ++ * to va_arg() can return wrong positional arguments. ++ * ++ * Ensure that ap is no longer used in this case. ++ */ ++ if (iter->seq.full) { ++ p = ""; ++ break; ++ } ++ + if (star) + len = va_arg(ap, int); + +@@ -6077,7 +6094,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start, + + static void trace_create_eval_file(struct dentry *d_tracer) + { +- trace_create_file("eval_map", 0444, d_tracer, ++ trace_create_file("eval_map", TRACE_MODE_READ, d_tracer, + NULL, &tracing_eval_map_fops); + } + +@@ -7736,7 +7753,8 @@ static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr) + err = kzalloc(sizeof(*err), GFP_KERNEL); + if (!err) + err = ERR_PTR(-ENOMEM); +- tr->n_err_log_entries++; ++ else ++ tr->n_err_log_entries++; + + return err; + } +@@ -8590,27 +8608,27 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu) + } + + /* per cpu trace_pipe */ +- trace_create_cpu_file("trace_pipe", 0444, d_cpu, ++ trace_create_cpu_file("trace_pipe", TRACE_MODE_READ, d_cpu, + tr, cpu, &tracing_pipe_fops); + + /* per cpu trace */ +- trace_create_cpu_file("trace", 0644, d_cpu, ++ trace_create_cpu_file("trace", TRACE_MODE_WRITE, d_cpu, + tr, cpu, &tracing_fops); + +- trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu, ++ trace_create_cpu_file("trace_pipe_raw", TRACE_MODE_READ, d_cpu, + tr, cpu, &tracing_buffers_fops); + +- trace_create_cpu_file("stats", 0444, d_cpu, ++ trace_create_cpu_file("stats", TRACE_MODE_READ, d_cpu, + tr, cpu, &tracing_stats_fops); + +- trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, ++ trace_create_cpu_file("buffer_size_kb", TRACE_MODE_READ, d_cpu, + tr, cpu, &tracing_entries_fops); + + #ifdef CONFIG_TRACER_SNAPSHOT +- trace_create_cpu_file("snapshot", 0644, d_cpu, ++ trace_create_cpu_file("snapshot", TRACE_MODE_WRITE, d_cpu, + tr, cpu, &snapshot_fops); + +- trace_create_cpu_file("snapshot_raw", 0444, d_cpu, ++ trace_create_cpu_file("snapshot_raw", TRACE_MODE_READ, d_cpu, + tr, cpu, &snapshot_raw_fops); + #endif + } +@@ -8816,8 +8834,8 @@ create_trace_option_file(struct trace_array *tr, + topt->opt = opt; + topt->tr = tr; + +- topt->entry = trace_create_file(opt->name, 0644, t_options, topt, +- &trace_options_fops); ++ topt->entry = trace_create_file(opt->name, TRACE_MODE_WRITE, ++ t_options, topt, &trace_options_fops); + + } + +@@ -8892,7 +8910,7 @@ create_trace_option_core_file(struct trace_array *tr, + if (!t_options) + return NULL; + +- return trace_create_file(option, 0644, t_options, ++ return trace_create_file(option, TRACE_MODE_WRITE, t_options, + (void *)&tr->trace_flags_index[index], + &trace_options_core_fops); + } +@@ -9417,28 +9435,28 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) + struct trace_event_file *file; + int cpu; + +- trace_create_file("available_tracers", 0444, d_tracer, ++ trace_create_file("available_tracers", TRACE_MODE_READ, d_tracer, + tr, &show_traces_fops); + +- trace_create_file("current_tracer", 0644, d_tracer, ++ trace_create_file("current_tracer", TRACE_MODE_WRITE, d_tracer, + tr, &set_tracer_fops); + +- trace_create_file("tracing_cpumask", 0644, d_tracer, ++ trace_create_file("tracing_cpumask", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_cpumask_fops); + +- trace_create_file("trace_options", 0644, d_tracer, ++ trace_create_file("trace_options", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_iter_fops); + +- trace_create_file("trace", 0644, d_tracer, ++ trace_create_file("trace", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_fops); + +- trace_create_file("trace_pipe", 0444, d_tracer, ++ trace_create_file("trace_pipe", TRACE_MODE_READ, d_tracer, + tr, &tracing_pipe_fops); + +- trace_create_file("buffer_size_kb", 0644, d_tracer, ++ trace_create_file("buffer_size_kb", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_entries_fops); + +- trace_create_file("buffer_total_size_kb", 0444, d_tracer, ++ trace_create_file("buffer_total_size_kb", TRACE_MODE_READ, d_tracer, + tr, &tracing_total_entries_fops); + + trace_create_file("free_buffer", 0200, d_tracer, +@@ -9449,25 +9467,25 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) + + file = __find_event_file(tr, "ftrace", "print"); + if (file && file->dir) +- trace_create_file("trigger", 0644, file->dir, file, +- &event_trigger_fops); ++ trace_create_file("trigger", TRACE_MODE_WRITE, file->dir, ++ file, &event_trigger_fops); + tr->trace_marker_file = file; + + trace_create_file("trace_marker_raw", 0220, d_tracer, + tr, &tracing_mark_raw_fops); + +- trace_create_file("trace_clock", 0644, d_tracer, tr, ++ trace_create_file("trace_clock", TRACE_MODE_WRITE, d_tracer, tr, + &trace_clock_fops); + +- trace_create_file("tracing_on", 0644, d_tracer, ++ trace_create_file("tracing_on", TRACE_MODE_WRITE, d_tracer, + tr, &rb_simple_fops); + +- trace_create_file("timestamp_mode", 0444, d_tracer, tr, ++ trace_create_file("timestamp_mode", TRACE_MODE_READ, d_tracer, tr, + &trace_time_stamp_mode_fops); + + tr->buffer_percent = 50; + +- trace_create_file("buffer_percent", 0444, d_tracer, ++ trace_create_file("buffer_percent", TRACE_MODE_READ, d_tracer, + tr, &buffer_percent_fops); + + create_trace_options_dir(tr); +@@ -9478,11 +9496,11 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) + MEM_FAIL(1, "Could not allocate function filter files"); + + #ifdef CONFIG_TRACER_SNAPSHOT +- trace_create_file("snapshot", 0644, d_tracer, ++ trace_create_file("snapshot", TRACE_MODE_WRITE, d_tracer, + tr, &snapshot_fops); + #endif + +- trace_create_file("error_log", 0644, d_tracer, ++ trace_create_file("error_log", TRACE_MODE_WRITE, d_tracer, + tr, &tracing_err_log_fops); + + for_each_tracing_cpu(cpu) +@@ -9675,19 +9693,19 @@ static __init int tracer_init_tracefs(void) + init_tracer_tracefs(&global_trace, NULL); + ftrace_init_tracefs_toplevel(&global_trace, NULL); + +- trace_create_file("tracing_thresh", 0644, NULL, ++ trace_create_file("tracing_thresh", TRACE_MODE_WRITE, NULL, + &global_trace, &tracing_thresh_fops); + +- trace_create_file("README", 0444, NULL, ++ trace_create_file("README", TRACE_MODE_READ, NULL, + NULL, &tracing_readme_fops); + +- trace_create_file("saved_cmdlines", 0444, NULL, ++ trace_create_file("saved_cmdlines", TRACE_MODE_READ, NULL, + NULL, &tracing_saved_cmdlines_fops); + +- trace_create_file("saved_cmdlines_size", 0644, NULL, ++ trace_create_file("saved_cmdlines_size", TRACE_MODE_WRITE, NULL, + NULL, &tracing_saved_cmdlines_size_fops); + +- trace_create_file("saved_tgids", 0444, NULL, ++ trace_create_file("saved_tgids", TRACE_MODE_READ, NULL, + NULL, &tracing_saved_tgids_fops); + + trace_eval_init(); +@@ -9699,7 +9717,7 @@ static __init int tracer_init_tracefs(void) + #endif + + #ifdef CONFIG_DYNAMIC_FTRACE +- trace_create_file("dyn_ftrace_total_info", 0444, NULL, ++ trace_create_file("dyn_ftrace_total_info", TRACE_MODE_READ, NULL, + NULL, &tracing_dyn_info_fops); + #endif + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index b7c0f8e160fb4..421374c304fc0 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -27,6 +27,9 @@ + #include <asm/syscall.h> /* some archs define it here */ + #endif + ++#define TRACE_MODE_WRITE 0640 ++#define TRACE_MODE_READ 0440 ++ + enum trace_type { + __TRACE_FIRST_TYPE = 0, + +@@ -1357,14 +1360,26 @@ __event_trigger_test_discard(struct trace_event_file *file, + if (eflags & EVENT_FILE_FL_TRIGGER_COND) + *tt = event_triggers_call(file, buffer, entry, event); + +- if (test_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &file->flags) || +- (unlikely(file->flags & EVENT_FILE_FL_FILTERED) && +- !filter_match_preds(file->filter, entry))) { +- __trace_event_discard_commit(buffer, event); +- return true; +- } ++ if (likely(!(file->flags & (EVENT_FILE_FL_SOFT_DISABLED | ++ EVENT_FILE_FL_FILTERED | ++ EVENT_FILE_FL_PID_FILTER)))) ++ return false; ++ ++ if (file->flags & EVENT_FILE_FL_SOFT_DISABLED) ++ goto discard; ++ ++ if (file->flags & EVENT_FILE_FL_FILTERED && ++ !filter_match_preds(file->filter, entry)) ++ goto discard; ++ ++ if ((file->flags & EVENT_FILE_FL_PID_FILTER) && ++ trace_event_ignore_this_pid(file)) ++ goto discard; + + return false; ++ discard: ++ __trace_event_discard_commit(buffer, event); ++ return true; + } + + /** +diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c +index 8d252f63cd784..0580287d7a0d1 100644 +--- a/kernel/trace/trace_boot.c ++++ b/kernel/trace/trace_boot.c +@@ -430,6 +430,8 @@ trace_boot_init_histograms(struct trace_event_file *file, + /* All digit started node should be instances. */ + if (trace_boot_compose_hist_cmd(node, buf, size) == 0) { + tmp = kstrdup(buf, GFP_KERNEL); ++ if (!tmp) ++ return; + if (trigger_process_regex(file, buf) < 0) + pr_err("Failed to apply hist trigger: %s\n", tmp); + kfree(tmp); +@@ -439,6 +441,8 @@ trace_boot_init_histograms(struct trace_event_file *file, + if (xbc_node_find_subkey(hnode, "keys")) { + if (trace_boot_compose_hist_cmd(hnode, buf, size) == 0) { + tmp = kstrdup(buf, GFP_KERNEL); ++ if (!tmp) ++ return; + if (trigger_process_regex(file, buf) < 0) + pr_err("Failed to apply hist trigger: %s\n", tmp); + kfree(tmp); +diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c +index 1110112e55bd7..e34e8182ee4b5 100644 +--- a/kernel/trace/trace_dynevent.c ++++ b/kernel/trace/trace_dynevent.c +@@ -262,7 +262,7 @@ static __init int init_dynamic_event(void) + if (ret) + return 0; + +- entry = tracefs_create_file("dynamic_events", 0644, NULL, ++ entry = tracefs_create_file("dynamic_events", TRACE_MODE_WRITE, NULL, + NULL, &dynamic_events_ops); + + /* Event list interface */ +diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c +index 6aed10e2f7ce0..fba8cb77a73af 100644 +--- a/kernel/trace/trace_event_perf.c ++++ b/kernel/trace/trace_event_perf.c +@@ -441,13 +441,13 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip, + if (!rcu_is_watching()) + return; + +- if ((unsigned long)ops->private != smp_processor_id()) +- return; +- + bit = ftrace_test_recursion_trylock(ip, parent_ip); + if (bit < 0) + return; + ++ if ((unsigned long)ops->private != smp_processor_id()) ++ goto out; ++ + event = container_of(ops, struct perf_event, ftrace_ops); + + /* +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index 830b3b9940f4c..44d031ffe5112 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -2312,7 +2312,8 @@ event_subsystem_dir(struct trace_array *tr, const char *name, + /* the ftrace system is special, do not create enable or filter files */ + if (strcmp(name, "ftrace") != 0) { + +- entry = tracefs_create_file("filter", 0644, dir->entry, dir, ++ entry = tracefs_create_file("filter", TRACE_MODE_WRITE, ++ dir->entry, dir, + &ftrace_subsystem_filter_fops); + if (!entry) { + kfree(system->filter); +@@ -2320,7 +2321,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name, + pr_warn("Could not create tracefs '%s/filter' entry\n", name); + } + +- trace_create_file("enable", 0644, dir->entry, dir, ++ trace_create_file("enable", TRACE_MODE_WRITE, dir->entry, dir, + &ftrace_system_enable_fops); + } + +@@ -2402,12 +2403,12 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) + } + + if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) +- trace_create_file("enable", 0644, file->dir, file, ++ trace_create_file("enable", TRACE_MODE_WRITE, file->dir, file, + &ftrace_enable_fops); + + #ifdef CONFIG_PERF_EVENTS + if (call->event.type && call->class->reg) +- trace_create_file("id", 0444, file->dir, ++ trace_create_file("id", TRACE_MODE_READ, file->dir, + (void *)(long)call->event.type, + &ftrace_event_id_fops); + #endif +@@ -2423,22 +2424,22 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) + * triggers or filters. + */ + if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) { +- trace_create_file("filter", 0644, file->dir, file, +- &ftrace_event_filter_fops); ++ trace_create_file("filter", TRACE_MODE_WRITE, file->dir, ++ file, &ftrace_event_filter_fops); + +- trace_create_file("trigger", 0644, file->dir, file, +- &event_trigger_fops); ++ trace_create_file("trigger", TRACE_MODE_WRITE, file->dir, ++ file, &event_trigger_fops); + } + + #ifdef CONFIG_HIST_TRIGGERS +- trace_create_file("hist", 0444, file->dir, file, ++ trace_create_file("hist", TRACE_MODE_READ, file->dir, file, + &event_hist_fops); + #endif + #ifdef CONFIG_HIST_TRIGGERS_DEBUG +- trace_create_file("hist_debug", 0444, file->dir, file, ++ trace_create_file("hist_debug", TRACE_MODE_READ, file->dir, file, + &event_hist_debug_fops); + #endif +- trace_create_file("format", 0444, file->dir, call, ++ trace_create_file("format", TRACE_MODE_READ, file->dir, call, + &ftrace_event_format_fops); + + #ifdef CONFIG_TRACE_EVENT_INJECT +@@ -2677,12 +2678,22 @@ static struct trace_event_file * + trace_create_new_event(struct trace_event_call *call, + struct trace_array *tr) + { ++ struct trace_pid_list *no_pid_list; ++ struct trace_pid_list *pid_list; + struct trace_event_file *file; + + file = kmem_cache_alloc(file_cachep, GFP_TRACE); + if (!file) + return NULL; + ++ pid_list = rcu_dereference_protected(tr->filtered_pids, ++ lockdep_is_held(&event_mutex)); ++ no_pid_list = rcu_dereference_protected(tr->filtered_no_pids, ++ lockdep_is_held(&event_mutex)); ++ ++ if (pid_list || no_pid_list) ++ file->flags |= EVENT_FILE_FL_PID_FILTER; ++ + file->event_call = call; + file->tr = tr; + atomic_set(&file->sm_ref, 0); +@@ -3433,7 +3444,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) + struct dentry *d_events; + struct dentry *entry; + +- entry = tracefs_create_file("set_event", 0644, parent, ++ entry = tracefs_create_file("set_event", TRACE_MODE_WRITE, parent, + tr, &ftrace_set_event_fops); + if (!entry) { + pr_warn("Could not create tracefs 'set_event' entry\n"); +@@ -3446,7 +3457,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) + return -ENOMEM; + } + +- entry = trace_create_file("enable", 0644, d_events, ++ entry = trace_create_file("enable", TRACE_MODE_WRITE, d_events, + tr, &ftrace_tr_enable_fops); + if (!entry) { + pr_warn("Could not create tracefs 'enable' entry\n"); +@@ -3455,24 +3466,25 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) + + /* There are not as crucial, just warn if they are not created */ + +- entry = tracefs_create_file("set_event_pid", 0644, parent, ++ entry = tracefs_create_file("set_event_pid", TRACE_MODE_WRITE, parent, + tr, &ftrace_set_event_pid_fops); + if (!entry) + pr_warn("Could not create tracefs 'set_event_pid' entry\n"); + +- entry = tracefs_create_file("set_event_notrace_pid", 0644, parent, +- tr, &ftrace_set_event_notrace_pid_fops); ++ entry = tracefs_create_file("set_event_notrace_pid", ++ TRACE_MODE_WRITE, parent, tr, ++ &ftrace_set_event_notrace_pid_fops); + if (!entry) + pr_warn("Could not create tracefs 'set_event_notrace_pid' entry\n"); + + /* ring buffer internal formats */ +- entry = trace_create_file("header_page", 0444, d_events, ++ entry = trace_create_file("header_page", TRACE_MODE_READ, d_events, + ring_buffer_print_page_header, + &ftrace_show_header_fops); + if (!entry) + pr_warn("Could not create tracefs 'header_page' entry\n"); + +- entry = trace_create_file("header_event", 0444, d_events, ++ entry = trace_create_file("header_event", TRACE_MODE_READ, d_events, + ring_buffer_print_entry_header, + &ftrace_show_header_fops); + if (!entry) +@@ -3689,8 +3701,8 @@ __init int event_trace_init(void) + if (!tr) + return -ENODEV; + +- entry = tracefs_create_file("available_events", 0444, NULL, +- tr, &ftrace_avail_fops); ++ entry = tracefs_create_file("available_events", TRACE_MODE_READ, ++ NULL, tr, &ftrace_avail_fops); + if (!entry) + pr_warn("Could not create tracefs 'available_events' entry\n"); + +diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c +index c9124038b140f..06d6318ee5377 100644 +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -5,6 +5,7 @@ + * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> + */ + ++#include <linux/uaccess.h> + #include <linux/module.h> + #include <linux/ctype.h> + #include <linux/mutex.h> +@@ -654,6 +655,52 @@ DEFINE_EQUALITY_PRED(32); + DEFINE_EQUALITY_PRED(16); + DEFINE_EQUALITY_PRED(8); + ++/* user space strings temp buffer */ ++#define USTRING_BUF_SIZE 1024 ++ ++struct ustring_buffer { ++ char buffer[USTRING_BUF_SIZE]; ++}; ++ ++static __percpu struct ustring_buffer *ustring_per_cpu; ++ ++static __always_inline char *test_string(char *str) ++{ ++ struct ustring_buffer *ubuf; ++ char *kstr; ++ ++ if (!ustring_per_cpu) ++ return NULL; ++ ++ ubuf = this_cpu_ptr(ustring_per_cpu); ++ kstr = ubuf->buffer; ++ ++ /* For safety, do not trust the string pointer */ ++ if (!strncpy_from_kernel_nofault(kstr, str, USTRING_BUF_SIZE)) ++ return NULL; ++ return kstr; ++} ++ ++static __always_inline char *test_ustring(char *str) ++{ ++ struct ustring_buffer *ubuf; ++ char __user *ustr; ++ char *kstr; ++ ++ if (!ustring_per_cpu) ++ return NULL; ++ ++ ubuf = this_cpu_ptr(ustring_per_cpu); ++ kstr = ubuf->buffer; ++ ++ /* user space address? */ ++ ustr = (char __user *)str; ++ if (!strncpy_from_user_nofault(kstr, ustr, USTRING_BUF_SIZE)) ++ return NULL; ++ ++ return kstr; ++} ++ + /* Filter predicate for fixed sized arrays of characters */ + static int filter_pred_string(struct filter_pred *pred, void *event) + { +@@ -667,19 +714,43 @@ static int filter_pred_string(struct filter_pred *pred, void *event) + return match; + } + +-/* Filter predicate for char * pointers */ +-static int filter_pred_pchar(struct filter_pred *pred, void *event) ++static __always_inline int filter_pchar(struct filter_pred *pred, char *str) + { +- char **addr = (char **)(event + pred->offset); + int cmp, match; +- int len = strlen(*addr) + 1; /* including tailing '\0' */ ++ int len; + +- cmp = pred->regex.match(*addr, &pred->regex, len); ++ len = strlen(str) + 1; /* including tailing '\0' */ ++ cmp = pred->regex.match(str, &pred->regex, len); + + match = cmp ^ pred->not; + + return match; + } ++/* Filter predicate for char * pointers */ ++static int filter_pred_pchar(struct filter_pred *pred, void *event) ++{ ++ char **addr = (char **)(event + pred->offset); ++ char *str; ++ ++ str = test_string(*addr); ++ if (!str) ++ return 0; ++ ++ return filter_pchar(pred, str); ++} ++ ++/* Filter predicate for char * pointers in user space*/ ++static int filter_pred_pchar_user(struct filter_pred *pred, void *event) ++{ ++ char **addr = (char **)(event + pred->offset); ++ char *str; ++ ++ str = test_ustring(*addr); ++ if (!str) ++ return 0; ++ ++ return filter_pchar(pred, str); ++} + + /* + * Filter predicate for dynamic sized arrays of characters. +@@ -1158,6 +1229,7 @@ static int parse_pred(const char *str, void *data, + struct filter_pred *pred = NULL; + char num_buf[24]; /* Big enough to hold an address */ + char *field_name; ++ bool ustring = false; + char q; + u64 val; + int len; +@@ -1192,6 +1264,12 @@ static int parse_pred(const char *str, void *data, + return -EINVAL; + } + ++ /* See if the field is a user space string */ ++ if ((len = str_has_prefix(str + i, ".ustring"))) { ++ ustring = true; ++ i += len; ++ } ++ + while (isspace(str[i])) + i++; + +@@ -1320,8 +1398,20 @@ static int parse_pred(const char *str, void *data, + + } else if (field->filter_type == FILTER_DYN_STRING) + pred->fn = filter_pred_strloc; +- else +- pred->fn = filter_pred_pchar; ++ else { ++ ++ if (!ustring_per_cpu) { ++ /* Once allocated, keep it around for good */ ++ ustring_per_cpu = alloc_percpu(struct ustring_buffer); ++ if (!ustring_per_cpu) ++ goto err_mem; ++ } ++ ++ if (ustring) ++ pred->fn = filter_pred_pchar_user; ++ else ++ pred->fn = filter_pred_pchar; ++ } + /* go past the last quote */ + i++; + +@@ -1387,6 +1477,9 @@ static int parse_pred(const char *str, void *data, + err_free: + kfree(pred); + return -EINVAL; ++err_mem: ++ kfree(pred); ++ return -ENOMEM; + } + + enum { +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index f01e442716e2f..ea168d42c8a2a 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -1733,9 +1733,10 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data, + if (!hist_field->type) + goto free; + +- if (field->filter_type == FILTER_STATIC_STRING) ++ if (field->filter_type == FILTER_STATIC_STRING) { + hist_field->fn = hist_field_string; +- else if (field->filter_type == FILTER_DYN_STRING) ++ hist_field->size = field->size; ++ } else if (field->filter_type == FILTER_DYN_STRING) + hist_field->fn = hist_field_dynstring; + else + hist_field->fn = hist_field_pstring; +@@ -2048,9 +2049,9 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file, + /* + * For backward compatibility, if field_name + * was "cpu", then we treat this the same as +- * common_cpu. ++ * common_cpu. This also works for "CPU". + */ +- if (strcmp(field_name, "cpu") == 0) { ++ if (field && field->filter_type == FILTER_CPU) { + *flags |= HIST_FIELD_FL_CPU; + } else { + hist_err(tr, HIST_ERR_FIELD_NOT_FOUND, +@@ -2219,6 +2220,8 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data, + (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS); + expr->fn = hist_field_unary_minus; + expr->operands[0] = operand1; ++ expr->size = operand1->size; ++ expr->is_signed = operand1->is_signed; + expr->operator = FIELD_OP_UNARY_MINUS; + expr->name = expr_str(expr, 0); + expr->type = kstrdup_const(operand1->type, GFP_KERNEL); +@@ -2358,6 +2361,7 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data, + + /* The operand sizes should be the same, so just pick one */ + expr->size = operand1->size; ++ expr->is_signed = operand1->is_signed; + + expr->operator = field_op; + expr->name = expr_str(expr, 0); +@@ -2690,8 +2694,10 @@ static inline void __update_field_vars(struct tracing_map_elt *elt, + if (val->flags & HIST_FIELD_FL_STRING) { + char *str = elt_data->field_var_str[j++]; + char *val_str = (char *)(uintptr_t)var_val; ++ unsigned int size; + +- strscpy(str, val_str, STR_VAR_LEN_MAX); ++ size = min(val->size, STR_VAR_LEN_MAX); ++ strscpy(str, val_str, size); + var_val = (u64)(uintptr_t)str; + } + tracing_map_set_var(elt, var_idx, var_val); +@@ -3416,7 +3422,7 @@ static int check_synth_field(struct synth_event *event, + + if (strcmp(field->type, hist_field->type) != 0) { + if (field->size != hist_field->size || +- field->is_signed != hist_field->is_signed) ++ (!field->is_string && field->is_signed != hist_field->is_signed)) + return -EINVAL; + } + +@@ -3578,6 +3584,7 @@ static int trace_action_create(struct hist_trigger_data *hist_data, + + var_ref_idx = find_var_ref_idx(hist_data, var_ref); + if (WARN_ON(var_ref_idx < 0)) { ++ kfree(p); + ret = var_ref_idx; + goto err; + } +@@ -4471,7 +4478,7 @@ static int create_tracing_map_fields(struct hist_trigger_data *hist_data) + + if (hist_field->flags & HIST_FIELD_FL_STACKTRACE) + cmp_fn = tracing_map_cmp_none; +- else if (!field) ++ else if (!field || hist_field->flags & HIST_FIELD_FL_CPU) + cmp_fn = tracing_map_cmp_num(hist_field->size, + hist_field->is_signed); + else if (is_string_field(field)) +@@ -4578,6 +4585,7 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, + if (hist_field->flags & HIST_FIELD_FL_STRING) { + unsigned int str_start, var_str_idx, idx; + char *str, *val_str; ++ unsigned int size; + + str_start = hist_data->n_field_var_str + + hist_data->n_save_var_str; +@@ -4586,7 +4594,9 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, + + str = elt_data->field_var_str[idx]; + val_str = (char *)(uintptr_t)hist_val; +- strscpy(str, val_str, STR_VAR_LEN_MAX); ++ ++ size = min(hist_field->size, STR_VAR_LEN_MAX); ++ strscpy(str, val_str, size); + + hist_val = (u64)(uintptr_t)str; + } +diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c +index d54094b7a9d75..8c26092db8dee 100644 +--- a/kernel/trace/trace_events_synth.c ++++ b/kernel/trace/trace_events_synth.c +@@ -2053,6 +2053,13 @@ static int create_synth_event(const char *raw_command) + + last_cmd_set(raw_command); + ++ name = raw_command; ++ ++ /* Don't try to process if not our system */ ++ if (name[0] != 's' || name[1] != ':') ++ return -ECANCELED; ++ name += 2; ++ + p = strpbrk(raw_command, " \t"); + if (!p) { + synth_err(SYNTH_ERR_INVALID_CMD, 0); +@@ -2061,12 +2068,6 @@ static int create_synth_event(const char *raw_command) + + fields = skip_spaces(p); + +- name = raw_command; +- +- if (name[0] != 's' || name[1] != ':') +- return -ECANCELED; +- name += 2; +- + /* This interface accepts group name prefix */ + if (strchr(name, '/')) { + len = str_has_prefix(name, SYNTH_SYSTEM "/"); +@@ -2227,8 +2228,8 @@ static __init int trace_events_synth_init(void) + if (err) + goto err; + +- entry = tracefs_create_file("synthetic_events", 0644, NULL, +- NULL, &synth_events_fops); ++ entry = tracefs_create_file("synthetic_events", TRACE_MODE_WRITE, ++ NULL, NULL, &synth_events_fops); + if (!entry) { + err = -ENODEV; + goto err; +diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c +index 3d5c07239a2a8..67c7979c40c0b 100644 +--- a/kernel/trace/trace_events_trigger.c ++++ b/kernel/trace/trace_events_trigger.c +@@ -955,6 +955,16 @@ traceon_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) + { ++ struct trace_event_file *file = data->private_data; ++ ++ if (file) { ++ if (tracer_tracing_is_on(file->tr)) ++ return; ++ ++ tracer_tracing_on(file->tr); ++ return; ++ } ++ + if (tracing_is_on()) + return; + +@@ -966,8 +976,15 @@ traceon_count_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) + { +- if (tracing_is_on()) +- return; ++ struct trace_event_file *file = data->private_data; ++ ++ if (file) { ++ if (tracer_tracing_is_on(file->tr)) ++ return; ++ } else { ++ if (tracing_is_on()) ++ return; ++ } + + if (!data->count) + return; +@@ -975,7 +992,10 @@ traceon_count_trigger(struct event_trigger_data *data, + if (data->count != -1) + (data->count)--; + +- tracing_on(); ++ if (file) ++ tracer_tracing_on(file->tr); ++ else ++ tracing_on(); + } + + static void +@@ -983,6 +1003,16 @@ traceoff_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) + { ++ struct trace_event_file *file = data->private_data; ++ ++ if (file) { ++ if (!tracer_tracing_is_on(file->tr)) ++ return; ++ ++ tracer_tracing_off(file->tr); ++ return; ++ } ++ + if (!tracing_is_on()) + return; + +@@ -994,8 +1024,15 @@ traceoff_count_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) + { +- if (!tracing_is_on()) +- return; ++ struct trace_event_file *file = data->private_data; ++ ++ if (file) { ++ if (!tracer_tracing_is_on(file->tr)) ++ return; ++ } else { ++ if (!tracing_is_on()) ++ return; ++ } + + if (!data->count) + return; +@@ -1003,7 +1040,10 @@ traceoff_count_trigger(struct event_trigger_data *data, + if (data->count != -1) + (data->count)--; + +- tracing_off(); ++ if (file) ++ tracer_tracing_off(file->tr); ++ else ++ tracing_off(); + } + + static int +@@ -1200,7 +1240,12 @@ stacktrace_trigger(struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) + { +- trace_dump_stack(STACK_SKIP); ++ struct trace_event_file *file = data->private_data; ++ ++ if (file) ++ __trace_stack(file->tr, tracing_gen_ctx(), STACK_SKIP); ++ else ++ trace_dump_stack(STACK_SKIP); + } + + static void +diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c +index 0de6837722da5..6b5ff3ba4251f 100644 +--- a/kernel/trace/trace_functions_graph.c ++++ b/kernel/trace/trace_functions_graph.c +@@ -1340,7 +1340,7 @@ static __init int init_graph_tracefs(void) + if (ret) + return 0; + +- trace_create_file("max_graph_depth", 0644, NULL, ++ trace_create_file("max_graph_depth", TRACE_MODE_WRITE, NULL, + NULL, &graph_depth_fops); + + return 0; +diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c +index 1b83d75eb103b..d0a730d99a331 100644 +--- a/kernel/trace/trace_hwlat.c ++++ b/kernel/trace/trace_hwlat.c +@@ -782,21 +782,21 @@ static int init_tracefs(void) + if (!top_dir) + return -ENOMEM; + +- hwlat_sample_window = tracefs_create_file("window", 0640, ++ hwlat_sample_window = tracefs_create_file("window", TRACE_MODE_WRITE, + top_dir, + &hwlat_window, + &trace_min_max_fops); + if (!hwlat_sample_window) + goto err; + +- hwlat_sample_width = tracefs_create_file("width", 0644, ++ hwlat_sample_width = tracefs_create_file("width", TRACE_MODE_WRITE, + top_dir, + &hwlat_width, + &trace_min_max_fops); + if (!hwlat_sample_width) + goto err; + +- hwlat_thread_mode = trace_create_file("mode", 0644, ++ hwlat_thread_mode = trace_create_file("mode", TRACE_MODE_WRITE, + top_dir, + NULL, + &thread_mode_fops); +diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c +index 3a64ba4bbad6f..39ee60725519b 100644 +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -31,7 +31,7 @@ static int __init set_kprobe_boot_events(char *str) + strlcpy(kprobe_boot_events_buf, str, COMMAND_LINE_SIZE); + disable_tracing_selftest("running kprobe events"); + +- return 0; ++ return 1; + } + __setup("kprobe_event=", set_kprobe_boot_events); + +@@ -1175,15 +1175,18 @@ static int probes_profile_seq_show(struct seq_file *m, void *v) + { + struct dyn_event *ev = v; + struct trace_kprobe *tk; ++ unsigned long nmissed; + + if (!is_trace_kprobe(ev)) + return 0; + + tk = to_trace_kprobe(ev); ++ nmissed = trace_kprobe_is_return(tk) ? ++ tk->rp.kp.nmissed + tk->rp.nmissed : tk->rp.kp.nmissed; + seq_printf(m, " %-44s %15lu %15lu\n", + trace_probe_name(&tk->tp), + trace_kprobe_nhit(tk), +- tk->rp.kp.nmissed); ++ nmissed); + + return 0; + } +@@ -1925,16 +1928,16 @@ static __init int init_kprobe_trace(void) + if (ret) + return 0; + +- entry = tracefs_create_file("kprobe_events", 0644, NULL, +- NULL, &kprobe_events_ops); ++ entry = tracefs_create_file("kprobe_events", TRACE_MODE_WRITE, ++ NULL, NULL, &kprobe_events_ops); + + /* Event list interface */ + if (!entry) + pr_warn("Could not create tracefs 'kprobe_events' entry\n"); + + /* Profile interface */ +- entry = tracefs_create_file("kprobe_profile", 0444, NULL, +- NULL, &kprobe_profile_ops); ++ entry = tracefs_create_file("kprobe_profile", TRACE_MODE_READ, ++ NULL, NULL, &kprobe_profile_ops); + + if (!entry) + pr_warn("Could not create tracefs 'kprobe_profile' entry\n"); +diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c +index ce053619f289e..65a518649997b 100644 +--- a/kernel/trace/trace_osnoise.c ++++ b/kernel/trace/trace_osnoise.c +@@ -1856,38 +1856,38 @@ static int init_tracefs(void) + if (!top_dir) + return 0; + +- tmp = tracefs_create_file("period_us", 0640, top_dir, ++ tmp = tracefs_create_file("period_us", TRACE_MODE_WRITE, top_dir, + &osnoise_period, &trace_min_max_fops); + if (!tmp) + goto err; + +- tmp = tracefs_create_file("runtime_us", 0644, top_dir, ++ tmp = tracefs_create_file("runtime_us", TRACE_MODE_WRITE, top_dir, + &osnoise_runtime, &trace_min_max_fops); + if (!tmp) + goto err; + +- tmp = tracefs_create_file("stop_tracing_us", 0640, top_dir, ++ tmp = tracefs_create_file("stop_tracing_us", TRACE_MODE_WRITE, top_dir, + &osnoise_stop_tracing_in, &trace_min_max_fops); + if (!tmp) + goto err; + +- tmp = tracefs_create_file("stop_tracing_total_us", 0640, top_dir, ++ tmp = tracefs_create_file("stop_tracing_total_us", TRACE_MODE_WRITE, top_dir, + &osnoise_stop_tracing_total, &trace_min_max_fops); + if (!tmp) + goto err; + +- tmp = trace_create_file("cpus", 0644, top_dir, NULL, &cpus_fops); ++ tmp = trace_create_file("cpus", TRACE_MODE_WRITE, top_dir, NULL, &cpus_fops); + if (!tmp) + goto err; + #ifdef CONFIG_TIMERLAT_TRACER + #ifdef CONFIG_STACKTRACE +- tmp = tracefs_create_file("print_stack", 0640, top_dir, ++ tmp = tracefs_create_file("print_stack", TRACE_MODE_WRITE, top_dir, + &osnoise_print_stack, &trace_min_max_fops); + if (!tmp) + goto err; + #endif + +- tmp = tracefs_create_file("timerlat_period_us", 0640, top_dir, ++ tmp = tracefs_create_file("timerlat_period_us", TRACE_MODE_WRITE, top_dir, + &timerlat_period, &trace_min_max_fops); + if (!tmp) + goto err; +@@ -1932,6 +1932,13 @@ out_unhook_irq: + return -EINVAL; + } + ++static void osnoise_unhook_events(void) ++{ ++ unhook_thread_events(); ++ unhook_softirq_events(); ++ unhook_irq_events(); ++} ++ + static int __osnoise_tracer_start(struct trace_array *tr) + { + int retval; +@@ -1949,7 +1956,14 @@ static int __osnoise_tracer_start(struct trace_array *tr) + + retval = start_per_cpu_kthreads(tr); + if (retval) { +- unhook_irq_events(); ++ trace_osnoise_callback_enabled = false; ++ /* ++ * Make sure that ftrace_nmi_enter/exit() see ++ * trace_osnoise_callback_enabled as false before continuing. ++ */ ++ barrier(); ++ ++ osnoise_unhook_events(); + return retval; + } + +@@ -1981,9 +1995,7 @@ static void osnoise_tracer_stop(struct trace_array *tr) + + stop_per_cpu_kthreads(); + +- unhook_irq_events(); +- unhook_softirq_events(); +- unhook_thread_events(); ++ osnoise_unhook_events(); + + osnoise_busy = false; + } +diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c +index 4b320fe7df704..29f6e95439b67 100644 +--- a/kernel/trace/trace_printk.c ++++ b/kernel/trace/trace_printk.c +@@ -384,7 +384,7 @@ static __init int init_trace_printk_function_export(void) + if (ret) + return 0; + +- trace_create_file("printk_formats", 0444, NULL, ++ trace_create_file("printk_formats", TRACE_MODE_READ, NULL, + NULL, &ftrace_formats_fops); + + return 0; +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index 3ed2a3f372972..bb4605b60de79 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -356,6 +356,8 @@ static int __parse_imm_string(char *str, char **pbuf, int offs) + return -EINVAL; + } + *pbuf = kstrndup(str, len - 1, GFP_KERNEL); ++ if (!*pbuf) ++ return -ENOMEM; + return 0; + } + +diff --git a/kernel/trace/trace_recursion_record.c b/kernel/trace/trace_recursion_record.c +index b2edac1fe156e..4d4b78c8ca257 100644 +--- a/kernel/trace/trace_recursion_record.c ++++ b/kernel/trace/trace_recursion_record.c +@@ -226,8 +226,8 @@ __init static int create_recursed_functions(void) + { + struct dentry *dentry; + +- dentry = trace_create_file("recursed_functions", 0644, NULL, NULL, +- &recursed_functions_fops); ++ dentry = trace_create_file("recursed_functions", TRACE_MODE_WRITE, ++ NULL, NULL, &recursed_functions_fops); + if (!dentry) + pr_warn("WARNING: Failed to create recursed_functions\n"); + return 0; +diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c +index 63c2850420516..5a48dba912eae 100644 +--- a/kernel/trace/trace_stack.c ++++ b/kernel/trace/trace_stack.c +@@ -559,14 +559,14 @@ static __init int stack_trace_init(void) + if (ret) + return 0; + +- trace_create_file("stack_max_size", 0644, NULL, ++ trace_create_file("stack_max_size", TRACE_MODE_WRITE, NULL, + &stack_trace_max_size, &stack_max_size_fops); + +- trace_create_file("stack_trace", 0444, NULL, ++ trace_create_file("stack_trace", TRACE_MODE_READ, NULL, + NULL, &stack_trace_fops); + + #ifdef CONFIG_DYNAMIC_FTRACE +- trace_create_file("stack_trace_filter", 0644, NULL, ++ trace_create_file("stack_trace_filter", TRACE_MODE_WRITE, NULL, + &trace_ops, &stack_trace_filter_fops); + #endif + +diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c +index 8d141c3825a94..bb247beec4470 100644 +--- a/kernel/trace/trace_stat.c ++++ b/kernel/trace/trace_stat.c +@@ -297,9 +297,9 @@ static int init_stat_file(struct stat_session *session) + if (!stat_dir && (ret = tracing_stat_init())) + return ret; + +- session->file = tracefs_create_file(session->ts->name, 0644, +- stat_dir, +- session, &tracing_stat_fops); ++ session->file = tracefs_create_file(session->ts->name, TRACE_MODE_WRITE, ++ stat_dir, session, ++ &tracing_stat_fops); + if (!session->file) + return -ENOMEM; + return 0; +diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c +index 8bfcd3b094226..f755bde42fd07 100644 +--- a/kernel/trace/trace_syscalls.c ++++ b/kernel/trace/trace_syscalls.c +@@ -323,8 +323,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) + + trace_ctx = tracing_gen_ctx(); + +- buffer = tr->array_buffer.buffer; +- event = trace_buffer_lock_reserve(buffer, ++ event = trace_event_buffer_lock_reserve(&buffer, trace_file, + sys_data->enter_event->event.type, size, trace_ctx); + if (!event) + return; +@@ -367,8 +366,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) + + trace_ctx = tracing_gen_ctx(); + +- buffer = tr->array_buffer.buffer; +- event = trace_buffer_lock_reserve(buffer, ++ event = trace_event_buffer_lock_reserve(&buffer, trace_file, + sys_data->exit_event->event.type, sizeof(*entry), + trace_ctx); + if (!event) +diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c +index 225ce569bf8f8..78ec1c16ccf4b 100644 +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -1313,6 +1313,7 @@ static int uprobe_perf_open(struct trace_event_call *call, + return 0; + + list_for_each_entry(pos, trace_probe_probe_list(tp), list) { ++ tu = container_of(pos, struct trace_uprobe, tp); + err = uprobe_apply(tu->inode, tu->offset, &tu->consumer, true); + if (err) { + uprobe_perf_close(call, event); +@@ -1618,6 +1619,11 @@ create_local_trace_uprobe(char *name, unsigned long offs, + tu->path = path; + tu->ref_ctr_offset = ref_ctr_offset; + tu->filename = kstrdup(name, GFP_KERNEL); ++ if (!tu->filename) { ++ ret = -ENOMEM; ++ goto error; ++ } ++ + init_trace_event_call(tu); + + ptype = is_ret_probe(tu) ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL; +@@ -1655,10 +1661,10 @@ static __init int init_uprobe_trace(void) + if (ret) + return 0; + +- trace_create_file("uprobe_events", 0644, NULL, ++ trace_create_file("uprobe_events", TRACE_MODE_WRITE, NULL, + NULL, &uprobe_events_ops); + /* Profile interface */ +- trace_create_file("uprobe_profile", 0444, NULL, ++ trace_create_file("uprobe_profile", TRACE_MODE_READ, NULL, + NULL, &uprobe_profile_ops); + return 0; + } +diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c +index d6bddb157ef20..9628b55718468 100644 +--- a/kernel/trace/tracing_map.c ++++ b/kernel/trace/tracing_map.c +@@ -15,6 +15,7 @@ + #include <linux/jhash.h> + #include <linux/slab.h> + #include <linux/sort.h> ++#include <linux/kmemleak.h> + + #include "tracing_map.h" + #include "trace.h" +@@ -307,6 +308,7 @@ static void tracing_map_array_free(struct tracing_map_array *a) + for (i = 0; i < a->n_pages; i++) { + if (!a->pages[i]) + break; ++ kmemleak_free(a->pages[i]); + free_page((unsigned long)a->pages[i]); + } + +@@ -342,6 +344,7 @@ static struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, + a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL); + if (!a->pages[i]) + goto free; ++ kmemleak_alloc(a->pages[i], PAGE_SIZE, 1, GFP_KERNEL); + } + out: + return a; +@@ -834,29 +837,35 @@ int tracing_map_init(struct tracing_map *map) + return err; + } + +-static int cmp_entries_dup(const struct tracing_map_sort_entry **a, +- const struct tracing_map_sort_entry **b) ++static int cmp_entries_dup(const void *A, const void *B) + { ++ const struct tracing_map_sort_entry *a, *b; + int ret = 0; + +- if (memcmp((*a)->key, (*b)->key, (*a)->elt->map->key_size)) ++ a = *(const struct tracing_map_sort_entry **)A; ++ b = *(const struct tracing_map_sort_entry **)B; ++ ++ if (memcmp(a->key, b->key, a->elt->map->key_size)) + ret = 1; + + return ret; + } + +-static int cmp_entries_sum(const struct tracing_map_sort_entry **a, +- const struct tracing_map_sort_entry **b) ++static int cmp_entries_sum(const void *A, const void *B) + { + const struct tracing_map_elt *elt_a, *elt_b; ++ const struct tracing_map_sort_entry *a, *b; + struct tracing_map_sort_key *sort_key; + struct tracing_map_field *field; + tracing_map_cmp_fn_t cmp_fn; + void *val_a, *val_b; + int ret = 0; + +- elt_a = (*a)->elt; +- elt_b = (*b)->elt; ++ a = *(const struct tracing_map_sort_entry **)A; ++ b = *(const struct tracing_map_sort_entry **)B; ++ ++ elt_a = a->elt; ++ elt_b = b->elt; + + sort_key = &elt_a->map->sort_key; + +@@ -873,18 +882,21 @@ static int cmp_entries_sum(const struct tracing_map_sort_entry **a, + return ret; + } + +-static int cmp_entries_key(const struct tracing_map_sort_entry **a, +- const struct tracing_map_sort_entry **b) ++static int cmp_entries_key(const void *A, const void *B) + { + const struct tracing_map_elt *elt_a, *elt_b; ++ const struct tracing_map_sort_entry *a, *b; + struct tracing_map_sort_key *sort_key; + struct tracing_map_field *field; + tracing_map_cmp_fn_t cmp_fn; + void *val_a, *val_b; + int ret = 0; + +- elt_a = (*a)->elt; +- elt_b = (*b)->elt; ++ a = *(const struct tracing_map_sort_entry **)A; ++ b = *(const struct tracing_map_sort_entry **)B; ++ ++ elt_a = a->elt; ++ elt_b = b->elt; + + sort_key = &elt_a->map->sort_key; + +@@ -989,10 +1001,8 @@ static void sort_secondary(struct tracing_map *map, + struct tracing_map_sort_key *primary_key, + struct tracing_map_sort_key *secondary_key) + { +- int (*primary_fn)(const struct tracing_map_sort_entry **, +- const struct tracing_map_sort_entry **); +- int (*secondary_fn)(const struct tracing_map_sort_entry **, +- const struct tracing_map_sort_entry **); ++ int (*primary_fn)(const void *, const void *); ++ int (*secondary_fn)(const void *, const void *); + unsigned i, start = 0, n_sub = 1; + + if (is_key(map, primary_key->field_idx)) +@@ -1061,8 +1071,7 @@ int tracing_map_sort_entries(struct tracing_map *map, + unsigned int n_sort_keys, + struct tracing_map_sort_entry ***sort_entries) + { +- int (*cmp_entries_fn)(const struct tracing_map_sort_entry **, +- const struct tracing_map_sort_entry **); ++ int (*cmp_entries_fn)(const void *, const void *); + struct tracing_map_sort_entry *sort_entry, **entries; + int i, n_entries, ret; + +diff --git a/kernel/tsacct.c b/kernel/tsacct.c +index 257ffb993ea23..fd2f7a052fdd9 100644 +--- a/kernel/tsacct.c ++++ b/kernel/tsacct.c +@@ -38,11 +38,10 @@ void bacct_add_tsk(struct user_namespace *user_ns, + stats->ac_btime = clamp_t(time64_t, btime, 0, U32_MAX); + stats->ac_btime64 = btime; + +- if (thread_group_leader(tsk)) { ++ if (tsk->flags & PF_EXITING) + stats->ac_exitcode = tsk->exit_code; +- if (tsk->flags & PF_FORKNOEXEC) +- stats->ac_flag |= AFORK; +- } ++ if (thread_group_leader(tsk) && (tsk->flags & PF_FORKNOEXEC)) ++ stats->ac_flag |= AFORK; + if (tsk->flags & PF_SUPERPRIV) + stats->ac_flag |= ASU; + if (tsk->flags & PF_DUMPCORE) +diff --git a/kernel/ucount.c b/kernel/ucount.c +index eb03f3c68375d..a1d67261501a6 100644 +--- a/kernel/ucount.c ++++ b/kernel/ucount.c +@@ -184,6 +184,7 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid) + kfree(new); + } else { + hlist_add_head(&new->node, hashent); ++ get_user_ns(new->ns); + spin_unlock_irq(&ucounts_lock); + return new; + } +@@ -204,6 +205,7 @@ void put_ucounts(struct ucounts *ucounts) + if (atomic_dec_and_lock_irqsave(&ucounts->count, &ucounts_lock, flags)) { + hlist_del_init(&ucounts->node); + spin_unlock_irqrestore(&ucounts_lock, flags); ++ put_user_ns(ucounts->ns); + kfree(ucounts); + } + } +@@ -258,15 +260,16 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type) + long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v) + { + struct ucounts *iter; ++ long max = LONG_MAX; + long ret = 0; + + for (iter = ucounts; iter; iter = iter->ns->ucounts) { +- long max = READ_ONCE(iter->ns->ucount_max[type]); + long new = atomic_long_add_return(v, &iter->ucount[type]); + if (new < 0 || new > max) + ret = LONG_MAX; + else if (iter == ucounts) + ret = new; ++ max = READ_ONCE(iter->ns->ucount_max[type]); + } + return ret; + } +@@ -306,15 +309,16 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type) + { + /* Caller must hold a reference to ucounts */ + struct ucounts *iter; ++ long max = LONG_MAX; + long dec, ret = 0; + + for (iter = ucounts; iter; iter = iter->ns->ucounts) { +- long max = READ_ONCE(iter->ns->ucount_max[type]); + long new = atomic_long_add_return(1, &iter->ucount[type]); + if (new < 0 || new > max) + goto unwind; + if (iter == ucounts) + ret = new; ++ max = READ_ONCE(iter->ns->ucount_max[type]); + /* + * Grab an extra ucount reference for the caller when + * the rlimit count was previously 0. +@@ -333,15 +337,17 @@ unwind: + return 0; + } + +-bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long max) ++bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long rlimit) + { + struct ucounts *iter; +- if (get_ucounts_value(ucounts, type) > max) +- return true; ++ long max = rlimit; ++ if (rlimit > LONG_MAX) ++ max = LONG_MAX; + for (iter = ucounts; iter; iter = iter->ns->ucounts) { +- max = READ_ONCE(iter->ns->ucount_max[type]); +- if (get_ucounts_value(iter, type) > max) ++ long val = get_ucounts_value(iter, type); ++ if (val < 0 || val > max) + return true; ++ max = READ_ONCE(iter->ns->ucount_max[type]); + } + return false; + } +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index 6b2e3ca7ee993..5481ba44a8d68 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -58,6 +58,18 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) + cred->user_ns = user_ns; + } + ++static unsigned long enforced_nproc_rlimit(void) ++{ ++ unsigned long limit = RLIM_INFINITY; ++ ++ /* Is RLIMIT_NPROC currently enforced? */ ++ if (!uid_eq(current_uid(), GLOBAL_ROOT_UID) || ++ (current_user_ns() != &init_user_ns)) ++ limit = rlimit(RLIMIT_NPROC); ++ ++ return limit; ++} ++ + /* + * Create a new user namespace, deriving the creator from the user in the + * passed credentials, and replacing that user with the new root user for the +@@ -122,7 +134,7 @@ int create_user_ns(struct cred *new) + for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++) { + ns->ucount_max[i] = INT_MAX; + } +- set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)); ++ set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_NPROC, enforced_nproc_rlimit()); + set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE)); + set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING)); + set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK)); +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 1b3eb1e9531f4..3f4d276685768 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -867,8 +867,17 @@ void wq_worker_running(struct task_struct *task) + + if (!worker->sleeping) + return; ++ ++ /* ++ * If preempted by unbind_workers() between the WORKER_NOT_RUNNING check ++ * and the nr_running increment below, we may ruin the nr_running reset ++ * and leave with an unexpected pool->nr_running == 1 on the newly unbound ++ * pool. Protect against such race. ++ */ ++ preempt_disable(); + if (!(worker->flags & WORKER_NOT_RUNNING)) + atomic_inc(&worker->pool->nr_running); ++ preempt_enable(); + worker->sleeping = 0; + } + +@@ -5384,9 +5393,6 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) + int ret = -EINVAL; + cpumask_var_t saved_cpumask; + +- if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) +- return -ENOMEM; +- + /* + * Not excluding isolated cpus on purpose. + * If the user wishes to include them, we allow that. +@@ -5394,6 +5400,15 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) + cpumask_and(cpumask, cpumask, cpu_possible_mask); + if (!cpumask_empty(cpumask)) { + apply_wqattrs_lock(); ++ if (cpumask_equal(cpumask, wq_unbound_cpumask)) { ++ ret = 0; ++ goto out_unlock; ++ } ++ ++ if (!zalloc_cpumask_var(&saved_cpumask, GFP_KERNEL)) { ++ ret = -ENOMEM; ++ goto out_unlock; ++ } + + /* save the old wq_unbound_cpumask. */ + cpumask_copy(saved_cpumask, wq_unbound_cpumask); +@@ -5406,10 +5421,11 @@ int workqueue_set_unbound_cpumask(cpumask_var_t cpumask) + if (ret < 0) + cpumask_copy(wq_unbound_cpumask, saved_cpumask); + ++ free_cpumask_var(saved_cpumask); ++out_unlock: + apply_wqattrs_unlock(); + } + +- free_cpumask_var(saved_cpumask); + return ret; + } + +diff --git a/lib/Kconfig.kfence b/lib/Kconfig.kfence +index e641add339475..912f252a41fc6 100644 +--- a/lib/Kconfig.kfence ++++ b/lib/Kconfig.kfence +@@ -25,17 +25,6 @@ menuconfig KFENCE + + if KFENCE + +-config KFENCE_STATIC_KEYS +- bool "Use static keys to set up allocations" +- default y +- depends on JUMP_LABEL # To ensure performance, require jump labels +- help +- Use static keys (static branches) to set up KFENCE allocations. Using +- static keys is normally recommended, because it avoids a dynamic +- branch in the allocator's fast path. However, with very low sample +- intervals, or on systems that do not support jump labels, a dynamic +- branch may still be an acceptable performance trade-off. +- + config KFENCE_SAMPLE_INTERVAL + int "Default sample interval in milliseconds" + default 100 +@@ -56,6 +45,21 @@ config KFENCE_NUM_OBJECTS + pages are required; with one containing the object and two adjacent + ones used as guard pages. + ++config KFENCE_STATIC_KEYS ++ bool "Use static keys to set up allocations" if EXPERT ++ depends on JUMP_LABEL ++ help ++ Use static keys (static branches) to set up KFENCE allocations. This ++ option is only recommended when using very large sample intervals, or ++ performance has carefully been evaluated with this option. ++ ++ Using static keys comes with trade-offs that need to be carefully ++ evaluated given target workloads and system architectures. Notably, ++ enabling and disabling static keys invoke IPI broadcasts, the latency ++ and impact of which is much harder to predict than a dynamic branch. ++ ++ Say N if you are unsure. ++ + config KFENCE_STRESS_TEST_FAULTS + int "Stress testing of fault handling and error reporting" if EXPERT + default 0 +diff --git a/lib/crypto/sm4.c b/lib/crypto/sm4.c +index 633b59fed9db8..284e62576d0c6 100644 +--- a/lib/crypto/sm4.c ++++ b/lib/crypto/sm4.c +@@ -15,7 +15,7 @@ static const u32 fk[4] = { + 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc + }; + +-static const u32 __cacheline_aligned ck[32] = { ++static const u32 ____cacheline_aligned ck[32] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, +@@ -26,7 +26,7 @@ static const u32 __cacheline_aligned ck[32] = { + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 + }; + +-static const u8 __cacheline_aligned sbox[256] = { ++static const u8 ____cacheline_aligned sbox[256] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, +diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c +index a2f38e23004aa..f7a3dc13316a3 100644 +--- a/lib/decompress_unxz.c ++++ b/lib/decompress_unxz.c +@@ -167,7 +167,7 @@ + * memeq and memzero are not used much and any remotely sane implementation + * is fast enough. memcpy/memmove speed matters in multi-call mode, but + * the kernel image is decompressed in single-call mode, in which only +- * memcpy speed can matter and only if there is a lot of uncompressible data ++ * memmove speed can matter and only if there is a lot of uncompressible data + * (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the + * functions below should just be kept small; it's probably not worth + * optimizing for speed. +diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c +index cb5abb42c16a2..84c16309cc637 100644 +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -761,6 +761,18 @@ static __init int ddebug_setup_query(char *str) + + __setup("ddebug_query=", ddebug_setup_query); + ++/* ++ * Install a noop handler to make dyndbg look like a normal kernel cli param. ++ * This avoids warnings about dyndbg being an unknown cli param when supplied ++ * by a user. ++ */ ++static __init int dyndbg_setup(char *str) ++{ ++ return 1; ++} ++ ++__setup("dyndbg=", dyndbg_setup); ++ + /* + * File_ops->write method for <debugfs>/dynamic_debug/control. Gathers the + * command text from userspace, parses and executes it. +diff --git a/lib/iov_iter.c b/lib/iov_iter.c +index 755c10c5138cd..c5b2f0f4b8a84 100644 +--- a/lib/iov_iter.c ++++ b/lib/iov_iter.c +@@ -416,6 +416,7 @@ static size_t copy_page_to_iter_pipe(struct page *page, size_t offset, size_t by + return 0; + + buf->ops = &page_cache_pipe_buf_ops; ++ buf->flags = 0; + get_page(page); + buf->page = page; + buf->offset = offset; +@@ -532,6 +533,7 @@ static size_t push_pipe(struct iov_iter *i, size_t size, + break; + + buf->ops = &default_pipe_buf_ops; ++ buf->flags = 0; + buf->page = page; + buf->offset = 0; + buf->len = min_t(ssize_t, left, PAGE_SIZE); +@@ -1488,7 +1490,7 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, + res = get_user_pages_fast(addr, n, + iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, + pages); +- if (unlikely(res < 0)) ++ if (unlikely(res <= 0)) + return res; + return (res == n ? len : res * PAGE_SIZE) - *start; + } +@@ -1612,8 +1614,9 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, + return -ENOMEM; + res = get_user_pages_fast(addr, n, + iov_iter_rw(i) != WRITE ? FOLL_WRITE : 0, p); +- if (unlikely(res < 0)) { ++ if (unlikely(res <= 0)) { + kvfree(p); ++ *pages = NULL; + return res; + } + *pages = p; +diff --git a/lib/kunit/test.c b/lib/kunit/test.c +index f246b847024e3..9aef816e573c1 100644 +--- a/lib/kunit/test.c ++++ b/lib/kunit/test.c +@@ -504,16 +504,18 @@ int kunit_run_tests(struct kunit_suite *suite) + struct kunit_result_stats param_stats = { 0 }; + test_case->status = KUNIT_SKIPPED; + +- if (test_case->generate_params) { ++ if (!test_case->generate_params) { ++ /* Non-parameterised test. */ ++ kunit_run_case_catch_errors(suite, test_case, &test); ++ kunit_update_stats(¶m_stats, test.status); ++ } else { + /* Get initial param. */ + param_desc[0] = '\0'; + test.param_value = test_case->generate_params(NULL, param_desc); +- } + +- do { +- kunit_run_case_catch_errors(suite, test_case, &test); ++ while (test.param_value) { ++ kunit_run_case_catch_errors(suite, test_case, &test); + +- if (test_case->generate_params) { + if (param_desc[0] == '\0') { + snprintf(param_desc, sizeof(param_desc), + "param-%d", test.param_index); +@@ -530,11 +532,11 @@ int kunit_run_tests(struct kunit_suite *suite) + param_desc[0] = '\0'; + test.param_value = test_case->generate_params(test.param_value, param_desc); + test.param_index++; +- } + +- kunit_update_stats(¶m_stats, test.status); ++ kunit_update_stats(¶m_stats, test.status); ++ } ++ } + +- } while (test.param_value); + + kunit_print_test_stats(&test, param_stats); + +diff --git a/lib/logic_iomem.c b/lib/logic_iomem.c +index 9bdfde0c0f86d..549b22d4bcde1 100644 +--- a/lib/logic_iomem.c ++++ b/lib/logic_iomem.c +@@ -21,15 +21,15 @@ struct logic_iomem_area { + + #define AREA_SHIFT 24 + #define MAX_AREA_SIZE (1 << AREA_SHIFT) +-#define MAX_AREAS ((1ULL<<32) / MAX_AREA_SIZE) ++#define MAX_AREAS ((1U << 31) / MAX_AREA_SIZE) + #define AREA_BITS ((MAX_AREAS - 1) << AREA_SHIFT) + #define AREA_MASK (MAX_AREA_SIZE - 1) + #ifdef CONFIG_64BIT + #define IOREMAP_BIAS 0xDEAD000000000000UL + #define IOREMAP_MASK 0xFFFFFFFF00000000UL + #else +-#define IOREMAP_BIAS 0 +-#define IOREMAP_MASK 0 ++#define IOREMAP_BIAS 0x80000000UL ++#define IOREMAP_MASK 0x80000000UL + #endif + + static DEFINE_MUTEX(regions_mtx); +@@ -79,7 +79,7 @@ static void __iomem *real_ioremap(phys_addr_t offset, size_t size) + static void real_iounmap(void __iomem *addr) + { + WARN(1, "invalid iounmap for addr 0x%llx\n", +- (unsigned long long __force)addr); ++ (unsigned long long)(uintptr_t __force)addr); + } + #endif /* CONFIG_LOGIC_IOMEM_FALLBACK */ + +@@ -173,7 +173,7 @@ EXPORT_SYMBOL(iounmap); + static u##sz real_raw_read ## op(const volatile void __iomem *addr) \ + { \ + WARN(1, "Invalid read" #op " at address %llx\n", \ +- (unsigned long long __force)addr); \ ++ (unsigned long long)(uintptr_t __force)addr); \ + return (u ## sz)~0ULL; \ + } \ + \ +@@ -181,7 +181,8 @@ static void real_raw_write ## op(u ## sz val, \ + volatile void __iomem *addr) \ + { \ + WARN(1, "Invalid writeq" #op " of 0x%llx at address %llx\n", \ +- (unsigned long long)val, (unsigned long long __force)addr);\ ++ (unsigned long long)val, \ ++ (unsigned long long)(uintptr_t __force)addr);\ + } \ + + MAKE_FALLBACK(b, 8); +@@ -194,14 +195,14 @@ MAKE_FALLBACK(q, 64); + static void real_memset_io(volatile void __iomem *addr, int value, size_t size) + { + WARN(1, "Invalid memset_io at address 0x%llx\n", +- (unsigned long long __force)addr); ++ (unsigned long long)(uintptr_t __force)addr); + } + + static void real_memcpy_fromio(void *buffer, const volatile void __iomem *addr, + size_t size) + { + WARN(1, "Invalid memcpy_fromio at address 0x%llx\n", +- (unsigned long long __force)addr); ++ (unsigned long long)(uintptr_t __force)addr); + + memset(buffer, 0xff, size); + } +@@ -210,7 +211,7 @@ static void real_memcpy_toio(volatile void __iomem *addr, const void *buffer, + size_t size) + { + WARN(1, "Invalid memcpy_toio at address 0x%llx\n", +- (unsigned long long __force)addr); ++ (unsigned long long)(uintptr_t __force)addr); + } + #endif /* CONFIG_LOGIC_IOMEM_FALLBACK */ + +diff --git a/lib/mpi/mpi-mod.c b/lib/mpi/mpi-mod.c +index 47bc59edd4ff9..54fcc01564d9d 100644 +--- a/lib/mpi/mpi-mod.c ++++ b/lib/mpi/mpi-mod.c +@@ -40,6 +40,8 @@ mpi_barrett_t mpi_barrett_init(MPI m, int copy) + + mpi_normalize(m); + ctx = kcalloc(1, sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return NULL; + + if (copy) { + ctx->m = mpi_copy(m); +diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c +index f9e89001b52eb..199ab201d5019 100644 +--- a/lib/nmi_backtrace.c ++++ b/lib/nmi_backtrace.c +@@ -75,6 +75,12 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask, + touch_softlockup_watchdog(); + } + ++ /* ++ * Force flush any remote buffers that might be stuck in IRQ context ++ * and therefore could not run their irq_work. ++ */ ++ printk_trigger_flush(); ++ + clear_bit_unlock(0, &backtrace_flag); + put_cpu(); + } +diff --git a/lib/siphash.c b/lib/siphash.c +index a90112ee72a1f..72b9068ab57bf 100644 +--- a/lib/siphash.c ++++ b/lib/siphash.c +@@ -49,6 +49,7 @@ + SIPROUND; \ + return (v0 ^ v1) ^ (v2 ^ v3); + ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) + { + const u8 *end = data + len - (len % sizeof(u64)); +@@ -80,8 +81,8 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) + POSTAMBLE + } + EXPORT_SYMBOL(__siphash_aligned); ++#endif + +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) + { + const u8 *end = data + len - (len % sizeof(u64)); +@@ -113,7 +114,6 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) + POSTAMBLE + } + EXPORT_SYMBOL(__siphash_unaligned); +-#endif + + /** + * siphash_1u64 - compute 64-bit siphash PRF value of a u64 +@@ -250,6 +250,7 @@ EXPORT_SYMBOL(siphash_3u32); + HSIPROUND; \ + return (v0 ^ v1) ^ (v2 ^ v3); + ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) + { + const u8 *end = data + len - (len % sizeof(u64)); +@@ -280,8 +281,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) + HPOSTAMBLE + } + EXPORT_SYMBOL(__hsiphash_aligned); ++#endif + +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u32 __hsiphash_unaligned(const void *data, size_t len, + const hsiphash_key_t *key) + { +@@ -313,7 +314,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len, + HPOSTAMBLE + } + EXPORT_SYMBOL(__hsiphash_unaligned); +-#endif + + /** + * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32 +@@ -418,6 +418,7 @@ EXPORT_SYMBOL(hsiphash_4u32); + HSIPROUND; \ + return v1 ^ v3; + ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) + { + const u8 *end = data + len - (len % sizeof(u32)); +@@ -438,8 +439,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) + HPOSTAMBLE + } + EXPORT_SYMBOL(__hsiphash_aligned); ++#endif + +-#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + u32 __hsiphash_unaligned(const void *data, size_t len, + const hsiphash_key_t *key) + { +@@ -461,7 +462,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len, + HPOSTAMBLE + } + EXPORT_SYMBOL(__hsiphash_unaligned); +-#endif + + /** + * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32 +diff --git a/lib/string_helpers.c b/lib/string_helpers.c +index 3806a52ce697a..2ddc10bd9add6 100644 +--- a/lib/string_helpers.c ++++ b/lib/string_helpers.c +@@ -696,3 +696,23 @@ void kfree_strarray(char **array, size_t n) + kfree(array); + } + EXPORT_SYMBOL_GPL(kfree_strarray); ++ ++/** ++ * memcpy_and_pad - Copy one buffer to another with padding ++ * @dest: Where to copy to ++ * @dest_len: The destination buffer size ++ * @src: Where to copy from ++ * @count: The number of bytes to copy ++ * @pad: Character to use for padding if space is left in destination. ++ */ ++void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, ++ int pad) ++{ ++ if (dest_len > count) { ++ memcpy(dest, src, count); ++ memset(dest + count, pad, dest_len - count); ++ } else { ++ memcpy(dest, src, dest_len); ++ } ++} ++EXPORT_SYMBOL(memcpy_and_pad); +diff --git a/lib/test_bpf.c b/lib/test_bpf.c +index 830a18ecffc88..68d125b409f20 100644 +--- a/lib/test_bpf.c ++++ b/lib/test_bpf.c +@@ -8992,10 +8992,15 @@ static __init int test_bpf(void) + struct tail_call_test { + const char *descr; + struct bpf_insn insns[MAX_INSNS]; ++ int flags; + int result; + int stack_depth; + }; + ++/* Flags that can be passed to tail call test cases */ ++#define FLAG_NEED_STATE BIT(0) ++#define FLAG_RESULT_IN_STATE BIT(1) ++ + /* + * Magic marker used in test snippets for tail calls below. + * BPF_LD/MOV to R2 and R2 with this immediate value is replaced +@@ -9065,32 +9070,38 @@ static struct tail_call_test tail_call_tests[] = { + { + "Tail call error path, max count reached", + .insns = { +- BPF_ALU64_IMM(BPF_ADD, R1, 1), +- BPF_ALU64_REG(BPF_MOV, R0, R1), ++ BPF_LDX_MEM(BPF_W, R2, R1, 0), ++ BPF_ALU64_IMM(BPF_ADD, R2, 1), ++ BPF_STX_MEM(BPF_W, R1, R2, 0), + TAIL_CALL(0), + BPF_EXIT_INSN(), + }, +- .result = MAX_TAIL_CALL_CNT + 1, ++ .flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, ++ .result = (MAX_TAIL_CALL_CNT + 1 + 1) * MAX_TESTRUNS, + }, + { + "Tail call error path, NULL target", + .insns = { +- BPF_ALU64_IMM(BPF_MOV, R0, -1), ++ BPF_LDX_MEM(BPF_W, R2, R1, 0), ++ BPF_ALU64_IMM(BPF_ADD, R2, 1), ++ BPF_STX_MEM(BPF_W, R1, R2, 0), + TAIL_CALL(TAIL_CALL_NULL), +- BPF_ALU64_IMM(BPF_MOV, R0, 1), + BPF_EXIT_INSN(), + }, +- .result = 1, ++ .flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, ++ .result = MAX_TESTRUNS, + }, + { + "Tail call error path, index out of range", + .insns = { +- BPF_ALU64_IMM(BPF_MOV, R0, -1), ++ BPF_LDX_MEM(BPF_W, R2, R1, 0), ++ BPF_ALU64_IMM(BPF_ADD, R2, 1), ++ BPF_STX_MEM(BPF_W, R1, R2, 0), + TAIL_CALL(TAIL_CALL_INVALID), +- BPF_ALU64_IMM(BPF_MOV, R0, 1), + BPF_EXIT_INSN(), + }, +- .result = 1, ++ .flags = FLAG_NEED_STATE | FLAG_RESULT_IN_STATE, ++ .result = MAX_TESTRUNS, + }, + }; + +@@ -9196,6 +9207,8 @@ static __init int test_tail_calls(struct bpf_array *progs) + for (i = 0; i < ARRAY_SIZE(tail_call_tests); i++) { + struct tail_call_test *test = &tail_call_tests[i]; + struct bpf_prog *fp = progs->ptrs[i]; ++ int *data = NULL; ++ int state = 0; + u64 duration; + int ret; + +@@ -9212,7 +9225,11 @@ static __init int test_tail_calls(struct bpf_array *progs) + if (fp->jited) + jit_cnt++; + +- ret = __run_one(fp, NULL, MAX_TESTRUNS, &duration); ++ if (test->flags & FLAG_NEED_STATE) ++ data = &state; ++ ret = __run_one(fp, data, MAX_TESTRUNS, &duration); ++ if (test->flags & FLAG_RESULT_IN_STATE) ++ ret = state; + if (ret == test->result) { + pr_cont("%lld PASS", duration); + pass_cnt++; +diff --git a/lib/test_hmm.c b/lib/test_hmm.c +index c259842f6d443..ac794e3540693 100644 +--- a/lib/test_hmm.c ++++ b/lib/test_hmm.c +@@ -1087,9 +1087,33 @@ static long dmirror_fops_unlocked_ioctl(struct file *filp, + return 0; + } + ++static int dmirror_fops_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ unsigned long addr; ++ ++ for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) { ++ struct page *page; ++ int ret; ++ ++ page = alloc_page(GFP_KERNEL | __GFP_ZERO); ++ if (!page) ++ return -ENOMEM; ++ ++ ret = vm_insert_page(vma, addr, page); ++ if (ret) { ++ __free_page(page); ++ return ret; ++ } ++ put_page(page); ++ } ++ ++ return 0; ++} ++ + static const struct file_operations dmirror_fops = { + .open = dmirror_fops_open, + .release = dmirror_fops_release, ++ .mmap = dmirror_fops_mmap, + .unlocked_ioctl = dmirror_fops_unlocked_ioctl, + .llseek = default_llseek, + .owner = THIS_MODULE, +diff --git a/lib/test_meminit.c b/lib/test_meminit.c +index e4f706a404b3a..3ca717f113977 100644 +--- a/lib/test_meminit.c ++++ b/lib/test_meminit.c +@@ -337,6 +337,7 @@ static int __init do_kmem_cache_size_bulk(int size, int *total_failures) + if (num) + kmem_cache_free_bulk(c, num, objects); + } ++ kmem_cache_destroy(c); + *total_failures += fail; + return 1; + } +diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c +index 7a6781e3f47b6..d548cf0e59fe6 100644 +--- a/lib/xz/xz_dec_lzma2.c ++++ b/lib/xz/xz_dec_lzma2.c +@@ -387,7 +387,14 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, + + *left -= copy_size; + +- memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); ++ /* ++ * If doing in-place decompression in single-call mode and the ++ * uncompressed size of the file is larger than the caller ++ * thought (i.e. it is invalid input!), the buffers below may ++ * overlap and cause undefined behavior with memcpy(). ++ * With valid inputs memcpy() would be fine here. ++ */ ++ memmove(dict->buf + dict->pos, b->in + b->in_pos, copy_size); + dict->pos += copy_size; + + if (dict->full < dict->pos) +@@ -397,7 +404,11 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, + if (dict->pos == dict->end) + dict->pos = 0; + +- memcpy(b->out + b->out_pos, b->in + b->in_pos, ++ /* ++ * Like above but for multi-call mode: use memmove() ++ * to avoid undefined behavior with invalid input. ++ */ ++ memmove(b->out + b->out_pos, b->in + b->in_pos, + copy_size); + } + +@@ -421,6 +432,12 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) + if (dict->pos == dict->end) + dict->pos = 0; + ++ /* ++ * These buffers cannot overlap even if doing in-place ++ * decompression because in multi-call mode dict->buf ++ * has been allocated by us in this file; it's not ++ * provided by the caller like in single-call mode. ++ */ + memcpy(b->out + b->out_pos, dict->buf + dict->start, + copy_size); + } +diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c +index fea86deaaa01d..683570b93a8c4 100644 +--- a/lib/xz/xz_dec_stream.c ++++ b/lib/xz/xz_dec_stream.c +@@ -402,12 +402,12 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) + * we will accept other check types too, but then the check won't + * be verified and a warning (XZ_UNSUPPORTED_CHECK) will be given. + */ ++ if (s->temp.buf[HEADER_MAGIC_SIZE + 1] > XZ_CHECK_MAX) ++ return XZ_OPTIONS_ERROR; ++ + s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; + + #ifdef XZ_DEC_ANY_CHECK +- if (s->check_type > XZ_CHECK_MAX) +- return XZ_OPTIONS_ERROR; +- + if (s->check_type > XZ_CHECK_CRC32) + return XZ_UNSUPPORTED_CHECK; + #else +diff --git a/mm/Kconfig b/mm/Kconfig +index d16ba9249bc53..c048dea7e3420 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -887,6 +887,9 @@ config MAPPING_DIRTY_HELPERS + config KMAP_LOCAL + bool + ++config KMAP_LOCAL_NON_LINEAR_PTE_ARRAY ++ bool ++ + # struct io_mapping based helper. Selected by drivers that need them + config IO_MAPPING + bool +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 4a9d4e27d0d9b..02ff66f863587 100644 +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -947,6 +947,13 @@ void bdi_unregister(struct backing_dev_info *bdi) + wb_shutdown(&bdi->wb); + cgwb_bdi_unregister(bdi); + ++ /* ++ * If this BDI's min ratio has been set, use bdi_set_min_ratio() to ++ * update the global bdi_min_ratio. ++ */ ++ if (bdi->min_ratio) ++ bdi_set_min_ratio(bdi, 0); ++ + if (bdi->dev) { + bdi_debug_unregister(bdi); + device_unregister(bdi->dev); +diff --git a/mm/damon/core.c b/mm/damon/core.c +index 30e9211f494a7..7a4912d6e65f2 100644 +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -357,6 +357,15 @@ int damon_start(struct damon_ctx **ctxs, int nr_ctxs) + return err; + } + ++static void kdamond_usleep(unsigned long usecs) ++{ ++ /* See Documentation/timers/timers-howto.rst for the thresholds */ ++ if (usecs > 20 * 1000) ++ schedule_timeout_idle(usecs_to_jiffies(usecs)); ++ else ++ usleep_idle_range(usecs, usecs + 1); ++} ++ + /* + * __damon_stop() - Stops monitoring of given context. + * @ctx: monitoring context +@@ -370,8 +379,7 @@ static int __damon_stop(struct damon_ctx *ctx) + ctx->kdamond_stop = true; + mutex_unlock(&ctx->kdamond_lock); + while (damon_kdamond_running(ctx)) +- usleep_range(ctx->sample_interval, +- ctx->sample_interval * 2); ++ kdamond_usleep(ctx->sample_interval); + return 0; + } + mutex_unlock(&ctx->kdamond_lock); +@@ -670,7 +678,7 @@ static int kdamond_fn(void *data) + ctx->callback.after_sampling(ctx)) + set_kdamond_stop(ctx); + +- usleep_range(ctx->sample_interval, ctx->sample_interval + 1); ++ kdamond_usleep(ctx->sample_interval); + + if (ctx->primitive.check_accesses) + max_nr_accesses = ctx->primitive.check_accesses(ctx); +diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c +index faee070977d80..36624990b5777 100644 +--- a/mm/damon/dbgfs.c ++++ b/mm/damon/dbgfs.c +@@ -32,7 +32,7 @@ static char *user_input_str(const char __user *buf, size_t count, loff_t *ppos) + if (*ppos) + return ERR_PTR(-EINVAL); + +- kbuf = kmalloc(count + 1, GFP_KERNEL); ++ kbuf = kmalloc(count + 1, GFP_KERNEL | __GFP_NOWARN); + if (!kbuf) + return ERR_PTR(-ENOMEM); + +@@ -185,6 +185,7 @@ static ssize_t dbgfs_target_ids_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) + { + struct damon_ctx *ctx = file->private_data; ++ struct damon_target *t, *next_t; + char *kbuf, *nrs; + unsigned long *targets; + ssize_t nr_targets; +@@ -224,6 +225,13 @@ static ssize_t dbgfs_target_ids_write(struct file *file, + goto unlock_out; + } + ++ /* remove previously set targets */ ++ damon_for_each_target_safe(t, next_t, ctx) { ++ if (targetid_is_pid(ctx)) ++ put_pid((struct pid *)t->id); ++ damon_destroy_target(t); ++ } ++ + err = damon_set_targets(ctx, targets, nr_targets); + if (err) { + if (targetid_is_pid(ctx)) +@@ -247,7 +255,7 @@ static ssize_t dbgfs_kdamond_pid_read(struct file *file, + char *kbuf; + ssize_t len; + +- kbuf = kmalloc(count, GFP_KERNEL); ++ kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); + if (!kbuf) + return -ENOMEM; + +@@ -309,10 +317,12 @@ static int dbgfs_before_terminate(struct damon_ctx *ctx) + if (!targetid_is_pid(ctx)) + return 0; + ++ mutex_lock(&ctx->kdamond_lock); + damon_for_each_target_safe(t, next, ctx) { + put_pid((struct pid *)t->id); + damon_destroy_target(t); + } ++ mutex_unlock(&ctx->kdamond_lock); + return 0; + } + +@@ -538,12 +548,14 @@ static ssize_t dbgfs_monitor_on_write(struct file *file, + return -EINVAL; + } + ++ mutex_lock(&damon_dbgfs_lock); + if (!strncmp(kbuf, "on", count)) + err = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs); + else if (!strncmp(kbuf, "off", count)) + err = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs); + else + err = -EINVAL; ++ mutex_unlock(&damon_dbgfs_lock); + + if (err) + ret = err; +@@ -596,15 +608,16 @@ static int __init __damon_dbgfs_init(void) + + static int __init damon_dbgfs_init(void) + { +- int rc; ++ int rc = -ENOMEM; + ++ mutex_lock(&damon_dbgfs_lock); + dbgfs_ctxs = kmalloc(sizeof(*dbgfs_ctxs), GFP_KERNEL); + if (!dbgfs_ctxs) +- return -ENOMEM; ++ goto out; + dbgfs_ctxs[0] = dbgfs_new_ctx(); + if (!dbgfs_ctxs[0]) { + kfree(dbgfs_ctxs); +- return -ENOMEM; ++ goto out; + } + dbgfs_nr_ctxs = 1; + +@@ -615,6 +628,8 @@ static int __init damon_dbgfs_init(void) + pr_err("%s: dbgfs init failed\n", __func__); + } + ++out: ++ mutex_unlock(&damon_dbgfs_lock); + return rc; + } + +diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c +index 1403639302e48..718d0d3ad8c4e 100644 +--- a/mm/debug_vm_pgtable.c ++++ b/mm/debug_vm_pgtable.c +@@ -171,6 +171,8 @@ static void __init pte_advanced_tests(struct pgtable_debug_args *args) + ptep_test_and_clear_young(args->vma, args->vaddr, args->ptep); + pte = ptep_get(args->ptep); + WARN_ON(pte_young(pte)); ++ ++ ptep_get_and_clear_full(args->mm, args->vaddr, args->ptep, 1); + } + + static void __init pte_savedwrite_tests(struct pgtable_debug_args *args) +diff --git a/mm/filemap.c b/mm/filemap.c +index dae481293b5d9..1293c3409e429 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2093,7 +2093,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t start, + if (!xa_is_value(page)) { + if (page->index < start) + goto put; +- VM_BUG_ON_PAGE(page->index != xas.xa_index, page); + if (page->index + thp_nr_pages(page) - 1 > end) + goto put; + if (!trylock_page(page)) +@@ -2355,8 +2354,12 @@ static void filemap_get_read_batch(struct address_space *mapping, + break; + if (PageReadahead(head)) + break; +- xas.xa_index = head->index + thp_nr_pages(head) - 1; +- xas.xa_offset = (xas.xa_index >> xas.xa_shift) & XA_CHUNK_MASK; ++ if (PageHead(head)) { ++ xas_set(&xas, head->index + thp_nr_pages(head)); ++ /* Handle wrap correctly */ ++ if (xas.xa_index - 1 >= max) ++ break; ++ } + continue; + put_page: + put_page(head); +diff --git a/mm/gup.c b/mm/gup.c +index 886d6148d3d03..52f08e3177e9f 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -124,8 +124,8 @@ static inline struct page *try_get_compound_head(struct page *page, int refs) + * considered failure, and furthermore, a likely bug in the caller, so a warning + * is also emitted. + */ +-struct page *try_grab_compound_head(struct page *page, +- int refs, unsigned int flags) ++__maybe_unused struct page *try_grab_compound_head(struct page *page, ++ int refs, unsigned int flags) + { + if (flags & FOLL_GET) + return try_get_compound_head(page, refs); +@@ -208,10 +208,35 @@ static void put_compound_head(struct page *page, int refs, unsigned int flags) + */ + bool __must_check try_grab_page(struct page *page, unsigned int flags) + { +- if (!(flags & (FOLL_GET | FOLL_PIN))) +- return true; ++ WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == (FOLL_GET | FOLL_PIN)); + +- return try_grab_compound_head(page, 1, flags); ++ if (flags & FOLL_GET) ++ return try_get_page(page); ++ else if (flags & FOLL_PIN) { ++ int refs = 1; ++ ++ page = compound_head(page); ++ ++ if (WARN_ON_ONCE(page_ref_count(page) <= 0)) ++ return false; ++ ++ if (hpage_pincount_available(page)) ++ hpage_pincount_add(page, 1); ++ else ++ refs = GUP_PIN_COUNTING_BIAS; ++ ++ /* ++ * Similar to try_grab_compound_head(): even if using the ++ * hpage_pincount_add/_sub() routines, be sure to ++ * *also* increment the normal page refcount field at least ++ * once, so that the page really is pinned. ++ */ ++ page_ref_add(page, refs); ++ ++ mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED, 1); ++ } ++ ++ return true; + } + + /** +diff --git a/mm/highmem.c b/mm/highmem.c +index 4212ad0e4a195..1f0c8a52fd807 100644 +--- a/mm/highmem.c ++++ b/mm/highmem.c +@@ -504,16 +504,22 @@ static inline int kmap_local_calc_idx(int idx) + + static pte_t *__kmap_pte; + +-static pte_t *kmap_get_pte(void) ++static pte_t *kmap_get_pte(unsigned long vaddr, int idx) + { ++ if (IS_ENABLED(CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY)) ++ /* ++ * Set by the arch if __kmap_pte[-idx] does not produce ++ * the correct entry. ++ */ ++ return virt_to_kpte(vaddr); + if (!__kmap_pte) + __kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); +- return __kmap_pte; ++ return &__kmap_pte[-idx]; + } + + void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot) + { +- pte_t pteval, *kmap_pte = kmap_get_pte(); ++ pte_t pteval, *kmap_pte; + unsigned long vaddr; + int idx; + +@@ -525,9 +531,10 @@ void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot) + preempt_disable(); + idx = arch_kmap_local_map_idx(kmap_local_idx_push(), pfn); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +- BUG_ON(!pte_none(*(kmap_pte - idx))); ++ kmap_pte = kmap_get_pte(vaddr, idx); ++ BUG_ON(!pte_none(*kmap_pte)); + pteval = pfn_pte(pfn, prot); +- arch_kmap_local_set_pte(&init_mm, vaddr, kmap_pte - idx, pteval); ++ arch_kmap_local_set_pte(&init_mm, vaddr, kmap_pte, pteval); + arch_kmap_local_post_map(vaddr, pteval); + current->kmap_ctrl.pteval[kmap_local_idx()] = pteval; + preempt_enable(); +@@ -560,7 +567,7 @@ EXPORT_SYMBOL(__kmap_local_page_prot); + void kunmap_local_indexed(void *vaddr) + { + unsigned long addr = (unsigned long) vaddr & PAGE_MASK; +- pte_t *kmap_pte = kmap_get_pte(); ++ pte_t *kmap_pte; + int idx; + + if (addr < __fix_to_virt(FIX_KMAP_END) || +@@ -585,8 +592,9 @@ void kunmap_local_indexed(void *vaddr) + idx = arch_kmap_local_unmap_idx(kmap_local_idx(), addr); + WARN_ON_ONCE(addr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); + ++ kmap_pte = kmap_get_pte(addr, idx); + arch_kmap_local_pre_unmap(addr); +- pte_clear(&init_mm, addr, kmap_pte - idx); ++ pte_clear(&init_mm, addr, kmap_pte); + arch_kmap_local_post_unmap(addr); + current->kmap_ctrl.pteval[kmap_local_idx()] = __pte(0); + kmap_local_idx_pop(); +@@ -608,7 +616,7 @@ EXPORT_SYMBOL(kunmap_local_indexed); + void __kmap_local_sched_out(void) + { + struct task_struct *tsk = current; +- pte_t *kmap_pte = kmap_get_pte(); ++ pte_t *kmap_pte; + int i; + + /* Clear kmaps */ +@@ -635,8 +643,9 @@ void __kmap_local_sched_out(void) + idx = arch_kmap_local_map_idx(i, pte_pfn(pteval)); + + addr = __fix_to_virt(FIX_KMAP_BEGIN + idx); ++ kmap_pte = kmap_get_pte(addr, idx); + arch_kmap_local_pre_unmap(addr); +- pte_clear(&init_mm, addr, kmap_pte - idx); ++ pte_clear(&init_mm, addr, kmap_pte); + arch_kmap_local_post_unmap(addr); + } + } +@@ -644,7 +653,7 @@ void __kmap_local_sched_out(void) + void __kmap_local_sched_in(void) + { + struct task_struct *tsk = current; +- pte_t *kmap_pte = kmap_get_pte(); ++ pte_t *kmap_pte; + int i; + + /* Restore kmaps */ +@@ -664,7 +673,8 @@ void __kmap_local_sched_in(void) + /* See comment in __kmap_local_sched_out() */ + idx = arch_kmap_local_map_idx(i, pte_pfn(pteval)); + addr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +- set_pte_at(&init_mm, addr, kmap_pte - idx, pteval); ++ kmap_pte = kmap_get_pte(addr, idx); ++ set_pte_at(&init_mm, addr, kmap_pte, pteval); + arch_kmap_local_post_map(addr, pteval); + } + } +diff --git a/mm/hmm.c b/mm/hmm.c +index 842e265992380..bd56641c79d4e 100644 +--- a/mm/hmm.c ++++ b/mm/hmm.c +@@ -300,7 +300,8 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr, + * Since each architecture defines a struct page for the zero page, just + * fall through and treat it like a normal page. + */ +- if (pte_special(pte) && !pte_devmap(pte) && ++ if (!vm_normal_page(walk->vma, addr, pte) && ++ !pte_devmap(pte) && + !is_zero_pfn(pte_pfn(pte))) { + if (hmm_pte_need_fault(hmm_vma_walk, pfn_req_flags, 0)) { + pte_unmap(ptep); +@@ -518,7 +519,7 @@ static int hmm_vma_walk_test(unsigned long start, unsigned long end, + struct hmm_range *range = hmm_vma_walk->range; + struct vm_area_struct *vma = walk->vma; + +- if (!(vma->vm_flags & (VM_IO | VM_PFNMAP | VM_MIXEDMAP)) && ++ if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)) && + vma->vm_flags & VM_READ) + return 0; + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 95dc7b83381f9..f5ed98843557b 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -4439,6 +4439,7 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + struct hstate *h = hstate_vma(vma); + unsigned long sz = huge_page_size(h); + struct mmu_notifier_range range; ++ bool force_flush = false; + + WARN_ON(!is_vm_hugetlb_page(vma)); + BUG_ON(start & ~huge_page_mask(h)); +@@ -4467,10 +4468,8 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + ptl = huge_pte_lock(h, mm, ptep); + if (huge_pmd_unshare(mm, vma, &address, ptep)) { + spin_unlock(ptl); +- /* +- * We just unmapped a page of PMDs by clearing a PUD. +- * The caller's TLB flush range should cover this area. +- */ ++ tlb_flush_pmd_range(tlb, address & PUD_MASK, PUD_SIZE); ++ force_flush = true; + continue; + } + +@@ -4527,6 +4526,22 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, + } + mmu_notifier_invalidate_range_end(&range); + tlb_end_vma(tlb, vma); ++ ++ /* ++ * If we unshared PMDs, the TLB flush was not recorded in mmu_gather. We ++ * could defer the flush until now, since by holding i_mmap_rwsem we ++ * guaranteed that the last refernece would not be dropped. But we must ++ * do the flushing before we return, as otherwise i_mmap_rwsem will be ++ * dropped and the last reference to the shared PMDs page might be ++ * dropped as well. ++ * ++ * In theory we could defer the freeing of the PMD pages as well, but ++ * huge_pmd_unshare() relies on the exact page_count for the PMD page to ++ * detect sharing, so we cannot defer the release of the page either. ++ * Instead, do flush now. ++ */ ++ if (force_flush) ++ tlb_flush_mmu_tlbonly(tlb); + } + + void __unmap_hugepage_range_final(struct mmu_gather *tlb, +@@ -5236,13 +5251,14 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, + int ret = -ENOMEM; + struct page *page; + int writable; +- bool new_pagecache_page = false; ++ bool page_in_pagecache = false; + + if (is_continue) { + ret = -EFAULT; + page = find_lock_page(mapping, idx); + if (!page) + goto out; ++ page_in_pagecache = true; + } else if (!*pagep) { + /* If a page already exists, then it's UFFDIO_COPY for + * a non-missing case. Return -EEXIST. +@@ -5330,7 +5346,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, + ret = huge_add_to_page_cache(page, mapping, idx); + if (ret) + goto out_release_nounlock; +- new_pagecache_page = true; ++ page_in_pagecache = true; + } + + ptl = huge_pte_lockptr(h, dst_mm, dst_pte); +@@ -5394,7 +5410,7 @@ out_release_unlock: + if (vm_shared || is_continue) + unlock_page(page); + out_release_nounlock: +- if (!new_pagecache_page) ++ if (!page_in_pagecache) + restore_reserve_on_error(h, dst_vma, dst_addr, page); + put_page(page); + goto out; +diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c +index d8ccff4c1275e..47ed4fc33a29e 100644 +--- a/mm/kasan/quarantine.c ++++ b/mm/kasan/quarantine.c +@@ -132,11 +132,22 @@ static void *qlink_to_object(struct qlist_node *qlink, struct kmem_cache *cache) + static void qlink_free(struct qlist_node *qlink, struct kmem_cache *cache) + { + void *object = qlink_to_object(qlink, cache); ++ struct kasan_free_meta *meta = kasan_get_free_meta(cache, object); + unsigned long flags; + + if (IS_ENABLED(CONFIG_SLAB)) + local_irq_save(flags); + ++ /* ++ * If init_on_free is enabled and KASAN's free metadata is stored in ++ * the object, zero the metadata. Otherwise, the object's memory will ++ * not be properly zeroed, as KASAN saves the metadata after the slab ++ * allocator zeroes the object. ++ */ ++ if (slab_want_init_on_free(cache) && ++ cache->kasan_info.free_meta_offset == 0) ++ memzero_explicit(meta, sizeof(*meta)); ++ + /* + * As the object now gets freed from the quarantine, assume that its + * free track is no longer valid. +diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c +index 8d95ee52d0194..dd79840e60964 100644 +--- a/mm/kasan/shadow.c ++++ b/mm/kasan/shadow.c +@@ -493,7 +493,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, + + #else /* CONFIG_KASAN_VMALLOC */ + +-int kasan_module_alloc(void *addr, size_t size) ++int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask) + { + void *ret; + size_t scaled_size; +@@ -515,9 +515,14 @@ int kasan_module_alloc(void *addr, size_t size) + __builtin_return_address(0)); + + if (ret) { ++ struct vm_struct *vm = find_vm_area(addr); + __memset(ret, KASAN_SHADOW_INIT, shadow_size); +- find_vm_area(addr)->flags |= VM_KASAN; ++ vm->flags |= VM_KASAN; + kmemleak_ignore(ret); ++ ++ if (vm->flags & VM_DEFER_KMEMLEAK) ++ kmemleak_vmalloc(vm, size, gfp_mask); ++ + return 0; + } + +diff --git a/mm/kfence/core.c b/mm/kfence/core.c +index 7a97db8bc8e75..84555b8233efc 100644 +--- a/mm/kfence/core.c ++++ b/mm/kfence/core.c +@@ -97,10 +97,11 @@ struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS]; + static struct list_head kfence_freelist = LIST_HEAD_INIT(kfence_freelist); + static DEFINE_RAW_SPINLOCK(kfence_freelist_lock); /* Lock protecting freelist. */ + +-#ifdef CONFIG_KFENCE_STATIC_KEYS +-/* The static key to set up a KFENCE allocation. */ ++/* ++ * The static key to set up a KFENCE allocation; or if static keys are not used ++ * to gate allocations, to avoid a load and compare if KFENCE is disabled. ++ */ + DEFINE_STATIC_KEY_FALSE(kfence_allocation_key); +-#endif + + /* Gates the allocation, ensuring only one succeeds in a given period. */ + atomic_t kfence_allocation_gate = ATOMIC_INIT(1); +@@ -577,6 +578,7 @@ static const struct file_operations objects_fops = { + .open = open_objects, + .read = seq_read, + .llseek = seq_lseek, ++ .release = seq_release, + }; + + static int __init kfence_debugfs_init(void) +@@ -668,6 +670,8 @@ void __init kfence_init(void) + return; + } + ++ if (!IS_ENABLED(CONFIG_KFENCE_STATIC_KEYS)) ++ static_branch_enable(&kfence_allocation_key); + WRITE_ONCE(kfence_enabled, true); + queue_delayed_work(system_unbound_wq, &kfence_timer, 0); + pr_info("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n", KFENCE_POOL_SIZE, +@@ -752,12 +756,7 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) + (s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32))) + return NULL; + +- /* +- * allocation_gate only needs to become non-zero, so it doesn't make +- * sense to continue writing to it and pay the associated contention +- * cost, in case we have a large number of concurrent allocations. +- */ +- if (atomic_read(&kfence_allocation_gate) || atomic_inc_return(&kfence_allocation_gate) > 1) ++ if (atomic_inc_return(&kfence_allocation_gate) > 1) + return NULL; + #ifdef CONFIG_KFENCE_STATIC_KEYS + /* +diff --git a/mm/kmemleak.c b/mm/kmemleak.c +index b57383c17cf60..adbe5aa011848 100644 +--- a/mm/kmemleak.c ++++ b/mm/kmemleak.c +@@ -1403,7 +1403,8 @@ static void kmemleak_scan(void) + { + unsigned long flags; + struct kmemleak_object *object; +- int i; ++ struct zone *zone; ++ int __maybe_unused i; + int new_leaks = 0; + + jiffies_last_scan = jiffies; +@@ -1443,9 +1444,9 @@ static void kmemleak_scan(void) + * Struct page scanning for each node. + */ + get_online_mems(); +- for_each_online_node(i) { +- unsigned long start_pfn = node_start_pfn(i); +- unsigned long end_pfn = node_end_pfn(i); ++ for_each_populated_zone(zone) { ++ unsigned long start_pfn = zone->zone_start_pfn; ++ unsigned long end_pfn = zone_end_pfn(zone); + unsigned long pfn; + + for (pfn = start_pfn; pfn < end_pfn; pfn++) { +@@ -1454,8 +1455,8 @@ static void kmemleak_scan(void) + if (!page) + continue; + +- /* only scan pages belonging to this node */ +- if (page_to_nid(page) != i) ++ /* only scan pages belonging to this zone */ ++ if (page_zone(page) != zone) + continue; + /* only scan if page is in use */ + if (page_count(page) == 0) +diff --git a/mm/memblock.c b/mm/memblock.c +index 5096500b26473..2b7397781c99a 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -366,14 +366,20 @@ void __init memblock_discard(void) + addr = __pa(memblock.reserved.regions); + size = PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.reserved.max); +- __memblock_free_late(addr, size); ++ if (memblock_reserved_in_slab) ++ kfree(memblock.reserved.regions); ++ else ++ __memblock_free_late(addr, size); + } + + if (memblock.memory.regions != memblock_memory_init_regions) { + addr = __pa(memblock.memory.regions); + size = PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.memory.max); +- __memblock_free_late(addr, size); ++ if (memblock_memory_in_slab) ++ kfree(memblock.memory.regions); ++ else ++ __memblock_free_late(addr, size); + } + + memblock_memory = NULL; +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 6da5020a8656d..32ba963ebf2e5 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -103,11 +103,6 @@ static bool do_memsw_account(void) + return !cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_noswap; + } + +-/* memcg and lruvec stats flushing */ +-static void flush_memcg_stats_dwork(struct work_struct *w); +-static DECLARE_DEFERRABLE_WORK(stats_flush_dwork, flush_memcg_stats_dwork); +-static DEFINE_SPINLOCK(stats_flush_lock); +- + #define THRESHOLDS_EVENTS_TARGET 128 + #define SOFTLIMIT_EVENTS_TARGET 1024 + +@@ -239,7 +234,7 @@ enum res_type { + iter != NULL; \ + iter = mem_cgroup_iter(NULL, iter, NULL)) + +-static inline bool should_force_charge(void) ++static inline bool task_is_dying(void) + { + return tsk_is_oom_victim(current) || fatal_signal_pending(current) || + (current->flags & PF_EXITING); +@@ -259,7 +254,7 @@ struct mem_cgroup *vmpressure_to_memcg(struct vmpressure *vmpr) + } + + #ifdef CONFIG_MEMCG_KMEM +-extern spinlock_t css_set_lock; ++static DEFINE_SPINLOCK(objcg_lock); + + bool mem_cgroup_kmem_disabled(void) + { +@@ -303,9 +298,9 @@ static void obj_cgroup_release(struct percpu_ref *ref) + if (nr_pages) + obj_cgroup_uncharge_pages(objcg, nr_pages); + +- spin_lock_irqsave(&css_set_lock, flags); ++ spin_lock_irqsave(&objcg_lock, flags); + list_del(&objcg->list); +- spin_unlock_irqrestore(&css_set_lock, flags); ++ spin_unlock_irqrestore(&objcg_lock, flags); + + percpu_ref_exit(ref); + kfree_rcu(objcg, rcu); +@@ -337,7 +332,7 @@ static void memcg_reparent_objcgs(struct mem_cgroup *memcg, + + objcg = rcu_replace_pointer(memcg->objcg, NULL, true); + +- spin_lock_irq(&css_set_lock); ++ spin_lock_irq(&objcg_lock); + + /* 1) Ready to reparent active objcg. */ + list_add(&objcg->list, &memcg->objcg_list); +@@ -347,7 +342,7 @@ static void memcg_reparent_objcgs(struct mem_cgroup *memcg, + /* 3) Move already reparented objcgs to the parent's list */ + list_splice(&memcg->objcg_list, &parent->objcg_list); + +- spin_unlock_irq(&css_set_lock); ++ spin_unlock_irq(&objcg_lock); + + percpu_ref_kill(&objcg->refcnt); + } +@@ -635,6 +630,64 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_node *mctz) + return mz; + } + ++/* ++ * memcg and lruvec stats flushing ++ * ++ * Many codepaths leading to stats update or read are performance sensitive and ++ * adding stats flushing in such codepaths is not desirable. So, to optimize the ++ * flushing the kernel does: ++ * ++ * 1) Periodically and asynchronously flush the stats every 2 seconds to not let ++ * rstat update tree grow unbounded. ++ * ++ * 2) Flush the stats synchronously on reader side only when there are more than ++ * (MEMCG_CHARGE_BATCH * nr_cpus) update events. Though this optimization ++ * will let stats be out of sync by atmost (MEMCG_CHARGE_BATCH * nr_cpus) but ++ * only for 2 seconds due to (1). ++ */ ++static void flush_memcg_stats_dwork(struct work_struct *w); ++static DECLARE_DEFERRABLE_WORK(stats_flush_dwork, flush_memcg_stats_dwork); ++static DEFINE_SPINLOCK(stats_flush_lock); ++static DEFINE_PER_CPU(unsigned int, stats_updates); ++static atomic_t stats_flush_threshold = ATOMIC_INIT(0); ++ ++static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val) ++{ ++ unsigned int x; ++ ++ cgroup_rstat_updated(memcg->css.cgroup, smp_processor_id()); ++ ++ x = __this_cpu_add_return(stats_updates, abs(val)); ++ if (x > MEMCG_CHARGE_BATCH) { ++ atomic_add(x / MEMCG_CHARGE_BATCH, &stats_flush_threshold); ++ __this_cpu_write(stats_updates, 0); ++ } ++} ++ ++static void __mem_cgroup_flush_stats(void) ++{ ++ unsigned long flag; ++ ++ if (!spin_trylock_irqsave(&stats_flush_lock, flag)) ++ return; ++ ++ cgroup_rstat_flush_irqsafe(root_mem_cgroup->css.cgroup); ++ atomic_set(&stats_flush_threshold, 0); ++ spin_unlock_irqrestore(&stats_flush_lock, flag); ++} ++ ++void mem_cgroup_flush_stats(void) ++{ ++ if (atomic_read(&stats_flush_threshold) > num_online_cpus()) ++ __mem_cgroup_flush_stats(); ++} ++ ++static void flush_memcg_stats_dwork(struct work_struct *w) ++{ ++ __mem_cgroup_flush_stats(); ++ queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ); ++} ++ + /** + * __mod_memcg_state - update cgroup memory statistics + * @memcg: the memory cgroup +@@ -647,7 +700,7 @@ void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val) + return; + + __this_cpu_add(memcg->vmstats_percpu->state[idx], val); +- cgroup_rstat_updated(memcg->css.cgroup, smp_processor_id()); ++ memcg_rstat_updated(memcg, val); + } + + /* idx can be of type enum memcg_stat_item or node_stat_item. */ +@@ -675,10 +728,12 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, + memcg = pn->memcg; + + /* Update memcg */ +- __mod_memcg_state(memcg, idx, val); ++ __this_cpu_add(memcg->vmstats_percpu->state[idx], val); + + /* Update lruvec */ + __this_cpu_add(pn->lruvec_stats_percpu->state[idx], val); ++ ++ memcg_rstat_updated(memcg, val); + } + + /** +@@ -780,7 +835,7 @@ void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx, + return; + + __this_cpu_add(memcg->vmstats_percpu->events[idx], count); +- cgroup_rstat_updated(memcg->css.cgroup, smp_processor_id()); ++ memcg_rstat_updated(memcg, count); + } + + static unsigned long memcg_events(struct mem_cgroup *memcg, int event) +@@ -1414,7 +1469,7 @@ static char *memory_stat_format(struct mem_cgroup *memcg) + * + * Current memory state: + */ +- cgroup_rstat_flush(memcg->css.cgroup); ++ mem_cgroup_flush_stats(); + + for (i = 0; i < ARRAY_SIZE(memory_stats); i++) { + u64 size; +@@ -1575,7 +1630,7 @@ static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, + * A few threads which were not waiting at mutex_lock_killable() can + * fail to bail out. Therefore, check again after holding oom_lock. + */ +- ret = should_force_charge() || out_of_memory(&oc); ++ ret = task_is_dying() || out_of_memory(&oc); + + unlock: + mutex_unlock(&oom_lock); +@@ -2530,6 +2585,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask, + struct page_counter *counter; + enum oom_status oom_status; + unsigned long nr_reclaimed; ++ bool passed_oom = false; + bool may_swap = true; + bool drained = false; + unsigned long pflags; +@@ -2564,15 +2620,6 @@ retry: + if (gfp_mask & __GFP_ATOMIC) + goto force; + +- /* +- * Unlike in global OOM situations, memcg is not in a physical +- * memory shortage. Allow dying and OOM-killed tasks to +- * bypass the last charges so that they can exit quickly and +- * free their memory. +- */ +- if (unlikely(should_force_charge())) +- goto force; +- + /* + * Prevent unbounded recursion when reclaim operations need to + * allocate memory. This might exceed the limits temporarily, +@@ -2630,8 +2677,9 @@ retry: + if (gfp_mask & __GFP_RETRY_MAYFAIL) + goto nomem; + +- if (fatal_signal_pending(current)) +- goto force; ++ /* Avoid endless loop for tasks bypassed by the oom killer */ ++ if (passed_oom && task_is_dying()) ++ goto nomem; + + /* + * keep retrying as long as the memcg oom killer is able to make +@@ -2640,14 +2688,10 @@ retry: + */ + oom_status = mem_cgroup_oom(mem_over_limit, gfp_mask, + get_order(nr_pages * PAGE_SIZE)); +- switch (oom_status) { +- case OOM_SUCCESS: ++ if (oom_status == OOM_SUCCESS) { ++ passed_oom = true; + nr_retries = MAX_RECLAIM_RETRIES; + goto retry; +- case OOM_FAILED: +- goto force; +- default: +- goto nomem; + } + nomem: + if (!(gfp_mask & __GFP_NOFAIL)) +@@ -3518,8 +3562,7 @@ static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) + unsigned long val; + + if (mem_cgroup_is_root(memcg)) { +- /* mem_cgroup_threshold() calls here from irqsafe context */ +- cgroup_rstat_flush_irqsafe(memcg->css.cgroup); ++ mem_cgroup_flush_stats(); + val = memcg_page_state(memcg, NR_FILE_PAGES) + + memcg_page_state(memcg, NR_ANON_MAPPED); + if (swap) +@@ -3900,7 +3943,7 @@ static int memcg_numa_stat_show(struct seq_file *m, void *v) + int nid; + struct mem_cgroup *memcg = mem_cgroup_from_seq(m); + +- cgroup_rstat_flush(memcg->css.cgroup); ++ mem_cgroup_flush_stats(); + + for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) { + seq_printf(m, "%s=%lu", stat->name, +@@ -3972,7 +4015,7 @@ static int memcg_stat_show(struct seq_file *m, void *v) + + BUILD_BUG_ON(ARRAY_SIZE(memcg1_stat_names) != ARRAY_SIZE(memcg1_stats)); + +- cgroup_rstat_flush(memcg->css.cgroup); ++ mem_cgroup_flush_stats(); + + for (i = 0; i < ARRAY_SIZE(memcg1_stats); i++) { + unsigned long nr; +@@ -4475,7 +4518,7 @@ void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages, + struct mem_cgroup *memcg = mem_cgroup_from_css(wb->memcg_css); + struct mem_cgroup *parent; + +- cgroup_rstat_flush_irqsafe(memcg->css.cgroup); ++ mem_cgroup_flush_stats(); + + *pdirty = memcg_page_state(memcg, NR_FILE_DIRTY); + *pwriteback = memcg_page_state(memcg, NR_WRITEBACK); +@@ -5341,21 +5384,6 @@ static void mem_cgroup_css_reset(struct cgroup_subsys_state *css) + memcg_wb_domain_size_changed(memcg); + } + +-void mem_cgroup_flush_stats(void) +-{ +- if (!spin_trylock(&stats_flush_lock)) +- return; +- +- cgroup_rstat_flush_irqsafe(root_mem_cgroup->css.cgroup); +- spin_unlock(&stats_flush_lock); +-} +- +-static void flush_memcg_stats_dwork(struct work_struct *w) +-{ +- mem_cgroup_flush_stats(); +- queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ); +-} +- + static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu) + { + struct mem_cgroup *memcg = mem_cgroup_from_css(css); +@@ -6373,7 +6401,7 @@ static int memory_numa_stat_show(struct seq_file *m, void *v) + int i; + struct mem_cgroup *memcg = mem_cgroup_from_seq(m); + +- cgroup_rstat_flush(memcg->css.cgroup); ++ mem_cgroup_flush_stats(); + + for (i = 0; i < ARRAY_SIZE(memory_stats); i++) { + int nid; +diff --git a/mm/memfd.c b/mm/memfd.c +index 081dd33e6a61b..475d095dd7f53 100644 +--- a/mm/memfd.c ++++ b/mm/memfd.c +@@ -31,20 +31,28 @@ + static void memfd_tag_pins(struct xa_state *xas) + { + struct page *page; +- unsigned int tagged = 0; ++ int latency = 0; ++ int cache_count; + + lru_add_drain(); + + xas_lock_irq(xas); + xas_for_each(xas, page, ULONG_MAX) { +- if (xa_is_value(page)) +- continue; +- page = find_subpage(page, xas->xa_index); +- if (page_count(page) - page_mapcount(page) > 1) ++ cache_count = 1; ++ if (!xa_is_value(page) && ++ PageTransHuge(page) && !PageHuge(page)) ++ cache_count = HPAGE_PMD_NR; ++ ++ if (!xa_is_value(page) && ++ page_count(page) - total_mapcount(page) != cache_count) + xas_set_mark(xas, MEMFD_TAG_PINNED); ++ if (cache_count != 1) ++ xas_set(xas, page->index + cache_count); + +- if (++tagged % XA_CHECK_SCHED) ++ latency += cache_count; ++ if (latency < XA_CHECK_SCHED) + continue; ++ latency = 0; + + xas_pause(xas); + xas_unlock_irq(xas); +@@ -73,7 +81,8 @@ static int memfd_wait_for_pins(struct address_space *mapping) + + error = 0; + for (scan = 0; scan <= LAST_SCAN; scan++) { +- unsigned int tagged = 0; ++ int latency = 0; ++ int cache_count; + + if (!xas_marked(&xas, MEMFD_TAG_PINNED)) + break; +@@ -87,10 +96,14 @@ static int memfd_wait_for_pins(struct address_space *mapping) + xas_lock_irq(&xas); + xas_for_each_marked(&xas, page, ULONG_MAX, MEMFD_TAG_PINNED) { + bool clear = true; +- if (xa_is_value(page)) +- continue; +- page = find_subpage(page, xas.xa_index); +- if (page_count(page) - page_mapcount(page) != 1) { ++ ++ cache_count = 1; ++ if (!xa_is_value(page) && ++ PageTransHuge(page) && !PageHuge(page)) ++ cache_count = HPAGE_PMD_NR; ++ ++ if (!xa_is_value(page) && cache_count != ++ page_count(page) - total_mapcount(page)) { + /* + * On the last scan, we clean up all those tags + * we inserted; but make a note that we still +@@ -103,8 +116,11 @@ static int memfd_wait_for_pins(struct address_space *mapping) + } + if (clear) + xas_clear_mark(&xas, MEMFD_TAG_PINNED); +- if (++tagged % XA_CHECK_SCHED) ++ ++ latency += cache_count; ++ if (latency < XA_CHECK_SCHED) + continue; ++ latency = 0; + + xas_pause(&xas); + xas_unlock_irq(&xas); +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index bdbbb32211a58..f66977a171966 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -1437,17 +1437,12 @@ static int memory_failure_hugetlb(unsigned long pfn, int flags) + if (!(flags & MF_COUNT_INCREASED)) { + res = get_hwpoison_page(p, flags); + if (!res) { +- /* +- * Check "filter hit" and "race with other subpage." +- */ + lock_page(head); +- if (PageHWPoison(head)) { +- if ((hwpoison_filter(p) && TestClearPageHWPoison(p)) +- || (p != head && TestSetPageHWPoison(head))) { ++ if (hwpoison_filter(p)) { ++ if (TestClearPageHWPoison(head)) + num_poisoned_pages_dec(); +- unlock_page(head); +- return 0; +- } ++ unlock_page(head); ++ return 0; + } + unlock_page(head); + res = MF_FAILED; +@@ -2206,6 +2201,7 @@ retry: + } else if (ret == 0) { + if (soft_offline_free_page(page) && try_again) { + try_again = false; ++ flags &= ~MF_COUNT_INCREASED; + goto retry; + } + } +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index d12e0608fced2..fa9ed9c98739a 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -2140,8 +2140,7 @@ struct page *alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma, + * memory with both reclaim and compact as well. + */ + if (!page && (gfp & __GFP_DIRECT_RECLAIM)) +- page = __alloc_pages_node(hpage_node, +- gfp, order); ++ page = __alloc_pages(gfp, order, hpage_node, nmask); + + goto out; + } +diff --git a/mm/mprotect.c b/mm/mprotect.c +index 883e2cc85cad8..ed18dc49533f6 100644 +--- a/mm/mprotect.c ++++ b/mm/mprotect.c +@@ -94,7 +94,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, + + /* Also skip shared copy-on-write pages */ + if (is_cow_mapping(vma->vm_flags) && +- page_mapcount(page) != 1) ++ page_count(page) != 1) + continue; + + /* +diff --git a/mm/oom_kill.c b/mm/oom_kill.c +index 989f35a2bbb1d..bfa9e348c3a3a 100644 +--- a/mm/oom_kill.c ++++ b/mm/oom_kill.c +@@ -1120,27 +1120,24 @@ bool out_of_memory(struct oom_control *oc) + } + + /* +- * The pagefault handler calls here because it is out of memory, so kill a +- * memory-hogging task. If oom_lock is held by somebody else, a parallel oom +- * killing is already in progress so do nothing. ++ * The pagefault handler calls here because some allocation has failed. We have ++ * to take care of the memcg OOM here because this is the only safe context without ++ * any locks held but let the oom killer triggered from the allocation context care ++ * about the global OOM. + */ + void pagefault_out_of_memory(void) + { +- struct oom_control oc = { +- .zonelist = NULL, +- .nodemask = NULL, +- .memcg = NULL, +- .gfp_mask = 0, +- .order = 0, +- }; ++ static DEFINE_RATELIMIT_STATE(pfoom_rs, DEFAULT_RATELIMIT_INTERVAL, ++ DEFAULT_RATELIMIT_BURST); + + if (mem_cgroup_oom_synchronize(true)) + return; + +- if (!mutex_trylock(&oom_lock)) ++ if (fatal_signal_pending(current)) + return; +- out_of_memory(&oc); +- mutex_unlock(&oom_lock); ++ ++ if (__ratelimit(&pfoom_rs)) ++ pr_warn("Huh VM_FAULT_OOM leaked out to the #PF handler. Retrying PF\n"); + } + + SYSCALL_DEFINE2(process_mrelease, int, pidfd, unsigned int, flags) +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 23d3339ac4e8e..7773bae3b6edb 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -4210,7 +4210,9 @@ void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...) + va_list args; + static DEFINE_RATELIMIT_STATE(nopage_rs, 10*HZ, 1); + +- if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs)) ++ if ((gfp_mask & __GFP_NOWARN) || ++ !__ratelimit(&nopage_rs) || ++ ((gfp_mask & __GFP_DMA) && !has_managed_dma())) + return; + + va_start(args, fmt); +@@ -9449,3 +9451,18 @@ bool take_page_off_buddy(struct page *page) + return ret; + } + #endif ++ ++#ifdef CONFIG_ZONE_DMA ++bool has_managed_dma(void) ++{ ++ struct pglist_data *pgdat; ++ ++ for_each_online_pgdat(pgdat) { ++ struct zone *zone = &pgdat->node_zones[ZONE_DMA]; ++ ++ if (managed_zone(zone)) ++ return true; ++ } ++ return false; ++} ++#endif /* CONFIG_ZONE_DMA */ +diff --git a/mm/shmem.c b/mm/shmem.c +index b5860f4a2738e..1609a8daba26e 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -555,7 +555,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, + struct shmem_inode_info *info; + struct page *page; + unsigned long batch = sc ? sc->nr_to_scan : 128; +- int removed = 0, split = 0; ++ int split = 0; + + if (list_empty(&sbinfo->shrinklist)) + return SHRINK_STOP; +@@ -570,7 +570,6 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, + /* inode is about to be evicted */ + if (!inode) { + list_del_init(&info->shrinklist); +- removed++; + goto next; + } + +@@ -578,12 +577,12 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, + if (round_up(inode->i_size, PAGE_SIZE) == + round_up(inode->i_size, HPAGE_PMD_SIZE)) { + list_move(&info->shrinklist, &to_remove); +- removed++; + goto next; + } + + list_move(&info->shrinklist, &list); + next: ++ sbinfo->shrinklist_len--; + if (!--batch) + break; + } +@@ -603,7 +602,7 @@ next: + inode = &info->vfs_inode; + + if (nr_to_split && split >= nr_to_split) +- goto leave; ++ goto move_back; + + page = find_get_page(inode->i_mapping, + (inode->i_size & HPAGE_PMD_MASK) >> PAGE_SHIFT); +@@ -617,38 +616,44 @@ next: + } + + /* +- * Leave the inode on the list if we failed to lock +- * the page at this time. ++ * Move the inode on the list back to shrinklist if we failed ++ * to lock the page at this time. + * + * Waiting for the lock may lead to deadlock in the + * reclaim path. + */ + if (!trylock_page(page)) { + put_page(page); +- goto leave; ++ goto move_back; + } + + ret = split_huge_page(page); + unlock_page(page); + put_page(page); + +- /* If split failed leave the inode on the list */ ++ /* If split failed move the inode on the list back to shrinklist */ + if (ret) +- goto leave; ++ goto move_back; + + split++; + drop: + list_del_init(&info->shrinklist); +- removed++; +-leave: ++ goto put; ++move_back: ++ /* ++ * Make sure the inode is either on the global list or deleted ++ * from any local list before iput() since it could be deleted ++ * in another thread once we put the inode (then the local list ++ * is corrupted). ++ */ ++ spin_lock(&sbinfo->shrinklist_lock); ++ list_move(&info->shrinklist, &sbinfo->shrinklist); ++ sbinfo->shrinklist_len++; ++ spin_unlock(&sbinfo->shrinklist_lock); ++put: + iput(inode); + } + +- spin_lock(&sbinfo->shrinklist_lock); +- list_splice_tail(&list, &sbinfo->shrinklist); +- sbinfo->shrinklist_len -= removed; +- spin_unlock(&sbinfo->shrinklist_lock); +- + return split; + } + +diff --git a/mm/slab.h b/mm/slab.h +index 58c01a34e5b86..56ad7eea3ddfb 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -147,7 +147,7 @@ static inline slab_flags_t kmem_cache_flags(unsigned int object_size, + #define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE | SLAB_RECLAIM_ACCOUNT | \ + SLAB_TEMPORARY | SLAB_ACCOUNT) + #else +-#define SLAB_CACHE_FLAGS (0) ++#define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE) + #endif + + /* Common flags available with current configuration */ +diff --git a/mm/slub.c b/mm/slub.c +index d8f77346376d8..ca6ba6bdf27b1 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -5072,6 +5072,7 @@ struct loc_track { + unsigned long max; + unsigned long count; + struct location *loc; ++ loff_t idx; + }; + + static struct dentry *slab_debugfs_root; +@@ -6035,11 +6036,11 @@ __initcall(slab_sysfs_init); + #if defined(CONFIG_SLUB_DEBUG) && defined(CONFIG_DEBUG_FS) + static int slab_debugfs_show(struct seq_file *seq, void *v) + { +- +- struct location *l; +- unsigned int idx = *(unsigned int *)v; + struct loc_track *t = seq->private; ++ struct location *l; ++ unsigned long idx; + ++ idx = (unsigned long) t->idx; + if (idx < t->count) { + l = &t->loc[idx]; + +@@ -6088,16 +6089,18 @@ static void *slab_debugfs_next(struct seq_file *seq, void *v, loff_t *ppos) + { + struct loc_track *t = seq->private; + +- v = ppos; +- ++*ppos; ++ t->idx = ++(*ppos); + if (*ppos <= t->count) +- return v; ++ return ppos; + + return NULL; + } + + static void *slab_debugfs_start(struct seq_file *seq, loff_t *ppos) + { ++ struct loc_track *t = seq->private; ++ ++ t->idx = *ppos; + return ppos; + } + +diff --git a/mm/util.c b/mm/util.c +index bacabe4469065..ea09dd33ab594 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -594,8 +594,10 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node) + return ret; + + /* Don't even allow crazy sizes */ +- if (WARN_ON_ONCE(size > INT_MAX)) ++ if (unlikely(size > INT_MAX)) { ++ WARN_ON_ONCE(!(flags & __GFP_NOWARN)); + return NULL; ++ } + + return __vmalloc_node(size, 1, flags, node, + __builtin_return_address(0)); +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index e8a807c781107..8375eecc55de5 100644 +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -3032,7 +3032,8 @@ again: + clear_vm_uninitialized_flag(area); + + size = PAGE_ALIGN(size); +- kmemleak_vmalloc(area, size, gfp_mask); ++ if (!(vm_flags & VM_DEFER_KMEMLEAK)) ++ kmemleak_vmalloc(area, size, gfp_mask); + + return addr; + +diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c +index 68e8831068f4b..b897ce3b399a1 100644 +--- a/mm/zsmalloc.c ++++ b/mm/zsmalloc.c +@@ -1830,10 +1830,11 @@ static inline void zs_pool_dec_isolated(struct zs_pool *pool) + VM_BUG_ON(atomic_long_read(&pool->isolated_pages) <= 0); + atomic_long_dec(&pool->isolated_pages); + /* +- * There's no possibility of racing, since wait_for_isolated_drain() +- * checks the isolated count under &class->lock after enqueuing +- * on migration_wait. ++ * Checking pool->destroying must happen after atomic_long_dec() ++ * for pool->isolated_pages above. Paired with the smp_mb() in ++ * zs_unregister_migration(). + */ ++ smp_mb__after_atomic(); + if (atomic_long_read(&pool->isolated_pages) == 0 && pool->destroying) + wake_up_all(&pool->migration_wait); + } +diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c +index 55275ef9a31a7..abaa5d96ded24 100644 +--- a/net/8021q/vlan.c ++++ b/net/8021q/vlan.c +@@ -123,9 +123,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) + } + + vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); +- +- /* Get rid of the vlan's reference to real_dev */ +- dev_put(real_dev); + } + + int vlan_check_real_dev(struct net_device *real_dev, +@@ -187,9 +184,6 @@ int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack) + if (err) + goto out_unregister_netdev; + +- /* Account for reference in struct vlan_dev_priv */ +- dev_hold(real_dev); +- + vlan_stacked_transfer_operstate(real_dev, dev, vlan); + linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ + +diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c +index 0c21d1fec8522..8602885c8a8e0 100644 +--- a/net/8021q/vlan_dev.c ++++ b/net/8021q/vlan_dev.c +@@ -615,6 +615,9 @@ static int vlan_dev_init(struct net_device *dev) + if (!vlan->vlan_pcpu_stats) + return -ENOMEM; + ++ /* Get vlan's reference to real_dev */ ++ dev_hold(real_dev); ++ + return 0; + } + +@@ -843,6 +846,9 @@ static void vlan_dev_free(struct net_device *dev) + + free_percpu(vlan->vlan_pcpu_stats); + vlan->vlan_pcpu_stats = NULL; ++ ++ /* Get rid of the vlan's reference to real_dev */ ++ dev_put(vlan->real_dev); + } + + void vlan_setup(struct net_device *dev) +diff --git a/net/9p/client.c b/net/9p/client.c +index 213f12ed76cd8..7973267ec8464 100644 +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -541,6 +541,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) + kfree(ename); + } else { + err = p9pdu_readf(&req->rc, c->proto_version, "d", &ecode); ++ if (err) ++ goto out_err; + err = -ecode; + + p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); +diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c +index 3ec1a51a6944e..432ac5a16f2e0 100644 +--- a/net/9p/trans_xen.c ++++ b/net/9p/trans_xen.c +@@ -304,9 +304,9 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv) + ref = priv->rings[i].intf->ref[j]; + gnttab_end_foreign_access(ref, 0, 0); + } +- free_pages((unsigned long)priv->rings[i].data.in, +- priv->rings[i].intf->ring_order - +- (PAGE_SHIFT - XEN_PAGE_SHIFT)); ++ free_pages_exact(priv->rings[i].data.in, ++ 1UL << (priv->rings[i].intf->ring_order + ++ XEN_PAGE_SHIFT)); + } + gnttab_end_foreign_access(priv->rings[i].ref, 0, 0); + free_page((unsigned long)priv->rings[i].intf); +@@ -345,8 +345,8 @@ static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev, + if (ret < 0) + goto out; + ring->ref = ret; +- bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, +- order - (PAGE_SHIFT - XEN_PAGE_SHIFT)); ++ bytes = alloc_pages_exact(1UL << (order + XEN_PAGE_SHIFT), ++ GFP_KERNEL | __GFP_ZERO); + if (!bytes) { + ret = -ENOMEM; + goto out; +@@ -377,9 +377,7 @@ out: + if (bytes) { + for (i--; i >= 0; i--) + gnttab_end_foreign_access(ring->intf->ref[i], 0, 0); +- free_pages((unsigned long)bytes, +- ring->intf->ring_order - +- (PAGE_SHIFT - XEN_PAGE_SHIFT)); ++ free_pages_exact(bytes, 1UL << (order + XEN_PAGE_SHIFT)); + } + gnttab_end_foreign_access(ring->ref, 0, 0); + free_page((unsigned long)ring->intf); +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 2631efc6e359f..ea3431ac46a14 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -77,6 +77,7 @@ static void ax25_kill_by_device(struct net_device *dev) + { + ax25_dev *ax25_dev; + ax25_cb *s; ++ struct sock *sk; + + if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) + return; +@@ -85,11 +86,15 @@ static void ax25_kill_by_device(struct net_device *dev) + again: + ax25_for_each(s, &ax25_list) { + if (s->ax25_dev == ax25_dev) { +- s->ax25_dev = NULL; ++ sk = s->sk; ++ sock_hold(sk); + spin_unlock_bh(&ax25_list_lock); ++ lock_sock(sk); ++ s->ax25_dev = NULL; ++ release_sock(sk); + ax25_disconnect(s, ENETUNREACH); + spin_lock_bh(&ax25_list_lock); +- ++ sock_put(sk); + /* The entry could have been deleted from the + * list meanwhile and thus the next pointer is + * no longer valid. Play it safe and restart +@@ -534,7 +539,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, + ax25_cb *ax25; + struct net_device *dev; + char devname[IFNAMSIZ]; +- unsigned long opt; ++ unsigned int opt; + int res = 0; + + if (level != SOL_AX25) +@@ -566,7 +571,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, + break; + + case AX25_T1: +- if (opt < 1 || opt > ULONG_MAX / HZ) { ++ if (opt < 1 || opt > UINT_MAX / HZ) { + res = -EINVAL; + break; + } +@@ -575,7 +580,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, + break; + + case AX25_T2: +- if (opt < 1 || opt > ULONG_MAX / HZ) { ++ if (opt < 1 || opt > UINT_MAX / HZ) { + res = -EINVAL; + break; + } +@@ -591,7 +596,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, + break; + + case AX25_T3: +- if (opt < 1 || opt > ULONG_MAX / HZ) { ++ if (opt < 1 || opt > UINT_MAX / HZ) { + res = -EINVAL; + break; + } +@@ -599,7 +604,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, + break; + + case AX25_IDLE: +- if (opt > ULONG_MAX / (60 * HZ)) { ++ if (opt > UINT_MAX / (60 * HZ)) { + res = -EINVAL; + break; + } +diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c +index 8a2b78f9c4b2c..35fadb9248498 100644 +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -149,22 +149,25 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) + struct net *net = dev_net(net_dev); + struct net_device *parent_dev; + struct net *parent_net; ++ int iflink; + bool ret; + + /* check if this is a batman-adv mesh interface */ + if (batadv_softif_is_valid(net_dev)) + return true; + +- /* no more parents..stop recursion */ +- if (dev_get_iflink(net_dev) == 0 || +- dev_get_iflink(net_dev) == net_dev->ifindex) ++ iflink = dev_get_iflink(net_dev); ++ if (iflink == 0) + return false; + + parent_net = batadv_getlink_net(net_dev, net); + ++ /* iflink to itself, most likely physical device */ ++ if (net == parent_net && iflink == net_dev->ifindex) ++ return false; ++ + /* recurse over the parent device */ +- parent_dev = __dev_get_by_index((struct net *)parent_net, +- dev_get_iflink(net_dev)); ++ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink); + /* if we got a NULL parent_dev there is something broken.. */ + if (!parent_dev) { + pr_err("Cannot find parent device\n"); +@@ -214,14 +217,15 @@ static struct net_device *batadv_get_real_netdevice(struct net_device *netdev) + struct net_device *real_netdev = NULL; + struct net *real_net; + struct net *net; +- int ifindex; ++ int iflink; + + ASSERT_RTNL(); + + if (!netdev) + return NULL; + +- if (netdev->ifindex == dev_get_iflink(netdev)) { ++ iflink = dev_get_iflink(netdev); ++ if (iflink == 0) { + dev_hold(netdev); + return netdev; + } +@@ -231,9 +235,16 @@ static struct net_device *batadv_get_real_netdevice(struct net_device *netdev) + goto out; + + net = dev_net(hard_iface->soft_iface); +- ifindex = dev_get_iflink(netdev); + real_net = batadv_getlink_net(netdev, net); +- real_netdev = dev_get_by_index(real_net, ifindex); ++ ++ /* iflink to itself, most likely physical device */ ++ if (net == real_net && netdev->ifindex == iflink) { ++ real_netdev = netdev; ++ dev_hold(real_netdev); ++ goto out; ++ } ++ ++ real_netdev = dev_get_by_index(real_net, iflink); + + out: + batadv_hardif_put(hard_iface); +diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c +index a3b6658ed7899..6e3419beca098 100644 +--- a/net/batman-adv/multicast.c ++++ b/net/batman-adv/multicast.c +@@ -1339,6 +1339,7 @@ batadv_mcast_forw_rtr_node_get(struct batadv_priv *bat_priv, + * @bat_priv: the bat priv with all the soft interface information + * @skb: The multicast packet to check + * @orig: an originator to be set to forward the skb to ++ * @is_routable: stores whether the destination is routable + * + * Return: the forwarding mode as enum batadv_forw_mode and in case of + * BATADV_FORW_SINGLE set the orig to the single originator the skb +@@ -1346,17 +1347,16 @@ batadv_mcast_forw_rtr_node_get(struct batadv_priv *bat_priv, + */ + enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, +- struct batadv_orig_node **orig) ++ struct batadv_orig_node **orig, int *is_routable) + { + int ret, tt_count, ip_count, unsnoop_count, total_count; + bool is_unsnoopable = false; + unsigned int mcast_fanout; + struct ethhdr *ethhdr; +- int is_routable = 0; + int rtr_count = 0; + + ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable, +- &is_routable); ++ is_routable); + if (ret == -ENOMEM) + return BATADV_FORW_NONE; + else if (ret < 0) +@@ -1369,7 +1369,7 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, + ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr); + unsnoop_count = !is_unsnoopable ? 0 : + atomic_read(&bat_priv->mcast.num_want_all_unsnoopables); +- rtr_count = batadv_mcast_forw_rtr_count(bat_priv, is_routable); ++ rtr_count = batadv_mcast_forw_rtr_count(bat_priv, *is_routable); + + total_count = tt_count + ip_count + unsnoop_count + rtr_count; + +@@ -1689,6 +1689,7 @@ batadv_mcast_forw_want_rtr(struct batadv_priv *bat_priv, + * @bat_priv: the bat priv with all the soft interface information + * @skb: the multicast packet to transmit + * @vid: the vlan identifier ++ * @is_routable: stores whether the destination is routable + * + * Sends copies of a frame with multicast destination to any node that signaled + * interest in it, that is either via the translation table or the according +@@ -1701,7 +1702,7 @@ batadv_mcast_forw_want_rtr(struct batadv_priv *bat_priv, + * is neither IPv4 nor IPv6. NET_XMIT_SUCCESS otherwise. + */ + int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +- unsigned short vid) ++ unsigned short vid, int is_routable) + { + int ret; + +@@ -1717,12 +1718,16 @@ int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, + return ret; + } + ++ if (!is_routable) ++ goto skip_mc_router; ++ + ret = batadv_mcast_forw_want_rtr(bat_priv, skb, vid); + if (ret != NET_XMIT_SUCCESS) { + kfree_skb(skb); + return ret; + } + ++skip_mc_router: + consume_skb(skb); + return ret; + } +diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h +index 9fee5da083113..8aec818d0bf63 100644 +--- a/net/batman-adv/multicast.h ++++ b/net/batman-adv/multicast.h +@@ -43,7 +43,8 @@ enum batadv_forw_mode { + + enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, +- struct batadv_orig_node **mcast_single_orig); ++ struct batadv_orig_node **mcast_single_orig, ++ int *is_routable); + + int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, + struct sk_buff *skb, +@@ -51,7 +52,7 @@ int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, + struct batadv_orig_node *orig_node); + + int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +- unsigned short vid); ++ unsigned short vid, int is_routable); + + void batadv_mcast_init(struct batadv_priv *bat_priv); + +@@ -68,7 +69,8 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); + + static inline enum batadv_forw_mode + batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, +- struct batadv_orig_node **mcast_single_orig) ++ struct batadv_orig_node **mcast_single_orig, ++ int *is_routable) + { + return BATADV_FORW_ALL; + } +@@ -85,7 +87,7 @@ batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv, + + static inline int + batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb, +- unsigned short vid) ++ unsigned short vid, int is_routable) + { + kfree_skb(skb); + return NET_XMIT_DROP; +diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c +index 29276284d281c..00875e1d8c44c 100644 +--- a/net/batman-adv/netlink.c ++++ b/net/batman-adv/netlink.c +@@ -1368,21 +1368,21 @@ static const struct genl_small_ops batadv_netlink_ops[] = { + { + .cmd = BATADV_CMD_TP_METER, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .doit = batadv_netlink_tp_meter_start, + .internal_flags = BATADV_FLAG_NEED_MESH, + }, + { + .cmd = BATADV_CMD_TP_METER_CANCEL, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .doit = batadv_netlink_tp_meter_cancel, + .internal_flags = BATADV_FLAG_NEED_MESH, + }, + { + .cmd = BATADV_CMD_GET_ROUTING_ALGOS, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_algo_dump, + }, + { +@@ -1397,68 +1397,68 @@ static const struct genl_small_ops batadv_netlink_ops[] = { + { + .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_tt_local_dump, + }, + { + .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_tt_global_dump, + }, + { + .cmd = BATADV_CMD_GET_ORIGINATORS, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_orig_dump, + }, + { + .cmd = BATADV_CMD_GET_NEIGHBORS, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_hardif_neigh_dump, + }, + { + .cmd = BATADV_CMD_GET_GATEWAYS, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_gw_dump, + }, + { + .cmd = BATADV_CMD_GET_BLA_CLAIM, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_bla_claim_dump, + }, + { + .cmd = BATADV_CMD_GET_BLA_BACKBONE, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_bla_backbone_dump, + }, + { + .cmd = BATADV_CMD_GET_DAT_CACHE, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_dat_cache_dump, + }, + { + .cmd = BATADV_CMD_GET_MCAST_FLAGS, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .dumpit = batadv_mcast_flags_dump, + }, + { + .cmd = BATADV_CMD_SET_MESH, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .doit = batadv_netlink_set_mesh, + .internal_flags = BATADV_FLAG_NEED_MESH, + }, + { + .cmd = BATADV_CMD_SET_HARDIF, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .doit = batadv_netlink_set_hardif, + .internal_flags = BATADV_FLAG_NEED_MESH | + BATADV_FLAG_NEED_HARDIF, +@@ -1474,7 +1474,7 @@ static const struct genl_small_ops batadv_netlink_ops[] = { + { + .cmd = BATADV_CMD_SET_VLAN, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, +- .flags = GENL_ADMIN_PERM, ++ .flags = GENL_UNS_ADMIN_PERM, + .doit = batadv_netlink_set_vlan, + .internal_flags = BATADV_FLAG_NEED_MESH | + BATADV_FLAG_NEED_VLAN, +diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c +index 0604b02795731..6ab28b509d4bb 100644 +--- a/net/batman-adv/soft-interface.c ++++ b/net/batman-adv/soft-interface.c +@@ -198,6 +198,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, + int gw_mode; + enum batadv_forw_mode forw_mode = BATADV_FORW_SINGLE; + struct batadv_orig_node *mcast_single_orig = NULL; ++ int mcast_is_routable = 0; + int network_offset = ETH_HLEN; + __be16 proto; + +@@ -300,7 +301,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, + send: + if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { + forw_mode = batadv_mcast_forw_mode(bat_priv, skb, +- &mcast_single_orig); ++ &mcast_single_orig, ++ &mcast_is_routable); + if (forw_mode == BATADV_FORW_NONE) + goto dropped; + +@@ -359,7 +361,8 @@ send: + ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid, + mcast_single_orig); + } else if (forw_mode == BATADV_FORW_SOME) { +- ret = batadv_mcast_forw_send(bat_priv, skb, vid); ++ ret = batadv_mcast_forw_send(bat_priv, skb, vid, ++ mcast_is_routable); + } else { + if (batadv_dat_snoop_outgoing_arp_request(bat_priv, + skb)) +diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c +index 0a2d78e811cf5..83eb84e8e688f 100644 +--- a/net/bluetooth/cmtp/core.c ++++ b/net/bluetooth/cmtp/core.c +@@ -501,9 +501,7 @@ static int __init cmtp_init(void) + { + BT_INFO("CMTP (CAPI Emulation) ver %s", VERSION); + +- cmtp_init_sockets(); +- +- return 0; ++ return cmtp_init_sockets(); + } + + static void __exit cmtp_exit(void) +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 8a47a3017d61d..53f1b08017aab 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -742,7 +742,8 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt) + hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); + } + +- if (hdev->commands[38] & 0x80) { ++ if ((hdev->commands[38] & 0x80) && ++ !test_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks)) { + /* Read LE Min/Max Tx Power*/ + hci_req_add(req, HCI_OP_LE_READ_TRANSMIT_POWER, + 0, NULL); +@@ -3998,6 +3999,7 @@ int hci_register_dev(struct hci_dev *hdev) + return id; + + err_wqueue: ++ debugfs_remove_recursive(hdev->debugfs); + destroy_workqueue(hdev->workqueue); + destroy_workqueue(hdev->req_workqueue); + err: +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 0bca035bf2dcc..868a22df32850 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -1325,8 +1325,10 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, + &conn->le_conn_timeout, + conn->conn_timeout); + } else { +- if (adv) { +- adv->enabled = false; ++ if (cp->num_of_sets) { ++ if (adv) ++ adv->enabled = false; ++ + /* If just one instance was disabled check if there are + * any other instance enabled before clearing HCI_LE_ADV + */ +@@ -5780,7 +5782,13 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) + struct hci_ev_le_advertising_info *ev = ptr; + s8 rssi; + +- if (ev->length <= HCI_MAX_AD_LENGTH) { ++ if (ptr > (void *)skb_tail_pointer(skb) - sizeof(*ev)) { ++ bt_dev_err(hdev, "Malicious advertising data."); ++ break; ++ } ++ ++ if (ev->length <= HCI_MAX_AD_LENGTH && ++ ev->data + ev->length <= skb_tail_pointer(skb)) { + rssi = ev->data[ev->length]; + process_adv_report(hdev, ev->evt_type, &ev->bdaddr, + ev->bdaddr_type, NULL, 0, rssi, +diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c +index f15626607b2d6..1d34d330afd34 100644 +--- a/net/bluetooth/hci_request.c ++++ b/net/bluetooth/hci_request.c +@@ -2318,7 +2318,7 @@ int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance) + /* Set duration per instance since controller is responsible for + * scheduling it. + */ +- if (adv_instance && adv_instance->duration) { ++ if (adv_instance && adv_instance->timeout) { + u16 duration = adv_instance->timeout * MSEC_PER_SEC; + + /* Time = N * 10 ms */ +diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c +index 7827639ecf5c3..4e3e0451b08c1 100644 +--- a/net/bluetooth/hci_sysfs.c ++++ b/net/bluetooth/hci_sysfs.c +@@ -86,6 +86,8 @@ static void bt_host_release(struct device *dev) + + if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) + hci_release_dev(hdev); ++ else ++ kfree(hdev); + module_put(THIS_MODULE); + } + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index c99d65ef13b1e..d2c6785205992 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -161,7 +161,11 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) + break; + } + +- if (chan->psm && bdaddr_type_is_le(chan->src_type)) ++ /* Use L2CAP_MODE_LE_FLOWCTL (CoC) in case of LE address and ++ * L2CAP_MODE_EXT_FLOWCTL (ECRED) has not been set. ++ */ ++ if (chan->psm && bdaddr_type_is_le(chan->src_type) && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) + chan->mode = L2CAP_MODE_LE_FLOWCTL; + + chan->state = BT_BOUND; +@@ -172,6 +176,21 @@ done: + return err; + } + ++static void l2cap_sock_init_pid(struct sock *sk) ++{ ++ struct l2cap_chan *chan = l2cap_pi(sk)->chan; ++ ++ /* Only L2CAP_MODE_EXT_FLOWCTL ever need to access the PID in order to ++ * group the channels being requested. ++ */ ++ if (chan->mode != L2CAP_MODE_EXT_FLOWCTL) ++ return; ++ ++ spin_lock(&sk->sk_peer_lock); ++ sk->sk_peer_pid = get_pid(task_tgid(current)); ++ spin_unlock(&sk->sk_peer_lock); ++} ++ + static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, + int alen, int flags) + { +@@ -240,9 +259,15 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, + return -EINVAL; + } + +- if (chan->psm && bdaddr_type_is_le(chan->src_type) && !chan->mode) ++ /* Use L2CAP_MODE_LE_FLOWCTL (CoC) in case of LE address and ++ * L2CAP_MODE_EXT_FLOWCTL (ECRED) has not been set. ++ */ ++ if (chan->psm && bdaddr_type_is_le(chan->src_type) && ++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) + chan->mode = L2CAP_MODE_LE_FLOWCTL; + ++ l2cap_sock_init_pid(sk); ++ + err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), + &la.l2_bdaddr, la.l2_bdaddr_type); + if (err) +@@ -298,6 +323,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) + goto done; + } + ++ l2cap_sock_init_pid(sk); ++ + sk->sk_max_ack_backlog = backlog; + sk->sk_ack_backlog = 0; + +@@ -876,6 +903,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, + struct l2cap_conn *conn; + int len, err = 0; + u32 opt; ++ u16 mtu; ++ u8 mode; + + BT_DBG("sk %p", sk); + +@@ -1058,16 +1087,16 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, + break; + } + +- if (copy_from_sockptr(&opt, optval, sizeof(u16))) { ++ if (copy_from_sockptr(&mtu, optval, sizeof(u16))) { + err = -EFAULT; + break; + } + + if (chan->mode == L2CAP_MODE_EXT_FLOWCTL && + sk->sk_state == BT_CONNECTED) +- err = l2cap_chan_reconfigure(chan, opt); ++ err = l2cap_chan_reconfigure(chan, mtu); + else +- chan->imtu = opt; ++ chan->imtu = mtu; + + break; + +@@ -1089,14 +1118,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, + break; + } + +- if (copy_from_sockptr(&opt, optval, sizeof(u8))) { ++ if (copy_from_sockptr(&mode, optval, sizeof(u8))) { + err = -EFAULT; + break; + } + +- BT_DBG("opt %u", opt); ++ BT_DBG("mode %u", mode); + +- err = l2cap_set_mode(chan, opt); ++ err = l2cap_set_mode(chan, mode); + if (err) + break; + +@@ -1508,6 +1537,9 @@ static void l2cap_sock_close_cb(struct l2cap_chan *chan) + { + struct sock *sk = chan->data; + ++ if (!sk) ++ return; ++ + l2cap_sock_kill(sk); + } + +@@ -1516,6 +1548,9 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) + struct sock *sk = chan->data; + struct sock *parent; + ++ if (!sk) ++ return; ++ + BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); + + /* This callback can be called both for server (BT_LISTEN) +@@ -1707,8 +1742,10 @@ static void l2cap_sock_destruct(struct sock *sk) + { + BT_DBG("sk %p", sk); + +- if (l2cap_pi(sk)->chan) ++ if (l2cap_pi(sk)->chan) { ++ l2cap_pi(sk)->chan->data = NULL; + l2cap_chan_put(l2cap_pi(sk)->chan); ++ } + + if (l2cap_pi(sk)->rx_busy_skb) { + kfree_skb(l2cap_pi(sk)->rx_busy_skb); +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index cea01e275f1ea..f09f0a78eb7be 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -3806,7 +3806,7 @@ static const u8 rpa_resolution_uuid[16] = { + static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev, + void *data, u16 data_len) + { +- char buf[62]; /* Enough space for 3 features */ ++ char buf[62]; /* Enough space for 3 features */ + struct mgmt_rp_read_exp_features_info *rp = (void *)buf; + u16 idx = 0; + u32 flags; +@@ -3892,150 +3892,186 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip) + } + #endif + +-static int set_exp_feature(struct sock *sk, struct hci_dev *hdev, +- void *data, u16 data_len) ++#define EXP_FEAT(_uuid, _set_func) \ ++{ \ ++ .uuid = _uuid, \ ++ .set_func = _set_func, \ ++} ++ ++/* The zero key uuid is special. Multiple exp features are set through it. */ ++static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev, ++ struct mgmt_cp_set_exp_feature *cp, u16 data_len) + { +- struct mgmt_cp_set_exp_feature *cp = data; + struct mgmt_rp_set_exp_feature rp; + +- bt_dev_dbg(hdev, "sock %p", sk); +- +- if (!memcmp(cp->uuid, ZERO_KEY, 16)) { +- memset(rp.uuid, 0, 16); +- rp.flags = cpu_to_le32(0); ++ memset(rp.uuid, 0, 16); ++ rp.flags = cpu_to_le32(0); + + #ifdef CONFIG_BT_FEATURE_DEBUG +- if (!hdev) { +- bool changed = bt_dbg_get(); ++ if (!hdev) { ++ bool changed = bt_dbg_get(); + +- bt_dbg_set(false); ++ bt_dbg_set(false); + +- if (changed) +- exp_debug_feature_changed(false, sk); +- } ++ if (changed) ++ exp_debug_feature_changed(false, sk); ++ } + #endif + +- if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) { +- bool changed = hci_dev_test_flag(hdev, +- HCI_ENABLE_LL_PRIVACY); +- +- hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY); ++ if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) { ++ bool changed; + +- if (changed) +- exp_ll_privacy_feature_changed(false, hdev, sk); +- } ++ changed = hci_dev_test_and_clear_flag(hdev, ++ HCI_ENABLE_LL_PRIVACY); ++ if (changed) ++ exp_ll_privacy_feature_changed(false, hdev, sk); ++ } + +- hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS); ++ hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS); + +- return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE, +- MGMT_OP_SET_EXP_FEATURE, 0, +- &rp, sizeof(rp)); +- } ++ return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE, ++ MGMT_OP_SET_EXP_FEATURE, 0, ++ &rp, sizeof(rp)); ++} + + #ifdef CONFIG_BT_FEATURE_DEBUG +- if (!memcmp(cp->uuid, debug_uuid, 16)) { +- bool val, changed; +- int err; ++static int set_debug_func(struct sock *sk, struct hci_dev *hdev, ++ struct mgmt_cp_set_exp_feature *cp, u16 data_len) ++{ ++ struct mgmt_rp_set_exp_feature rp; + +- /* Command requires to use the non-controller index */ +- if (hdev) +- return mgmt_cmd_status(sk, hdev->id, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_INVALID_INDEX); ++ bool val, changed; ++ int err; + +- /* Parameters are limited to a single octet */ +- if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1) +- return mgmt_cmd_status(sk, MGMT_INDEX_NONE, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_INVALID_PARAMS); ++ /* Command requires to use the non-controller index */ ++ if (hdev) ++ return mgmt_cmd_status(sk, hdev->id, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_INVALID_INDEX); + +- /* Only boolean on/off is supported */ +- if (cp->param[0] != 0x00 && cp->param[0] != 0x01) +- return mgmt_cmd_status(sk, MGMT_INDEX_NONE, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_INVALID_PARAMS); ++ /* Parameters are limited to a single octet */ ++ if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1) ++ return mgmt_cmd_status(sk, MGMT_INDEX_NONE, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_INVALID_PARAMS); + +- val = !!cp->param[0]; +- changed = val ? !bt_dbg_get() : bt_dbg_get(); +- bt_dbg_set(val); ++ /* Only boolean on/off is supported */ ++ if (cp->param[0] != 0x00 && cp->param[0] != 0x01) ++ return mgmt_cmd_status(sk, MGMT_INDEX_NONE, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_INVALID_PARAMS); + +- memcpy(rp.uuid, debug_uuid, 16); +- rp.flags = cpu_to_le32(val ? BIT(0) : 0); ++ val = !!cp->param[0]; ++ changed = val ? !bt_dbg_get() : bt_dbg_get(); ++ bt_dbg_set(val); + +- hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS); ++ memcpy(rp.uuid, debug_uuid, 16); ++ rp.flags = cpu_to_le32(val ? BIT(0) : 0); + +- err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, +- MGMT_OP_SET_EXP_FEATURE, 0, +- &rp, sizeof(rp)); ++ hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS); + +- if (changed) +- exp_debug_feature_changed(val, sk); ++ err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, ++ MGMT_OP_SET_EXP_FEATURE, 0, ++ &rp, sizeof(rp)); + +- return err; +- } ++ if (changed) ++ exp_debug_feature_changed(val, sk); ++ ++ return err; ++} + #endif + +- if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) { +- bool val, changed; +- int err; +- u32 flags; ++static int set_rpa_resolution_func(struct sock *sk, struct hci_dev *hdev, ++ struct mgmt_cp_set_exp_feature *cp, ++ u16 data_len) ++{ ++ struct mgmt_rp_set_exp_feature rp; ++ bool val, changed; ++ int err; ++ u32 flags; + +- /* Command requires to use the controller index */ +- if (!hdev) +- return mgmt_cmd_status(sk, MGMT_INDEX_NONE, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_INVALID_INDEX); ++ /* Command requires to use the controller index */ ++ if (!hdev) ++ return mgmt_cmd_status(sk, MGMT_INDEX_NONE, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_INVALID_INDEX); + +- /* Changes can only be made when controller is powered down */ +- if (hdev_is_powered(hdev)) +- return mgmt_cmd_status(sk, hdev->id, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_REJECTED); ++ /* Changes can only be made when controller is powered down */ ++ if (hdev_is_powered(hdev)) ++ return mgmt_cmd_status(sk, hdev->id, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_REJECTED); + +- /* Parameters are limited to a single octet */ +- if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1) +- return mgmt_cmd_status(sk, hdev->id, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_INVALID_PARAMS); ++ /* Parameters are limited to a single octet */ ++ if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1) ++ return mgmt_cmd_status(sk, hdev->id, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_INVALID_PARAMS); + +- /* Only boolean on/off is supported */ +- if (cp->param[0] != 0x00 && cp->param[0] != 0x01) +- return mgmt_cmd_status(sk, hdev->id, +- MGMT_OP_SET_EXP_FEATURE, +- MGMT_STATUS_INVALID_PARAMS); ++ /* Only boolean on/off is supported */ ++ if (cp->param[0] != 0x00 && cp->param[0] != 0x01) ++ return mgmt_cmd_status(sk, hdev->id, ++ MGMT_OP_SET_EXP_FEATURE, ++ MGMT_STATUS_INVALID_PARAMS); + +- val = !!cp->param[0]; ++ val = !!cp->param[0]; + +- if (val) { +- changed = !hci_dev_test_flag(hdev, ++ if (val) { ++ changed = !hci_dev_test_and_set_flag(hdev, + HCI_ENABLE_LL_PRIVACY); +- hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY); +- hci_dev_clear_flag(hdev, HCI_ADVERTISING); ++ hci_dev_clear_flag(hdev, HCI_ADVERTISING); + +- /* Enable LL privacy + supported settings changed */ +- flags = BIT(0) | BIT(1); +- } else { +- changed = hci_dev_test_flag(hdev, +- HCI_ENABLE_LL_PRIVACY); +- hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY); ++ /* Enable LL privacy + supported settings changed */ ++ flags = BIT(0) | BIT(1); ++ } else { ++ changed = hci_dev_test_and_clear_flag(hdev, ++ HCI_ENABLE_LL_PRIVACY); + +- /* Disable LL privacy + supported settings changed */ +- flags = BIT(1); +- } ++ /* Disable LL privacy + supported settings changed */ ++ flags = BIT(1); ++ } + +- memcpy(rp.uuid, rpa_resolution_uuid, 16); +- rp.flags = cpu_to_le32(flags); ++ memcpy(rp.uuid, rpa_resolution_uuid, 16); ++ rp.flags = cpu_to_le32(flags); + +- hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS); ++ hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS); + +- err = mgmt_cmd_complete(sk, hdev->id, +- MGMT_OP_SET_EXP_FEATURE, 0, +- &rp, sizeof(rp)); ++ err = mgmt_cmd_complete(sk, hdev->id, ++ MGMT_OP_SET_EXP_FEATURE, 0, ++ &rp, sizeof(rp)); + +- if (changed) +- exp_ll_privacy_feature_changed(val, hdev, sk); ++ if (changed) ++ exp_ll_privacy_feature_changed(val, hdev, sk); + +- return err; ++ return err; ++} ++ ++static const struct mgmt_exp_feature { ++ const u8 *uuid; ++ int (*set_func)(struct sock *sk, struct hci_dev *hdev, ++ struct mgmt_cp_set_exp_feature *cp, u16 data_len); ++} exp_features[] = { ++ EXP_FEAT(ZERO_KEY, set_zero_key_func), ++#ifdef CONFIG_BT_FEATURE_DEBUG ++ EXP_FEAT(debug_uuid, set_debug_func), ++#endif ++ EXP_FEAT(rpa_resolution_uuid, set_rpa_resolution_func), ++ ++ /* end with a null feature */ ++ EXP_FEAT(NULL, NULL) ++}; ++ ++static int set_exp_feature(struct sock *sk, struct hci_dev *hdev, ++ void *data, u16 data_len) ++{ ++ struct mgmt_cp_set_exp_feature *cp = data; ++ size_t i = 0; ++ ++ bt_dev_dbg(hdev, "sock %p", sk); ++ ++ for (i = 0; exp_features[i].uuid; i++) { ++ if (!memcmp(cp->uuid, exp_features[i].uuid, 16)) ++ return exp_features[i].set_func(sk, hdev, cp, data_len); + } + + return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE, +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 98a8815865128..6e047e178c0ab 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -133,6 +133,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) + return NULL; + + spin_lock_init(&conn->lock); ++ INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout); + + hcon->sco_data = conn; + conn->hcon = hcon; +@@ -187,20 +188,21 @@ static void sco_conn_del(struct hci_conn *hcon, int err) + /* Kill socket */ + sco_conn_lock(conn); + sk = conn->sk; ++ if (sk) ++ sock_hold(sk); + sco_conn_unlock(conn); + + if (sk) { +- sock_hold(sk); + lock_sock(sk); + sco_sock_clear_timer(sk); + sco_chan_del(sk, err); + release_sock(sk); + sock_put(sk); +- +- /* Ensure no more work items will run before freeing conn. */ +- cancel_delayed_work_sync(&conn->timeout_work); + } + ++ /* Ensure no more work items will run before freeing conn. */ ++ cancel_delayed_work_sync(&conn->timeout_work); ++ + hcon->sco_data = NULL; + kfree(conn); + } +@@ -213,8 +215,6 @@ static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, + sco_pi(sk)->conn = conn; + conn->sk = sk; + +- INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout); +- + if (parent) + bt_accept_enqueue(parent, sk, true); + } +@@ -280,7 +280,8 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk) + return err; + } + +-static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) ++static int sco_send_frame(struct sock *sk, void *buf, int len, ++ unsigned int msg_flags) + { + struct sco_conn *conn = sco_pi(sk)->conn; + struct sk_buff *skb; +@@ -292,15 +293,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) + + BT_DBG("sk %p len %d", sk, len); + +- skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); ++ skb = bt_skb_send_alloc(sk, len, msg_flags & MSG_DONTWAIT, &err); + if (!skb) + return err; + +- if (memcpy_from_msg(skb_put(skb, len), msg, len)) { +- kfree_skb(skb); +- return -EFAULT; +- } +- ++ memcpy(skb_put(skb, len), buf, len); + hci_send_sco(conn->hcon, skb); + + return len; +@@ -725,6 +722,7 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg, + size_t len) + { + struct sock *sk = sock->sk; ++ void *buf; + int err; + + BT_DBG("sock %p, sk %p", sock, sk); +@@ -736,14 +734,24 @@ static int sco_sock_sendmsg(struct socket *sock, struct msghdr *msg, + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + ++ buf = kmalloc(len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (memcpy_from_msg(buf, msg, len)) { ++ kfree(buf); ++ return -EFAULT; ++ } ++ + lock_sock(sk); + + if (sk->sk_state == BT_CONNECTED) +- err = sco_send_frame(sk, msg, len); ++ err = sco_send_frame(sk, buf, len, msg->msg_flags); + else + err = -ENOTCONN; + + release_sock(sk); ++ kfree(buf); + return err; + } + +diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c +index 793b0db9d9a36..9922497e59f8c 100644 +--- a/net/bridge/br_ioctl.c ++++ b/net/bridge/br_ioctl.c +@@ -71,7 +71,8 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, + + num = br_fdb_fillbuf(br, buf, maxnum, offset); + if (num > 0) { +- if (copy_to_user(userbuf, buf, num*sizeof(struct __fdb_entry))) ++ if (copy_to_user(userbuf, buf, ++ array_size(num, sizeof(struct __fdb_entry)))) + num = -EFAULT; + } + kfree(buf); +@@ -188,7 +189,7 @@ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user + return -ENOMEM; + + get_port_ifindices(br, indices, num); +- if (copy_to_user(argp, indices, num * sizeof(int))) ++ if (copy_to_user(argp, indices, array_size(num, sizeof(int)))) + num = -EFAULT; + kfree(indices); + return num; +@@ -336,7 +337,8 @@ static int old_deviceless(struct net *net, void __user *uarg) + + args[2] = get_bridge_ifindices(net, indices, args[2]); + +- ret = copy_to_user(uarg, indices, args[2]*sizeof(int)) ++ ret = copy_to_user((void __user *)args[1], indices, ++ array_size(args[2], sizeof(int))) + ? -EFAULT : args[2]; + + kfree(indices); +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index f3d751105343c..db4f2641d1cd1 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -82,6 +82,9 @@ static void br_multicast_find_del_pg(struct net_bridge *br, + struct net_bridge_port_group *pg); + static void __br_multicast_stop(struct net_bridge_mcast *brmctx); + ++static int br_mc_disabled_update(struct net_device *dev, bool value, ++ struct netlink_ext_ack *extack); ++ + static struct net_bridge_port_group * + br_sg_port_find(struct net_bridge *br, + struct net_bridge_port_group_sg_key *sg_p) +@@ -1156,6 +1159,7 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, + return mp; + + if (atomic_read(&br->mdb_hash_tbl.nelems) >= br->hash_max) { ++ br_mc_disabled_update(br->dev, false, NULL); + br_opt_toggle(br, BROPT_MULTICAST_ENABLED, false); + return ERR_PTR(-E2BIG); + } +@@ -4522,6 +4526,38 @@ int br_multicast_set_mld_version(struct net_bridge_mcast *brmctx, + } + #endif + ++void br_multicast_set_query_intvl(struct net_bridge_mcast *brmctx, ++ unsigned long val) ++{ ++ unsigned long intvl_jiffies = clock_t_to_jiffies(val); ++ ++ if (intvl_jiffies < BR_MULTICAST_QUERY_INTVL_MIN) { ++ br_info(brmctx->br, ++ "trying to set multicast query interval below minimum, setting to %lu (%ums)\n", ++ jiffies_to_clock_t(BR_MULTICAST_QUERY_INTVL_MIN), ++ jiffies_to_msecs(BR_MULTICAST_QUERY_INTVL_MIN)); ++ intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MIN; ++ } ++ ++ brmctx->multicast_query_interval = intvl_jiffies; ++} ++ ++void br_multicast_set_startup_query_intvl(struct net_bridge_mcast *brmctx, ++ unsigned long val) ++{ ++ unsigned long intvl_jiffies = clock_t_to_jiffies(val); ++ ++ if (intvl_jiffies < BR_MULTICAST_STARTUP_QUERY_INTVL_MIN) { ++ br_info(brmctx->br, ++ "trying to set multicast startup query interval below minimum, setting to %lu (%ums)\n", ++ jiffies_to_clock_t(BR_MULTICAST_STARTUP_QUERY_INTVL_MIN), ++ jiffies_to_msecs(BR_MULTICAST_STARTUP_QUERY_INTVL_MIN)); ++ intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MIN; ++ } ++ ++ brmctx->multicast_startup_query_interval = intvl_jiffies; ++} ++ + /** + * br_multicast_list_adjacent - Returns snooped multicast addresses + * @dev: The bridge port adjacent to which to retrieve addresses +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index 8edfb98ae1d58..68c0d0f928908 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -743,6 +743,9 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff + if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu) + mtu = nf_bridge->frag_max_size; + ++ nf_bridge_update_protocol(skb); ++ nf_bridge_push_encap_header(skb); ++ + if (skb_is_gso(skb) || skb->len + mtu_reserved <= mtu) { + nf_bridge_info_free(skb); + return br_dev_queue_push_xmit(net, sk, skb); +@@ -760,8 +763,6 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff + + IPCB(skb)->frag_max_size = nf_bridge->frag_max_size; + +- nf_bridge_update_protocol(skb); +- + data = this_cpu_ptr(&brnf_frag_data_storage); + + if (skb_vlan_tag_present(skb)) { +@@ -789,8 +790,6 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff + + IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size; + +- nf_bridge_update_protocol(skb); +- + data = this_cpu_ptr(&brnf_frag_data_storage); + data->encap_size = nf_bridge_encap_header_len(skb); + data->size = ETH_HLEN + data->encap_size; +diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c +index 5c6c4305ed235..e365cf82f0615 100644 +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -1357,7 +1357,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], + if (data[IFLA_BR_MCAST_QUERY_INTVL]) { + u64 val = nla_get_u64(data[IFLA_BR_MCAST_QUERY_INTVL]); + +- br->multicast_ctx.multicast_query_interval = clock_t_to_jiffies(val); ++ br_multicast_set_query_intvl(&br->multicast_ctx, val); + } + + if (data[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) { +@@ -1369,7 +1369,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], + if (data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) { + u64 val = nla_get_u64(data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]); + +- br->multicast_ctx.multicast_startup_query_interval = clock_t_to_jiffies(val); ++ br_multicast_set_startup_query_intvl(&br->multicast_ctx, val); + } + + if (data[IFLA_BR_MCAST_STATS_ENABLED]) { +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 37ca76406f1e8..bd218c2b2cd97 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -28,6 +28,8 @@ + #define BR_MAX_PORTS (1<<BR_PORT_BITS) + + #define BR_MULTICAST_DEFAULT_HASH_MAX 4096 ++#define BR_MULTICAST_QUERY_INTVL_MIN msecs_to_jiffies(1000) ++#define BR_MULTICAST_STARTUP_QUERY_INTVL_MIN BR_MULTICAST_QUERY_INTVL_MIN + + #define BR_HWDOM_MAX BITS_PER_LONG + +@@ -968,6 +970,10 @@ int br_multicast_dump_querier_state(struct sk_buff *skb, + int nest_attr); + size_t br_multicast_querier_state_size(void); + size_t br_rports_size(const struct net_bridge_mcast *brmctx); ++void br_multicast_set_query_intvl(struct net_bridge_mcast *brmctx, ++ unsigned long val); ++void br_multicast_set_startup_query_intvl(struct net_bridge_mcast *brmctx, ++ unsigned long val); + + static inline bool br_group_is_l2(const struct br_ip *group) + { +@@ -1152,9 +1158,9 @@ br_multicast_port_ctx_get_global(const struct net_bridge_mcast_port *pmctx) + static inline bool + br_multicast_ctx_vlan_global_disabled(const struct net_bridge_mcast *brmctx) + { +- return br_opt_get(brmctx->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED) && +- br_multicast_ctx_is_vlan(brmctx) && +- !(brmctx->vlan->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED); ++ return br_multicast_ctx_is_vlan(brmctx) && ++ (!br_opt_get(brmctx->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED) || ++ !(brmctx->vlan->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED)); + } + + static inline bool +@@ -1911,11 +1917,13 @@ static inline int br_cfm_status_fill_info(struct sk_buff *skb, + + static inline int br_cfm_mep_count(struct net_bridge *br, u32 *count) + { ++ *count = 0; + return -EOPNOTSUPP; + } + + static inline int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count) + { ++ *count = 0; + return -EOPNOTSUPP; + } + #endif +diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c +index d9a89ddd03310..7b0c19772111c 100644 +--- a/net/bridge/br_sysfs_br.c ++++ b/net/bridge/br_sysfs_br.c +@@ -658,7 +658,7 @@ static ssize_t multicast_query_interval_show(struct device *d, + static int set_query_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) + { +- br->multicast_ctx.multicast_query_interval = clock_t_to_jiffies(val); ++ br_multicast_set_query_intvl(&br->multicast_ctx, val); + return 0; + } + +@@ -706,7 +706,7 @@ static ssize_t multicast_startup_query_interval_show( + static int set_startup_query_interval(struct net_bridge *br, unsigned long val, + struct netlink_ext_ack *extack) + { +- br->multicast_ctx.multicast_startup_query_interval = clock_t_to_jiffies(val); ++ br_multicast_set_startup_query_intvl(&br->multicast_ctx, val); + return 0; + } + +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 19f65ab91a027..10e63ea6a13e1 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -560,10 +560,10 @@ static bool __allowed_ingress(const struct net_bridge *br, + !br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { + if (*state == BR_STATE_FORWARDING) { + *state = br_vlan_get_pvid_state(vg); +- return br_vlan_state_allowed(*state, true); +- } else { +- return true; ++ if (!br_vlan_state_allowed(*state, true)) ++ goto drop; + } ++ return true; + } + } + v = br_vlan_find(vg, *vid); +@@ -2105,7 +2105,8 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) + goto out_err; + } + err = br_vlan_dump_dev(dev, skb, cb, dump_flags); +- if (err && err != -EMSGSIZE) ++ /* if the dump completed without an error we return 0 here */ ++ if (err != -EMSGSIZE) + goto out_err; + } else { + for_each_netdev_rcu(net, dev) { +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index 8ffd4ed2563c6..a6382973b3e70 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -521,7 +521,7 @@ static int br_vlan_process_global_one_opts(const struct net_bridge *br, + u64 val; + + val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]); +- v->br_mcast_ctx.multicast_query_interval = clock_t_to_jiffies(val); ++ br_multicast_set_query_intvl(&v->br_mcast_ctx, val); + *changed = true; + } + if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]) { +@@ -535,7 +535,7 @@ static int br_vlan_process_global_one_opts(const struct net_bridge *br, + u64 val; + + val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]); +- v->br_mcast_ctx.multicast_startup_query_interval = clock_t_to_jiffies(val); ++ br_multicast_set_startup_query_intvl(&v->br_mcast_ctx, val); + *changed = true; + } + if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]) { +diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c +index eba0efe64d05a..fbf858ddec352 100644 +--- a/net/bridge/netfilter/nft_reject_bridge.c ++++ b/net/bridge/netfilter/nft_reject_bridge.c +@@ -49,7 +49,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct net *net, + { + struct sk_buff *nskb; + +- nskb = nf_reject_skb_v4_tcp_reset(net, oldskb, dev, hook); ++ nskb = nf_reject_skb_v4_tcp_reset(net, oldskb, NULL, hook); + if (!nskb) + return; + +@@ -65,7 +65,7 @@ static void nft_reject_br_send_v4_unreach(struct net *net, + { + struct sk_buff *nskb; + +- nskb = nf_reject_skb_v4_unreach(net, oldskb, dev, hook, code); ++ nskb = nf_reject_skb_v4_unreach(net, oldskb, NULL, hook, code); + if (!nskb) + return; + +@@ -81,7 +81,7 @@ static void nft_reject_br_send_v6_tcp_reset(struct net *net, + { + struct sk_buff *nskb; + +- nskb = nf_reject_skb_v6_tcp_reset(net, oldskb, dev, hook); ++ nskb = nf_reject_skb_v6_tcp_reset(net, oldskb, NULL, hook); + if (!nskb) + return; + +@@ -98,7 +98,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net, + { + struct sk_buff *nskb; + +- nskb = nf_reject_skb_v6_unreach(net, oldskb, dev, hook, code); ++ nskb = nf_reject_skb_v6_unreach(net, oldskb, NULL, hook, code); + if (!nskb) + return; + +diff --git a/net/can/isotp.c b/net/can/isotp.c +index df6968b28bf41..d2a430b6a13bd 100644 +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -56,6 +56,7 @@ + #include <linux/module.h> + #include <linux/init.h> + #include <linux/interrupt.h> ++#include <linux/spinlock.h> + #include <linux/hrtimer.h> + #include <linux/wait.h> + #include <linux/uio.h> +@@ -119,8 +120,8 @@ enum { + }; + + struct tpcon { +- int idx; +- int len; ++ unsigned int idx; ++ unsigned int len; + u32 state; + u8 bs; + u8 sn; +@@ -145,6 +146,7 @@ struct isotp_sock { + struct tpcon rx, tx; + struct list_head notifier; + wait_queue_head_t wait; ++ spinlock_t rx_lock; /* protect single thread state machine */ + }; + + static LIST_HEAD(isotp_notifier_list); +@@ -615,11 +617,17 @@ static void isotp_rcv(struct sk_buff *skb, void *data) + + n_pci_type = cf->data[ae] & 0xF0; + ++ /* Make sure the state changes and data structures stay consistent at ++ * CAN frame reception time. This locking is not needed in real world ++ * use cases but the inconsistency can be triggered with syzkaller. ++ */ ++ spin_lock(&so->rx_lock); ++ + if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) { + /* check rx/tx path half duplex expectations */ + if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) || + (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC)) +- return; ++ goto out_unlock; + } + + switch (n_pci_type) { +@@ -668,6 +676,9 @@ static void isotp_rcv(struct sk_buff *skb, void *data) + isotp_rcv_cf(sk, cf, ae, skb); + break; + } ++ ++out_unlock: ++ spin_unlock(&so->rx_lock); + } + + static void isotp_fill_dataframe(struct canfd_frame *cf, struct isotp_sock *so, +@@ -876,7 +887,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + + if (!size || size > MAX_MSG_LENGTH) { + err = -EINVAL; +- goto err_out; ++ goto err_out_drop; + } + + /* take care of a potential SF_DL ESC offset for TX_DL > 8 */ +@@ -886,24 +897,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + if ((so->opt.flags & CAN_ISOTP_SF_BROADCAST) && + (size > so->tx.ll_dl - SF_PCI_SZ4 - ae - off)) { + err = -EINVAL; +- goto err_out; ++ goto err_out_drop; + } + + err = memcpy_from_msg(so->tx.buf, msg, size); + if (err < 0) +- goto err_out; ++ goto err_out_drop; + + dev = dev_get_by_index(sock_net(sk), so->ifindex); + if (!dev) { + err = -ENXIO; +- goto err_out; ++ goto err_out_drop; + } + + skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv), + msg->msg_flags & MSG_DONTWAIT, &err); + if (!skb) { + dev_put(dev); +- goto err_out; ++ goto err_out_drop; + } + + can_skb_reserve(skb); +@@ -965,7 +976,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + if (err) { + pr_notice_once("can-isotp: %s: can_send_ret %pe\n", + __func__, ERR_PTR(err)); +- goto err_out; ++ goto err_out_drop; + } + + if (wait_tx_done) { +@@ -978,6 +989,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + + return size; + ++err_out_drop: ++ /* drop this PDU and unlock a potential wait queue */ ++ old_state = ISOTP_IDLE; + err_out: + so->tx.state = old_state; + if (so->tx.state == ISOTP_IDLE) +@@ -1444,6 +1458,7 @@ static int isotp_init(struct sock *sk) + so->txtimer.function = isotp_tx_timer_handler; + + init_waitqueue_head(&so->wait); ++ spin_lock_init(&so->rx_lock); + + spin_lock(&isotp_notifier_lock); + list_add_tail(&so->notifier, &isotp_notifier_list); +diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c +index 9bc55ecb37f9f..8452b0fbb78c9 100644 +--- a/net/can/j1939/main.c ++++ b/net/can/j1939/main.c +@@ -75,6 +75,13 @@ static void j1939_can_recv(struct sk_buff *iskb, void *data) + skcb->addr.pgn = (cf->can_id >> 8) & J1939_PGN_MAX; + /* set default message type */ + skcb->addr.type = J1939_TP; ++ ++ if (!j1939_address_is_valid(skcb->addr.sa)) { ++ netdev_err_once(priv->ndev, "%s: sa is broadcast address, ignoring!\n", ++ __func__); ++ goto done; ++ } ++ + if (j1939_pgn_is_pdu1(skcb->addr.pgn)) { + /* Type 1: with destination address */ + skcb->addr.da = skcb->addr.pgn; +diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c +index 6c0a0ebdd024c..307ee1174a6e2 100644 +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -2006,7 +2006,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv, + /* set the end-packet for broadcast */ + session->pkt.last = session->pkt.total; + +- skcb->tskey = session->sk->sk_tskey++; ++ skcb->tskey = atomic_inc_return(&session->sk->sk_tskey) - 1; + session->tskey = skcb->tskey; + + return session; +@@ -2023,6 +2023,11 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) + extd = J1939_ETP; + fallthrough; + case J1939_TP_CMD_BAM: ++ if (cmd == J1939_TP_CMD_BAM && !j1939_cb_is_broadcast(skcb)) { ++ netdev_err_once(priv->ndev, "%s: BAM to unicast (%02x), ignoring!\n", ++ __func__, skcb->addr.sa); ++ return; ++ } + fallthrough; + case J1939_TP_CMD_RTS: + if (skcb->addr.type != extd) +@@ -2085,6 +2090,12 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) + break; + + case J1939_ETP_CMD_ABORT: /* && J1939_TP_CMD_ABORT */ ++ if (j1939_cb_is_broadcast(skcb)) { ++ netdev_err_once(priv->ndev, "%s: abort to broadcast (%02x), ignoring!\n", ++ __func__, skcb->addr.sa); ++ return; ++ } ++ + if (j1939_tp_im_transmitter(skcb)) + j1939_xtp_rx_abort(priv, skb, true); + +diff --git a/net/core/Makefile b/net/core/Makefile +index 35ced6201814c..4268846f2f475 100644 +--- a/net/core/Makefile ++++ b/net/core/Makefile +@@ -36,3 +36,4 @@ obj-$(CONFIG_FAILOVER) += failover.o + obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o + obj-$(CONFIG_BPF_SYSCALL) += sock_map.o + obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o ++obj-$(CONFIG_OF) += of_net.o +diff --git a/net/core/dev.c b/net/core/dev.c +index eb3a366bf212c..33dc2a3ff7d78 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2921,6 +2921,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) + if (dev->num_tc) + netif_setup_tc(dev, txq); + ++ dev_qdisc_change_real_num_tx(dev, txq); ++ + dev->real_num_tx_queues = txq; + + if (disabling) { +@@ -3932,8 +3934,8 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev) + return skb; + + /* qdisc_skb_cb(skb)->pkt_len was already set by the caller. */ +- qdisc_skb_cb(skb)->mru = 0; +- qdisc_skb_cb(skb)->post_ct = false; ++ tc_skb_cb(skb)->mru = 0; ++ tc_skb_cb(skb)->post_ct = false; + mini_qdisc_bstats_cpu_update(miniq, skb); + + switch (tcf_classify(skb, miniq->block, miniq->filter_list, &cl_res, false)) { +@@ -4193,7 +4195,10 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) + if (dev->flags & IFF_UP) { + int cpu = smp_processor_id(); /* ok because BHs are off */ + +- if (txq->xmit_lock_owner != cpu) { ++ /* Other cpus might concurrently change txq->xmit_lock_owner ++ * to -1 or to their cpu id, but not to our id. ++ */ ++ if (READ_ONCE(txq->xmit_lock_owner) != cpu) { + if (dev_xmit_recursion()) + goto recursion_alert; + +@@ -5083,8 +5088,8 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret, + } + + qdisc_skb_cb(skb)->pkt_len = skb->len; +- qdisc_skb_cb(skb)->mru = 0; +- qdisc_skb_cb(skb)->post_ct = false; ++ tc_skb_cb(skb)->mru = 0; ++ tc_skb_cb(skb)->post_ct = false; + skb->tc_at_ingress = 1; + mini_qdisc_bstats_cpu_update(miniq, skb); + +@@ -9631,6 +9636,12 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog, + goto out_unlock; + } + old_prog = link->prog; ++ if (old_prog->type != new_prog->type || ++ old_prog->expected_attach_type != new_prog->expected_attach_type) { ++ err = -EINVAL; ++ goto out_unlock; ++ } ++ + if (old_prog == new_prog) { + /* no-op, don't disturb drivers */ + bpf_prog_put(new_prog); +diff --git a/net/core/devlink.c b/net/core/devlink.c +index a856ae401ea5c..db76c55e1a6d7 100644 +--- a/net/core/devlink.c ++++ b/net/core/devlink.c +@@ -4031,14 +4031,6 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) + return err; + } + +- if (info->attrs[DEVLINK_ATTR_NETNS_PID] || +- info->attrs[DEVLINK_ATTR_NETNS_FD] || +- info->attrs[DEVLINK_ATTR_NETNS_ID]) { +- dest_net = devlink_netns_get(skb, info); +- if (IS_ERR(dest_net)) +- return PTR_ERR(dest_net); +- } +- + if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION]) + action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]); + else +@@ -4081,6 +4073,14 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) + return -EINVAL; + } + } ++ if (info->attrs[DEVLINK_ATTR_NETNS_PID] || ++ info->attrs[DEVLINK_ATTR_NETNS_FD] || ++ info->attrs[DEVLINK_ATTR_NETNS_ID]) { ++ dest_net = devlink_netns_get(skb, info); ++ if (IS_ERR(dest_net)) ++ return PTR_ERR(dest_net); ++ } ++ + err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack); + + if (dest_net) +@@ -8795,8 +8795,6 @@ static const struct genl_small_ops devlink_nl_ops[] = { + GENL_DONT_VALIDATE_DUMP_STRICT, + .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit, + .flags = GENL_ADMIN_PERM, +- .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | +- DEVLINK_NL_FLAG_NO_LOCK, + }, + { + .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, +diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c +index 49442cae6f69d..1d99b731e5b21 100644 +--- a/net/core/drop_monitor.c ++++ b/net/core/drop_monitor.c +@@ -280,13 +280,17 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi, + + rcu_read_lock(); + list_for_each_entry_rcu(new_stat, &hw_stats_list, list) { ++ struct net_device *dev; ++ + /* + * only add a note to our monitor buffer if: + * 1) this is the dev we received on + * 2) its after the last_rx delta + * 3) our rx_dropped count has gone up + */ +- if ((new_stat->dev == napi->dev) && ++ /* Paired with WRITE_ONCE() in dropmon_net_event() */ ++ dev = READ_ONCE(new_stat->dev); ++ if ((dev == napi->dev) && + (time_after(jiffies, new_stat->last_rx + dm_hw_check_delta)) && + (napi->dev->stats.rx_dropped != new_stat->last_drop_val)) { + trace_drop_common(NULL, NULL); +@@ -1572,7 +1576,10 @@ static int dropmon_net_event(struct notifier_block *ev_block, + mutex_lock(&net_dm_mutex); + list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) { + if (new_stat->dev == dev) { +- new_stat->dev = NULL; ++ ++ /* Paired with READ_ONCE() in trace_napi_poll_hit() */ ++ WRITE_ONCE(new_stat->dev, NULL); ++ + if (trace_state == TRACE_OFF) { + list_del_rcu(&new_stat->list); + kfree_rcu(new_stat, rcu); +diff --git a/net/core/dst_cache.c b/net/core/dst_cache.c +index be74ab4551c20..0ccfd5fa5cb9b 100644 +--- a/net/core/dst_cache.c ++++ b/net/core/dst_cache.c +@@ -162,3 +162,22 @@ void dst_cache_destroy(struct dst_cache *dst_cache) + free_percpu(dst_cache->cache); + } + EXPORT_SYMBOL_GPL(dst_cache_destroy); ++ ++void dst_cache_reset_now(struct dst_cache *dst_cache) ++{ ++ int i; ++ ++ if (!dst_cache->cache) ++ return; ++ ++ dst_cache->reset_ts = jiffies; ++ for_each_possible_cpu(i) { ++ struct dst_cache_pcpu *idst = per_cpu_ptr(dst_cache->cache, i); ++ struct dst_entry *dst = idst->dst; ++ ++ idst->cookie = 0; ++ idst->dst = NULL; ++ dst_release(dst); ++ } ++} ++EXPORT_SYMBOL_GPL(dst_cache_reset_now); +diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c +index 79df7cd9dbc16..1bb567a3b329c 100644 +--- a/net/core/fib_rules.c ++++ b/net/core/fib_rules.c +@@ -323,7 +323,7 @@ jumped: + if (!err && ops->suppress && INDIRECT_CALL_MT(ops->suppress, + fib6_rule_suppress, + fib4_rule_suppress, +- rule, arg)) ++ rule, flags, arg)) + continue; + + if (err != -EAGAIN) { +diff --git a/net/core/filter.c b/net/core/filter.c +index 2e32cee2c4690..76e406965b6f9 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2711,6 +2711,9 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + if (unlikely(flags)) + return -EINVAL; + ++ if (unlikely(len == 0)) ++ return 0; ++ + /* First find the starting scatterlist element */ + i = msg->sg.start; + do { +@@ -4742,12 +4745,14 @@ static int _bpf_setsockopt(struct sock *sk, int level, int optname, + switch (optname) { + case SO_RCVBUF: + val = min_t(u32, val, sysctl_rmem_max); ++ val = min_t(int, val, INT_MAX / 2); + sk->sk_userlocks |= SOCK_RCVBUF_LOCK; + WRITE_ONCE(sk->sk_rcvbuf, + max_t(int, val * 2, SOCK_MIN_RCVBUF)); + break; + case SO_SNDBUF: + val = min_t(u32, val, sysctl_wmem_max); ++ val = min_t(int, val, INT_MAX / 2); + sk->sk_userlocks |= SOCK_SNDBUF_LOCK; + WRITE_ONCE(sk->sk_sndbuf, + max_t(int, val * 2, SOCK_MIN_SNDBUF)); +@@ -7162,6 +7167,8 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) + #endif + case BPF_FUNC_sk_storage_get: + return &bpf_sk_storage_get_cg_sock_proto; ++ case BPF_FUNC_ktime_get_coarse_ns: ++ return &bpf_ktime_get_coarse_ns_proto; + default: + return bpf_base_func_proto(func_id); + } +@@ -8174,9 +8181,9 @@ void bpf_warn_invalid_xdp_action(u32 act) + { + const u32 act_max = XDP_REDIRECT; + +- WARN_ONCE(1, "%s XDP return value %u, expect packet loss!\n", +- act > act_max ? "Illegal" : "Driver unsupported", +- act); ++ pr_warn_once("%s XDP return value %u, expect packet loss!\n", ++ act > act_max ? "Illegal" : "Driver unsupported", ++ act); + } + EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action); + +@@ -9735,22 +9742,46 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, + static struct bpf_insn *bpf_convert_data_end_access(const struct bpf_insn *si, + struct bpf_insn *insn) + { +- /* si->dst_reg = skb->data */ ++ int reg; ++ int temp_reg_off = offsetof(struct sk_buff, cb) + ++ offsetof(struct sk_skb_cb, temp_reg); ++ ++ if (si->src_reg == si->dst_reg) { ++ /* We need an extra register, choose and save a register. */ ++ reg = BPF_REG_9; ++ if (si->src_reg == reg || si->dst_reg == reg) ++ reg--; ++ if (si->src_reg == reg || si->dst_reg == reg) ++ reg--; ++ *insn++ = BPF_STX_MEM(BPF_DW, si->src_reg, reg, temp_reg_off); ++ } else { ++ reg = si->dst_reg; ++ } ++ ++ /* reg = skb->data */ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data), +- si->dst_reg, si->src_reg, ++ reg, si->src_reg, + offsetof(struct sk_buff, data)); + /* AX = skb->len */ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, len), + BPF_REG_AX, si->src_reg, + offsetof(struct sk_buff, len)); +- /* si->dst_reg = skb->data + skb->len */ +- *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX); ++ /* reg = skb->data + skb->len */ ++ *insn++ = BPF_ALU64_REG(BPF_ADD, reg, BPF_REG_AX); + /* AX = skb->data_len */ + *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data_len), + BPF_REG_AX, si->src_reg, + offsetof(struct sk_buff, data_len)); +- /* si->dst_reg = skb->data + skb->len - skb->data_len */ +- *insn++ = BPF_ALU64_REG(BPF_SUB, si->dst_reg, BPF_REG_AX); ++ ++ /* reg = skb->data + skb->len - skb->data_len */ ++ *insn++ = BPF_ALU64_REG(BPF_SUB, reg, BPF_REG_AX); ++ ++ if (si->src_reg == si->dst_reg) { ++ /* Restore the saved register */ ++ *insn++ = BPF_MOV64_REG(BPF_REG_AX, si->src_reg); ++ *insn++ = BPF_MOV64_REG(si->dst_reg, reg); ++ *insn++ = BPF_LDX_MEM(BPF_DW, reg, BPF_REG_AX, temp_reg_off); ++ } + + return insn; + } +@@ -9761,11 +9792,33 @@ static u32 sk_skb_convert_ctx_access(enum bpf_access_type type, + struct bpf_prog *prog, u32 *target_size) + { + struct bpf_insn *insn = insn_buf; ++ int off; + + switch (si->off) { + case offsetof(struct __sk_buff, data_end): + insn = bpf_convert_data_end_access(si, insn); + break; ++ case offsetof(struct __sk_buff, cb[0]) ... ++ offsetofend(struct __sk_buff, cb[4]) - 1: ++ BUILD_BUG_ON(sizeof_field(struct sk_skb_cb, data) < 20); ++ BUILD_BUG_ON((offsetof(struct sk_buff, cb) + ++ offsetof(struct sk_skb_cb, data)) % ++ sizeof(__u64)); ++ ++ prog->cb_access = 1; ++ off = si->off; ++ off -= offsetof(struct __sk_buff, cb[0]); ++ off += offsetof(struct sk_buff, cb); ++ off += offsetof(struct sk_skb_cb, data); ++ if (type == BPF_WRITE) ++ *insn++ = BPF_STX_MEM(BPF_SIZE(si->code), si->dst_reg, ++ si->src_reg, off); ++ else ++ *insn++ = BPF_LDX_MEM(BPF_SIZE(si->code), si->dst_reg, ++ si->src_reg, off); ++ break; ++ ++ + default: + return bpf_convert_ctx_access(type, si, insn_buf, prog, + target_size); +@@ -10260,6 +10313,8 @@ sk_reuseport_func_proto(enum bpf_func_id func_id, + return &sk_reuseport_load_bytes_relative_proto; + case BPF_FUNC_get_socket_cookie: + return &bpf_get_socket_ptr_cookie_proto; ++ case BPF_FUNC_ktime_get_coarse_ns: ++ return &bpf_ktime_get_coarse_ns_proto; + default: + return bpf_base_func_proto(func_id); + } +@@ -10741,6 +10796,8 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id) + case BPF_FUNC_skc_to_udp6_sock: + func = &bpf_skc_to_udp6_sock_proto; + break; ++ case BPF_FUNC_ktime_get_coarse_ns: ++ return &bpf_ktime_get_coarse_ns_proto; + default: + return bpf_base_func_proto(func_id); + } +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index bac0184cf3de7..edffdaa875f1f 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -238,7 +238,7 @@ void + skb_flow_dissect_ct(const struct sk_buff *skb, + struct flow_dissector *flow_dissector, + void *target_container, u16 *ctinfo_map, +- size_t mapsize, bool post_ct) ++ size_t mapsize, bool post_ct, u16 zone) + { + #if IS_ENABLED(CONFIG_NF_CONNTRACK) + struct flow_dissector_key_ct *key; +@@ -260,6 +260,7 @@ skb_flow_dissect_ct(const struct sk_buff *skb, + if (!ct) { + key->ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED | + TCA_FLOWER_KEY_CT_FLAGS_INVALID; ++ key->ct_zone = zone; + return; + } + +diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c +index 2820aca2173a8..9ccd64e8a666a 100644 +--- a/net/core/lwtunnel.c ++++ b/net/core/lwtunnel.c +@@ -197,6 +197,10 @@ int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining, + nla_entype = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); + + if (nla_entype) { ++ if (nla_len(nla_entype) < sizeof(u16)) { ++ NL_SET_ERR_MSG(extack, "Invalid RTA_ENCAP_TYPE"); ++ return -EINVAL; ++ } + encap_type = nla_get_u16(nla_entype); + + if (lwtunnel_valid_encap_type(encap_type, +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 2d5bc3a75faec..ff049733cceeb 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -379,7 +379,7 @@ EXPORT_SYMBOL(neigh_ifdown); + + static struct neighbour *neigh_alloc(struct neigh_table *tbl, + struct net_device *dev, +- bool exempt_from_gc) ++ u8 flags, bool exempt_from_gc) + { + struct neighbour *n = NULL; + unsigned long now = jiffies; +@@ -412,6 +412,7 @@ do_alloc: + n->updated = n->used = now; + n->nud_state = NUD_NONE; + n->output = neigh_blackhole; ++ n->flags = flags; + seqlock_init(&n->hh.hh_lock); + n->parms = neigh_parms_clone(&tbl->parms); + timer_setup(&n->timer, neigh_timer_handler, 0); +@@ -575,19 +576,18 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, + } + EXPORT_SYMBOL(neigh_lookup_nodev); + +-static struct neighbour *___neigh_create(struct neigh_table *tbl, +- const void *pkey, +- struct net_device *dev, +- bool exempt_from_gc, bool want_ref) ++static struct neighbour * ++___neigh_create(struct neigh_table *tbl, const void *pkey, ++ struct net_device *dev, u8 flags, ++ bool exempt_from_gc, bool want_ref) + { +- struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, exempt_from_gc); +- u32 hash_val; +- unsigned int key_len = tbl->key_len; +- int error; ++ u32 hash_val, key_len = tbl->key_len; ++ struct neighbour *n1, *rc, *n; + struct neigh_hash_table *nht; ++ int error; + ++ n = neigh_alloc(tbl, dev, flags, exempt_from_gc); + trace_neigh_create(tbl, dev, pkey, n, exempt_from_gc); +- + if (!n) { + rc = ERR_PTR(-ENOBUFS); + goto out; +@@ -674,7 +674,7 @@ out_neigh_release: + struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey, + struct net_device *dev, bool want_ref) + { +- return ___neigh_create(tbl, pkey, dev, false, want_ref); ++ return ___neigh_create(tbl, pkey, dev, 0, false, want_ref); + } + EXPORT_SYMBOL(__neigh_create); + +@@ -733,11 +733,10 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, + + ASSERT_RTNL(); + +- n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); ++ n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL); + if (!n) + goto out; + +- n->protocol = 0; + write_pnet(&n->net, net); + memcpy(n->key, pkey, key_len); + n->dev = dev; +@@ -1217,7 +1216,7 @@ static void neigh_update_hhs(struct neighbour *neigh) + lladdr instead of overriding it + if it is different. + NEIGH_UPDATE_F_ADMIN means that the change is administrative. +- ++ NEIGH_UPDATE_F_USE means that the entry is user triggered. + NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing + NTF_ROUTER flag. + NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as +@@ -1255,6 +1254,12 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + goto out; + + ext_learn_change = neigh_update_ext_learned(neigh, flags, ¬ify); ++ if (flags & NEIGH_UPDATE_F_USE) { ++ new = old & ~NUD_PERMANENT; ++ neigh->nud_state = new; ++ err = 0; ++ goto out; ++ } + + if (!(new & NUD_VALID)) { + neigh_del_timer(neigh); +@@ -1942,7 +1947,9 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, + + exempt_from_gc = ndm->ndm_state & NUD_PERMANENT || + ndm->ndm_flags & NTF_EXT_LEARNED; +- neigh = ___neigh_create(tbl, dst, dev, exempt_from_gc, true); ++ neigh = ___neigh_create(tbl, dst, dev, ++ ndm->ndm_flags & NTF_EXT_LEARNED, ++ exempt_from_gc, true); + if (IS_ERR(neigh)) { + err = PTR_ERR(neigh); + goto out; +@@ -1961,22 +1968,20 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, + + if (protocol) + neigh->protocol = protocol; +- + if (ndm->ndm_flags & NTF_EXT_LEARNED) + flags |= NEIGH_UPDATE_F_EXT_LEARNED; +- + if (ndm->ndm_flags & NTF_ROUTER) + flags |= NEIGH_UPDATE_F_ISROUTER; ++ if (ndm->ndm_flags & NTF_USE) ++ flags |= NEIGH_UPDATE_F_USE; + +- if (ndm->ndm_flags & NTF_USE) { ++ err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, ++ NETLINK_CB(skb).portid, extack); ++ if (!err && ndm->ndm_flags & NTF_USE) { + neigh_event_send(neigh, NULL); + err = 0; +- } else +- err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, +- NETLINK_CB(skb).portid, extack); +- ++ } + neigh_release(neigh); +- + out: + return err; + } +diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c +index d8b9dbabd4a43..88cc0ad7d386e 100644 +--- a/net/core/net-procfs.c ++++ b/net/core/net-procfs.c +@@ -190,12 +190,23 @@ static const struct seq_operations softnet_seq_ops = { + .show = softnet_seq_show, + }; + +-static void *ptype_get_idx(loff_t pos) ++static void *ptype_get_idx(struct seq_file *seq, loff_t pos) + { ++ struct list_head *ptype_list = NULL; + struct packet_type *pt = NULL; ++ struct net_device *dev; + loff_t i = 0; + int t; + ++ for_each_netdev_rcu(seq_file_net(seq), dev) { ++ ptype_list = &dev->ptype_all; ++ list_for_each_entry_rcu(pt, ptype_list, list) { ++ if (i == pos) ++ return pt; ++ ++i; ++ } ++ } ++ + list_for_each_entry_rcu(pt, &ptype_all, list) { + if (i == pos) + return pt; +@@ -216,22 +227,40 @@ static void *ptype_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) + { + rcu_read_lock(); +- return *pos ? ptype_get_idx(*pos - 1) : SEQ_START_TOKEN; ++ return *pos ? ptype_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; + } + + static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos) + { ++ struct net_device *dev; + struct packet_type *pt; + struct list_head *nxt; + int hash; + + ++*pos; + if (v == SEQ_START_TOKEN) +- return ptype_get_idx(0); ++ return ptype_get_idx(seq, 0); + + pt = v; + nxt = pt->list.next; ++ if (pt->dev) { ++ if (nxt != &pt->dev->ptype_all) ++ goto found; ++ ++ dev = pt->dev; ++ for_each_netdev_continue_rcu(seq_file_net(seq), dev) { ++ if (!list_empty(&dev->ptype_all)) { ++ nxt = dev->ptype_all.next; ++ goto found; ++ } ++ } ++ ++ nxt = ptype_all.next; ++ goto ptype_all; ++ } ++ + if (pt->type == htons(ETH_P_ALL)) { ++ptype_all: + if (nxt != &ptype_all) + goto found; + hash = 0; +@@ -260,7 +289,8 @@ static int ptype_seq_show(struct seq_file *seq, void *v) + + if (v == SEQ_START_TOKEN) + seq_puts(seq, "Type Device Function\n"); +- else if (pt->dev == NULL || dev_net(pt->dev) == seq_file_net(seq)) { ++ else if ((!pt->af_packet_net || net_eq(pt->af_packet_net, seq_file_net(seq))) && ++ (!pt->dev || net_eq(dev_net(pt->dev), seq_file_net(seq)))) { + if (pt->type == htons(ETH_P_ALL)) + seq_puts(seq, "ALL "); + else +diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c +index b2e49eb7001d6..d7f9ee830d34c 100644 +--- a/net/core/net-sysfs.c ++++ b/net/core/net-sysfs.c +@@ -175,6 +175,14 @@ static int change_carrier(struct net_device *dev, unsigned long new_carrier) + static ssize_t carrier_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) + { ++ struct net_device *netdev = to_net_dev(dev); ++ ++ /* The check is also done in change_carrier; this helps returning early ++ * without hitting the trylock/restart in netdev_store. ++ */ ++ if (!netdev->netdev_ops->ndo_change_carrier) ++ return -EOPNOTSUPP; ++ + return netdev_store(dev, attr, buf, len, change_carrier); + } + +@@ -196,6 +204,12 @@ static ssize_t speed_show(struct device *dev, + struct net_device *netdev = to_net_dev(dev); + int ret = -EINVAL; + ++ /* The check is also done in __ethtool_get_link_ksettings; this helps ++ * returning early without hitting the trylock/restart below. ++ */ ++ if (!netdev->ethtool_ops->get_link_ksettings) ++ return ret; ++ + if (!rtnl_trylock()) + return restart_syscall(); + +@@ -216,6 +230,12 @@ static ssize_t duplex_show(struct device *dev, + struct net_device *netdev = to_net_dev(dev); + int ret = -EINVAL; + ++ /* The check is also done in __ethtool_get_link_ksettings; this helps ++ * returning early without hitting the trylock/restart below. ++ */ ++ if (!netdev->ethtool_ops->get_link_ksettings) ++ return ret; ++ + if (!rtnl_trylock()) + return restart_syscall(); + +@@ -468,6 +488,14 @@ static ssize_t proto_down_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) + { ++ struct net_device *netdev = to_net_dev(dev); ++ ++ /* The check is also done in change_proto_down; this helps returning ++ * early without hitting the trylock/restart in netdev_store. ++ */ ++ if (!netdev->netdev_ops->ndo_change_proto_down) ++ return -EOPNOTSUPP; ++ + return netdev_store(dev, attr, buf, len, change_proto_down); + } + NETDEVICE_SHOW_RW(proto_down, fmt_dec); +@@ -478,6 +506,12 @@ static ssize_t phys_port_id_show(struct device *dev, + struct net_device *netdev = to_net_dev(dev); + ssize_t ret = -EINVAL; + ++ /* The check is also done in dev_get_phys_port_id; this helps returning ++ * early without hitting the trylock/restart below. ++ */ ++ if (!netdev->netdev_ops->ndo_get_phys_port_id) ++ return -EOPNOTSUPP; ++ + if (!rtnl_trylock()) + return restart_syscall(); + +@@ -500,6 +534,13 @@ static ssize_t phys_port_name_show(struct device *dev, + struct net_device *netdev = to_net_dev(dev); + ssize_t ret = -EINVAL; + ++ /* The checks are also done in dev_get_phys_port_name; this helps ++ * returning early without hitting the trylock/restart below. ++ */ ++ if (!netdev->netdev_ops->ndo_get_phys_port_name && ++ !netdev->netdev_ops->ndo_get_devlink_port) ++ return -EOPNOTSUPP; ++ + if (!rtnl_trylock()) + return restart_syscall(); + +@@ -522,6 +563,14 @@ static ssize_t phys_switch_id_show(struct device *dev, + struct net_device *netdev = to_net_dev(dev); + ssize_t ret = -EINVAL; + ++ /* The checks are also done in dev_get_phys_port_name; this helps ++ * returning early without hitting the trylock/restart below. This works ++ * because recurse is false when calling dev_get_port_parent_id. ++ */ ++ if (!netdev->netdev_ops->ndo_get_port_parent_id && ++ !netdev->netdev_ops->ndo_get_devlink_port) ++ return -EOPNOTSUPP; ++ + if (!rtnl_trylock()) + return restart_syscall(); + +@@ -1226,6 +1275,12 @@ static ssize_t tx_maxrate_store(struct netdev_queue *queue, + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + ++ /* The check is also done later; this helps returning early without ++ * hitting the trylock/restart below. ++ */ ++ if (!dev->netdev_ops->ndo_set_tx_maxrate) ++ return -EOPNOTSUPP; ++ + err = kstrtou32(buf, 10, &rate); + if (err < 0) + return err; +@@ -1765,6 +1820,9 @@ static void remove_queue_kobjects(struct net_device *dev) + + net_rx_queue_update_kobjects(dev, real_rx, 0); + netdev_queue_update_kobjects(dev, real_tx, 0); ++ ++ dev->real_num_rx_queues = 0; ++ dev->real_num_tx_queues = 0; + #ifdef CONFIG_SYSFS + kset_unregister(dev->queues_kset); + #endif +@@ -1869,7 +1927,7 @@ static struct class net_class __ro_after_init = { + .get_ownership = net_get_ownership, + }; + +-#ifdef CONFIG_OF_NET ++#ifdef CONFIG_OF + static int of_dev_node_match(struct device *dev, const void *data) + { + for (; dev; dev = dev->parent) { +diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c +index a448a9b5bb2d6..9702d2b0d9207 100644 +--- a/net/core/net_namespace.c ++++ b/net/core/net_namespace.c +@@ -164,8 +164,10 @@ static void ops_exit_list(const struct pernet_operations *ops, + { + struct net *net; + if (ops->exit) { +- list_for_each_entry(net, net_exit_list, exit_list) ++ list_for_each_entry(net, net_exit_list, exit_list) { + ops->exit(net); ++ cond_resched(); ++ } + } + if (ops->exit_batch) + ops->exit_batch(net_exit_list); +@@ -473,7 +475,9 @@ struct net *copy_net_ns(unsigned long flags, + + if (rv < 0) { + put_userns: ++#ifdef CONFIG_KEYS + key_remove_domain(net->key_domain); ++#endif + put_user_ns(user_ns); + net_free(net); + dec_ucounts: +@@ -605,7 +609,9 @@ static void cleanup_net(struct work_struct *work) + list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { + list_del_init(&net->exit_list); + dec_net_namespaces(net->ucounts); ++#ifdef CONFIG_KEYS + key_remove_domain(net->key_domain); ++#endif + put_user_ns(net->user_ns); + net_free(net); + } +diff --git a/net/core/of_net.c b/net/core/of_net.c +new file mode 100644 +index 0000000000000..dbac3a172a11e +--- /dev/null ++++ b/net/core/of_net.c +@@ -0,0 +1,145 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * OF helpers for network devices. ++ * ++ * Initially copied out of arch/powerpc/kernel/prom_parse.c ++ */ ++#include <linux/etherdevice.h> ++#include <linux/kernel.h> ++#include <linux/of_net.h> ++#include <linux/of_platform.h> ++#include <linux/phy.h> ++#include <linux/export.h> ++#include <linux/device.h> ++#include <linux/nvmem-consumer.h> ++ ++/** ++ * of_get_phy_mode - Get phy mode for given device_node ++ * @np: Pointer to the given device_node ++ * @interface: Pointer to the result ++ * ++ * The function gets phy interface string from property 'phy-mode' or ++ * 'phy-connection-type'. The index in phy_modes table is set in ++ * interface and 0 returned. In case of error interface is set to ++ * PHY_INTERFACE_MODE_NA and an errno is returned, e.g. -ENODEV. ++ */ ++int of_get_phy_mode(struct device_node *np, phy_interface_t *interface) ++{ ++ const char *pm; ++ int err, i; ++ ++ *interface = PHY_INTERFACE_MODE_NA; ++ ++ err = of_property_read_string(np, "phy-mode", &pm); ++ if (err < 0) ++ err = of_property_read_string(np, "phy-connection-type", &pm); ++ if (err < 0) ++ return err; ++ ++ for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) ++ if (!strcasecmp(pm, phy_modes(i))) { ++ *interface = i; ++ return 0; ++ } ++ ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(of_get_phy_mode); ++ ++static int of_get_mac_addr(struct device_node *np, const char *name, u8 *addr) ++{ ++ struct property *pp = of_find_property(np, name, NULL); ++ ++ if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)) { ++ memcpy(addr, pp->value, ETH_ALEN); ++ return 0; ++ } ++ return -ENODEV; ++} ++ ++static int of_get_mac_addr_nvmem(struct device_node *np, u8 *addr) ++{ ++ struct platform_device *pdev = of_find_device_by_node(np); ++ struct nvmem_cell *cell; ++ const void *mac; ++ size_t len; ++ int ret; ++ ++ /* Try lookup by device first, there might be a nvmem_cell_lookup ++ * associated with a given device. ++ */ ++ if (pdev) { ++ ret = nvmem_get_mac_address(&pdev->dev, addr); ++ put_device(&pdev->dev); ++ return ret; ++ } ++ ++ cell = of_nvmem_cell_get(np, "mac-address"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ mac = nvmem_cell_read(cell, &len); ++ nvmem_cell_put(cell); ++ ++ if (IS_ERR(mac)) ++ return PTR_ERR(mac); ++ ++ if (len != ETH_ALEN || !is_valid_ether_addr(mac)) { ++ kfree(mac); ++ return -EINVAL; ++ } ++ ++ memcpy(addr, mac, ETH_ALEN); ++ kfree(mac); ++ ++ return 0; ++} ++ ++/** ++ * of_get_mac_address() ++ * @np: Caller's Device Node ++ * @addr: Pointer to a six-byte array for the result ++ * ++ * Search the device tree for the best MAC address to use. 'mac-address' is ++ * checked first, because that is supposed to contain to "most recent" MAC ++ * address. If that isn't set, then 'local-mac-address' is checked next, ++ * because that is the default address. If that isn't set, then the obsolete ++ * 'address' is checked, just in case we're using an old device tree. If any ++ * of the above isn't set, then try to get MAC address from nvmem cell named ++ * 'mac-address'. ++ * ++ * Note that the 'address' property is supposed to contain a virtual address of ++ * the register set, but some DTS files have redefined that property to be the ++ * MAC address. ++ * ++ * All-zero MAC addresses are rejected, because those could be properties that ++ * exist in the device tree, but were not set by U-Boot. For example, the ++ * DTS could define 'mac-address' and 'local-mac-address', with zero MAC ++ * addresses. Some older U-Boots only initialized 'local-mac-address'. In ++ * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists ++ * but is all zeros. ++ * ++ * Return: 0 on success and errno in case of error. ++*/ ++int of_get_mac_address(struct device_node *np, u8 *addr) ++{ ++ int ret; ++ ++ if (!np) ++ return -ENODEV; ++ ++ ret = of_get_mac_addr(np, "mac-address", addr); ++ if (!ret) ++ return 0; ++ ++ ret = of_get_mac_addr(np, "local-mac-address", addr); ++ if (!ret) ++ return 0; ++ ++ ret = of_get_mac_addr(np, "address", addr); ++ if (!ret) ++ return 0; ++ ++ return of_get_mac_addr_nvmem(np, addr); ++} ++EXPORT_SYMBOL(of_get_mac_address); +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 8ccce85562a1d..91d7a5a5a08d0 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1698,6 +1698,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, + { + struct ifinfomsg *ifm; + struct nlmsghdr *nlh; ++ struct Qdisc *qdisc; + + ASSERT_RTNL(); + nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); +@@ -1715,6 +1716,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, + if (tgt_netnsid >= 0 && nla_put_s32(skb, IFLA_TARGET_NETNSID, tgt_netnsid)) + goto nla_put_failure; + ++ qdisc = rtnl_dereference(dev->qdisc); + if (nla_put_string(skb, IFLA_IFNAME, dev->name) || + nla_put_u32(skb, IFLA_TXQLEN, dev->tx_queue_len) || + nla_put_u8(skb, IFLA_OPERSTATE, +@@ -1733,8 +1735,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, + #endif + put_master_ifindex(skb, dev) || + nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) || +- (dev->qdisc && +- nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || ++ (qdisc && ++ nla_put_string(skb, IFLA_QDISC, qdisc->ops->id)) || + nla_put_ifalias(skb, dev) || + nla_put_u32(skb, IFLA_CARRIER_CHANGES, + atomic_read(&dev->carrier_up_count) + +@@ -3254,8 +3256,8 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, + struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1]; + unsigned char name_assign_type = NET_NAME_USER; + struct nlattr *linkinfo[IFLA_INFO_MAX + 1]; +- const struct rtnl_link_ops *m_ops = NULL; +- struct net_device *master_dev = NULL; ++ const struct rtnl_link_ops *m_ops; ++ struct net_device *master_dev; + struct net *net = sock_net(skb->sk); + const struct rtnl_link_ops *ops; + struct nlattr *tb[IFLA_MAX + 1]; +@@ -3293,6 +3295,8 @@ replay: + else + dev = NULL; + ++ master_dev = NULL; ++ m_ops = NULL; + if (dev) { + master_dev = netdev_master_upper_dev_get(dev); + if (master_dev) +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index fe9358437380c..6cb7ec85c9a1f 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -832,7 +832,7 @@ void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt) + ntohs(skb->protocol), skb->pkt_type, skb->skb_iif); + + if (dev) +- printk("%sdev name=%s feat=0x%pNF\n", ++ printk("%sdev name=%s feat=%pNF\n", + level, dev->name, &dev->features); + if (sk) + printk("%ssk family=%hu type=%u proto=%u\n", +@@ -2254,7 +2254,7 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta) + /* Free pulled out fragments. */ + while ((list = skb_shinfo(skb)->frag_list) != insp) { + skb_shinfo(skb)->frag_list = list->next; +- kfree_skb(list); ++ consume_skb(list); + } + /* And insert new clone at head. */ + if (clone) { +@@ -3449,19 +3449,7 @@ EXPORT_SYMBOL(skb_split); + */ + static int skb_prepare_for_shift(struct sk_buff *skb) + { +- int ret = 0; +- +- if (skb_cloned(skb)) { +- /* Save and restore truesize: pskb_expand_head() may reallocate +- * memory where ksize(kmalloc(S)) != ksize(kmalloc(S)), but we +- * cannot change truesize at this point. +- */ +- unsigned int save_truesize = skb->truesize; +- +- ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); +- skb->truesize = save_truesize; +- } +- return ret; ++ return skb_unclone_keeptruesize(skb, GFP_ATOMIC); + } + + /** +@@ -3865,6 +3853,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, + list_skb = list_skb->next; + + err = 0; ++ delta_truesize += nskb->truesize; + if (skb_shared(nskb)) { + tmp = skb_clone(nskb, GFP_ATOMIC); + if (tmp) { +@@ -3889,7 +3878,6 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, + tail = nskb; + + delta_len += nskb->len; +- delta_truesize += nskb->truesize; + + skb_push(nskb, -skb_network_offset(nskb) + offset); + +@@ -4856,7 +4844,7 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb, + serr->ee.ee_data = skb_shinfo(skb)->tskey; + if (sk->sk_protocol == IPPROTO_TCP && + sk->sk_type == SOCK_STREAM) +- serr->ee.ee_data -= sk->sk_tskey; ++ serr->ee.ee_data -= atomic_read(&sk->sk_tskey); + } + + err = sock_queue_err_skb(sk, skb); +@@ -6232,7 +6220,7 @@ static int pskb_carve_frag_list(struct sk_buff *skb, + /* Free pulled out fragments. */ + while ((list = shinfo->frag_list) != insp) { + shinfo->frag_list = list->next; +- kfree_skb(list); ++ consume_skb(list); + } + /* And insert new clone at head. */ + if (clone) { +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index a86ef7e844f8c..929a2b096b04e 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -508,6 +508,7 @@ static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk, + } + + static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, ++ u32 off, u32 len, + struct sk_psock *psock, + struct sock *sk, + struct sk_msg *msg) +@@ -521,11 +522,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, + */ + if (skb_linearize(skb)) + return -EAGAIN; +- num_sge = skb_to_sgvec(skb, msg->sg.data, 0, skb->len); ++ num_sge = skb_to_sgvec(skb, msg->sg.data, off, len); + if (unlikely(num_sge < 0)) + return num_sge; + +- copied = skb->len; ++ copied = len; + msg->sg.start = 0; + msg->sg.size = copied; + msg->sg.end = num_sge; +@@ -536,9 +537,11 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, + return copied; + } + +-static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb); ++static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb, ++ u32 off, u32 len); + +-static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) ++static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb, ++ u32 off, u32 len) + { + struct sock *sk = psock->sk; + struct sk_msg *msg; +@@ -549,7 +552,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) + * correctly. + */ + if (unlikely(skb->sk == sk)) +- return sk_psock_skb_ingress_self(psock, skb); ++ return sk_psock_skb_ingress_self(psock, skb, off, len); + msg = sk_psock_create_ingress_msg(sk, skb); + if (!msg) + return -EAGAIN; +@@ -561,7 +564,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) + * into user buffers. + */ + skb_set_owner_r(skb, sk); +- err = sk_psock_skb_ingress_enqueue(skb, psock, sk, msg); ++ err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg); + if (err < 0) + kfree(msg); + return err; +@@ -571,7 +574,8 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb) + * skb. In this case we do not need to check memory limits or skb_set_owner_r + * because the skb is already accounted for here. + */ +-static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb) ++static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb, ++ u32 off, u32 len) + { + struct sk_msg *msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC); + struct sock *sk = psock->sk; +@@ -581,7 +585,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb + return -EAGAIN; + sk_msg_init(msg); + skb_set_owner_r(skb, sk); +- err = sk_psock_skb_ingress_enqueue(skb, psock, sk, msg); ++ err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg); + if (err < 0) + kfree(msg); + return err; +@@ -595,7 +599,7 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb, + return -EAGAIN; + return skb_send_sock(psock->sk, skb, off, len); + } +- return sk_psock_skb_ingress(psock, skb); ++ return sk_psock_skb_ingress(psock, skb, off, len); + } + + static void sk_psock_skb_state(struct sk_psock *psock, +@@ -638,6 +642,12 @@ static void sk_psock_backlog(struct work_struct *work) + while ((skb = skb_dequeue(&psock->ingress_skb))) { + len = skb->len; + off = 0; ++ if (skb_bpf_strparser(skb)) { ++ struct strp_msg *stm = strp_msg(skb); ++ ++ off = stm->offset; ++ len = stm->full_len; ++ } + start: + ingress = skb_bpf_ingress(skb); + skb_bpf_redirect_clear(skb); +@@ -877,6 +887,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb) + * return code, but then didn't set a redirect interface. + */ + if (unlikely(!sk_other)) { ++ skb_bpf_redirect_clear(skb); + sock_drop(from->sk, skb); + return -EIO; + } +@@ -944,6 +955,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, + { + struct sock *sk_other; + int err = 0; ++ u32 len, off; + + switch (verdict) { + case __SK_PASS: +@@ -951,6 +963,7 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, + sk_other = psock->sk; + if (sock_flag(sk_other, SOCK_DEAD) || + !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { ++ skb_bpf_redirect_clear(skb); + goto out_free; + } + +@@ -963,7 +976,15 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, + * retrying later from workqueue. + */ + if (skb_queue_empty(&psock->ingress_skb)) { +- err = sk_psock_skb_ingress_self(psock, skb); ++ len = skb->len; ++ off = 0; ++ if (skb_bpf_strparser(skb)) { ++ struct strp_msg *stm = strp_msg(skb); ++ ++ off = stm->offset; ++ len = stm->full_len; ++ } ++ err = sk_psock_skb_ingress_self(psock, skb, off, len); + } + if (err < 0) { + spin_lock_bh(&psock->ingress_lock); +@@ -1029,6 +1050,8 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb) + skb_dst_drop(skb); + skb_bpf_redirect_clear(skb); + ret = bpf_prog_run_pin_on_cpu(prog, skb); ++ if (ret == SK_PASS) ++ skb_bpf_set_strparser(skb); + ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb)); + skb->sk = NULL; + } +@@ -1101,6 +1124,8 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) + + void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) + { ++ psock_set_prog(&psock->progs.stream_parser, NULL); ++ + if (!psock->saved_data_ready) + return; + +@@ -1128,7 +1153,7 @@ static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb, + struct sk_psock *psock; + struct bpf_prog *prog; + int ret = __SK_DROP; +- int len = skb->len; ++ int len = orig_len; + + /* clone here so sk_eat_skb() in tcp_read_sock does not drop our data */ + skb = skb_clone(skb, GFP_ATOMIC); +@@ -1189,6 +1214,9 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) + + void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) + { ++ psock_set_prog(&psock->progs.stream_verdict, NULL); ++ psock_set_prog(&psock->progs.skb_verdict, NULL); ++ + if (!psock->saved_data_ready) + return; + +diff --git a/net/core/sock.c b/net/core/sock.c +index c1601f75ec4b3..deaed1b206823 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -830,6 +830,8 @@ static int sock_timestamping_bind_phc(struct sock *sk, int phc_index) + } + + num = ethtool_get_phc_vclocks(dev, &vclock_index); ++ dev_put(dev); ++ + for (i = 0; i < num; i++) { + if (*(vclock_index + i) == phc_index) { + match = true; +@@ -864,9 +866,9 @@ int sock_set_timestamping(struct sock *sk, int optname, + if ((1 << sk->sk_state) & + (TCPF_CLOSE | TCPF_LISTEN)) + return -EINVAL; +- sk->sk_tskey = tcp_sk(sk)->snd_una; ++ atomic_set(&sk->sk_tskey, tcp_sk(sk)->snd_una); + } else { +- sk->sk_tskey = 0; ++ atomic_set(&sk->sk_tskey, 0); + } + } + +@@ -2043,8 +2045,10 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + newsk->sk_prot_creator = prot; + + /* SANITY */ +- if (likely(newsk->sk_net_refcnt)) ++ if (likely(newsk->sk_net_refcnt)) { + get_net(sock_net(newsk)); ++ sock_inuse_add(sock_net(newsk), 1); ++ } + sk_node_init(&newsk->sk_node); + sock_lock_init(newsk); + bh_lock_sock(newsk); +@@ -2115,8 +2119,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + newsk->sk_err_soft = 0; + newsk->sk_priority = 0; + newsk->sk_incoming_cpu = raw_smp_processor_id(); +- if (likely(newsk->sk_net_refcnt)) +- sock_inuse_add(sock_net(newsk), 1); + + /* Before updating sk_refcnt, we must commit prior changes to memory + * (Documentation/RCU/rculist_nulls.rst for details) +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index e252b8ec2b85e..8288b5382f08d 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -167,8 +167,11 @@ static void sock_map_del_link(struct sock *sk, + write_lock_bh(&sk->sk_callback_lock); + if (strp_stop) + sk_psock_stop_strp(sk, psock); +- else ++ if (verdict_stop) + sk_psock_stop_verdict(sk, psock); ++ ++ if (psock->psock_update_sk_prot) ++ psock->psock_update_sk_prot(sk, psock, false); + write_unlock_bh(&sk->sk_callback_lock); + } + } +@@ -282,32 +285,38 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk) + + if (msg_parser) + psock_set_prog(&psock->progs.msg_parser, msg_parser); ++ if (stream_parser) ++ psock_set_prog(&psock->progs.stream_parser, stream_parser); ++ if (stream_verdict) ++ psock_set_prog(&psock->progs.stream_verdict, stream_verdict); ++ if (skb_verdict) ++ psock_set_prog(&psock->progs.skb_verdict, skb_verdict); + ++ /* msg_* and stream_* programs references tracked in psock after this ++ * point. Reference dec and cleanup will occur through psock destructor ++ */ + ret = sock_map_init_proto(sk, psock); +- if (ret < 0) +- goto out_drop; ++ if (ret < 0) { ++ sk_psock_put(sk, psock); ++ goto out; ++ } + + write_lock_bh(&sk->sk_callback_lock); + if (stream_parser && stream_verdict && !psock->saved_data_ready) { + ret = sk_psock_init_strp(sk, psock); +- if (ret) +- goto out_unlock_drop; +- psock_set_prog(&psock->progs.stream_verdict, stream_verdict); +- psock_set_prog(&psock->progs.stream_parser, stream_parser); ++ if (ret) { ++ write_unlock_bh(&sk->sk_callback_lock); ++ sk_psock_put(sk, psock); ++ goto out; ++ } + sk_psock_start_strp(sk, psock); + } else if (!stream_parser && stream_verdict && !psock->saved_data_ready) { +- psock_set_prog(&psock->progs.stream_verdict, stream_verdict); + sk_psock_start_verdict(sk,psock); + } else if (!stream_verdict && skb_verdict && !psock->saved_data_ready) { +- psock_set_prog(&psock->progs.skb_verdict, skb_verdict); + sk_psock_start_verdict(sk, psock); + } + write_unlock_bh(&sk->sk_callback_lock); + return 0; +-out_unlock_drop: +- write_unlock_bh(&sk->sk_callback_lock); +-out_drop: +- sk_psock_put(sk, psock); + out_progs: + if (skb_verdict) + bpf_prog_put(skb_verdict); +@@ -320,6 +329,7 @@ out_put_stream_parser: + out_put_stream_verdict: + if (stream_verdict) + bpf_prog_put(stream_verdict); ++out: + return ret; + } + +diff --git a/net/core/stream.c b/net/core/stream.c +index 4f1d4aa5fb38d..a166a32b411fa 100644 +--- a/net/core/stream.c ++++ b/net/core/stream.c +@@ -195,9 +195,6 @@ void sk_stream_kill_queues(struct sock *sk) + /* First the read buffer. */ + __skb_queue_purge(&sk->sk_receive_queue); + +- /* Next, the error queue. */ +- __skb_queue_purge(&sk->sk_error_queue); +- + /* Next, the write queue. */ + WARN_ON(!skb_queue_empty(&sk->sk_write_queue)); + +diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c +index b441ab330fd34..dc4fb699b56c3 100644 +--- a/net/dcb/dcbnl.c ++++ b/net/dcb/dcbnl.c +@@ -2073,8 +2073,52 @@ u8 dcb_ieee_getapp_default_prio_mask(const struct net_device *dev) + } + EXPORT_SYMBOL(dcb_ieee_getapp_default_prio_mask); + ++static void dcbnl_flush_dev(struct net_device *dev) ++{ ++ struct dcb_app_type *itr, *tmp; ++ ++ spin_lock_bh(&dcb_lock); ++ ++ list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) { ++ if (itr->ifindex == dev->ifindex) { ++ list_del(&itr->list); ++ kfree(itr); ++ } ++ } ++ ++ spin_unlock_bh(&dcb_lock); ++} ++ ++static int dcbnl_netdevice_event(struct notifier_block *nb, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ switch (event) { ++ case NETDEV_UNREGISTER: ++ if (!dev->dcbnl_ops) ++ return NOTIFY_DONE; ++ ++ dcbnl_flush_dev(dev); ++ ++ return NOTIFY_OK; ++ default: ++ return NOTIFY_DONE; ++ } ++} ++ ++static struct notifier_block dcbnl_nb __read_mostly = { ++ .notifier_call = dcbnl_netdevice_event, ++}; ++ + static int __init dcbnl_init(void) + { ++ int err; ++ ++ err = register_netdevice_notifier(&dcbnl_nb); ++ if (err) ++ return err; ++ + rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, 0); + rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, 0); + +diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h +index c5c1d2b8045e8..5183e627468d8 100644 +--- a/net/dccp/dccp.h ++++ b/net/dccp/dccp.h +@@ -48,7 +48,7 @@ extern bool dccp_debug; + + extern struct inet_hashinfo dccp_hashinfo; + +-extern struct percpu_counter dccp_orphan_count; ++DECLARE_PER_CPU(unsigned int, dccp_orphan_count); + + void dccp_time_wait(struct sock *sk, int state, int timeo); + +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index abb5c596a8176..fc44dadc778bb 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -42,8 +42,8 @@ DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; + + EXPORT_SYMBOL_GPL(dccp_statistics); + +-struct percpu_counter dccp_orphan_count; +-EXPORT_SYMBOL_GPL(dccp_orphan_count); ++DEFINE_PER_CPU(unsigned int, dccp_orphan_count); ++EXPORT_PER_CPU_SYMBOL_GPL(dccp_orphan_count); + + struct inet_hashinfo dccp_hashinfo; + EXPORT_SYMBOL_GPL(dccp_hashinfo); +@@ -1055,7 +1055,7 @@ adjudge_to_death: + bh_lock_sock(sk); + WARN_ON(sock_owned_by_user(sk)); + +- percpu_counter_inc(sk->sk_prot->orphan_count); ++ this_cpu_inc(dccp_orphan_count); + + /* Have we already been destroyed by a softirq or backlog? */ + if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED) +@@ -1115,13 +1115,10 @@ static int __init dccp_init(void) + + BUILD_BUG_ON(sizeof(struct dccp_skb_cb) > + sizeof_field(struct sk_buff, cb)); +- rc = percpu_counter_init(&dccp_orphan_count, 0, GFP_KERNEL); +- if (rc) +- goto out_fail; + inet_hashinfo_init(&dccp_hashinfo); + rc = inet_hashinfo2_init_mod(&dccp_hashinfo); + if (rc) +- goto out_free_percpu; ++ goto out_fail; + rc = -ENOBUFS; + dccp_hashinfo.bind_bucket_cachep = + kmem_cache_create("dccp_bind_bucket", +@@ -1226,8 +1223,6 @@ out_free_bind_bucket_cachep: + kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); + out_free_hashinfo2: + inet_hashinfo2_free_mod(&dccp_hashinfo); +-out_free_percpu: +- percpu_counter_destroy(&dccp_orphan_count); + out_fail: + dccp_hashinfo.bhash = NULL; + dccp_hashinfo.ehash = NULL; +@@ -1250,7 +1245,6 @@ static void __exit dccp_fini(void) + dccp_ackvec_exit(); + dccp_sysctl_exit(); + inet_hashinfo2_free_mod(&dccp_hashinfo); +- percpu_counter_destroy(&dccp_orphan_count); + } + + module_init(dccp_init); +diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c +index 41f36ad8b0ec6..4ff03fb262e02 100644 +--- a/net/dsa/dsa.c ++++ b/net/dsa/dsa.c +@@ -349,6 +349,7 @@ void dsa_flush_workqueue(void) + { + flush_workqueue(dsa_owq); + } ++EXPORT_SYMBOL_GPL(dsa_flush_workqueue); + + int dsa_devlink_param_get(struct devlink *dl, u32 id, + struct devlink_param_gset_ctx *ctx) +diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h +index a5c9bc7b66c6e..33ab7d7af9eb4 100644 +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -170,7 +170,6 @@ void dsa_tag_driver_put(const struct dsa_device_ops *ops); + const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf); + + bool dsa_schedule_work(struct work_struct *work); +-void dsa_flush_workqueue(void); + const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops); + + static inline int dsa_tag_protocol_overhead(const struct dsa_device_ops *ops) +diff --git a/net/dsa/switch.c b/net/dsa/switch.c +index 6466d0539af9f..fb69f2f14234e 100644 +--- a/net/dsa/switch.c ++++ b/net/dsa/switch.c +@@ -264,7 +264,7 @@ static int dsa_switch_do_mdb_del(struct dsa_switch *ds, int port, + + err = ds->ops->port_mdb_del(ds, port, mdb); + if (err) { +- refcount_inc(&a->refcount); ++ refcount_set(&a->refcount, 1); + return err; + } + +@@ -329,7 +329,7 @@ static int dsa_switch_do_fdb_del(struct dsa_switch *ds, int port, + + err = ds->ops->port_fdb_del(ds, port, addr, vid); + if (err) { +- refcount_inc(&a->refcount); ++ refcount_set(&a->refcount, 1); + return err; + } + +@@ -644,7 +644,7 @@ static int + dsa_switch_mrp_add_ring_role(struct dsa_switch *ds, + struct dsa_notifier_mrp_ring_role_info *info) + { +- if (!ds->ops->port_mrp_add) ++ if (!ds->ops->port_mrp_add_ring_role) + return -EOPNOTSUPP; + + if (ds->index == info->sw_index) +@@ -658,7 +658,7 @@ static int + dsa_switch_mrp_del_ring_role(struct dsa_switch *ds, + struct dsa_notifier_mrp_ring_role_info *info) + { +- if (!ds->ops->port_mrp_del) ++ if (!ds->ops->port_mrp_del_ring_role) + return -EOPNOTSUPP; + + if (ds->index == info->sw_index) +diff --git a/net/dsa/tag_lan9303.c b/net/dsa/tag_lan9303.c +index cb548188f8134..98d7d7120bab2 100644 +--- a/net/dsa/tag_lan9303.c ++++ b/net/dsa/tag_lan9303.c +@@ -77,7 +77,6 @@ static struct sk_buff *lan9303_xmit(struct sk_buff *skb, struct net_device *dev) + + static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev) + { +- __be16 *lan9303_tag; + u16 lan9303_tag1; + unsigned int source_port; + +@@ -87,14 +86,15 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev) + return NULL; + } + +- lan9303_tag = dsa_etype_header_pos_rx(skb); +- +- if (lan9303_tag[0] != htons(ETH_P_8021Q)) { +- dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid VLAN marker\n"); +- return NULL; ++ if (skb_vlan_tag_present(skb)) { ++ lan9303_tag1 = skb_vlan_tag_get(skb); ++ __vlan_hwaccel_clear_tag(skb); ++ } else { ++ skb_push_rcsum(skb, ETH_HLEN); ++ __skb_vlan_pop(skb, &lan9303_tag1); ++ skb_pull_rcsum(skb, ETH_HLEN); + } + +- lan9303_tag1 = ntohs(lan9303_tag[1]); + source_port = lan9303_tag1 & 0x3; + + skb->dev = dsa_master_find_slave(dev, 0, source_port); +@@ -103,13 +103,6 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev) + return NULL; + } + +- /* remove the special VLAN tag between the MAC addresses +- * and the current ethertype field. +- */ +- skb_pull_rcsum(skb, 2 + 2); +- +- dsa_strip_etype_header(skb, LAN9303_TAG_LEN); +- + if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU)) + dsa_default_offload_fwd_mark(skb); + +diff --git a/net/dsa/tag_ocelot.c b/net/dsa/tag_ocelot.c +index 605b51ca69210..6e0518aa3a4d2 100644 +--- a/net/dsa/tag_ocelot.c ++++ b/net/dsa/tag_ocelot.c +@@ -62,6 +62,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, + struct dsa_port *dp; + u8 *extraction; + u16 vlan_tpid; ++ u64 rew_val; + + /* Revert skb->data by the amount consumed by the DSA master, + * so it points to the beginning of the frame. +@@ -91,6 +92,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, + ocelot_xfh_get_qos_class(extraction, &qos_class); + ocelot_xfh_get_tag_type(extraction, &tag_type); + ocelot_xfh_get_vlan_tci(extraction, &vlan_tci); ++ ocelot_xfh_get_rew_val(extraction, &rew_val); + + skb->dev = dsa_master_find_slave(netdev, 0, src_port); + if (!skb->dev) +@@ -104,6 +106,7 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, + + dsa_default_offload_fwd_mark(skb); + skb->priority = qos_class; ++ OCELOT_SKB_CB(skb)->tstamp_lo = rew_val; + + /* Ocelot switches copy frames unmodified to the CPU. However, it is + * possible for the user to request a VLAN modification through +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index f2abc31528883..e4983f473a3c5 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1697,7 +1697,7 @@ static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, + struct ethtool_coalesce coalesce; + int ret; + +- if (!dev->ethtool_ops->set_coalesce && !dev->ethtool_ops->get_coalesce) ++ if (!dev->ethtool_ops->set_coalesce || !dev->ethtool_ops->get_coalesce) + return -EOPNOTSUPP; + + ret = dev->ethtool_ops->get_coalesce(dev, &coalesce, &kernel_coalesce, +diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c +index 1797a0a900195..b3729bdafb602 100644 +--- a/net/ethtool/netlink.c ++++ b/net/ethtool/netlink.c +@@ -40,7 +40,8 @@ int ethnl_ops_begin(struct net_device *dev) + if (dev->dev.parent) + pm_runtime_get_sync(dev->dev.parent); + +- if (!netif_device_present(dev)) { ++ if (!netif_device_present(dev) || ++ dev->reg_state == NETREG_UNREGISTERING) { + ret = -ENODEV; + goto err; + } +diff --git a/net/ethtool/pause.c b/net/ethtool/pause.c +index 9009f412151e7..ee1e5806bc93a 100644 +--- a/net/ethtool/pause.c ++++ b/net/ethtool/pause.c +@@ -56,8 +56,7 @@ static int pause_reply_size(const struct ethnl_req_info *req_base, + + if (req_base->flags & ETHTOOL_FLAG_STATS) + n += nla_total_size(0) + /* _PAUSE_STATS */ +- nla_total_size_64bit(sizeof(u64)) * +- (ETHTOOL_A_PAUSE_STAT_MAX - 2); ++ nla_total_size_64bit(sizeof(u64)) * ETHTOOL_PAUSE_STAT_CNT; + return n; + } + +diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c +index 277124f206e06..e0b072aecf0f3 100644 +--- a/net/ieee802154/nl802154.c ++++ b/net/ieee802154/nl802154.c +@@ -1441,7 +1441,7 @@ static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid, + + hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) +- return -1; ++ return -ENOBUFS; + + if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) + goto nla_put_failure; +@@ -1634,7 +1634,7 @@ static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid, + + hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) +- return -1; ++ return -ENOBUFS; + + if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) + goto nla_put_failure; +@@ -1812,7 +1812,7 @@ static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid, + + hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) +- return -1; ++ return -ENOBUFS; + + if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) + goto nla_put_failure; +@@ -1988,7 +1988,7 @@ static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid, + + hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) +- return -1; ++ return -ENOBUFS; + + if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) + goto nla_put_failure; +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 1d816a5fd3eb9..77534b44b8c7c 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -158,7 +158,7 @@ void inet_sock_destruct(struct sock *sk) + + kfree(rcu_dereference_protected(inet->inet_opt, 1)); + dst_release(rcu_dereference_protected(sk->sk_dst_cache, 1)); +- dst_release(sk->sk_rx_dst); ++ dst_release(rcu_dereference_protected(sk->sk_rx_dst, 1)); + sk_refcnt_debug_dec(sk); + } + EXPORT_SYMBOL(inet_sock_destruct); +@@ -773,26 +773,28 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr, + DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr); + + sin->sin_family = AF_INET; ++ lock_sock(sk); + if (peer) { + if (!inet->inet_dport || + (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && +- peer == 1)) ++ peer == 1)) { ++ release_sock(sk); + return -ENOTCONN; ++ } + sin->sin_port = inet->inet_dport; + sin->sin_addr.s_addr = inet->inet_daddr; +- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, +- CGROUP_INET4_GETPEERNAME, +- NULL); ++ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, ++ CGROUP_INET4_GETPEERNAME); + } else { + __be32 addr = inet->inet_rcv_saddr; + if (!addr) + addr = inet->inet_saddr; + sin->sin_port = inet->inet_sport; + sin->sin_addr.s_addr = addr; +- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, +- CGROUP_INET4_GETSOCKNAME, +- NULL); ++ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, ++ CGROUP_INET4_GETSOCKNAME); + } ++ release_sock(sk); + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + return sizeof(*sin); + } +@@ -1378,8 +1380,11 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb, + } + + ops = rcu_dereference(inet_offloads[proto]); +- if (likely(ops && ops->callbacks.gso_segment)) ++ if (likely(ops && ops->callbacks.gso_segment)) { + segs = ops->callbacks.gso_segment(skb, features); ++ if (!segs) ++ skb->network_header = skb_mac_header(skb) + nhoff - skb->head; ++ } + + if (IS_ERR_OR_NULL(segs)) + goto out; +@@ -2002,6 +2007,10 @@ static int __init inet_init(void) + + ip_init(); + ++ /* Initialise per-cpu ipv4 mibs */ ++ if (init_ipv4_mibs()) ++ panic("%s: Cannot init ipv4 mibs\n", __func__); ++ + /* Setup TCP slab cache for open requests. */ + tcp_init(); + +@@ -2032,12 +2041,6 @@ static int __init inet_init(void) + + if (init_inet_pernet_ops()) + pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__); +- /* +- * Initialise per-cpu ipv4 mibs +- */ +- +- if (init_ipv4_mibs()) +- pr_crit("%s: Cannot init ipv4 mibs\n", __func__); + + ipv4_proc_init(); + +diff --git a/net/ipv4/bpf_tcp_ca.c b/net/ipv4/bpf_tcp_ca.c +index 0dcee9df13268..d3a2dbd13ea6b 100644 +--- a/net/ipv4/bpf_tcp_ca.c ++++ b/net/ipv4/bpf_tcp_ca.c +@@ -212,6 +212,8 @@ bpf_tcp_ca_get_func_proto(enum bpf_func_id func_id, + offsetof(struct tcp_congestion_ops, release)) + return &bpf_sk_getsockopt_proto; + return NULL; ++ case BPF_FUNC_ktime_get_coarse_ns: ++ return &bpf_ktime_get_coarse_ns_proto; + default: + return bpf_base_func_proto(func_id); + } +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index f4468980b6757..4744c7839de53 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -2587,7 +2587,7 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, + free: + kfree(t); + out: +- return -ENOBUFS; ++ return -ENOMEM; + } + + static void __devinet_sysctl_unregister(struct net *net, +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index 851f542928a33..e1b1d080e908d 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -671,7 +671,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) + struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); + u32 padto; + +- padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached)); ++ padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); + if (skb->len < padto) + esp.tfclen = padto - skb->len; + } +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 9fe13e4f5d08a..4d61ddd8a0ecf 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -1582,7 +1582,7 @@ static int __net_init fib_net_init(struct net *net) + int error; + + #ifdef CONFIG_IP_ROUTE_CLASSID +- net->ipv4.fib_num_tclassid_users = 0; ++ atomic_set(&net->ipv4.fib_num_tclassid_users, 0); + #endif + error = ip_fib_net_init(net); + if (error < 0) +diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h +index e184bcb199434..78e40ea42e58d 100644 +--- a/net/ipv4/fib_lookup.h ++++ b/net/ipv4/fib_lookup.h +@@ -16,10 +16,9 @@ struct fib_alias { + u8 fa_slen; + u32 tb_id; + s16 fa_default; +- u8 offload:1, +- trap:1, +- offload_failed:1, +- unused:5; ++ u8 offload; ++ u8 trap; ++ u8 offload_failed; + struct rcu_head rcu; + }; + +diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c +index ce54a30c2ef1e..d279cb8ac1584 100644 +--- a/net/ipv4/fib_rules.c ++++ b/net/ipv4/fib_rules.c +@@ -141,6 +141,7 @@ INDIRECT_CALLABLE_SCOPE int fib4_rule_action(struct fib_rule *rule, + } + + INDIRECT_CALLABLE_SCOPE bool fib4_rule_suppress(struct fib_rule *rule, ++ int flags, + struct fib_lookup_arg *arg) + { + struct fib_result *result = (struct fib_result *) arg->result; +@@ -263,7 +264,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, + if (tb[FRA_FLOW]) { + rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); + if (rule4->tclassid) +- net->ipv4.fib_num_tclassid_users++; ++ atomic_inc(&net->ipv4.fib_num_tclassid_users); + } + #endif + +@@ -295,7 +296,7 @@ static int fib4_rule_delete(struct fib_rule *rule) + + #ifdef CONFIG_IP_ROUTE_CLASSID + if (((struct fib4_rule *)rule)->tclassid) +- net->ipv4.fib_num_tclassid_users--; ++ atomic_dec(&net->ipv4.fib_num_tclassid_users); + #endif + net->ipv4.fib_has_custom_rules = true; + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 3364cb9c67e01..d244c57b73031 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -29,6 +29,7 @@ + #include <linux/init.h> + #include <linux/slab.h> + #include <linux/netlink.h> ++#include <linux/hash.h> + + #include <net/arp.h> + #include <net/ip.h> +@@ -220,7 +221,7 @@ void fib_nh_release(struct net *net, struct fib_nh *fib_nh) + { + #ifdef CONFIG_IP_ROUTE_CLASSID + if (fib_nh->nh_tclassid) +- net->ipv4.fib_num_tclassid_users--; ++ atomic_dec(&net->ipv4.fib_num_tclassid_users); + #endif + fib_nh_common_release(&fib_nh->nh_common); + } +@@ -249,7 +250,6 @@ void free_fib_info(struct fib_info *fi) + pr_warn("Freeing alive fib_info %p\n", fi); + return; + } +- fib_info_cnt--; + + call_rcu(&fi->rcu, free_fib_info_rcu); + } +@@ -260,6 +260,10 @@ void fib_release_info(struct fib_info *fi) + spin_lock_bh(&fib_info_lock); + if (fi && refcount_dec_and_test(&fi->fib_treeref)) { + hlist_del(&fi->fib_hash); ++ ++ /* Paired with READ_ONCE() in fib_create_info(). */ ++ WRITE_ONCE(fib_info_cnt, fib_info_cnt - 1); ++ + if (fi->fib_prefsrc) + hlist_del(&fi->fib_lhash); + if (fi->nh) { +@@ -316,11 +320,15 @@ static inline int nh_comp(struct fib_info *fi, struct fib_info *ofi) + + static inline unsigned int fib_devindex_hashfn(unsigned int val) + { +- unsigned int mask = DEVINDEX_HASHSIZE - 1; ++ return hash_32(val, DEVINDEX_HASHBITS); ++} ++ ++static struct hlist_head * ++fib_info_devhash_bucket(const struct net_device *dev) ++{ ++ u32 val = net_hash_mix(dev_net(dev)) ^ dev->ifindex; + +- return (val ^ +- (val >> DEVINDEX_HASHBITS) ^ +- (val >> (DEVINDEX_HASHBITS * 2))) & mask; ++ return &fib_info_devhash[fib_devindex_hashfn(val)]; + } + + static unsigned int fib_info_hashfn_1(int init_val, u8 protocol, u8 scope, +@@ -430,12 +438,11 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev) + { + struct hlist_head *head; + struct fib_nh *nh; +- unsigned int hash; + + spin_lock(&fib_info_lock); + +- hash = fib_devindex_hashfn(dev->ifindex); +- head = &fib_info_devhash[hash]; ++ head = fib_info_devhash_bucket(dev); ++ + hlist_for_each_entry(nh, head, nh_hash) { + if (nh->fib_nh_dev == dev && + nh->fib_nh_gw4 == gw && +@@ -517,9 +524,9 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, + fri.dst_len = dst_len; + fri.tos = fa->fa_tos; + fri.type = fa->fa_type; +- fri.offload = fa->offload; +- fri.trap = fa->trap; +- fri.offload_failed = fa->offload_failed; ++ fri.offload = READ_ONCE(fa->offload); ++ fri.trap = READ_ONCE(fa->trap); ++ fri.offload_failed = READ_ONCE(fa->offload_failed); + err = fib_dump_info(skb, info->portid, seq, event, &fri, nlm_flags); + if (err < 0) { + /* -EMSGSIZE implies BUG in fib_nlmsg_size() */ +@@ -632,7 +639,7 @@ int fib_nh_init(struct net *net, struct fib_nh *nh, + #ifdef CONFIG_IP_ROUTE_CLASSID + nh->nh_tclassid = cfg->fc_flow; + if (nh->nh_tclassid) +- net->ipv4.fib_num_tclassid_users++; ++ atomic_inc(&net->ipv4.fib_num_tclassid_users); + #endif + #ifdef CONFIG_IP_ROUTE_MULTIPATH + nh->fib_nh_weight = nh_weight; +@@ -662,6 +669,19 @@ static int fib_count_nexthops(struct rtnexthop *rtnh, int remaining, + return nhs; + } + ++static int fib_gw_from_attr(__be32 *gw, struct nlattr *nla, ++ struct netlink_ext_ack *extack) ++{ ++ if (nla_len(nla) < sizeof(*gw)) { ++ NL_SET_ERR_MSG(extack, "Invalid IPv4 address in RTA_GATEWAY"); ++ return -EINVAL; ++ } ++ ++ *gw = nla_get_in_addr(nla); ++ ++ return 0; ++} ++ + /* only called when fib_nh is integrated into fib_info */ + static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, + int remaining, struct fib_config *cfg, +@@ -704,7 +724,11 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, + return -EINVAL; + } + if (nla) { +- fib_cfg.fc_gw4 = nla_get_in_addr(nla); ++ ret = fib_gw_from_attr(&fib_cfg.fc_gw4, nla, ++ extack); ++ if (ret) ++ goto errout; ++ + if (fib_cfg.fc_gw4) + fib_cfg.fc_gw_family = AF_INET; + } else if (nlav) { +@@ -714,10 +738,18 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, + } + + nla = nla_find(attrs, attrlen, RTA_FLOW); +- if (nla) ++ if (nla) { ++ if (nla_len(nla) < sizeof(u32)) { ++ NL_SET_ERR_MSG(extack, "Invalid RTA_FLOW"); ++ return -EINVAL; ++ } + fib_cfg.fc_flow = nla_get_u32(nla); ++ } + + fib_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); ++ /* RTA_ENCAP_TYPE length checked in ++ * lwtunnel_valid_encap_type_attr ++ */ + nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); + if (nla) + fib_cfg.fc_encap_type = nla_get_u16(nla); +@@ -902,6 +934,7 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi, + attrlen = rtnh_attrlen(rtnh); + if (attrlen > 0) { + struct nlattr *nla, *nlav, *attrs = rtnh_attrs(rtnh); ++ int err; + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); + nlav = nla_find(attrs, attrlen, RTA_VIA); +@@ -912,12 +945,17 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi, + } + + if (nla) { ++ __be32 gw; ++ ++ err = fib_gw_from_attr(&gw, nla, extack); ++ if (err) ++ return err; ++ + if (nh->fib_nh_gw_family != AF_INET || +- nla_get_in_addr(nla) != nh->fib_nh_gw4) ++ gw != nh->fib_nh_gw4) + return 1; + } else if (nlav) { + struct fib_config cfg2; +- int err; + + err = fib_gw_from_via(&cfg2, nlav, extack); + if (err) +@@ -940,8 +978,14 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi, + + #ifdef CONFIG_IP_ROUTE_CLASSID + nla = nla_find(attrs, attrlen, RTA_FLOW); +- if (nla && nla_get_u32(nla) != nh->nh_tclassid) +- return 1; ++ if (nla) { ++ if (nla_len(nla) < sizeof(u32)) { ++ NL_SET_ERR_MSG(extack, "Invalid RTA_FLOW"); ++ return -EINVAL; ++ } ++ if (nla_get_u32(nla) != nh->nh_tclassid) ++ return 1; ++ } + #endif + } + +@@ -1393,7 +1437,9 @@ struct fib_info *fib_create_info(struct fib_config *cfg, + #endif + + err = -ENOBUFS; +- if (fib_info_cnt >= fib_info_hash_size) { ++ ++ /* Paired with WRITE_ONCE() in fib_release_info() */ ++ if (READ_ONCE(fib_info_cnt) >= fib_info_hash_size) { + unsigned int new_size = fib_info_hash_size << 1; + struct hlist_head *new_info_hash; + struct hlist_head *new_laddrhash; +@@ -1425,7 +1471,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg, + return ERR_PTR(err); + } + +- fib_info_cnt++; + fi->fib_net = net; + fi->fib_protocol = cfg->fc_protocol; + fi->fib_scope = cfg->fc_scope; +@@ -1552,6 +1597,7 @@ link_it: + refcount_set(&fi->fib_treeref, 1); + refcount_set(&fi->fib_clntref, 1); + spin_lock_bh(&fib_info_lock); ++ fib_info_cnt++; + hlist_add_head(&fi->fib_hash, + &fib_info_hash[fib_info_hashfn(fi)]); + if (fi->fib_prefsrc) { +@@ -1565,12 +1611,10 @@ link_it: + } else { + change_nexthops(fi) { + struct hlist_head *head; +- unsigned int hash; + + if (!nexthop_nh->fib_nh_dev) + continue; +- hash = fib_devindex_hashfn(nexthop_nh->fib_nh_dev->ifindex); +- head = &fib_info_devhash[hash]; ++ head = fib_info_devhash_bucket(nexthop_nh->fib_nh_dev); + hlist_add_head(&nexthop_nh->nh_hash, head); + } endfor_nexthops(fi) + } +@@ -1922,8 +1966,7 @@ void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig) + + void fib_sync_mtu(struct net_device *dev, u32 orig_mtu) + { +- unsigned int hash = fib_devindex_hashfn(dev->ifindex); +- struct hlist_head *head = &fib_info_devhash[hash]; ++ struct hlist_head *head = fib_info_devhash_bucket(dev); + struct fib_nh *nh; + + hlist_for_each_entry(nh, head, nh_hash) { +@@ -1942,12 +1985,11 @@ void fib_sync_mtu(struct net_device *dev, u32 orig_mtu) + */ + int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force) + { +- int ret = 0; +- int scope = RT_SCOPE_NOWHERE; ++ struct hlist_head *head = fib_info_devhash_bucket(dev); + struct fib_info *prev_fi = NULL; +- unsigned int hash = fib_devindex_hashfn(dev->ifindex); +- struct hlist_head *head = &fib_info_devhash[hash]; ++ int scope = RT_SCOPE_NOWHERE; + struct fib_nh *nh; ++ int ret = 0; + + if (force) + scope = -1; +@@ -2092,7 +2134,6 @@ out: + int fib_sync_up(struct net_device *dev, unsigned char nh_flags) + { + struct fib_info *prev_fi; +- unsigned int hash; + struct hlist_head *head; + struct fib_nh *nh; + int ret; +@@ -2108,8 +2149,7 @@ int fib_sync_up(struct net_device *dev, unsigned char nh_flags) + } + + prev_fi = NULL; +- hash = fib_devindex_hashfn(dev->ifindex); +- head = &fib_info_devhash[hash]; ++ head = fib_info_devhash_bucket(dev); + ret = 0; + + hlist_for_each_entry(nh, head, nh_hash) { +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 8060524f42566..f7f74d5c14da6 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1047,19 +1047,23 @@ void fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri) + if (!fa_match) + goto out; + +- if (fa_match->offload == fri->offload && fa_match->trap == fri->trap && +- fa_match->offload_failed == fri->offload_failed) ++ /* These are paired with the WRITE_ONCE() happening in this function. ++ * The reason is that we are only protected by RCU at this point. ++ */ ++ if (READ_ONCE(fa_match->offload) == fri->offload && ++ READ_ONCE(fa_match->trap) == fri->trap && ++ READ_ONCE(fa_match->offload_failed) == fri->offload_failed) + goto out; + +- fa_match->offload = fri->offload; +- fa_match->trap = fri->trap; ++ WRITE_ONCE(fa_match->offload, fri->offload); ++ WRITE_ONCE(fa_match->trap, fri->trap); + + /* 2 means send notifications only if offload_failed was changed. */ + if (net->ipv4.sysctl_fib_notify_on_flag_change == 2 && +- fa_match->offload_failed == fri->offload_failed) ++ READ_ONCE(fa_match->offload_failed) == fri->offload_failed) + goto out; + +- fa_match->offload_failed = fri->offload_failed; ++ WRITE_ONCE(fa_match->offload_failed, fri->offload_failed); + + if (!net->ipv4.sysctl_fib_notify_on_flag_change) + goto out; +@@ -2297,9 +2301,9 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb, + fri.dst_len = KEYLENGTH - fa->fa_slen; + fri.tos = fa->fa_tos; + fri.type = fa->fa_type; +- fri.offload = fa->offload; +- fri.trap = fa->trap; +- fri.offload_failed = fa->offload_failed; ++ fri.offload = READ_ONCE(fa->offload); ++ fri.trap = READ_ONCE(fa->trap); ++ fri.offload_failed = READ_ONCE(fa->offload_failed); + err = fib_dump_info(skb, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index f25d02ad4a8af..62a67fdc344cd 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -721,7 +721,7 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req, + + sk_node_init(&nreq_sk->sk_node); + nreq_sk->sk_tx_queue_mapping = req_sk->sk_tx_queue_mapping; +-#ifdef CONFIG_XPS ++#ifdef CONFIG_SOCK_RX_QUEUE_MAPPING + nreq_sk->sk_rx_queue_mapping = req_sk->sk_rx_queue_mapping; + #endif + nreq_sk->sk_incoming_cpu = req_sk->sk_incoming_cpu; +@@ -1015,7 +1015,7 @@ void inet_csk_destroy_sock(struct sock *sk) + + sk_refcnt_debug_release(sk); + +- percpu_counter_dec(sk->sk_prot->orphan_count); ++ this_cpu_dec(*sk->sk_prot->orphan_count); + + sock_put(sk); + } +@@ -1074,7 +1074,7 @@ static void inet_child_forget(struct sock *sk, struct request_sock *req, + + sock_orphan(child); + +- percpu_counter_inc(sk->sk_prot->orphan_count); ++ this_cpu_inc(*sk->sk_prot->orphan_count); + + if (sk->sk_protocol == IPPROTO_TCP && tcp_rsk(req)->tfo_listener) { + BUG_ON(rcu_access_pointer(tcp_sk(child)->fastopen_rsk) != req); +diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c +index ef7897226f08e..ae70e07c52445 100644 +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -261,6 +261,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, + r->idiag_state = sk->sk_state; + r->idiag_timer = 0; + r->idiag_retrans = 0; ++ r->idiag_expires = 0; + + if (inet_diag_msg_attrs_fill(sk, skb, r, ext, + sk_user_ns(NETLINK_CB(cb->skb).sk), +@@ -314,9 +315,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, + r->idiag_retrans = icsk->icsk_probes_out; + r->idiag_expires = + jiffies_delta_to_msecs(sk->sk_timer.expires - jiffies); +- } else { +- r->idiag_timer = 0; +- r->idiag_expires = 0; + } + + if ((ext & (1 << (INET_DIAG_INFO - 1))) && handler->idiag_info_size) { +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 05cd198d7a6ba..341096807100c 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -235,9 +235,9 @@ void inet_frag_kill(struct inet_frag_queue *fq) + /* The RCU read lock provides a memory barrier + * guaranteeing that if fqdir->dead is false then + * the hash table destruction will not start until +- * after we unlock. Paired with inet_frags_exit_net(). ++ * after we unlock. Paired with fqdir_pre_exit(). + */ +- if (!fqdir->dead) { ++ if (!READ_ONCE(fqdir->dead)) { + rhashtable_remove_fast(&fqdir->rhashtable, &fq->node, + fqdir->f->rhash_params); + refcount_dec(&fq->refcnt); +@@ -352,9 +352,11 @@ static struct inet_frag_queue *inet_frag_create(struct fqdir *fqdir, + /* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */ + struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key) + { ++ /* This pairs with WRITE_ONCE() in fqdir_pre_exit(). */ ++ long high_thresh = READ_ONCE(fqdir->high_thresh); + struct inet_frag_queue *fq = NULL, *prev; + +- if (!fqdir->high_thresh || frag_mem_limit(fqdir) > fqdir->high_thresh) ++ if (!high_thresh || frag_mem_limit(fqdir) > high_thresh) + return NULL; + + rcu_read_lock(); +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index bfb522e513461..75737267746f8 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -598,7 +598,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, bool *found_dup_sk) + if (ok) { + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + } else { +- percpu_counter_inc(sk->sk_prot->orphan_count); ++ this_cpu_inc(*sk->sk_prot->orphan_count); + inet_sk_set_state(sk, TCP_CLOSE); + sock_set_flag(sk, SOCK_DEAD); + inet_csk_destroy_sock(sk); +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index cfeb8890f94ee..fad803d2d711e 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -144,7 +144,8 @@ static void ip_expire(struct timer_list *t) + + rcu_read_lock(); + +- if (qp->q.fqdir->dead) ++ /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */ ++ if (READ_ONCE(qp->q.fqdir->dead)) + goto out_rcu_unlock; + + spin_lock(&qp->q.lock); +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 0fe6c936dc54a..e7f3e37e4aa83 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -604,8 +604,9 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) + + key = &info->key; + ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, +- tunnel_id_to_key32(key->tun_id), key->tos, 0, +- skb->mark, skb_get_hash(skb)); ++ tunnel_id_to_key32(key->tun_id), ++ key->tos & ~INET_ECN_MASK, 0, skb->mark, ++ skb_get_hash(skb)); + rt = ip_route_output_key(dev_net(dev), &fl4); + if (IS_ERR(rt)) + return PTR_ERR(rt); +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 9bca57ef8b838..131066d0319a2 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -162,12 +162,19 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, + iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); + iph->saddr = saddr; + iph->protocol = sk->sk_protocol; +- if (ip_dont_fragment(sk, &rt->dst)) { ++ /* Do not bother generating IPID for small packets (eg SYNACK) */ ++ if (skb->len <= IPV4_MIN_MTU || ip_dont_fragment(sk, &rt->dst)) { + iph->frag_off = htons(IP_DF); + iph->id = 0; + } else { + iph->frag_off = 0; +- __ip_select_ident(net, iph, 1); ++ /* TCP packets here are SYNACK with fat IPv4/TCP options. ++ * Avoid using the hashed IP ident generator. ++ */ ++ if (sk->sk_protocol == IPPROTO_TCP) ++ iph->id = (__force __be16)prandom_u32(); ++ else ++ __ip_select_ident(net, iph, 1); + } + + if (opt && opt->opt.optlen) { +@@ -826,15 +833,24 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + /* Everything is OK. Generate! */ + ip_fraglist_init(skb, iph, hlen, &iter); + +- if (iter.frag) +- ip_options_fragment(iter.frag); +- + for (;;) { + /* Prepare header of the next frame, + * before previous one went down. */ + if (iter.frag) { ++ bool first_frag = (iter.offset == 0); ++ + IPCB(iter.frag)->flags = IPCB(skb)->flags; + ip_fraglist_prepare(skb, &iter); ++ if (first_frag && IPCB(skb)->opt.optlen) { ++ /* ipcb->opt is not populated for frags ++ * coming from __ip_make_skb(), ++ * ip_options_fragment() needs optlen ++ */ ++ IPCB(iter.frag)->opt.optlen = ++ IPCB(skb)->opt.optlen; ++ ip_options_fragment(iter.frag); ++ ip_send_check(iter.iph); ++ } + } + + skb->tstamp = tstamp; +@@ -976,7 +992,7 @@ static int __ip_append_data(struct sock *sk, + + if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && + sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) +- tskey = sk->sk_tskey++; ++ tskey = atomic_inc_return(&sk->sk_tskey) - 1; + + hh_len = LL_RESERVED_SPACE(rt->dst.dev); + +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 2dda856ca2602..aea29d97f8dfa 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -261,7 +261,9 @@ static int __net_init ipmr_rules_init(struct net *net) + return 0; + + err2: ++ rtnl_lock(); + ipmr_free_table(mrt); ++ rtnl_unlock(); + err1: + fib_rules_unregister(ops); + return err; +diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c +index 8fd1aba8af31c..b518f20c9a244 100644 +--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c ++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c +@@ -520,8 +520,11 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) + if (IS_ERR(config)) + return PTR_ERR(config); + } +- } else if (memcmp(&config->clustermac, &cipinfo->clustermac, ETH_ALEN)) ++ } else if (memcmp(&config->clustermac, &cipinfo->clustermac, ETH_ALEN)) { ++ clusterip_config_entry_put(config); ++ clusterip_config_put(config); + return -EINVAL; ++ } + + ret = nf_ct_netns_get(par->net, par->family); + if (ret < 0) { +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 9e8100728d464..5dbd4b5505eba 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1899,15 +1899,36 @@ static void remove_nexthop(struct net *net, struct nexthop *nh, + /* if any FIB entries reference this nexthop, any dst entries + * need to be regenerated + */ +-static void nh_rt_cache_flush(struct net *net, struct nexthop *nh) ++static void nh_rt_cache_flush(struct net *net, struct nexthop *nh, ++ struct nexthop *replaced_nh) + { + struct fib6_info *f6i; ++ struct nh_group *nhg; ++ int i; + + if (!list_empty(&nh->fi_list)) + rt_cache_flush(net); + + list_for_each_entry(f6i, &nh->f6i_list, nh_list) + ipv6_stub->fib6_update_sernum(net, f6i); ++ ++ /* if an IPv6 group was replaced, we have to release all old ++ * dsts to make sure all refcounts are released ++ */ ++ if (!replaced_nh->is_group) ++ return; ++ ++ /* new dsts must use only the new nexthop group */ ++ synchronize_net(); ++ ++ nhg = rtnl_dereference(replaced_nh->nh_grp); ++ for (i = 0; i < nhg->num_nh; i++) { ++ struct nh_grp_entry *nhge = &nhg->nh_entries[i]; ++ struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info); ++ ++ if (nhi->family == AF_INET6) ++ ipv6_stub->fib6_nh_release_dsts(&nhi->fib6_nh); ++ } + } + + static int replace_nexthop_grp(struct net *net, struct nexthop *old, +@@ -2247,7 +2268,7 @@ static int replace_nexthop(struct net *net, struct nexthop *old, + err = replace_nexthop_single(net, old, new, extack); + + if (!err) { +- nh_rt_cache_flush(net, old); ++ nh_rt_cache_flush(net, old, new); + + __remove_nexthop(net, new, NULL); + nexthop_put(new); +@@ -2544,11 +2565,15 @@ static int nh_create_ipv6(struct net *net, struct nexthop *nh, + /* sets nh_dev if successful */ + err = ipv6_stub->fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL, + extack); +- if (err) ++ if (err) { ++ /* IPv6 is not enabled, don't call fib6_nh_release */ ++ if (err == -EAFNOSUPPORT) ++ goto out; + ipv6_stub->fib6_nh_release(fib6_nh); +- else ++ } else { + nh->nh_flags = fib6_nh->fib_nh_flags; +- ++ } ++out: + return err; + } + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 1e44a43acfe2d..36e89b6873876 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -172,16 +172,22 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) + struct sock *sk = NULL; + struct inet_sock *isk; + struct hlist_nulls_node *hnode; +- int dif = skb->dev->ifindex; ++ int dif, sdif; + + if (skb->protocol == htons(ETH_P_IP)) { ++ dif = inet_iif(skb); ++ sdif = inet_sdif(skb); + pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", + (int)ident, &ip_hdr(skb)->daddr, dif); + #if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { ++ dif = inet6_iif(skb); ++ sdif = inet6_sdif(skb); + pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n", + (int)ident, &ipv6_hdr(skb)->daddr, dif); + #endif ++ } else { ++ return NULL; + } + + read_lock_bh(&ping_table.lock); +@@ -220,7 +226,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) + continue; + } + +- if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) ++ if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif && ++ sk->sk_bound_dev_if != sdif) + continue; + + sock_hold(sk); +diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c +index b0d3a09dc84e7..f30273afb5399 100644 +--- a/net/ipv4/proc.c ++++ b/net/ipv4/proc.c +@@ -53,7 +53,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) + struct net *net = seq->private; + int orphans, sockets; + +- orphans = percpu_counter_sum_positive(&tcp_orphan_count); ++ orphans = tcp_orphan_count_sum(); + sockets = proto_sockets_allocated_sum_positive(&tcp_prot); + + socket_seq_show(seq); +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index bb446e60cf580..b8689052079cd 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -721,6 +721,7 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + int ret = -EINVAL; + int chk_addr_ret; + ++ lock_sock(sk); + if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in)) + goto out; + +@@ -740,7 +741,9 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + inet->inet_saddr = 0; /* Use device */ + sk_dst_reset(sk); + ret = 0; +-out: return ret; ++out: ++ release_sock(sk); ++ return ret; + } + + /* +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index d6899ab5fb39b..23833660584df 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -3401,8 +3401,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + fa->fa_tos == fri.tos && + fa->fa_info == res.fi && + fa->fa_type == fri.type) { +- fri.offload = fa->offload; +- fri.trap = fa->trap; ++ fri.offload = READ_ONCE(fa->offload); ++ fri.trap = READ_ONCE(fa->trap); + break; + } + } +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index f5c336f8b0c8e..f48f1059b31a6 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -287,8 +287,8 @@ enum { + TCP_CMSG_TS = 2 + }; + +-struct percpu_counter tcp_orphan_count; +-EXPORT_SYMBOL_GPL(tcp_orphan_count); ++DEFINE_PER_CPU(unsigned int, tcp_orphan_count); ++EXPORT_PER_CPU_SYMBOL_GPL(tcp_orphan_count); + + long sysctl_tcp_mem[3] __read_mostly; + EXPORT_SYMBOL(sysctl_tcp_mem); +@@ -952,7 +952,7 @@ int tcp_send_mss(struct sock *sk, int *size_goal, int flags) + */ + void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb) + { +- if (skb && !skb->len) { ++ if (skb && TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) { + tcp_unlink_write_queue(skb, sk); + if (tcp_write_queue_empty(sk)) + tcp_chrono_stop(sk, TCP_CHRONO_BUSY); +@@ -1776,6 +1776,9 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb, + { + skb_frag_t *frag; + ++ if (unlikely(offset_skb >= skb->len)) ++ return NULL; ++ + offset_skb -= skb_headlen(skb); + if ((int)offset_skb < 0 || skb_has_frag_list(skb)) + return NULL; +@@ -2687,11 +2690,36 @@ void tcp_shutdown(struct sock *sk, int how) + } + EXPORT_SYMBOL(tcp_shutdown); + ++int tcp_orphan_count_sum(void) ++{ ++ int i, total = 0; ++ ++ for_each_possible_cpu(i) ++ total += per_cpu(tcp_orphan_count, i); ++ ++ return max(total, 0); ++} ++ ++static int tcp_orphan_cache; ++static struct timer_list tcp_orphan_timer; ++#define TCP_ORPHAN_TIMER_PERIOD msecs_to_jiffies(100) ++ ++static void tcp_orphan_update(struct timer_list *unused) ++{ ++ WRITE_ONCE(tcp_orphan_cache, tcp_orphan_count_sum()); ++ mod_timer(&tcp_orphan_timer, jiffies + TCP_ORPHAN_TIMER_PERIOD); ++} ++ ++static bool tcp_too_many_orphans(int shift) ++{ ++ return READ_ONCE(tcp_orphan_cache) << shift > sysctl_tcp_max_orphans; ++} ++ + bool tcp_check_oom(struct sock *sk, int shift) + { + bool too_many_orphans, out_of_socket_memory; + +- too_many_orphans = tcp_too_many_orphans(sk, shift); ++ too_many_orphans = tcp_too_many_orphans(shift); + out_of_socket_memory = tcp_out_of_memory(sk); + + if (too_many_orphans) +@@ -2800,7 +2828,7 @@ adjudge_to_death: + /* remove backlog if any, without releasing ownership. */ + __release_sock(sk); + +- percpu_counter_inc(sk->sk_prot->orphan_count); ++ this_cpu_inc(tcp_orphan_count); + + /* Have we already been destroyed by a softirq or backlog? */ + if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) +@@ -3011,8 +3039,7 @@ int tcp_disconnect(struct sock *sk, int flags) + icsk->icsk_ack.rcv_mss = TCP_MIN_MSS; + memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); + __sk_dst_reset(sk); +- dst_release(sk->sk_rx_dst); +- sk->sk_rx_dst = NULL; ++ dst_release(xchg((__force struct dst_entry **)&sk->sk_rx_dst, NULL)); + tcp_saved_syn_free(tp); + tp->compressed_ack = 0; + tp->segs_in = 0; +@@ -4502,7 +4529,10 @@ void __init tcp_init(void) + sizeof_field(struct sk_buff, cb)); + + percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL); +- percpu_counter_init(&tcp_orphan_count, 0, GFP_KERNEL); ++ ++ timer_setup(&tcp_orphan_timer, tcp_orphan_update, TIMER_DEFERRABLE); ++ mod_timer(&tcp_orphan_timer, jiffies + TCP_ORPHAN_TIMER_PERIOD); ++ + inet_hashinfo_init(&tcp_hashinfo); + inet_hashinfo2_init(&tcp_hashinfo, "tcp_listen_portaddr_hash", + thash_entries, 21, /* one slot per 2 MB*/ +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 5f4d6f45d87f7..9b9b02052fd36 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -172,6 +172,68 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock, + return ret; + } + ++static int tcp_bpf_recvmsg_parser(struct sock *sk, ++ struct msghdr *msg, ++ size_t len, ++ int nonblock, ++ int flags, ++ int *addr_len) ++{ ++ struct sk_psock *psock; ++ int copied; ++ ++ if (unlikely(flags & MSG_ERRQUEUE)) ++ return inet_recv_error(sk, msg, len, addr_len); ++ ++ psock = sk_psock_get(sk); ++ if (unlikely(!psock)) ++ return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len); ++ ++ lock_sock(sk); ++msg_bytes_ready: ++ copied = sk_msg_recvmsg(sk, psock, msg, len, flags); ++ if (!copied) { ++ long timeo; ++ int data; ++ ++ if (sock_flag(sk, SOCK_DONE)) ++ goto out; ++ ++ if (sk->sk_err) { ++ copied = sock_error(sk); ++ goto out; ++ } ++ ++ if (sk->sk_shutdown & RCV_SHUTDOWN) ++ goto out; ++ ++ if (sk->sk_state == TCP_CLOSE) { ++ copied = -ENOTCONN; ++ goto out; ++ } ++ ++ timeo = sock_rcvtimeo(sk, nonblock); ++ if (!timeo) { ++ copied = -EAGAIN; ++ goto out; ++ } ++ ++ if (signal_pending(current)) { ++ copied = sock_intr_errno(timeo); ++ goto out; ++ } ++ ++ data = tcp_msg_wait_data(sk, psock, timeo); ++ if (data && !sk_psock_queue_empty(psock)) ++ goto msg_bytes_ready; ++ copied = -EAGAIN; ++ } ++out: ++ release_sock(sk); ++ sk_psock_put(sk, psock); ++ return copied; ++} ++ + static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + int nonblock, int flags, int *addr_len) + { +@@ -464,6 +526,8 @@ enum { + enum { + TCP_BPF_BASE, + TCP_BPF_TX, ++ TCP_BPF_RX, ++ TCP_BPF_TXRX, + TCP_BPF_NUM_CFGS, + }; + +@@ -475,7 +539,6 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], + struct proto *base) + { + prot[TCP_BPF_BASE] = *base; +- prot[TCP_BPF_BASE].unhash = sock_map_unhash; + prot[TCP_BPF_BASE].close = sock_map_close; + prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg; + prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable; +@@ -483,6 +546,12 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], + prot[TCP_BPF_TX] = prot[TCP_BPF_BASE]; + prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg; + prot[TCP_BPF_TX].sendpage = tcp_bpf_sendpage; ++ ++ prot[TCP_BPF_RX] = prot[TCP_BPF_BASE]; ++ prot[TCP_BPF_RX].recvmsg = tcp_bpf_recvmsg_parser; ++ ++ prot[TCP_BPF_TXRX] = prot[TCP_BPF_TX]; ++ prot[TCP_BPF_TXRX].recvmsg = tcp_bpf_recvmsg_parser; + } + + static void tcp_bpf_check_v6_needs_rebuild(struct proto *ops) +@@ -520,6 +589,10 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) + int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; + int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE; + ++ if (psock->progs.stream_verdict || psock->progs.skb_verdict) { ++ config = (config == TCP_BPF_TX) ? TCP_BPF_TXRX : TCP_BPF_RX; ++ } ++ + if (restore) { + if (inet_csk_has_ulp(sk)) { + /* TLS does not have an unhash proto in SW cases, +diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c +index 4a30deaa9a37f..8d2d4d652f6d4 100644 +--- a/net/ipv4/tcp_cubic.c ++++ b/net/ipv4/tcp_cubic.c +@@ -328,8 +328,6 @@ static void cubictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked) + return; + + if (tcp_in_slow_start(tp)) { +- if (hystart && after(ack, ca->end_seq)) +- bictcp_hystart_reset(sk); + acked = tcp_slow_start(tp, acked); + if (!acked) + return; +@@ -389,6 +387,9 @@ static void hystart_update(struct sock *sk, u32 delay) + struct bictcp *ca = inet_csk_ca(sk); + u32 threshold; + ++ if (after(tp->snd_una, ca->end_seq)) ++ bictcp_hystart_reset(sk); ++ + if (hystart_detect & HYSTART_ACK_TRAIN) { + u32 now = bictcp_clock_us(sk); + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 141e85e6422b1..509f577869d4e 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -1652,6 +1652,8 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, + (mss != tcp_skb_seglen(skb))) + goto out; + ++ if (!tcp_skb_can_collapse(prev, skb)) ++ goto out; + len = skb->len; + pcount = tcp_skb_pcount(skb); + if (tcp_skb_shift(prev, skb, pcount, len)) +@@ -5770,7 +5772,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb) + trace_tcp_probe(sk, skb); + + tcp_mstamp_refresh(tp); +- if (unlikely(!sk->sk_rx_dst)) ++ if (unlikely(!rcu_access_pointer(sk->sk_rx_dst))) + inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); + /* + * Header prediction. +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 5b8ce65dfc067..0fe9461647da5 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1698,16 +1698,19 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) + struct sock *rsk; + + if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ +- struct dst_entry *dst = sk->sk_rx_dst; ++ struct dst_entry *dst; ++ ++ dst = rcu_dereference_protected(sk->sk_rx_dst, ++ lockdep_sock_is_held(sk)); + + sock_rps_save_rxhash(sk, skb); + sk_mark_napi_id(sk, skb); + if (dst) { +- if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || ++ if (sk->sk_rx_dst_ifindex != skb->skb_iif || + !INDIRECT_CALL_1(dst->ops->check, ipv4_dst_check, + dst, 0)) { ++ RCU_INIT_POINTER(sk->sk_rx_dst, NULL); + dst_release(dst); +- sk->sk_rx_dst = NULL; + } + } + tcp_rcv_established(sk, skb); +@@ -1783,12 +1786,12 @@ int tcp_v4_early_demux(struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_edemux; + if (sk_fullsock(sk)) { +- struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); ++ struct dst_entry *dst = rcu_dereference(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, 0); + if (dst && +- inet_sk(sk)->rx_dst_ifindex == skb->skb_iif) ++ sk->sk_rx_dst_ifindex == skb->skb_iif) + skb_dst_set_noref(skb, dst); + } + } +@@ -2200,8 +2203,8 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) + struct dst_entry *dst = skb_dst(skb); + + if (dst && dst_hold_safe(dst)) { +- sk->sk_rx_dst = dst; +- inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; ++ rcu_assign_pointer(sk->sk_rx_dst, dst); ++ sk->sk_rx_dst_ifindex = skb->skb_iif; + } + } + EXPORT_SYMBOL(inet_sk_rx_dst_set); +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 6d72f3ea48c4e..0492f6942778d 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1562,7 +1562,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, + return -ENOMEM; + } + +- if (skb_unclone(skb, gfp)) ++ if (skb_unclone_keeptruesize(skb, gfp)) + return -ENOMEM; + + /* Get a new skb... force flag on. */ +@@ -1672,7 +1672,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) + { + u32 delta_truesize; + +- if (skb_unclone(skb, GFP_ATOMIC)) ++ if (skb_unclone_keeptruesize(skb, GFP_ATOMIC)) + return -ENOMEM; + + delta_truesize = __pskb_trim_head(skb, len); +@@ -3184,7 +3184,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) + cur_mss, GFP_ATOMIC)) + return -ENOMEM; /* We'll try again later. */ + } else { +- if (skb_unclone(skb, GFP_ATOMIC)) ++ if (skb_unclone_keeptruesize(skb, GFP_ATOMIC)) + return -ENOMEM; + + diff = tcp_skb_pcount(skb); +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 2fffcf2b54f3f..835b9d6e4e686 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -917,7 +917,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4, + kfree_skb(skb); + return -EINVAL; + } +- if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { ++ if (datalen > cork->gso_size * UDP_MAX_SEGMENTS) { + kfree_skb(skb); + return -EINVAL; + } +@@ -1808,6 +1808,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc, + skb = skb_recv_udp(sk, 0, 1, &err); + if (!skb) + return err; ++ ++ if (udp_lib_checksum_complete(skb)) { ++ __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, ++ IS_UDPLITE(sk)); ++ __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, ++ IS_UDPLITE(sk)); ++ atomic_inc(&sk->sk_drops); ++ kfree_skb(skb); ++ continue; ++ } ++ + used = recv_actor(desc, skb, 0, skb->len); + if (used <= 0) { + if (!copied) +@@ -2240,7 +2251,7 @@ bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) + struct dst_entry *old; + + if (dst_hold_safe(dst)) { +- old = xchg(&sk->sk_rx_dst, dst); ++ old = xchg((__force struct dst_entry **)&sk->sk_rx_dst, dst); + dst_release(old); + return old != dst; + } +@@ -2430,7 +2441,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, + struct dst_entry *dst = skb_dst(skb); + int ret; + +- if (unlikely(sk->sk_rx_dst != dst)) ++ if (unlikely(rcu_dereference(sk->sk_rx_dst) != dst)) + udp_sk_rx_dst_set(sk, dst); + + ret = udp_unicast_rcv_skb(sk, skb, uh); +@@ -2589,7 +2600,7 @@ int udp_v4_early_demux(struct sk_buff *skb) + + skb->sk = sk; + skb->destructor = sock_efree; +- dst = READ_ONCE(sk->sk_rx_dst); ++ dst = rcu_dereference(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, 0); +@@ -3065,7 +3076,7 @@ int udp4_seq_show(struct seq_file *seq, void *v) + { + seq_setwidth(seq, 127); + if (v == SEQ_START_TOKEN) +- seq_puts(seq, " sl local_address rem_address st tx_queue " ++ seq_puts(seq, " sl local_address rem_address st tx_queue " + "rx_queue tr tm->when retrnsmt uid timeout " + "inode ref pointer drops"); + else { +diff --git a/net/ipv4/udp_tunnel_nic.c b/net/ipv4/udp_tunnel_nic.c +index b91003538d87a..bc3a043a5d5c7 100644 +--- a/net/ipv4/udp_tunnel_nic.c ++++ b/net/ipv4/udp_tunnel_nic.c +@@ -846,7 +846,7 @@ udp_tunnel_nic_unregister(struct net_device *dev, struct udp_tunnel_nic *utn) + list_for_each_entry(node, &info->shared->devices, list) + if (node->dev == dev) + break; +- if (node->dev != dev) ++ if (list_entry_is_head(node, &info->shared->devices, list)) + return; + + list_del(&node->list); +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index c6a90b7bbb70e..e852bbc839dd8 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1837,8 +1837,8 @@ out: + } + EXPORT_SYMBOL(ipv6_dev_get_saddr); + +-int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, +- u32 banned_flags) ++static int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, ++ u32 banned_flags) + { + struct inet6_ifaddr *ifp; + int err = -EADDRNOTAVAIL; +@@ -2587,7 +2587,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, + __u32 valid_lft, u32 prefered_lft) + { + struct inet6_ifaddr *ifp = ipv6_get_ifaddr(net, addr, dev, 1); +- int create = 0; ++ int create = 0, update_lft = 0; + + if (!ifp && valid_lft) { + int max_addresses = in6_dev->cnf.max_addresses; +@@ -2631,19 +2631,32 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, + unsigned long now; + u32 stored_lft; + +- /* Update lifetime (RFC4862 5.5.3 e) +- * We deviate from RFC4862 by honoring all Valid Lifetimes to +- * improve the reaction of SLAAC to renumbering events +- * (draft-gont-6man-slaac-renum-06, Section 4.2) +- */ ++ /* update lifetime (RFC2462 5.5.3 e) */ + spin_lock_bh(&ifp->lock); + now = jiffies; + if (ifp->valid_lft > (now - ifp->tstamp) / HZ) + stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ; + else + stored_lft = 0; +- + if (!create && stored_lft) { ++ const u32 minimum_lft = min_t(u32, ++ stored_lft, MIN_VALID_LIFETIME); ++ valid_lft = max(valid_lft, minimum_lft); ++ ++ /* RFC4862 Section 5.5.3e: ++ * "Note that the preferred lifetime of the ++ * corresponding address is always reset to ++ * the Preferred Lifetime in the received ++ * Prefix Information option, regardless of ++ * whether the valid lifetime is also reset or ++ * ignored." ++ * ++ * So we should always update prefered_lft here. ++ */ ++ update_lft = 1; ++ } ++ ++ if (update_lft) { + ifp->valid_lft = valid_lft; + ifp->prefered_lft = prefered_lft; + ifp->tstamp = now; +@@ -3110,6 +3123,9 @@ static void add_v4_addrs(struct inet6_dev *idev) + memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4); + + if (idev->dev->flags&IFF_POINTOPOINT) { ++ if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE) ++ return; ++ + addr.s6_addr32[0] = htonl(0xfe800000); + scope = IFA_LINK; + plen = 64; +@@ -3714,6 +3730,7 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister) + struct inet6_dev *idev; + struct inet6_ifaddr *ifa, *tmp; + bool keep_addr = false; ++ bool was_ready; + int state, i; + + ASSERT_RTNL(); +@@ -3779,7 +3796,10 @@ restart: + + addrconf_del_rs_timer(idev); + +- /* Step 2: clear flags for stateless addrconf */ ++ /* Step 2: clear flags for stateless addrconf, repeated down ++ * detection ++ */ ++ was_ready = idev->if_flags & IF_READY; + if (!unregister) + idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); + +@@ -3853,7 +3873,7 @@ restart: + if (unregister) { + ipv6_ac_destroy_dev(idev); + ipv6_mc_destroy_dev(idev); +- } else { ++ } else if (was_ready) { + ipv6_mc_down(idev); + } + +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index b5878bb8e419d..dab4a047590b7 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -521,31 +521,32 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, + sin->sin6_family = AF_INET6; + sin->sin6_flowinfo = 0; + sin->sin6_scope_id = 0; ++ lock_sock(sk); + if (peer) { +- if (!inet->inet_dport) +- return -ENOTCONN; +- if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && +- peer == 1) ++ if (!inet->inet_dport || ++ (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && ++ peer == 1)) { ++ release_sock(sk); + return -ENOTCONN; ++ } + sin->sin6_port = inet->inet_dport; + sin->sin6_addr = sk->sk_v6_daddr; + if (np->sndflow) + sin->sin6_flowinfo = np->flow_label; +- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, +- CGROUP_INET6_GETPEERNAME, +- NULL); ++ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, ++ CGROUP_INET6_GETPEERNAME); + } else { + if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) + sin->sin6_addr = np->saddr; + else + sin->sin6_addr = sk->sk_v6_rcv_saddr; + sin->sin6_port = inet->inet_sport; +- BPF_CGROUP_RUN_SA_PROG_LOCK(sk, (struct sockaddr *)sin, +- CGROUP_INET6_GETSOCKNAME, +- NULL); ++ BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, ++ CGROUP_INET6_GETSOCKNAME); + } + sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr, + sk->sk_bound_dev_if); ++ release_sock(sk); + return sizeof(*sin); + } + EXPORT_SYMBOL(inet6_getname); +@@ -1025,6 +1026,7 @@ static const struct ipv6_stub ipv6_stub_impl = { + .ip6_mtu_from_fib6 = ip6_mtu_from_fib6, + .fib6_nh_init = fib6_nh_init, + .fib6_nh_release = fib6_nh_release, ++ .fib6_nh_release_dsts = fib6_nh_release_dsts, + .fib6_update_sernum = fib6_update_sernum_stub, + .fib6_rt_update = fib6_rt_update, + .ip6_del_rt = ip6_del_rt, +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index ed2f061b87685..883b53fd78467 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -708,7 +708,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) + struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); + u32 padto; + +- padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached)); ++ padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); + if (skb->len < padto) + esp.tfclen = padto - skb->len; + } +@@ -808,6 +808,12 @@ int esp6_input_done2(struct sk_buff *skb, int err) + struct tcphdr *th; + + offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off); ++ ++ if (offset < 0) { ++ err = -EINVAL; ++ goto out; ++ } ++ + uh = (void *)(skb->data + offset); + th = (void *)(skb->data + offset); + hdr_len += offset; +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index 40f3e4f9f33a2..dcedfe29d9d93 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -267,6 +267,7 @@ INDIRECT_CALLABLE_SCOPE int fib6_rule_action(struct fib_rule *rule, + } + + INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, ++ int flags, + struct fib_lookup_arg *arg) + { + struct fib6_result *res = arg->result; +@@ -294,8 +295,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, + return false; + + suppress_route: +- if (!(arg->flags & FIB_LOOKUP_NOREF)) +- ip6_rt_put(rt); ++ ip6_rt_put_flags(rt, flags); + return true; + } + +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index a7c31ab67c5d6..96c5cc0f30ceb 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -57,6 +57,7 @@ + #include <net/protocol.h> + #include <net/raw.h> + #include <net/rawv6.h> ++#include <net/seg6.h> + #include <net/transp_v6.h> + #include <net/ip6_route.h> + #include <net/addrconf.h> +@@ -820,6 +821,7 @@ out_bh_enable: + + void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) + { ++ struct inet6_skb_parm *opt = IP6CB(skb); + const struct inet6_protocol *ipprot; + int inner_offset; + __be16 frag_off; +@@ -829,6 +831,8 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + goto out; + ++ seg6_icmp_srh(skb, opt); ++ + nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; + if (ipv6_ext_hdr(nexthdr)) { + /* now skip over extension headers */ +@@ -853,7 +857,7 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) + + ipprot = rcu_dereference(inet6_protos[nexthdr]); + if (ipprot && ipprot->err_handler) +- ipprot->err_handler(skb, NULL, type, code, inner_offset, info); ++ ipprot->err_handler(skb, opt, type, code, inner_offset, info); + + raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); + return; +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 0371d2c141455..a506e57c4032a 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -111,7 +111,7 @@ void fib6_update_sernum(struct net *net, struct fib6_info *f6i) + fn = rcu_dereference_protected(f6i->fib6_node, + lockdep_is_held(&f6i->fib6_table->tb6_lock)); + if (fn) +- fn->fn_sernum = fib6_new_sernum(net); ++ WRITE_ONCE(fn->fn_sernum, fib6_new_sernum(net)); + } + + /* +@@ -589,12 +589,13 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb, + spin_unlock_bh(&table->tb6_lock); + if (res > 0) { + cb->args[4] = 1; +- cb->args[5] = w->root->fn_sernum; ++ cb->args[5] = READ_ONCE(w->root->fn_sernum); + } + } else { +- if (cb->args[5] != w->root->fn_sernum) { ++ int sernum = READ_ONCE(w->root->fn_sernum); ++ if (cb->args[5] != sernum) { + /* Begin at the root if the tree changed */ +- cb->args[5] = w->root->fn_sernum; ++ cb->args[5] = sernum; + w->state = FWS_INIT; + w->node = w->root; + w->skip = w->count; +@@ -1344,7 +1345,7 @@ static void __fib6_update_sernum_upto_root(struct fib6_info *rt, + /* paired with smp_rmb() in fib6_get_cookie_safe() */ + smp_wmb(); + while (fn) { +- fn->fn_sernum = sernum; ++ WRITE_ONCE(fn->fn_sernum, sernum); + fn = rcu_dereference_protected(fn->parent, + lockdep_is_held(&rt->fib6_table->tb6_lock)); + } +@@ -2173,8 +2174,8 @@ static int fib6_clean_node(struct fib6_walker *w) + }; + + if (c->sernum != FIB6_NO_SERNUM_CHANGE && +- w->node->fn_sernum != c->sernum) +- w->node->fn_sernum = c->sernum; ++ READ_ONCE(w->node->fn_sernum) != c->sernum) ++ WRITE_ONCE(w->node->fn_sernum, c->sernum); + + if (!c->func) { + WARN_ON_ONCE(c->sernum == FIB6_NO_SERNUM_CHANGE); +@@ -2542,7 +2543,7 @@ static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter, + iter->w.state = FWS_INIT; + iter->w.node = iter->w.root; + iter->w.args = iter; +- iter->sernum = iter->w.root->fn_sernum; ++ iter->sernum = READ_ONCE(iter->w.root->fn_sernum); + INIT_LIST_HEAD(&iter->w.lh); + fib6_walker_link(net, &iter->w); + } +@@ -2570,8 +2571,10 @@ static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl, + + static void ipv6_route_check_sernum(struct ipv6_route_iter *iter) + { +- if (iter->sernum != iter->w.root->fn_sernum) { +- iter->sernum = iter->w.root->fn_sernum; ++ int sernum = READ_ONCE(iter->w.root->fn_sernum); ++ ++ if (iter->sernum != sernum) { ++ iter->sernum = sernum; + iter->w.state = FWS_INIT; + iter->w.node = iter->w.root; + WARN_ON(iter->w.skip); +diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c +index aa673a6a7e432..ceb85c67ce395 100644 +--- a/net/ipv6/ip6_flowlabel.c ++++ b/net/ipv6/ip6_flowlabel.c +@@ -450,8 +450,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, + err = -EINVAL; + goto done; + } +- if (fl_shared_exclusive(fl) || fl->opt) ++ if (fl_shared_exclusive(fl) || fl->opt) { ++ WRITE_ONCE(sock_net(sk)->ipv6.flowlabel_has_excl, 1); + static_branch_deferred_inc(&ipv6_flowlabel_exclusive); ++ } + return fl; + + done: +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 3ad201d372d88..466a5610e3ca9 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -755,6 +755,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb, + fl6->daddr = key->u.ipv6.dst; + fl6->flowlabel = key->label; + fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL); ++ fl6->fl6_gre_key = tunnel_id_to_key32(key->tun_id); + + dsfield = key->tos; + flags = key->tun_flags & +@@ -990,6 +991,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, + fl6.daddr = key->u.ipv6.dst; + fl6.flowlabel = key->label; + fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); ++ fl6.fl6_gre_key = tunnel_id_to_key32(key->tun_id); + + dsfield = key->tos; + if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT)) +@@ -1098,6 +1100,7 @@ static void ip6gre_tnl_link_config_common(struct ip6_tnl *t) + fl6->flowi6_oif = p->link; + fl6->flowlabel = 0; + fl6->flowi6_proto = IPPROTO_GRE; ++ fl6->fl6_gre_key = t->parms.o_key; + + if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) + fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; +@@ -1544,7 +1547,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev) + static struct inet6_protocol ip6gre_protocol __read_mostly = { + .handler = gre_rcv, + .err_handler = ip6gre_err, +- .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, ++ .flags = INET6_PROTO_FINAL, + }; + + static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head) +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index 1b9827ff8ccf4..172565d125704 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -114,6 +114,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, + if (likely(ops && ops->callbacks.gso_segment)) { + skb_reset_transport_header(skb); + segs = ops->callbacks.gso_segment(skb, features); ++ if (!segs) ++ skb->network_header = skb_mac_header(skb) + nhoff - skb->head; + } + + if (IS_ERR_OR_NULL(segs)) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 2f044a49afa8c..61970fd839c36 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -174,7 +174,7 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff + #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) + /* Policy lookup after SNAT yielded a new policy */ + if (skb_dst(skb)->xfrm) { +- IPCB(skb)->flags |= IPSKB_REROUTED; ++ IP6CB(skb)->flags |= IP6SKB_REROUTED; + return dst_output(net, sk, skb); + } + #endif +@@ -1408,8 +1408,6 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, + if (np->frag_size) + mtu = np->frag_size; + } +- if (mtu < IPV6_MIN_MTU) +- return -EINVAL; + cork->base.fragsize = mtu; + cork->base.gso_size = ipc6->gso_size; + cork->base.tx_flags = 0; +@@ -1465,14 +1463,12 @@ static int __ip6_append_data(struct sock *sk, + + if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && + sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) +- tskey = sk->sk_tskey++; ++ tskey = atomic_inc_return(&sk->sk_tskey) - 1; + + hh_len = LL_RESERVED_SPACE(rt->dst.dev); + + fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + + (opt ? opt->opt_nflen : 0); +- maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - +- sizeof(struct frag_hdr); + + headersize = sizeof(struct ipv6hdr) + + (opt ? opt->opt_flen + opt->opt_nflen : 0) + +@@ -1480,6 +1476,13 @@ static int __ip6_append_data(struct sock *sk, + sizeof(struct frag_hdr) : 0) + + rt->rt6i_nfheader_len; + ++ if (mtu < fragheaderlen || ++ ((mtu - fragheaderlen) & ~7) + fragheaderlen < sizeof(struct frag_hdr)) ++ goto emsgsize; ++ ++ maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - ++ sizeof(struct frag_hdr); ++ + /* as per RFC 7112 section 5, the entire IPv6 Header Chain must fit + * the first fragment + */ +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 20a67efda47f5..fa8da8ff35b42 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -1036,14 +1036,14 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t, + + if (unlikely(!ipv6_chk_addr_and_flags(net, laddr, ldev, false, + 0, IFA_F_TENTATIVE))) +- pr_warn("%s xmit: Local address not yet configured!\n", +- p->name); ++ pr_warn_ratelimited("%s xmit: Local address not yet configured!\n", ++ p->name); + else if (!(p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) && + !ipv6_addr_is_multicast(raddr) && + unlikely(ipv6_chk_addr_and_flags(net, raddr, ldev, + true, 0, IFA_F_TENTATIVE))) +- pr_warn("%s xmit: Routing loop! Remote address found on this node!\n", +- p->name); ++ pr_warn_ratelimited("%s xmit: Routing loop! Remote address found on this node!\n", ++ p->name); + else + ret = 1; + rcu_read_unlock(); +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 1d8e3ffa225d8..42c37ec832f15 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -808,6 +808,8 @@ vti6_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data + struct net *net = dev_net(dev); + struct vti6_net *ip6n = net_generic(net, vti6_net_id); + ++ memset(&p1, 0, sizeof(p1)); ++ + switch (cmd) { + case SIOCGETTUNNEL: + if (dev == ip6n->fb_tnl_dev) { +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index 36ed9efb88254..6a4065d81aa91 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -248,7 +248,9 @@ static int __net_init ip6mr_rules_init(struct net *net) + return 0; + + err2: ++ rtnl_lock(); + ip6mr_free_table(mrt); ++ rtnl_unlock(); + err1: + fib_rules_unregister(ops); + return err; +diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c +index bed8155508c85..909f937befd71 100644 +--- a/net/ipv6/mcast.c ++++ b/net/ipv6/mcast.c +@@ -1371,27 +1371,23 @@ static void mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld, + } + + /* called with rcu_read_lock() */ +-int igmp6_event_query(struct sk_buff *skb) ++void igmp6_event_query(struct sk_buff *skb) + { + struct inet6_dev *idev = __in6_dev_get(skb->dev); + +- if (!idev) +- return -EINVAL; +- +- if (idev->dead) { +- kfree_skb(skb); +- return -ENODEV; +- } ++ if (!idev || idev->dead) ++ goto out; + + spin_lock_bh(&idev->mc_query_lock); + if (skb_queue_len(&idev->mc_query_queue) < MLD_MAX_SKBS) { + __skb_queue_tail(&idev->mc_query_queue, skb); + if (!mod_delayed_work(mld_wq, &idev->mc_query_work, 0)) + in6_dev_hold(idev); ++ skb = NULL; + } + spin_unlock_bh(&idev->mc_query_lock); +- +- return 0; ++out: ++ kfree_skb(skb); + } + + static void __mld_query_work(struct sk_buff *skb) +@@ -1542,27 +1538,23 @@ static void mld_query_work(struct work_struct *work) + } + + /* called with rcu_read_lock() */ +-int igmp6_event_report(struct sk_buff *skb) ++void igmp6_event_report(struct sk_buff *skb) + { + struct inet6_dev *idev = __in6_dev_get(skb->dev); + +- if (!idev) +- return -EINVAL; +- +- if (idev->dead) { +- kfree_skb(skb); +- return -ENODEV; +- } ++ if (!idev || idev->dead) ++ goto out; + + spin_lock_bh(&idev->mc_report_lock); + if (skb_queue_len(&idev->mc_report_queue) < MLD_MAX_SKBS) { + __skb_queue_tail(&idev->mc_report_queue, skb); + if (!mod_delayed_work(mld_wq, &idev->mc_report_work, 0)) + in6_dev_hold(idev); ++ skb = NULL; + } + spin_unlock_bh(&idev->mc_report_lock); +- +- return 0; ++out: ++ kfree_skb(skb); + } + + static void __mld_report_work(struct sk_buff *skb) +@@ -1759,7 +1751,7 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu) + skb_reserve(skb, hlen); + skb_tailroom_reserve(skb, mtu, tlen); + +- if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { ++ if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { + /* <draft-ietf-magma-mld-source-05.txt>: + * use unspecified address as the source address + * when a valid link-local address is not available. +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 60f1e4f5be5aa..c51d5ce3711c2 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -1020,6 +1020,9 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, + struct raw6_sock *rp = raw6_sk(sk); + int val; + ++ if (optlen < sizeof(val)) ++ return -EINVAL; ++ + if (copy_from_sockptr(&val, optval, sizeof(val))) + return -EFAULT; + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 9b9ef09382ab9..e0766bdf20e7d 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -2802,7 +2802,7 @@ static void ip6_link_failure(struct sk_buff *skb) + if (from) { + fn = rcu_dereference(from->fib6_node); + if (fn && (rt->rt6i_flags & RTF_DEFAULT)) +- fn->fn_sernum = -1; ++ WRITE_ONCE(fn->fn_sernum, -1); + } + } + rcu_read_unlock(); +@@ -3680,6 +3680,25 @@ void fib6_nh_release(struct fib6_nh *fib6_nh) + fib_nh_common_release(&fib6_nh->nh_common); + } + ++void fib6_nh_release_dsts(struct fib6_nh *fib6_nh) ++{ ++ int cpu; ++ ++ if (!fib6_nh->rt6i_pcpu) ++ return; ++ ++ for_each_possible_cpu(cpu) { ++ struct rt6_info *pcpu_rt, **ppcpu_rt; ++ ++ ppcpu_rt = per_cpu_ptr(fib6_nh->rt6i_pcpu, cpu); ++ pcpu_rt = xchg(ppcpu_rt, NULL); ++ if (pcpu_rt) { ++ dst_dev_put(&pcpu_rt->dst); ++ dst_release(&pcpu_rt->dst); ++ } ++ } ++} ++ + static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, + gfp_t gfp_flags, + struct netlink_ext_ack *extack) +@@ -5205,6 +5224,19 @@ out: + return should_notify; + } + ++static int fib6_gw_from_attr(struct in6_addr *gw, struct nlattr *nla, ++ struct netlink_ext_ack *extack) ++{ ++ if (nla_len(nla) < sizeof(*gw)) { ++ NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_GATEWAY"); ++ return -EINVAL; ++ } ++ ++ *gw = nla_get_in6_addr(nla); ++ ++ return 0; ++} ++ + static int ip6_route_multipath_add(struct fib6_config *cfg, + struct netlink_ext_ack *extack) + { +@@ -5245,10 +5277,18 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); + if (nla) { +- r_cfg.fc_gateway = nla_get_in6_addr(nla); ++ err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, ++ extack); ++ if (err) ++ goto cleanup; ++ + r_cfg.fc_flags |= RTF_GATEWAY; + } + r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); ++ ++ /* RTA_ENCAP_TYPE length checked in ++ * lwtunnel_valid_encap_type_attr ++ */ + nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); + if (nla) + r_cfg.fc_encap_type = nla_get_u16(nla); +@@ -5415,7 +5455,13 @@ static int ip6_route_multipath_del(struct fib6_config *cfg, + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); + if (nla) { +- nla_memcpy(&r_cfg.fc_gateway, nla, 16); ++ err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, ++ extack); ++ if (err) { ++ last_err = err; ++ goto next_rtnh; ++ } ++ + r_cfg.fc_flags |= RTF_GATEWAY; + } + } +@@ -5423,6 +5469,7 @@ static int ip6_route_multipath_del(struct fib6_config *cfg, + if (err) + last_err = err; + ++next_rtnh: + rtnh = rtnh_next(rtnh, &remaining); + } + +@@ -5720,11 +5767,11 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, + } + + if (!dst) { +- if (rt->offload) ++ if (READ_ONCE(rt->offload)) + rtm->rtm_flags |= RTM_F_OFFLOAD; +- if (rt->trap) ++ if (READ_ONCE(rt->trap)) + rtm->rtm_flags |= RTM_F_TRAP; +- if (rt->offload_failed) ++ if (READ_ONCE(rt->offload_failed)) + rtm->rtm_flags |= RTM_F_OFFLOAD_FAILED; + } + +@@ -6182,19 +6229,20 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i, + struct sk_buff *skb; + int err; + +- if (f6i->offload == offload && f6i->trap == trap && +- f6i->offload_failed == offload_failed) ++ if (READ_ONCE(f6i->offload) == offload && ++ READ_ONCE(f6i->trap) == trap && ++ READ_ONCE(f6i->offload_failed) == offload_failed) + return; + +- f6i->offload = offload; +- f6i->trap = trap; ++ WRITE_ONCE(f6i->offload, offload); ++ WRITE_ONCE(f6i->trap, trap); + + /* 2 means send notifications only if offload_failed was changed. */ + if (net->ipv6.sysctl.fib_notify_on_flag_change == 2 && +- f6i->offload_failed == offload_failed) ++ READ_ONCE(f6i->offload_failed) == offload_failed) + return; + +- f6i->offload_failed = offload_failed; ++ WRITE_ONCE(f6i->offload_failed, offload_failed); + + if (!rcu_access_pointer(f6i->fib6_node)) + /* The route was removed from the tree, do not send +diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c +index e412817fba2f3..fa6b64c95d3ae 100644 +--- a/net/ipv6/seg6.c ++++ b/net/ipv6/seg6.c +@@ -75,6 +75,65 @@ bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len, bool reduced) + return true; + } + ++struct ipv6_sr_hdr *seg6_get_srh(struct sk_buff *skb, int flags) ++{ ++ struct ipv6_sr_hdr *srh; ++ int len, srhoff = 0; ++ ++ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, &flags) < 0) ++ return NULL; ++ ++ if (!pskb_may_pull(skb, srhoff + sizeof(*srh))) ++ return NULL; ++ ++ srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); ++ ++ len = (srh->hdrlen + 1) << 3; ++ ++ if (!pskb_may_pull(skb, srhoff + len)) ++ return NULL; ++ ++ /* note that pskb_may_pull may change pointers in header; ++ * for this reason it is necessary to reload them when needed. ++ */ ++ srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); ++ ++ if (!seg6_validate_srh(srh, len, true)) ++ return NULL; ++ ++ return srh; ++} ++ ++/* Determine if an ICMP invoking packet contains a segment routing ++ * header. If it does, extract the offset to the true destination ++ * address, which is in the first segment address. ++ */ ++void seg6_icmp_srh(struct sk_buff *skb, struct inet6_skb_parm *opt) ++{ ++ __u16 network_header = skb->network_header; ++ struct ipv6_sr_hdr *srh; ++ ++ /* Update network header to point to the invoking packet ++ * inside the ICMP packet, so we can use the seg6_get_srh() ++ * helper. ++ */ ++ skb_reset_network_header(skb); ++ ++ srh = seg6_get_srh(skb, 0); ++ if (!srh) ++ goto out; ++ ++ if (srh->type != IPV6_SRCRT_TYPE_4) ++ goto out; ++ ++ opt->flags |= IP6SKB_SEG6; ++ opt->srhoff = (unsigned char *)srh - skb->data; ++ ++out: ++ /* Restore the network header back to the ICMP packet */ ++ skb->network_header = network_header; ++} ++ + static struct genl_family seg6_genl_family; + + static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = { +diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c +index 3adc5d9211ad6..d64855010948d 100644 +--- a/net/ipv6/seg6_iptunnel.c ++++ b/net/ipv6/seg6_iptunnel.c +@@ -161,6 +161,14 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) + hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); + + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); ++ ++ /* the control block has been erased, so we have to set the ++ * iif once again. ++ * We read the receiving interface index directly from the ++ * skb->skb_iif as it is done in the IPv4 receiving path (i.e.: ++ * ip_rcv_core(...)). ++ */ ++ IP6CB(skb)->iif = skb->skb_iif; + } + + hdr->nexthdr = NEXTHDR_ROUTING; +diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c +index 2dc40b3f373ef..ef88489c71f52 100644 +--- a/net/ipv6/seg6_local.c ++++ b/net/ipv6/seg6_local.c +@@ -150,40 +150,11 @@ static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt) + return (struct seg6_local_lwt *)lwt->data; + } + +-static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb, int flags) +-{ +- struct ipv6_sr_hdr *srh; +- int len, srhoff = 0; +- +- if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, &flags) < 0) +- return NULL; +- +- if (!pskb_may_pull(skb, srhoff + sizeof(*srh))) +- return NULL; +- +- srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); +- +- len = (srh->hdrlen + 1) << 3; +- +- if (!pskb_may_pull(skb, srhoff + len)) +- return NULL; +- +- /* note that pskb_may_pull may change pointers in header; +- * for this reason it is necessary to reload them when needed. +- */ +- srh = (struct ipv6_sr_hdr *)(skb->data + srhoff); +- +- if (!seg6_validate_srh(srh, len, true)) +- return NULL; +- +- return srh; +-} +- + static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb) + { + struct ipv6_sr_hdr *srh; + +- srh = get_srh(skb, IP6_FH_F_SKIP_RH); ++ srh = seg6_get_srh(skb, IP6_FH_F_SKIP_RH); + if (!srh) + return NULL; + +@@ -200,7 +171,7 @@ static bool decap_and_validate(struct sk_buff *skb, int proto) + struct ipv6_sr_hdr *srh; + unsigned int off = 0; + +- srh = get_srh(skb, 0); ++ srh = seg6_get_srh(skb, 0); + if (srh && srh->segments_left > 0) + return false; + +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index ef0c7a7c18e23..626cb53aa57ab 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -1933,7 +1933,6 @@ static int __net_init sit_init_net(struct net *net) + return 0; + + err_reg_dev: +- ipip6_dev_free(sitn->fb_tunnel_dev); + free_netdev(sitn->fb_tunnel_dev); + err_alloc_dev: + return err; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index b03dd02c9f13c..8eedf59e9cf25 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -107,9 +107,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) + if (dst && dst_hold_safe(dst)) { + const struct rt6_info *rt = (const struct rt6_info *)dst; + +- sk->sk_rx_dst = dst; +- inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +- tcp_inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); ++ rcu_assign_pointer(sk->sk_rx_dst, dst); ++ sk->sk_rx_dst_ifindex = skb->skb_iif; ++ sk->sk_rx_dst_cookie = rt6_get_cookie(rt); + } + } + +@@ -1504,16 +1504,19 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) + opt_skb = skb_clone(skb, sk_gfp_mask(sk, GFP_ATOMIC)); + + if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ +- struct dst_entry *dst = sk->sk_rx_dst; ++ struct dst_entry *dst; ++ ++ dst = rcu_dereference_protected(sk->sk_rx_dst, ++ lockdep_sock_is_held(sk)); + + sock_rps_save_rxhash(sk, skb); + sk_mark_napi_id(sk, skb); + if (dst) { +- if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || ++ if (sk->sk_rx_dst_ifindex != skb->skb_iif || + INDIRECT_CALL_1(dst->ops->check, ip6_dst_check, +- dst, np->rx_dst_cookie) == NULL) { ++ dst, sk->sk_rx_dst_cookie) == NULL) { ++ RCU_INIT_POINTER(sk->sk_rx_dst, NULL); + dst_release(dst); +- sk->sk_rx_dst = NULL; + } + } + +@@ -1875,12 +1878,12 @@ INDIRECT_CALLABLE_SCOPE void tcp_v6_early_demux(struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_edemux; + if (sk_fullsock(sk)) { +- struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); ++ struct dst_entry *dst = rcu_dereference(sk->sk_rx_dst); + + if (dst) +- dst = dst_check(dst, tcp_inet6_sk(sk)->rx_dst_cookie); ++ dst = dst_check(dst, sk->sk_rx_dst_cookie); + if (dst && +- inet_sk(sk)->rx_dst_ifindex == skb->skb_iif) ++ sk->sk_rx_dst_ifindex == skb->skb_iif) + skb_dst_set_noref(skb, dst); + } + } +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 8d785232b4796..932c6f2a54946 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -40,6 +40,7 @@ + #include <net/transp_v6.h> + #include <net/ip6_route.h> + #include <net/raw.h> ++#include <net/seg6.h> + #include <net/tcp_states.h> + #include <net/ip6_checksum.h> + #include <net/ip6_tunnel.h> +@@ -561,7 +562,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + struct ipv6_pinfo *np; + const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; + const struct in6_addr *saddr = &hdr->saddr; +- const struct in6_addr *daddr = &hdr->daddr; ++ const struct in6_addr *daddr = seg6_get_daddr(skb, opt) ? : &hdr->daddr; + struct udphdr *uh = (struct udphdr *)(skb->data+offset); + bool tunnel = false; + struct sock *sk; +@@ -884,7 +885,7 @@ static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) + if (udp_sk_rx_dst_set(sk, dst)) { + const struct rt6_info *rt = (const struct rt6_info *)dst; + +- inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); ++ sk->sk_rx_dst_cookie = rt6_get_cookie(rt); + } + } + +@@ -956,7 +957,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, + struct dst_entry *dst = skb_dst(skb); + int ret; + +- if (unlikely(sk->sk_rx_dst != dst)) ++ if (unlikely(rcu_dereference(sk->sk_rx_dst) != dst)) + udp6_sk_rx_dst_set(sk, dst); + + if (!uh->check && !udp_sk(sk)->no_check6_rx) { +@@ -1070,10 +1071,10 @@ INDIRECT_CALLABLE_SCOPE void udp_v6_early_demux(struct sk_buff *skb) + + skb->sk = sk; + skb->destructor = sock_efree; +- dst = READ_ONCE(sk->sk_rx_dst); ++ dst = rcu_dereference(sk->sk_rx_dst); + + if (dst) +- dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); ++ dst = dst_check(dst, sk->sk_rx_dst_cookie); + if (dst) { + /* set noref for now. + * any place which wants to hold dst has to call +@@ -1204,7 +1205,7 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6, + kfree_skb(skb); + return -EINVAL; + } +- if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { ++ if (datalen > cork->gso_size * UDP_MAX_SEGMENTS) { + kfree_skb(skb); + return -EINVAL; + } +@@ -1435,7 +1436,6 @@ do_udp_sendmsg: + if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; + +- fl6.flowi6_mark = ipc6.sockc.mark; + fl6.flowi6_uid = sk->sk_uid; + + if (msg->msg_controllen) { +@@ -1471,6 +1471,7 @@ do_udp_sendmsg: + ipc6.opt = opt; + + fl6.flowi6_proto = sk->sk_protocol; ++ fl6.flowi6_mark = ipc6.sockc.mark; + fl6.daddr = *daddr; + if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) + fl6.saddr = np->saddr; +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index cce28e3b22323..ef729b1e39ea3 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -9,7 +9,7 @@ + * Copyright 2007, Michael Wu <flamingice@sourmilk.net> + * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2020 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + */ + + /** +@@ -191,7 +191,8 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata, + sband = ieee80211_get_sband(sdata); + if (!sband) + return; +- he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type); ++ he_cap = ieee80211_get_he_iftype_cap(sband, ++ ieee80211_vif_type_p2p(&sdata->vif)); + if (!he_cap) + return; + +diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c +index 430a585875388..74a878f213d3e 100644 +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -9,7 +9,7 @@ + * Copyright 2007, Michael Wu <flamingice@sourmilk.net> + * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2020 Intel Corporation ++ * Copyright (C) 2018 - 2021 Intel Corporation + */ + + #include <linux/ieee80211.h> +@@ -106,7 +106,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, + mgmt->u.action.u.addba_req.start_seq_num = + cpu_to_le16(start_seq_num << 4); + +- ieee80211_tx_skb(sdata, skb); ++ ieee80211_tx_skb_tid(sdata, skb, tid); + } + + void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) +@@ -213,6 +213,8 @@ ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable) + struct ieee80211_txq *txq = sta->sta.txq[tid]; + struct txq_info *txqi; + ++ lockdep_assert_held(&sta->ampdu_mlme.mtx); ++ + if (!txq) + return; + +@@ -290,7 +292,6 @@ static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid) + ieee80211_assign_tid_tx(sta, tid, NULL); + + ieee80211_agg_splice_finish(sta->sdata, tid); +- ieee80211_agg_start_txq(sta, tid, false); + + kfree_rcu(tid_tx, rcu_head); + } +@@ -480,8 +481,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta, + + /* send AddBA request */ + ieee80211_send_addba_request(sdata, sta->sta.addr, tid, +- tid_tx->dialog_token, +- sta->tid_seq[tid] >> 4, ++ tid_tx->dialog_token, tid_tx->ssn, + buf_size, tid_tx->timeout); + + WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)); +@@ -523,6 +523,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) + + params.ssn = sta->tid_seq[tid] >> 4; + ret = drv_ampdu_action(local, sdata, ¶ms); ++ tid_tx->ssn = params.ssn; + if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) { + return; + } else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) { +@@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, + { + struct ieee80211_sub_if_data *sdata = sta->sdata; + bool send_delba = false; ++ bool start_txq = false; + + ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", + sta->sta.addr, tid); +@@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, + send_delba = true; + + ieee80211_remove_tid_tx(sta, tid); ++ start_txq = true; + + unlock_sta: + spin_unlock_bh(&sta->lock); + ++ if (start_txq) ++ ieee80211_agg_start_txq(sta, tid, false); ++ + if (send_delba) + ieee80211_send_delba(sdata, sta->sta.addr, tid, + WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index d69b31c20fe28..1bf83b8d84021 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -80,7 +80,8 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, + } + + /* also validate MU-MIMO change */ +- monitor_sdata = rtnl_dereference(local->monitor_sdata); ++ monitor_sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata); + + if (!monitor_sdata && + (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) +@@ -810,7 +811,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, + + mutex_lock(&local->mtx); + if (local->use_chanctx) { +- sdata = rtnl_dereference(local->monitor_sdata); ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata); + if (sdata) { + ieee80211_vif_release_channel(sdata); + ret = ieee80211_vif_use_channel(sdata, chandef, +@@ -1224,7 +1226,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, + return 0; + + error: ++ mutex_lock(&local->mtx); + ieee80211_vif_release_channel(sdata); ++ mutex_unlock(&local->mtx); ++ + return err; + } + +@@ -2669,7 +2674,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, + sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); + + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { +- sdata = rtnl_dereference(local->monitor_sdata); ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata); + if (!sdata) + return -EOPNOTSUPP; + } +@@ -2729,7 +2735,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, + mutex_unlock(&local->iflist_mtx); + + if (has_monitor) { +- sdata = rtnl_dereference(local->monitor_sdata); ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata); + if (sdata) { + sdata->user_power_level = local->user_power_level; + if (txp_type != sdata->vif.bss_conf.txpower_type) +diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h +index cd3731cbf6c68..c336267f4599c 100644 +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -1219,8 +1219,11 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local, + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); + +- if (local->in_reconfig) ++ /* In reconfig don't transmit now, but mark for waking later */ ++ if (local->in_reconfig) { ++ set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txq->flags); + return; ++ } + + if (!check_sdata_in_driver(sdata)) + return; +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 159af6c3ffb05..6a88195e5abef 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -376,7 +376,7 @@ struct ieee80211_mgd_auth_data { + + u8 key[WLAN_KEY_LEN_WEP104]; + u8 key_len, key_idx; +- bool done; ++ bool done, waiting; + bool peer_confirmed; + bool timeout_started; + +@@ -648,6 +648,26 @@ struct mesh_csa_settings { + struct cfg80211_csa_settings settings; + }; + ++/** ++ * struct mesh_table ++ * ++ * @known_gates: list of known mesh gates and their mpaths by the station. The ++ * gate's mpath may or may not be resolved and active. ++ * @gates_lock: protects updates to known_gates ++ * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr ++ * @walk_head: linked list containing all mesh_path objects ++ * @walk_lock: lock protecting walk_head ++ * @entries: number of entries in the table ++ */ ++struct mesh_table { ++ struct hlist_head known_gates; ++ spinlock_t gates_lock; ++ struct rhashtable rhead; ++ struct hlist_head walk_head; ++ spinlock_t walk_lock; ++ atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ ++}; ++ + struct ieee80211_if_mesh { + struct timer_list housekeeping_timer; + struct timer_list mesh_path_timer; +@@ -722,8 +742,8 @@ struct ieee80211_if_mesh { + /* offset from skb->data while building IE */ + int meshconf_offset; + +- struct mesh_table *mesh_paths; +- struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ ++ struct mesh_table mesh_paths; ++ struct mesh_table mpp_paths; /* Store paths for MPP&MAP */ + int mesh_paths_generation; + int mpp_paths_generation; + }; +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 62c95597704b4..041859b5b71d0 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -588,7 +588,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do + */ + if (local->suspended) { + WARN_ON(local->wowlan); +- WARN_ON(rtnl_dereference(local->monitor_sdata)); ++ WARN_ON(rcu_access_pointer(local->monitor_sdata)); + return; + } + +@@ -932,6 +932,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) + return 0; + + ASSERT_RTNL(); ++ lockdep_assert_wiphy(local->hw.wiphy); + + if (local->monitor_sdata) + return 0; +@@ -999,6 +1000,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) + return; + + ASSERT_RTNL(); ++ lockdep_assert_wiphy(local->hw.wiphy); + + mutex_lock(&local->iflist_mtx); + +diff --git a/net/mac80211/led.h b/net/mac80211/led.h +index fb3aaa3c56069..b71a1428d883c 100644 +--- a/net/mac80211/led.h ++++ b/net/mac80211/led.h +@@ -72,19 +72,19 @@ static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, + #endif + + static inline void +-ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) ++ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, int bytes) + { + #ifdef CONFIG_MAC80211_LEDS +- if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active)) ++ if (atomic_read(&local->tpt_led_active)) + local->tpt_led_trigger->tx_bytes += bytes; + #endif + } + + static inline void +-ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) ++ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, int bytes) + { + #ifdef CONFIG_MAC80211_LEDS +- if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active)) ++ if (atomic_read(&local->tpt_led_active)) + local->tpt_led_trigger->rx_bytes += bytes; + #endif + } +diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h +index 77080b4f87b8a..b2b717a78114f 100644 +--- a/net/mac80211/mesh.h ++++ b/net/mac80211/mesh.h +@@ -127,26 +127,6 @@ struct mesh_path { + u32 path_change_count; + }; + +-/** +- * struct mesh_table +- * +- * @known_gates: list of known mesh gates and their mpaths by the station. The +- * gate's mpath may or may not be resolved and active. +- * @gates_lock: protects updates to known_gates +- * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr +- * @walk_head: linked list containing all mesh_path objects +- * @walk_lock: lock protecting walk_head +- * @entries: number of entries in the table +- */ +-struct mesh_table { +- struct hlist_head known_gates; +- spinlock_t gates_lock; +- struct rhashtable rhead; +- struct hlist_head walk_head; +- spinlock_t walk_lock; +- atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ +-}; +- + /* Recent multicast cache */ + /* RMC_BUCKETS must be a power of 2, maximum 256 */ + #define RMC_BUCKETS 256 +@@ -308,7 +288,7 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, + void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); + void mesh_path_flush_pending(struct mesh_path *mpath); + void mesh_path_tx_pending(struct mesh_path *mpath); +-int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata); ++void mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata); + void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata); + int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); + void mesh_path_timer(struct timer_list *t); +diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c +index 7cab1cf09bf1a..acc1c299f1ae5 100644 +--- a/net/mac80211/mesh_pathtbl.c ++++ b/net/mac80211/mesh_pathtbl.c +@@ -47,32 +47,24 @@ static void mesh_path_rht_free(void *ptr, void *tblptr) + mesh_path_free_rcu(tbl, mpath); + } + +-static struct mesh_table *mesh_table_alloc(void) ++static void mesh_table_init(struct mesh_table *tbl) + { +- struct mesh_table *newtbl; ++ INIT_HLIST_HEAD(&tbl->known_gates); ++ INIT_HLIST_HEAD(&tbl->walk_head); ++ atomic_set(&tbl->entries, 0); ++ spin_lock_init(&tbl->gates_lock); ++ spin_lock_init(&tbl->walk_lock); + +- newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC); +- if (!newtbl) +- return NULL; +- +- INIT_HLIST_HEAD(&newtbl->known_gates); +- INIT_HLIST_HEAD(&newtbl->walk_head); +- atomic_set(&newtbl->entries, 0); +- spin_lock_init(&newtbl->gates_lock); +- spin_lock_init(&newtbl->walk_lock); +- if (rhashtable_init(&newtbl->rhead, &mesh_rht_params)) { +- kfree(newtbl); +- return NULL; +- } +- +- return newtbl; ++ /* rhashtable_init() may fail only in case of wrong ++ * mesh_rht_params ++ */ ++ WARN_ON(rhashtable_init(&tbl->rhead, &mesh_rht_params)); + } + + static void mesh_table_free(struct mesh_table *tbl) + { + rhashtable_free_and_destroy(&tbl->rhead, + mesh_path_rht_free, tbl); +- kfree(tbl); + } + + /** +@@ -238,13 +230,13 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, + struct mesh_path * + mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) + { +- return mpath_lookup(sdata->u.mesh.mesh_paths, dst, sdata); ++ return mpath_lookup(&sdata->u.mesh.mesh_paths, dst, sdata); + } + + struct mesh_path * + mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) + { +- return mpath_lookup(sdata->u.mesh.mpp_paths, dst, sdata); ++ return mpath_lookup(&sdata->u.mesh.mpp_paths, dst, sdata); + } + + static struct mesh_path * +@@ -281,7 +273,7 @@ __mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx) + struct mesh_path * + mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) + { +- return __mesh_path_lookup_by_idx(sdata->u.mesh.mesh_paths, idx); ++ return __mesh_path_lookup_by_idx(&sdata->u.mesh.mesh_paths, idx); + } + + /** +@@ -296,7 +288,7 @@ mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) + struct mesh_path * + mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) + { +- return __mesh_path_lookup_by_idx(sdata->u.mesh.mpp_paths, idx); ++ return __mesh_path_lookup_by_idx(&sdata->u.mesh.mpp_paths, idx); + } + + /** +@@ -309,7 +301,7 @@ int mesh_path_add_gate(struct mesh_path *mpath) + int err; + + rcu_read_lock(); +- tbl = mpath->sdata->u.mesh.mesh_paths; ++ tbl = &mpath->sdata->u.mesh.mesh_paths; + + spin_lock_bh(&mpath->state_lock); + if (mpath->is_gate) { +@@ -418,7 +410,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, + if (!new_mpath) + return ERR_PTR(-ENOMEM); + +- tbl = sdata->u.mesh.mesh_paths; ++ tbl = &sdata->u.mesh.mesh_paths; + spin_lock_bh(&tbl->walk_lock); + mpath = rhashtable_lookup_get_insert_fast(&tbl->rhead, + &new_mpath->rhash, +@@ -460,7 +452,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, + return -ENOMEM; + + memcpy(new_mpath->mpp, mpp, ETH_ALEN); +- tbl = sdata->u.mesh.mpp_paths; ++ tbl = &sdata->u.mesh.mpp_paths; + + spin_lock_bh(&tbl->walk_lock); + ret = rhashtable_lookup_insert_fast(&tbl->rhead, +@@ -489,7 +481,7 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata, + void mesh_plink_broken(struct sta_info *sta) + { + struct ieee80211_sub_if_data *sdata = sta->sdata; +- struct mesh_table *tbl = sdata->u.mesh.mesh_paths; ++ struct mesh_table *tbl = &sdata->u.mesh.mesh_paths; + static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct mesh_path *mpath; + +@@ -548,7 +540,7 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath) + void mesh_path_flush_by_nexthop(struct sta_info *sta) + { + struct ieee80211_sub_if_data *sdata = sta->sdata; +- struct mesh_table *tbl = sdata->u.mesh.mesh_paths; ++ struct mesh_table *tbl = &sdata->u.mesh.mesh_paths; + struct mesh_path *mpath; + struct hlist_node *n; + +@@ -563,7 +555,7 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) + static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata, + const u8 *proxy) + { +- struct mesh_table *tbl = sdata->u.mesh.mpp_paths; ++ struct mesh_table *tbl = &sdata->u.mesh.mpp_paths; + struct mesh_path *mpath; + struct hlist_node *n; + +@@ -597,8 +589,8 @@ static void table_flush_by_iface(struct mesh_table *tbl) + */ + void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) + { +- table_flush_by_iface(sdata->u.mesh.mesh_paths); +- table_flush_by_iface(sdata->u.mesh.mpp_paths); ++ table_flush_by_iface(&sdata->u.mesh.mesh_paths); ++ table_flush_by_iface(&sdata->u.mesh.mpp_paths); + } + + /** +@@ -644,7 +636,7 @@ int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) + /* flush relevant mpp entries first */ + mpp_flush_by_proxy(sdata, addr); + +- err = table_path_del(sdata->u.mesh.mesh_paths, sdata, addr); ++ err = table_path_del(&sdata->u.mesh.mesh_paths, sdata, addr); + sdata->u.mesh.mesh_paths_generation++; + return err; + } +@@ -682,7 +674,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) + struct mesh_path *gate; + bool copy = false; + +- tbl = sdata->u.mesh.mesh_paths; ++ tbl = &sdata->u.mesh.mesh_paths; + + rcu_read_lock(); + hlist_for_each_entry_rcu(gate, &tbl->known_gates, gate_list) { +@@ -762,29 +754,10 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop) + mesh_path_tx_pending(mpath); + } + +-int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) ++void mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) + { +- struct mesh_table *tbl_path, *tbl_mpp; +- int ret; +- +- tbl_path = mesh_table_alloc(); +- if (!tbl_path) +- return -ENOMEM; +- +- tbl_mpp = mesh_table_alloc(); +- if (!tbl_mpp) { +- ret = -ENOMEM; +- goto free_path; +- } +- +- sdata->u.mesh.mesh_paths = tbl_path; +- sdata->u.mesh.mpp_paths = tbl_mpp; +- +- return 0; +- +-free_path: +- mesh_table_free(tbl_path); +- return ret; ++ mesh_table_init(&sdata->u.mesh.mesh_paths); ++ mesh_table_init(&sdata->u.mesh.mpp_paths); + } + + static +@@ -806,12 +779,12 @@ void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata, + + void mesh_path_expire(struct ieee80211_sub_if_data *sdata) + { +- mesh_path_tbl_expire(sdata, sdata->u.mesh.mesh_paths); +- mesh_path_tbl_expire(sdata, sdata->u.mesh.mpp_paths); ++ mesh_path_tbl_expire(sdata, &sdata->u.mesh.mesh_paths); ++ mesh_path_tbl_expire(sdata, &sdata->u.mesh.mpp_paths); + } + + void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata) + { +- mesh_table_free(sdata->u.mesh.mesh_paths); +- mesh_table_free(sdata->u.mesh.mpp_paths); ++ mesh_table_free(&sdata->u.mesh.mesh_paths); ++ mesh_table_free(&sdata->u.mesh.mpp_paths); + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index c0ea3b1aa9e1c..6c8505edce75b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -37,6 +37,7 @@ + #define IEEE80211_AUTH_TIMEOUT_SAE (HZ * 2) + #define IEEE80211_AUTH_MAX_TRIES 3 + #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) ++#define IEEE80211_AUTH_WAIT_SAE_RETRY (HZ * 2) + #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) + #define IEEE80211_ASSOC_TIMEOUT_LONG (HZ / 2) + #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) +@@ -664,7 +665,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata, + ieee80211_ie_build_he_6ghz_cap(sdata, skb); + } + +-static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ++static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +@@ -684,6 +685,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) + enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); + const struct ieee80211_sband_iftype_data *iftd; + struct ieee80211_prep_tx_info info = {}; ++ int ret; + + /* we know it's writable, cast away the const */ + if (assoc_data->ie_len) +@@ -697,7 +699,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); + if (WARN_ON(!chanctx_conf)) { + rcu_read_unlock(); +- return; ++ return -EINVAL; + } + chan = chanctx_conf->def.chan; + rcu_read_unlock(); +@@ -748,7 +750,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) + (iftd ? iftd->vendor_elems.len : 0), + GFP_KERNEL); + if (!skb) +- return; ++ return -ENOMEM; + + skb_reserve(skb, local->hw.extra_tx_headroom); + +@@ -1029,15 +1031,22 @@ skip_rates: + skb_put_data(skb, assoc_data->ie + offset, noffset - offset); + } + +- if (assoc_data->fils_kek_len && +- fils_encrypt_assoc_req(skb, assoc_data) < 0) { +- dev_kfree_skb(skb); +- return; ++ if (assoc_data->fils_kek_len) { ++ ret = fils_encrypt_assoc_req(skb, assoc_data); ++ if (ret < 0) { ++ dev_kfree_skb(skb); ++ return ret; ++ } + } + + pos = skb_tail_pointer(skb); + kfree(ifmgd->assoc_req_ies); + ifmgd->assoc_req_ies = kmemdup(ie_start, pos - ie_start, GFP_ATOMIC); ++ if (!ifmgd->assoc_req_ies) { ++ dev_kfree_skb(skb); ++ return -ENOMEM; ++ } ++ + ifmgd->assoc_req_ies_len = pos - ie_start; + + drv_mgd_prepare_tx(local, sdata, &info); +@@ -1047,6 +1056,8 @@ skip_rates: + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | + IEEE80211_TX_INTFL_MLME_CONN_TX; + ieee80211_tx_skb(sdata, skb); ++ ++ return 0; + } + + void ieee80211_send_pspoll(struct ieee80211_local *local, +@@ -2446,11 +2457,18 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata, + u16 tx_time) + { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +- u16 tid = ieee80211_get_tid(hdr); +- int ac = ieee80211_ac_from_tid(tid); +- struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac]; ++ u16 tid; ++ int ac; ++ struct ieee80211_sta_tx_tspec *tx_tspec; + unsigned long now = jiffies; + ++ if (!ieee80211_is_data_qos(hdr->frame_control)) ++ return; ++ ++ tid = ieee80211_get_tid(hdr); ++ ac = ieee80211_ac_from_tid(tid); ++ tx_tspec = &ifmgd->tx_tspec[ac]; ++ + if (likely(!tx_tspec->admitted_time)) + return; + +@@ -2977,8 +2995,15 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, + (status_code == WLAN_STATUS_ANTI_CLOG_REQUIRED || + (auth_transaction == 1 && + (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || +- status_code == WLAN_STATUS_SAE_PK)))) ++ status_code == WLAN_STATUS_SAE_PK)))) { ++ /* waiting for userspace now */ ++ ifmgd->auth_data->waiting = true; ++ ifmgd->auth_data->timeout = ++ jiffies + IEEE80211_AUTH_WAIT_SAE_RETRY; ++ ifmgd->auth_data->timeout_started = true; ++ run_again(sdata, ifmgd->auth_data->timeout); + goto notify_driver; ++ } + + sdata_info(sdata, "%pM denied authentication (status %d)\n", + mgmt->sa, status_code); +@@ -4444,6 +4469,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) + { + struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; + struct ieee80211_local *local = sdata->local; ++ int ret; + + sdata_assert_lock(sdata); + +@@ -4464,7 +4490,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) + sdata_info(sdata, "associate with %pM (try %d/%d)\n", + assoc_data->bss->bssid, assoc_data->tries, + IEEE80211_ASSOC_MAX_TRIES); +- ieee80211_send_assoc(sdata); ++ ret = ieee80211_send_assoc(sdata); ++ if (ret) ++ return ret; + + if (!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { + assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; +@@ -4537,10 +4565,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) + + if (ifmgd->auth_data && ifmgd->auth_data->timeout_started && + time_after(jiffies, ifmgd->auth_data->timeout)) { +- if (ifmgd->auth_data->done) { ++ if (ifmgd->auth_data->done || ifmgd->auth_data->waiting) { + /* +- * ok ... we waited for assoc but userspace didn't, +- * so let's just kill the auth data ++ * ok ... we waited for assoc or continuation but ++ * userspace didn't do it, so kill the auth data + */ + ieee80211_destroy_auth_data(sdata, false); + } else if (ieee80211_auth(sdata)) { +@@ -5209,7 +5237,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, + */ + if (new_sta) { + u32 rates = 0, basic_rates = 0; +- bool have_higher_than_11mbit; ++ bool have_higher_than_11mbit = false; + int min_rate = INT_MAX, min_rate_index = -1; + const struct cfg80211_bss_ies *ies; + int shift = ieee80211_vif_get_shift(&sdata->vif); +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index c4071b015c188..eab6283b3479c 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -364,7 +364,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, + * the compiler to think we have walked past the end of the + * struct member. + */ +- pos = (void *)&rthdr->it_optional[it_present - rthdr->it_optional]; ++ pos = (void *)&rthdr->it_optional[it_present + 1 - rthdr->it_optional]; + + /* the order of the following fields is important */ + +@@ -1952,7 +1952,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + int keyid = rx->sta->ptk_idx; + sta_ptk = rcu_dereference(rx->sta->ptk[keyid]); + +- if (ieee80211_has_protected(fc)) { ++ if (ieee80211_has_protected(fc) && ++ !(status->flag & RX_FLAG_IV_STRIPPED)) { + cs = rx->sta->cipher_scheme; + keyid = ieee80211_get_keyid(rx->skb, cs); + +@@ -2601,7 +2602,8 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb, + * address, so that the authenticator (e.g. hostapd) will see + * the frame, but bridge won't forward it anywhere else. Note + * that due to earlier filtering, the only other address can +- * be the PAE group address. ++ * be the PAE group address, unless the hardware allowed them ++ * through in 802.3 offloaded mode. + */ + if (unlikely(skb->protocol == sdata->control_port_protocol && + !ether_addr_equal(ehdr->h_dest, sdata->vif.addr))) +@@ -2916,13 +2918,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) + ether_addr_equal(sdata->vif.addr, hdr->addr3)) + return RX_CONTINUE; + +- ac = ieee80211_select_queue_80211(sdata, skb, hdr); ++ ac = ieee802_1d_to_ac[skb->priority]; + q = sdata->vif.hw_queue[ac]; + if (ieee80211_queue_stopped(&local->hw, q)) { + IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); + return RX_DROP_MONITOR; + } +- skb_set_queue_mapping(skb, q); ++ skb_set_queue_mapping(skb, ac); + + if (!--mesh_hdr->ttl) { + if (!is_multicast_ether_addr(hdr->addr1)) +@@ -4517,12 +4519,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, + + /* deliver to local stack */ + skb->protocol = eth_type_trans(skb, fast_rx->dev); +- memset(skb->cb, 0, sizeof(skb->cb)); +- if (rx->list) +- list_add_tail(&skb->list, rx->list); +- else +- netif_receive_skb(skb); +- ++ ieee80211_deliver_skb_to_local_stack(skb, rx); + } + + static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, +@@ -4873,6 +4870,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + struct ieee80211_rate *rate = NULL; + struct ieee80211_supported_band *sband; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + WARN_ON_ONCE(softirq_count() == 0); + +@@ -4931,7 +4929,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + goto drop; + break; + case RX_ENC_VHT: +- if (WARN_ONCE(status->rate_idx > 9 || ++ if (WARN_ONCE(status->rate_idx > 11 || + !status->nss || + status->nss > 8, + "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n", +@@ -4969,9 +4967,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (!(status->flag & RX_FLAG_8023)) + skb = ieee80211_rx_monitor(local, skb, rate); + if (skb) { +- ieee80211_tpt_led_trig_rx(local, +- ((struct ieee80211_hdr *)skb->data)->frame_control, +- skb->len); ++ if ((status->flag & RX_FLAG_8023) || ++ ieee80211_is_data_present(hdr->frame_control)) ++ ieee80211_tpt_led_trig_rx(local, skb->len); + + if (status->flag & RX_FLAG_8023) + __ieee80211_rx_handle_8023(hw, pubsta, skb, list); +diff --git a/net/mac80211/s1g.c b/net/mac80211/s1g.c +index 7e35ab5b61664..4141bc80cdfd6 100644 +--- a/net/mac80211/s1g.c ++++ b/net/mac80211/s1g.c +@@ -104,9 +104,11 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata, + + /* broadcast TWT not supported yet */ + if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) { +- le16p_replace_bits(&twt_agrt->req_type, +- TWT_SETUP_CMD_REJECT, +- IEEE80211_TWT_REQTYPE_SETUP_CMD); ++ twt_agrt->req_type &= ++ ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); ++ twt_agrt->req_type |= ++ le16_encode_bits(TWT_SETUP_CMD_REJECT, ++ IEEE80211_TWT_REQTYPE_SETUP_CMD); + goto out; + } + +diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h +index ba27967820084..e7443fc4669c8 100644 +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -199,6 +199,7 @@ struct tid_ampdu_tx { + u8 stop_initiator; + bool tx_stop; + u16 buf_size; ++ u16 ssn; + + u16 failed_bar_ssn; + bool bar_pending; +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 8921088a5df65..a499b07fee336 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1720,21 +1720,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, + * Returns false if the frame couldn't be transmitted but was queued instead. + */ + static bool __ieee80211_tx(struct ieee80211_local *local, +- struct sk_buff_head *skbs, int led_len, +- struct sta_info *sta, bool txpending) ++ struct sk_buff_head *skbs, struct sta_info *sta, ++ bool txpending) + { + struct ieee80211_tx_info *info; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_vif *vif; + struct sk_buff *skb; + bool result; +- __le16 fc; + + if (WARN_ON(skb_queue_empty(skbs))) + return true; + + skb = skb_peek(skbs); +- fc = ((struct ieee80211_hdr *)skb->data)->frame_control; + info = IEEE80211_SKB_CB(skb); + sdata = vif_to_sdata(info->control.vif); + if (sta && !sta->uploaded) +@@ -1768,8 +1766,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local, + + result = ieee80211_tx_frags(local, vif, sta, skbs, txpending); + +- ieee80211_tpt_led_trig_tx(local, fc, led_len); +- + WARN_ON_ONCE(!skb_queue_empty(skbs)); + + return result; +@@ -1825,15 +1821,15 @@ static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx) + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + ieee80211_tx_result res = TX_CONTINUE; + ++ if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) ++ CALL_TXH(ieee80211_tx_h_rate_ctrl); ++ + if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) { + __skb_queue_tail(&tx->skbs, tx->skb); + tx->skb = NULL; + goto txh_done; + } + +- if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL)) +- CALL_TXH(ieee80211_tx_h_rate_ctrl); +- + CALL_TXH(ieee80211_tx_h_michael_mic_add); + CALL_TXH(ieee80211_tx_h_sequence); + CALL_TXH(ieee80211_tx_h_fragment); +@@ -1919,7 +1915,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, + ieee80211_tx_result res_prepare; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool result = true; +- int led_len; + + if (unlikely(skb->len < 10)) { + dev_kfree_skb(skb); +@@ -1927,7 +1922,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, + } + + /* initialises tx */ +- led_len = skb->len; + res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); + + if (unlikely(res_prepare == TX_DROP)) { +@@ -1950,8 +1944,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, + return true; + + if (!invoke_tx_handlers_late(&tx)) +- result = __ieee80211_tx(local, &tx.skbs, led_len, +- tx.sta, txpending); ++ result = __ieee80211_tx(local, &tx.skbs, tx.sta, txpending); + + return result; + } +@@ -4174,6 +4167,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + struct sk_buff *next; ++ int len = skb->len; + + if (unlikely(skb->len < ETH_HLEN)) { + kfree_skb(skb); +@@ -4220,10 +4214,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, + } + } else { + /* we cannot process non-linear frames on this path */ +- if (skb_linearize(skb)) { +- kfree_skb(skb); +- goto out; +- } ++ if (skb_linearize(skb)) ++ goto out_free; + + /* the frame could be fragmented, software-encrypted, and other + * things so we cannot really handle checksum offload with it - +@@ -4257,7 +4249,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, + goto out; + out_free: + kfree_skb(skb); ++ len = 0; + out: ++ if (len) ++ ieee80211_tpt_led_trig_tx(local, len); + rcu_read_unlock(); + } + +@@ -4395,8 +4390,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, + } + + static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, int led_len, +- struct sta_info *sta, ++ struct sk_buff *skb, struct sta_info *sta, + bool txpending) + { + struct ieee80211_local *local = sdata->local; +@@ -4409,6 +4403,8 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, + if (sta) + sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift); + ++ ieee80211_tpt_led_trig_tx(local, skb->len); ++ + if (ieee80211_queue_skb(local, sdata, sta, skb)) + return true; + +@@ -4497,7 +4493,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, + if (key) + info->control.hw_key = &key->conf; + +- ieee80211_tx_8023(sdata, skb, skb->len, sta, false); ++ ieee80211_tx_8023(sdata, skb, sta, false); + + return; + +@@ -4636,7 +4632,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, + if (IS_ERR(sta) || (sta && !sta->uploaded)) + sta = NULL; + +- result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true); ++ result = ieee80211_tx_8023(sdata, skb, sta, true); + } else { + struct sk_buff_head skbs; + +@@ -4646,7 +4642,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, + hdr = (struct ieee80211_hdr *)skb->data; + sta = sta_info_get(sdata, hdr->addr1); + +- result = __ieee80211_tx(local, &skbs, skb->len, sta, true); ++ result = __ieee80211_tx(local, &skbs, sta, true); + } + + return result; +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 49cb96d251695..2fe71ed9137b0 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -796,7 +796,7 @@ static void __iterate_interfaces(struct ieee80211_local *local, + + sdata = rcu_dereference_check(local->monitor_sdata, + lockdep_is_held(&local->iflist_mtx) || +- lockdep_rtnl_is_held()); ++ lockdep_is_held(&local->hw.wiphy->mtx)); + if (sdata && + (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only || + sdata->flags & IEEE80211_SDATA_IN_DRIVER)) +@@ -943,7 +943,12 @@ static void ieee80211_parse_extension_element(u32 *crc, + struct ieee802_11_elems *elems) + { + const void *data = elem->data + 1; +- u8 len = elem->datalen - 1; ++ u8 len; ++ ++ if (!elem->datalen) ++ return; ++ ++ len = elem->datalen - 1; + + switch (elem->data[0]) { + case WLAN_EID_EXT_HE_MU_EDCA: +@@ -2379,7 +2384,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) + IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); + + /* add interfaces */ +- sdata = rtnl_dereference(local->monitor_sdata); ++ sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); + if (sdata) { + /* in HW restart it exists already */ + WARN_ON(local->resuming); +@@ -2424,7 +2429,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) + WARN_ON(drv_add_chanctx(local, ctx)); + mutex_unlock(&local->chanctx_mtx); + +- sdata = rtnl_dereference(local->monitor_sdata); ++ sdata = wiphy_dereference(local->hw.wiphy, ++ local->monitor_sdata); + if (sdata && ieee80211_sdata_running(sdata)) + ieee80211_assign_chanctx(local, sdata); + } +diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c +index 9ea6004abe1be..62c6733e07923 100644 +--- a/net/mac80211/wme.c ++++ b/net/mac80211/wme.c +@@ -143,7 +143,6 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata, + u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, struct sk_buff *skb) + { +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct mac80211_qos_map *qos_map; + bool qos; + +@@ -156,7 +155,7 @@ u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, + else + qos = false; + +- if (!qos || (info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER)) { ++ if (!qos) { + skb->priority = 0; /* required for correct WPA/11i MIC */ + return IEEE80211_AC_BE; + } +diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c +index a9526ac29dffe..85cc1a28cbe9f 100644 +--- a/net/mctp/af_mctp.c ++++ b/net/mctp/af_mctp.c +@@ -30,6 +30,12 @@ static int mctp_release(struct socket *sock) + return 0; + } + ++/* Generic sockaddr checks, padding checks only so far */ ++static bool mctp_sockaddr_is_ok(const struct sockaddr_mctp *addr) ++{ ++ return !addr->__smctp_pad0 && !addr->__smctp_pad1; ++} ++ + static int mctp_bind(struct socket *sock, struct sockaddr *addr, int addrlen) + { + struct sock *sk = sock->sk; +@@ -49,6 +55,9 @@ static int mctp_bind(struct socket *sock, struct sockaddr *addr, int addrlen) + /* it's a valid sockaddr for MCTP, cast and do protocol checks */ + smctp = (struct sockaddr_mctp *)addr; + ++ if (!mctp_sockaddr_is_ok(smctp)) ++ return -EINVAL; ++ + lock_sock(sk); + + /* TODO: allow rebind */ +@@ -83,6 +92,8 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + return -EINVAL; + if (addr->smctp_family != AF_MCTP) + return -EINVAL; ++ if (!mctp_sockaddr_is_ok(addr)) ++ return -EINVAL; + if (addr->smctp_tag & ~(MCTP_TAG_MASK | MCTP_TAG_OWNER)) + return -EINVAL; + +@@ -172,11 +183,13 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + + addr = msg->msg_name; + addr->smctp_family = AF_MCTP; ++ addr->__smctp_pad0 = 0; + addr->smctp_network = cb->net; + addr->smctp_addr.s_addr = hdr->src; + addr->smctp_type = type; + addr->smctp_tag = hdr->flags_seq_tag & + (MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO); ++ addr->__smctp_pad1 = 0; + msg->msg_namelen = sizeof(*addr); + } + +diff --git a/net/mctp/route.c b/net/mctp/route.c +index 5ca186d53cb0f..fb1bf4ec85296 100644 +--- a/net/mctp/route.c ++++ b/net/mctp/route.c +@@ -760,7 +760,7 @@ static int mctp_route_add(struct mctp_dev *mdev, mctp_eid_t daddr_start, + } + + static int mctp_route_remove(struct mctp_dev *mdev, mctp_eid_t daddr_start, +- unsigned int daddr_extent) ++ unsigned int daddr_extent, unsigned char type) + { + struct net *net = dev_net(mdev->dev); + struct mctp_route *rt, *tmp; +@@ -777,7 +777,8 @@ static int mctp_route_remove(struct mctp_dev *mdev, mctp_eid_t daddr_start, + + list_for_each_entry_safe(rt, tmp, &net->mctp.routes, list) { + if (rt->dev == mdev && +- rt->min == daddr_start && rt->max == daddr_end) { ++ rt->min == daddr_start && rt->max == daddr_end && ++ rt->type == type) { + list_del_rcu(&rt->list); + /* TODO: immediate RTM_DELROUTE */ + mctp_route_release(rt); +@@ -795,7 +796,7 @@ int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr) + + int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr) + { +- return mctp_route_remove(mdev, addr, 0); ++ return mctp_route_remove(mdev, addr, 0, RTN_LOCAL); + } + + /* removes all entries for a given device */ +@@ -975,7 +976,7 @@ static int mctp_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, + if (rtm->rtm_type != RTN_UNICAST) + return -EINVAL; + +- rc = mctp_route_remove(mdev, daddr_start, rtm->rtm_dst_len); ++ rc = mctp_route_remove(mdev, daddr_start, rtm->rtm_dst_len, RTN_UNICAST); + return rc; + } + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index ffeb2df8be7ae..6e587feb705c4 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -1491,22 +1491,52 @@ static void mpls_dev_destroy_rcu(struct rcu_head *head) + kfree(mdev); + } + +-static void mpls_ifdown(struct net_device *dev, int event) ++static int mpls_ifdown(struct net_device *dev, int event) + { + struct mpls_route __rcu **platform_label; + struct net *net = dev_net(dev); +- u8 alive, deleted; + unsigned index; + + platform_label = rtnl_dereference(net->mpls.platform_label); + for (index = 0; index < net->mpls.platform_labels; index++) { + struct mpls_route *rt = rtnl_dereference(platform_label[index]); ++ bool nh_del = false; ++ u8 alive = 0; + + if (!rt) + continue; + +- alive = 0; +- deleted = 0; ++ if (event == NETDEV_UNREGISTER) { ++ u8 deleted = 0; ++ ++ for_nexthops(rt) { ++ struct net_device *nh_dev = ++ rtnl_dereference(nh->nh_dev); ++ ++ if (!nh_dev || nh_dev == dev) ++ deleted++; ++ if (nh_dev == dev) ++ nh_del = true; ++ } endfor_nexthops(rt); ++ ++ /* if there are no more nexthops, delete the route */ ++ if (deleted == rt->rt_nhn) { ++ mpls_route_update(net, index, NULL, NULL); ++ continue; ++ } ++ ++ if (nh_del) { ++ size_t size = sizeof(*rt) + rt->rt_nhn * ++ rt->rt_nh_size; ++ struct mpls_route *orig = rt; ++ ++ rt = kmalloc(size, GFP_KERNEL); ++ if (!rt) ++ return -ENOMEM; ++ memcpy(rt, orig, size); ++ } ++ } ++ + change_nexthops(rt) { + unsigned int nh_flags = nh->nh_flags; + +@@ -1530,16 +1560,15 @@ static void mpls_ifdown(struct net_device *dev, int event) + next: + if (!(nh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN))) + alive++; +- if (!rtnl_dereference(nh->nh_dev)) +- deleted++; + } endfor_nexthops(rt); + + WRITE_ONCE(rt->rt_nhn_alive, alive); + +- /* if there are no more nexthops, delete the route */ +- if (event == NETDEV_UNREGISTER && deleted == rt->rt_nhn) +- mpls_route_update(net, index, NULL, NULL); ++ if (nh_del) ++ mpls_route_update(net, index, rt, NULL); + } ++ ++ return 0; + } + + static void mpls_ifup(struct net_device *dev, unsigned int flags) +@@ -1597,8 +1626,12 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, + return NOTIFY_OK; + + switch (event) { ++ int err; ++ + case NETDEV_DOWN: +- mpls_ifdown(dev, event); ++ err = mpls_ifdown(dev, event); ++ if (err) ++ return notifier_from_errno(err); + break; + case NETDEV_UP: + flags = dev_get_flags(dev); +@@ -1609,13 +1642,18 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, + break; + case NETDEV_CHANGE: + flags = dev_get_flags(dev); +- if (flags & (IFF_RUNNING | IFF_LOWER_UP)) ++ if (flags & (IFF_RUNNING | IFF_LOWER_UP)) { + mpls_ifup(dev, RTNH_F_DEAD | RTNH_F_LINKDOWN); +- else +- mpls_ifdown(dev, event); ++ } else { ++ err = mpls_ifdown(dev, event); ++ if (err) ++ return notifier_from_errno(err); ++ } + break; + case NETDEV_UNREGISTER: +- mpls_ifdown(dev, event); ++ err = mpls_ifdown(dev, event); ++ if (err) ++ return notifier_from_errno(err); + mdev = mpls_dev_get(dev); + if (mdev) { + mpls_dev_sysctl_unregister(dev, mdev); +@@ -1626,8 +1664,6 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, + case NETDEV_CHANGENAME: + mdev = mpls_dev_get(dev); + if (mdev) { +- int err; +- + mpls_dev_sysctl_unregister(dev, mdev); + err = mpls_dev_sysctl_register(dev, mdev); + if (err) +diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c +index b21ff9be04c61..8d1c67b935911 100644 +--- a/net/mptcp/mib.c ++++ b/net/mptcp/mib.c +@@ -35,12 +35,14 @@ static const struct snmp_mib mptcp_snmp_list[] = { + SNMP_MIB_ITEM("AddAddr", MPTCP_MIB_ADDADDR), + SNMP_MIB_ITEM("EchoAdd", MPTCP_MIB_ECHOADD), + SNMP_MIB_ITEM("PortAdd", MPTCP_MIB_PORTADD), ++ SNMP_MIB_ITEM("AddAddrDrop", MPTCP_MIB_ADDADDRDROP), + SNMP_MIB_ITEM("MPJoinPortSynRx", MPTCP_MIB_JOINPORTSYNRX), + SNMP_MIB_ITEM("MPJoinPortSynAckRx", MPTCP_MIB_JOINPORTSYNACKRX), + SNMP_MIB_ITEM("MPJoinPortAckRx", MPTCP_MIB_JOINPORTACKRX), + SNMP_MIB_ITEM("MismatchPortSynRx", MPTCP_MIB_MISMATCHPORTSYNRX), + SNMP_MIB_ITEM("MismatchPortAckRx", MPTCP_MIB_MISMATCHPORTACKRX), + SNMP_MIB_ITEM("RmAddr", MPTCP_MIB_RMADDR), ++ SNMP_MIB_ITEM("RmAddrDrop", MPTCP_MIB_RMADDRDROP), + SNMP_MIB_ITEM("RmSubflow", MPTCP_MIB_RMSUBFLOW), + SNMP_MIB_ITEM("MPPrioTx", MPTCP_MIB_MPPRIOTX), + SNMP_MIB_ITEM("MPPrioRx", MPTCP_MIB_MPPRIORX), +diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h +index ecd3d8b117e0b..2966fcb6548ba 100644 +--- a/net/mptcp/mib.h ++++ b/net/mptcp/mib.h +@@ -28,12 +28,14 @@ enum linux_mptcp_mib_field { + MPTCP_MIB_ADDADDR, /* Received ADD_ADDR with echo-flag=0 */ + MPTCP_MIB_ECHOADD, /* Received ADD_ADDR with echo-flag=1 */ + MPTCP_MIB_PORTADD, /* Received ADD_ADDR with a port-number */ ++ MPTCP_MIB_ADDADDRDROP, /* Dropped incoming ADD_ADDR */ + MPTCP_MIB_JOINPORTSYNRX, /* Received a SYN MP_JOIN with a different port-number */ + MPTCP_MIB_JOINPORTSYNACKRX, /* Received a SYNACK MP_JOIN with a different port-number */ + MPTCP_MIB_JOINPORTACKRX, /* Received an ACK MP_JOIN with a different port-number */ + MPTCP_MIB_MISMATCHPORTSYNRX, /* Received a SYN MP_JOIN with a mismatched port-number */ + MPTCP_MIB_MISMATCHPORTACKRX, /* Received an ACK MP_JOIN with a mismatched port-number */ + MPTCP_MIB_RMADDR, /* Received RM_ADDR */ ++ MPTCP_MIB_RMADDRDROP, /* Dropped incoming RM_ADDR */ + MPTCP_MIB_RMSUBFLOW, /* Remove a subflow */ + MPTCP_MIB_MPPRIOTX, /* Transmit a MP_PRIO */ + MPTCP_MIB_MPPRIORX, /* Received a MP_PRIO */ +diff --git a/net/mptcp/options.c b/net/mptcp/options.c +index f0f22eb4fd5f7..e515ba9ccb5d8 100644 +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -422,28 +422,6 @@ bool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb, + return false; + } + +-/* MP_JOIN client subflow must wait for 4th ack before sending any data: +- * TCP can't schedule delack timer before the subflow is fully established. +- * MPTCP uses the delack timer to do 3rd ack retransmissions +- */ +-static void schedule_3rdack_retransmission(struct sock *sk) +-{ +- struct inet_connection_sock *icsk = inet_csk(sk); +- struct tcp_sock *tp = tcp_sk(sk); +- unsigned long timeout; +- +- /* reschedule with a timeout above RTT, as we must look only for drop */ +- if (tp->srtt_us) +- timeout = tp->srtt_us << 1; +- else +- timeout = TCP_TIMEOUT_INIT; +- +- WARN_ON_ONCE(icsk->icsk_ack.pending & ICSK_ACK_TIMER); +- icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER; +- icsk->icsk_ack.timeout = timeout; +- sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout); +-} +- + static void clear_3rdack_retransmission(struct sock *sk) + { + struct inet_connection_sock *icsk = inet_csk(sk); +@@ -526,7 +504,15 @@ static bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb, + *size = TCPOLEN_MPTCP_MPJ_ACK; + pr_debug("subflow=%p", subflow); + +- schedule_3rdack_retransmission(sk); ++ /* we can use the full delegate action helper only from BH context ++ * If we are in process context - sk is flushing the backlog at ++ * socket lock release time - just set the appropriate flag, will ++ * be handled by the release callback ++ */ ++ if (sock_owned_by_user(sk)) ++ set_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status); ++ else ++ mptcp_subflow_delegate(subflow, MPTCP_DELEGATE_ACK); + return true; + } + return false; +@@ -837,10 +823,13 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, + if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, remaining, opts)) + ret = true; + else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) { ++ unsigned int mp_fail_size; ++ + ret = true; +- if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { +- *size += opt_size; +- remaining -= opt_size; ++ if (mptcp_established_options_mp_fail(sk, &mp_fail_size, ++ remaining - opt_size, opts)) { ++ *size += opt_size + mp_fail_size; ++ remaining -= opt_size - mp_fail_size; + return true; + } + } +@@ -1019,11 +1008,9 @@ static void ack_update_msk(struct mptcp_sock *msk, + old_snd_una = msk->snd_una; + new_snd_una = mptcp_expand_seq(old_snd_una, mp_opt->data_ack, mp_opt->ack64); + +- /* ACK for data not even sent yet and even above recovery bound? Ignore.*/ +- if (unlikely(after64(new_snd_una, snd_nxt))) { +- if (!msk->recovery || after64(new_snd_una, msk->recovery_snd_nxt)) +- new_snd_una = old_snd_una; +- } ++ /* ACK for data not even sent yet? Ignore.*/ ++ if (unlikely(after64(new_snd_una, snd_nxt))) ++ new_snd_una = old_snd_una; + + new_wnd_end = new_snd_una + tcp_sk(ssk)->snd_wnd; + +@@ -1334,6 +1321,7 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, + put_unaligned_be32(mpext->data_len << 16 | + TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); + } ++ ptr += 1; + } + } else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | + OPTION_MPTCP_MPC_ACK) & opts->suboptions) { +diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c +index 6ab386ff32944..d9790d6fbce9c 100644 +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -194,6 +194,8 @@ void mptcp_pm_add_addr_received(struct mptcp_sock *msk, + mptcp_pm_add_addr_send_ack(msk); + } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) { + pm->remote = *addr; ++ } else { ++ __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP); + } + + spin_unlock_bh(&pm->lock); +@@ -234,8 +236,10 @@ void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, + mptcp_event_addr_removed(msk, rm_list->ids[i]); + + spin_lock_bh(&pm->lock); +- mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED); +- pm->rm_list_rx = *rm_list; ++ if (mptcp_pm_schedule_work(msk, MPTCP_PM_RM_ADDR_RECEIVED)) ++ pm->rm_list_rx = *rm_list; ++ else ++ __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_RMADDRDROP); + spin_unlock_bh(&pm->lock); + } + +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index 050eea231528b..cf0f700f46dd9 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -459,6 +459,18 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, bool fullm + return i; + } + ++static struct mptcp_pm_addr_entry * ++__lookup_addr(struct pm_nl_pernet *pernet, struct mptcp_addr_info *info) ++{ ++ struct mptcp_pm_addr_entry *entry; ++ ++ list_for_each_entry(entry, &pernet->local_addr_list, list) { ++ if (addresses_equal(&entry->addr, info, true)) ++ return entry; ++ } ++ return NULL; ++} ++ + static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + { + struct sock *sk = (struct sock *)msk; +@@ -594,6 +606,7 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk) + unsigned int add_addr_accept_max; + struct mptcp_addr_info remote; + unsigned int subflows_max; ++ bool reset_port = false; + int i, nr; + + add_addr_accept_max = mptcp_pm_get_add_addr_accept_max(msk); +@@ -603,15 +616,19 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk) + msk->pm.add_addr_accepted, add_addr_accept_max, + msk->pm.remote.family); + +- if (lookup_subflow_by_daddr(&msk->conn_list, &msk->pm.remote)) ++ remote = msk->pm.remote; ++ if (lookup_subflow_by_daddr(&msk->conn_list, &remote)) + goto add_addr_echo; + ++ /* pick id 0 port, if none is provided the remote address */ ++ if (!remote.port) { ++ reset_port = true; ++ remote.port = sk->sk_dport; ++ } ++ + /* connect to the specified remote address, using whatever + * local address the routing configuration will pick. + */ +- remote = msk->pm.remote; +- if (!remote.port) +- remote.port = sk->sk_dport; + nr = fill_local_addresses_vec(msk, addrs); + + msk->pm.add_addr_accepted++; +@@ -624,8 +641,12 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk) + __mptcp_subflow_connect(sk, &addrs[i], &remote); + spin_lock_bh(&msk->pm.lock); + ++ /* be sure to echo exactly the received address */ ++ if (reset_port) ++ remote.port = 0; ++ + add_addr_echo: +- mptcp_pm_announce_addr(msk, &msk->pm.remote, true); ++ mptcp_pm_announce_addr(msk, &remote, true); + mptcp_pm_nl_addr_send_ack(msk); + } + +@@ -700,6 +721,9 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, + + msk_owned_by_me(msk); + ++ if (sk->sk_state == TCP_LISTEN) ++ return; ++ + if (!rm_list->nr) + return; + +@@ -707,6 +731,8 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, + return; + + for (i = 0; i < rm_list->nr; i++) { ++ bool removed = false; ++ + list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) { + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); + int how = RCV_SHUTDOWN | SEND_SHUTDOWN; +@@ -726,15 +752,19 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk, + mptcp_close_ssk(sk, ssk, subflow); + spin_lock_bh(&msk->pm.lock); + +- if (rm_type == MPTCP_MIB_RMADDR) { +- msk->pm.add_addr_accepted--; +- WRITE_ONCE(msk->pm.accept_addr, true); +- } else if (rm_type == MPTCP_MIB_RMSUBFLOW) { +- msk->pm.local_addr_used--; +- } ++ removed = true; + msk->pm.subflows--; + __MPTCP_INC_STATS(sock_net(sk), rm_type); + } ++ if (!removed) ++ continue; ++ ++ if (rm_type == MPTCP_MIB_RMADDR) { ++ msk->pm.add_addr_accepted--; ++ WRITE_ONCE(msk->pm.accept_addr, true); ++ } else if (rm_type == MPTCP_MIB_RMSUBFLOW) { ++ msk->pm.local_addr_used--; ++ } + } + } + +@@ -857,6 +887,7 @@ out: + static int mptcp_pm_nl_create_listen_socket(struct sock *sk, + struct mptcp_pm_addr_entry *entry) + { ++ int addrlen = sizeof(struct sockaddr_in); + struct sockaddr_storage addr; + struct mptcp_sock *msk; + struct socket *ssock; +@@ -881,8 +912,11 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk, + } + + mptcp_info2sockaddr(&entry->addr, &addr, entry->addr.family); +- err = kernel_bind(ssock, (struct sockaddr *)&addr, +- sizeof(struct sockaddr_in)); ++#if IS_ENABLED(CONFIG_MPTCP_IPV6) ++ if (entry->addr.family == AF_INET6) ++ addrlen = sizeof(struct sockaddr_in6); ++#endif ++ err = kernel_bind(ssock, (struct sockaddr *)&addr, addrlen); + if (err) { + pr_warn("kernel_bind error, err=%d", err); + goto out; +@@ -1716,17 +1750,21 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) + if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP) + bkup = 1; + +- list_for_each_entry(entry, &pernet->local_addr_list, list) { +- if (addresses_equal(&entry->addr, &addr.addr, true)) { +- mptcp_nl_addr_backup(net, &entry->addr, bkup); +- +- if (bkup) +- entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; +- else +- entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP; +- } ++ spin_lock_bh(&pernet->lock); ++ entry = __lookup_addr(pernet, &addr.addr); ++ if (!entry) { ++ spin_unlock_bh(&pernet->lock); ++ return -EINVAL; + } + ++ if (bkup) ++ entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; ++ else ++ entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP; ++ addr = *entry; ++ spin_unlock_bh(&pernet->lock); ++ ++ mptcp_nl_addr_backup(net, &addr.addr, bkup); + return 0; + } + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index d073b21113828..d6def23b8cba0 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -406,9 +406,12 @@ static bool mptcp_pending_data_fin(struct sock *sk, u64 *seq) + static void mptcp_set_datafin_timeout(const struct sock *sk) + { + struct inet_connection_sock *icsk = inet_csk(sk); ++ u32 retransmits; + +- mptcp_sk(sk)->timer_ival = min(TCP_RTO_MAX, +- TCP_RTO_MIN << icsk->icsk_retransmits); ++ retransmits = min_t(u32, icsk->icsk_retransmits, ++ ilog2(TCP_RTO_MAX / TCP_RTO_MIN)); ++ ++ mptcp_sk(sk)->timer_ival = TCP_RTO_MIN << retransmits; + } + + static void __mptcp_set_timeout(struct sock *sk, long tout) +@@ -1505,6 +1508,32 @@ static void mptcp_push_release(struct sock *sk, struct sock *ssk, + release_sock(ssk); + } + ++static void mptcp_update_post_push(struct mptcp_sock *msk, ++ struct mptcp_data_frag *dfrag, ++ u32 sent) ++{ ++ u64 snd_nxt_new = dfrag->data_seq; ++ ++ dfrag->already_sent += sent; ++ ++ msk->snd_burst -= sent; ++ msk->tx_pending_data -= sent; ++ ++ snd_nxt_new += dfrag->already_sent; ++ ++ /* snd_nxt_new can be smaller than snd_nxt in case mptcp ++ * is recovering after a failover. In that event, this re-sends ++ * old segments. ++ * ++ * Thus compute snd_nxt_new candidate based on ++ * the dfrag->data_seq that was sent and the data ++ * that has been handed to the subflow for transmission ++ * and skip update in case it was old dfrag. ++ */ ++ if (likely(after64(snd_nxt_new, msk->snd_nxt))) ++ msk->snd_nxt = snd_nxt_new; ++} ++ + void __mptcp_push_pending(struct sock *sk, unsigned int flags) + { + struct sock *prev_ssk = NULL, *ssk = NULL; +@@ -1523,7 +1552,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags) + int ret = 0; + + prev_ssk = ssk; +- mptcp_flush_join_list(msk); ++ __mptcp_flush_join_list(msk); + ssk = mptcp_subflow_get_send(msk); + + /* First check. If the ssk has changed since +@@ -1548,12 +1577,10 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags) + } + + info.sent += ret; +- dfrag->already_sent += ret; +- msk->snd_nxt += ret; +- msk->snd_burst -= ret; +- msk->tx_pending_data -= ret; + copied += ret; + len -= ret; ++ ++ mptcp_update_post_push(msk, dfrag, ret); + } + WRITE_ONCE(msk->first_pending, mptcp_send_next(sk)); + } +@@ -1597,7 +1624,8 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk) + if (!xmit_ssk) + goto out; + if (xmit_ssk != ssk) { +- mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk)); ++ mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), ++ MPTCP_DELEGATE_SEND); + goto out; + } + +@@ -1606,13 +1634,11 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk) + goto out; + + info.sent += ret; +- dfrag->already_sent += ret; +- msk->snd_nxt += ret; +- msk->snd_burst -= ret; +- msk->tx_pending_data -= ret; + copied += ret; + len -= ret; + first = false; ++ ++ mptcp_update_post_push(msk, dfrag, ret); + } + WRITE_ONCE(msk->first_pending, mptcp_send_next(sk)); + } +@@ -2183,15 +2209,12 @@ bool __mptcp_retransmit_pending_data(struct sock *sk) + return false; + } + +- /* will accept ack for reijected data before re-sending them */ +- if (!msk->recovery || after64(msk->snd_nxt, msk->recovery_snd_nxt)) +- msk->recovery_snd_nxt = msk->snd_nxt; ++ msk->recovery_snd_nxt = msk->snd_nxt; + msk->recovery = true; + mptcp_data_unlock(sk); + + msk->first_pending = rtx_head; + msk->tx_pending_data += msk->snd_nxt - rtx_head->data_seq; +- msk->snd_nxt = rtx_head->data_seq; + msk->snd_burst = 0; + + /* be sure to clear the "sent status" on all re-injected fragments */ +@@ -2881,7 +2904,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err, + */ + if (WARN_ON_ONCE(!new_mptcp_sock)) { + tcp_sk(newsk)->is_mptcp = 0; +- return newsk; ++ goto out; + } + + /* acquire the 2nd reference for the owning socket */ +@@ -2893,6 +2916,8 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err, + MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK); + } + ++out: ++ newsk->sk_kern_sock = kern; + return newsk; + } + +@@ -2940,7 +2965,7 @@ void __mptcp_check_push(struct sock *sk, struct sock *ssk) + if (xmit_ssk == ssk) + __mptcp_subflow_push_pending(sk, ssk); + else if (xmit_ssk) +- mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk)); ++ mptcp_subflow_delegate(mptcp_subflow_ctx(xmit_ssk), MPTCP_DELEGATE_SEND); + } else { + set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags); + } +@@ -2994,18 +3019,50 @@ static void mptcp_release_cb(struct sock *sk) + __mptcp_update_rmem(sk); + } + ++/* MP_JOIN client subflow must wait for 4th ack before sending any data: ++ * TCP can't schedule delack timer before the subflow is fully established. ++ * MPTCP uses the delack timer to do 3rd ack retransmissions ++ */ ++static void schedule_3rdack_retransmission(struct sock *ssk) ++{ ++ struct inet_connection_sock *icsk = inet_csk(ssk); ++ struct tcp_sock *tp = tcp_sk(ssk); ++ unsigned long timeout; ++ ++ if (mptcp_subflow_ctx(ssk)->fully_established) ++ return; ++ ++ /* reschedule with a timeout above RTT, as we must look only for drop */ ++ if (tp->srtt_us) ++ timeout = usecs_to_jiffies(tp->srtt_us >> (3 - 1)); ++ else ++ timeout = TCP_TIMEOUT_INIT; ++ timeout += jiffies; ++ ++ WARN_ON_ONCE(icsk->icsk_ack.pending & ICSK_ACK_TIMER); ++ icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER; ++ icsk->icsk_ack.timeout = timeout; ++ sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); ++} ++ + void mptcp_subflow_process_delegated(struct sock *ssk) + { + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); + struct sock *sk = subflow->conn; + +- mptcp_data_lock(sk); +- if (!sock_owned_by_user(sk)) +- __mptcp_subflow_push_pending(sk, ssk); +- else +- set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags); +- mptcp_data_unlock(sk); +- mptcp_subflow_delegated_done(subflow); ++ if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { ++ mptcp_data_lock(sk); ++ if (!sock_owned_by_user(sk)) ++ __mptcp_subflow_push_pending(sk, ssk); ++ else ++ set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->flags); ++ mptcp_data_unlock(sk); ++ mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND); ++ } ++ if (test_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status)) { ++ schedule_3rdack_retransmission(ssk); ++ mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK); ++ } + } + + static int mptcp_hash(struct sock *sk) +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index dc984676c5eb1..82c5dc4d6b49d 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -401,6 +401,7 @@ struct mptcp_delegated_action { + DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); + + #define MPTCP_DELEGATE_SEND 0 ++#define MPTCP_DELEGATE_ACK 1 + + /* MPTCP subflow context */ + struct mptcp_subflow_context { +@@ -506,23 +507,23 @@ static inline void mptcp_add_pending_subflow(struct mptcp_sock *msk, + + void mptcp_subflow_process_delegated(struct sock *ssk); + +-static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow) ++static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) + { + struct mptcp_delegated_action *delegated; + bool schedule; + ++ /* the caller held the subflow bh socket lock */ ++ lockdep_assert_in_softirq(); ++ + /* The implied barrier pairs with mptcp_subflow_delegated_done(), and + * ensures the below list check sees list updates done prior to status + * bit changes + */ +- if (!test_and_set_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { ++ if (!test_and_set_bit(action, &subflow->delegated_status)) { + /* still on delegated list from previous scheduling */ + if (!list_empty(&subflow->delegated_node)) + return; + +- /* the caller held the subflow bh socket lock */ +- lockdep_assert_in_softirq(); +- + delegated = this_cpu_ptr(&mptcp_delegated_actions); + schedule = list_empty(&delegated->head); + list_add_tail(&subflow->delegated_node, &delegated->head); +@@ -547,16 +548,16 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated) + + static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow) + { +- return test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status); ++ return !!READ_ONCE(subflow->delegated_status); + } + +-static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow) ++static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow, int action) + { + /* pairs with mptcp_subflow_delegate, ensures delegate_node is updated before + * touching the status bit + */ + smp_wmb(); +- clear_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status); ++ clear_bit(action, &subflow->delegated_status); + } + + int mptcp_is_enabled(const struct net *net); +diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c +index 8c03afac5ca03..4bb305342fcc7 100644 +--- a/net/mptcp/sockopt.c ++++ b/net/mptcp/sockopt.c +@@ -523,7 +523,6 @@ static bool mptcp_supported_sockopt(int level, int optname) + case TCP_NODELAY: + case TCP_THIN_LINEAR_TIMEOUTS: + case TCP_CONGESTION: +- case TCP_ULP: + case TCP_CORK: + case TCP_KEEPIDLE: + case TCP_KEEPINTVL: +diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c +index ba9ae482141b0..dda8b76b77988 100644 +--- a/net/ncsi/ncsi-cmd.c ++++ b/net/ncsi/ncsi-cmd.c +@@ -18,6 +18,8 @@ + #include "internal.h" + #include "ncsi-pkt.h" + ++static const int padding_bytes = 26; ++ + u32 ncsi_calculate_checksum(unsigned char *data, int len) + { + u32 checksum = 0; +@@ -213,12 +215,17 @@ static int ncsi_cmd_handler_oem(struct sk_buff *skb, + { + struct ncsi_cmd_oem_pkt *cmd; + unsigned int len; ++ int payload; ++ /* NC-SI spec DSP_0222_1.2.0, section 8.2.2.2 ++ * requires payload to be padded with 0 to ++ * 32-bit boundary before the checksum field. ++ * Ensure the padding bytes are accounted for in ++ * skb allocation ++ */ + ++ payload = ALIGN(nca->payload, 4); + len = sizeof(struct ncsi_cmd_pkt_hdr) + 4; +- if (nca->payload < 26) +- len += 26; +- else +- len += nca->payload; ++ len += max(payload, padding_bytes); + + cmd = skb_put_zero(skb, len); + memcpy(&cmd->mfr_id, nca->data, nca->payload); +@@ -272,6 +279,7 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca) + struct net_device *dev = nd->dev; + int hlen = LL_RESERVED_SPACE(dev); + int tlen = dev->needed_tailroom; ++ int payload; + int len = hlen + tlen; + struct sk_buff *skb; + struct ncsi_request *nr; +@@ -281,14 +289,14 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca) + return NULL; + + /* NCSI command packet has 16-bytes header, payload, 4 bytes checksum. ++ * Payload needs padding so that the checksum field following payload is ++ * aligned to 32-bit boundary. + * The packet needs padding if its payload is less than 26 bytes to + * meet 64 bytes minimal ethernet frame length. + */ + len += sizeof(struct ncsi_cmd_pkt_hdr) + 4; +- if (nca->payload < 26) +- len += 26; +- else +- len += nca->payload; ++ payload = ALIGN(nca->payload, 4); ++ len += max(payload, padding_bytes); + + /* Allocate skb */ + skb = alloc_skb(len, GFP_ATOMIC); +diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c +index bb5f1650f11cb..c189b4c8a1823 100644 +--- a/net/ncsi/ncsi-netlink.c ++++ b/net/ncsi/ncsi-netlink.c +@@ -112,7 +112,11 @@ static int ncsi_write_package_info(struct sk_buff *skb, + pnest = nla_nest_start_noflag(skb, NCSI_PKG_ATTR); + if (!pnest) + return -ENOMEM; +- nla_put_u32(skb, NCSI_PKG_ATTR_ID, np->id); ++ rc = nla_put_u32(skb, NCSI_PKG_ATTR_ID, np->id); ++ if (rc) { ++ nla_nest_cancel(skb, pnest); ++ return rc; ++ } + if ((0x1 << np->id) == ndp->package_whitelist) + nla_put_flag(skb, NCSI_PKG_ATTR_FORCED); + cnest = nla_nest_start_noflag(skb, NCSI_PKG_ATTR_CHANNEL_LIST); +diff --git a/net/netfilter/core.c b/net/netfilter/core.c +index 63d032191e626..60332fdb6dd44 100644 +--- a/net/netfilter/core.c ++++ b/net/netfilter/core.c +@@ -406,14 +406,15 @@ static int __nf_register_net_hook(struct net *net, int pf, + p = nf_entry_dereference(*pp); + new_hooks = nf_hook_entries_grow(p, reg); + +- if (!IS_ERR(new_hooks)) ++ if (!IS_ERR(new_hooks)) { ++ hooks_validate(new_hooks); + rcu_assign_pointer(*pp, new_hooks); ++ } + + mutex_unlock(&nf_hook_mutex); + if (IS_ERR(new_hooks)) + return PTR_ERR(new_hooks); + +- hooks_validate(new_hooks); + #ifdef CONFIG_NETFILTER_INGRESS + if (nf_ingress_hook(reg, pf)) + net_inc_ingress_queue(); +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 128690c512dff..393058a43aa73 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -1964,7 +1964,6 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int + struct ip_vs_proto_data *pd; + struct ip_vs_conn *cp; + int ret, pkts; +- int conn_reuse_mode; + struct sock *sk; + + /* Already marked as IPVS request or reply? */ +@@ -2041,15 +2040,16 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int + cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto, + ipvs, af, skb, &iph); + +- conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); +- if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { ++ if (!iph.fragoffs && is_new_conn(skb, &iph) && cp) { ++ int conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); + bool old_ct = false, resched = false; + + if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && + unlikely(!atomic_read(&cp->dest->weight))) { + resched = true; + old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); +- } else if (is_new_conn_expected(cp, conn_reuse_mode)) { ++ } else if (conn_reuse_mode && ++ is_new_conn_expected(cp, conn_reuse_mode)) { + old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); + if (!atomic_read(&cp->n_control)) { + resched = true; +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index 770a63103c7a4..7f79974607643 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -684,7 +684,7 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) + + tstamp = nf_conn_tstamp_find(ct); + if (tstamp) { +- s32 timeout = ct->timeout - nfct_time_stamp; ++ s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; + + tstamp->stop = ktime_get_real_ns(); + if (timeout < 0) +@@ -1036,7 +1036,7 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx) + } + + /* We want the clashing entry to go away real soon: 1 second timeout. */ +- loser_ct->timeout = nfct_time_stamp + HZ; ++ WRITE_ONCE(loser_ct->timeout, nfct_time_stamp + HZ); + + /* IPS_NAT_CLASH removes the entry automatically on the first + * reply. Also prevents UDP tracker from moving the entry to +@@ -1560,7 +1560,7 @@ __nf_conntrack_alloc(struct net *net, + /* save hash for reusing when confirming */ + *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; + ct->status = 0; +- ct->timeout = 0; ++ WRITE_ONCE(ct->timeout, 0); + write_pnet(&ct->ct_net, net); + memset(&ct->__nfct_init_offset, 0, + offsetof(struct nf_conn, proto) - +@@ -1922,15 +1922,17 @@ repeat: + pr_debug("nf_conntrack_in: Can't track with proto module\n"); + nf_conntrack_put(&ct->ct_general); + skb->_nfct = 0; +- NF_CT_STAT_INC_ATOMIC(state->net, invalid); +- if (ret == -NF_DROP) +- NF_CT_STAT_INC_ATOMIC(state->net, drop); + /* Special case: TCP tracker reports an attempt to reopen a + * closed/aborted connection. We have to go back and create a + * fresh conntrack. + */ + if (ret == -NF_REPEAT) + goto repeat; ++ ++ NF_CT_STAT_INC_ATOMIC(state->net, invalid); ++ if (ret == -NF_DROP) ++ NF_CT_STAT_INC_ATOMIC(state->net, drop); ++ + ret = -ret; + goto out; + } +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index f1e5443fe7c74..1c02be04aaf5c 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -1011,11 +1011,9 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) + CTA_TUPLE_REPLY, + filter->family, + &filter->zone, +- filter->orig_flags); +- if (err < 0) { +- err = -EINVAL; ++ filter->reply_flags); ++ if (err < 0) + goto err_filter; +- } + } + + return filter; +@@ -2000,7 +1998,7 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, + + if (timeout > INT_MAX) + timeout = INT_MAX; +- ct->timeout = nfct_time_stamp + (u32)timeout; ++ WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout); + + if (test_bit(IPS_DYING_BIT, &ct->status)) + return -ETIME; +@@ -2312,7 +2310,8 @@ ctnetlink_create_conntrack(struct net *net, + if (helper->from_nlattr) + helper->from_nlattr(helpinfo, ct); + +- /* not in hash table yet so not strictly necessary */ ++ /* disable helper auto-assignment for this entry */ ++ ct->status |= IPS_HELPER; + RCU_INIT_POINTER(help->helper, helper); + } + } else { +diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c +index 2394238d01c91..5a936334b517a 100644 +--- a/net/netfilter/nf_conntrack_proto_sctp.c ++++ b/net/netfilter/nf_conntrack_proto_sctp.c +@@ -489,6 +489,15 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, + pr_debug("Setting vtag %x for dir %d\n", + ih->init_tag, !dir); + ct->proto.sctp.vtag[!dir] = ih->init_tag; ++ ++ /* don't renew timeout on init retransmit so ++ * port reuse by client or NAT middlebox cannot ++ * keep entry alive indefinitely (incl. nat info). ++ */ ++ if (new_state == SCTP_CONNTRACK_CLOSED && ++ old_state == SCTP_CONNTRACK_CLOSED && ++ nf_ct_is_confirmed(ct)) ++ ignore = true; + } + + ct->proto.sctp.state = new_state; +diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c +index f8e3c0d2602f6..3b516cffc779b 100644 +--- a/net/netfilter/nf_conntrack_proto_udp.c ++++ b/net/netfilter/nf_conntrack_proto_udp.c +@@ -104,10 +104,13 @@ int nf_conntrack_udp_packet(struct nf_conn *ct, + */ + if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { + unsigned long extra = timeouts[UDP_CT_UNREPLIED]; ++ bool stream = false; + + /* Still active after two seconds? Extend timeout. */ +- if (time_after(jiffies, ct->proto.udp.stream_ts)) ++ if (time_after(jiffies, ct->proto.udp.stream_ts)) { + extra = timeouts[UDP_CT_REPLIED]; ++ stream = true; ++ } + + nf_ct_refresh_acct(ct, ctinfo, skb, extra); + +@@ -116,7 +119,7 @@ int nf_conntrack_udp_packet(struct nf_conn *ct, + return NF_ACCEPT; + + /* Also, more likely to be important, and not a probe */ +- if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) ++ if (stream && !test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) + nf_conntrack_event_cache(IPCT_ASSURED, ct); + } else { + nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]); +diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c +index 87a7388b6c894..ed37bb9b4e588 100644 +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -201,8 +201,8 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) + if (timeout < 0) + timeout = 0; + +- if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout) +- ct->timeout = nfct_time_stamp + timeout; ++ if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout) ++ WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout); + } + + static void flow_offload_fixup_ct_state(struct nf_conn *ct) +diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c +index d6bf1b2cd541b..b561e0a44a45f 100644 +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -65,11 +65,11 @@ static void nf_flow_rule_lwt_match(struct nf_flow_match *match, + sizeof(struct in6_addr)); + if (memcmp(&key->enc_ipv6.src, &in6addr_any, + sizeof(struct in6_addr))) +- memset(&key->enc_ipv6.src, 0xff, ++ memset(&mask->enc_ipv6.src, 0xff, + sizeof(struct in6_addr)); + if (memcmp(&key->enc_ipv6.dst, &in6addr_any, + sizeof(struct in6_addr))) +- memset(&key->enc_ipv6.dst, 0xff, ++ memset(&mask->enc_ipv6.dst, 0xff, + sizeof(struct in6_addr)); + enc_keys |= BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS); + key->enc_control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; +diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c +index 6d12afabfe8a3..63d1516816b1f 100644 +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -46,6 +46,15 @@ void nf_unregister_queue_handler(void) + } + EXPORT_SYMBOL(nf_unregister_queue_handler); + ++static void nf_queue_sock_put(struct sock *sk) ++{ ++#ifdef CONFIG_INET ++ sock_gen_put(sk); ++#else ++ sock_put(sk); ++#endif ++} ++ + static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) + { + struct nf_hook_state *state = &entry->state; +@@ -54,7 +63,7 @@ static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) + dev_put(state->in); + dev_put(state->out); + if (state->sk) +- sock_put(state->sk); ++ nf_queue_sock_put(state->sk); + + #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) + dev_put(entry->physin); +@@ -87,19 +96,21 @@ static void __nf_queue_entry_init_physdevs(struct nf_queue_entry *entry) + } + + /* Bump dev refs so they don't vanish while packet is out */ +-void nf_queue_entry_get_refs(struct nf_queue_entry *entry) ++bool nf_queue_entry_get_refs(struct nf_queue_entry *entry) + { + struct nf_hook_state *state = &entry->state; + ++ if (state->sk && !refcount_inc_not_zero(&state->sk->sk_refcnt)) ++ return false; ++ + dev_hold(state->in); + dev_hold(state->out); +- if (state->sk) +- sock_hold(state->sk); + + #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) + dev_hold(entry->physin); + dev_hold(entry->physout); + #endif ++ return true; + } + EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs); + +@@ -169,6 +180,18 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, + break; + } + ++ if (skb_sk_is_prefetched(skb)) { ++ struct sock *sk = skb->sk; ++ ++ if (!sk_is_refcounted(sk)) { ++ if (!refcount_inc_not_zero(&sk->sk_refcnt)) ++ return -ENOTCONN; ++ ++ /* drop refcount on skb_orphan */ ++ skb->destructor = sock_edemux; ++ } ++ } ++ + entry = kmalloc(sizeof(*entry) + route_key_size, GFP_ATOMIC); + if (!entry) + return -ENOMEM; +@@ -187,7 +210,10 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, + + __nf_queue_entry_init_physdevs(entry); + +- nf_queue_entry_get_refs(entry); ++ if (!nf_queue_entry_get_refs(entry)) { ++ kfree(entry); ++ return -ENOTCONN; ++ } + + switch (entry->state.pf) { + case AF_INET: +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index c0851fec11d46..2b2e0210a7f9e 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -4481,12 +4481,12 @@ struct nft_set_elem_catchall { + static void nft_set_catchall_destroy(const struct nft_ctx *ctx, + struct nft_set *set) + { +- struct nft_set_elem_catchall *catchall; ++ struct nft_set_elem_catchall *next, *catchall; + +- list_for_each_entry_rcu(catchall, &set->catchall_list, list) { ++ list_for_each_entry_safe(catchall, next, &set->catchall_list, list) { + list_del_rcu(&catchall->list); + nft_set_elem_destroy(set, catchall->elem, true); +- kfree_rcu(catchall); ++ kfree_rcu(catchall, rcu); + } + } + +@@ -5653,7 +5653,7 @@ static void nft_setelem_catchall_remove(const struct net *net, + list_for_each_entry_safe(catchall, next, &set->catchall_list, list) { + if (catchall->elem == elem->priv) { + list_del_rcu(&catchall->list); +- kfree_rcu(catchall); ++ kfree_rcu(catchall, rcu); + break; + } + } +@@ -6535,12 +6535,15 @@ static int nf_tables_updobj(const struct nft_ctx *ctx, + { + struct nft_object *newobj; + struct nft_trans *trans; +- int err; ++ int err = -ENOMEM; ++ ++ if (!try_module_get(type->owner)) ++ return -ENOENT; + + trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ, + sizeof(struct nft_trans_obj)); + if (!trans) +- return -ENOMEM; ++ goto err_trans; + + newobj = nft_obj_init(ctx, type, attr); + if (IS_ERR(newobj)) { +@@ -6557,6 +6560,8 @@ static int nf_tables_updobj(const struct nft_ctx *ctx, + + err_free_trans: + kfree(trans); ++err_trans: ++ module_put(type->owner); + return err; + } + +@@ -8169,7 +8174,7 @@ static void nft_obj_commit_update(struct nft_trans *trans) + if (obj->ops->update) + obj->ops->update(obj, newobj); + +- kfree(newobj); ++ nft_obj_destroy(&trans->ctx, newobj); + } + + static void nft_commit_release(struct nft_trans *trans) +@@ -8914,7 +8919,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) + break; + case NFT_MSG_NEWOBJ: + if (nft_trans_obj_update(trans)) { +- kfree(nft_trans_obj_newobj(trans)); ++ nft_obj_destroy(&trans->ctx, nft_trans_obj_newobj(trans)); + nft_trans_destroy(trans); + } else { + trans->ctx.table->use--; +@@ -9574,10 +9579,13 @@ EXPORT_SYMBOL_GPL(__nft_release_basechain); + + static void __nft_release_hook(struct net *net, struct nft_table *table) + { ++ struct nft_flowtable *flowtable; + struct nft_chain *chain; + + list_for_each_entry(chain, &table->chains, list) + nf_tables_unregister_hook(net, table, chain); ++ list_for_each_entry(flowtable, &table->flowtables, list) ++ nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list); + } + + static void __nft_release_hooks(struct net *net) +diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c +index 9656c16462222..2d36952b13920 100644 +--- a/net/netfilter/nf_tables_offload.c ++++ b/net/netfilter/nf_tables_offload.c +@@ -94,7 +94,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net, + + expr = nft_expr_first(rule); + while (nft_expr_more(rule, expr)) { +- if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION) ++ if (expr->ops->offload_action && ++ expr->ops->offload_action(expr)) + num_actions++; + + expr = nft_expr_next(expr); +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index 691ef4cffdd90..7f83f9697fc14 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -556,7 +556,8 @@ __build_packet_message(struct nfnl_log_net *log, + goto nla_put_failure; + + if (indev && skb->dev && +- skb->mac_header != skb->network_header) { ++ skb_mac_header_was_set(skb) && ++ skb_mac_header_len(skb) != 0) { + struct nfulnl_msg_packet_hw phw; + int len; + +diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c +index 4c3fbaaeb1030..8787d0613ad83 100644 +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -560,7 +560,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, + goto nla_put_failure; + + if (indev && entskb->dev && +- entskb->mac_header != entskb->network_header) { ++ skb_mac_header_was_set(entskb) && ++ skb_mac_header_len(entskb) != 0) { + struct nfqnl_msg_packet_hw phw; + int len; + +@@ -709,9 +710,15 @@ static struct nf_queue_entry * + nf_queue_entry_dup(struct nf_queue_entry *e) + { + struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC); +- if (entry) +- nf_queue_entry_get_refs(entry); +- return entry; ++ ++ if (!entry) ++ return NULL; ++ ++ if (nf_queue_entry_get_refs(entry)) ++ return entry; ++ ++ kfree(entry); ++ return NULL; + } + + #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) +diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c +index bbf3fcba3df40..5b5c607fbf83f 100644 +--- a/net/netfilter/nft_dup_netdev.c ++++ b/net/netfilter/nft_dup_netdev.c +@@ -67,6 +67,11 @@ static int nft_dup_netdev_offload(struct nft_offload_ctx *ctx, + return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_MIRRED, oif); + } + ++static bool nft_dup_netdev_offload_action(const struct nft_expr *expr) ++{ ++ return true; ++} ++ + static struct nft_expr_type nft_dup_netdev_type; + static const struct nft_expr_ops nft_dup_netdev_ops = { + .type = &nft_dup_netdev_type, +@@ -75,6 +80,7 @@ static const struct nft_expr_ops nft_dup_netdev_ops = { + .init = nft_dup_netdev_init, + .dump = nft_dup_netdev_dump, + .offload = nft_dup_netdev_offload, ++ .offload_action = nft_dup_netdev_offload_action, + }; + + static struct nft_expr_type nft_dup_netdev_type __read_mostly = { +diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c +index 6ba3256fa8449..87f3af4645d9c 100644 +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -198,17 +198,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx, + return -EBUSY; + + priv->op = ntohl(nla_get_be32(tb[NFTA_DYNSET_OP])); +- switch (priv->op) { +- case NFT_DYNSET_OP_ADD: +- case NFT_DYNSET_OP_DELETE: +- break; +- case NFT_DYNSET_OP_UPDATE: +- if (!(set->flags & NFT_SET_TIMEOUT)) +- return -EOPNOTSUPP; +- break; +- default: ++ if (priv->op > NFT_DYNSET_OP_DELETE) + return -EOPNOTSUPP; +- } + + timeout = 0; + if (tb[NFTA_DYNSET_TIMEOUT] != NULL) { +diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c +index af4ee874a067c..dbe1f2e7dd9ed 100644 +--- a/net/netfilter/nft_exthdr.c ++++ b/net/netfilter/nft_exthdr.c +@@ -236,7 +236,7 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, + + tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, &tcphdr_len); + if (!tcph) +- return; ++ goto err; + + opt = (u8 *)tcph; + for (i = sizeof(*tcph); i < tcphdr_len - 1; i += optl) { +@@ -251,16 +251,16 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, + continue; + + if (i + optl > tcphdr_len || priv->len + priv->offset > optl) +- return; ++ goto err; + + if (skb_ensure_writable(pkt->skb, + nft_thoff(pkt) + i + priv->len)) +- return; ++ goto err; + + tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, + &tcphdr_len); + if (!tcph) +- return; ++ goto err; + + offset = i + priv->offset; + +@@ -303,6 +303,9 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, + + return; + } ++ return; ++err: ++ regs->verdict.code = NFT_BREAK; + } + + static void nft_exthdr_sctp_eval(const struct nft_expr *expr, +diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c +index cd59afde5b2f8..7730409f6f091 100644 +--- a/net/netfilter/nft_fwd_netdev.c ++++ b/net/netfilter/nft_fwd_netdev.c +@@ -77,6 +77,11 @@ static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx, + return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_REDIRECT, oif); + } + ++static bool nft_fwd_netdev_offload_action(const struct nft_expr *expr) ++{ ++ return true; ++} ++ + struct nft_fwd_neigh { + u8 sreg_dev; + u8 sreg_addr; +@@ -219,6 +224,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = { + .dump = nft_fwd_netdev_dump, + .validate = nft_fwd_validate, + .offload = nft_fwd_netdev_offload, ++ .offload_action = nft_fwd_netdev_offload_action, + }; + + static const struct nft_expr_ops * +diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c +index 90c64d27ae532..d0f67d325bdfd 100644 +--- a/net/netfilter/nft_immediate.c ++++ b/net/netfilter/nft_immediate.c +@@ -213,6 +213,16 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx, + return 0; + } + ++static bool nft_immediate_offload_action(const struct nft_expr *expr) ++{ ++ const struct nft_immediate_expr *priv = nft_expr_priv(expr); ++ ++ if (priv->dreg == NFT_REG_VERDICT) ++ return true; ++ ++ return false; ++} ++ + static const struct nft_expr_ops nft_imm_ops = { + .type = &nft_imm_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), +@@ -224,7 +234,7 @@ static const struct nft_expr_ops nft_imm_ops = { + .dump = nft_immediate_dump, + .validate = nft_immediate_validate, + .offload = nft_immediate_offload, +- .offload_flags = NFT_OFFLOAD_F_ACTION, ++ .offload_action = nft_immediate_offload_action, + }; + + struct nft_expr_type nft_imm_type __read_mostly = { +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index a44b14f6c0dc0..132875cd7fff2 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -502,6 +502,9 @@ static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt, + struct sk_buff *skb, + unsigned int *l4csum_offset) + { ++ if (pkt->fragoff) ++ return -1; ++ + switch (pkt->tprot) { + case IPPROTO_TCP: + *l4csum_offset = offsetof(struct tcphdr, check); +diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c +index dce866d93feed..2c8051d8cca69 100644 +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -1290,6 +1290,11 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old) + if (!new->scratch_aligned) + goto out_scratch; + #endif ++ for_each_possible_cpu(i) ++ *per_cpu_ptr(new->scratch, i) = NULL; ++ ++ if (pipapo_realloc_scratch(new, old->bsize_max)) ++ goto out_scratch_realloc; + + rcu_head_init(&new->rcu); + +@@ -1334,6 +1339,9 @@ out_lt: + kvfree(dst->lt); + dst--; + } ++out_scratch_realloc: ++ for_each_possible_cpu(i) ++ kfree(*per_cpu_ptr(new->scratch, i)); + #ifdef NFT_PIPAPO_ALIGN + free_percpu(new->scratch_aligned); + #endif +diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c +index e517663e0cd17..6f4116e729581 100644 +--- a/net/netfilter/nft_set_pipapo_avx2.c ++++ b/net/netfilter/nft_set_pipapo_avx2.c +@@ -886,7 +886,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill, + NFT_PIPAPO_AVX2_BUCKET_LOAD8(4, lt, 4, pkt[4], bsize); + + NFT_PIPAPO_AVX2_AND(5, 0, 1); +- NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 6, pkt[5], bsize); ++ NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 5, pkt[5], bsize); + NFT_PIPAPO_AVX2_AND(7, 2, 3); + + /* Stall */ +diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c +index a0109fa1e92d0..1133e06f3c40e 100644 +--- a/net/netfilter/nft_synproxy.c ++++ b/net/netfilter/nft_synproxy.c +@@ -191,8 +191,10 @@ static int nft_synproxy_do_init(const struct nft_ctx *ctx, + if (err) + goto nf_ct_failure; + err = nf_synproxy_ipv6_init(snet, ctx->net); +- if (err) ++ if (err) { ++ nf_synproxy_ipv4_fini(snet, ctx->net); + goto nf_ct_failure; ++ } + break; + } + +diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c +index 5e6459e116055..7013f55f05d1e 100644 +--- a/net/netfilter/xt_socket.c ++++ b/net/netfilter/xt_socket.c +@@ -220,8 +220,10 @@ static void socket_mt_destroy(const struct xt_mtdtor_param *par) + { + if (par->family == NFPROTO_IPV4) + nf_defrag_ipv4_disable(par->net); ++#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) + else if (par->family == NFPROTO_IPV6) +- nf_defrag_ipv4_disable(par->net); ++ nf_defrag_ipv6_disable(par->net); ++#endif + } + + static struct xt_match socket_mt_reg[] __read_mostly = { +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index ada47e59647a0..81ba8e51e01ff 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1871,6 +1871,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + ++ if (len == 0) { ++ pr_warn_once("Zero length message leads to an empty skb\n"); ++ return -ENODATA; ++ } ++ + err = scm_send(sock, msg, &scm, true); + if (err < 0) + return err; +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 6d16e1ab1a8ab..e5c8a295e6406 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -298,7 +298,7 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, + { + struct sock *sk = sock->sk; + struct nr_sock *nr = nr_sk(sk); +- unsigned long opt; ++ unsigned int opt; + + if (level != SOL_NETROM) + return -ENOPROTOOPT; +@@ -306,18 +306,18 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, + if (optlen < sizeof(unsigned int)) + return -EINVAL; + +- if (copy_from_sockptr(&opt, optval, sizeof(unsigned int))) ++ if (copy_from_sockptr(&opt, optval, sizeof(opt))) + return -EFAULT; + + switch (optname) { + case NETROM_T1: +- if (opt < 1 || opt > ULONG_MAX / HZ) ++ if (opt < 1 || opt > UINT_MAX / HZ) + return -EINVAL; + nr->t1 = opt * HZ; + return 0; + + case NETROM_T2: +- if (opt < 1 || opt > ULONG_MAX / HZ) ++ if (opt < 1 || opt > UINT_MAX / HZ) + return -EINVAL; + nr->t2 = opt * HZ; + return 0; +@@ -329,13 +329,13 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, + return 0; + + case NETROM_T4: +- if (opt < 1 || opt > ULONG_MAX / HZ) ++ if (opt < 1 || opt > UINT_MAX / HZ) + return -EINVAL; + nr->t4 = opt * HZ; + return 0; + + case NETROM_IDLE: +- if (opt > ULONG_MAX / (60 * HZ)) ++ if (opt > UINT_MAX / (60 * HZ)) + return -EINVAL; + nr->idle = opt * 60 * HZ; + return 0; +diff --git a/net/nfc/core.c b/net/nfc/core.c +index 3c645c1d99c9b..dc7a2404efdf9 100644 +--- a/net/nfc/core.c ++++ b/net/nfc/core.c +@@ -94,13 +94,13 @@ int nfc_dev_up(struct nfc_dev *dev) + + device_lock(&dev->dev); + +- if (dev->rfkill && rfkill_blocked(dev->rfkill)) { +- rc = -ERFKILL; ++ if (!device_is_registered(&dev->dev)) { ++ rc = -ENODEV; + goto error; + } + +- if (!device_is_registered(&dev->dev)) { +- rc = -ENODEV; ++ if (dev->rfkill && rfkill_blocked(dev->rfkill)) { ++ rc = -ERFKILL; + goto error; + } + +@@ -1125,11 +1125,7 @@ int nfc_register_device(struct nfc_dev *dev) + if (rc) + pr_err("Could not register llcp device\n"); + +- rc = nfc_genl_device_added(dev); +- if (rc) +- pr_debug("The userspace won't be notified that the device %s was added\n", +- dev_name(&dev->dev)); +- ++ device_lock(&dev->dev); + dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev, + RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev); + if (dev->rfkill) { +@@ -1138,6 +1134,12 @@ int nfc_register_device(struct nfc_dev *dev) + dev->rfkill = NULL; + } + } ++ device_unlock(&dev->dev); ++ ++ rc = nfc_genl_device_added(dev); ++ if (rc) ++ pr_debug("The userspace won't be notified that the device %s was added\n", ++ dev_name(&dev->dev)); + + return 0; + } +@@ -1154,10 +1156,17 @@ void nfc_unregister_device(struct nfc_dev *dev) + + pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + ++ rc = nfc_genl_device_removed(dev); ++ if (rc) ++ pr_debug("The userspace won't be notified that the device %s " ++ "was removed\n", dev_name(&dev->dev)); ++ ++ device_lock(&dev->dev); + if (dev->rfkill) { + rfkill_unregister(dev->rfkill); + rfkill_destroy(dev->rfkill); + } ++ device_unlock(&dev->dev); + + if (dev->ops->check_presence) { + device_lock(&dev->dev); +@@ -1167,11 +1176,6 @@ void nfc_unregister_device(struct nfc_dev *dev) + cancel_work_sync(&dev->check_pres_work); + } + +- rc = nfc_genl_device_removed(dev); +- if (rc) +- pr_debug("The userspace won't be notified that the device %s " +- "was removed\n", dev_name(&dev->dev)); +- + nfc_llcp_unregister_device(dev); + + mutex_lock(&nfc_devlist_mutex); +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 6cfd30fc07985..0b93a17b9f11f 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -789,6 +789,11 @@ static int llcp_sock_sendmsg(struct socket *sock, struct msghdr *msg, + + lock_sock(sk); + ++ if (!llcp_sock->local) { ++ release_sock(sk); ++ return -ENODEV; ++ } ++ + if (sk->sk_type == SOCK_DGRAM) { + DECLARE_SOCKADDR(struct sockaddr_nfc_llcp *, addr, + msg->msg_name); +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index 82ab39d80726e..e41e2e9e54984 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -144,12 +144,15 @@ inline int nci_request(struct nci_dev *ndev, + { + int rc; + +- if (!test_bit(NCI_UP, &ndev->flags)) +- return -ENETDOWN; +- + /* Serialize all requests */ + mutex_lock(&ndev->req_lock); +- rc = __nci_request(ndev, req, opt, timeout); ++ /* check the state after obtaing the lock against any races ++ * from nci_close_device when the device gets removed. ++ */ ++ if (test_bit(NCI_UP, &ndev->flags)) ++ rc = __nci_request(ndev, req, opt, timeout); ++ else ++ rc = -ENETDOWN; + mutex_unlock(&ndev->req_lock); + + return rc; +@@ -473,6 +476,11 @@ static int nci_open_device(struct nci_dev *ndev) + + mutex_lock(&ndev->req_lock); + ++ if (test_bit(NCI_UNREG, &ndev->flags)) { ++ rc = -ENODEV; ++ goto done; ++ } ++ + if (test_bit(NCI_UP, &ndev->flags)) { + rc = -EALREADY; + goto done; +@@ -545,6 +553,10 @@ done: + static int nci_close_device(struct nci_dev *ndev) + { + nci_req_cancel(ndev, ENODEV); ++ ++ /* This mutex needs to be held as a barrier for ++ * caller nci_unregister_device ++ */ + mutex_lock(&ndev->req_lock); + + if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { +@@ -582,8 +594,8 @@ static int nci_close_device(struct nci_dev *ndev) + + del_timer_sync(&ndev->cmd_timer); + +- /* Clear flags */ +- ndev->flags = 0; ++ /* Clear flags except NCI_UNREG */ ++ ndev->flags &= BIT(NCI_UNREG); + + mutex_unlock(&ndev->req_lock); + +@@ -1270,6 +1282,12 @@ void nci_unregister_device(struct nci_dev *ndev) + { + struct nci_conn_info *conn_info, *n; + ++ /* This set_bit is not protected with specialized barrier, ++ * However, it is fine because the mutex_lock(&ndev->req_lock); ++ * in nci_close_device() will help to emit one. ++ */ ++ set_bit(NCI_UNREG, &ndev->flags); ++ + nci_close_device(ndev); + + destroy_workqueue(ndev->cmd_wq); +diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c +index 49089c50872e6..8048a3dcc5f8b 100644 +--- a/net/nfc/netlink.c ++++ b/net/nfc/netlink.c +@@ -636,8 +636,10 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) + { + struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; + +- nfc_device_iter_exit(iter); +- kfree(iter); ++ if (iter) { ++ nfc_device_iter_exit(iter); ++ kfree(iter); ++ } + + return 0; + } +@@ -1392,8 +1394,10 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) + { + struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; + +- nfc_device_iter_exit(iter); +- kfree(iter); ++ if (iter) { ++ nfc_device_iter_exit(iter); ++ kfree(iter); ++ } + + return 0; + } +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 076774034bb96..780d9e2246f39 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -423,12 +423,43 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto, + memcpy(addr, new_addr, sizeof(__be32[4])); + } + +-static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl, u32 mask) ++static void set_ipv6_dsfield(struct sk_buff *skb, struct ipv6hdr *nh, u8 ipv6_tclass, u8 mask) + { ++ u8 old_ipv6_tclass = ipv6_get_dsfield(nh); ++ ++ ipv6_tclass = OVS_MASKED(old_ipv6_tclass, ipv6_tclass, mask); ++ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ csum_replace(&skb->csum, (__force __wsum)(old_ipv6_tclass << 12), ++ (__force __wsum)(ipv6_tclass << 12)); ++ ++ ipv6_change_dsfield(nh, ~mask, ipv6_tclass); ++} ++ ++static void set_ipv6_fl(struct sk_buff *skb, struct ipv6hdr *nh, u32 fl, u32 mask) ++{ ++ u32 ofl; ++ ++ ofl = nh->flow_lbl[0] << 16 | nh->flow_lbl[1] << 8 | nh->flow_lbl[2]; ++ fl = OVS_MASKED(ofl, fl, mask); ++ + /* Bits 21-24 are always unmasked, so this retains their values. */ +- OVS_SET_MASKED(nh->flow_lbl[0], (u8)(fl >> 16), (u8)(mask >> 16)); +- OVS_SET_MASKED(nh->flow_lbl[1], (u8)(fl >> 8), (u8)(mask >> 8)); +- OVS_SET_MASKED(nh->flow_lbl[2], (u8)fl, (u8)mask); ++ nh->flow_lbl[0] = (u8)(fl >> 16); ++ nh->flow_lbl[1] = (u8)(fl >> 8); ++ nh->flow_lbl[2] = (u8)fl; ++ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ csum_replace(&skb->csum, (__force __wsum)htonl(ofl), (__force __wsum)htonl(fl)); ++} ++ ++static void set_ipv6_ttl(struct sk_buff *skb, struct ipv6hdr *nh, u8 new_ttl, u8 mask) ++{ ++ new_ttl = OVS_MASKED(nh->hop_limit, new_ttl, mask); ++ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ csum_replace(&skb->csum, (__force __wsum)(nh->hop_limit << 8), ++ (__force __wsum)(new_ttl << 8)); ++ nh->hop_limit = new_ttl; + } + + static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl, +@@ -546,18 +577,17 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key, + } + } + if (mask->ipv6_tclass) { +- ipv6_change_dsfield(nh, ~mask->ipv6_tclass, key->ipv6_tclass); ++ set_ipv6_dsfield(skb, nh, key->ipv6_tclass, mask->ipv6_tclass); + flow_key->ip.tos = ipv6_get_dsfield(nh); + } + if (mask->ipv6_label) { +- set_ipv6_fl(nh, ntohl(key->ipv6_label), ++ set_ipv6_fl(skb, nh, ntohl(key->ipv6_label), + ntohl(mask->ipv6_label)); + flow_key->ipv6.label = + *(__be32 *)nh & htonl(IPV6_FLOWINFO_FLOWLABEL); + } + if (mask->ipv6_hlimit) { +- OVS_SET_MASKED(nh->hop_limit, key->ipv6_hlimit, +- mask->ipv6_hlimit); ++ set_ipv6_ttl(skb, nh, key->ipv6_hlimit, mask->ipv6_hlimit); + flow_key->ip.ttl = nh->hop_limit; + } + return 0; +diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c +index 9713035b89e3a..02096f2ec6784 100644 +--- a/net/openvswitch/flow.c ++++ b/net/openvswitch/flow.c +@@ -34,6 +34,7 @@ + #include <net/mpls.h> + #include <net/ndisc.h> + #include <net/nsh.h> ++#include <net/netfilter/nf_conntrack_zones.h> + + #include "conntrack.h" + #include "datapath.h" +@@ -858,8 +859,9 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, + #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) + struct tc_skb_ext *tc_ext; + #endif +- bool post_ct = false; ++ bool post_ct = false, post_ct_snat = false, post_ct_dnat = false; + int res, err; ++ u16 zone = 0; + + /* Extract metadata from packet. */ + if (tun_info) { +@@ -898,6 +900,9 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, + key->recirc_id = tc_ext ? tc_ext->chain : 0; + OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0; + post_ct = tc_ext ? tc_ext->post_ct : false; ++ post_ct_snat = post_ct ? tc_ext->post_ct_snat : false; ++ post_ct_dnat = post_ct ? tc_ext->post_ct_dnat : false; ++ zone = post_ct ? tc_ext->zone : 0; + } else { + key->recirc_id = 0; + } +@@ -906,8 +911,19 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, + #endif + + err = key_extract(skb, key); +- if (!err) ++ if (!err) { + ovs_ct_fill_key(skb, key, post_ct); /* Must be after key_extract(). */ ++ if (post_ct) { ++ if (!skb_get_nfct(skb)) { ++ key->ct_zone = zone; ++ } else { ++ if (!post_ct_dnat) ++ key->ct_state &= ~OVS_CS_F_DST_NAT; ++ if (!post_ct_snat) ++ key->ct_state &= ~OVS_CS_F_SRC_NAT; ++ } ++ } ++ } + return err; + } + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 2a2bc64f75cfd..e00c38f242c32 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1738,6 +1738,7 @@ static int fanout_add(struct sock *sk, struct fanout_args *args) + match->prot_hook.dev = po->prot_hook.dev; + match->prot_hook.func = packet_rcv_fanout; + match->prot_hook.af_packet_priv = match; ++ match->prot_hook.af_packet_net = read_pnet(&match->net); + match->prot_hook.id_match = match_fanout_group; + match->max_num_members = args->max_num_members; + list_add(&match->list, &fanout_list); +@@ -1752,7 +1753,10 @@ static int fanout_add(struct sock *sk, struct fanout_args *args) + err = -ENOSPC; + if (refcount_read(&match->sk_ref) < match->max_num_members) { + __dev_remove_pack(&po->prot_hook); +- po->fanout = match; ++ ++ /* Paired with packet_setsockopt(PACKET_FANOUT_DATA) */ ++ WRITE_ONCE(po->fanout, match); ++ + po->rollover = rollover; + rollover = NULL; + refcount_set(&match->sk_ref, refcount_read(&match->sk_ref) + 1); +@@ -3323,6 +3327,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, + po->prot_hook.func = packet_rcv_spkt; + + po->prot_hook.af_packet_priv = sk; ++ po->prot_hook.af_packet_net = sock_net(sk); + + if (proto) { + po->prot_hook.type = proto; +@@ -3904,7 +3909,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, + } + case PACKET_FANOUT_DATA: + { +- if (!po->fanout) ++ /* Paired with the WRITE_ONCE() in fanout_add() */ ++ if (!READ_ONCE(po->fanout)) + return -EINVAL; + + return fanout_set_data(po, optval, optlen); +@@ -4457,9 +4463,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + } + + out_free_pg_vec: +- bitmap_free(rx_owner_map); +- if (pg_vec) ++ if (pg_vec) { ++ bitmap_free(rx_owner_map); + free_pg_vec(pg_vec, order, req->tp_block_nr); ++ } + out: + return err; + } +diff --git a/net/phonet/pep.c b/net/phonet/pep.c +index a1525916885ae..65d463ad87707 100644 +--- a/net/phonet/pep.c ++++ b/net/phonet/pep.c +@@ -868,6 +868,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp, + + err = pep_accept_conn(newsk, skb); + if (err) { ++ __sock_put(sk); + sock_put(newsk); + newsk = NULL; + goto drop; +@@ -946,6 +947,8 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) + ret = -EBUSY; + else if (sk->sk_state == TCP_ESTABLISHED) + ret = -EISCONN; ++ else if (!pn->pn_sk.sobject) ++ ret = -EADDRNOTAVAIL; + else + ret = pep_sock_enable(sk, NULL, 0); + release_sock(sk); +diff --git a/net/rds/connection.c b/net/rds/connection.c +index a3bc4b54d4910..b4cc699c5fad3 100644 +--- a/net/rds/connection.c ++++ b/net/rds/connection.c +@@ -253,6 +253,7 @@ static struct rds_connection *__rds_conn_create(struct net *net, + * should end up here, but if it + * does, reset/destroy the connection. + */ ++ kfree(conn->c_path); + kmem_cache_free(rds_conn_slab, conn); + conn = ERR_PTR(-EOPNOTSUPP); + goto out; +diff --git a/net/rds/tcp.c b/net/rds/tcp.c +index abf19c0e3ba0b..5327d130c4b56 100644 +--- a/net/rds/tcp.c ++++ b/net/rds/tcp.c +@@ -500,7 +500,7 @@ void rds_tcp_tune(struct socket *sock) + sk->sk_userlocks |= SOCK_SNDBUF_LOCK; + } + if (rtn->rcvbuf_size > 0) { +- sk->sk_sndbuf = rtn->rcvbuf_size; ++ sk->sk_rcvbuf = rtn->rcvbuf_size; + sk->sk_userlocks |= SOCK_RCVBUF_LOCK; + } + release_sock(sk); +diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c +index 6be2672a65eab..df864e6922679 100644 +--- a/net/rxrpc/call_event.c ++++ b/net/rxrpc/call_event.c +@@ -157,7 +157,7 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call) + static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) + { + struct sk_buff *skb; +- unsigned long resend_at, rto_j; ++ unsigned long resend_at; + rxrpc_seq_t cursor, seq, top; + ktime_t now, max_age, oldest, ack_ts; + int ix; +@@ -165,10 +165,8 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) + + _enter("{%d,%d}", call->tx_hard_ack, call->tx_top); + +- rto_j = call->peer->rto_j; +- + now = ktime_get_real(); +- max_age = ktime_sub(now, jiffies_to_usecs(rto_j)); ++ max_age = ktime_sub(now, jiffies_to_usecs(call->peer->rto_j)); + + spin_lock_bh(&call->lock); + +@@ -213,7 +211,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) + } + + resend_at = nsecs_to_jiffies(ktime_to_ns(ktime_sub(now, oldest))); +- resend_at += jiffies + rto_j; ++ resend_at += jiffies + rxrpc_get_rto_backoff(call->peer, retrans); + WRITE_ONCE(call->resend_at, resend_at); + + if (unacked) +diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c +index dbea0bfee48e9..8120138dac018 100644 +--- a/net/rxrpc/conn_client.c ++++ b/net/rxrpc/conn_client.c +@@ -135,16 +135,20 @@ struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle) + return bundle; + } + ++static void rxrpc_free_bundle(struct rxrpc_bundle *bundle) ++{ ++ rxrpc_put_peer(bundle->params.peer); ++ kfree(bundle); ++} ++ + void rxrpc_put_bundle(struct rxrpc_bundle *bundle) + { + unsigned int d = bundle->debug_id; + unsigned int u = atomic_dec_return(&bundle->usage); + + _debug("PUT B=%x %u", d, u); +- if (u == 0) { +- rxrpc_put_peer(bundle->params.peer); +- kfree(bundle); +- } ++ if (u == 0) ++ rxrpc_free_bundle(bundle); + } + + /* +@@ -328,7 +332,7 @@ static struct rxrpc_bundle *rxrpc_look_up_bundle(struct rxrpc_conn_parameters *c + return candidate; + + found_bundle_free: +- kfree(candidate); ++ rxrpc_free_bundle(candidate); + found_bundle: + rxrpc_get_bundle(bundle); + spin_unlock(&local->client_bundles_lock); +diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c +index 10f2bf2e9068a..a45c83f22236e 100644 +--- a/net/rxrpc/output.c ++++ b/net/rxrpc/output.c +@@ -468,7 +468,7 @@ done: + if (call->peer->rtt_count > 1) { + unsigned long nowj = jiffies, ack_lost_at; + +- ack_lost_at = rxrpc_get_rto_backoff(call->peer, retrans); ++ ack_lost_at = rxrpc_get_rto_backoff(call->peer, false); + ack_lost_at += nowj; + WRITE_ONCE(call->ack_lost_at, ack_lost_at); + rxrpc_reduce_call_timer(call, ack_lost_at, nowj, +diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c +index 68396d0520525..0298fe2ad6d32 100644 +--- a/net/rxrpc/peer_object.c ++++ b/net/rxrpc/peer_object.c +@@ -299,6 +299,12 @@ static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_sock *rx, + return peer; + } + ++static void rxrpc_free_peer(struct rxrpc_peer *peer) ++{ ++ rxrpc_put_local(peer->local); ++ kfree_rcu(peer, rcu); ++} ++ + /* + * Set up a new incoming peer. There shouldn't be any other matching peers + * since we've already done a search in the list from the non-reentrant context +@@ -365,7 +371,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx, + spin_unlock_bh(&rxnet->peer_hash_lock); + + if (peer) +- kfree(candidate); ++ rxrpc_free_peer(candidate); + else + peer = candidate; + } +@@ -420,8 +426,7 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer) + list_del_init(&peer->keepalive_link); + spin_unlock_bh(&rxnet->peer_hash_lock); + +- rxrpc_put_local(peer->local); +- kfree_rcu(peer, rcu); ++ rxrpc_free_peer(peer); + } + + /* +@@ -457,8 +462,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *peer) + if (n == 0) { + hash_del_rcu(&peer->hash_link); + list_del_init(&peer->keepalive_link); +- rxrpc_put_local(peer->local); +- kfree_rcu(peer, rcu); ++ rxrpc_free_peer(peer); + } + } + +diff --git a/net/rxrpc/rtt.c b/net/rxrpc/rtt.c +index 4e565eeab4260..be61d6f5be8d1 100644 +--- a/net/rxrpc/rtt.c ++++ b/net/rxrpc/rtt.c +@@ -22,7 +22,7 @@ static u32 rxrpc_rto_min_us(struct rxrpc_peer *peer) + + static u32 __rxrpc_set_rto(const struct rxrpc_peer *peer) + { +- return _usecs_to_jiffies((peer->srtt_us >> 3) + peer->rttvar_us); ++ return usecs_to_jiffies((peer->srtt_us >> 3) + peer->rttvar_us); + } + + static u32 rxrpc_bound_rto(u32 rto) +diff --git a/net/sched/act_api.c b/net/sched/act_api.c +index 7dd3a2dc5fa40..7d53272727bfa 100644 +--- a/net/sched/act_api.c ++++ b/net/sched/act_api.c +@@ -728,15 +728,24 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions, + restart_act_graph: + for (i = 0; i < nr_actions; i++) { + const struct tc_action *a = actions[i]; ++ int repeat_ttl; + + if (jmp_prgcnt > 0) { + jmp_prgcnt -= 1; + continue; + } ++ ++ repeat_ttl = 32; + repeat: + ret = a->ops->act(skb, a, res); +- if (ret == TC_ACT_REPEAT) +- goto repeat; /* we need a ttl - JHS */ ++ ++ if (unlikely(ret == TC_ACT_REPEAT)) { ++ if (--repeat_ttl != 0) ++ goto repeat; ++ /* suspicious opcode, stop pipeline */ ++ net_warn_ratelimited("TC_ACT_REPEAT abuse ?\n"); ++ return TC_ACT_OK; ++ } + + if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) { + jmp_prgcnt = ret & TCA_ACT_MAX_PRIO_MASK; +diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c +index 90866ae45573a..4ffea1290ce1c 100644 +--- a/net/sched/act_ct.c ++++ b/net/sched/act_ct.c +@@ -516,11 +516,6 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p, + struct nf_conn *ct; + u8 dir; + +- /* Previously seen or loopback */ +- ct = nf_ct_get(skb, &ctinfo); +- if ((ct && !nf_ct_is_template(ct)) || ctinfo == IP_CT_UNTRACKED) +- return false; +- + switch (family) { + case NFPROTO_IPV4: + if (!tcf_ct_flow_table_fill_tuple_ipv4(skb, &tuple, &tcph)) +@@ -690,10 +685,10 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, + u8 family, u16 zone, bool *defrag) + { + enum ip_conntrack_info ctinfo; +- struct qdisc_skb_cb cb; + struct nf_conn *ct; + int err = 0; + bool frag; ++ u16 mru; + + /* Previously seen (loopback)? Ignore. */ + ct = nf_ct_get(skb, &ctinfo); +@@ -708,7 +703,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, + return err; + + skb_get(skb); +- cb = *qdisc_skb_cb(skb); ++ mru = tc_skb_cb(skb)->mru; + + if (family == NFPROTO_IPV4) { + enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone; +@@ -722,7 +717,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, + + if (!err) { + *defrag = true; +- cb.mru = IPCB(skb)->frag_max_size; ++ mru = IPCB(skb)->frag_max_size; + } + } else { /* NFPROTO_IPV6 */ + #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) +@@ -735,7 +730,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, + + if (!err) { + *defrag = true; +- cb.mru = IP6CB(skb)->frag_max_size; ++ mru = IP6CB(skb)->frag_max_size; + } + #else + err = -EOPNOTSUPP; +@@ -744,7 +739,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, + } + + if (err != -EINPROGRESS) +- *qdisc_skb_cb(skb) = cb; ++ tc_skb_cb(skb)->mru = mru; + skb_clear_hash(skb); + skb->ignore_df = 1; + return err; +@@ -839,6 +834,12 @@ static int ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct, + } + + err = nf_nat_packet(ct, ctinfo, hooknum, skb); ++ if (err == NF_ACCEPT) { ++ if (maniptype == NF_NAT_MANIP_SRC) ++ tc_skb_cb(skb)->post_ct_snat = 1; ++ if (maniptype == NF_NAT_MANIP_DST) ++ tc_skb_cb(skb)->post_ct_dnat = 1; ++ } + out: + return err; + } +@@ -963,7 +964,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a, + tcf_action_update_bstats(&c->common, skb); + + if (clear) { +- qdisc_skb_cb(skb)->post_ct = false; ++ tc_skb_cb(skb)->post_ct = false; + ct = nf_ct_get(skb, &ctinfo); + if (ct) { + nf_conntrack_put(&ct->ct_general); +@@ -1048,7 +1049,8 @@ do_nat: + out_push: + skb_push_rcsum(skb, nh_ofs); + +- qdisc_skb_cb(skb)->post_ct = true; ++ tc_skb_cb(skb)->post_ct = true; ++ tc_skb_cb(skb)->zone = p->zone; + out_clear: + if (defrag) + qdisc_skb_cb(skb)->pkt_len = skb->len; +diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c +index d64b0eeccbe4d..efc963ab995a3 100644 +--- a/net/sched/act_mirred.c ++++ b/net/sched/act_mirred.c +@@ -19,6 +19,7 @@ + #include <linux/if_arp.h> + #include <net/net_namespace.h> + #include <net/netlink.h> ++#include <net/dst.h> + #include <net/pkt_sched.h> + #include <net/pkt_cls.h> + #include <linux/tc_act/tc_mirred.h> +@@ -228,6 +229,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, + bool want_ingress; + bool is_redirect; + bool expects_nh; ++ bool at_ingress; + int m_eaction; + int mac_len; + bool at_nh; +@@ -263,7 +265,8 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, + * ingress - that covers the TC S/W datapath. + */ + is_redirect = tcf_mirred_is_act_redirect(m_eaction); +- use_reinsert = skb_at_tc_ingress(skb) && is_redirect && ++ at_ingress = skb_at_tc_ingress(skb); ++ use_reinsert = at_ingress && is_redirect && + tcf_mirred_can_reinsert(retval); + if (!use_reinsert) { + skb2 = skb_clone(skb, GFP_ATOMIC); +@@ -271,10 +274,12 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, + goto out; + } + ++ want_ingress = tcf_mirred_act_wants_ingress(m_eaction); ++ + /* All mirred/redirected skbs should clear previous ct info */ + nf_reset_ct(skb2); +- +- want_ingress = tcf_mirred_act_wants_ingress(m_eaction); ++ if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */ ++ skb_dst_drop(skb2); + + expects_nh = want_ingress || !m_mac_header_xmit; + at_nh = skb->data == skb_network_header(skb); +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index 2ef8f5a6205a9..cd44cac7fbcf9 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -1044,7 +1044,7 @@ static int __tcf_qdisc_find(struct net *net, struct Qdisc **q, + + /* Find qdisc */ + if (!*parent) { +- *q = dev->qdisc; ++ *q = rcu_dereference(dev->qdisc); + *parent = (*q)->handle; + } else { + *q = qdisc_lookup_rcu(dev, TC_H_MAJ(*parent)); +@@ -1617,12 +1617,17 @@ int tcf_classify(struct sk_buff *skb, + + /* If we missed on some chain */ + if (ret == TC_ACT_UNSPEC && last_executed_chain) { ++ struct tc_skb_cb *cb = tc_skb_cb(skb); ++ + ext = tc_skb_ext_alloc(skb); + if (WARN_ON_ONCE(!ext)) + return TC_ACT_SHOT; + ext->chain = last_executed_chain; +- ext->mru = qdisc_skb_cb(skb)->mru; +- ext->post_ct = qdisc_skb_cb(skb)->post_ct; ++ ext->mru = cb->mru; ++ ext->post_ct = cb->post_ct; ++ ext->post_ct_snat = cb->post_ct_snat; ++ ext->post_ct_dnat = cb->post_ct_dnat; ++ ext->zone = cb->zone; + } + + return ret; +@@ -1940,9 +1945,9 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + bool prio_allocate; + u32 parent; + u32 chain_index; +- struct Qdisc *q = NULL; ++ struct Qdisc *q; + struct tcf_chain_info chain_info; +- struct tcf_chain *chain = NULL; ++ struct tcf_chain *chain; + struct tcf_block *block; + struct tcf_proto *tp; + unsigned long cl; +@@ -1971,6 +1976,8 @@ replay: + tp = NULL; + cl = 0; + block = NULL; ++ q = NULL; ++ chain = NULL; + flags = 0; + + if (prio == 0) { +@@ -2580,7 +2587,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) + + parent = tcm->tcm_parent; + if (!parent) +- q = dev->qdisc; ++ q = rtnl_dereference(dev->qdisc); + else + q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); + if (!q) +@@ -2793,8 +2800,8 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, + struct tcmsg *t; + u32 parent; + u32 chain_index; +- struct Qdisc *q = NULL; +- struct tcf_chain *chain = NULL; ++ struct Qdisc *q; ++ struct tcf_chain *chain; + struct tcf_block *block; + unsigned long cl; + int err; +@@ -2804,6 +2811,7 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, + return -EPERM; + + replay: ++ q = NULL; + err = nlmsg_parse_deprecated(n, sizeof(*t), tca, TCA_MAX, + rtm_tca_policy, extack); + if (err < 0) +@@ -2954,7 +2962,7 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb) + return skb->len; + + if (!tcm->tcm_parent) +- q = dev->qdisc; ++ q = rtnl_dereference(dev->qdisc); + else + q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent)); + +@@ -3687,6 +3695,7 @@ int tc_setup_flow_action(struct flow_action *flow_action, + entry->mpls_mangle.ttl = tcf_mpls_ttl(act); + break; + default: ++ err = -EOPNOTSUPP; + goto err_out_locked; + } + } else if (is_tcf_skbedit_ptype(act)) { +diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c +index eb6345a027e13..709348262410c 100644 +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -19,6 +19,7 @@ + + #include <net/sch_generic.h> + #include <net/pkt_cls.h> ++#include <net/pkt_sched.h> + #include <net/ip.h> + #include <net/flow_dissector.h> + #include <net/geneve.h> +@@ -309,7 +310,8 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, + struct tcf_result *res) + { + struct cls_fl_head *head = rcu_dereference_bh(tp->root); +- bool post_ct = qdisc_skb_cb(skb)->post_ct; ++ bool post_ct = tc_skb_cb(skb)->post_ct; ++ u16 zone = tc_skb_cb(skb)->zone; + struct fl_flow_key skb_key; + struct fl_flow_mask *mask; + struct cls_fl_filter *f; +@@ -327,7 +329,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp, + skb_flow_dissect_ct(skb, &mask->dissector, &skb_key, + fl_ct_info_to_flower_map, + ARRAY_SIZE(fl_ct_info_to_flower_map), +- post_ct); ++ post_ct, zone); + skb_flow_dissect_hash(skb, &mask->dissector, &skb_key); + skb_flow_dissect(skb, &mask->dissector, &skb_key, 0); + +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index 12f39a2dffd47..0fb387c9d706d 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -301,7 +301,7 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) + + if (!handle) + return NULL; +- q = qdisc_match_from_root(dev->qdisc, handle); ++ q = qdisc_match_from_root(rtnl_dereference(dev->qdisc), handle); + if (q) + goto out; + +@@ -320,7 +320,7 @@ struct Qdisc *qdisc_lookup_rcu(struct net_device *dev, u32 handle) + + if (!handle) + return NULL; +- q = qdisc_match_from_root(dev->qdisc, handle); ++ q = qdisc_match_from_root(rcu_dereference(dev->qdisc), handle); + if (q) + goto out; + +@@ -1062,7 +1062,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, + + qdisc_offload_graft_root(dev, new, old, extack); + +- if (new && new->ops->attach) ++ if (new && new->ops->attach && !ingress) + goto skip; + + for (i = 0; i < num_q; i++) { +@@ -1082,10 +1082,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, + skip: + if (!ingress) { + notify_and_destroy(net, skb, n, classid, +- dev->qdisc, new); ++ rtnl_dereference(dev->qdisc), new); + if (new && !new->ops->attach) + qdisc_refcount_inc(new); +- dev->qdisc = new ? : &noop_qdisc; ++ rcu_assign_pointer(dev->qdisc, new ? : &noop_qdisc); + + if (new && new->ops->attach) + new->ops->attach(new); +@@ -1204,7 +1204,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev, + + err = -ENOENT; + if (!ops) { +- NL_SET_ERR_MSG(extack, "Specified qdisc not found"); ++ NL_SET_ERR_MSG(extack, "Specified qdisc kind is unknown"); + goto err_out; + } + +@@ -1460,7 +1460,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, + q = dev_ingress_queue(dev)->qdisc_sleeping; + } + } else { +- q = dev->qdisc; ++ q = rtnl_dereference(dev->qdisc); + } + if (!q) { + NL_SET_ERR_MSG(extack, "Cannot find specified qdisc on specified device"); +@@ -1549,7 +1549,7 @@ replay: + q = dev_ingress_queue(dev)->qdisc_sleeping; + } + } else { +- q = dev->qdisc; ++ q = rtnl_dereference(dev->qdisc); + } + + /* It may be default qdisc, ignore it */ +@@ -1771,7 +1771,8 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) + s_q_idx = 0; + q_idx = 0; + +- if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx, ++ if (tc_dump_qdisc_root(rtnl_dereference(dev->qdisc), ++ skb, cb, &q_idx, s_q_idx, + true, tca[TCA_DUMP_INVISIBLE]) < 0) + goto done; + +@@ -2042,7 +2043,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, + } else if (qid1) { + qid = qid1; + } else if (qid == 0) +- qid = dev->qdisc->handle; ++ qid = rtnl_dereference(dev->qdisc)->handle; + + /* Now qid is genuine qdisc handle consistent + * both with parent and child. +@@ -2053,7 +2054,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, + portid = TC_H_MAKE(qid, portid); + } else { + if (qid == 0) +- qid = dev->qdisc->handle; ++ qid = rtnl_dereference(dev->qdisc)->handle; + } + + /* OK. Locate qdisc */ +@@ -2214,7 +2215,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) + s_t = cb->args[0]; + t = 0; + +- if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t, true) < 0) ++ if (tc_dump_tclass_root(rtnl_dereference(dev->qdisc), ++ skb, tcm, cb, &t, s_t, true) < 0) + goto done; + + dev_queue = dev_ingress_queue(dev); +diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c +index 3c2300d144681..857aaebd49f43 100644 +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -2736,7 +2736,7 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt, + q->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data), + GFP_KERNEL); + if (!q->tins) +- goto nomem; ++ return -ENOMEM; + + for (i = 0; i < CAKE_MAX_TINS; i++) { + struct cake_tin_data *b = q->tins + i; +@@ -2766,10 +2766,6 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt, + q->min_netlen = ~0; + q->min_adjlen = ~0; + return 0; +- +-nomem: +- cake_destroy(sch); +- return -ENOMEM; + } + + static int cake_dump(struct Qdisc *sch, struct sk_buff *skb) +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 1f857ffd1ac23..44fa2532a87c0 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -667,12 +667,14 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + q->classes[i].deficit = quanta[i]; + } + } ++ for (i = q->nbands; i < oldbands; i++) { ++ if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ list_del(&q->classes[i].alist); ++ qdisc_tree_flush_backlog(q->classes[i].qdisc); ++ } + q->nstrict = nstrict; + memcpy(q->prio2band, priomap, sizeof(priomap)); + +- for (i = q->nbands; i < oldbands; i++) +- qdisc_tree_flush_backlog(q->classes[i].qdisc); +- + for (i = 0; i < q->nbands; i++) + q->classes[i].quantum = quanta[i]; + +diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c +index 830f3559f727a..d6aba6edd16e5 100644 +--- a/net/sched/sch_fq_pie.c ++++ b/net/sched/sch_fq_pie.c +@@ -531,6 +531,7 @@ static void fq_pie_destroy(struct Qdisc *sch) + struct fq_pie_sched_data *q = qdisc_priv(sch); + + tcf_block_put(q->block); ++ q->p_params.tupdate = 0; + del_timer_sync(&q->adapt_timer); + kvfree(q->flows); + } +diff --git a/net/sched/sch_frag.c b/net/sched/sch_frag.c +index 8c06381391d6f..5ded4c8672a64 100644 +--- a/net/sched/sch_frag.c ++++ b/net/sched/sch_frag.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB + #include <net/netlink.h> + #include <net/sch_generic.h> ++#include <net/pkt_sched.h> + #include <net/dst.h> + #include <net/ip.h> + #include <net/ip6_fib.h> +@@ -137,7 +138,7 @@ err: + + int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb)) + { +- u16 mru = qdisc_skb_cb(skb)->mru; ++ u16 mru = tc_skb_cb(skb)->mru; + int err; + + if (mru && skb->len > mru + skb->dev->hard_header_len) +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index a8dd06c74e318..30c29a9a2efd2 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -1114,30 +1114,33 @@ static void attach_default_qdiscs(struct net_device *dev) + if (!netif_is_multiqueue(dev) || + dev->priv_flags & IFF_NO_QUEUE) { + netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); +- dev->qdisc = txq->qdisc_sleeping; +- qdisc_refcount_inc(dev->qdisc); ++ qdisc = txq->qdisc_sleeping; ++ rcu_assign_pointer(dev->qdisc, qdisc); ++ qdisc_refcount_inc(qdisc); + } else { + qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT, NULL); + if (qdisc) { +- dev->qdisc = qdisc; ++ rcu_assign_pointer(dev->qdisc, qdisc); + qdisc->ops->attach(qdisc); + } + } ++ qdisc = rtnl_dereference(dev->qdisc); + + /* Detect default qdisc setup/init failed and fallback to "noqueue" */ +- if (dev->qdisc == &noop_qdisc) { ++ if (qdisc == &noop_qdisc) { + netdev_warn(dev, "default qdisc (%s) fail, fallback to %s\n", + default_qdisc_ops->id, noqueue_qdisc_ops.id); + dev->priv_flags |= IFF_NO_QUEUE; + netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL); +- dev->qdisc = txq->qdisc_sleeping; +- qdisc_refcount_inc(dev->qdisc); ++ qdisc = txq->qdisc_sleeping; ++ rcu_assign_pointer(dev->qdisc, qdisc); ++ qdisc_refcount_inc(qdisc); + dev->priv_flags ^= IFF_NO_QUEUE; + } + + #ifdef CONFIG_NET_SCHED +- if (dev->qdisc != &noop_qdisc) +- qdisc_hash_add(dev->qdisc, false); ++ if (qdisc != &noop_qdisc) ++ qdisc_hash_add(qdisc, false); + #endif + } + +@@ -1167,7 +1170,7 @@ void dev_activate(struct net_device *dev) + * and noqueue_qdisc for virtual interfaces + */ + +- if (dev->qdisc == &noop_qdisc) ++ if (rtnl_dereference(dev->qdisc) == &noop_qdisc) + attach_default_qdiscs(dev); + + if (!netif_carrier_ok(dev)) +@@ -1330,6 +1333,15 @@ static int qdisc_change_tx_queue_len(struct net_device *dev, + return 0; + } + ++void dev_qdisc_change_real_num_tx(struct net_device *dev, ++ unsigned int new_real_tx) ++{ ++ struct Qdisc *qdisc = rtnl_dereference(dev->qdisc); ++ ++ if (qdisc->ops->change_real_num_tx) ++ qdisc->ops->change_real_num_tx(qdisc, new_real_tx); ++} ++ + int dev_qdisc_change_tx_queue_len(struct net_device *dev) + { + bool up = dev->flags & IFF_UP; +@@ -1364,7 +1376,7 @@ static void dev_init_scheduler_queue(struct net_device *dev, + + void dev_init_scheduler(struct net_device *dev) + { +- dev->qdisc = &noop_qdisc; ++ rcu_assign_pointer(dev->qdisc, &noop_qdisc); + netdev_for_each_tx_queue(dev, dev_init_scheduler_queue, &noop_qdisc); + if (dev_ingress_queue(dev)) + dev_init_scheduler_queue(dev, dev_ingress_queue(dev), &noop_qdisc); +@@ -1392,8 +1404,8 @@ void dev_shutdown(struct net_device *dev) + netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc); + if (dev_ingress_queue(dev)) + shutdown_scheduler_queue(dev, dev_ingress_queue(dev), &noop_qdisc); +- qdisc_put(dev->qdisc); +- dev->qdisc = &noop_qdisc; ++ qdisc_put(rtnl_dereference(dev->qdisc)); ++ rcu_assign_pointer(dev->qdisc, &noop_qdisc); + + WARN_ON(timer_pending(&dev->watchdog_timer)); + } +@@ -1446,6 +1458,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r, + { + memset(r, 0, sizeof(*r)); + r->overhead = conf->overhead; ++ r->mpu = conf->mpu; + r->rate_bytes_ps = max_t(u64, conf->rate, rate64); + r->linklayer = (conf->linklayer & TC_LINKLAYER_MASK); + psched_ratecfg_precompute__(r->rate_bytes_ps, &r->mult, &r->shift); +diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c +index 5067a6e5d4fde..5cbc32fee8674 100644 +--- a/net/sched/sch_htb.c ++++ b/net/sched/sch_htb.c +@@ -1803,6 +1803,26 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, + if (!hopt->rate.rate || !hopt->ceil.rate) + goto failure; + ++ if (q->offload) { ++ /* Options not supported by the offload. */ ++ if (hopt->rate.overhead || hopt->ceil.overhead) { ++ NL_SET_ERR_MSG(extack, "HTB offload doesn't support the overhead parameter"); ++ goto failure; ++ } ++ if (hopt->rate.mpu || hopt->ceil.mpu) { ++ NL_SET_ERR_MSG(extack, "HTB offload doesn't support the mpu parameter"); ++ goto failure; ++ } ++ if (hopt->quantum) { ++ NL_SET_ERR_MSG(extack, "HTB offload doesn't support the quantum parameter"); ++ goto failure; ++ } ++ if (hopt->prio) { ++ NL_SET_ERR_MSG(extack, "HTB offload doesn't support the prio parameter"); ++ goto failure; ++ } ++ } ++ + /* Keeping backward compatible with rate_table based iproute2 tc */ + if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) + qdisc_put_rtab(qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB], +diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c +index e79f1afe0cfd6..db18d8a860f9c 100644 +--- a/net/sched/sch_mq.c ++++ b/net/sched/sch_mq.c +@@ -125,6 +125,29 @@ static void mq_attach(struct Qdisc *sch) + priv->qdiscs = NULL; + } + ++static void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx) ++{ ++#ifdef CONFIG_NET_SCHED ++ struct net_device *dev = qdisc_dev(sch); ++ struct Qdisc *qdisc; ++ unsigned int i; ++ ++ for (i = new_real_tx; i < dev->real_num_tx_queues; i++) { ++ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; ++ /* Only update the default qdiscs we created, ++ * qdiscs with handles are always hashed. ++ */ ++ if (qdisc != &noop_qdisc && !qdisc->handle) ++ qdisc_hash_del(qdisc); ++ } ++ for (i = dev->real_num_tx_queues; i < new_real_tx; i++) { ++ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; ++ if (qdisc != &noop_qdisc && !qdisc->handle) ++ qdisc_hash_add(qdisc, false); ++ } ++#endif ++} ++ + static int mq_dump(struct Qdisc *sch, struct sk_buff *skb) + { + struct net_device *dev = qdisc_dev(sch); +@@ -288,6 +311,7 @@ struct Qdisc_ops mq_qdisc_ops __read_mostly = { + .init = mq_init, + .destroy = mq_destroy, + .attach = mq_attach, ++ .change_real_num_tx = mq_change_real_num_tx, + .dump = mq_dump, + .owner = THIS_MODULE, + }; +diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c +index 5eb3b1b7ae5e7..50e15add6068f 100644 +--- a/net/sched/sch_mqprio.c ++++ b/net/sched/sch_mqprio.c +@@ -306,6 +306,28 @@ static void mqprio_attach(struct Qdisc *sch) + priv->qdiscs = NULL; + } + ++static void mqprio_change_real_num_tx(struct Qdisc *sch, ++ unsigned int new_real_tx) ++{ ++ struct net_device *dev = qdisc_dev(sch); ++ struct Qdisc *qdisc; ++ unsigned int i; ++ ++ for (i = new_real_tx; i < dev->real_num_tx_queues; i++) { ++ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; ++ /* Only update the default qdiscs we created, ++ * qdiscs with handles are always hashed. ++ */ ++ if (qdisc != &noop_qdisc && !qdisc->handle) ++ qdisc_hash_del(qdisc); ++ } ++ for (i = dev->real_num_tx_queues; i < new_real_tx; i++) { ++ qdisc = netdev_get_tx_queue(dev, i)->qdisc_sleeping; ++ if (qdisc != &noop_qdisc && !qdisc->handle) ++ qdisc_hash_add(qdisc, false); ++ } ++} ++ + static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch, + unsigned long cl) + { +@@ -629,6 +651,7 @@ static struct Qdisc_ops mqprio_qdisc_ops __read_mostly = { + .init = mqprio_init, + .destroy = mqprio_destroy, + .attach = mqprio_attach, ++ .change_real_num_tx = mqprio_change_real_num_tx, + .dump = mqprio_dump, + .owner = THIS_MODULE, + }; +diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c +index 58a9d42b52b8f..aea435b0aeb34 100644 +--- a/net/sched/sch_qfq.c ++++ b/net/sched/sch_qfq.c +@@ -1422,10 +1422,8 @@ static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt, + if (err < 0) + return err; + +- if (qdisc_dev(sch)->tx_queue_len + 1 > QFQ_MAX_AGG_CLASSES) +- max_classes = QFQ_MAX_AGG_CLASSES; +- else +- max_classes = qdisc_dev(sch)->tx_queue_len + 1; ++ max_classes = min_t(u64, (u64)qdisc_dev(sch)->tx_queue_len + 1, ++ QFQ_MAX_AGG_CLASSES); + /* max_cl_shift = floor(log_2(max_classes)) */ + max_cl_shift = __fls(max_classes); + q->max_agg_classes = 1<<max_cl_shift; +diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c +index b9fd18d986464..a66398fb2d6d0 100644 +--- a/net/sched/sch_taprio.c ++++ b/net/sched/sch_taprio.c +@@ -95,18 +95,22 @@ static ktime_t sched_base_time(const struct sched_gate_list *sched) + return ns_to_ktime(sched->base_time); + } + +-static ktime_t taprio_get_time(struct taprio_sched *q) ++static ktime_t taprio_mono_to_any(const struct taprio_sched *q, ktime_t mono) + { +- ktime_t mono = ktime_get(); ++ /* This pairs with WRITE_ONCE() in taprio_parse_clockid() */ ++ enum tk_offsets tk_offset = READ_ONCE(q->tk_offset); + +- switch (q->tk_offset) { ++ switch (tk_offset) { + case TK_OFFS_MAX: + return mono; + default: +- return ktime_mono_to_any(mono, q->tk_offset); ++ return ktime_mono_to_any(mono, tk_offset); + } ++} + +- return KTIME_MAX; ++static ktime_t taprio_get_time(const struct taprio_sched *q) ++{ ++ return taprio_mono_to_any(q, ktime_get()); + } + + static void taprio_free_sched_cb(struct rcu_head *head) +@@ -319,7 +323,7 @@ static ktime_t get_tcp_tstamp(struct taprio_sched *q, struct sk_buff *skb) + return 0; + } + +- return ktime_mono_to_any(skb->skb_mstamp_ns, q->tk_offset); ++ return taprio_mono_to_any(q, skb->skb_mstamp_ns); + } + + /* There are a few scenarios where we will have to modify the txtime from +@@ -1352,6 +1356,7 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb, + } + } else if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]) { + int clockid = nla_get_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]); ++ enum tk_offsets tk_offset; + + /* We only support static clockids and we don't allow + * for it to be modified after the first init. +@@ -1366,22 +1371,24 @@ static int taprio_parse_clockid(struct Qdisc *sch, struct nlattr **tb, + + switch (clockid) { + case CLOCK_REALTIME: +- q->tk_offset = TK_OFFS_REAL; ++ tk_offset = TK_OFFS_REAL; + break; + case CLOCK_MONOTONIC: +- q->tk_offset = TK_OFFS_MAX; ++ tk_offset = TK_OFFS_MAX; + break; + case CLOCK_BOOTTIME: +- q->tk_offset = TK_OFFS_BOOT; ++ tk_offset = TK_OFFS_BOOT; + break; + case CLOCK_TAI: +- q->tk_offset = TK_OFFS_TAI; ++ tk_offset = TK_OFFS_TAI; + break; + default: + NL_SET_ERR_MSG(extack, "Invalid 'clockid'"); + err = -EINVAL; + goto out; + } ++ /* This pairs with READ_ONCE() in taprio_mono_to_any */ ++ WRITE_ONCE(q->tk_offset, tk_offset); + + q->clockid = clockid; + } else { +diff --git a/net/sctp/diag.c b/net/sctp/diag.c +index 760b367644c12..034e2c74497df 100644 +--- a/net/sctp/diag.c ++++ b/net/sctp/diag.c +@@ -245,54 +245,49 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc) + + 64; + } + +-static int sctp_tsp_dump_one(struct sctp_transport *tsp, void *p) ++static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p) + { + struct sctp_association *assoc = tsp->asoc; +- struct sock *sk = tsp->asoc->base.sk; + struct sctp_comm_param *commp = p; +- struct sk_buff *in_skb = commp->skb; ++ struct sock *sk = ep->base.sk; + const struct inet_diag_req_v2 *req = commp->r; +- const struct nlmsghdr *nlh = commp->nlh; +- struct net *net = sock_net(in_skb->sk); ++ struct sk_buff *skb = commp->skb; + struct sk_buff *rep; + int err; + + err = sock_diag_check_cookie(sk, req->id.idiag_cookie); + if (err) +- goto out; ++ return err; + +- err = -ENOMEM; + rep = nlmsg_new(inet_assoc_attr_size(assoc), GFP_KERNEL); + if (!rep) +- goto out; ++ return -ENOMEM; + + lock_sock(sk); +- if (sk != assoc->base.sk) { +- release_sock(sk); +- sk = assoc->base.sk; +- lock_sock(sk); ++ if (ep != assoc->ep) { ++ err = -EAGAIN; ++ goto out; + } +- err = inet_sctp_diag_fill(sk, assoc, rep, req, +- sk_user_ns(NETLINK_CB(in_skb).sk), +- NETLINK_CB(in_skb).portid, +- nlh->nlmsg_seq, 0, nlh, +- commp->net_admin); +- release_sock(sk); ++ ++ err = inet_sctp_diag_fill(sk, assoc, rep, req, sk_user_ns(NETLINK_CB(skb).sk), ++ NETLINK_CB(skb).portid, commp->nlh->nlmsg_seq, 0, ++ commp->nlh, commp->net_admin); + if (err < 0) { + WARN_ON(err == -EMSGSIZE); +- kfree_skb(rep); + goto out; + } ++ release_sock(sk); + +- err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); ++ return nlmsg_unicast(sock_net(skb->sk)->diag_nlsk, rep, NETLINK_CB(skb).portid); + + out: ++ release_sock(sk); ++ kfree_skb(rep); + return err; + } + +-static int sctp_sock_dump(struct sctp_transport *tsp, void *p) ++static int sctp_sock_dump(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p) + { +- struct sctp_endpoint *ep = tsp->asoc->ep; + struct sctp_comm_param *commp = p; + struct sock *sk = ep->base.sk; + struct sk_buff *skb = commp->skb; +@@ -302,6 +297,8 @@ static int sctp_sock_dump(struct sctp_transport *tsp, void *p) + int err = 0; + + lock_sock(sk); ++ if (ep != tsp->asoc->ep) ++ goto release; + list_for_each_entry(assoc, &ep->asocs, asocs) { + if (cb->args[4] < cb->args[1]) + goto next; +@@ -344,9 +341,8 @@ release: + return err; + } + +-static int sctp_sock_filter(struct sctp_transport *tsp, void *p) ++static int sctp_sock_filter(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p) + { +- struct sctp_endpoint *ep = tsp->asoc->ep; + struct sctp_comm_param *commp = p; + struct sock *sk = ep->base.sk; + const struct inet_diag_req_v2 *r = commp->r; +@@ -429,15 +425,15 @@ static void sctp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, + static int sctp_diag_dump_one(struct netlink_callback *cb, + const struct inet_diag_req_v2 *req) + { +- struct sk_buff *in_skb = cb->skb; +- struct net *net = sock_net(in_skb->sk); ++ struct sk_buff *skb = cb->skb; ++ struct net *net = sock_net(skb->sk); + const struct nlmsghdr *nlh = cb->nlh; + union sctp_addr laddr, paddr; + struct sctp_comm_param commp = { +- .skb = in_skb, ++ .skb = skb, + .r = req, + .nlh = nlh, +- .net_admin = netlink_net_capable(in_skb, CAP_NET_ADMIN), ++ .net_admin = netlink_net_capable(skb, CAP_NET_ADMIN), + }; + + if (req->sdiag_family == AF_INET) { +@@ -460,7 +456,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb, + paddr.v6.sin6_family = AF_INET6; + } + +- return sctp_transport_lookup_process(sctp_tsp_dump_one, ++ return sctp_transport_lookup_process(sctp_sock_dump_one, + net, &laddr, &paddr, &commp); + } + +@@ -505,8 +501,8 @@ skip: + if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE))) + goto done; + +- sctp_for_each_transport(sctp_sock_filter, sctp_sock_dump, +- net, &pos, &commp); ++ sctp_transport_traverse_process(sctp_sock_filter, sctp_sock_dump, ++ net, &pos, &commp); + cb->args[2] = pos; + + done: +diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c +index 48c9c2c7602f7..efffde7f2328e 100644 +--- a/net/sctp/endpointola.c ++++ b/net/sctp/endpointola.c +@@ -184,6 +184,18 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) + } + + /* Final destructor for endpoint. */ ++static void sctp_endpoint_destroy_rcu(struct rcu_head *head) ++{ ++ struct sctp_endpoint *ep = container_of(head, struct sctp_endpoint, rcu); ++ struct sock *sk = ep->base.sk; ++ ++ sctp_sk(sk)->ep = NULL; ++ sock_put(sk); ++ ++ kfree(ep); ++ SCTP_DBG_OBJCNT_DEC(ep); ++} ++ + static void sctp_endpoint_destroy(struct sctp_endpoint *ep) + { + struct sock *sk; +@@ -213,18 +225,13 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) + if (sctp_sk(sk)->bind_hash) + sctp_put_port(sk); + +- sctp_sk(sk)->ep = NULL; +- /* Give up our hold on the sock */ +- sock_put(sk); +- +- kfree(ep); +- SCTP_DBG_OBJCNT_DEC(ep); ++ call_rcu(&ep->rcu, sctp_endpoint_destroy_rcu); + } + + /* Hold a reference to an endpoint. */ +-void sctp_endpoint_hold(struct sctp_endpoint *ep) ++int sctp_endpoint_hold(struct sctp_endpoint *ep) + { +- refcount_inc(&ep->base.refcnt); ++ return refcount_inc_not_zero(&ep->base.refcnt); + } + + /* Release a reference to an endpoint and clean up if there are +diff --git a/net/sctp/output.c b/net/sctp/output.c +index 4dfb5ea82b05b..cdfdbd353c678 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -581,13 +581,16 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp) + chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list); + sk = chunk->skb->sk; + +- /* check gso */ + if (packet->size > tp->pathmtu && !packet->ipfragok && !chunk->pmtu_probe) { +- if (!sk_can_gso(sk)) { +- pr_err_once("Trying to GSO but underlying device doesn't support it."); +- goto out; ++ if (tp->pl.state == SCTP_PL_ERROR) { /* do IP fragmentation if in Error state */ ++ packet->ipfragok = 1; ++ } else { ++ if (!sk_can_gso(sk)) { /* check gso */ ++ pr_err_once("Trying to GSO but underlying device doesn't support it."); ++ goto out; ++ } ++ gso = 1; + } +- gso = 1; + } + + /* alloc head skb */ +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 6b937bfd47515..6b3c32264cbc8 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -5317,32 +5317,41 @@ int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), + } + EXPORT_SYMBOL_GPL(sctp_for_each_endpoint); + +-int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), +- struct net *net, ++int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net, + const union sctp_addr *laddr, + const union sctp_addr *paddr, void *p) + { + struct sctp_transport *transport; +- int err; ++ struct sctp_endpoint *ep; ++ int err = -ENOENT; + + rcu_read_lock(); + transport = sctp_addrs_lookup_transport(net, laddr, paddr); ++ if (!transport) { ++ rcu_read_unlock(); ++ return err; ++ } ++ ep = transport->asoc->ep; ++ if (!sctp_endpoint_hold(ep)) { /* asoc can be peeled off */ ++ sctp_transport_put(transport); ++ rcu_read_unlock(); ++ return err; ++ } + rcu_read_unlock(); +- if (!transport) +- return -ENOENT; + +- err = cb(transport, p); ++ err = cb(ep, transport, p); ++ sctp_endpoint_put(ep); + sctp_transport_put(transport); +- + return err; + } + EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); + +-int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), +- int (*cb_done)(struct sctp_transport *, void *), +- struct net *net, int *pos, void *p) { ++int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done, ++ struct net *net, int *pos, void *p) ++{ + struct rhashtable_iter hti; + struct sctp_transport *tsp; ++ struct sctp_endpoint *ep; + int ret; + + again: +@@ -5351,26 +5360,32 @@ again: + + tsp = sctp_transport_get_idx(net, &hti, *pos + 1); + for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) { +- ret = cb(tsp, p); +- if (ret) +- break; ++ ep = tsp->asoc->ep; ++ if (sctp_endpoint_hold(ep)) { /* asoc can be peeled off */ ++ ret = cb(ep, tsp, p); ++ if (ret) ++ break; ++ sctp_endpoint_put(ep); ++ } + (*pos)++; + sctp_transport_put(tsp); + } + sctp_transport_walk_stop(&hti); + + if (ret) { +- if (cb_done && !cb_done(tsp, p)) { ++ if (cb_done && !cb_done(ep, tsp, p)) { + (*pos)++; ++ sctp_endpoint_put(ep); + sctp_transport_put(tsp); + goto again; + } ++ sctp_endpoint_put(ep); + sctp_transport_put(tsp); + } + + return ret; + } +-EXPORT_SYMBOL_GPL(sctp_for_each_transport); ++EXPORT_SYMBOL_GPL(sctp_transport_traverse_process); + + /* 7.2.1 Association Status (SCTP_STATUS) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index a3d3ca6dd63dd..133f1719bf1b7 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -269,7 +269,7 @@ bool sctp_transport_pl_send(struct sctp_transport *t) + if (t->pl.probe_size == SCTP_BASE_PLPMTU) { /* BASE_PLPMTU Confirmation Failed */ + t->pl.state = SCTP_PL_ERROR; /* Base -> Error */ + +- t->pl.pmtu = SCTP_MIN_PLPMTU; ++ t->pl.pmtu = SCTP_BASE_PLPMTU; + t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); + sctp_assoc_sync_pmtu(t->asoc); + } +@@ -366,8 +366,9 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu) + if (pmtu >= SCTP_MIN_PLPMTU && pmtu < SCTP_BASE_PLPMTU) { + t->pl.state = SCTP_PL_ERROR; /* Base -> Error */ + +- t->pl.pmtu = SCTP_MIN_PLPMTU; ++ t->pl.pmtu = SCTP_BASE_PLPMTU; + t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); ++ return true; + } + } else if (t->pl.state == SCTP_PL_SEARCH) { + if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) { +@@ -378,11 +379,10 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu) + t->pl.probe_high = 0; + t->pl.pmtu = SCTP_BASE_PLPMTU; + t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); ++ return true; + } else if (pmtu > t->pl.pmtu && pmtu < t->pl.probe_size) { + t->pl.probe_size = pmtu; + t->pl.probe_count = 0; +- +- return false; + } + } else if (t->pl.state == SCTP_PL_COMPLETE) { + if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) { +@@ -393,10 +393,11 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu) + t->pl.probe_high = 0; + t->pl.pmtu = SCTP_BASE_PLPMTU; + t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); ++ return true; + } + } + +- return true; ++ return false; + } + + bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) +diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c +index 78b663dbfa1f9..5c4c0320e822a 100644 +--- a/net/smc/af_smc.c ++++ b/net/smc/af_smc.c +@@ -148,14 +148,18 @@ static int __smc_release(struct smc_sock *smc) + sock_set_flag(sk, SOCK_DEAD); + sk->sk_shutdown |= SHUTDOWN_MASK; + } else { +- if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT) +- sock_put(sk); /* passive closing */ +- if (sk->sk_state == SMC_LISTEN) { +- /* wake up clcsock accept */ +- rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); ++ if (sk->sk_state != SMC_CLOSED) { ++ if (sk->sk_state != SMC_LISTEN && ++ sk->sk_state != SMC_INIT) ++ sock_put(sk); /* passive closing */ ++ if (sk->sk_state == SMC_LISTEN) { ++ /* wake up clcsock accept */ ++ rc = kernel_sock_shutdown(smc->clcsock, ++ SHUT_RDWR); ++ } ++ sk->sk_state = SMC_CLOSED; ++ sk->sk_state_change(sk); + } +- sk->sk_state = SMC_CLOSED; +- sk->sk_state_change(sk); + smc_restore_fallback_changes(smc); + } + +@@ -178,7 +182,7 @@ static int smc_release(struct socket *sock) + { + struct sock *sk = sock->sk; + struct smc_sock *smc; +- int rc = 0; ++ int old_state, rc = 0; + + if (!sk) + goto out; +@@ -186,10 +190,14 @@ static int smc_release(struct socket *sock) + sock_hold(sk); /* sock_put below */ + smc = smc_sk(sk); + ++ old_state = sk->sk_state; ++ + /* cleanup for a dangling non-blocking connect */ +- if (smc->connect_nonblock && sk->sk_state == SMC_INIT) ++ if (smc->connect_nonblock && old_state == SMC_INIT) + tcp_abort(smc->clcsock->sk, ECONNABORTED); +- flush_work(&smc->connect_work); ++ ++ if (cancel_work_sync(&smc->connect_work)) ++ sock_put(&smc->sk); /* sock_hold in smc_connect for passive closing */ + + if (sk->sk_state == SMC_LISTEN) + /* smc_close_non_accepted() is called and acquires +@@ -199,6 +207,10 @@ static int smc_release(struct socket *sock) + else + lock_sock(sk); + ++ if (old_state == SMC_INIT && sk->sk_state == SMC_ACTIVE && ++ !smc->use_fallback) ++ smc_close_active_abort(smc); ++ + rc = __smc_release(smc); + + /* detach socket */ +@@ -542,8 +554,118 @@ static void smc_stat_fallback(struct smc_sock *smc) + mutex_unlock(&net->smc.mutex_fback_rsn); + } + +-static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code) ++/* must be called under rcu read lock */ ++static void smc_fback_wakeup_waitqueue(struct smc_sock *smc, void *key) ++{ ++ struct socket_wq *wq; ++ __poll_t flags; ++ ++ wq = rcu_dereference(smc->sk.sk_wq); ++ if (!skwq_has_sleeper(wq)) ++ return; ++ ++ /* wake up smc sk->sk_wq */ ++ if (!key) { ++ /* sk_state_change */ ++ wake_up_interruptible_all(&wq->wait); ++ } else { ++ flags = key_to_poll(key); ++ if (flags & (EPOLLIN | EPOLLOUT)) ++ /* sk_data_ready or sk_write_space */ ++ wake_up_interruptible_sync_poll(&wq->wait, flags); ++ else if (flags & EPOLLERR) ++ /* sk_error_report */ ++ wake_up_interruptible_poll(&wq->wait, flags); ++ } ++} ++ ++static int smc_fback_mark_woken(wait_queue_entry_t *wait, ++ unsigned int mode, int sync, void *key) ++{ ++ struct smc_mark_woken *mark = ++ container_of(wait, struct smc_mark_woken, wait_entry); ++ ++ mark->woken = true; ++ mark->key = key; ++ return 0; ++} ++ ++static void smc_fback_forward_wakeup(struct smc_sock *smc, struct sock *clcsk, ++ void (*clcsock_callback)(struct sock *sk)) ++{ ++ struct smc_mark_woken mark = { .woken = false }; ++ struct socket_wq *wq; ++ ++ init_waitqueue_func_entry(&mark.wait_entry, ++ smc_fback_mark_woken); ++ rcu_read_lock(); ++ wq = rcu_dereference(clcsk->sk_wq); ++ if (!wq) ++ goto out; ++ add_wait_queue(sk_sleep(clcsk), &mark.wait_entry); ++ clcsock_callback(clcsk); ++ remove_wait_queue(sk_sleep(clcsk), &mark.wait_entry); ++ ++ if (mark.woken) ++ smc_fback_wakeup_waitqueue(smc, mark.key); ++out: ++ rcu_read_unlock(); ++} ++ ++static void smc_fback_state_change(struct sock *clcsk) ++{ ++ struct smc_sock *smc = ++ smc_clcsock_user_data(clcsk); ++ ++ if (!smc) ++ return; ++ smc_fback_forward_wakeup(smc, clcsk, smc->clcsk_state_change); ++} ++ ++static void smc_fback_data_ready(struct sock *clcsk) ++{ ++ struct smc_sock *smc = ++ smc_clcsock_user_data(clcsk); ++ ++ if (!smc) ++ return; ++ smc_fback_forward_wakeup(smc, clcsk, smc->clcsk_data_ready); ++} ++ ++static void smc_fback_write_space(struct sock *clcsk) ++{ ++ struct smc_sock *smc = ++ smc_clcsock_user_data(clcsk); ++ ++ if (!smc) ++ return; ++ smc_fback_forward_wakeup(smc, clcsk, smc->clcsk_write_space); ++} ++ ++static void smc_fback_error_report(struct sock *clcsk) + { ++ struct smc_sock *smc = ++ smc_clcsock_user_data(clcsk); ++ ++ if (!smc) ++ return; ++ smc_fback_forward_wakeup(smc, clcsk, smc->clcsk_error_report); ++} ++ ++static int smc_switch_to_fallback(struct smc_sock *smc, int reason_code) ++{ ++ struct sock *clcsk; ++ int rc = 0; ++ ++ mutex_lock(&smc->clcsock_release_lock); ++ if (!smc->clcsock) { ++ rc = -EBADF; ++ goto out; ++ } ++ clcsk = smc->clcsock->sk; ++ ++ if (smc->use_fallback) ++ goto out; + smc->use_fallback = true; + smc->fallback_rsn = reason_code; + smc_stat_fallback(smc); +@@ -552,13 +674,42 @@ static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code) + smc->clcsock->file->private_data = smc->clcsock; + smc->clcsock->wq.fasync_list = + smc->sk.sk_socket->wq.fasync_list; ++ ++ /* There might be some wait entries remaining ++ * in smc sk->sk_wq and they should be woken up ++ * as clcsock's wait queue is woken up. ++ */ ++ smc->clcsk_state_change = clcsk->sk_state_change; ++ smc->clcsk_data_ready = clcsk->sk_data_ready; ++ smc->clcsk_write_space = clcsk->sk_write_space; ++ smc->clcsk_error_report = clcsk->sk_error_report; ++ ++ clcsk->sk_state_change = smc_fback_state_change; ++ clcsk->sk_data_ready = smc_fback_data_ready; ++ clcsk->sk_write_space = smc_fback_write_space; ++ clcsk->sk_error_report = smc_fback_error_report; ++ ++ smc->clcsock->sk->sk_user_data = ++ (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); + } ++out: ++ mutex_unlock(&smc->clcsock_release_lock); ++ return rc; + } + + /* fall back during connect */ + static int smc_connect_fallback(struct smc_sock *smc, int reason_code) + { +- smc_switch_to_fallback(smc, reason_code); ++ struct net *net = sock_net(&smc->sk); ++ int rc = 0; ++ ++ rc = smc_switch_to_fallback(smc, reason_code); ++ if (rc) { /* fallback fails */ ++ this_cpu_inc(net->smc.smc_stats->clnt_hshake_err_cnt); ++ if (smc->sk.sk_state == SMC_INIT) ++ sock_put(&smc->sk); /* passive closing */ ++ return rc; ++ } + smc_copy_sock_settings_to_clc(smc); + smc->connect_nonblock = 0; + if (smc->sk.sk_state == SMC_INIT) +@@ -593,10 +744,12 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code, + + static void smc_conn_abort(struct smc_sock *smc, int local_first) + { ++ struct smc_connection *conn = &smc->conn; ++ struct smc_link_group *lgr = conn->lgr; ++ ++ smc_conn_free(conn); + if (local_first) +- smc_lgr_cleanup_early(&smc->conn); +- else +- smc_conn_free(&smc->conn); ++ smc_lgr_cleanup_early(lgr); + } + + /* check if there is a rdma device available for this connection. */ +@@ -1362,11 +1515,12 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code, + { + /* RDMA setup failed, switch back to TCP */ + smc_conn_abort(new_smc, local_first); +- if (reason_code < 0) { /* error, no fallback possible */ ++ if (reason_code < 0 || ++ smc_switch_to_fallback(new_smc, reason_code)) { ++ /* error, no fallback possible */ + smc_listen_out_err(new_smc); + return; + } +- smc_switch_to_fallback(new_smc, reason_code); + if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) { + if (smc_clc_send_decline(new_smc, reason_code, version) < 0) { + smc_listen_out_err(new_smc); +@@ -1739,8 +1893,11 @@ static void smc_listen_work(struct work_struct *work) + + /* check if peer is smc capable */ + if (!tcp_sk(newclcsock->sk)->syn_smc) { +- smc_switch_to_fallback(new_smc, SMC_CLC_DECL_PEERNOSMC); +- smc_listen_out_connected(new_smc); ++ rc = smc_switch_to_fallback(new_smc, SMC_CLC_DECL_PEERNOSMC); ++ if (rc) ++ smc_listen_out_err(new_smc); ++ else ++ smc_listen_out_connected(new_smc); + return; + } + +@@ -1866,10 +2023,9 @@ out: + + static void smc_clcsock_data_ready(struct sock *listen_clcsock) + { +- struct smc_sock *lsmc; ++ struct smc_sock *lsmc = ++ smc_clcsock_user_data(listen_clcsock); + +- lsmc = (struct smc_sock *) +- ((uintptr_t)listen_clcsock->sk_user_data & ~SK_USER_DATA_NOCOPY); + if (!lsmc) + return; + lsmc->clcsk_data_ready(listen_clcsock); +@@ -1914,8 +2070,10 @@ static int smc_listen(struct socket *sock, int backlog) + smc->clcsock->sk->sk_user_data = + (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); + rc = kernel_listen(smc->clcsock, backlog); +- if (rc) ++ if (rc) { ++ smc->clcsock->sk->sk_data_ready = smc->clcsk_data_ready; + goto out; ++ } + sk->sk_max_ack_backlog = backlog; + sk->sk_ack_backlog = 0; + sk->sk_state = SMC_LISTEN; +@@ -2024,7 +2182,9 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + + if (msg->msg_flags & MSG_FASTOPEN) { + if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) { +- smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); ++ rc = smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); ++ if (rc) ++ goto out; + } else { + rc = -EINVAL; + goto out; +@@ -2148,8 +2308,10 @@ static __poll_t smc_poll(struct file *file, struct socket *sock, + static int smc_shutdown(struct socket *sock, int how) + { + struct sock *sk = sock->sk; ++ bool do_shutdown = true; + struct smc_sock *smc; + int rc = -EINVAL; ++ int old_state; + int rc1 = 0; + + smc = smc_sk(sk); +@@ -2176,7 +2338,11 @@ static int smc_shutdown(struct socket *sock, int how) + } + switch (how) { + case SHUT_RDWR: /* shutdown in both directions */ ++ old_state = sk->sk_state; + rc = smc_close_active(smc); ++ if (old_state == SMC_ACTIVE && ++ sk->sk_state == SMC_PEERCLOSEWAIT1) ++ do_shutdown = false; + break; + case SHUT_WR: + rc = smc_close_shutdown_write(smc); +@@ -2186,7 +2352,7 @@ static int smc_shutdown(struct socket *sock, int how) + /* nothing more to do because peer is not involved */ + break; + } +- if (smc->clcsock) ++ if (do_shutdown && smc->clcsock) + rc1 = kernel_sock_shutdown(smc->clcsock, how); + /* map sock_shutdown_cmd constants to sk_shutdown value range */ + sk->sk_shutdown |= how + 1; +@@ -2211,6 +2377,11 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, + /* generic setsockopts reaching us here always apply to the + * CLC socket + */ ++ mutex_lock(&smc->clcsock_release_lock); ++ if (!smc->clcsock) { ++ mutex_unlock(&smc->clcsock_release_lock); ++ return -EBADF; ++ } + if (unlikely(!smc->clcsock->ops->setsockopt)) + rc = -EOPNOTSUPP; + else +@@ -2220,6 +2391,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, + sk->sk_err = smc->clcsock->sk->sk_err; + sk_error_report(sk); + } ++ mutex_unlock(&smc->clcsock_release_lock); + + if (optlen < sizeof(int)) + return -EINVAL; +@@ -2236,7 +2408,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, + case TCP_FASTOPEN_NO_COOKIE: + /* option not supported by SMC */ + if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) { +- smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); ++ rc = smc_switch_to_fallback(smc, SMC_CLC_DECL_OPTUNSUPP); + } else { + rc = -EINVAL; + } +@@ -2279,13 +2451,23 @@ static int smc_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) + { + struct smc_sock *smc; ++ int rc; + + smc = smc_sk(sock->sk); ++ mutex_lock(&smc->clcsock_release_lock); ++ if (!smc->clcsock) { ++ mutex_unlock(&smc->clcsock_release_lock); ++ return -EBADF; ++ } + /* socket options apply to the CLC socket */ +- if (unlikely(!smc->clcsock->ops->getsockopt)) ++ if (unlikely(!smc->clcsock->ops->getsockopt)) { ++ mutex_unlock(&smc->clcsock_release_lock); + return -EOPNOTSUPP; +- return smc->clcsock->ops->getsockopt(smc->clcsock, level, optname, +- optval, optlen); ++ } ++ rc = smc->clcsock->ops->getsockopt(smc->clcsock, level, optname, ++ optval, optlen); ++ mutex_unlock(&smc->clcsock_release_lock); ++ return rc; + } + + static int smc_ioctl(struct socket *sock, unsigned int cmd, +diff --git a/net/smc/smc.h b/net/smc/smc.h +index d65e15f0c944c..930544f7b2e2c 100644 +--- a/net/smc/smc.h ++++ b/net/smc/smc.h +@@ -129,6 +129,12 @@ enum smc_urg_state { + SMC_URG_READ = 3, /* data was already read */ + }; + ++struct smc_mark_woken { ++ bool woken; ++ void *key; ++ wait_queue_entry_t wait_entry; ++}; ++ + struct smc_connection { + struct rb_node alert_node; + struct smc_link_group *lgr; /* link group of connection */ +@@ -170,6 +176,11 @@ struct smc_connection { + u16 tx_cdc_seq; /* sequence # for CDC send */ + u16 tx_cdc_seq_fin; /* sequence # - tx completed */ + spinlock_t send_lock; /* protect wr_sends */ ++ atomic_t cdc_pend_tx_wr; /* number of pending tx CDC wqe ++ * - inc when post wqe, ++ * - dec on polled tx cqe ++ */ ++ wait_queue_head_t cdc_pend_tx_wq; /* wakeup on no cdc_pend_tx_wr*/ + struct delayed_work tx_work; /* retry of smc_cdc_msg_send */ + u32 tx_off; /* base offset in peer rmb */ + +@@ -212,8 +223,14 @@ struct smc_connection { + struct smc_sock { /* smc sock container */ + struct sock sk; + struct socket *clcsock; /* internal tcp socket */ ++ void (*clcsk_state_change)(struct sock *sk); ++ /* original stat_change fct. */ + void (*clcsk_data_ready)(struct sock *sk); +- /* original data_ready fct. **/ ++ /* original data_ready fct. */ ++ void (*clcsk_write_space)(struct sock *sk); ++ /* original write_space fct. */ ++ void (*clcsk_error_report)(struct sock *sk); ++ /* original error_report fct. */ + struct smc_connection conn; /* smc connection */ + struct smc_sock *listen_smc; /* listen parent */ + struct work_struct connect_work; /* handle non-blocking connect*/ +@@ -248,6 +265,12 @@ static inline struct smc_sock *smc_sk(const struct sock *sk) + return (struct smc_sock *)sk; + } + ++static inline struct smc_sock *smc_clcsock_user_data(struct sock *clcsk) ++{ ++ return (struct smc_sock *) ++ ((uintptr_t)clcsk->sk_user_data & ~SK_USER_DATA_NOCOPY); ++} ++ + extern struct workqueue_struct *smc_hs_wq; /* wq for handshake work */ + extern struct workqueue_struct *smc_close_wq; /* wq for close work */ + +diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c +index 99acd337ba90d..84c8a4374fddd 100644 +--- a/net/smc/smc_cdc.c ++++ b/net/smc/smc_cdc.c +@@ -31,10 +31,6 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, + struct smc_sock *smc; + int diff; + +- if (!conn) +- /* already dismissed */ +- return; +- + smc = container_of(conn, struct smc_sock, conn); + bh_lock_sock(&smc->sk); + if (!wc_status) { +@@ -51,6 +47,12 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, + conn); + conn->tx_cdc_seq_fin = cdcpend->ctrl_seq; + } ++ ++ if (atomic_dec_and_test(&conn->cdc_pend_tx_wr) && ++ unlikely(wq_has_sleeper(&conn->cdc_pend_tx_wq))) ++ wake_up(&conn->cdc_pend_tx_wq); ++ WARN_ON(atomic_read(&conn->cdc_pend_tx_wr) < 0); ++ + smc_tx_sndbuf_nonfull(smc); + bh_unlock_sock(&smc->sk); + } +@@ -107,6 +109,10 @@ int smc_cdc_msg_send(struct smc_connection *conn, + conn->tx_cdc_seq++; + conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; + smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, conn, &cfed); ++ ++ atomic_inc(&conn->cdc_pend_tx_wr); ++ smp_mb__after_atomic(); /* Make sure cdc_pend_tx_wr added before post */ ++ + rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); + if (!rc) { + smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn); +@@ -114,6 +120,7 @@ int smc_cdc_msg_send(struct smc_connection *conn, + } else { + conn->tx_cdc_seq--; + conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; ++ atomic_dec(&conn->cdc_pend_tx_wr); + } + + return rc; +@@ -136,7 +143,18 @@ int smcr_cdc_msg_send_validation(struct smc_connection *conn, + peer->token = htonl(local->token); + peer->prod_flags.failover_validation = 1; + ++ /* We need to set pend->conn here to make sure smc_cdc_tx_handler() ++ * can handle properly ++ */ ++ smc_cdc_add_pending_send(conn, pend); ++ ++ atomic_inc(&conn->cdc_pend_tx_wr); ++ smp_mb__after_atomic(); /* Make sure cdc_pend_tx_wr added before post */ ++ + rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); ++ if (unlikely(rc)) ++ atomic_dec(&conn->cdc_pend_tx_wr); ++ + return rc; + } + +@@ -193,31 +211,9 @@ int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn) + return rc; + } + +-static bool smc_cdc_tx_filter(struct smc_wr_tx_pend_priv *tx_pend, +- unsigned long data) ++void smc_cdc_wait_pend_tx_wr(struct smc_connection *conn) + { +- struct smc_connection *conn = (struct smc_connection *)data; +- struct smc_cdc_tx_pend *cdc_pend = +- (struct smc_cdc_tx_pend *)tx_pend; +- +- return cdc_pend->conn == conn; +-} +- +-static void smc_cdc_tx_dismisser(struct smc_wr_tx_pend_priv *tx_pend) +-{ +- struct smc_cdc_tx_pend *cdc_pend = +- (struct smc_cdc_tx_pend *)tx_pend; +- +- cdc_pend->conn = NULL; +-} +- +-void smc_cdc_tx_dismiss_slots(struct smc_connection *conn) +-{ +- struct smc_link *link = conn->lnk; +- +- smc_wr_tx_dismiss_slots(link, SMC_CDC_MSG_TYPE, +- smc_cdc_tx_filter, smc_cdc_tx_dismisser, +- (unsigned long)conn); ++ wait_event(conn->cdc_pend_tx_wq, !atomic_read(&conn->cdc_pend_tx_wr)); + } + + /* Send a SMC-D CDC header. +diff --git a/net/smc/smc_cdc.h b/net/smc/smc_cdc.h +index 0a0a89abd38b2..696cc11f2303b 100644 +--- a/net/smc/smc_cdc.h ++++ b/net/smc/smc_cdc.h +@@ -291,7 +291,7 @@ int smc_cdc_get_free_slot(struct smc_connection *conn, + struct smc_wr_buf **wr_buf, + struct smc_rdma_wr **wr_rdma_buf, + struct smc_cdc_tx_pend **pend); +-void smc_cdc_tx_dismiss_slots(struct smc_connection *conn); ++void smc_cdc_wait_pend_tx_wr(struct smc_connection *conn); + int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, + struct smc_cdc_tx_pend *pend); + int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn); +diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c +index 0f9ffba07d268..84102db5bb314 100644 +--- a/net/smc/smc_close.c ++++ b/net/smc/smc_close.c +@@ -195,6 +195,7 @@ int smc_close_active(struct smc_sock *smc) + int old_state; + long timeout; + int rc = 0; ++ int rc1 = 0; + + timeout = current->flags & PF_EXITING ? + 0 : sock_flag(sk, SOCK_LINGER) ? +@@ -228,6 +229,15 @@ again: + /* send close request */ + rc = smc_close_final(conn); + sk->sk_state = SMC_PEERCLOSEWAIT1; ++ ++ /* actively shutdown clcsock before peer close it, ++ * prevent peer from entering TIME_WAIT state. ++ */ ++ if (smc->clcsock && smc->clcsock->sk) { ++ rc1 = kernel_sock_shutdown(smc->clcsock, ++ SHUT_RDWR); ++ rc = rc ? rc : rc1; ++ } + } else { + /* peer event has changed the state */ + goto again; +diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c +index d2206743dc714..dee336eef6d21 100644 +--- a/net/smc/smc_core.c ++++ b/net/smc/smc_core.c +@@ -170,8 +170,10 @@ static int smc_lgr_register_conn(struct smc_connection *conn, bool first) + + if (!conn->lgr->is_smcd) { + rc = smcr_lgr_conn_assign_link(conn, first); +- if (rc) ++ if (rc) { ++ conn->lgr = NULL; + return rc; ++ } + } + /* find a new alert_token_local value not yet used by some connection + * in this link group +@@ -579,21 +581,18 @@ int smcd_nl_get_lgr(struct sk_buff *skb, struct netlink_callback *cb) + return skb->len; + } + +-void smc_lgr_cleanup_early(struct smc_connection *conn) ++void smc_lgr_cleanup_early(struct smc_link_group *lgr) + { +- struct smc_link_group *lgr = conn->lgr; +- struct list_head *lgr_list; + spinlock_t *lgr_lock; + + if (!lgr) + return; + +- smc_conn_free(conn); +- lgr_list = smc_lgr_list_head(lgr, &lgr_lock); ++ smc_lgr_list_head(lgr, &lgr_lock); + spin_lock_bh(lgr_lock); + /* do not use this link group for new connections */ +- if (!list_empty(lgr_list)) +- list_del_init(lgr_list); ++ if (!list_empty(&lgr->list)) ++ list_del_init(&lgr->list); + spin_unlock_bh(lgr_lock); + __smc_lgr_terminate(lgr, true); + } +@@ -605,7 +604,7 @@ static void smcr_lgr_link_deactivate_all(struct smc_link_group *lgr) + for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { + struct smc_link *lnk = &lgr->lnk[i]; + +- if (smc_link_usable(lnk)) ++ if (smc_link_sendable(lnk)) + lnk->state = SMC_LNK_INACTIVE; + } + wake_up_all(&lgr->llc_msg_waiter); +@@ -665,13 +664,14 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr) + int i; + + while (1) { ++again: + link_id = ++lgr->next_link_id; + if (!link_id) /* skip zero as link_id */ + link_id = ++lgr->next_link_id; + for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { + if (smc_link_usable(&lgr->lnk[i]) && + lgr->lnk[i].link_id == link_id) +- continue; ++ goto again; + } + break; + } +@@ -1056,13 +1056,13 @@ void smc_conn_free(struct smc_connection *conn) + smc_ism_unset_conn(conn); + tasklet_kill(&conn->rx_tsklet); + } else { +- smc_cdc_tx_dismiss_slots(conn); ++ smc_cdc_wait_pend_tx_wr(conn); + if (current_work() != &conn->abort_work) + cancel_work_sync(&conn->abort_work); + } + if (!list_empty(&lgr->list)) { +- smc_lgr_unregister_conn(conn); + smc_buf_unuse(conn, lgr); /* allow buffer reuse */ ++ smc_lgr_unregister_conn(conn); + } + + if (!lgr->conns_num) +@@ -1133,7 +1133,7 @@ void smcr_link_clear(struct smc_link *lnk, bool log) + smc_llc_link_clear(lnk, log); + smcr_buf_unmap_lgr(lnk); + smcr_rtoken_clear_link(lnk); +- smc_ib_modify_qp_reset(lnk); ++ smc_ib_modify_qp_error(lnk); + smc_wr_free_link(lnk); + smc_ib_destroy_queue_pair(lnk); + smc_ib_dealloc_protection_domain(lnk); +@@ -1264,7 +1264,7 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft) + else + tasklet_unlock_wait(&conn->rx_tsklet); + } else { +- smc_cdc_tx_dismiss_slots(conn); ++ smc_cdc_wait_pend_tx_wr(conn); + } + smc_lgr_unregister_conn(conn); + smc_close_active_abort(smc); +@@ -1514,7 +1514,6 @@ static void smcr_link_down(struct smc_link *lnk) + if (!lgr || lnk->state == SMC_LNK_UNUSED || list_empty(&lgr->list)) + return; + +- smc_ib_modify_qp_reset(lnk); + to_lnk = smc_switch_conns(lgr, lnk, true); + if (!to_lnk) { /* no backup link available */ + smcr_link_clear(lnk, true); +@@ -1595,14 +1594,26 @@ static void smc_link_down_work(struct work_struct *work) + mutex_unlock(&lgr->llc_conf_mutex); + } + +-/* Determine vlan of internal TCP socket. +- * @vlan_id: address to store the determined vlan id into +- */ ++static int smc_vlan_by_tcpsk_walk(struct net_device *lower_dev, ++ struct netdev_nested_priv *priv) ++{ ++ unsigned short *vlan_id = (unsigned short *)priv->data; ++ ++ if (is_vlan_dev(lower_dev)) { ++ *vlan_id = vlan_dev_vlan_id(lower_dev); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/* Determine vlan of internal TCP socket. */ + int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini) + { + struct dst_entry *dst = sk_dst_get(clcsock->sk); ++ struct netdev_nested_priv priv; + struct net_device *ndev; +- int i, nest_lvl, rc = 0; ++ int rc = 0; + + ini->vlan_id = 0; + if (!dst) { +@@ -1620,20 +1631,9 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini) + goto out_rel; + } + ++ priv.data = (void *)&ini->vlan_id; + rtnl_lock(); +- nest_lvl = ndev->lower_level; +- for (i = 0; i < nest_lvl; i++) { +- struct list_head *lower = &ndev->adj_list.lower; +- +- if (list_empty(lower)) +- break; +- lower = lower->next; +- ndev = (struct net_device *)netdev_lower_get_next(ndev, &lower); +- if (is_vlan_dev(ndev)) { +- ini->vlan_id = vlan_dev_vlan_id(ndev); +- break; +- } +- } ++ netdev_walk_all_lower_dev(ndev, smc_vlan_by_tcpsk_walk, &priv); + rtnl_unlock(); + + out_rel: +@@ -1701,7 +1701,8 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini) + (ini->smcd_version == SMC_V2 || + lgr->vlan_id == ini->vlan_id) && + (role == SMC_CLNT || ini->is_smcd || +- lgr->conns_num < SMC_RMBS_PER_LGR_MAX)) { ++ (lgr->conns_num < SMC_RMBS_PER_LGR_MAX && ++ !bitmap_full(lgr->rtokens_used_mask, SMC_RMBS_PER_LGR_MAX)))) { + /* link group found */ + ini->first_contact_local = 0; + conn->lgr = lgr; +@@ -1735,12 +1736,15 @@ create: + write_lock_bh(&lgr->conns_lock); + rc = smc_lgr_register_conn(conn, true); + write_unlock_bh(&lgr->conns_lock); +- if (rc) ++ if (rc) { ++ smc_lgr_cleanup_early(lgr); + goto out; ++ } + } + conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE; + conn->local_tx_ctrl.len = SMC_WR_TX_SIZE; + conn->urg_state = SMC_URG_READ; ++ init_waitqueue_head(&conn->cdc_pend_tx_wq); + INIT_WORK(&smc->conn.abort_work, smc_conn_abort_work); + if (ini->is_smcd) { + conn->rx_off = sizeof(struct smcd_cdc_msg); +diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h +index c043ecdca5c44..9a0523f4c7ba6 100644 +--- a/net/smc/smc_core.h ++++ b/net/smc/smc_core.h +@@ -366,6 +366,12 @@ static inline bool smc_link_usable(struct smc_link *lnk) + return true; + } + ++static inline bool smc_link_sendable(struct smc_link *lnk) ++{ ++ return smc_link_usable(lnk) && ++ lnk->qp_attr.cur_qp_state == IB_QPS_RTS; ++} ++ + static inline bool smc_link_active(struct smc_link *lnk) + { + return lnk->state == SMC_LNK_ACTIVE; +@@ -413,7 +419,7 @@ static inline void smc_set_pci_values(struct pci_dev *pci_dev, + struct smc_sock; + struct smc_clc_msg_accept_confirm; + +-void smc_lgr_cleanup_early(struct smc_connection *conn); ++void smc_lgr_cleanup_early(struct smc_link_group *lgr); + void smc_lgr_terminate_sched(struct smc_link_group *lgr); + void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport); + void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport); +diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c +index a8845343d183e..f0ec1f1d50fac 100644 +--- a/net/smc/smc_ib.c ++++ b/net/smc/smc_ib.c +@@ -101,12 +101,12 @@ int smc_ib_modify_qp_rts(struct smc_link *lnk) + IB_QP_MAX_QP_RD_ATOMIC); + } + +-int smc_ib_modify_qp_reset(struct smc_link *lnk) ++int smc_ib_modify_qp_error(struct smc_link *lnk) + { + struct ib_qp_attr qp_attr; + + memset(&qp_attr, 0, sizeof(qp_attr)); +- qp_attr.qp_state = IB_QPS_RESET; ++ qp_attr.qp_state = IB_QPS_ERR; + return ib_modify_qp(lnk->roce_qp, &qp_attr, IB_QP_STATE); + } + +diff --git a/net/smc/smc_ib.h b/net/smc/smc_ib.h +index 3085f5180da79..6967c3d52b03e 100644 +--- a/net/smc/smc_ib.h ++++ b/net/smc/smc_ib.h +@@ -79,6 +79,7 @@ int smc_ib_create_queue_pair(struct smc_link *lnk); + int smc_ib_ready_link(struct smc_link *lnk); + int smc_ib_modify_qp_rts(struct smc_link *lnk); + int smc_ib_modify_qp_reset(struct smc_link *lnk); ++int smc_ib_modify_qp_error(struct smc_link *lnk); + long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev); + int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags, + struct smc_buf_desc *buf_slot, u8 link_idx); +diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c +index f1d323439a2af..ee1f0fdba0855 100644 +--- a/net/smc/smc_llc.c ++++ b/net/smc/smc_llc.c +@@ -1358,7 +1358,7 @@ void smc_llc_send_link_delete_all(struct smc_link_group *lgr, bool ord, u32 rsn) + delllc.reason = htonl(rsn); + + for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { +- if (!smc_link_usable(&lgr->lnk[i])) ++ if (!smc_link_sendable(&lgr->lnk[i])) + continue; + if (!smc_llc_send_message_wait(&lgr->lnk[i], &delllc)) + break; +diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c +index 4a964e9190b02..707615809e5a9 100644 +--- a/net/smc/smc_pnet.c ++++ b/net/smc/smc_pnet.c +@@ -112,7 +112,7 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name) + pnettable = &sn->pnettable; + + /* remove table entry */ +- write_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, + list) { + if (!pnet_name || +@@ -130,7 +130,7 @@ static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name) + rc = 0; + } + } +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + + /* if this is not the initial namespace, stop here */ + if (net != &init_net) +@@ -191,7 +191,7 @@ static int smc_pnet_add_by_ndev(struct net_device *ndev) + sn = net_generic(net, smc_net_id); + pnettable = &sn->pnettable; + +- write_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, list) { + if (pnetelem->type == SMC_PNET_ETH && !pnetelem->ndev && + !strncmp(pnetelem->eth_name, ndev->name, IFNAMSIZ)) { +@@ -205,7 +205,7 @@ static int smc_pnet_add_by_ndev(struct net_device *ndev) + break; + } + } +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + return rc; + } + +@@ -223,7 +223,7 @@ static int smc_pnet_remove_by_ndev(struct net_device *ndev) + sn = net_generic(net, smc_net_id); + pnettable = &sn->pnettable; + +- write_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, list) { + if (pnetelem->type == SMC_PNET_ETH && pnetelem->ndev == ndev) { + dev_put(pnetelem->ndev); +@@ -236,7 +236,7 @@ static int smc_pnet_remove_by_ndev(struct net_device *ndev) + break; + } + } +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + return rc; + } + +@@ -371,7 +371,7 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net, + + rc = -EEXIST; + new_netdev = true; +- write_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { + if (tmp_pe->type == SMC_PNET_ETH && + !strncmp(tmp_pe->eth_name, eth_name, IFNAMSIZ)) { +@@ -381,9 +381,9 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net, + } + if (new_netdev) { + list_add_tail(&new_pe->list, &pnettable->pnetlist); +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + } else { +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + kfree(new_pe); + goto out_put; + } +@@ -444,7 +444,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name, + new_pe->ib_port = ib_port; + + new_ibdev = true; +- write_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { + if (tmp_pe->type == SMC_PNET_IB && + !strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX)) { +@@ -454,9 +454,9 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name, + } + if (new_ibdev) { + list_add_tail(&new_pe->list, &pnettable->pnetlist); +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + } else { +- write_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + kfree(new_pe); + } + return (new_ibdev) ? 0 : -EEXIST; +@@ -601,7 +601,7 @@ static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid, + pnettable = &sn->pnettable; + + /* dump pnettable entries */ +- read_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry(pnetelem, &pnettable->pnetlist, list) { + if (pnetid && !smc_pnet_match(pnetelem->pnet_name, pnetid)) + continue; +@@ -616,7 +616,7 @@ static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid, + break; + } + } +- read_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + return idx; + } + +@@ -860,7 +860,7 @@ int smc_pnet_net_init(struct net *net) + struct smc_pnetids_ndev *pnetids_ndev = &sn->pnetids_ndev; + + INIT_LIST_HEAD(&pnettable->pnetlist); +- rwlock_init(&pnettable->lock); ++ mutex_init(&pnettable->lock); + INIT_LIST_HEAD(&pnetids_ndev->list); + rwlock_init(&pnetids_ndev->lock); + +@@ -940,7 +940,7 @@ static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev, + sn = net_generic(net, smc_net_id); + pnettable = &sn->pnettable; + +- read_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry(pnetelem, &pnettable->pnetlist, list) { + if (pnetelem->type == SMC_PNET_ETH && ndev == pnetelem->ndev) { + /* get pnetid of netdev device */ +@@ -949,7 +949,7 @@ static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev, + break; + } + } +- read_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + return rc; + } + +@@ -1130,7 +1130,7 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port) + sn = net_generic(&init_net, smc_net_id); + pnettable = &sn->pnettable; + +- read_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { + if (tmp_pe->type == SMC_PNET_IB && + !strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX) && +@@ -1140,7 +1140,7 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port) + break; + } + } +- read_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + + return rc; + } +@@ -1159,7 +1159,7 @@ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev) + sn = net_generic(&init_net, smc_net_id); + pnettable = &sn->pnettable; + +- read_lock(&pnettable->lock); ++ mutex_lock(&pnettable->lock); + list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { + if (tmp_pe->type == SMC_PNET_IB && + !strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX)) { +@@ -1168,7 +1168,7 @@ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev) + break; + } + } +- read_unlock(&pnettable->lock); ++ mutex_unlock(&pnettable->lock); + + return rc; + } +diff --git a/net/smc/smc_pnet.h b/net/smc/smc_pnet.h +index 14039272f7e42..80a88eea49491 100644 +--- a/net/smc/smc_pnet.h ++++ b/net/smc/smc_pnet.h +@@ -29,7 +29,7 @@ struct smc_link_group; + * @pnetlist: List of PNETIDs + */ + struct smc_pnettable { +- rwlock_t lock; ++ struct mutex lock; + struct list_head pnetlist; + }; + +diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c +index a419e9af36b98..59ca1a2d5c650 100644 +--- a/net/smc/smc_wr.c ++++ b/net/smc/smc_wr.c +@@ -62,13 +62,9 @@ static inline bool smc_wr_is_tx_pend(struct smc_link *link) + } + + /* wait till all pending tx work requests on the given link are completed */ +-int smc_wr_tx_wait_no_pending_sends(struct smc_link *link) ++void smc_wr_tx_wait_no_pending_sends(struct smc_link *link) + { +- if (wait_event_timeout(link->wr_tx_wait, !smc_wr_is_tx_pend(link), +- SMC_WR_TX_WAIT_PENDING_TIME)) +- return 0; +- else /* timeout */ +- return -EPIPE; ++ wait_event(link->wr_tx_wait, !smc_wr_is_tx_pend(link)); + } + + static inline int smc_wr_tx_find_pending_index(struct smc_link *link, u64 wr_id) +@@ -87,7 +83,6 @@ static inline void smc_wr_tx_process_cqe(struct ib_wc *wc) + struct smc_wr_tx_pend pnd_snd; + struct smc_link *link; + u32 pnd_snd_idx; +- int i; + + link = wc->qp->qp_context; + +@@ -115,14 +110,6 @@ static inline void smc_wr_tx_process_cqe(struct ib_wc *wc) + if (!test_and_clear_bit(pnd_snd_idx, link->wr_tx_mask)) + return; + if (wc->status) { +- for_each_set_bit(i, link->wr_tx_mask, link->wr_tx_cnt) { +- /* clear full struct smc_wr_tx_pend including .priv */ +- memset(&link->wr_tx_pends[i], 0, +- sizeof(link->wr_tx_pends[i])); +- memset(&link->wr_tx_bufs[i], 0, +- sizeof(link->wr_tx_bufs[i])); +- clear_bit(i, link->wr_tx_mask); +- } + /* terminate link */ + smcr_link_down_cond_sched(link); + } +@@ -169,7 +156,7 @@ void smc_wr_tx_cq_handler(struct ib_cq *ib_cq, void *cq_context) + static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx) + { + *idx = link->wr_tx_cnt; +- if (!smc_link_usable(link)) ++ if (!smc_link_sendable(link)) + return -ENOLINK; + for_each_clear_bit(*idx, link->wr_tx_mask, link->wr_tx_cnt) { + if (!test_and_set_bit(*idx, link->wr_tx_mask)) +@@ -212,7 +199,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, + } else { + rc = wait_event_interruptible_timeout( + link->wr_tx_wait, +- !smc_link_usable(link) || ++ !smc_link_sendable(link) || + lgr->terminating || + (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY), + SMC_WR_TX_WAIT_FREE_SLOT_TIME); +@@ -288,18 +275,20 @@ int smc_wr_tx_send_wait(struct smc_link *link, struct smc_wr_tx_pend_priv *priv, + unsigned long timeout) + { + struct smc_wr_tx_pend *pend; ++ u32 pnd_idx; + int rc; + + pend = container_of(priv, struct smc_wr_tx_pend, priv); + pend->compl_requested = 1; +- init_completion(&link->wr_tx_compl[pend->idx]); ++ pnd_idx = pend->idx; ++ init_completion(&link->wr_tx_compl[pnd_idx]); + + rc = smc_wr_tx_send(link, priv); + if (rc) + return rc; + /* wait for completion by smc_wr_tx_process_cqe() */ + rc = wait_for_completion_interruptible_timeout( +- &link->wr_tx_compl[pend->idx], timeout); ++ &link->wr_tx_compl[pnd_idx], timeout); + if (rc <= 0) + rc = -ENODATA; + if (rc > 0) +@@ -349,25 +338,6 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr) + return rc; + } + +-void smc_wr_tx_dismiss_slots(struct smc_link *link, u8 wr_tx_hdr_type, +- smc_wr_tx_filter filter, +- smc_wr_tx_dismisser dismisser, +- unsigned long data) +-{ +- struct smc_wr_tx_pend_priv *tx_pend; +- struct smc_wr_rx_hdr *wr_tx; +- int i; +- +- for_each_set_bit(i, link->wr_tx_mask, link->wr_tx_cnt) { +- wr_tx = (struct smc_wr_rx_hdr *)&link->wr_tx_bufs[i]; +- if (wr_tx->type != wr_tx_hdr_type) +- continue; +- tx_pend = &link->wr_tx_pends[i].priv; +- if (filter(tx_pend, data)) +- dismisser(tx_pend); +- } +-} +- + /****************************** receive queue ********************************/ + + int smc_wr_rx_register_handler(struct smc_wr_rx_handler *handler) +@@ -572,10 +542,7 @@ void smc_wr_free_link(struct smc_link *lnk) + smc_wr_wakeup_reg_wait(lnk); + smc_wr_wakeup_tx_wait(lnk); + +- if (smc_wr_tx_wait_no_pending_sends(lnk)) +- memset(lnk->wr_tx_mask, 0, +- BITS_TO_LONGS(SMC_WR_BUF_CNT) * +- sizeof(*lnk->wr_tx_mask)); ++ smc_wr_tx_wait_no_pending_sends(lnk); + wait_event(lnk->wr_reg_wait, (!atomic_read(&lnk->wr_reg_refcnt))); + wait_event(lnk->wr_tx_wait, (!atomic_read(&lnk->wr_tx_refcnt))); + +diff --git a/net/smc/smc_wr.h b/net/smc/smc_wr.h +index 2bc626f230a56..cb58e60078f57 100644 +--- a/net/smc/smc_wr.h ++++ b/net/smc/smc_wr.h +@@ -22,7 +22,6 @@ + #define SMC_WR_BUF_CNT 16 /* # of ctrl buffers per link */ + + #define SMC_WR_TX_WAIT_FREE_SLOT_TIME (10 * HZ) +-#define SMC_WR_TX_WAIT_PENDING_TIME (5 * HZ) + + #define SMC_WR_TX_SIZE 44 /* actual size of wr_send data (<=SMC_WR_BUF_SIZE) */ + +@@ -62,7 +61,7 @@ static inline void smc_wr_tx_set_wr_id(atomic_long_t *wr_tx_id, long val) + + static inline bool smc_wr_tx_link_hold(struct smc_link *link) + { +- if (!smc_link_usable(link)) ++ if (!smc_link_sendable(link)) + return false; + atomic_inc(&link->wr_tx_refcnt); + return true; +@@ -122,7 +121,7 @@ void smc_wr_tx_dismiss_slots(struct smc_link *lnk, u8 wr_rx_hdr_type, + smc_wr_tx_filter filter, + smc_wr_tx_dismisser dismisser, + unsigned long data); +-int smc_wr_tx_wait_no_pending_sends(struct smc_link *link); ++void smc_wr_tx_wait_no_pending_sends(struct smc_link *link); + + int smc_wr_rx_register_handler(struct smc_wr_rx_handler *handler); + int smc_wr_rx_post_init(struct smc_link *link); +diff --git a/net/socket.c b/net/socket.c +index 7f64a6eccf63f..5053eb0100e48 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -829,6 +829,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, + int empty = 1, false_tstamp = 0; + struct skb_shared_hwtstamps *shhwtstamps = + skb_hwtstamps(skb); ++ ktime_t hwtstamp; + + /* Race occurred between timestamp enabling and packet + receiving. Fill in the current time for now. */ +@@ -877,10 +878,12 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, + (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && + !skb_is_swtx_tstamp(skb, false_tstamp)) { + if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC) +- ptp_convert_timestamp(shhwtstamps, sk->sk_bind_phc); ++ hwtstamp = ptp_convert_timestamp(shhwtstamps, ++ sk->sk_bind_phc); ++ else ++ hwtstamp = shhwtstamps->hwtstamp; + +- if (ktime_to_timespec64_cond(shhwtstamps->hwtstamp, +- tss.ts + 2)) { ++ if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) { + empty = 0; + + if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && +diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c +index 9c0343568d2a0..1a72c67afed5e 100644 +--- a/net/strparser/strparser.c ++++ b/net/strparser/strparser.c +@@ -27,18 +27,10 @@ + + static struct workqueue_struct *strp_wq; + +-struct _strp_msg { +- /* Internal cb structure. struct strp_msg must be first for passing +- * to upper layer. +- */ +- struct strp_msg strp; +- int accum_len; +-}; +- + static inline struct _strp_msg *_strp_msg(struct sk_buff *skb) + { + return (struct _strp_msg *)((void *)skb->cb + +- offsetof(struct qdisc_skb_cb, data)); ++ offsetof(struct sk_skb_cb, strp)); + } + + /* Lower lock held */ +diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c +index 6e4dbd577a39f..d435bffc61999 100644 +--- a/net/sunrpc/addr.c ++++ b/net/sunrpc/addr.c +@@ -162,8 +162,10 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, + const size_t buflen, const char *delim, + struct sockaddr_in6 *sin6) + { +- char *p; ++ char p[IPV6_SCOPE_ID_LEN + 1]; + size_t len; ++ u32 scope_id = 0; ++ struct net_device *dev; + + if ((buf + buflen) == delim) + return 1; +@@ -175,29 +177,23 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, + return 0; + + len = (buf + buflen) - delim - 1; +- p = kmemdup_nul(delim + 1, len, GFP_KERNEL); +- if (p) { +- u32 scope_id = 0; +- struct net_device *dev; +- +- dev = dev_get_by_name(net, p); +- if (dev != NULL) { +- scope_id = dev->ifindex; +- dev_put(dev); +- } else { +- if (kstrtou32(p, 10, &scope_id) != 0) { +- kfree(p); +- return 0; +- } +- } +- +- kfree(p); +- +- sin6->sin6_scope_id = scope_id; +- return 1; ++ if (len > IPV6_SCOPE_ID_LEN) ++ return 0; ++ ++ memcpy(p, delim + 1, len); ++ p[len] = 0; ++ ++ dev = dev_get_by_name(net, p); ++ if (dev != NULL) { ++ scope_id = dev->ifindex; ++ dev_put(dev); ++ } else { ++ if (kstrtou32(p, 10, &scope_id) != 0) ++ return 0; + } + +- return 0; ++ sin6->sin6_scope_id = scope_id; ++ return 1; + } + + static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index f056ff9314442..5da1d7e8468a5 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -2903,7 +2903,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt, + unsigned long connect_timeout; + unsigned long reconnect_timeout; + unsigned char resvport, reuseport; +- int ret = 0; ++ int ret = 0, ident; + + rcu_read_lock(); + xps = xprt_switch_get(rcu_dereference(clnt->cl_xpi.xpi_xpswitch)); +@@ -2917,8 +2917,11 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt, + reuseport = xprt->reuseport; + connect_timeout = xprt->connect_timeout; + reconnect_timeout = xprt->max_reconnect_timeout; ++ ident = xprt->xprt_class->ident; + rcu_read_unlock(); + ++ if (!xprtargs->ident) ++ xprtargs->ident = ident; + xprt = xprt_create_transport(xprtargs); + if (IS_ERR(xprt)) { + ret = PTR_ERR(xprt); +diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c +index ee5336d73fddc..35588f0afa864 100644 +--- a/net/sunrpc/rpc_pipe.c ++++ b/net/sunrpc/rpc_pipe.c +@@ -600,9 +600,9 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) + + dget(dentry); + ret = simple_rmdir(dir, dentry); ++ d_drop(dentry); + if (!ret) + fsnotify_rmdir(dir, dentry); +- d_delete(dentry); + dput(dentry); + return ret; + } +@@ -613,9 +613,9 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry) + + dget(dentry); + ret = simple_unlink(dir, dentry); ++ d_drop(dentry); + if (!ret) + fsnotify_unlink(dir, dentry); +- d_delete(dentry); + dput(dentry); + return ret; + } +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index a3bbe5ce4570f..08ca797bb8a46 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -1676,16 +1676,17 @@ EXPORT_SYMBOL_GPL(svc_encode_result_payload); + /** + * svc_fill_write_vector - Construct data argument for VFS write call + * @rqstp: svc_rqst to operate on +- * @pages: list of pages containing data payload +- * @first: buffer containing first section of write payload +- * @total: total number of bytes of write payload ++ * @payload: xdr_buf containing only the write data payload + * + * Fills in rqstp::rq_vec, and returns the number of elements. + */ +-unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct page **pages, +- struct kvec *first, size_t total) ++unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, ++ struct xdr_buf *payload) + { ++ struct page **pages = payload->pages; ++ struct kvec *first = payload->head; + struct kvec *vec = rqstp->rq_vec; ++ size_t total = payload->len; + unsigned int i; + + /* Some types of transport can present the write payload +diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c +index 6316bd2b8f37b..d4b663401be14 100644 +--- a/net/sunrpc/svc_xprt.c ++++ b/net/sunrpc/svc_xprt.c +@@ -243,7 +243,7 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, + xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); + if (IS_ERR(xprt)) + trace_svc_xprt_create_err(serv->sv_program->pg_name, +- xcl->xcl_name, sap, xprt); ++ xcl->xcl_name, sap, len, xprt); + return xprt; + } + +diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c +index 9a6f17e18f73b..326a31422a3c1 100644 +--- a/net/sunrpc/sysfs.c ++++ b/net/sunrpc/sysfs.c +@@ -291,8 +291,10 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj, + online = 1; + else if (!strncmp(buf, "remove", 6)) + remove = 1; +- else +- return -EINVAL; ++ else { ++ count = -EINVAL; ++ goto out_put; ++ } + + if (wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_KILLABLE)) { + count = -EINTR; +@@ -303,25 +305,28 @@ static ssize_t rpc_sysfs_xprt_state_change(struct kobject *kobj, + goto release_tasks; + } + if (offline) { +- set_bit(XPRT_OFFLINE, &xprt->state); +- spin_lock(&xps->xps_lock); +- xps->xps_nactive--; +- spin_unlock(&xps->xps_lock); ++ if (!test_and_set_bit(XPRT_OFFLINE, &xprt->state)) { ++ spin_lock(&xps->xps_lock); ++ xps->xps_nactive--; ++ spin_unlock(&xps->xps_lock); ++ } + } else if (online) { +- clear_bit(XPRT_OFFLINE, &xprt->state); +- spin_lock(&xps->xps_lock); +- xps->xps_nactive++; +- spin_unlock(&xps->xps_lock); ++ if (test_and_clear_bit(XPRT_OFFLINE, &xprt->state)) { ++ spin_lock(&xps->xps_lock); ++ xps->xps_nactive++; ++ spin_unlock(&xps->xps_lock); ++ } + } else if (remove) { + if (test_bit(XPRT_OFFLINE, &xprt->state)) { +- set_bit(XPRT_REMOVE, &xprt->state); +- xprt_force_disconnect(xprt); +- if (test_bit(XPRT_CONNECTED, &xprt->state)) { +- if (!xprt->sending.qlen && +- !xprt->pending.qlen && +- !xprt->backlog.qlen && +- !atomic_long_read(&xprt->queuelen)) +- rpc_xprt_switch_remove_xprt(xps, xprt); ++ if (!test_and_set_bit(XPRT_REMOVE, &xprt->state)) { ++ xprt_force_disconnect(xprt); ++ if (test_bit(XPRT_CONNECTED, &xprt->state)) { ++ if (!xprt->sending.qlen && ++ !xprt->pending.qlen && ++ !xprt->backlog.qlen && ++ !atomic_long_read(&xprt->queuelen)) ++ rpc_xprt_switch_remove_xprt(xps, xprt); ++ } + } + } else { + count = -EINVAL; +diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c +index cfd681700d1a1..d4aeee83763e6 100644 +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1603,15 +1603,14 @@ xprt_transmit(struct rpc_task *task) + { + struct rpc_rqst *next, *req = task->tk_rqstp; + struct rpc_xprt *xprt = req->rq_xprt; +- int counter, status; ++ int status; + + spin_lock(&xprt->queue_lock); +- counter = 0; +- while (!list_empty(&xprt->xmit_queue)) { +- if (++counter == 20) ++ for (;;) { ++ next = list_first_entry_or_null(&xprt->xmit_queue, ++ struct rpc_rqst, rq_xmit); ++ if (!next) + break; +- next = list_first_entry(&xprt->xmit_queue, +- struct rpc_rqst, rq_xmit); + xprt_pin_rqst(next); + spin_unlock(&xprt->queue_lock); + status = xprt_request_transmit(next, task); +@@ -1619,13 +1618,16 @@ xprt_transmit(struct rpc_task *task) + status = 0; + spin_lock(&xprt->queue_lock); + xprt_unpin_rqst(next); +- if (status == 0) { +- if (!xprt_request_data_received(task) || +- test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) +- continue; +- } else if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) +- task->tk_status = status; +- break; ++ if (status < 0) { ++ if (test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) ++ task->tk_status = status; ++ break; ++ } ++ /* Was @task transmitted, and has it received a reply? */ ++ if (xprt_request_data_received(task) && ++ !test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) ++ break; ++ cond_resched_lock(&xprt->queue_lock); + } + spin_unlock(&xprt->queue_lock); + } +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index aaec3c9be8db6..1295f9ab839fd 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -438,6 +438,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) + IB_POLL_WORKQUEUE); + if (IS_ERR(ep->re_attr.send_cq)) { + rc = PTR_ERR(ep->re_attr.send_cq); ++ ep->re_attr.send_cq = NULL; + goto out_destroy; + } + +@@ -446,6 +447,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) + IB_POLL_WORKQUEUE); + if (IS_ERR(ep->re_attr.recv_cq)) { + rc = PTR_ERR(ep->re_attr.recv_cq); ++ ep->re_attr.recv_cq = NULL; + goto out_destroy; + } + ep->re_receive_count = 0; +@@ -484,6 +486,7 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt) + ep->re_pd = ib_alloc_pd(device, 0); + if (IS_ERR(ep->re_pd)) { + rc = PTR_ERR(ep->re_pd); ++ ep->re_pd = NULL; + goto out_destroy; + } + +diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c +index dc60c32bb70df..b5074957e8812 100644 +--- a/net/tipc/crypto.c ++++ b/net/tipc/crypto.c +@@ -597,6 +597,10 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey, + tmp->cloned = NULL; + tmp->authsize = TIPC_AES_GCM_TAG_SIZE; + tmp->key = kmemdup(ukey, tipc_aead_key_size(ukey), GFP_KERNEL); ++ if (!tmp->key) { ++ tipc_aead_free(&tmp->rcu); ++ return -ENOMEM; ++ } + memcpy(&tmp->salt, ukey->key + keylen, TIPC_AES_GCM_SALT_SIZE); + atomic_set(&tmp->users, 0); + atomic64_set(&tmp->seqno, 0); +@@ -2283,7 +2287,7 @@ static bool tipc_crypto_key_rcv(struct tipc_crypto *rx, struct tipc_msg *hdr) + struct tipc_crypto *tx = tipc_net(rx->net)->crypto_tx; + struct tipc_aead_key *skey = NULL; + u16 key_gen = msg_key_gen(hdr); +- u16 size = msg_data_sz(hdr); ++ u32 size = msg_data_sz(hdr); + u8 *data = msg_data(hdr); + unsigned int keylen; + +diff --git a/net/tipc/link.c b/net/tipc/link.c +index 1b7a487c88419..4e7936d9b4424 100644 +--- a/net/tipc/link.c ++++ b/net/tipc/link.c +@@ -1298,8 +1298,11 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb, + return false; + #ifdef CONFIG_TIPC_CRYPTO + case MSG_CRYPTO: +- tipc_crypto_msg_rcv(l->net, skb); +- return true; ++ if (TIPC_SKB_CB(skb)->decrypted) { ++ tipc_crypto_msg_rcv(l->net, skb); ++ return true; ++ } ++ fallthrough; + #endif + default: + pr_warn("Dropping received illegal msg type\n"); +@@ -2196,7 +2199,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, + struct tipc_msg *hdr = buf_msg(skb); + struct tipc_gap_ack_blks *ga = NULL; + bool reply = msg_probe(hdr), retransmitted = false; +- u16 dlen = msg_data_sz(hdr), glen = 0; ++ u32 dlen = msg_data_sz(hdr), glen = 0; + u16 peers_snd_nxt = msg_next_sent(hdr); + u16 peers_tol = msg_link_tolerance(hdr); + u16 peers_prio = msg_linkprio(hdr); +@@ -2210,6 +2213,10 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, + void *data; + + trace_tipc_proto_rcv(skb, false, l->name); ++ ++ if (dlen > U16_MAX) ++ goto exit; ++ + if (tipc_link_is_blocked(l) || !xmitq) + goto exit; + +@@ -2305,7 +2312,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, + + /* Receive Gap ACK blocks from peer if any */ + glen = tipc_get_gap_ack_blks(&ga, l, hdr, true); +- ++ if(glen > dlen) ++ break; + tipc_mon_rcv(l->net, data + glen, dlen - glen, l->addr, + &l->mon_state, l->bearer_id); + +diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c +index 407619697292f..2f4d23238a7e3 100644 +--- a/net/tipc/monitor.c ++++ b/net/tipc/monitor.c +@@ -496,6 +496,8 @@ void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr, + state->probing = false; + + /* Sanity check received domain record */ ++ if (new_member_cnt > MAX_MON_DOMAIN) ++ return; + if (dlen < dom_rec_len(arrv_dom, 0)) + return; + if (dlen != dom_rec_len(arrv_dom, new_member_cnt)) +diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c +index bda902caa8147..8267b751a526a 100644 +--- a/net/tipc/name_distr.c ++++ b/net/tipc/name_distr.c +@@ -313,7 +313,7 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, + pr_warn_ratelimited("Failed to remove binding %u,%u from %u\n", + ua.sr.type, ua.sr.lower, node); + } else { +- pr_warn("Unrecognized name table message received\n"); ++ pr_warn_ratelimited("Unknown name table message received\n"); + } + return false; + } +diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c +index 01396dd1c899b..1d8ba233d0474 100644 +--- a/net/tipc/name_table.c ++++ b/net/tipc/name_table.c +@@ -967,7 +967,7 @@ static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg, + list_for_each_entry(p, &sr->all_publ, all_publ) + if (p->key == *last_key) + break; +- if (p->key != *last_key) ++ if (list_entry_is_head(p, &sr->all_publ, all_publ)) + return -EPIPE; + } else { + p = list_first_entry(&sr->all_publ, +diff --git a/net/tipc/node.c b/net/tipc/node.c +index 9947b7dfe1d2d..6ef95ce565bd3 100644 +--- a/net/tipc/node.c ++++ b/net/tipc/node.c +@@ -403,7 +403,7 @@ static void tipc_node_write_unlock(struct tipc_node *n) + u32 flags = n->action_flags; + struct list_head *publ_list; + struct tipc_uaddr ua; +- u32 bearer_id; ++ u32 bearer_id, node; + + if (likely(!flags)) { + write_unlock_bh(&n->lock); +@@ -413,7 +413,8 @@ static void tipc_node_write_unlock(struct tipc_node *n) + tipc_uaddr(&ua, TIPC_SERVICE_RANGE, TIPC_NODE_SCOPE, + TIPC_LINK_STATE, n->addr, n->addr); + sk.ref = n->link_id; +- sk.node = n->addr; ++ sk.node = tipc_own_addr(net); ++ node = n->addr; + bearer_id = n->link_id & 0xffff; + publ_list = &n->publ_list; + +@@ -423,17 +424,17 @@ static void tipc_node_write_unlock(struct tipc_node *n) + write_unlock_bh(&n->lock); + + if (flags & TIPC_NOTIFY_NODE_DOWN) +- tipc_publ_notify(net, publ_list, sk.node, n->capabilities); ++ tipc_publ_notify(net, publ_list, node, n->capabilities); + + if (flags & TIPC_NOTIFY_NODE_UP) +- tipc_named_node_up(net, sk.node, n->capabilities); ++ tipc_named_node_up(net, node, n->capabilities); + + if (flags & TIPC_NOTIFY_LINK_UP) { +- tipc_mon_peer_up(net, sk.node, bearer_id); ++ tipc_mon_peer_up(net, node, bearer_id); + tipc_nametbl_publish(net, &ua, &sk, sk.ref); + } + if (flags & TIPC_NOTIFY_LINK_DOWN) { +- tipc_mon_peer_down(net, sk.node, bearer_id); ++ tipc_mon_peer_down(net, node, bearer_id); + tipc_nametbl_withdraw(net, &ua, &sk, sk.ref); + } + } +diff --git a/net/tipc/socket.c b/net/tipc/socket.c +index ad570c2450be8..7545321c3440b 100644 +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -1461,6 +1461,8 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen) + msg_set_syn(hdr, 1); + } + ++ memset(&skaddr, 0, sizeof(skaddr)); ++ + /* Determine destination */ + if (atype == TIPC_SERVICE_RANGE) { + return tipc_sendmcast(sock, ua, m, dlen, timeout); +@@ -3747,7 +3749,7 @@ static int __tipc_nl_list_sk_publ(struct sk_buff *skb, + if (p->key == *last_publ) + break; + } +- if (p->key != *last_publ) { ++ if (list_entry_is_head(p, &tsk->publications, binding_sock)) { + /* We never set seq or call nl_dump_check_consistent() + * this means that setting prev_seq here will cause the + * consistence check to fail in the netlink callback +diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c +index 9ab81db8a6545..9aac9c60d786d 100644 +--- a/net/tls/tls_main.c ++++ b/net/tls/tls_main.c +@@ -61,7 +61,7 @@ static DEFINE_MUTEX(tcpv6_prot_mutex); + static const struct proto *saved_tcpv4_prot; + static DEFINE_MUTEX(tcpv4_prot_mutex); + static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG]; +-static struct proto_ops tls_sw_proto_ops; ++static struct proto_ops tls_proto_ops[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG]; + static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], + const struct proto *base); + +@@ -71,6 +71,8 @@ void update_sk_prot(struct sock *sk, struct tls_context *ctx) + + WRITE_ONCE(sk->sk_prot, + &tls_prots[ip_ver][ctx->tx_conf][ctx->rx_conf]); ++ WRITE_ONCE(sk->sk_socket->ops, ++ &tls_proto_ops[ip_ver][ctx->tx_conf][ctx->rx_conf]); + } + + int wait_on_pending_writer(struct sock *sk, long *timeo) +@@ -581,8 +583,6 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, + if (tx) { + ctx->sk_write_space = sk->sk_write_space; + sk->sk_write_space = tls_write_space; +- } else { +- sk->sk_socket->ops = &tls_sw_proto_ops; + } + goto out; + +@@ -640,6 +640,39 @@ struct tls_context *tls_ctx_create(struct sock *sk) + return ctx; + } + ++static void build_proto_ops(struct proto_ops ops[TLS_NUM_CONFIG][TLS_NUM_CONFIG], ++ const struct proto_ops *base) ++{ ++ ops[TLS_BASE][TLS_BASE] = *base; ++ ++ ops[TLS_SW ][TLS_BASE] = ops[TLS_BASE][TLS_BASE]; ++ ops[TLS_SW ][TLS_BASE].sendpage_locked = tls_sw_sendpage_locked; ++ ++ ops[TLS_BASE][TLS_SW ] = ops[TLS_BASE][TLS_BASE]; ++ ops[TLS_BASE][TLS_SW ].splice_read = tls_sw_splice_read; ++ ++ ops[TLS_SW ][TLS_SW ] = ops[TLS_SW ][TLS_BASE]; ++ ops[TLS_SW ][TLS_SW ].splice_read = tls_sw_splice_read; ++ ++#ifdef CONFIG_TLS_DEVICE ++ ops[TLS_HW ][TLS_BASE] = ops[TLS_BASE][TLS_BASE]; ++ ops[TLS_HW ][TLS_BASE].sendpage_locked = NULL; ++ ++ ops[TLS_HW ][TLS_SW ] = ops[TLS_BASE][TLS_SW ]; ++ ops[TLS_HW ][TLS_SW ].sendpage_locked = NULL; ++ ++ ops[TLS_BASE][TLS_HW ] = ops[TLS_BASE][TLS_SW ]; ++ ++ ops[TLS_SW ][TLS_HW ] = ops[TLS_SW ][TLS_SW ]; ++ ++ ops[TLS_HW ][TLS_HW ] = ops[TLS_HW ][TLS_SW ]; ++ ops[TLS_HW ][TLS_HW ].sendpage_locked = NULL; ++#endif ++#ifdef CONFIG_TLS_TOE ++ ops[TLS_HW_RECORD][TLS_HW_RECORD] = *base; ++#endif ++} ++ + static void tls_build_proto(struct sock *sk) + { + int ip_ver = sk->sk_family == AF_INET6 ? TLSV6 : TLSV4; +@@ -651,6 +684,8 @@ static void tls_build_proto(struct sock *sk) + mutex_lock(&tcpv6_prot_mutex); + if (likely(prot != saved_tcpv6_prot)) { + build_protos(tls_prots[TLSV6], prot); ++ build_proto_ops(tls_proto_ops[TLSV6], ++ sk->sk_socket->ops); + smp_store_release(&saved_tcpv6_prot, prot); + } + mutex_unlock(&tcpv6_prot_mutex); +@@ -661,6 +696,8 @@ static void tls_build_proto(struct sock *sk) + mutex_lock(&tcpv4_prot_mutex); + if (likely(prot != saved_tcpv4_prot)) { + build_protos(tls_prots[TLSV4], prot); ++ build_proto_ops(tls_proto_ops[TLSV4], ++ sk->sk_socket->ops); + smp_store_release(&saved_tcpv4_prot, prot); + } + mutex_unlock(&tcpv4_prot_mutex); +@@ -871,10 +908,6 @@ static int __init tls_register(void) + if (err) + return err; + +- tls_sw_proto_ops = inet_stream_ops; +- tls_sw_proto_ops.splice_read = tls_sw_splice_read; +- tls_sw_proto_ops.sendpage_locked = tls_sw_sendpage_locked; +- + tls_device_init(); + tcp_register_ulp(&tcp_tls_ulp_ops); + +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 1b08b877a8900..bd96ec26f4f99 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -515,7 +515,7 @@ static int tls_do_encryption(struct sock *sk, + memcpy(&rec->iv_data[iv_offset], tls_ctx->tx.iv, + prot->iv_size + prot->salt_size); + +- xor_iv_with_seq(prot, rec->iv_data, tls_ctx->tx.rec_seq); ++ xor_iv_with_seq(prot, rec->iv_data + iv_offset, tls_ctx->tx.rec_seq); + + sge->offset += prot->prepend_size; + sge->length -= prot->prepend_size; +@@ -1487,7 +1487,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb, + else + memcpy(iv + iv_offset, tls_ctx->rx.iv, prot->salt_size); + +- xor_iv_with_seq(prot, iv, tls_ctx->rx.rec_seq); ++ xor_iv_with_seq(prot, iv + iv_offset, tls_ctx->rx.rec_seq); + + /* Prepare AAD */ + tls_make_aad(aad, rxm->full_len - prot->overhead_size + +@@ -1993,6 +1993,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, + struct sock *sk = sock->sk; + struct sk_buff *skb; + ssize_t copied = 0; ++ bool from_queue; + int err = 0; + long timeo; + int chunk; +@@ -2002,25 +2003,28 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, + + timeo = sock_rcvtimeo(sk, flags & SPLICE_F_NONBLOCK); + +- skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo, &err); +- if (!skb) +- goto splice_read_end; +- +- if (!ctx->decrypted) { +- err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc, false); +- +- /* splice does not support reading control messages */ +- if (ctx->control != TLS_RECORD_TYPE_DATA) { +- err = -EINVAL; ++ from_queue = !skb_queue_empty(&ctx->rx_list); ++ if (from_queue) { ++ skb = __skb_dequeue(&ctx->rx_list); ++ } else { ++ skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo, ++ &err); ++ if (!skb) + goto splice_read_end; +- } + ++ err = decrypt_skb_update(sk, skb, NULL, &chunk, &zc, false); + if (err < 0) { + tls_err_abort(sk, -EBADMSG); + goto splice_read_end; + } +- ctx->decrypted = 1; + } ++ ++ /* splice does not support reading control messages */ ++ if (ctx->control != TLS_RECORD_TYPE_DATA) { ++ err = -EINVAL; ++ goto splice_read_end; ++ } ++ + rxm = strp_msg(skb); + + chunk = min_t(unsigned int, rxm->full_len, len); +@@ -2028,7 +2032,17 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, + if (copied < 0) + goto splice_read_end; + +- tls_sw_advance_skb(sk, skb, copied); ++ if (!from_queue) { ++ ctx->recv_pkt = NULL; ++ __strp_unpause(&ctx->strp); ++ } ++ if (chunk < rxm->full_len) { ++ __skb_queue_head(&ctx->rx_list, skb); ++ rxm->offset += len; ++ rxm->full_len -= len; ++ } else { ++ consume_skb(skb); ++ } + + splice_read_end: + release_sock(sk); +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 78e08e82c08c4..b0bfc78e421ce 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2882,9 +2882,6 @@ static int unix_shutdown(struct socket *sock, int mode) + + unix_state_lock(sk); + sk->sk_shutdown |= mode; +- if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && +- mode == SHUTDOWN_MASK) +- sk->sk_state = TCP_CLOSE; + other = unix_peer(sk); + if (other) + sock_hold(other); +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 12e2ddaf887f2..d45d5366115a7 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -192,8 +192,11 @@ void wait_for_unix_gc(void) + { + /* If number of inflight sockets is insane, + * force a garbage collect right now. ++ * Paired with the WRITE_ONCE() in unix_inflight(), ++ * unix_notinflight() and gc_in_progress(). + */ +- if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress) ++ if (READ_ONCE(unix_tot_inflight) > UNIX_INFLIGHT_TRIGGER_GC && ++ !READ_ONCE(gc_in_progress)) + unix_gc(); + wait_event(unix_gc_wait, gc_in_progress == false); + } +@@ -213,7 +216,9 @@ void unix_gc(void) + if (gc_in_progress) + goto out; + +- gc_in_progress = true; ++ /* Paired with READ_ONCE() in wait_for_unix_gc(). */ ++ WRITE_ONCE(gc_in_progress, true); ++ + /* First, select candidates for garbage collection. Only + * in-flight sockets are considered, and from those only ones + * which don't have any external reference. +@@ -299,7 +304,10 @@ void unix_gc(void) + + /* All candidates should have been detached by now. */ + BUG_ON(!list_empty(&gc_candidates)); +- gc_in_progress = false; ++ ++ /* Paired with READ_ONCE() in wait_for_unix_gc(). */ ++ WRITE_ONCE(gc_in_progress, false); ++ + wake_up(&unix_gc_wait); + + out: +diff --git a/net/unix/scm.c b/net/unix/scm.c +index 052ae709ce289..aa27a02478dc1 100644 +--- a/net/unix/scm.c ++++ b/net/unix/scm.c +@@ -60,7 +60,8 @@ void unix_inflight(struct user_struct *user, struct file *fp) + } else { + BUG_ON(list_empty(&u->link)); + } +- unix_tot_inflight++; ++ /* Paired with READ_ONCE() in wait_for_unix_gc() */ ++ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1); + } + user->unix_inflight++; + spin_unlock(&unix_gc_lock); +@@ -80,7 +81,8 @@ void unix_notinflight(struct user_struct *user, struct file *fp) + + if (atomic_long_dec_and_test(&u->inflight)) + list_del_init(&u->link); +- unix_tot_inflight--; ++ /* Paired with READ_ONCE() in wait_for_unix_gc() */ ++ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1); + } + user->unix_inflight--; + spin_unlock(&unix_gc_lock); +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index e2c0cfb334d20..91a5c65707ba1 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -1322,6 +1322,8 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr, + * non-blocking call. + */ + err = -EALREADY; ++ if (flags & O_NONBLOCK) ++ goto out; + break; + default: + if ((sk->sk_state == TCP_LISTEN) || +@@ -1398,6 +1400,7 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr, + sk->sk_state = sk->sk_state == TCP_ESTABLISHED ? TCP_CLOSING : TCP_CLOSE; + sock->state = SS_UNCONNECTED; + vsock_transport_cancel_pkt(vsk); ++ vsock_remove_connected(vsk); + goto out_wait; + } else if (timeout == 0) { + err = -ETIMEDOUT; +diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c +index 59ee1be5a6dd3..ec2c2afbf0d06 100644 +--- a/net/vmw_vsock/virtio_transport_common.c ++++ b/net/vmw_vsock/virtio_transport_common.c +@@ -1299,7 +1299,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, + space_available = virtio_transport_space_update(sk, pkt); + + /* Update CID in case it has changed after a transport reset event */ +- vsk->local_addr.svm_cid = dst.svm_cid; ++ if (vsk->local_addr.svm_cid != VMADDR_CID_ANY) ++ vsk->local_addr.svm_cid = dst.svm_cid; + + if (space_available) + sk->sk_write_space(sk); +diff --git a/net/wireless/core.c b/net/wireless/core.c +index aaba847d79eb2..441136646f89a 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -5,7 +5,7 @@ + * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2021 Intel Corporation ++ * Copyright (C) 2018-2022 Intel Corporation + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +@@ -332,29 +332,20 @@ static void cfg80211_event_work(struct work_struct *work) + void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) + { + struct wireless_dev *wdev, *tmp; +- bool found = false; + + ASSERT_RTNL(); + +- list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { ++ list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) { + if (wdev->nl_owner_dead) { + if (wdev->netdev) + dev_close(wdev->netdev); +- found = true; +- } +- } + +- if (!found) +- return; +- +- wiphy_lock(&rdev->wiphy); +- list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) { +- if (wdev->nl_owner_dead) { ++ wiphy_lock(&rdev->wiphy); + cfg80211_leave(rdev, wdev); + rdev_del_virtual_intf(rdev, wdev); ++ wiphy_unlock(&rdev->wiphy); + } + } +- wiphy_unlock(&rdev->wiphy); + } + + static void cfg80211_destroy_iface_wk(struct work_struct *work) +@@ -1081,6 +1072,16 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) + list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) + cfg80211_put_bss(&rdev->wiphy, &scan->pub); + mutex_destroy(&rdev->wiphy.mtx); ++ ++ /* ++ * The 'regd' can only be non-NULL if we never finished ++ * initializing the wiphy and thus never went through the ++ * unregister path - e.g. in failure scenarios. Thus, it ++ * cannot have been visible to anyone if non-NULL, so we ++ * can just free it here. ++ */ ++ kfree(rcu_dereference_raw(rdev->wiphy.regd)); ++ + kfree(rdev); + } + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index bf7cd47525472..99564db14aa12 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -922,33 +922,37 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { + [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, + }; + +-int nl80211_prepare_wdev_dump(struct netlink_callback *cb, +- struct cfg80211_registered_device **rdev, +- struct wireless_dev **wdev) ++static int nl80211_prepare_wdev_dump(struct netlink_callback *cb, ++ struct cfg80211_registered_device **rdev, ++ struct wireless_dev **wdev, ++ struct nlattr **attrbuf) + { + int err; + + if (!cb->args[0]) { +- struct nlattr **attrbuf; ++ struct nlattr **attrbuf_free = NULL; + +- attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), +- GFP_KERNEL); +- if (!attrbuf) +- return -ENOMEM; ++ if (!attrbuf) { ++ attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf), ++ GFP_KERNEL); ++ if (!attrbuf) ++ return -ENOMEM; ++ attrbuf_free = attrbuf; ++ } + + err = nlmsg_parse_deprecated(cb->nlh, + GENL_HDRLEN + nl80211_fam.hdrsize, + attrbuf, nl80211_fam.maxattr, + nl80211_policy, NULL); + if (err) { +- kfree(attrbuf); ++ kfree(attrbuf_free); + return err; + } + + rtnl_lock(); + *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk), + attrbuf); +- kfree(attrbuf); ++ kfree(attrbuf_free); + if (IS_ERR(*wdev)) { + rtnl_unlock(); + return PTR_ERR(*wdev); +@@ -6001,7 +6005,7 @@ static int nl80211_dump_station(struct sk_buff *skb, + int sta_idx = cb->args[2]; + int err; + +- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); ++ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); + if (err) + return err; + /* nl80211_prepare_wdev_dump acquired it in the successful case */ +@@ -6896,7 +6900,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, + int path_idx = cb->args[2]; + int err; + +- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); ++ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); + if (err) + return err; + /* nl80211_prepare_wdev_dump acquired it in the successful case */ +@@ -7096,7 +7100,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, + int path_idx = cb->args[2]; + int err; + +- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); ++ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); + if (err) + return err; + /* nl80211_prepare_wdev_dump acquired it in the successful case */ +@@ -9518,7 +9522,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) + int start = cb->args[2], idx = 0; + int err; + +- err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); ++ err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); + if (err) + return err; + /* nl80211_prepare_wdev_dump acquired it in the successful case */ +@@ -9651,7 +9655,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) + if (!attrbuf) + return -ENOMEM; + +- res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); ++ res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf); + if (res) { + kfree(attrbuf); + return res; +@@ -13173,6 +13177,9 @@ static int handle_nan_filter(struct nlattr *attr_filter, + i = 0; + nla_for_each_nested(attr, attr_filter, rem) { + filter[i].filter = nla_memdup(attr, GFP_KERNEL); ++ if (!filter[i].filter) ++ goto err; ++ + filter[i].len = nla_len(attr); + i++; + } +@@ -13185,6 +13192,15 @@ static int handle_nan_filter(struct nlattr *attr_filter, + } + + return 0; ++ ++err: ++ i = 0; ++ nla_for_each_nested(attr, attr_filter, rem) { ++ kfree(filter[i].filter); ++ i++; ++ } ++ kfree(filter); ++ return -ENOMEM; + } + + static int nl80211_nan_add_func(struct sk_buff *skb, +diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h +index a3f387770f1bf..d642e3be4ee78 100644 +--- a/net/wireless/nl80211.h ++++ b/net/wireless/nl80211.h +@@ -1,7 +1,7 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + /* + * Portions of this file +- * Copyright (C) 2018, 2020 Intel Corporation ++ * Copyright (C) 2018, 2020-2021 Intel Corporation + */ + #ifndef __NET_WIRELESS_NL80211_H + #define __NET_WIRELESS_NL80211_H +@@ -22,10 +22,6 @@ static inline u64 wdev_id(struct wireless_dev *wdev) + ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32); + } + +-int nl80211_prepare_wdev_dump(struct netlink_callback *cb, +- struct cfg80211_registered_device **rdev, +- struct wireless_dev **wdev); +- + int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, + struct genl_info *info, + struct cfg80211_chan_def *chandef); +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index df87c7f3a0492..795e86b371bba 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -2338,6 +2338,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) + struct cfg80211_chan_def chandef = {}; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + enum nl80211_iftype iftype; ++ bool ret; + + wdev_lock(wdev); + iftype = wdev->iftype; +@@ -2387,7 +2388,11 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_ADHOC: +- return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype); ++ wiphy_lock(wiphy); ++ ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype); ++ wiphy_unlock(wiphy); ++ ++ return ret; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: + return cfg80211_chandef_usable(wiphy, &chandef, +diff --git a/net/wireless/util.c b/net/wireless/util.c +index a1a99a5749844..4ddc269164f86 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -1044,6 +1044,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, + + switch (otype) { + case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: + cfg80211_stop_ap(rdev, dev, true); + break; + case NL80211_IFTYPE_ADHOC: +diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c +index 2bf2693901631..a0f62fa02e06e 100644 +--- a/net/xfrm/xfrm_compat.c ++++ b/net/xfrm/xfrm_compat.c +@@ -127,6 +127,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = { + [XFRMA_SET_MARK] = { .type = NLA_U32 }, + [XFRMA_SET_MARK_MASK] = { .type = NLA_U32 }, + [XFRMA_IF_ID] = { .type = NLA_U32 }, ++ [XFRMA_MTIMER_THRESH] = { .type = NLA_U32 }, + }; + + static struct nlmsghdr *xfrm_nlmsg_put_compat(struct sk_buff *skb, +@@ -274,9 +275,10 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src) + case XFRMA_SET_MARK: + case XFRMA_SET_MARK_MASK: + case XFRMA_IF_ID: ++ case XFRMA_MTIMER_THRESH: + return xfrm_nla_cpy(dst, src, nla_len(src)); + default: +- BUILD_BUG_ON(XFRMA_MAX != XFRMA_IF_ID); ++ BUILD_BUG_ON(XFRMA_MAX != XFRMA_MTIMER_THRESH); + pr_warn_once("unsupported nla_type %d\n", src->nla_type); + return -EOPNOTSUPP; + } +@@ -431,7 +433,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla, + int err; + + if (type > XFRMA_MAX) { +- BUILD_BUG_ON(XFRMA_MAX != XFRMA_IF_ID); ++ BUILD_BUG_ON(XFRMA_MAX != XFRMA_MTIMER_THRESH); + NL_SET_ERR_MSG(extack, "Bad attribute"); + return -EOPNOTSUPP; + } +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index e843b0d9e2a61..c255aac6b816b 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -223,6 +223,9 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + if (x->encap || x->tfcpad) + return -EINVAL; + ++ if (xuo->flags & ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND)) ++ return -EINVAL; ++ + dev = dev_get_by_index(net, xuo->ifindex); + if (!dev) { + if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) { +@@ -261,7 +264,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, + xso->dev = dev; + xso->real_dev = dev; + xso->num_exthdrs = 1; +- xso->flags = xuo->flags; ++ /* Don't forward bit that is not implemented */ ++ xso->flags = xuo->flags & ~XFRM_OFFLOAD_IPV6; + + err = dev->xfrmdev_ops->xdo_dev_state_add(x); + if (err) { +diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c +index 41de46b5ffa94..4e3c62d1ad9e9 100644 +--- a/net/xfrm/xfrm_interface.c ++++ b/net/xfrm/xfrm_interface.c +@@ -637,11 +637,16 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev, + struct netlink_ext_ack *extack) + { + struct net *net = dev_net(dev); +- struct xfrm_if_parms p; ++ struct xfrm_if_parms p = {}; + struct xfrm_if *xi; + int err; + + xfrmi_netlink_parms(data, &p); ++ if (!p.if_id) { ++ NL_SET_ERR_MSG(extack, "if_id must be non zero"); ++ return -EINVAL; ++ } ++ + xi = xfrmi_locate(net, &p); + if (xi) + return -EEXIST; +@@ -666,9 +671,14 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[], + { + struct xfrm_if *xi = netdev_priv(dev); + struct net *net = xi->net; +- struct xfrm_if_parms p; ++ struct xfrm_if_parms p = {}; + + xfrmi_netlink_parms(data, &p); ++ if (!p.if_id) { ++ NL_SET_ERR_MSG(extack, "if_id must be non zero"); ++ return -EINVAL; ++ } ++ + xi = xfrmi_locate(net, &p); + if (!xi) { + xi = netdev_priv(dev); +diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c +index 229544bc70c21..4dc4a7bbe51cf 100644 +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -647,10 +647,12 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb + * This requires hardware to know the inner packet type to calculate + * the inner header checksum. Save inner ip protocol here to avoid + * traversing the packet in the vendor's xmit code. +- * If the encap type is IPIP, just save skb->inner_ipproto. Otherwise, +- * get the ip protocol from the IP header. ++ * For IPsec tunnel mode save the ip protocol from the IP header of the ++ * plain text packet. Otherwise If the encap type is IPIP, just save ++ * skb->inner_ipproto in any other case get the ip protocol from the IP ++ * header. + */ +-static void xfrm_get_inner_ipproto(struct sk_buff *skb) ++static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x) + { + struct xfrm_offload *xo = xfrm_offload(skb); + const struct ethhdr *eth; +@@ -658,6 +660,25 @@ static void xfrm_get_inner_ipproto(struct sk_buff *skb) + if (!xo) + return; + ++ if (x->outer_mode.encap == XFRM_MODE_TUNNEL) { ++ switch (x->outer_mode.family) { ++ case AF_INET: ++ xo->inner_ipproto = ip_hdr(skb)->protocol; ++ break; ++ case AF_INET6: ++ xo->inner_ipproto = ipv6_hdr(skb)->nexthdr; ++ break; ++ default: ++ break; ++ } ++ ++ return; ++ } ++ ++ /* non-Tunnel Mode */ ++ if (!skb->encapsulation) ++ return; ++ + if (skb->inner_protocol_type == ENCAP_TYPE_IPPROTO) { + xo->inner_ipproto = skb->inner_ipproto; + return; +@@ -712,8 +733,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb) + sp->xvec[sp->len++] = x; + xfrm_state_hold(x); + +- if (skb->encapsulation) +- xfrm_get_inner_ipproto(skb); ++ xfrm_get_inner_ipproto(skb, x); + skb->encapsulation = 1; + + if (skb_is_gso(skb)) { +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 37d17a79617c9..37b149f632624 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -31,8 +31,10 @@ + #include <linux/if_tunnel.h> + #include <net/dst.h> + #include <net/flow.h> ++#include <net/inet_ecn.h> + #include <net/xfrm.h> + #include <net/ip.h> ++#include <net/gre.h> + #if IS_ENABLED(CONFIG_IPV6_MIP6) + #include <net/mip6.h> + #endif +@@ -3296,7 +3298,7 @@ decode_session4(struct sk_buff *skb, struct flowi *fl, bool reverse) + fl4->flowi4_proto = iph->protocol; + fl4->daddr = reverse ? iph->saddr : iph->daddr; + fl4->saddr = reverse ? iph->daddr : iph->saddr; +- fl4->flowi4_tos = iph->tos; ++ fl4->flowi4_tos = iph->tos & ~INET_ECN_MASK; + + if (!ip_is_fragment(iph)) { + switch (iph->protocol) { +@@ -3424,6 +3426,26 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse) + } + fl6->flowi6_proto = nexthdr; + return; ++ case IPPROTO_GRE: ++ if (!onlyproto && ++ (nh + offset + 12 < skb->data || ++ pskb_may_pull(skb, nh + offset + 12 - skb->data))) { ++ struct gre_base_hdr *gre_hdr; ++ __be32 *gre_key; ++ ++ nh = skb_network_header(skb); ++ gre_hdr = (struct gre_base_hdr *)(nh + offset); ++ gre_key = (__be32 *)(gre_hdr + 1); ++ ++ if (gre_hdr->flags & GRE_KEY) { ++ if (gre_hdr->flags & GRE_CSUM) ++ gre_key++; ++ fl6->fl6_gre_key = *gre_key; ++ } ++ } ++ fl6->flowi6_proto = nexthdr; ++ return; ++ + #if IS_ENABLED(CONFIG_IPV6_MIP6) + case IPPROTO_MH: + offset += ipv6_optlen(exthdr); +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index a2f4001221d16..100b4b3723e72 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -1593,6 +1593,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, + x->km.seq = orig->km.seq; + x->replay = orig->replay; + x->preplay = orig->preplay; ++ x->mapping_maxage = orig->mapping_maxage; ++ x->new_mapping = 0; ++ x->new_mapping_sport = 0; + + return x; + +@@ -2242,7 +2245,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) + } + EXPORT_SYMBOL(km_query); + +-int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) ++static int __km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) + { + int err = -EINVAL; + struct xfrm_mgr *km; +@@ -2257,6 +2260,24 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) + rcu_read_unlock(); + return err; + } ++ ++int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) ++{ ++ int ret = 0; ++ ++ if (x->mapping_maxage) { ++ if ((jiffies / HZ - x->new_mapping) > x->mapping_maxage || ++ x->new_mapping_sport != sport) { ++ x->new_mapping_sport = sport; ++ x->new_mapping = jiffies / HZ; ++ ret = __km_new_mapping(x, ipaddr, sport); ++ } ++ } else { ++ ret = __km_new_mapping(x, ipaddr, sport); ++ } ++ ++ return ret; ++} + EXPORT_SYMBOL(km_new_mapping); + + void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid) +@@ -2550,7 +2571,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x) + } + EXPORT_SYMBOL(xfrm_state_delete_tunnel); + +-u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu) ++u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) + { + const struct xfrm_type *type = READ_ONCE(x->type); + struct crypto_aead *aead; +@@ -2581,17 +2602,7 @@ u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu) + return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - + net_adj) & ~(blksize - 1)) + net_adj - 2; + } +-EXPORT_SYMBOL_GPL(__xfrm_state_mtu); +- +-u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) +-{ +- mtu = __xfrm_state_mtu(x, mtu); +- +- if (x->props.family == AF_INET6 && mtu < IPV6_MIN_MTU) +- return IPV6_MIN_MTU; +- +- return mtu; +-} ++EXPORT_SYMBOL_GPL(xfrm_state_mtu); + + int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) + { +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 3a3cb09eec122..b10f88822c0df 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -282,6 +282,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, + + err = 0; + ++ if (attrs[XFRMA_MTIMER_THRESH]) ++ if (!attrs[XFRMA_ENCAP]) ++ err = -EINVAL; ++ + out: + return err; + } +@@ -521,6 +525,7 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, + struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; + struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; + struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; ++ struct nlattr *mt = attrs[XFRMA_MTIMER_THRESH]; + + if (re) { + struct xfrm_replay_state_esn *replay_esn; +@@ -552,6 +557,9 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, + + if (rt) + x->replay_maxdiff = nla_get_u32(rt); ++ ++ if (mt) ++ x->mapping_maxage = nla_get_u32(mt); + } + + static void xfrm_smark_init(struct nlattr **attrs, struct xfrm_mark *m) +@@ -621,8 +629,13 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, + + xfrm_smark_init(attrs, &x->props.smark); + +- if (attrs[XFRMA_IF_ID]) ++ if (attrs[XFRMA_IF_ID]) { + x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); ++ if (!x->if_id) { ++ err = -EINVAL; ++ goto error; ++ } ++ } + + err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]); + if (err) +@@ -1024,8 +1037,13 @@ static int copy_to_user_state_extra(struct xfrm_state *x, + if (ret) + goto out; + } +- if (x->security) ++ if (x->security) { + ret = copy_sec_ctx(x->security, skb); ++ if (ret) ++ goto out; ++ } ++ if (x->mapping_maxage) ++ ret = nla_put_u32(skb, XFRMA_MTIMER_THRESH, x->mapping_maxage); + out: + return ret; + } +@@ -1413,8 +1431,13 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, + + mark = xfrm_mark_get(attrs, &m); + +- if (attrs[XFRMA_IF_ID]) ++ if (attrs[XFRMA_IF_ID]) { + if_id = nla_get_u32(attrs[XFRMA_IF_ID]); ++ if (!if_id) { ++ err = -EINVAL; ++ goto out_noput; ++ } ++ } + + if (p->info.seq) { + x = xfrm_find_acq_byseq(net, mark, p->info.seq); +@@ -1727,8 +1750,13 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us + + xfrm_mark_get(attrs, &xp->mark); + +- if (attrs[XFRMA_IF_ID]) ++ if (attrs[XFRMA_IF_ID]) { + xp->if_id = nla_get_u32(attrs[XFRMA_IF_ID]); ++ if (!xp->if_id) { ++ err = -EINVAL; ++ goto error; ++ } ++ } + + return xp; + error: +@@ -3058,7 +3086,7 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x) + if (x->props.extra_flags) + l += nla_total_size(sizeof(x->props.extra_flags)); + if (x->xso.dev) +- l += nla_total_size(sizeof(x->xso)); ++ l += nla_total_size(sizeof(struct xfrm_user_offload)); + if (x->props.smark.v | x->props.smark.m) { + l += nla_total_size(sizeof(x->props.smark.v)); + l += nla_total_size(sizeof(x->props.smark.m)); +@@ -3069,6 +3097,9 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x) + /* Must count x->lastused as it may become non-zero behind our back. */ + l += nla_total_size_64bit(sizeof(u64)); + ++ if (x->mapping_maxage) ++ l += nla_total_size(sizeof(x->mapping_maxage)); ++ + return l; + } + +diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile +index 5fd48a8d4f10a..c6e38e43c3fd0 100644 +--- a/samples/bpf/Makefile ++++ b/samples/bpf/Makefile +@@ -59,7 +59,11 @@ tprogs-y += xdp_redirect + tprogs-y += xdp_monitor + + # Libbpf dependencies +-LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a ++LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf ++LIBBPF_OUTPUT = $(abspath $(BPF_SAMPLES_PATH))/libbpf ++LIBBPF_DESTDIR = $(LIBBPF_OUTPUT) ++LIBBPF_INCLUDE = $(LIBBPF_DESTDIR)/include ++LIBBPF = $(LIBBPF_OUTPUT)/libbpf.a + + CGROUP_HELPERS := ../../tools/testing/selftests/bpf/cgroup_helpers.o + TRACE_HELPERS := ../../tools/testing/selftests/bpf/trace_helpers.o +@@ -198,7 +202,7 @@ TPROGS_CFLAGS += -Wstrict-prototypes + + TPROGS_CFLAGS += -I$(objtree)/usr/include + TPROGS_CFLAGS += -I$(srctree)/tools/testing/selftests/bpf/ +-TPROGS_CFLAGS += -I$(srctree)/tools/lib/ ++TPROGS_CFLAGS += -I$(LIBBPF_INCLUDE) + TPROGS_CFLAGS += -I$(srctree)/tools/include + TPROGS_CFLAGS += -I$(srctree)/tools/perf + TPROGS_CFLAGS += -DHAVE_ATTR_TEST=0 +@@ -209,6 +213,11 @@ TPROGS_LDFLAGS := -L$(SYSROOT)/usr/lib + endif + + TPROGS_LDLIBS += $(LIBBPF) -lelf -lz ++TPROGLDLIBS_xdp_monitor += -lm ++TPROGLDLIBS_xdp_redirect += -lm ++TPROGLDLIBS_xdp_redirect_cpu += -lm ++TPROGLDLIBS_xdp_redirect_map += -lm ++TPROGLDLIBS_xdp_redirect_map_multi += -lm + TPROGLDLIBS_tracex4 += -lrt + TPROGLDLIBS_trace_output += -lrt + TPROGLDLIBS_map_perf_test += -lrt +@@ -268,16 +277,27 @@ all: + clean: + $(MAKE) -C ../../ M=$(CURDIR) clean + @find $(CURDIR) -type f -name '*~' -delete ++ @$(RM) -r $(CURDIR)/libbpf $(CURDIR)/bpftool + +-$(LIBBPF): FORCE ++$(LIBBPF): FORCE | $(LIBBPF_OUTPUT) + # Fix up variables inherited from Kbuild that tools/ build system won't like +- $(MAKE) -C $(dir $@) RM='rm -rf' EXTRA_CFLAGS="$(TPROGS_CFLAGS)" \ +- LDFLAGS=$(TPROGS_LDFLAGS) srctree=$(BPF_SAMPLES_PATH)/../../ O= ++ $(MAKE) -C $(LIBBPF_SRC) RM='rm -rf' EXTRA_CFLAGS="$(TPROGS_CFLAGS)" \ ++ LDFLAGS=$(TPROGS_LDFLAGS) srctree=$(BPF_SAMPLES_PATH)/../../ \ ++ O= OUTPUT=$(LIBBPF_OUTPUT)/ DESTDIR=$(LIBBPF_DESTDIR) prefix= \ ++ $@ install_headers + + BPFTOOLDIR := $(TOOLS_PATH)/bpf/bpftool +-BPFTOOL := $(BPFTOOLDIR)/bpftool +-$(BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) +- $(MAKE) -C $(BPFTOOLDIR) srctree=$(BPF_SAMPLES_PATH)/../../ ++BPFTOOL_OUTPUT := $(abspath $(BPF_SAMPLES_PATH))/bpftool ++BPFTOOL := $(BPFTOOL_OUTPUT)/bpftool ++$(BPFTOOL): $(LIBBPF) $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) | $(BPFTOOL_OUTPUT) ++ $(MAKE) -C $(BPFTOOLDIR) srctree=$(BPF_SAMPLES_PATH)/../../ \ ++ OUTPUT=$(BPFTOOL_OUTPUT)/ \ ++ LIBBPF_OUTPUT=$(LIBBPF_OUTPUT)/ \ ++ LIBBPF_DESTDIR=$(LIBBPF_DESTDIR)/ ++ ++$(LIBBPF_OUTPUT) $(BPFTOOL_OUTPUT): ++ $(call msg,MKDIR,$@) ++ $(Q)mkdir -p $@ + + $(obj)/syscall_nrs.h: $(obj)/syscall_nrs.s FORCE + $(call filechk,offsets,__SYSCALL_NRS_H__) +@@ -309,6 +329,11 @@ verify_target_bpf: verify_cmds + $(BPF_SAMPLES_PATH)/*.c: verify_target_bpf $(LIBBPF) + $(src)/*.c: verify_target_bpf $(LIBBPF) + ++libbpf_hdrs: $(LIBBPF) ++$(obj)/$(TRACE_HELPERS) $(obj)/$(CGROUP_HELPERS) $(obj)/$(XDP_SAMPLE): | libbpf_hdrs ++ ++.PHONY: libbpf_hdrs ++ + $(obj)/xdp_redirect_cpu_user.o: $(obj)/xdp_redirect_cpu.skel.h + $(obj)/xdp_redirect_map_multi_user.o: $(obj)/xdp_redirect_map_multi.skel.h + $(obj)/xdp_redirect_map_user.o: $(obj)/xdp_redirect_map.skel.h +@@ -320,6 +345,17 @@ $(obj)/hbm_out_kern.o: $(src)/hbm.h $(src)/hbm_kern.h + $(obj)/hbm.o: $(src)/hbm.h + $(obj)/hbm_edt_kern.o: $(src)/hbm.h $(src)/hbm_kern.h + ++# Override includes for xdp_sample_user.o because $(srctree)/usr/include in ++# TPROGS_CFLAGS causes conflicts ++XDP_SAMPLE_CFLAGS += -Wall -O2 \ ++ -I$(src)/../../tools/include \ ++ -I$(src)/../../tools/include/uapi \ ++ -I$(LIBBPF_INCLUDE) \ ++ -I$(src)/../../tools/testing/selftests/bpf ++ ++$(obj)/$(XDP_SAMPLE): TPROGS_CFLAGS = $(XDP_SAMPLE_CFLAGS) ++$(obj)/$(XDP_SAMPLE): $(src)/xdp_sample_user.h $(src)/xdp_sample_shared.h ++ + -include $(BPF_SAMPLES_PATH)/Makefile.target + + VMLINUX_BTF_PATHS ?= $(abspath $(if $(O),$(O)/vmlinux)) \ +@@ -366,7 +402,7 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/x + $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(SRCARCH) \ + -Wno-compare-distinct-pointer-types -I$(srctree)/include \ + -I$(srctree)/samples/bpf -I$(srctree)/tools/include \ +- -I$(srctree)/tools/lib $(CLANG_SYS_INCLUDES) \ ++ -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ + -c $(filter %.bpf.c,$^) -o $@ + + LINKED_SKELS := xdp_redirect_cpu.skel.h xdp_redirect_map_multi.skel.h \ +@@ -403,7 +439,7 @@ $(obj)/%.o: $(src)/%.c + @echo " CLANG-bpf " $@ + $(Q)$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(BPF_EXTRA_CFLAGS) \ + -I$(obj) -I$(srctree)/tools/testing/selftests/bpf/ \ +- -I$(srctree)/tools/lib/ \ ++ -I$(LIBBPF_INCLUDE) \ + -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \ + -D__TARGET_ARCH_$(SRCARCH) -Wno-compare-distinct-pointer-types \ + -Wno-gnu-variable-sized-type-not-at-end \ +diff --git a/samples/bpf/Makefile.target b/samples/bpf/Makefile.target +index 5a368affa0386..7621f55e2947d 100644 +--- a/samples/bpf/Makefile.target ++++ b/samples/bpf/Makefile.target +@@ -73,14 +73,3 @@ quiet_cmd_tprog-cobjs = CC $@ + cmd_tprog-cobjs = $(CC) $(tprogc_flags) -c -o $@ $< + $(tprog-cobjs): $(obj)/%.o: $(src)/%.c FORCE + $(call if_changed_dep,tprog-cobjs) +- +-# Override includes for xdp_sample_user.o because $(srctree)/usr/include in +-# TPROGS_CFLAGS causes conflicts +-XDP_SAMPLE_CFLAGS += -Wall -O2 -lm \ +- -I./tools/include \ +- -I./tools/include/uapi \ +- -I./tools/lib \ +- -I./tools/testing/selftests/bpf +-$(obj)/xdp_sample_user.o: $(src)/xdp_sample_user.c \ +- $(src)/xdp_sample_user.h $(src)/xdp_sample_shared.h +- $(CC) $(XDP_SAMPLE_CFLAGS) -c -o $@ $< +diff --git a/samples/bpf/hbm_kern.h b/samples/bpf/hbm_kern.h +index 722b3fadb4675..1752a46a2b056 100644 +--- a/samples/bpf/hbm_kern.h ++++ b/samples/bpf/hbm_kern.h +@@ -9,8 +9,6 @@ + * Include file for sample Host Bandwidth Manager (HBM) BPF programs + */ + #define KBUILD_MODNAME "foo" +-#include <stddef.h> +-#include <stdbool.h> + #include <uapi/linux/bpf.h> + #include <uapi/linux/if_ether.h> + #include <uapi/linux/if_packet.h> +diff --git a/samples/bpf/lwt_len_hist_kern.c b/samples/bpf/lwt_len_hist_kern.c +index 9ed63e10e1709..1fa14c54963a1 100644 +--- a/samples/bpf/lwt_len_hist_kern.c ++++ b/samples/bpf/lwt_len_hist_kern.c +@@ -16,13 +16,6 @@ + #include <uapi/linux/in.h> + #include <bpf/bpf_helpers.h> + +-# define printk(fmt, ...) \ +- ({ \ +- char ____fmt[] = fmt; \ +- bpf_trace_printk(____fmt, sizeof(____fmt), \ +- ##__VA_ARGS__); \ +- }) +- + struct bpf_elf_map { + __u32 type; + __u32 size_key; +diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c +index 6e25fba64c72b..a81704d3317ba 100644 +--- a/samples/bpf/xdp_redirect_cpu_user.c ++++ b/samples/bpf/xdp_redirect_cpu_user.c +@@ -309,7 +309,6 @@ int main(int argc, char **argv) + const char *mprog_filename = NULL, *mprog_name = NULL; + struct xdp_redirect_cpu *skel; + struct bpf_map_info info = {}; +- char ifname_buf[IF_NAMESIZE]; + struct bpf_cpumap_val value; + __u32 infosz = sizeof(info); + int ret = EXIT_FAIL_OPTION; +@@ -325,7 +324,6 @@ int main(int argc, char **argv) + int add_cpu = -1; + int ifindex = -1; + int *cpu, i, opt; +- char *ifname; + __u32 qsize; + int n_cpus; + +@@ -391,11 +389,10 @@ int main(int argc, char **argv) + case 'd': + if (strlen(optarg) >= IF_NAMESIZE) { + fprintf(stderr, "-d/--dev name too long\n"); ++ usage(argv, long_options, __doc__, mask, true, skel->obj); + goto end_cpu; + } +- ifname = (char *)&ifname_buf; +- safe_strncpy(ifname, optarg, sizeof(ifname)); +- ifindex = if_nametoindex(ifname); ++ ifindex = if_nametoindex(optarg); + if (!ifindex) + ifindex = strtoul(optarg, NULL, 0); + if (!ifindex) { +diff --git a/samples/bpf/xdp_sample_user.c b/samples/bpf/xdp_sample_user.c +index b32d821781990..8740838e77679 100644 +--- a/samples/bpf/xdp_sample_user.c ++++ b/samples/bpf/xdp_sample_user.c +@@ -120,7 +120,10 @@ struct sample_output { + __u64 xmit; + } totals; + struct { +- __u64 pps; ++ union { ++ __u64 pps; ++ __u64 num; ++ }; + __u64 drop; + __u64 err; + } rx_cnt; +@@ -1322,7 +1325,7 @@ int sample_install_xdp(struct bpf_program *xdp_prog, int ifindex, bool generic, + + static void sample_summary_print(void) + { +- double period = sample_out.rx_cnt.pps; ++ double num = sample_out.rx_cnt.num; + + if (sample_out.totals.rx) { + double pkts = sample_out.totals.rx; +@@ -1330,7 +1333,7 @@ static void sample_summary_print(void) + print_always(" Packets received : %'-10llu\n", + sample_out.totals.rx); + print_always(" Average packets/s : %'-10.0f\n", +- sample_round(pkts / period)); ++ sample_round(pkts / num)); + } + if (sample_out.totals.redir) { + double pkts = sample_out.totals.redir; +@@ -1338,7 +1341,7 @@ static void sample_summary_print(void) + print_always(" Packets redirected : %'-10llu\n", + sample_out.totals.redir); + print_always(" Average redir/s : %'-10.0f\n", +- sample_round(pkts / period)); ++ sample_round(pkts / num)); + } + if (sample_out.totals.drop) + print_always(" Rx dropped : %'-10llu\n", +@@ -1355,7 +1358,7 @@ static void sample_summary_print(void) + print_always(" Packets transmitted : %'-10llu\n", + sample_out.totals.xmit); + print_always(" Average transmit/s : %'-10.0f\n", +- sample_round(pkts / period)); ++ sample_round(pkts / num)); + } + } + +@@ -1422,7 +1425,7 @@ static int sample_stats_collect(struct stats_record *rec) + return 0; + } + +-static void sample_summary_update(struct sample_output *out, int interval) ++static void sample_summary_update(struct sample_output *out) + { + sample_out.totals.rx += out->totals.rx; + sample_out.totals.redir += out->totals.redir; +@@ -1430,12 +1433,11 @@ static void sample_summary_update(struct sample_output *out, int interval) + sample_out.totals.drop_xmit += out->totals.drop_xmit; + sample_out.totals.err += out->totals.err; + sample_out.totals.xmit += out->totals.xmit; +- sample_out.rx_cnt.pps += interval; ++ sample_out.rx_cnt.num++; + } + + static void sample_stats_print(int mask, struct stats_record *cur, +- struct stats_record *prev, char *prog_name, +- int interval) ++ struct stats_record *prev, char *prog_name) + { + struct sample_output out = {}; + +@@ -1452,7 +1454,7 @@ static void sample_stats_print(int mask, struct stats_record *cur, + else if (mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI) + stats_get_devmap_xmit_multi(cur, prev, 0, &out, + mask & SAMPLE_DEVMAP_XMIT_CNT); +- sample_summary_update(&out, interval); ++ sample_summary_update(&out); + + stats_print(prog_name, mask, cur, prev, &out); + } +@@ -1495,7 +1497,7 @@ static void swap(struct stats_record **a, struct stats_record **b) + } + + static int sample_timer_cb(int timerfd, struct stats_record **rec, +- struct stats_record **prev, int interval) ++ struct stats_record **prev) + { + char line[64] = "Summary"; + int ret; +@@ -1524,7 +1526,7 @@ static int sample_timer_cb(int timerfd, struct stats_record **rec, + snprintf(line, sizeof(line), "%s->%s", f ?: "?", t ?: "?"); + } + +- sample_stats_print(sample_mask, *rec, *prev, line, interval); ++ sample_stats_print(sample_mask, *rec, *prev, line); + return 0; + } + +@@ -1579,7 +1581,7 @@ int sample_run(int interval, void (*post_cb)(void *), void *ctx) + if (pfd[0].revents & POLLIN) + ret = sample_signal_cb(); + else if (pfd[1].revents & POLLIN) +- ret = sample_timer_cb(timerfd, &rec, &prev, interval); ++ ret = sample_timer_cb(timerfd, &rec, &prev); + + if (ret) + break; +diff --git a/samples/bpf/xdp_sample_user.h b/samples/bpf/xdp_sample_user.h +index d97465ff8c62c..5f44b877ecf5f 100644 +--- a/samples/bpf/xdp_sample_user.h ++++ b/samples/bpf/xdp_sample_user.h +@@ -45,7 +45,9 @@ const char *get_driver_name(int ifindex); + int get_mac_addr(int ifindex, void *mac_addr); + + #pragma GCC diagnostic push ++#ifndef __clang__ + #pragma GCC diagnostic ignored "-Wstringop-truncation" ++#endif + __attribute__((unused)) + static inline char *safe_strncpy(char *dst, const char *src, size_t size) + { +diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c +index 5b9a09957c6e0..89e6bf27cd9f6 100644 +--- a/samples/ftrace/ftrace-direct-modify.c ++++ b/samples/ftrace/ftrace-direct-modify.c +@@ -3,6 +3,9 @@ + #include <linux/kthread.h> + #include <linux/ftrace.h> + ++extern void my_direct_func1(void); ++extern void my_direct_func2(void); ++ + void my_direct_func1(void) + { + trace_printk("my direct func1\n"); +diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c +index 3f0079c9bd6fa..11b99325f3dbf 100644 +--- a/samples/ftrace/ftrace-direct-too.c ++++ b/samples/ftrace/ftrace-direct-too.c +@@ -4,6 +4,9 @@ + #include <linux/mm.h> /* for handle_mm_fault() */ + #include <linux/ftrace.h> + ++extern void my_direct_func(struct vm_area_struct *vma, ++ unsigned long address, unsigned int flags); ++ + void my_direct_func(struct vm_area_struct *vma, + unsigned long address, unsigned int flags) + { +diff --git a/samples/ftrace/ftrace-direct.c b/samples/ftrace/ftrace-direct.c +index a2729d1ef17f5..642c50b5f7166 100644 +--- a/samples/ftrace/ftrace-direct.c ++++ b/samples/ftrace/ftrace-direct.c +@@ -4,6 +4,8 @@ + #include <linux/sched.h> /* for wake_up_process() */ + #include <linux/ftrace.h> + ++extern void my_direct_func(struct task_struct *p); ++ + void my_direct_func(struct task_struct *p) + { + trace_printk("waking up %s-%d\n", p->comm, p->pid); +diff --git a/samples/kprobes/kretprobe_example.c b/samples/kprobes/kretprobe_example.c +index 5dc1bf3baa98b..228321ecb1616 100644 +--- a/samples/kprobes/kretprobe_example.c ++++ b/samples/kprobes/kretprobe_example.c +@@ -86,7 +86,7 @@ static int __init kretprobe_init(void) + ret = register_kretprobe(&my_kretprobe); + if (ret < 0) { + pr_err("register_kretprobe failed, returned %d\n", ret); +- return -1; ++ return ret; + } + pr_info("Planted return probe at %s: %p\n", + my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr); +diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn +index d538255038747..8be892887d716 100644 +--- a/scripts/Makefile.extrawarn ++++ b/scripts/Makefile.extrawarn +@@ -51,6 +51,7 @@ KBUILD_CFLAGS += -Wno-sign-compare + KBUILD_CFLAGS += -Wno-format-zero-length + KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) + KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare ++KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access) + endif + + endif +diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff +index d3422ee15e300..f2bbde4bba86b 100755 +--- a/scripts/dtc/dtx_diff ++++ b/scripts/dtc/dtx_diff +@@ -59,12 +59,8 @@ Otherwise DTx is treated as a dts source file (aka .dts). + or '/include/' to be processed. + + If DTx_1 and DTx_2 are in different architectures, then this script +- may not work since \${ARCH} is part of the include path. Two possible +- workarounds: +- +- `basename $0` \\ +- <(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\ +- <(ARCH=arch_of_dtx_2 `basename $0` DTx_2) ++ may not work since \${ARCH} is part of the include path. The following ++ workaround can be used: + + `basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts + `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts +diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c +index cf72680cd7692..4a828bca071e8 100644 +--- a/scripts/kconfig/confdata.c ++++ b/scripts/kconfig/confdata.c +@@ -983,14 +983,19 @@ static int conf_write_dep(const char *name) + + static int conf_touch_deps(void) + { +- const char *name; ++ const char *name, *tmp; + struct symbol *sym; + int res, i; + +- strcpy(depfile_path, "include/config/"); +- depfile_prefix_len = strlen(depfile_path); +- + name = conf_get_autoconfig_name(); ++ tmp = strrchr(name, '/'); ++ depfile_prefix_len = tmp ? tmp - name + 1 : 0; ++ if (depfile_prefix_len + 1 > sizeof(depfile_path)) ++ return -1; ++ ++ strncpy(depfile_path, name, depfile_prefix_len); ++ depfile_path[depfile_prefix_len] = 0; ++ + conf_read_simple(name, S_DEF_AUTO); + sym_calc_value(modules_sym); + +diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c +index 0590f86df6e40..748da578b418c 100644 +--- a/scripts/kconfig/preprocess.c ++++ b/scripts/kconfig/preprocess.c +@@ -141,7 +141,7 @@ static char *do_lineno(int argc, char *argv[]) + static char *do_shell(int argc, char *argv[]) + { + FILE *p; +- char buf[256]; ++ char buf[4096]; + char *cmd; + size_t nread; + int i; +diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl +index b2d8b8aa2d99e..8f636a23bc3f2 100755 +--- a/scripts/leaking_addresses.pl ++++ b/scripts/leaking_addresses.pl +@@ -455,8 +455,9 @@ sub parse_file + + open my $fh, "<", $file or return; + while ( <$fh> ) { ++ chomp; + if (may_leak_address($_)) { +- print $file . ': ' . $_; ++ printf("$file: $_\n"); + } + } + close $fh; +diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl +index 7d631aaa0ae11..3ccb2c70add4d 100755 +--- a/scripts/recordmcount.pl ++++ b/scripts/recordmcount.pl +@@ -219,7 +219,7 @@ if ($arch eq "x86_64") { + + } elsif ($arch eq "s390" && $bits == 64) { + if ($cc =~ /-DCC_USING_HOTPATCH/) { +- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$"; ++ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*(brcl\\s*0,|jgnop\\s*)[0-9a-f]+ <([^\+]*)>\$"; + $mcount_adjust = 0; + } + $alignment = 8; +diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install +index 288e86a9d1e58..f126ecbb0494d 100755 +--- a/scripts/sphinx-pre-install ++++ b/scripts/sphinx-pre-install +@@ -78,6 +78,7 @@ my %texlive = ( + 'ucs.sty' => 'texlive-ucs', + 'upquote.sty' => 'texlive-upquote', + 'wrapfig.sty' => 'texlive-wrapfig', ++ 'ctexhook.sty' => 'texlive-ctex', + ); + + # +@@ -369,6 +370,9 @@ sub give_debian_hints() + ); + + if ($pdf) { ++ check_missing_file(["/usr/share/texlive/texmf-dist/tex/latex/ctex/ctexhook.sty"], ++ "texlive-lang-chinese", 2); ++ + check_missing_file(["/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"], + "fonts-dejavu", 2); + +diff --git a/security/Kconfig b/security/Kconfig +index 0ced7fd33e4d0..fe6c0395fa025 100644 +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -191,6 +191,9 @@ config HARDENED_USERCOPY_PAGESPAN + config FORTIFY_SOURCE + bool "Harden common str/mem functions against buffer overflows" + depends on ARCH_HAS_FORTIFY_SOURCE ++ # https://bugs.llvm.org/show_bug.cgi?id=50322 ++ # https://bugs.llvm.org/show_bug.cgi?id=41459 ++ depends on !CC_IS_CLANG + help + Detect overflows of buffers in common string and memory functions + where the compiler can determine and validate the buffer sizes. +diff --git a/security/apparmor/label.c b/security/apparmor/label.c +index e68bcedca976b..6222fdfebe4e5 100644 +--- a/security/apparmor/label.c ++++ b/security/apparmor/label.c +@@ -1454,7 +1454,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp) + if (label->hname || labels_ns(label) != ns) + return res; + +- if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) == -1) ++ if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) < 0) + return res; + + ls = labels_set(label); +@@ -1704,7 +1704,7 @@ int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, + + /** + * aa_label_acntsxprint - allocate a __counted string buffer and print label +- * @strp: buffer to write to. (MAY BE NULL if @size == 0) ++ * @strp: buffer to write to. + * @ns: namespace profile is being viewed from + * @label: label to view (NOT NULL) + * @flags: flags controlling what label info is printed +diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c +index 23240d793b074..895f4b9ce8c6b 100644 +--- a/security/integrity/digsig_asymmetric.c ++++ b/security/integrity/digsig_asymmetric.c +@@ -109,22 +109,25 @@ int asymmetric_verify(struct key *keyring, const char *sig, + + pk = asymmetric_key_public_key(key); + pks.pkey_algo = pk->pkey_algo; +- if (!strcmp(pk->pkey_algo, "rsa")) ++ if (!strcmp(pk->pkey_algo, "rsa")) { + pks.encoding = "pkcs1"; +- else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) ++ } else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) { + /* edcsa-nist-p192 etc. */ + pks.encoding = "x962"; +- else if (!strcmp(pk->pkey_algo, "ecrdsa") || +- !strcmp(pk->pkey_algo, "sm2")) ++ } else if (!strcmp(pk->pkey_algo, "ecrdsa") || ++ !strcmp(pk->pkey_algo, "sm2")) { + pks.encoding = "raw"; +- else +- return -ENOPKG; ++ } else { ++ ret = -ENOPKG; ++ goto out; ++ } + + pks.digest = (u8 *)data; + pks.digest_size = datalen; + pks.s = hdr->sig; + pks.s_size = siglen; + ret = verify_signature(key, &pks); ++out: + key_put(key); + pr_debug("%s() = %d\n", __func__, ret); + return ret; +diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c +index 1c8435dfabeea..08f907382c618 100644 +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -78,7 +78,7 @@ static struct xattr_list evm_config_default_xattrnames[] = { + + LIST_HEAD(evm_config_xattrnames); + +-static int evm_fixmode; ++static int evm_fixmode __ro_after_init; + static int __init evm_set_fixmode(char *str) + { + if (strncmp(str, "fix", 3) == 0) +diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c +index 3d8e9d5db5aa5..3ad8f7734208b 100644 +--- a/security/integrity/ima/ima_fs.c ++++ b/security/integrity/ima/ima_fs.c +@@ -496,12 +496,12 @@ int __init ima_fs_init(void) + + return 0; + out: ++ securityfs_remove(ima_policy); + securityfs_remove(violations); + securityfs_remove(runtime_measurements_count); + securityfs_remove(ascii_runtime_measurements); + securityfs_remove(binary_runtime_measurements); + securityfs_remove(ima_symlink); + securityfs_remove(ima_dir); +- securityfs_remove(ima_policy); + return -1; + } +diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c +index 87b9b71cb8201..fa5a93dbe5d26 100644 +--- a/security/integrity/ima/ima_policy.c ++++ b/security/integrity/ima/ima_policy.c +@@ -228,7 +228,7 @@ static struct ima_rule_entry *arch_policy_entry __ro_after_init; + static LIST_HEAD(ima_default_rules); + static LIST_HEAD(ima_policy_rules); + static LIST_HEAD(ima_temp_rules); +-static struct list_head *ima_rules = &ima_default_rules; ++static struct list_head __rcu *ima_rules = (struct list_head __rcu *)(&ima_default_rules); + + static int ima_policy __initdata; + +@@ -675,12 +675,14 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, + { + struct ima_rule_entry *entry; + int action = 0, actmask = flags | (flags << 1); ++ struct list_head *ima_rules_tmp; + + if (template_desc && !*template_desc) + *template_desc = ima_template_desc_current(); + + rcu_read_lock(); +- list_for_each_entry_rcu(entry, ima_rules, list) { ++ ima_rules_tmp = rcu_dereference(ima_rules); ++ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { + + if (!(entry->action & actmask)) + continue; +@@ -741,9 +743,11 @@ void ima_update_policy_flags(void) + { + struct ima_rule_entry *entry; + int new_policy_flag = 0; ++ struct list_head *ima_rules_tmp; + + rcu_read_lock(); +- list_for_each_entry(entry, ima_rules, list) { ++ ima_rules_tmp = rcu_dereference(ima_rules); ++ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { + /* + * SETXATTR_CHECK rules do not implement a full policy check + * because rule checking would probably have an important +@@ -968,10 +972,10 @@ void ima_update_policy(void) + + list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu); + +- if (ima_rules != policy) { ++ if (ima_rules != (struct list_head __rcu *)policy) { + ima_policy_flag = 0; +- ima_rules = policy; + ++ rcu_assign_pointer(ima_rules, policy); + /* + * IMA architecture specific policy rules are specified + * as strings and converted to an array of ima_entry_rules +@@ -1061,7 +1065,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, + pr_warn("rule for LSM \'%s\' is undefined\n", + entry->lsm[lsm_rule].args_p); + +- if (ima_rules == &ima_default_rules) { ++ if (ima_rules == (struct list_head __rcu *)(&ima_default_rules)) { + kfree(entry->lsm[lsm_rule].args_p); + entry->lsm[lsm_rule].args_p = NULL; + result = -EINVAL; +@@ -1768,9 +1772,11 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) + { + loff_t l = *pos; + struct ima_rule_entry *entry; ++ struct list_head *ima_rules_tmp; + + rcu_read_lock(); +- list_for_each_entry_rcu(entry, ima_rules, list) { ++ ima_rules_tmp = rcu_dereference(ima_rules); ++ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { + if (!l--) { + rcu_read_unlock(); + return entry; +@@ -1789,7 +1795,8 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) + rcu_read_unlock(); + (*pos)++; + +- return (&entry->list == ima_rules) ? NULL : entry; ++ return (&entry->list == &ima_default_rules || ++ &entry->list == &ima_policy_rules) ? NULL : entry; + } + + void ima_policy_stop(struct seq_file *m, void *v) +@@ -1845,6 +1852,14 @@ int ima_policy_show(struct seq_file *m, void *v) + + rcu_read_lock(); + ++ /* Do not print rules with inactive LSM labels */ ++ for (i = 0; i < MAX_LSM_RULES; i++) { ++ if (entry->lsm[i].args_p && !entry->lsm[i].rule) { ++ rcu_read_unlock(); ++ return 0; ++ } ++ } ++ + if (entry->action & MEASURE) + seq_puts(m, pt(Opt_measure)); + if (entry->action & DONT_MEASURE) +@@ -2014,6 +2029,7 @@ bool ima_appraise_signature(enum kernel_read_file_id id) + struct ima_rule_entry *entry; + bool found = false; + enum ima_hooks func; ++ struct list_head *ima_rules_tmp; + + if (id >= READING_MAX_ID) + return false; +@@ -2021,7 +2037,8 @@ bool ima_appraise_signature(enum kernel_read_file_id id) + func = read_idmap[id] ?: FILE_CHECK; + + rcu_read_lock(); +- list_for_each_entry_rcu(entry, ima_rules, list) { ++ ima_rules_tmp = rcu_dereference(ima_rules); ++ list_for_each_entry_rcu(entry, ima_rules_tmp, list) { + if (entry->action != APPRAISE) + continue; + +diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c +index 694560396be05..db1ad6d7a57fb 100644 +--- a/security/integrity/ima/ima_template.c ++++ b/security/integrity/ima/ima_template.c +@@ -29,6 +29,7 @@ static struct ima_template_desc builtin_templates[] = { + + static LIST_HEAD(defined_templates); + static DEFINE_SPINLOCK(template_list); ++static int template_setup_done; + + static const struct ima_template_field supported_fields[] = { + {.field_id = "d", .field_init = ima_eventdigest_init, +@@ -101,10 +102,11 @@ static int __init ima_template_setup(char *str) + struct ima_template_desc *template_desc; + int template_len = strlen(str); + +- if (ima_template) ++ if (template_setup_done) + return 1; + +- ima_init_template_list(); ++ if (!ima_template) ++ ima_init_template_list(); + + /* + * Verify that a template with the supplied name exists. +@@ -128,6 +130,7 @@ static int __init ima_template_setup(char *str) + } + + ima_template = template_desc; ++ template_setup_done = 1; + return 1; + } + __setup("ima_template=", ima_template_setup); +@@ -136,7 +139,7 @@ static int __init ima_template_fmt_setup(char *str) + { + int num_templates = ARRAY_SIZE(builtin_templates); + +- if (ima_template) ++ if (template_setup_done) + return 1; + + if (template_desc_init_fields(str, NULL, NULL) < 0) { +@@ -147,6 +150,7 @@ static int __init ima_template_fmt_setup(char *str) + + builtin_templates[num_templates - 1].fmt = str; + ima_template = builtin_templates + num_templates - 1; ++ template_setup_done = 1; + + return 1; + } +diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c +index 29220056207f4..0ec5e4c22cb2a 100644 +--- a/security/integrity/integrity_audit.c ++++ b/security/integrity/integrity_audit.c +@@ -45,6 +45,8 @@ void integrity_audit_message(int audit_msgno, struct inode *inode, + return; + + ab = audit_log_start(audit_context(), GFP_KERNEL, audit_msgno); ++ if (!ab) ++ return; + audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", + task_pid_nr(current), + from_kuid(&init_user_ns, current_uid()), +diff --git a/security/security.c b/security/security.c +index 9ffa9e9c5c554..67264cb08fb31 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -747,25 +747,25 @@ static int lsm_superblock_alloc(struct super_block *sb) + + /* Security operations */ + +-int security_binder_set_context_mgr(struct task_struct *mgr) ++int security_binder_set_context_mgr(const struct cred *mgr) + { + return call_int_hook(binder_set_context_mgr, 0, mgr); + } + +-int security_binder_transaction(struct task_struct *from, +- struct task_struct *to) ++int security_binder_transaction(const struct cred *from, ++ const struct cred *to) + { + return call_int_hook(binder_transaction, 0, from, to); + } + +-int security_binder_transfer_binder(struct task_struct *from, +- struct task_struct *to) ++int security_binder_transfer_binder(const struct cred *from, ++ const struct cred *to) + { + return call_int_hook(binder_transfer_binder, 0, from, to); + } + +-int security_binder_transfer_file(struct task_struct *from, +- struct task_struct *to, struct file *file) ++int security_binder_transfer_file(const struct cred *from, ++ const struct cred *to, struct file *file) + { + return call_int_hook(binder_transfer_file, 0, from, to, file); + } +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index e7ebd45ca3457..baa12d1007c7c 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -255,29 +255,6 @@ static inline u32 task_sid_obj(const struct task_struct *task) + return sid; + } + +-/* +- * get the security ID of a task for use with binder +- */ +-static inline u32 task_sid_binder(const struct task_struct *task) +-{ +- /* +- * In many case where this function is used we should be using the +- * task's subjective SID, but we can't reliably access the subjective +- * creds of a task other than our own so we must use the objective +- * creds/SID, which are safe to access. The downside is that if a task +- * is temporarily overriding it's creds it will not be reflected here; +- * however, it isn't clear that binder would handle that case well +- * anyway. +- * +- * If this ever changes and we can safely reference the subjective +- * creds/SID of another task, this function will make it easier to +- * identify the various places where we make use of the task SIDs in +- * the binder code. It is also likely that we will need to adjust +- * the main drivers/android binder code as well. +- */ +- return task_sid_obj(task); +-} +- + static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); + + /* +@@ -634,10 +611,11 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, + return 0; + } + +-static int parse_sid(struct super_block *sb, const char *s, u32 *sid) ++static int parse_sid(struct super_block *sb, const char *s, u32 *sid, ++ gfp_t gfp) + { + int rc = security_context_str_to_sid(&selinux_state, s, +- sid, GFP_KERNEL); ++ sid, gfp); + if (rc) + pr_warn("SELinux: security_context_str_to_sid" + "(%s) failed for (dev %s, type %s) errno=%d\n", +@@ -708,7 +686,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, + */ + if (opts) { + if (opts->fscontext) { +- rc = parse_sid(sb, opts->fscontext, &fscontext_sid); ++ rc = parse_sid(sb, opts->fscontext, &fscontext_sid, ++ GFP_KERNEL); + if (rc) + goto out; + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, +@@ -717,7 +696,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, + sbsec->flags |= FSCONTEXT_MNT; + } + if (opts->context) { +- rc = parse_sid(sb, opts->context, &context_sid); ++ rc = parse_sid(sb, opts->context, &context_sid, ++ GFP_KERNEL); + if (rc) + goto out; + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, +@@ -726,7 +706,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, + sbsec->flags |= CONTEXT_MNT; + } + if (opts->rootcontext) { +- rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid); ++ rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid, ++ GFP_KERNEL); + if (rc) + goto out; + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, +@@ -735,7 +716,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, + sbsec->flags |= ROOTCONTEXT_MNT; + } + if (opts->defcontext) { +- rc = parse_sid(sb, opts->defcontext, &defcontext_sid); ++ rc = parse_sid(sb, opts->defcontext, &defcontext_sid, ++ GFP_KERNEL); + if (rc) + goto out; + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, +@@ -1005,18 +987,22 @@ out: + static int selinux_add_opt(int token, const char *s, void **mnt_opts) + { + struct selinux_mnt_opts *opts = *mnt_opts; ++ bool is_alloc_opts = false; + + if (token == Opt_seclabel) /* eaten and completely ignored */ + return 0; + ++ if (!s) ++ return -ENOMEM; ++ + if (!opts) { + opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL); + if (!opts) + return -ENOMEM; + *mnt_opts = opts; ++ is_alloc_opts = true; + } +- if (!s) +- return -ENOMEM; ++ + switch (token) { + case Opt_context: + if (opts->context || opts->defcontext) +@@ -1041,6 +1027,10 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts) + } + return 0; + Einval: ++ if (is_alloc_opts) { ++ kfree(opts); ++ *mnt_opts = NULL; ++ } + pr_warn(SEL_MOUNT_FAIL_MSG); + return -EINVAL; + } +@@ -2066,18 +2056,19 @@ static inline u32 open_file_to_av(struct file *file) + + /* Hook functions begin here. */ + +-static int selinux_binder_set_context_mgr(struct task_struct *mgr) ++static int selinux_binder_set_context_mgr(const struct cred *mgr) + { + return avc_has_perm(&selinux_state, +- current_sid(), task_sid_binder(mgr), SECCLASS_BINDER, ++ current_sid(), cred_sid(mgr), SECCLASS_BINDER, + BINDER__SET_CONTEXT_MGR, NULL); + } + +-static int selinux_binder_transaction(struct task_struct *from, +- struct task_struct *to) ++static int selinux_binder_transaction(const struct cred *from, ++ const struct cred *to) + { + u32 mysid = current_sid(); +- u32 fromsid = task_sid_binder(from); ++ u32 fromsid = cred_sid(from); ++ u32 tosid = cred_sid(to); + int rc; + + if (mysid != fromsid) { +@@ -2088,24 +2079,24 @@ static int selinux_binder_transaction(struct task_struct *from, + return rc; + } + +- return avc_has_perm(&selinux_state, fromsid, task_sid_binder(to), ++ return avc_has_perm(&selinux_state, fromsid, tosid, + SECCLASS_BINDER, BINDER__CALL, NULL); + } + +-static int selinux_binder_transfer_binder(struct task_struct *from, +- struct task_struct *to) ++static int selinux_binder_transfer_binder(const struct cred *from, ++ const struct cred *to) + { + return avc_has_perm(&selinux_state, +- task_sid_binder(from), task_sid_binder(to), ++ cred_sid(from), cred_sid(to), + SECCLASS_BINDER, BINDER__TRANSFER, + NULL); + } + +-static int selinux_binder_transfer_file(struct task_struct *from, +- struct task_struct *to, ++static int selinux_binder_transfer_file(const struct cred *from, ++ const struct cred *to, + struct file *file) + { +- u32 sid = task_sid_binder(to); ++ u32 sid = cred_sid(to); + struct file_security_struct *fsec = selinux_file(file); + struct dentry *dentry = file->f_path.dentry; + struct inode_security_struct *isec; +@@ -2723,14 +2714,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) + return (sbsec->flags & SE_MNTMASK) ? 1 : 0; + + if (opts->fscontext) { +- rc = parse_sid(sb, opts->fscontext, &sid); ++ rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT); + if (rc) + return 1; + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) + return 1; + } + if (opts->context) { +- rc = parse_sid(sb, opts->context, &sid); ++ rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT); + if (rc) + return 1; + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) +@@ -2740,14 +2731,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) + struct inode_security_struct *root_isec; + + root_isec = backing_inode_security(sb->s_root); +- rc = parse_sid(sb, opts->rootcontext, &sid); ++ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT); + if (rc) + return 1; + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) + return 1; + } + if (opts->defcontext) { +- rc = parse_sid(sb, opts->defcontext, &sid); ++ rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT); + if (rc) + return 1; + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) +@@ -2770,14 +2761,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) + return 0; + + if (opts->fscontext) { +- rc = parse_sid(sb, opts->fscontext, &sid); ++ rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL); + if (rc) + return rc; + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) + goto out_bad_option; + } + if (opts->context) { +- rc = parse_sid(sb, opts->context, &sid); ++ rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL); + if (rc) + return rc; + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) +@@ -2786,14 +2777,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) + if (opts->rootcontext) { + struct inode_security_struct *root_isec; + root_isec = backing_inode_security(sb->s_root); +- rc = parse_sid(sb, opts->rootcontext, &sid); ++ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL); + if (rc) + return rc; + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) + goto out_bad_option; + } + if (opts->defcontext) { +- rc = parse_sid(sb, opts->defcontext, &sid); ++ rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL); + if (rc) + return rc; + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) +@@ -5829,7 +5820,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, + struct common_audit_data ad; + struct lsm_network_audit net = {0,}; + char *addrp; +- u8 proto; ++ u8 proto = 0; + + if (sk == NULL) + return NF_ACCEPT; +diff --git a/security/selinux/ima.c b/security/selinux/ima.c +index 727c4e43219d7..ff7aea6b3774a 100644 +--- a/security/selinux/ima.c ++++ b/security/selinux/ima.c +@@ -77,7 +77,7 @@ void selinux_ima_measure_state_locked(struct selinux_state *state) + size_t policy_len; + int rc = 0; + +- WARN_ON(!mutex_is_locked(&state->policy_mutex)); ++ lockdep_assert_held(&state->policy_mutex); + + state_str = selinux_ima_collect_state(state); + if (!state_str) { +@@ -117,7 +117,7 @@ void selinux_ima_measure_state_locked(struct selinux_state *state) + */ + void selinux_ima_measure_state(struct selinux_state *state) + { +- WARN_ON(mutex_is_locked(&state->policy_mutex)); ++ lockdep_assert_not_held(&state->policy_mutex); + + mutex_lock(&state->policy_mutex); + selinux_ima_measure_state_locked(state); +diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c +index 2ec6e5cd25d9b..feb206f3acb4a 100644 +--- a/security/selinux/ss/conditional.c ++++ b/security/selinux/ss/conditional.c +@@ -152,6 +152,8 @@ static void cond_list_destroy(struct policydb *p) + for (i = 0; i < p->cond_list_len; i++) + cond_node_destroy(&p->cond_list[i]); + kfree(p->cond_list); ++ p->cond_list = NULL; ++ p->cond_list_len = 0; + } + + void cond_policydb_destroy(struct policydb *p) +@@ -441,7 +443,6 @@ int cond_read_list(struct policydb *p, void *fp) + return 0; + err: + cond_list_destroy(p); +- p->cond_list = NULL; + return rc; + } + +diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c +index b8f6b3e0a9219..a91fb0ed00de3 100644 +--- a/security/selinux/ss/hashtab.c ++++ b/security/selinux/ss/hashtab.c +@@ -30,13 +30,20 @@ static u32 hashtab_compute_size(u32 nel) + + int hashtab_init(struct hashtab *h, u32 nel_hint) + { +- h->size = hashtab_compute_size(nel_hint); ++ u32 size = hashtab_compute_size(nel_hint); ++ ++ /* should already be zeroed, but better be safe */ + h->nel = 0; +- if (!h->size) +- return 0; ++ h->size = 0; ++ h->htable = NULL; + +- h->htable = kcalloc(h->size, sizeof(*h->htable), GFP_KERNEL); +- return h->htable ? 0 : -ENOMEM; ++ if (size) { ++ h->htable = kcalloc(size, sizeof(*h->htable), GFP_KERNEL); ++ if (!h->htable) ++ return -ENOMEM; ++ h->size = size; ++ } ++ return 0; + } + + int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, +diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c +index e5f1b2757a83a..c4931bf6f92a4 100644 +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -2376,6 +2376,43 @@ err_policy: + return rc; + } + ++/** ++ * ocontext_to_sid - Helper to safely get sid for an ocontext ++ * @sidtab: SID table ++ * @c: ocontext structure ++ * @index: index of the context entry (0 or 1) ++ * @out_sid: pointer to the resulting SID value ++ * ++ * For all ocontexts except OCON_ISID the SID fields are populated ++ * on-demand when needed. Since updating the SID value is an SMP-sensitive ++ * operation, this helper must be used to do that safely. ++ * ++ * WARNING: This function may return -ESTALE, indicating that the caller ++ * must retry the operation after re-acquiring the policy pointer! ++ */ ++static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c, ++ size_t index, u32 *out_sid) ++{ ++ int rc; ++ u32 sid; ++ ++ /* Ensure the associated sidtab entry is visible to this thread. */ ++ sid = smp_load_acquire(&c->sid[index]); ++ if (!sid) { ++ rc = sidtab_context_to_sid(sidtab, &c->context[index], &sid); ++ if (rc) ++ return rc; ++ ++ /* ++ * Ensure the new sidtab entry is visible to other threads ++ * when they see the SID. ++ */ ++ smp_store_release(&c->sid[index], sid); ++ } ++ *out_sid = sid; ++ return 0; ++} ++ + /** + * security_port_sid - Obtain the SID for a port. + * @state: SELinux state +@@ -2414,17 +2451,13 @@ retry: + } + + if (c) { +- if (!c->sid[0]) { +- rc = sidtab_context_to_sid(sidtab, &c->context[0], +- &c->sid[0]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; ++ rc = ocontext_to_sid(sidtab, c, 0, out_sid); ++ if (rc == -ESTALE) { ++ rcu_read_unlock(); ++ goto retry; + } +- *out_sid = c->sid[0]; ++ if (rc) ++ goto out; + } else { + *out_sid = SECINITSID_PORT; + } +@@ -2473,18 +2506,13 @@ retry: + } + + if (c) { +- if (!c->sid[0]) { +- rc = sidtab_context_to_sid(sidtab, +- &c->context[0], +- &c->sid[0]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; ++ rc = ocontext_to_sid(sidtab, c, 0, out_sid); ++ if (rc == -ESTALE) { ++ rcu_read_unlock(); ++ goto retry; + } +- *out_sid = c->sid[0]; ++ if (rc) ++ goto out; + } else + *out_sid = SECINITSID_UNLABELED; + +@@ -2533,17 +2561,13 @@ retry: + } + + if (c) { +- if (!c->sid[0]) { +- rc = sidtab_context_to_sid(sidtab, &c->context[0], +- &c->sid[0]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; ++ rc = ocontext_to_sid(sidtab, c, 0, out_sid); ++ if (rc == -ESTALE) { ++ rcu_read_unlock(); ++ goto retry; + } +- *out_sid = c->sid[0]; ++ if (rc) ++ goto out; + } else + *out_sid = SECINITSID_UNLABELED; + +@@ -2587,25 +2611,13 @@ retry: + } + + if (c) { +- if (!c->sid[0] || !c->sid[1]) { +- rc = sidtab_context_to_sid(sidtab, &c->context[0], +- &c->sid[0]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; +- rc = sidtab_context_to_sid(sidtab, &c->context[1], +- &c->sid[1]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; ++ rc = ocontext_to_sid(sidtab, c, 0, if_sid); ++ if (rc == -ESTALE) { ++ rcu_read_unlock(); ++ goto retry; + } +- *if_sid = c->sid[0]; ++ if (rc) ++ goto out; + } else + *if_sid = SECINITSID_NETIF; + +@@ -2697,18 +2709,13 @@ retry: + } + + if (c) { +- if (!c->sid[0]) { +- rc = sidtab_context_to_sid(sidtab, +- &c->context[0], +- &c->sid[0]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; ++ rc = ocontext_to_sid(sidtab, c, 0, out_sid); ++ if (rc == -ESTALE) { ++ rcu_read_unlock(); ++ goto retry; + } +- *out_sid = c->sid[0]; ++ if (rc) ++ goto out; + } else { + *out_sid = SECINITSID_NODE; + } +@@ -2873,7 +2880,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, + u16 sclass; + struct genfs *genfs; + struct ocontext *c; +- int rc, cmp = 0; ++ int cmp = 0; + + while (path[0] == '/' && path[1] == '/') + path++; +@@ -2887,9 +2894,8 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, + break; + } + +- rc = -ENOENT; + if (!genfs || cmp) +- goto out; ++ return -ENOENT; + + for (c = genfs->head; c; c = c->next) { + len = strlen(c->u.name); +@@ -2898,20 +2904,10 @@ static inline int __security_genfs_sid(struct selinux_policy *policy, + break; + } + +- rc = -ENOENT; + if (!c) +- goto out; +- +- if (!c->sid[0]) { +- rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); +- if (rc) +- goto out; +- } ++ return -ENOENT; + +- *sid = c->sid[0]; +- rc = 0; +-out: +- return rc; ++ return ocontext_to_sid(sidtab, c, 0, sid); + } + + /** +@@ -2996,17 +2992,13 @@ retry: + + if (c) { + sbsec->behavior = c->v.behavior; +- if (!c->sid[0]) { +- rc = sidtab_context_to_sid(sidtab, &c->context[0], +- &c->sid[0]); +- if (rc == -ESTALE) { +- rcu_read_unlock(); +- goto retry; +- } +- if (rc) +- goto out; ++ rc = ocontext_to_sid(sidtab, c, 0, &sbsec->sid); ++ if (rc == -ESTALE) { ++ rcu_read_unlock(); ++ goto retry; + } +- sbsec->sid = c->sid[0]; ++ if (rc) ++ goto out; + } else { + rc = __security_genfs_sid(policy, fstype, "/", + SECCLASS_DIR, &sbsec->sid); +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index 3a75d2a8f5178..658eab05599e6 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -693,9 +693,7 @@ static void smk_cipso_doi(void) + printk(KERN_WARNING "%s:%d remove rc = %d\n", + __func__, __LINE__, rc); + +- doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL); +- if (doip == NULL) +- panic("smack: Failed to initialize cipso DOI.\n"); ++ doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL | __GFP_NOFAIL); + doip->map.std = NULL; + doip->doi = smk_cipso_doi_value; + doip->type = CIPSO_V4_MAP_PASS; +@@ -714,7 +712,7 @@ static void smk_cipso_doi(void) + if (rc != 0) { + printk(KERN_WARNING "%s:%d map add rc = %d\n", + __func__, __LINE__, rc); +- kfree(doip); ++ netlbl_cfg_cipsov4_del(doip->doi, &nai); + return; + } + } +@@ -831,6 +829,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file) + static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, int format) + { ++ struct netlbl_lsm_catmap *old_cat; + struct smack_known *skp; + struct netlbl_lsm_secattr ncats; + char mapcatset[SMK_CIPSOLEN]; +@@ -920,9 +919,11 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, + + rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); + if (rc >= 0) { +- netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat); ++ old_cat = skp->smk_netlabel.attr.mls.cat; + 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); + rc = count; + /* + * This mapping may have been cached, so clear the cache. +diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c +index 1da2e3722b126..6799b1122c9d8 100644 +--- a/security/tomoyo/util.c ++++ b/security/tomoyo/util.c +@@ -1051,10 +1051,11 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) + return false; + if (!domain) + return true; ++ if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED])) ++ return false; + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list, + srcu_read_lock_held(&tomoyo_ss)) { + u16 perm; +- u8 i; + + if (ptr->is_deleted) + continue; +@@ -1065,23 +1066,23 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) + */ + switch (ptr->type) { + case TOMOYO_TYPE_PATH_ACL: +- data_race(perm = container_of(ptr, struct tomoyo_path_acl, head)->perm); ++ perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm); + break; + case TOMOYO_TYPE_PATH2_ACL: +- data_race(perm = container_of(ptr, struct tomoyo_path2_acl, head)->perm); ++ perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm); + break; + case TOMOYO_TYPE_PATH_NUMBER_ACL: +- data_race(perm = container_of(ptr, struct tomoyo_path_number_acl, head) ++ perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head) + ->perm); + break; + case TOMOYO_TYPE_MKDEV_ACL: +- data_race(perm = container_of(ptr, struct tomoyo_mkdev_acl, head)->perm); ++ perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm); + break; + case TOMOYO_TYPE_INET_ACL: +- data_race(perm = container_of(ptr, struct tomoyo_inet_acl, head)->perm); ++ perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm); + break; + case TOMOYO_TYPE_UNIX_ACL: +- data_race(perm = container_of(ptr, struct tomoyo_unix_acl, head)->perm); ++ perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm); + break; + case TOMOYO_TYPE_MANUAL_TASK_ACL: + perm = 0; +@@ -1089,21 +1090,17 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) + default: + perm = 1; + } +- for (i = 0; i < 16; i++) +- if (perm & (1 << i)) +- count++; ++ count += hweight16(perm); + } + if (count < tomoyo_profile(domain->ns, domain->profile)-> + pref[TOMOYO_PREF_MAX_LEARNING_ENTRY]) + return true; +- if (!domain->flags[TOMOYO_DIF_QUOTA_WARNED]) { +- domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true; +- /* r->granted = false; */ +- tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]); ++ WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true); ++ /* r->granted = false; */ ++ tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]); + #ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING +- pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n", +- domain->domainname->name); ++ pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n", ++ domain->domainname->name); + #endif +- } + return false; + } +diff --git a/sound/core/Makefile b/sound/core/Makefile +index d774792850f31..79e1407cd0de7 100644 +--- a/sound/core/Makefile ++++ b/sound/core/Makefile +@@ -9,7 +9,9 @@ ifneq ($(CONFIG_SND_PROC_FS),) + snd-y += info.o + snd-$(CONFIG_SND_OSSEMUL) += info_oss.o + endif ++ifneq ($(CONFIG_M68K),y) + snd-$(CONFIG_ISA_DMA_API) += isadma.o ++endif + snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o + snd-$(CONFIG_SND_VMASTER) += vmaster.o + snd-$(CONFIG_SND_JACK) += ctljack.o jack.o +diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c +index 470dabc60aa0e..edff063e088d2 100644 +--- a/sound/core/control_compat.c ++++ b/sound/core/control_compat.c +@@ -264,6 +264,7 @@ static int copy_ctl_value_to_user(void __user *userdata, + struct snd_ctl_elem_value *data, + int type, int count) + { ++ struct snd_ctl_elem_value32 __user *data32 = userdata; + int i, size; + + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || +@@ -280,6 +281,8 @@ static int copy_ctl_value_to_user(void __user *userdata, + if (copy_to_user(valuep, data->value.bytes.data, size)) + return -EFAULT; + } ++ if (copy_to_user(&data32->id, &data->id, sizeof(data32->id))) ++ return -EFAULT; + return 0; + } + +diff --git a/sound/core/jack.c b/sound/core/jack.c +index 32350c6aba849..d1e3055f2b6a5 100644 +--- a/sound/core/jack.c ++++ b/sound/core/jack.c +@@ -62,10 +62,13 @@ static int snd_jack_dev_free(struct snd_device *device) + struct snd_card *card = device->card; + struct snd_jack_kctl *jack_kctl, *tmp_jack_kctl; + ++ down_write(&card->controls_rwsem); + list_for_each_entry_safe(jack_kctl, tmp_jack_kctl, &jack->kctl_list, list) { + list_del_init(&jack_kctl->list); + snd_ctl_remove(card, jack_kctl->kctl); + } ++ up_write(&card->controls_rwsem); ++ + if (jack->private_free) + jack->private_free(jack); + +@@ -509,6 +512,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, + return -ENOMEM; + + jack->id = kstrdup(id, GFP_KERNEL); ++ if (jack->id == NULL) { ++ kfree(jack); ++ return -ENOMEM; ++ } + + /* don't creat input device for phantom jack */ + if (!phantom_jack) { +diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c +index c7c943c661e63..2d842982576bb 100644 +--- a/sound/core/memalloc.c ++++ b/sound/core/memalloc.c +@@ -176,8 +176,11 @@ EXPORT_SYMBOL_GPL(snd_devm_alloc_pages); + int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area) + { +- const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); ++ const struct snd_malloc_ops *ops; + ++ if (!dmab) ++ return -ENOENT; ++ ops = snd_dma_get_ops(dmab); + if (ops && ops->mmap) + return ops->mmap(dmab, area); + else +@@ -491,6 +494,8 @@ static const struct snd_malloc_ops *dma_ops[] = { + + static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab) + { ++ if (WARN_ON_ONCE(!dmab)) ++ return NULL; + if (WARN_ON_ONCE(dmab->dev.type <= SNDRV_DMA_TYPE_UNKNOWN || + dmab->dev.type >= ARRAY_SIZE(dma_ops))) + return NULL; +diff --git a/sound/core/misc.c b/sound/core/misc.c +index 3579dd7a161f7..50e4aaa6270d1 100644 +--- a/sound/core/misc.c ++++ b/sound/core/misc.c +@@ -112,7 +112,7 @@ snd_pci_quirk_lookup_id(u16 vendor, u16 device, + { + const struct snd_pci_quirk *q; + +- for (q = list; q->subvendor; q++) { ++ for (q = list; q->subvendor || q->subdevice; q++) { + if (q->subvendor != vendor) + continue; + if (!q->subdevice || +diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c +index 6a5abdd4271ba..9620115cfdc09 100644 +--- a/sound/core/oss/mixer_oss.c ++++ b/sound/core/oss/mixer_oss.c +@@ -130,11 +130,13 @@ static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer) + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + for (chn = 0; chn < 31; chn++) { + pslot = &mixer->slots[chn]; + if (pslot->put_volume || pslot->put_recsrc) + result |= 1 << chn; + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -146,11 +148,13 @@ static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer) + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + for (chn = 0; chn < 31; chn++) { + pslot = &mixer->slots[chn]; + if (pslot->put_volume && pslot->stereo) + result |= 1 << chn; + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -161,6 +165,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ + result = mixer->mask_recsrc; + } else { +@@ -172,6 +177,7 @@ static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) + result |= 1 << chn; + } + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -182,12 +188,12 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ +- int err; + unsigned int index; +- err = mixer->get_recsrc(fmixer, &index); +- if (err < 0) +- return err; ++ result = mixer->get_recsrc(fmixer, &index); ++ if (result < 0) ++ goto unlock; + result = 1 << index; + } else { + struct snd_mixer_oss_slot *pslot; +@@ -202,7 +208,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) + } + } + } +- return mixer->oss_recsrc = result; ++ mixer->oss_recsrc = result; ++ unlock: ++ mutex_unlock(&mixer->reg_mutex); ++ return result; + } + + static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc) +@@ -215,6 +224,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr + + if (mixer == NULL) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */ + if (recsrc & ~mixer->oss_recsrc) + recsrc &= ~mixer->oss_recsrc; +@@ -240,6 +250,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr + } + } + } ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -251,6 +262,7 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) + + if (mixer == NULL || slot > 30) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + pslot = &mixer->slots[slot]; + left = pslot->volume[0]; + right = pslot->volume[1]; +@@ -258,15 +270,21 @@ static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) + result = pslot->get_volume(fmixer, pslot, &left, &right); + if (!pslot->stereo) + right = left; +- if (snd_BUG_ON(left < 0 || left > 100)) +- return -EIO; +- if (snd_BUG_ON(right < 0 || right > 100)) +- return -EIO; ++ if (snd_BUG_ON(left < 0 || left > 100)) { ++ result = -EIO; ++ goto unlock; ++ } ++ if (snd_BUG_ON(right < 0 || right > 100)) { ++ result = -EIO; ++ goto unlock; ++ } + if (result >= 0) { + pslot->volume[0] = left; + pslot->volume[1] = right; + result = (left & 0xff) | ((right & 0xff) << 8); + } ++ unlock: ++ mutex_unlock(&mixer->reg_mutex); + return result; + } + +@@ -279,6 +297,7 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, + + if (mixer == NULL || slot > 30) + return -EIO; ++ mutex_lock(&mixer->reg_mutex); + pslot = &mixer->slots[slot]; + if (left > 100) + left = 100; +@@ -289,10 +308,13 @@ static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, + if (pslot->put_volume) + result = pslot->put_volume(fmixer, pslot, left, right); + if (result < 0) +- return result; ++ goto unlock; + pslot->volume[0] = left; + pslot->volume[1] = right; +- return (left & 0xff) | ((right & 0xff) << 8); ++ result = (left & 0xff) | ((right & 0xff) << 8); ++ unlock: ++ mutex_unlock(&mixer->reg_mutex); ++ return result; + } + + static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg) +diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c +index 82a818734a5f7..3ee9edf858156 100644 +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, + * + * Return the maximum value for field PAR. + */ +-static unsigned int ++static int + snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, + snd_pcm_hw_param_t var, int *dir) + { +@@ -682,18 +682,24 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *oss_params, + struct snd_pcm_hw_params *slave_params) + { +- size_t s; +- size_t oss_buffer_size, oss_period_size, oss_periods; +- size_t min_period_size, max_period_size; ++ ssize_t s; ++ ssize_t oss_buffer_size; ++ ssize_t oss_period_size, oss_periods; ++ ssize_t min_period_size, max_period_size; + struct snd_pcm_runtime *runtime = substream->runtime; + size_t oss_frame_size; + + oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * + params_channels(oss_params) / 8; + ++ oss_buffer_size = snd_pcm_hw_param_value_max(slave_params, ++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, ++ NULL); ++ if (oss_buffer_size <= 0) ++ return -EINVAL; + oss_buffer_size = snd_pcm_plug_client_size(substream, +- snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; +- if (!oss_buffer_size) ++ oss_buffer_size * oss_frame_size); ++ if (oss_buffer_size <= 0) + return -EINVAL; + oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); + if (atomic_read(&substream->mmap_count)) { +@@ -730,7 +736,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + + min_period_size = snd_pcm_plug_client_size(substream, + snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); +- if (min_period_size) { ++ if (min_period_size > 0) { + min_period_size *= oss_frame_size; + min_period_size = roundup_pow_of_two(min_period_size); + if (oss_period_size < min_period_size) +@@ -739,7 +745,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + + max_period_size = snd_pcm_plug_client_size(substream, + snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); +- if (max_period_size) { ++ if (max_period_size > 0) { + max_period_size *= oss_frame_size; + max_period_size = rounddown_pow_of_two(max_period_size); + if (oss_period_size > max_period_size) +@@ -752,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, + oss_periods = substream->oss.setup.periods; + + s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); +- if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) ++ if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags) + s = runtime->oss.maxfrags; + if (oss_periods > s) + oss_periods = s; +@@ -878,8 +884,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) + err = -EINVAL; + goto failure; + } +- choose_rate(substream, sparams, runtime->oss.rate); +- snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); ++ ++ err = choose_rate(substream, sparams, runtime->oss.rate); ++ if (err < 0) ++ goto failure; ++ err = snd_pcm_hw_param_near(substream, sparams, ++ SNDRV_PCM_HW_PARAM_CHANNELS, ++ runtime->oss.channels, NULL); ++ if (err < 0) ++ goto failure; + + format = snd_pcm_oss_format_from(runtime->oss.format); + +@@ -1956,7 +1969,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign + if (runtime->oss.subdivision || runtime->oss.fragshift) + return -EINVAL; + fragshift = val & 0xffff; +- if (fragshift >= 31) ++ if (fragshift >= 25) /* should be large enough */ + return -EINVAL; + runtime->oss.fragshift = fragshift; + runtime->oss.maxfrags = (val >> 16) & 0xffff; +@@ -2052,7 +2065,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr + int err, cmd; + + #ifdef OSS_DEBUG +- pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger); ++ pr_debug("pcm_oss: trigger = 0x%x\n", trigger); + #endif + + psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; +diff --git a/sound/core/pcm.c b/sound/core/pcm.c +index 6fd3677685d70..ba4a987ed1c62 100644 +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -810,7 +810,11 @@ EXPORT_SYMBOL(snd_pcm_new_internal); + static void free_chmap(struct snd_pcm_str *pstr) + { + if (pstr->chmap_kctl) { +- snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl); ++ struct snd_card *card = pstr->pcm->card; ++ ++ down_write(&card->controls_rwsem); ++ snd_ctl_remove(card, pstr->chmap_kctl); ++ up_write(&card->controls_rwsem); + pstr->chmap_kctl = NULL; + } + } +diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c +index 6f30231bdb884..befa9809ff001 100644 +--- a/sound/core/rawmidi.c ++++ b/sound/core/rawmidi.c +@@ -447,6 +447,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) + err = -ENOMEM; + goto __error; + } ++ rawmidi_file->user_pversion = 0; + init_waitqueue_entry(&wait, current); + add_wait_queue(&rmidi->open_wait, &wait); + while (1) { +diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c +index d6c02dea976c8..bc933104c3eea 100644 +--- a/sound/core/seq/seq_queue.c ++++ b/sound/core/seq/seq_queue.c +@@ -235,12 +235,15 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name) + + /* -------------------------------------------------------- */ + ++#define MAX_CELL_PROCESSES_IN_QUEUE 1000 ++ + void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) + { + unsigned long flags; + struct snd_seq_event_cell *cell; + snd_seq_tick_time_t cur_tick; + snd_seq_real_time_t cur_time; ++ int processed = 0; + + if (q == NULL) + return; +@@ -263,6 +266,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) + if (!cell) + break; + snd_seq_dispatch_event(cell, atomic, hop); ++ if (++processed >= MAX_CELL_PROCESSES_IN_QUEUE) ++ goto out; /* the rest processed at the next batch */ + } + + /* Process time queue... */ +@@ -272,14 +277,19 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) + if (!cell) + break; + snd_seq_dispatch_event(cell, atomic, hop); ++ if (++processed >= MAX_CELL_PROCESSES_IN_QUEUE) ++ goto out; /* the rest processed at the next batch */ + } + ++ out: + /* free lock */ + spin_lock_irqsave(&q->check_lock, flags); + if (q->check_again) { + q->check_again = 0; +- spin_unlock_irqrestore(&q->check_lock, flags); +- goto __again; ++ if (processed < MAX_CELL_PROCESSES_IN_QUEUE) { ++ spin_unlock_irqrestore(&q->check_lock, flags); ++ goto __again; ++ } + } + q->check_blocked = 0; + spin_unlock_irqrestore(&q->check_lock, flags); +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 92b7008fcdb86..b3214baa89193 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -624,13 +624,13 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) + if (!timer) + return -EINVAL; + spin_lock_irqsave(&timer->lock, flags); ++ list_del_init(&timeri->ack_list); ++ list_del_init(&timeri->active_list); + if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | + SNDRV_TIMER_IFLG_START))) { + result = -EBUSY; + goto unlock; + } +- list_del_init(&timeri->ack_list); +- list_del_init(&timeri->active_list); + if (timer->card && timer->card->shutdown) + goto unlock; + if (stop) { +@@ -665,23 +665,22 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) + static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop) + { + unsigned long flags; ++ bool running; + + spin_lock_irqsave(&slave_active_lock, flags); +- if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { +- spin_unlock_irqrestore(&slave_active_lock, flags); +- return -EBUSY; +- } ++ running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING; + timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; + if (timeri->timer) { + spin_lock(&timeri->timer->lock); + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); +- snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : +- SNDRV_TIMER_EVENT_PAUSE); ++ if (running) ++ snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : ++ SNDRV_TIMER_EVENT_PAUSE); + spin_unlock(&timeri->timer->lock); + } + spin_unlock_irqrestore(&slave_active_lock, flags); +- return 0; ++ return running ? 0 : -EBUSY; + } + + /* +diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c +index e1b69c65c3c88..e2b7be67f0e30 100644 +--- a/sound/drivers/opl3/opl3_midi.c ++++ b/sound/drivers/opl3/opl3_midi.c +@@ -397,7 +397,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) + } + if (instr_4op) { + vp2 = &opl3->voices[voice + 3]; +- if (vp->state > 0) { ++ if (vp2->state > 0) { + opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + + voice_offset + 3); + reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT; +diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c +index fff18b5d4e052..f4a702def3979 100644 +--- a/sound/firewire/oxfw/oxfw-stream.c ++++ b/sound/firewire/oxfw/oxfw-stream.c +@@ -9,7 +9,7 @@ + #include <linux/delay.h> + + #define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512 +-#define READY_TIMEOUT_MS 200 ++#define READY_TIMEOUT_MS 600 + + /* + * According to datasheet of Oxford Semiconductor: +@@ -367,6 +367,11 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) + // Just after changing sampling transfer frequency, many cycles are + // skipped for packet transmission. + tx_init_skip_cycles = 400; ++ } else if (oxfw->quirks & SND_OXFW_QUIRK_VOLUNTARY_RECOVERY) { ++ // It takes a bit time for target device to adjust event frequency ++ // according to nominal event frequency in isochronous packets from ++ // ALSA oxfw driver. ++ tx_init_skip_cycles = 4000; + } else { + replay_seq = true; + } +diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c +index daf731364695b..b496f87841aec 100644 +--- a/sound/firewire/oxfw/oxfw.c ++++ b/sound/firewire/oxfw/oxfw.c +@@ -25,6 +25,7 @@ + #define MODEL_SATELLITE 0x00200f + #define MODEL_SCS1M 0x001000 + #define MODEL_DUET_FW 0x01dddd ++#define MODEL_ONYX_1640I 0x001640 + + #define SPECIFIER_1394TA 0x00a02d + #define VERSION_AVC 0x010001 +@@ -192,6 +193,13 @@ static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id + // OXFW971-based models may transfer events by blocking method. + if (!(oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD)) + oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; ++ ++ if (model == MODEL_ONYX_1640I) { ++ //Unless receiving packets without NOINFO packet, the device transfers ++ //mostly half of events in packets than expected. ++ oxfw->quirks |= SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET | ++ SND_OXFW_QUIRK_VOLUNTARY_RECOVERY; ++ } + } + + return 0; +diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h +index c13034f6c2ca5..d728e451a25c6 100644 +--- a/sound/firewire/oxfw/oxfw.h ++++ b/sound/firewire/oxfw/oxfw.h +@@ -47,6 +47,11 @@ enum snd_oxfw_quirk { + // the device to process audio data even if the value is invalid in a point of + // IEC 61883-1/6. + SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET = 0x10, ++ // Loud Technologies Mackie Onyx 1640i seems to configure OXFW971 ASIC so that it decides ++ // event frequency according to events in received isochronous packets. The device looks to ++ // performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO ++ // are ignored, thus driver should transfer packets with timestamp. ++ SND_OXFW_QUIRK_VOLUNTARY_RECOVERY = 0x20, + }; + + /* This is an arbitrary number for convinience. */ +diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c +index 0c005d67fa891..37154ed43bd53 100644 +--- a/sound/hda/ext/hdac_ext_stream.c ++++ b/sound/hda/ext/hdac_ext_stream.c +@@ -106,20 +106,14 @@ void snd_hdac_stream_free_all(struct hdac_bus *bus) + } + EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); + +-/** +- * snd_hdac_ext_stream_decouple - decouple the hdac stream +- * @bus: HD-audio core bus +- * @stream: HD-audio ext core stream object to initialize +- * @decouple: flag to decouple +- */ +-void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, +- struct hdac_ext_stream *stream, bool decouple) ++void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, ++ struct hdac_ext_stream *stream, ++ bool decouple) + { + struct hdac_stream *hstream = &stream->hstream; + u32 val; + int mask = AZX_PPCTL_PROCEN(hstream->index); + +- spin_lock_irq(&bus->reg_lock); + val = readw(bus->ppcap + AZX_REG_PP_PPCTL) & mask; + + if (decouple && !val) +@@ -128,6 +122,20 @@ void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, + snd_hdac_updatel(bus->ppcap, AZX_REG_PP_PPCTL, mask, 0); + + stream->decoupled = decouple; ++} ++EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple_locked); ++ ++/** ++ * snd_hdac_ext_stream_decouple - decouple the hdac stream ++ * @bus: HD-audio core bus ++ * @stream: HD-audio ext core stream object to initialize ++ * @decouple: flag to decouple ++ */ ++void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, ++ struct hdac_ext_stream *stream, bool decouple) ++{ ++ spin_lock_irq(&bus->reg_lock); ++ snd_hdac_ext_stream_decouple_locked(bus, stream, decouple); + spin_unlock_irq(&bus->reg_lock); + } + EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_decouple); +@@ -252,6 +260,7 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus, + return NULL; + } + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(stream, &bus->stream_list, list) { + struct hdac_ext_stream *hstream = container_of(stream, + struct hdac_ext_stream, +@@ -266,17 +275,16 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus, + } + + if (!hstream->link_locked) { +- snd_hdac_ext_stream_decouple(bus, hstream, true); ++ snd_hdac_ext_stream_decouple_locked(bus, hstream, true); + res = hstream; + break; + } + } + if (res) { +- spin_lock_irq(&bus->reg_lock); + res->link_locked = 1; + res->link_substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + return res; + } + +@@ -292,6 +300,7 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus, + return NULL; + } + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(stream, &bus->stream_list, list) { + struct hdac_ext_stream *hstream = container_of(stream, + struct hdac_ext_stream, +@@ -301,18 +310,17 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus, + + if (!stream->opened) { + if (!hstream->decoupled) +- snd_hdac_ext_stream_decouple(bus, hstream, true); ++ snd_hdac_ext_stream_decouple_locked(bus, hstream, true); + res = hstream; + break; + } + } + if (res) { +- spin_lock_irq(&bus->reg_lock); + res->hstream.opened = 1; + res->hstream.running = 0; + res->hstream.substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + + return res; + } +@@ -378,15 +386,17 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *stream, int type) + break; + + case HDAC_EXT_STREAM_TYPE_HOST: ++ spin_lock_irq(&bus->reg_lock); + if (stream->decoupled && !stream->link_locked) +- snd_hdac_ext_stream_decouple(bus, stream, false); ++ snd_hdac_ext_stream_decouple_locked(bus, stream, false); ++ spin_unlock_irq(&bus->reg_lock); + snd_hdac_stream_release(&stream->hstream); + break; + + case HDAC_EXT_STREAM_TYPE_LINK: +- if (stream->decoupled && !stream->hstream.opened) +- snd_hdac_ext_stream_decouple(bus, stream, false); + spin_lock_irq(&bus->reg_lock); ++ if (stream->decoupled && !stream->hstream.opened) ++ snd_hdac_ext_stream_decouple_locked(bus, stream, false); + stream->link_locked = 0; + stream->link_substream = NULL; + spin_unlock_irq(&bus->reg_lock); +diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c +index 1eb8563db2dff..aa7955fdf68a0 100644 +--- a/sound/hda/hdac_stream.c ++++ b/sound/hda/hdac_stream.c +@@ -296,6 +296,7 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, + int key = (substream->pcm->device << 16) | (substream->number << 2) | + (substream->stream + 1); + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(azx_dev, &bus->stream_list, list) { + if (azx_dev->direction != substream->stream) + continue; +@@ -309,13 +310,12 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, + res = azx_dev; + } + if (res) { +- spin_lock_irq(&bus->reg_lock); + res->opened = 1; + res->running = 0; + res->assigned_key = key; + res->substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + return res; + } + EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); +@@ -534,17 +534,11 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev, + cc->mask = CLOCKSOURCE_MASK(32); + + /* +- * Converting from 24 MHz to ns means applying a 125/3 factor. +- * To avoid any saturation issues in intermediate operations, +- * the 125 factor is applied first. The division is applied +- * last after reading the timecounter value. +- * Applying the 1/3 factor as part of the multiplication +- * requires at least 20 bits for a decent precision, however +- * overflows occur after about 4 hours or less, not a option. ++ * Calculate the optimal mult/shift values. The counter wraps ++ * around after ~178.9 seconds. + */ +- +- cc->mult = 125; /* saturation after 195 years */ +- cc->shift = 0; ++ clocks_calc_mult_shift(&cc->mult, &cc->shift, 24000000, ++ NSEC_PER_SEC, 178); + + nsec = 0; /* audio time is elapsed time since trigger */ + timecounter_init(tc, cc, nsec); +diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c +index c9d0ba353463b..4208fa8a4db5b 100644 +--- a/sound/hda/intel-dsp-config.c ++++ b/sound/hda/intel-dsp-config.c +@@ -31,6 +31,7 @@ struct config_entry { + u16 device; + u8 acpi_hid[ACPI_ID_LEN]; + const struct dmi_system_id *dmi_table; ++ u8 codec_hid[ACPI_ID_LEN]; + }; + + /* +@@ -56,7 +57,7 @@ static const struct config_entry config_table[] = { + /* + * Apollolake (Broxton-P) + * the legacy HDAudio driver is used except on Up Squared (SOF) and +- * Chromebooks (SST) ++ * Chromebooks (SST), as well as devices based on the ES8336 codec + */ + #if IS_ENABLED(CONFIG_SND_SOC_SOF_APOLLOLAKE) + { +@@ -73,6 +74,11 @@ static const struct config_entry config_table[] = { + {} + } + }, ++ { ++ .flags = FLAG_SOF, ++ .device = 0x5a98, ++ .codec_hid = "ESSX8336", ++ }, + #endif + #if IS_ENABLED(CONFIG_SND_SOC_INTEL_APL) + { +@@ -137,7 +143,7 @@ static const struct config_entry config_table[] = { + + /* + * Geminilake uses legacy HDAudio driver except for Google +- * Chromebooks ++ * Chromebooks and devices based on the ES8336 codec + */ + /* Geminilake */ + #if IS_ENABLED(CONFIG_SND_SOC_SOF_GEMINILAKE) +@@ -154,6 +160,11 @@ static const struct config_entry config_table[] = { + {} + } + }, ++ { ++ .flags = FLAG_SOF, ++ .device = 0x3198, ++ .codec_hid = "ESSX8336", ++ }, + #endif + + /* +@@ -241,6 +252,11 @@ static const struct config_entry config_table[] = { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x02c8, + }, ++ { ++ .flags = FLAG_SOF, ++ .device = 0x02c8, ++ .codec_hid = "ESSX8336", ++ }, + /* Cometlake-H */ + { + .flags = FLAG_SOF, +@@ -265,6 +281,11 @@ static const struct config_entry config_table[] = { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x06c8, + }, ++ { ++ .flags = FLAG_SOF, ++ .device = 0x06c8, ++ .codec_hid = "ESSX8336", ++ }, + #endif + + /* Icelake */ +@@ -288,6 +309,15 @@ static const struct config_entry config_table[] = { + }, + #endif + ++/* JasperLake */ ++#if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) ++ { ++ .flags = FLAG_SOF, ++ .device = 0x4dc8, ++ .codec_hid = "ESSX8336", ++ }, ++#endif ++ + /* Tigerlake */ + #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) + { +@@ -311,6 +341,11 @@ static const struct config_entry config_table[] = { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x43c8, + }, ++ { ++ .flags = FLAG_SOF, ++ .device = 0xa0c8, ++ .codec_hid = "ESSX8336", ++ }, + #endif + + /* Elkhart Lake */ +@@ -354,6 +389,8 @@ static const struct config_entry *snd_intel_dsp_find_config + continue; + if (table->dmi_table && !dmi_check_system(table->dmi_table)) + continue; ++ if (table->codec_hid[0] && !acpi_dev_present(table->codec_hid, NULL, -1)) ++ continue; + return table; + } + return NULL; +diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c +index c0123bc31c0dd..b7758dbe23714 100644 +--- a/sound/hda/intel-sdw-acpi.c ++++ b/sound/hda/intel-sdw-acpi.c +@@ -132,8 +132,6 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, + return AE_NOT_FOUND; + } + +- info->handle = handle; +- + /* + * On some Intel platforms, multiple children of the HDAS + * device can be found, but only one of them is the SoundWire +@@ -144,6 +142,9 @@ static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, + if (FIELD_GET(GENMASK(31, 28), adr) != SDW_LINK_TYPE) + return AE_OK; /* keep going */ + ++ /* found the correct SoundWire controller */ ++ info->handle = handle; ++ + /* device found, stop namespace walk */ + return AE_CTRL_TERMINATE; + } +@@ -164,8 +165,14 @@ int sdw_intel_acpi_scan(acpi_handle *parent_handle, + acpi_status status; + + info->handle = NULL; ++ /* ++ * In the HDAS ACPI scope, 'SNDW' may be either the child of ++ * 'HDAS' or the grandchild of 'HDAS'. So let's go through ++ * the ACPI from 'HDAS' at max depth of 2 to find the 'SNDW' ++ * device. ++ */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, +- parent_handle, 1, ++ parent_handle, 2, + sdw_intel_acpi_cb, + NULL, info, NULL); + if (ACPI_FAILURE(status) || info->handle == NULL) +diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig +index 6ffa48dd59830..570b88e0b2018 100644 +--- a/sound/isa/Kconfig ++++ b/sound/isa/Kconfig +@@ -22,7 +22,7 @@ config SND_SB16_DSP + menuconfig SND_ISA + bool "ISA sound devices" + depends on ISA || COMPILE_TEST +- depends on ISA_DMA_API ++ depends on ISA_DMA_API && !M68K + default y + help + Support for sound devices connected via the ISA bus. +diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c +index a1c770d826dda..6d664dd8dde0b 100644 +--- a/sound/isa/gus/gus_dma.c ++++ b/sound/isa/gus/gus_dma.c +@@ -126,6 +126,8 @@ static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) + } + block = snd_gf1_dma_next_block(gus); + spin_unlock(&gus->dma_lock); ++ if (!block) ++ return; + snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); + kfree(block); + #if 0 +diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig +index 93bc9bef7641f..41ce125971777 100644 +--- a/sound/pci/Kconfig ++++ b/sound/pci/Kconfig +@@ -279,6 +279,7 @@ config SND_CS46XX_NEW_DSP + config SND_CS5530 + tristate "CS5530 Audio" + depends on ISA_DMA_API && (X86_32 || COMPILE_TEST) ++ depends on !M68K + select SND_SB16_DSP + help + Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips. +diff --git a/sound/pci/ctxfi/ctamixer.c b/sound/pci/ctxfi/ctamixer.c +index da6e6350ceafa..d074727c3e21d 100644 +--- a/sound/pci/ctxfi/ctamixer.c ++++ b/sound/pci/ctxfi/ctamixer.c +@@ -23,16 +23,15 @@ + + #define BLANK_SLOT 4094 + +-static int amixer_master(struct rsc *rsc) ++static void amixer_master(struct rsc *rsc) + { + rsc->conj = 0; +- return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0]; ++ rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0]; + } + +-static int amixer_next_conj(struct rsc *rsc) ++static void amixer_next_conj(struct rsc *rsc) + { + rsc->conj++; +- return container_of(rsc, struct amixer, rsc)->idx[rsc->conj]; + } + + static int amixer_index(const struct rsc *rsc) +@@ -331,16 +330,15 @@ int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr) + + /* SUM resource management */ + +-static int sum_master(struct rsc *rsc) ++static void sum_master(struct rsc *rsc) + { + rsc->conj = 0; +- return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0]; ++ rsc->idx = container_of(rsc, struct sum, rsc)->idx[0]; + } + +-static int sum_next_conj(struct rsc *rsc) ++static void sum_next_conj(struct rsc *rsc) + { + rsc->conj++; +- return container_of(rsc, struct sum, rsc)->idx[rsc->conj]; + } + + static int sum_index(const struct rsc *rsc) +diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c +index f589da0453424..7fc720046ce29 100644 +--- a/sound/pci/ctxfi/ctdaio.c ++++ b/sound/pci/ctxfi/ctdaio.c +@@ -51,12 +51,12 @@ static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { + [SPDIFIO] = {.left = 0x05, .right = 0x85}, + }; + +-static int daio_master(struct rsc *rsc) ++static void daio_master(struct rsc *rsc) + { + /* Actually, this is not the resource index of DAIO. + * For DAO, it is the input mapper index. And, for DAI, + * it is the output time-slot index. */ +- return rsc->conj = rsc->idx; ++ rsc->conj = rsc->idx; + } + + static int daio_index(const struct rsc *rsc) +@@ -64,19 +64,19 @@ static int daio_index(const struct rsc *rsc) + return rsc->conj; + } + +-static int daio_out_next_conj(struct rsc *rsc) ++static void daio_out_next_conj(struct rsc *rsc) + { +- return rsc->conj += 2; ++ rsc->conj += 2; + } + +-static int daio_in_next_conj_20k1(struct rsc *rsc) ++static void daio_in_next_conj_20k1(struct rsc *rsc) + { +- return rsc->conj += 0x200; ++ rsc->conj += 0x200; + } + +-static int daio_in_next_conj_20k2(struct rsc *rsc) ++static void daio_in_next_conj_20k2(struct rsc *rsc) + { +- return rsc->conj += 0x100; ++ rsc->conj += 0x100; + } + + static const struct rsc_ops daio_out_rsc_ops = { +diff --git a/sound/pci/ctxfi/ctresource.c b/sound/pci/ctxfi/ctresource.c +index 81ad269345182..be1d3e61309ce 100644 +--- a/sound/pci/ctxfi/ctresource.c ++++ b/sound/pci/ctxfi/ctresource.c +@@ -109,18 +109,17 @@ static int audio_ring_slot(const struct rsc *rsc) + return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type]; + } + +-static int rsc_next_conj(struct rsc *rsc) ++static void rsc_next_conj(struct rsc *rsc) + { + unsigned int i; + for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); ) + i++; + rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i); +- return rsc->conj; + } + +-static int rsc_master(struct rsc *rsc) ++static void rsc_master(struct rsc *rsc) + { +- return rsc->conj = rsc->idx; ++ rsc->conj = rsc->idx; + } + + static const struct rsc_ops rsc_generic_ops = { +diff --git a/sound/pci/ctxfi/ctresource.h b/sound/pci/ctxfi/ctresource.h +index fdbfd808816d3..58553bda44f43 100644 +--- a/sound/pci/ctxfi/ctresource.h ++++ b/sound/pci/ctxfi/ctresource.h +@@ -39,8 +39,8 @@ struct rsc { + }; + + struct rsc_ops { +- int (*master)(struct rsc *rsc); /* Move to master resource */ +- int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */ ++ void (*master)(struct rsc *rsc); /* Move to master resource */ ++ void (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */ + int (*index)(const struct rsc *rsc); /* Return the index of resource */ + /* Return the output slot number */ + int (*output_slot)(const struct rsc *rsc); +diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c +index bd4697b442334..4a94b4708a77e 100644 +--- a/sound/pci/ctxfi/ctsrc.c ++++ b/sound/pci/ctxfi/ctsrc.c +@@ -590,16 +590,15 @@ int src_mgr_destroy(struct src_mgr *src_mgr) + + /* SRCIMP resource manager operations */ + +-static int srcimp_master(struct rsc *rsc) ++static void srcimp_master(struct rsc *rsc) + { + rsc->conj = 0; +- return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0]; ++ rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0]; + } + +-static int srcimp_next_conj(struct rsc *rsc) ++static void srcimp_next_conj(struct rsc *rsc) + { + rsc->conj++; +- return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj]; + } + + static int srcimp_index(const struct rsc *rsc) +diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c +index 4a854475a0e60..500d0d474d27b 100644 +--- a/sound/pci/hda/hda_auto_parser.c ++++ b/sound/pci/hda/hda_auto_parser.c +@@ -985,7 +985,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec, + int id = HDA_FIXUP_ID_NOT_SET; + const char *name = NULL; + const char *type = NULL; +- int vendor, device; ++ unsigned int vendor, device; + + if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) + return; +diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c +index 1c8bffc3eec6e..7153bd53e1893 100644 +--- a/sound/pci/hda/hda_bind.c ++++ b/sound/pci/hda/hda_bind.c +@@ -156,6 +156,11 @@ static int hda_codec_driver_remove(struct device *dev) + return codec->bus->core.ext_ops->hdev_detach(&codec->core); + } + ++ refcount_dec(&codec->pcm_ref); ++ snd_hda_codec_disconnect_pcms(codec); ++ wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); ++ snd_power_sync_ref(codec->bus->card); ++ + if (codec->patch_ops.free) + codec->patch_ops.free(codec); + snd_hda_codec_cleanup_for_unbind(codec); +diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c +index 0c4a337c9fc0d..f552785d301e0 100644 +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -703,20 +703,10 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) + /* + * PCM device + */ +-static void release_pcm(struct kref *kref) +-{ +- struct hda_pcm *pcm = container_of(kref, struct hda_pcm, kref); +- +- if (pcm->pcm) +- snd_device_free(pcm->codec->card, pcm->pcm); +- clear_bit(pcm->device, pcm->codec->bus->pcm_dev_bits); +- kfree(pcm->name); +- kfree(pcm); +-} +- + void snd_hda_codec_pcm_put(struct hda_pcm *pcm) + { +- kref_put(&pcm->kref, release_pcm); ++ if (refcount_dec_and_test(&pcm->codec->pcm_ref)) ++ wake_up(&pcm->codec->remove_sleep); + } + EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_put); + +@@ -731,7 +721,6 @@ struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, + return NULL; + + pcm->codec = codec; +- kref_init(&pcm->kref); + va_start(args, fmt); + pcm->name = kvasprintf(GFP_KERNEL, fmt, args); + va_end(args); +@@ -741,6 +730,7 @@ struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, + } + + list_add_tail(&pcm->list, &codec->pcm_list_head); ++ refcount_inc(&codec->pcm_ref); + return pcm; + } + EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new); +@@ -748,15 +738,31 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new); + /* + * codec destructor + */ ++void snd_hda_codec_disconnect_pcms(struct hda_codec *codec) ++{ ++ struct hda_pcm *pcm; ++ ++ list_for_each_entry(pcm, &codec->pcm_list_head, list) { ++ if (pcm->disconnected) ++ continue; ++ if (pcm->pcm) ++ snd_device_disconnect(codec->card, pcm->pcm); ++ snd_hda_codec_pcm_put(pcm); ++ pcm->disconnected = 1; ++ } ++} ++ + static void codec_release_pcms(struct hda_codec *codec) + { + struct hda_pcm *pcm, *n; + + list_for_each_entry_safe(pcm, n, &codec->pcm_list_head, list) { +- list_del_init(&pcm->list); ++ list_del(&pcm->list); + if (pcm->pcm) +- snd_device_disconnect(codec->card, pcm->pcm); +- snd_hda_codec_pcm_put(pcm); ++ snd_device_free(pcm->codec->card, pcm->pcm); ++ clear_bit(pcm->device, pcm->codec->bus->pcm_dev_bits); ++ kfree(pcm->name); ++ kfree(pcm); + } + } + +@@ -769,6 +775,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) + codec->registered = 0; + } + ++ snd_hda_codec_disconnect_pcms(codec); + cancel_delayed_work_sync(&codec->jackpoll_work); + if (!codec->in_freeing) + snd_hda_ctls_clear(codec); +@@ -792,6 +799,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) + remove_conn_list(codec); + snd_hdac_regmap_exit(&codec->core); + codec->configured = 0; ++ refcount_set(&codec->pcm_ref, 1); /* reset refcount */ + } + EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind); + +@@ -958,6 +966,8 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, + snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8); + INIT_LIST_HEAD(&codec->conn_list); + INIT_LIST_HEAD(&codec->pcm_list_head); ++ refcount_set(&codec->pcm_ref, 1); ++ init_waitqueue_head(&codec->remove_sleep); + + INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); + codec->depop_delay = -1; +@@ -1727,8 +1737,11 @@ void snd_hda_ctls_clear(struct hda_codec *codec) + { + int i; + struct hda_nid_item *items = codec->mixers.list; ++ ++ down_write(&codec->card->controls_rwsem); + for (i = 0; i < codec->mixers.used; i++) + snd_ctl_remove(codec->card, items[i].kctl); ++ up_write(&codec->card->controls_rwsem); + snd_array_free(&codec->mixers); + snd_array_free(&codec->nids); + } +@@ -2987,6 +3000,10 @@ void snd_hda_codec_shutdown(struct hda_codec *codec) + { + struct hda_pcm *cpcm; + ++ /* Skip the shutdown if codec is not registered */ ++ if (!codec->registered) ++ return; ++ + list_for_each_entry(cpcm, &codec->pcm_list_head, list) + snd_pcm_suspend_all(cpcm->pcm); + +diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c +index 930ae4002a818..75dcb14ff20ad 100644 +--- a/sound/pci/hda/hda_controller.c ++++ b/sound/pci/hda/hda_controller.c +@@ -504,7 +504,6 @@ static int azx_get_time_info(struct snd_pcm_substream *substream, + snd_pcm_gettime(substream->runtime, system_ts); + + nsec = timecounter_read(&azx_dev->core.tc); +- nsec = div_u64(nsec, 3); /* can be optimized */ + if (audio_tstamp_config->report_delay) + nsec = azx_adjust_codec_delay(substream, nsec); + +diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c +index 3bf5e34107038..fc114e5224806 100644 +--- a/sound/pci/hda/hda_generic.c ++++ b/sound/pci/hda/hda_generic.c +@@ -91,6 +91,12 @@ static void snd_hda_gen_spec_free(struct hda_gen_spec *spec) + free_kctls(spec); + snd_array_free(&spec->paths); + snd_array_free(&spec->loopback_list); ++#ifdef CONFIG_SND_HDA_GENERIC_LEDS ++ if (spec->led_cdevs[LED_AUDIO_MUTE]) ++ led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MUTE]); ++ if (spec->led_cdevs[LED_AUDIO_MICMUTE]) ++ led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MICMUTE]); ++#endif + } + + /* +@@ -3922,7 +3928,10 @@ static int create_mute_led_cdev(struct hda_codec *codec, + enum led_brightness), + bool micmute) + { ++ struct hda_gen_spec *spec = codec->spec; + struct led_classdev *cdev; ++ int idx = micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE; ++ int err; + + cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL); + if (!cdev) +@@ -3932,10 +3941,14 @@ static int create_mute_led_cdev(struct hda_codec *codec, + cdev->max_brightness = 1; + cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute"; + cdev->brightness_set_blocking = callback; +- cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE); ++ cdev->brightness = ledtrig_audio_get(idx); + cdev->flags = LED_CORE_SUSPENDRESUME; + +- return devm_led_classdev_register(&codec->core.dev, cdev); ++ err = led_classdev_register(&codec->core.dev, cdev); ++ if (err < 0) ++ return err; ++ spec->led_cdevs[idx] = cdev; ++ return 0; + } + + /** +diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h +index c43bd0f0338ea..362ddcaea15b3 100644 +--- a/sound/pci/hda/hda_generic.h ++++ b/sound/pci/hda/hda_generic.h +@@ -294,6 +294,9 @@ struct hda_gen_spec { + struct hda_jack_callback *cb); + void (*mic_autoswitch_hook)(struct hda_codec *codec, + struct hda_jack_callback *cb); ++ ++ /* leds */ ++ struct led_classdev *led_cdevs[NUM_AUDIO_LEDS]; + }; + + /* values for add_stereo_mix_input flag */ +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 4d22e7adeee8e..9e36f992605ab 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -335,7 +335,10 @@ enum { + ((pci)->device == 0x0c0c) || \ + ((pci)->device == 0x0d0c) || \ + ((pci)->device == 0x160c) || \ +- ((pci)->device == 0x490d)) ++ ((pci)->device == 0x490d) || \ ++ ((pci)->device == 0x4f90) || \ ++ ((pci)->device == 0x4f91) || \ ++ ((pci)->device == 0x4f92)) + + #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) + +@@ -638,13 +641,17 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) + * the update-IRQ timing. The IRQ is issued before actually the + * data is processed. So, we need to process it afterwords in a + * workqueue. ++ * ++ * Returns 1 if OK to proceed, 0 for delay handling, -1 for skipping update + */ + static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) + { + struct snd_pcm_substream *substream = azx_dev->core.substream; ++ struct snd_pcm_runtime *runtime = substream->runtime; + int stream = substream->stream; + u32 wallclk; + unsigned int pos; ++ snd_pcm_uframes_t hwptr, target; + + wallclk = azx_readl(chip, WALLCLK) - azx_dev->core.start_wallclk; + if (wallclk < (azx_dev->core.period_wallclk * 2) / 3) +@@ -681,6 +688,24 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) + /* NG - it's below the first next period boundary */ + return chip->bdl_pos_adj ? 0 : -1; + azx_dev->core.start_wallclk += wallclk; ++ ++ if (azx_dev->core.no_period_wakeup) ++ return 1; /* OK, no need to check period boundary */ ++ ++ if (runtime->hw_ptr_base != runtime->hw_ptr_interrupt) ++ return 1; /* OK, already in hwptr updating process */ ++ ++ /* check whether the period gets really elapsed */ ++ pos = bytes_to_frames(runtime, pos); ++ hwptr = runtime->hw_ptr_base + pos; ++ if (hwptr < runtime->status->hw_ptr) ++ hwptr += runtime->buffer_size; ++ target = runtime->hw_ptr_interrupt + runtime->period_size; ++ if (hwptr < target) { ++ /* too early wakeup, process it later */ ++ return chip->bdl_pos_adj ? 0 : -1; ++ } ++ + return 1; /* OK, it's fine */ + } + +@@ -859,31 +884,6 @@ static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev, + return substream->runtime->delay; + } + +-static unsigned int azx_skl_get_dpib_pos(struct azx *chip, +- struct azx_dev *azx_dev) +-{ +- return _snd_hdac_chip_readl(azx_bus(chip), +- AZX_REG_VS_SDXDPIB_XBASE + +- (AZX_REG_VS_SDXDPIB_XINTERVAL * +- azx_dev->core.index)); +-} +- +-/* get the current DMA position with correction on SKL+ chips */ +-static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev) +-{ +- /* DPIB register gives a more accurate position for playback */ +- if (azx_dev->core.substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- return azx_skl_get_dpib_pos(chip, azx_dev); +- +- /* For capture, we need to read posbuf, but it requires a delay +- * for the possible boundary overlap; the read of DPIB fetches the +- * actual posbuf +- */ +- udelay(20); +- azx_skl_get_dpib_pos(chip, azx_dev); +- return azx_get_pos_posbuf(chip, azx_dev); +-} +- + static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset) + { + azx_stop_chip(chip); +@@ -1573,7 +1573,7 @@ static void assign_position_fix(struct azx *chip, int fix) + [POS_FIX_POSBUF] = azx_get_pos_posbuf, + [POS_FIX_VIACOMBO] = azx_via_get_position, + [POS_FIX_COMBO] = azx_get_pos_lpib, +- [POS_FIX_SKL] = azx_get_pos_skl, ++ [POS_FIX_SKL] = azx_get_pos_posbuf, + [POS_FIX_FIFO] = azx_get_pos_fifo, + }; + +@@ -1611,6 +1611,7 @@ static const struct snd_pci_quirk probe_mask_list[] = { + /* forced codec slots */ + SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103), + SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103), ++ SND_PCI_QUIRK(0x1558, 0x0351, "Schenker Dock 15", 0x105), + /* WinFast VP200 H (Teradici) user reported broken communication */ + SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101), + {} +@@ -1794,8 +1795,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, + + assign_position_fix(chip, check_position_fix(chip, position_fix[dev])); + +- check_probe_mask(chip, dev); +- + if (single_cmd < 0) /* allow fallback to single_cmd at errors */ + chip->fallback_to_single_cmd = 1; + else /* explicitly set to single_cmd or not */ +@@ -1821,6 +1820,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, + chip->bus.core.needs_damn_long_delay = 1; + } + ++ check_probe_mask(chip, dev); ++ + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { + dev_err(card->dev, "Error creating device [card]!\n"); +@@ -2330,7 +2331,8 @@ static int azx_probe_continue(struct azx *chip) + + out_free: + if (err < 0) { +- azx_free(chip); ++ pci_set_drvdata(pci, NULL); ++ snd_card_free(chip->card); + return err; + } + +@@ -2474,6 +2476,13 @@ static const struct pci_device_id azx_ids[] = { + /* DG1 */ + { PCI_DEVICE(0x8086, 0x490d), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, ++ /* DG2 */ ++ { PCI_DEVICE(0x8086, 0x4f90), ++ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, ++ { PCI_DEVICE(0x8086, 0x4f91), ++ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, ++ { PCI_DEVICE(0x8086, 0x4f92), ++ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Alderlake-S */ + { PCI_DEVICE(0x8086, 0x7ad0), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, +diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h +index ea8ab8b433378..8621f576446b8 100644 +--- a/sound/pci/hda/hda_local.h ++++ b/sound/pci/hda/hda_local.h +@@ -137,6 +137,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, + int snd_hda_codec_reset(struct hda_codec *codec); + void snd_hda_codec_register(struct hda_codec *codec); + void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); ++void snd_hda_codec_disconnect_pcms(struct hda_codec *codec); + + #define snd_hda_regmap_sync(codec) snd_hdac_regmap_sync(&(codec)->core) + +@@ -438,6 +439,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid, + #define for_each_hda_codec_node(nid, codec) \ + for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) + ++/* Set the codec power_state flag to indicate to allow unsol event handling; ++ * see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the ++ * state tracking, so use with care. ++ */ ++static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec) ++{ ++ codec->core.dev.power.power_state = PMSG_ON; ++} ++ + /* + * get widget capabilities + */ +diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c +index ea700395bef40..773f4903550a0 100644 +--- a/sound/pci/hda/hda_tegra.c ++++ b/sound/pci/hda/hda_tegra.c +@@ -68,14 +68,20 @@ + */ + #define TEGRA194_NUM_SDO_LINES 4 + ++struct hda_tegra_soc { ++ bool has_hda2codec_2x_reset; ++}; ++ + struct hda_tegra { + struct azx chip; + struct device *dev; +- struct reset_control *reset; ++ struct reset_control_bulk_data resets[3]; + struct clk_bulk_data clocks[3]; ++ unsigned int nresets; + unsigned int nclocks; + void __iomem *regs; + struct work_struct probe_work; ++ const struct hda_tegra_soc *soc; + }; + + #ifdef CONFIG_PM +@@ -170,7 +176,7 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev) + int rc; + + if (!chip->running) { +- rc = reset_control_assert(hda->reset); ++ rc = reset_control_bulk_assert(hda->nresets, hda->resets); + if (rc) + return rc; + } +@@ -187,7 +193,7 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev) + } else { + usleep_range(10, 100); + +- rc = reset_control_deassert(hda->reset); ++ rc = reset_control_bulk_deassert(hda->nresets, hda->resets); + if (rc) + return rc; + } +@@ -427,9 +433,17 @@ static int hda_tegra_create(struct snd_card *card, + return 0; + } + ++static const struct hda_tegra_soc tegra30_data = { ++ .has_hda2codec_2x_reset = true, ++}; ++ ++static const struct hda_tegra_soc tegra194_data = { ++ .has_hda2codec_2x_reset = false, ++}; ++ + static const struct of_device_id hda_tegra_match[] = { +- { .compatible = "nvidia,tegra30-hda" }, +- { .compatible = "nvidia,tegra194-hda" }, ++ { .compatible = "nvidia,tegra30-hda", .data = &tegra30_data }, ++ { .compatible = "nvidia,tegra194-hda", .data = &tegra194_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, hda_tegra_match); +@@ -449,6 +463,8 @@ static int hda_tegra_probe(struct platform_device *pdev) + hda->dev = &pdev->dev; + chip = &hda->chip; + ++ hda->soc = of_device_get_match_data(&pdev->dev); ++ + err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, + THIS_MODULE, 0, &card); + if (err < 0) { +@@ -456,11 +472,20 @@ static int hda_tegra_probe(struct platform_device *pdev) + return err; + } + +- hda->reset = devm_reset_control_array_get_exclusive(&pdev->dev); +- if (IS_ERR(hda->reset)) { +- err = PTR_ERR(hda->reset); ++ hda->resets[hda->nresets++].id = "hda"; ++ hda->resets[hda->nresets++].id = "hda2hdmi"; ++ /* ++ * "hda2codec_2x" reset is not present on Tegra194. Though DT would ++ * be updated to reflect this, but to have backward compatibility ++ * below is necessary. ++ */ ++ if (hda->soc->has_hda2codec_2x_reset) ++ hda->resets[hda->nresets++].id = "hda2codec_2x"; ++ ++ err = devm_reset_control_bulk_get_exclusive(&pdev->dev, hda->nresets, ++ hda->resets); ++ if (err) + goto out_free; +- } + + hda->clocks[hda->nclocks++].id = "hda"; + hda->clocks[hda->nclocks++].id = "hda2hdmi"; +diff --git a/sound/pci/hda/patch_cs8409-tables.c b/sound/pci/hda/patch_cs8409-tables.c +index 0fb0a428428b4..df0b4522babf7 100644 +--- a/sound/pci/hda/patch_cs8409-tables.c ++++ b/sound/pci/hda/patch_cs8409-tables.c +@@ -252,6 +252,7 @@ struct sub_codec cs8409_cs42l42_codec = { + .init_seq_num = ARRAY_SIZE(cs42l42_init_reg_seq), + .hp_jack_in = 0, + .mic_jack_in = 0, ++ .force_status_change = 1, + .paged = 1, + .suspended = 1, + .no_type_dect = 0, +@@ -443,6 +444,7 @@ struct sub_codec dolphin_cs42l42_0 = { + .init_seq_num = ARRAY_SIZE(dolphin_c0_init_reg_seq), + .hp_jack_in = 0, + .mic_jack_in = 0, ++ .force_status_change = 1, + .paged = 1, + .suspended = 1, + .no_type_dect = 0, +@@ -456,6 +458,7 @@ struct sub_codec dolphin_cs42l42_1 = { + .init_seq_num = ARRAY_SIZE(dolphin_c1_init_reg_seq), + .hp_jack_in = 0, + .mic_jack_in = 0, ++ .force_status_change = 1, + .paged = 1, + .suspended = 1, + .no_type_dect = 1, +diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c +index 31ff11ab868e1..aff2b5abb81ea 100644 +--- a/sound/pci/hda/patch_cs8409.c ++++ b/sound/pci/hda/patch_cs8409.c +@@ -628,15 +628,17 @@ static void cs42l42_run_jack_detect(struct sub_codec *cs42l42) + cs8409_i2c_write(cs42l42, 0x1b74, 0x07); + cs8409_i2c_write(cs42l42, 0x131b, 0xFD); + cs8409_i2c_write(cs42l42, 0x1120, 0x80); +- /* Wait ~100us*/ +- usleep_range(100, 200); ++ /* Wait ~20ms*/ ++ usleep_range(20000, 25000); + cs8409_i2c_write(cs42l42, 0x111f, 0x77); + cs8409_i2c_write(cs42l42, 0x1120, 0xc0); + } + + static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status) + { +- int status_changed = 0; ++ int status_changed = cs42l42->force_status_change; ++ ++ cs42l42->force_status_change = 0; + + /* TIP_SENSE INSERT/REMOVE */ + switch (reg_ts_status) { +@@ -750,6 +752,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42) + if (cs42l42->full_scale_vol) + cs8409_i2c_write(cs42l42, 0x2001, 0x01); + ++ /* we have to explicitly allow unsol event handling even during the ++ * resume phase so that the jack event is processed properly ++ */ ++ snd_hda_codec_allow_unsol_events(cs42l42->codec); ++ + cs42l42_enable_jack_detect(cs42l42); + } + +@@ -786,6 +793,7 @@ static void cs42l42_suspend(struct sub_codec *cs42l42) + cs42l42->last_page = 0; + cs42l42->hp_jack_in = 0; + cs42l42->mic_jack_in = 0; ++ cs42l42->force_status_change = 1; + + /* Put CS42L42 into Reset */ + gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0); +diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h +index ade2b838590cf..d0b725c7285b6 100644 +--- a/sound/pci/hda/patch_cs8409.h ++++ b/sound/pci/hda/patch_cs8409.h +@@ -305,6 +305,7 @@ struct sub_codec { + + unsigned int hp_jack_in:1; + unsigned int mic_jack_in:1; ++ unsigned int force_status_change:1; + unsigned int suspended:1; + unsigned int paged:1; + unsigned int last_page; +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 65d2c55399195..ffcde7409d2a5 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -2947,7 +2947,8 @@ static int parse_intel_hdmi(struct hda_codec *codec) + + /* Intel Haswell and onwards; audio component with eld notifier */ + static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, +- const int *port_map, int port_num, int dev_num) ++ const int *port_map, int port_num, int dev_num, ++ bool send_silent_stream) + { + struct hdmi_spec *spec; + int err; +@@ -2980,7 +2981,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, + * Enable silent stream feature, if it is enabled via + * module param or Kconfig option + */ +- if (enable_silent_stream) ++ if (send_silent_stream) + spec->send_silent_stream = true; + + return parse_intel_hdmi(codec); +@@ -2988,12 +2989,18 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, + + static int patch_i915_hsw_hdmi(struct hda_codec *codec) + { +- return intel_hsw_common_init(codec, 0x08, NULL, 0, 3); ++ return intel_hsw_common_init(codec, 0x08, NULL, 0, 3, ++ enable_silent_stream); + } + + static int patch_i915_glk_hdmi(struct hda_codec *codec) + { +- return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3); ++ /* ++ * Silent stream calls audio component .get_power() from ++ * .pin_eld_notify(). On GLK this will deadlock in i915 due ++ * to the audio vs. CDCLK workaround. ++ */ ++ return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3, false); + } + + static int patch_i915_icl_hdmi(struct hda_codec *codec) +@@ -3004,7 +3011,8 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec) + */ + static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb}; + +- return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 3); ++ return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 3, ++ enable_silent_stream); + } + + static int patch_i915_tgl_hdmi(struct hda_codec *codec) +@@ -3016,7 +3024,8 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec) + static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + int ret; + +- ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4); ++ ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, ++ enable_silent_stream); + if (!ret) { + struct hdmi_spec *spec = codec->spec; + +@@ -4380,10 +4389,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), + HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), + HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi), + HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi), +-HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi), + HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi), ++HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI", patch_i915_tgl_hdmi), + HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), + HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), ++HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi), + HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), + HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), + HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 965b096f416f6..83b56c1ba3996 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -97,6 +97,7 @@ struct alc_spec { + unsigned int gpio_mic_led_mask; + struct alc_coef_led mute_led_coef; + struct alc_coef_led mic_led_coef; ++ struct mutex coef_mutex; + + hda_nid_t headset_mic_pin; + hda_nid_t headphone_mic_pin; +@@ -132,8 +133,24 @@ struct alc_spec { + * COEF access helper functions + */ + +-static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, +- unsigned int coef_idx) ++static void coef_mutex_lock(struct hda_codec *codec) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ snd_hda_power_up_pm(codec); ++ mutex_lock(&spec->coef_mutex); ++} ++ ++static void coef_mutex_unlock(struct hda_codec *codec) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ mutex_unlock(&spec->coef_mutex); ++ snd_hda_power_down_pm(codec); ++} ++ ++static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, ++ unsigned int coef_idx) + { + unsigned int val; + +@@ -142,28 +159,56 @@ static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + return val; + } + ++static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid, ++ unsigned int coef_idx) ++{ ++ unsigned int val; ++ ++ coef_mutex_lock(codec); ++ val = __alc_read_coefex_idx(codec, nid, coef_idx); ++ coef_mutex_unlock(codec); ++ return val; ++} ++ + #define alc_read_coef_idx(codec, coef_idx) \ + alc_read_coefex_idx(codec, 0x20, coef_idx) + +-static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, +- unsigned int coef_idx, unsigned int coef_val) ++static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, ++ unsigned int coef_idx, unsigned int coef_val) + { + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val); + } + ++static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid, ++ unsigned int coef_idx, unsigned int coef_val) ++{ ++ coef_mutex_lock(codec); ++ __alc_write_coefex_idx(codec, nid, coef_idx, coef_val); ++ coef_mutex_unlock(codec); ++} ++ + #define alc_write_coef_idx(codec, coef_idx, coef_val) \ + alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val) + ++static void __alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, ++ unsigned int coef_idx, unsigned int mask, ++ unsigned int bits_set) ++{ ++ unsigned int val = __alc_read_coefex_idx(codec, nid, coef_idx); ++ ++ if (val != -1) ++ __alc_write_coefex_idx(codec, nid, coef_idx, ++ (val & ~mask) | bits_set); ++} ++ + static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid, + unsigned int coef_idx, unsigned int mask, + unsigned int bits_set) + { +- unsigned int val = alc_read_coefex_idx(codec, nid, coef_idx); +- +- if (val != -1) +- alc_write_coefex_idx(codec, nid, coef_idx, +- (val & ~mask) | bits_set); ++ coef_mutex_lock(codec); ++ __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set); ++ coef_mutex_unlock(codec); + } + + #define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \ +@@ -196,13 +241,15 @@ struct coef_fw { + static void alc_process_coef_fw(struct hda_codec *codec, + const struct coef_fw *fw) + { ++ coef_mutex_lock(codec); + for (; fw->nid; fw++) { + if (fw->mask == (unsigned short)-1) +- alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); ++ __alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val); + else +- alc_update_coefex_idx(codec, fw->nid, fw->idx, +- fw->mask, fw->val); ++ __alc_update_coefex_idx(codec, fw->nid, fw->idx, ++ fw->mask, fw->val); + } ++ coef_mutex_unlock(codec); + } + + /* +@@ -1148,6 +1195,7 @@ static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid) + codec->spdif_status_reset = 1; + codec->forced_resume = 1; + codec->patch_ops = alc_patch_ops; ++ mutex_init(&spec->coef_mutex); + + err = alc_codec_rename_from_preset(codec); + if (err < 0) { +@@ -1924,6 +1972,7 @@ enum { + ALC887_FIXUP_ASUS_BASS, + ALC887_FIXUP_BASS_CHMAP, + ALC1220_FIXUP_GB_DUAL_CODECS, ++ ALC1220_FIXUP_GB_X570, + ALC1220_FIXUP_CLEVO_P950, + ALC1220_FIXUP_CLEVO_PB51ED, + ALC1220_FIXUP_CLEVO_PB51ED_PINS, +@@ -2113,6 +2162,30 @@ static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec, + } + } + ++static void alc1220_fixup_gb_x570(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ static const hda_nid_t conn1[] = { 0x0c }; ++ static const struct coef_fw gb_x570_coefs[] = { ++ WRITE_COEF(0x07, 0x03c0), ++ WRITE_COEF(0x1a, 0x01c1), ++ WRITE_COEF(0x1b, 0x0202), ++ WRITE_COEF(0x43, 0x3005), ++ {} ++ }; ++ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1); ++ snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1); ++ break; ++ case HDA_FIXUP_ACT_INIT: ++ alc_process_coef_fw(codec, gb_x570_coefs); ++ break; ++ } ++} ++ + static void alc1220_fixup_clevo_p950(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +@@ -2415,6 +2488,10 @@ static const struct hda_fixup alc882_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc1220_fixup_gb_dual_codecs, + }, ++ [ALC1220_FIXUP_GB_X570] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc1220_fixup_gb_x570, ++ }, + [ALC1220_FIXUP_CLEVO_P950] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc1220_fixup_clevo_p950, +@@ -2517,8 +2594,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), + SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), +- SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), +- SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950), ++ SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_GB_X570), ++ SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_GB_X570), ++ SND_PCI_QUIRK(0x1458, 0xa0d5, "Gigabyte X570S Aorus Master", ALC1220_FIXUP_GB_X570), + SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950), +@@ -2539,6 +2617,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS), ++ SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED), +@@ -2592,6 +2671,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = { + {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, + {.id = ALC887_FIXUP_ASUS_BASS, .name = "asus-bass"}, + {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"}, ++ {.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"}, + {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"}, + {} + }; +@@ -4355,6 +4435,16 @@ static void alc287_fixup_hp_gpio_led(struct hda_codec *codec, + alc_fixup_hp_gpio_led(codec, action, 0x10, 0); + } + ++static void alc245_fixup_hp_gpio_led(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) ++ spec->micmute_led_polarity = 1; ++ alc_fixup_hp_gpio_led(codec, action, 0, 0x04); ++} ++ + /* turn on/off mic-mute LED per capture hook via VREF change */ + static int vref_micmute_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +@@ -6492,22 +6582,64 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, + /* for alc285_fixup_ideapad_s740_coef() */ + #include "ideapad_s740_helper.c" + +-static void alc256_fixup_tongfang_reset_persistent_settings(struct hda_codec *codec, +- const struct hda_fixup *fix, +- int action) ++static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = { ++ WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000), ++ WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000), ++ WRITE_COEF(0x37, 0xfe05), WRITE_COEF(0x45, 0x5089), ++ {} ++}; ++ ++static void alc256_fixup_set_coef_defaults(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) + { + /* +- * A certain other OS sets these coeffs to different values. On at least one TongFang +- * barebone these settings might survive even a cold reboot. So to restore a clean slate the +- * values are explicitly reset to default here. Without this, the external microphone is +- * always in a plugged-in state, while the internal microphone is always in an unplugged +- * state, breaking the ability to use the internal microphone. +- */ +- alc_write_coef_idx(codec, 0x24, 0x0000); +- alc_write_coef_idx(codec, 0x26, 0x0000); +- alc_write_coef_idx(codec, 0x29, 0x3000); +- alc_write_coef_idx(codec, 0x37, 0xfe05); +- alc_write_coef_idx(codec, 0x45, 0x5089); ++ * A certain other OS sets these coeffs to different values. On at least ++ * one TongFang barebone these settings might survive even a cold ++ * reboot. So to restore a clean slate the values are explicitly reset ++ * to default here. Without this, the external microphone is always in a ++ * plugged-in state, while the internal microphone is always in an ++ * unplugged state, breaking the ability to use the internal microphone. ++ */ ++ alc_process_coef_fw(codec, alc256_fixup_set_coef_defaults_coefs); ++} ++ ++static const struct coef_fw alc233_fixup_no_audio_jack_coefs[] = { ++ WRITE_COEF(0x1a, 0x9003), WRITE_COEF(0x1b, 0x0e2b), WRITE_COEF(0x37, 0xfe06), ++ WRITE_COEF(0x38, 0x4981), WRITE_COEF(0x45, 0xd489), WRITE_COEF(0x46, 0x0074), ++ WRITE_COEF(0x49, 0x0149), ++ {} ++}; ++ ++static void alc233_fixup_no_audio_jack(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ /* ++ * The audio jack input and output is not detected on the ASRock NUC Box ++ * 1100 series when cold booting without this fix. Warm rebooting from a ++ * certain other OS makes the audio functional, as COEF settings are ++ * preserved in this case. This fix sets these altered COEF values as ++ * the default. ++ */ ++ alc_process_coef_fw(codec, alc233_fixup_no_audio_jack_coefs); ++} ++ ++static void alc256_fixup_mic_no_presence_and_resume(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ /* ++ * The Clevo NJ51CU comes either with the ALC293 or the ALC256 codec, ++ * but uses the 0x8686 subproduct id in both cases. The ALC256 codec ++ * needs an additional quirk for sound working after suspend and resume. ++ */ ++ if (codec->core.vendor_id == 0x10ec0256) { ++ alc_update_coef_idx(codec, 0x10, 1<<9, 0); ++ snd_hda_codec_set_pincfg(codec, 0x19, 0x04a11120); ++ } else { ++ snd_hda_codec_set_pincfg(codec, 0x1a, 0x04a1113c); ++ } + } + + enum { +@@ -6709,6 +6841,7 @@ enum { + ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK, + ALC287_FIXUP_HP_GPIO_LED, + ALC256_FIXUP_HP_HEADSET_MIC, ++ ALC245_FIXUP_HP_GPIO_LED, + ALC236_FIXUP_DELL_AIO_HEADSET_MIC, + ALC282_FIXUP_ACER_DISABLE_LINEOUT, + ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST, +@@ -6726,7 +6859,12 @@ enum { + ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, + ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, + ALC287_FIXUP_13S_GEN2_SPEAKERS, +- ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS, ++ ALC256_FIXUP_SET_COEF_DEFAULTS, ++ ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, ++ ALC233_FIXUP_NO_AUDIO_JACK, ++ ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME, ++ ALC285_FIXUP_LEGION_Y9000X_SPEAKERS, ++ ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -7333,6 +7471,8 @@ static const struct hda_fixup alc269_fixups[] = { + [ALC245_FIXUP_HP_X360_AMP] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc245_fixup_hp_x360_amp, ++ .chained = true, ++ .chain_id = ALC245_FIXUP_HP_GPIO_LED + }, + [ALC288_FIXUP_DELL_HEADSET_MODE] = { + .type = HDA_FIXUP_FUNC, +@@ -8321,6 +8461,18 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF, + }, ++ [ALC285_FIXUP_LEGION_Y9000X_SPEAKERS] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc285_fixup_ideapad_s740_coef, ++ .chained = true, ++ .chain_id = ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE, ++ }, ++ [ALC285_FIXUP_LEGION_Y9000X_AUTOMUTE] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc287_fixup_legion_15imhg05_speakers, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_THINKPAD_ACPI, ++ }, + [ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS] = { + .type = HDA_FIXUP_VERBS, + //.v.verbs = legion_15imhg05_coefs, +@@ -8428,9 +8580,32 @@ static const struct hda_fixup alc269_fixups[] = { + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE, + }, +- [ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS] = { ++ [ALC256_FIXUP_SET_COEF_DEFAULTS] = { + .type = HDA_FIXUP_FUNC, +- .v.func = alc256_fixup_tongfang_reset_persistent_settings, ++ .v.func = alc256_fixup_set_coef_defaults, ++ }, ++ [ALC245_FIXUP_HP_GPIO_LED] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc245_fixup_hp_gpio_led, ++ }, ++ [ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x19, 0x03a11120 }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, ++ }, ++ [ALC233_FIXUP_NO_AUDIO_JACK] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc233_fixup_no_audio_jack, ++ }, ++ [ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc256_fixup_mic_no_presence_and_resume, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + }, + }; + +@@ -8468,6 +8643,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1025, 0x141f, "Acer Spin SP513-54N", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC), +@@ -8601,14 +8777,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN), + SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360), ++ SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), + SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x8728, "HP EliteBook 840 G7", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), ++ SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), +@@ -8617,6 +8796,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x8783, "HP ZBook Fury 15 G7 Mobile Workstation", + ALC285_FIXUP_HP_GPIO_AMP_INIT), ++ SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), +@@ -8643,6 +8823,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x89c3, "HP", ALC285_FIXUP_HP_GPIO_LED), ++ SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), + SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), +@@ -8668,6 +8850,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE), ++ SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE), + SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), + SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE), +@@ -8683,6 +8866,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), + SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), ++ SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), + SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), +@@ -8731,11 +8915,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1558, 0x5015, "Clevo NH5[58]H[HJK]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1558, 0x5017, "Clevo NH7[79]H[HJK]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1558, 0x50e1, "Clevo NH5[58]HPQ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1558, 0x50e2, "Clevo NH7[79]HPQ", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), +@@ -8762,7 +8950,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[57][0-9]RZ[Q]", ALC269_FIXUP_DMIC), + SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), +- SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC256_FIXUP_MIC_NO_PRESENCE_AND_RESUME), + SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), +@@ -8828,13 +9016,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340), ++ SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), ++ SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS), ++ SND_PCI_QUIRK(0x17aa, 0x3824, "Legion Y9000X 2020", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), ++ SND_PCI_QUIRK(0x17aa, 0x3834, "Lenovo IdeaPad Slim 9i 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), ++ SND_PCI_QUIRK(0x17aa, 0x383d, "Legion Y9000X 2019", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP), +- SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS), ++ SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), +- SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), + SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), + SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), +@@ -8858,6 +9050,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), + SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), + SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), ++ SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK), + SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), + SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20), + SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI), +@@ -8865,7 +9058,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ + SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), + SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), +- SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS), ++ SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), + SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), + SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), +@@ -9055,6 +9248,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { + {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"}, + {.id = ALC623_FIXUP_LENOVO_THINKSTATION_P340, .name = "alc623-lenovo-thinkstation-p340"}, + {.id = ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, .name = "alc255-acer-headphone-and-mic"}, ++ {.id = ALC285_FIXUP_HP_GPIO_AMP_INIT, .name = "alc285-hp-amp-init"}, + {} + }; + #define ALC225_STANDARD_PINS \ +@@ -10167,6 +10361,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, + } + } + ++static void alc897_hp_automute_hook(struct hda_codec *codec, ++ struct hda_jack_callback *jack) ++{ ++ struct alc_spec *spec = codec->spec; ++ int vref; ++ ++ snd_hda_gen_hp_automute(codec, jack); ++ vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP; ++ snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, ++ vref); ++} ++ ++static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) { ++ spec->gen.hp_automute_hook = alc897_hp_automute_hook; ++ } ++} ++ + static const struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), +@@ -10247,6 +10462,8 @@ enum { + ALC668_FIXUP_ASUS_NO_HEADSET_MIC, + ALC668_FIXUP_HEADSET_MIC, + ALC668_FIXUP_MIC_DET_COEF, ++ ALC897_FIXUP_LENOVO_HEADSET_MIC, ++ ALC897_FIXUP_HEADSET_MIC_PIN, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -10653,6 +10870,19 @@ static const struct hda_fixup alc662_fixups[] = { + {} + }, + }, ++ [ALC897_FIXUP_LENOVO_HEADSET_MIC] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc897_fixup_lenovo_headset_mic, ++ }, ++ [ALC897_FIXUP_HEADSET_MIC_PIN] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x03a11050 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -10697,6 +10927,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), + SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), ++ SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), +diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c +index 75aa2ea733a59..96c12dfb24cf9 100644 +--- a/sound/pci/rme9652/hdsp.c ++++ b/sound/pci/rme9652/hdsp.c +@@ -468,8 +468,11 @@ struct hdsp { + unsigned char ss_out_channels; + u32 io_loopback; /* output loopback channel states*/ + +- struct snd_dma_buffer *capture_dma_buf; +- struct snd_dma_buffer *playback_dma_buf; ++ /* DMA buffers; those are copied instances from the original snd_dma_buf ++ * objects (which are managed via devres) for the address alignments ++ */ ++ struct snd_dma_buffer capture_dma_buf; ++ struct snd_dma_buffer playback_dma_buf; + unsigned char *capture_buffer; /* suitably aligned address */ + unsigned char *playback_buffer; /* suitably aligned address */ + +@@ -3764,30 +3767,32 @@ static void snd_hdsp_proc_init(struct hdsp *hdsp) + + static int snd_hdsp_initialize_memory(struct hdsp *hdsp) + { +- unsigned long pb_bus, cb_bus; ++ struct snd_dma_buffer *capture_dma, *playback_dma; + +- hdsp->capture_dma_buf = +- snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); +- hdsp->playback_dma_buf = +- snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); +- if (!hdsp->capture_dma_buf || !hdsp->playback_dma_buf) { ++ capture_dma = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); ++ playback_dma = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES); ++ if (!capture_dma || !playback_dma) { + dev_err(hdsp->card->dev, + "%s: no buffers available\n", hdsp->card_name); + return -ENOMEM; + } + +- /* Align to bus-space 64K boundary */ ++ /* copy to the own data for alignment */ ++ hdsp->capture_dma_buf = *capture_dma; ++ hdsp->playback_dma_buf = *playback_dma; + +- cb_bus = ALIGN(hdsp->capture_dma_buf->addr, 0x10000ul); +- pb_bus = ALIGN(hdsp->playback_dma_buf->addr, 0x10000ul); ++ /* Align to bus-space 64K boundary */ ++ hdsp->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul); ++ hdsp->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul); + + /* Tell the card where it is */ ++ hdsp_write(hdsp, HDSP_inputBufferAddress, hdsp->capture_dma_buf.addr); ++ hdsp_write(hdsp, HDSP_outputBufferAddress, hdsp->playback_dma_buf.addr); + +- hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus); +- hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus); +- +- hdsp->capture_buffer = hdsp->capture_dma_buf->area + (cb_bus - hdsp->capture_dma_buf->addr); +- hdsp->playback_buffer = hdsp->playback_dma_buf->area + (pb_bus - hdsp->playback_dma_buf->addr); ++ hdsp->capture_dma_buf.area += hdsp->capture_dma_buf.addr - capture_dma->addr; ++ hdsp->playback_dma_buf.area += hdsp->playback_dma_buf.addr - playback_dma->addr; ++ hdsp->capture_buffer = hdsp->capture_dma_buf.area; ++ hdsp->playback_buffer = hdsp->playback_dma_buf.area; + + return 0; + } +@@ -4507,7 +4512,7 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) + snd_pcm_set_sync(substream); + + runtime->hw = snd_hdsp_playback_subinfo; +- snd_pcm_set_runtime_buffer(substream, hdsp->playback_dma_buf); ++ snd_pcm_set_runtime_buffer(substream, &hdsp->playback_dma_buf); + + hdsp->playback_pid = current->pid; + hdsp->playback_substream = substream; +@@ -4583,7 +4588,7 @@ static int snd_hdsp_capture_open(struct snd_pcm_substream *substream) + snd_pcm_set_sync(substream); + + runtime->hw = snd_hdsp_capture_subinfo; +- snd_pcm_set_runtime_buffer(substream, hdsp->capture_dma_buf); ++ snd_pcm_set_runtime_buffer(substream, &hdsp->capture_dma_buf); + + hdsp->capture_pid = current->pid; + hdsp->capture_substream = substream; +diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c +index e76f737ac9e8e..7755e19aa7761 100644 +--- a/sound/pci/rme9652/rme9652.c ++++ b/sound/pci/rme9652/rme9652.c +@@ -208,8 +208,11 @@ struct snd_rme9652 { + unsigned char ds_channels; + unsigned char ss_channels; /* different for hammerfall/hammerfall-light */ + +- struct snd_dma_buffer *playback_dma_buf; +- struct snd_dma_buffer *capture_dma_buf; ++ /* DMA buffers; those are copied instances from the original snd_dma_buf ++ * objects (which are managed via devres) for the address alignments ++ */ ++ struct snd_dma_buffer playback_dma_buf; ++ struct snd_dma_buffer capture_dma_buf; + + unsigned char *capture_buffer; /* suitably aligned address */ + unsigned char *playback_buffer; /* suitably aligned address */ +@@ -1719,30 +1722,32 @@ static void snd_rme9652_card_free(struct snd_card *card) + + static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652) + { +- unsigned long pb_bus, cb_bus; ++ struct snd_dma_buffer *capture_dma, *playback_dma; + +- rme9652->capture_dma_buf = +- snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); +- rme9652->playback_dma_buf = +- snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); +- if (!rme9652->capture_dma_buf || !rme9652->playback_dma_buf) { ++ capture_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); ++ playback_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); ++ if (!capture_dma || !playback_dma) { + dev_err(rme9652->card->dev, + "%s: no buffers available\n", rme9652->card_name); + return -ENOMEM; + } + +- /* Align to bus-space 64K boundary */ ++ /* copy to the own data for alignment */ ++ rme9652->capture_dma_buf = *capture_dma; ++ rme9652->playback_dma_buf = *playback_dma; + +- cb_bus = ALIGN(rme9652->capture_dma_buf->addr, 0x10000ul); +- pb_bus = ALIGN(rme9652->playback_dma_buf->addr, 0x10000ul); ++ /* Align to bus-space 64K boundary */ ++ rme9652->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul); ++ rme9652->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul); + + /* Tell the card where it is */ ++ rme9652_write(rme9652, RME9652_rec_buffer, rme9652->capture_dma_buf.addr); ++ rme9652_write(rme9652, RME9652_play_buffer, rme9652->playback_dma_buf.addr); + +- rme9652_write(rme9652, RME9652_rec_buffer, cb_bus); +- rme9652_write(rme9652, RME9652_play_buffer, pb_bus); +- +- rme9652->capture_buffer = rme9652->capture_dma_buf->area + (cb_bus - rme9652->capture_dma_buf->addr); +- rme9652->playback_buffer = rme9652->playback_dma_buf->area + (pb_bus - rme9652->playback_dma_buf->addr); ++ rme9652->capture_dma_buf.area += rme9652->capture_dma_buf.addr - capture_dma->addr; ++ rme9652->playback_dma_buf.area += rme9652->playback_dma_buf.addr - playback_dma->addr; ++ rme9652->capture_buffer = rme9652->capture_dma_buf.area; ++ rme9652->playback_buffer = rme9652->playback_dma_buf.area; + + return 0; + } +@@ -2259,7 +2264,7 @@ static int snd_rme9652_playback_open(struct snd_pcm_substream *substream) + snd_pcm_set_sync(substream); + + runtime->hw = snd_rme9652_playback_subinfo; +- snd_pcm_set_runtime_buffer(substream, rme9652->playback_dma_buf); ++ snd_pcm_set_runtime_buffer(substream, &rme9652->playback_dma_buf); + + if (rme9652->capture_substream == NULL) { + rme9652_stop(rme9652); +@@ -2318,7 +2323,7 @@ static int snd_rme9652_capture_open(struct snd_pcm_substream *substream) + snd_pcm_set_sync(substream); + + runtime->hw = snd_rme9652_capture_subinfo; +- snd_pcm_set_runtime_buffer(substream, rme9652->capture_dma_buf); ++ snd_pcm_set_runtime_buffer(substream, &rme9652->capture_dma_buf); + + if (rme9652->playback_substream == NULL) { + rme9652_stop(rme9652); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 216cea04ad704..f12c9b9426788 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -235,8 +235,7 @@ config SND_SOC_ALL_CODECS + imply SND_SOC_UDA1380 + imply SND_SOC_WCD9335 + imply SND_SOC_WCD934X +- imply SND_SOC_WCD937X +- imply SND_SOC_WCD938X ++ imply SND_SOC_WCD938X_SDW + imply SND_SOC_LPASS_RX_MACRO + imply SND_SOC_LPASS_TX_MACRO + imply SND_SOC_WL1273 +diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c +index 05bbacd0d174d..f1c13f42e1c14 100644 +--- a/sound/soc/codecs/cpcap.c ++++ b/sound/soc/codecs/cpcap.c +@@ -1667,6 +1667,8 @@ static int cpcap_codec_probe(struct platform_device *pdev) + { + struct device_node *codec_node = + of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec"); ++ if (!codec_node) ++ return -ENODEV; + + pdev->dev.of_node = codec_node; + +diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c +index cffd6111afaca..b49cb92d7b9e8 100644 +--- a/sound/soc/codecs/cs4265.c ++++ b/sound/soc/codecs/cs4265.c +@@ -150,7 +150,6 @@ static const struct snd_kcontrol_new cs4265_snd_controls[] = { + SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1, + 6, 1, 0), + SOC_ENUM("C Data Access", cam_mode_enum), +- SOC_SINGLE("SPDIF Switch", CS4265_SPDIF_CTL2, 5, 1, 1), + SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2, + 3, 1, 0), + SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum), +@@ -186,7 +185,7 @@ static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = { + + SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0, + &loopback_ctl), +- SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0, ++ SND_SOC_DAPM_SWITCH("SPDIF", CS4265_SPDIF_CTL2, 5, 1, + &spdif_switch), + SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1, + &dac_switch), +diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c +index 9a463ab54bddc..762d9de73dbc2 100644 +--- a/sound/soc/codecs/cs42l42.c ++++ b/sound/soc/codecs/cs42l42.c +@@ -93,7 +93,7 @@ static const struct reg_default cs42l42_reg_defaults[] = { + { CS42L42_ASP_RX_INT_MASK, 0x1F }, + { CS42L42_ASP_TX_INT_MASK, 0x0F }, + { CS42L42_CODEC_INT_MASK, 0x03 }, +- { CS42L42_SRCPL_INT_MASK, 0xFF }, ++ { CS42L42_SRCPL_INT_MASK, 0x7F }, + { CS42L42_VPMON_INT_MASK, 0x01 }, + { CS42L42_PLL_LOCK_INT_MASK, 0x01 }, + { CS42L42_TSRS_PLUG_INT_MASK, 0x0F }, +@@ -130,7 +130,7 @@ static const struct reg_default cs42l42_reg_defaults[] = { + { CS42L42_MIXER_CHA_VOL, 0x3F }, + { CS42L42_MIXER_ADC_VOL, 0x3F }, + { CS42L42_MIXER_CHB_VOL, 0x3F }, +- { CS42L42_EQ_COEF_IN0, 0x22 }, ++ { CS42L42_EQ_COEF_IN0, 0x00 }, + { CS42L42_EQ_COEF_IN1, 0x00 }, + { CS42L42_EQ_COEF_IN2, 0x00 }, + { CS42L42_EQ_COEF_IN3, 0x00 }, +@@ -853,11 +853,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, + + switch(substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: +- if (channels == 2) { +- val |= CS42L42_ASP_TX_CH2_AP_MASK; +- val |= width << CS42L42_ASP_TX_CH2_RES_SHIFT; +- } +- val |= width << CS42L42_ASP_TX_CH1_RES_SHIFT; ++ /* channel 2 on high LRCLK */ ++ val = CS42L42_ASP_TX_CH2_AP_MASK | ++ (width << CS42L42_ASP_TX_CH2_RES_SHIFT) | ++ (width << CS42L42_ASP_TX_CH1_RES_SHIFT); + + snd_soc_component_update_bits(component, CS42L42_ASP_TX_CH_AP_RES, + CS42L42_ASP_TX_CH1_AP_MASK | CS42L42_ASP_TX_CH2_AP_MASK | +@@ -1685,12 +1684,15 @@ static void cs42l42_setup_hs_type_detect(struct cs42l42_private *cs42l42) + (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)); + + /* Enable the tip sense circuit */ ++ regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL, ++ CS42L42_TS_INV_MASK, CS42L42_TS_INV_MASK); ++ + regmap_update_bits(cs42l42->regmap, CS42L42_TIPSENSE_CTL, + CS42L42_TIP_SENSE_CTRL_MASK | + CS42L42_TIP_SENSE_INV_MASK | + CS42L42_TIP_SENSE_DEBOUNCE_MASK, + (3 << CS42L42_TIP_SENSE_CTRL_SHIFT) | +- (0 << CS42L42_TIP_SENSE_INV_SHIFT) | ++ (!cs42l42->ts_inv << CS42L42_TIP_SENSE_INV_SHIFT) | + (2 << CS42L42_TIP_SENSE_DEBOUNCE_SHIFT)); + + /* Save the initial status of the tip sense */ +@@ -1734,10 +1736,6 @@ static int cs42l42_handle_device_data(struct device *dev, + cs42l42->ts_inv = CS42L42_TS_INV_DIS; + } + +- regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL, +- CS42L42_TS_INV_MASK, +- (cs42l42->ts_inv << CS42L42_TS_INV_SHIFT)); +- + ret = device_property_read_u32(dev, "cirrus,ts-dbnc-rise", &val); + if (!ret) { + switch (val) { +@@ -1948,8 +1946,9 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, + NULL, cs42l42_irq_thread, + IRQF_ONESHOT | IRQF_TRIGGER_LOW, + "cs42l42", cs42l42); +- +- if (ret != 0) ++ if (ret == -EPROBE_DEFER) ++ goto err_disable; ++ else if (ret != 0) + dev_err(&i2c_client->dev, + "Failed to request IRQ: %d\n", ret); + +diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c +index 067757d1d70a3..5fb02635c1406 100644 +--- a/sound/soc/codecs/es8316.c ++++ b/sound/soc/codecs/es8316.c +@@ -811,12 +811,9 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client, + mutex_init(&es8316->lock); + + ret = devm_request_threaded_irq(dev, es8316->irq, NULL, es8316_irq, +- IRQF_TRIGGER_HIGH | IRQF_ONESHOT, ++ IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + "es8316", es8316); +- if (ret == 0) { +- /* Gets re-enabled by es8316_set_jack() */ +- disable_irq(es8316->irq); +- } else { ++ if (ret) { + dev_warn(dev, "Failed to get IRQ %d: %d\n", es8316->irq, ret); + es8316->irq = -ENXIO; + } +diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c +index b61f980cabdc0..b07607a9ecea4 100644 +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -277,7 +277,7 @@ struct hdmi_codec_priv { + bool busy; + struct snd_soc_jack *jack; + unsigned int jack_status; +- u8 iec_status[5]; ++ u8 iec_status[AES_IEC958_STATUS_SIZE]; + }; + + static const struct snd_soc_dapm_widget hdmi_widgets[] = { +diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c +index 196b06898eeb2..1c0409350e869 100644 +--- a/sound/soc/codecs/lpass-rx-macro.c ++++ b/sound/soc/codecs/lpass-rx-macro.c +@@ -2188,7 +2188,7 @@ static int rx_macro_config_classh(struct snd_soc_component *component, + snd_soc_component_update_bits(component, + CDC_RX_CLSH_DECAY_CTRL, + CDC_RX_CLSH_DECAY_RATE_MASK, 0x0); +- snd_soc_component_update_bits(component, ++ snd_soc_component_write_field(component, + CDC_RX_RX1_RX_PATH_CFG0, + CDC_RX_RXn_CLSH_EN_MASK, 0x1); + break; +@@ -2688,8 +2688,8 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, + int reg, b2_reg; + + /* Address does not automatically update if reading */ +- reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx; +- b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx; ++ reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx; ++ b2_reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx; + + snd_soc_component_write(component, reg, + ((band_idx * BAND_MAX + coeff_idx) * +@@ -2718,7 +2718,7 @@ static uint32_t get_iir_band_coeff(struct snd_soc_component *component, + static void set_iir_band_coeff(struct snd_soc_component *component, + int iir_idx, int band_idx, uint32_t value) + { +- int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 16 * iir_idx; ++ int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B2_CTL + 0x80 * iir_idx; + + snd_soc_component_write(component, reg, (value & 0xFF)); + snd_soc_component_write(component, reg, (value >> 8) & 0xFF); +@@ -2739,7 +2739,7 @@ static int rx_macro_put_iir_band_audio_mixer( + int iir_idx = ctl->iir_idx; + int band_idx = ctl->band_idx; + u32 coeff[BAND_MAX]; +- int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 16 * iir_idx; ++ int reg = CDC_RX_SIDETONE_IIR0_IIR_COEF_B1_CTL + 0x80 * iir_idx; + + memcpy(&coeff[0], ucontrol->value.bytes.data, params->max); + +diff --git a/sound/soc/codecs/max9759.c b/sound/soc/codecs/max9759.c +index 00e9d4fd1651f..0c261335c8a16 100644 +--- a/sound/soc/codecs/max9759.c ++++ b/sound/soc/codecs/max9759.c +@@ -64,7 +64,8 @@ static int speaker_gain_control_put(struct snd_kcontrol *kcontrol, + struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol); + struct max9759 *priv = snd_soc_component_get_drvdata(c); + +- if (ucontrol->value.integer.value[0] > 3) ++ if (ucontrol->value.integer.value[0] < 0 || ++ ucontrol->value.integer.value[0] > 3) + return -EINVAL; + + priv->gain = ucontrol->value.integer.value[0]; +diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c +index f946ef65a4c19..f7018f2dd21fd 100644 +--- a/sound/soc/codecs/nau8824.c ++++ b/sound/soc/codecs/nau8824.c +@@ -8,6 +8,7 @@ + + #include <linux/module.h> + #include <linux/delay.h> ++#include <linux/dmi.h> + #include <linux/init.h> + #include <linux/i2c.h> + #include <linux/regmap.h> +@@ -27,6 +28,12 @@ + + #include "nau8824.h" + ++#define NAU8824_JD_ACTIVE_HIGH BIT(0) ++ ++static int nau8824_quirk; ++static int quirk_override = -1; ++module_param_named(quirk, quirk_override, uint, 0444); ++MODULE_PARM_DESC(quirk, "Board-specific quirk override"); + + static int nau8824_config_sysclk(struct nau8824 *nau8824, + int clk_id, unsigned int freq); +@@ -1845,6 +1852,34 @@ static int nau8824_read_device_properties(struct device *dev, + return 0; + } + ++/* Please keep this list alphabetically sorted */ ++static const struct dmi_system_id nau8824_quirk_table[] = { ++ { ++ /* Cyberbook T116 rugged tablet */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"), ++ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "20170531"), ++ }, ++ .driver_data = (void *)(NAU8824_JD_ACTIVE_HIGH), ++ }, ++ {} ++}; ++ ++static void nau8824_check_quirks(void) ++{ ++ const struct dmi_system_id *dmi_id; ++ ++ if (quirk_override != -1) { ++ nau8824_quirk = quirk_override; ++ return; ++ } ++ ++ dmi_id = dmi_first_match(nau8824_quirk_table); ++ if (dmi_id) ++ nau8824_quirk = (unsigned long)dmi_id->driver_data; ++} ++ + static int nau8824_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) + { +@@ -1869,6 +1904,11 @@ static int nau8824_i2c_probe(struct i2c_client *i2c, + nau8824->irq = i2c->irq; + sema_init(&nau8824->jd_sem, 1); + ++ nau8824_check_quirks(); ++ ++ if (nau8824_quirk & NAU8824_JD_ACTIVE_HIGH) ++ nau8824->jkdet_polarity = 0; ++ + nau8824_print_device_properties(nau8824); + + ret = regmap_read(nau8824->regmap, NAU8824_REG_I2C_DEVICE_ID, &value); +diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c +index 943d7d933e81b..03f24edfe4f64 100644 +--- a/sound/soc/codecs/rk817_codec.c ++++ b/sound/soc/codecs/rk817_codec.c +@@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver); + MODULE_DESCRIPTION("ASoC RK817 codec driver"); + MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>"); + MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:rk817-codec"); +diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c +index fc0c83b73f099..93820561b9f5d 100644 +--- a/sound/soc/codecs/rt5651.c ++++ b/sound/soc/codecs/rt5651.c +@@ -2261,11 +2261,8 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, + + ret = devm_request_irq(&i2c->dev, rt5651->irq, rt5651_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING +- | IRQF_ONESHOT, "rt5651", rt5651); +- if (ret == 0) { +- /* Gets re-enabled by rt5651_set_jack() */ +- disable_irq(rt5651->irq); +- } else { ++ | IRQF_ONESHOT | IRQF_NO_AUTOEN, "rt5651", rt5651); ++ if (ret) { + dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n", + rt5651->irq, ret); + rt5651->irq = -ENXIO; +diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c +index be9fc58ff6812..ee09ccd448dcd 100644 +--- a/sound/soc/codecs/rt5663.c ++++ b/sound/soc/codecs/rt5663.c +@@ -3461,6 +3461,7 @@ static void rt5663_calibrate(struct rt5663_priv *rt5663) + static int rt5663_parse_dp(struct rt5663_priv *rt5663, struct device *dev) + { + int table_size; ++ int ret; + + device_property_read_u32(dev, "realtek,dc_offset_l_manual", + &rt5663->pdata.dc_offset_l_manual); +@@ -3477,9 +3478,11 @@ static int rt5663_parse_dp(struct rt5663_priv *rt5663, struct device *dev) + table_size = sizeof(struct impedance_mapping_table) * + rt5663->pdata.impedance_sensing_num; + rt5663->imp_table = devm_kzalloc(dev, table_size, GFP_KERNEL); +- device_property_read_u32_array(dev, ++ ret = device_property_read_u32_array(dev, + "realtek,impedance_sensing_table", + (u32 *)rt5663->imp_table, table_size); ++ if (ret) ++ return ret; + } + + return 0; +@@ -3504,8 +3507,11 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, + + if (pdata) + rt5663->pdata = *pdata; +- else +- rt5663_parse_dp(rt5663, &i2c->dev); ++ else { ++ ret = rt5663_parse_dp(rt5663, &i2c->dev); ++ if (ret) ++ return ret; ++ } + + for (i = 0; i < ARRAY_SIZE(rt5663->supplies); i++) + rt5663->supplies[i].supply = rt5663_supply_names[i]; +diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c +index 6ab1a8bc37352..1186ceb5a978e 100644 +--- a/sound/soc/codecs/rt5668.c ++++ b/sound/soc/codecs/rt5668.c +@@ -1022,11 +1022,13 @@ static void rt5668_jack_detect_handler(struct work_struct *work) + container_of(work, struct rt5668_priv, jack_detect_work.work); + int val, btn_type; + +- while (!rt5668->component) +- usleep_range(10000, 15000); +- +- while (!rt5668->component->card->instantiated) +- usleep_range(10000, 15000); ++ if (!rt5668->component || !rt5668->component->card || ++ !rt5668->component->card->instantiated) { ++ /* card not yet ready, try later */ ++ mod_delayed_work(system_power_efficient_wq, ++ &rt5668->jack_detect_work, msecs_to_jiffies(15)); ++ return; ++ } + + mutex_lock(&rt5668->calibrate_mutex); + +diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c +index 4a64cab99c55b..6ad3159eceb98 100644 +--- a/sound/soc/codecs/rt5682.c ++++ b/sound/soc/codecs/rt5682.c +@@ -46,6 +46,8 @@ static const struct reg_sequence patch_list[] = { + {RT5682_SAR_IL_CMD_1, 0x22b7}, + {RT5682_SAR_IL_CMD_3, 0x0365}, + {RT5682_SAR_IL_CMD_6, 0x0110}, ++ {RT5682_CHARGE_PUMP_1, 0x0210}, ++ {RT5682_HP_LOGIC_CTRL_2, 0x0007}, + }; + + void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev) +@@ -925,6 +927,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) + unsigned int val, count; + + if (jack_insert) { ++ snd_soc_dapm_mutex_lock(dapm); ++ + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, + RT5682_PWR_VREF2 | RT5682_PWR_MB, + RT5682_PWR_VREF2 | RT5682_PWR_MB); +@@ -971,6 +975,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) + snd_soc_component_update_bits(component, RT5682_MICBIAS_2, + RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, + RT5682_PWR_CLK25M_PU | RT5682_PWR_CLK1M_PU); ++ ++ snd_soc_dapm_mutex_unlock(dapm); + } else { + rt5682_enable_push_button_irq(component, false); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, +@@ -1084,11 +1090,13 @@ void rt5682_jack_detect_handler(struct work_struct *work) + container_of(work, struct rt5682_priv, jack_detect_work.work); + int val, btn_type; + +- while (!rt5682->component) +- usleep_range(10000, 15000); +- +- while (!rt5682->component->card->instantiated) +- usleep_range(10000, 15000); ++ if (!rt5682->component || !rt5682->component->card || ++ !rt5682->component->card->instantiated) { ++ /* card not yet ready, try later */ ++ mod_delayed_work(system_power_efficient_wq, ++ &rt5682->jack_detect_work, msecs_to_jiffies(15)); ++ return; ++ } + + mutex_lock(&rt5682->calibrate_mutex); + +@@ -1515,21 +1523,29 @@ static int rt5682_hp_event(struct snd_soc_dapm_widget *w, + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: +- snd_soc_component_write(component, +- RT5682_HP_LOGIC_CTRL_2, 0x0012); +- snd_soc_component_write(component, +- RT5682_HP_CTRL_2, 0x6000); ++ snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, ++ RT5682_HP_C2_DAC_AMP_MUTE, 0); ++ snd_soc_component_update_bits(component, RT5682_HP_LOGIC_CTRL_2, ++ RT5682_HP_LC2_SIG_SOUR2_MASK, RT5682_HP_LC2_SIG_SOUR2_REG); + snd_soc_component_update_bits(component, + RT5682_DEPOP_1, 0x60, 0x60); + snd_soc_component_update_bits(component, + RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0080); ++ snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, ++ RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, ++ RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN); ++ usleep_range(5000, 10000); ++ snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, ++ RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_L); + break; + + case SND_SOC_DAPM_POST_PMD: ++ snd_soc_component_update_bits(component, RT5682_HP_CTRL_2, ++ RT5682_HP_C2_DAC_L_EN | RT5682_HP_C2_DAC_R_EN, 0); ++ snd_soc_component_update_bits(component, RT5682_CHARGE_PUMP_1, ++ RT5682_CP_SW_SIZE_MASK, RT5682_CP_SW_SIZE_M); + snd_soc_component_update_bits(component, + RT5682_DEPOP_1, 0x60, 0x0); +- snd_soc_component_write(component, +- RT5682_HP_CTRL_2, 0x0000); + snd_soc_component_update_bits(component, + RT5682_DAC_ADC_DIG_VOL1, 0x00c0, 0x0000); + break; +@@ -1637,6 +1653,23 @@ static SOC_VALUE_ENUM_SINGLE_DECL(rt5682_adcdat_pin_enum, + static const struct snd_kcontrol_new rt5682_adcdat_pin_ctrl = + SOC_DAPM_ENUM("ADCDAT", rt5682_adcdat_pin_enum); + ++static const unsigned int rt5682_hpo_sig_out_values[] = { ++ 2, ++ 7, ++}; ++ ++static const char * const rt5682_hpo_sig_out_mode[] = { ++ "Legacy", ++ "OneBit", ++}; ++ ++static SOC_VALUE_ENUM_SINGLE_DECL(rt5682_hpo_sig_out_enum, ++ RT5682_HP_LOGIC_CTRL_2, 0, RT5682_HP_LC2_SIG_SOUR1_MASK, ++ rt5682_hpo_sig_out_mode, rt5682_hpo_sig_out_values); ++ ++static const struct snd_kcontrol_new rt5682_hpo_sig_demux = ++ SOC_DAPM_ENUM("HPO Signal Demux", rt5682_hpo_sig_out_enum); ++ + static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("LDO2", RT5682_PWR_ANLG_3, RT5682_PWR_LDO2_BIT, + 0, NULL, 0), +@@ -1820,6 +1853,10 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { + SND_SOC_DAPM_SWITCH("HPOR Playback", SND_SOC_NOPM, 0, 0, + &hpor_switch), + ++ SND_SOC_DAPM_OUT_DRV("HPO Legacy", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_OUT_DRV("HPO OneBit", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_DEMUX("HPO Signal Demux", SND_SOC_NOPM, 0, 0, &rt5682_hpo_sig_demux), ++ + /* CLK DET */ + SND_SOC_DAPM_SUPPLY("CLKDET SYS", RT5682_CLK_DET, + RT5682_SYS_CLK_DET_SFT, 0, NULL, 0), +@@ -1987,10 +2024,19 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = { + {"HP Amp", NULL, "Charge Pump"}, + {"HP Amp", NULL, "CLKDET SYS"}, + {"HP Amp", NULL, "Vref1"}, +- {"HPOL Playback", "Switch", "HP Amp"}, +- {"HPOR Playback", "Switch", "HP Amp"}, ++ ++ {"HPO Signal Demux", NULL, "HP Amp"}, ++ ++ {"HPO Legacy", "Legacy", "HPO Signal Demux"}, ++ {"HPO OneBit", "OneBit", "HPO Signal Demux"}, ++ ++ {"HPOL Playback", "Switch", "HPO Legacy"}, ++ {"HPOR Playback", "Switch", "HPO Legacy"}, ++ + {"HPOL", NULL, "HPOL Playback"}, + {"HPOR", NULL, "HPOR Playback"}, ++ {"HPOL", NULL, "HPO OneBit"}, ++ {"HPOR", NULL, "HPO OneBit"}, + }; + + static int rt5682_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, +@@ -2800,6 +2846,8 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) + + for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) { + struct clk_init_data init = { }; ++ struct clk_parent_data parent_data; ++ const struct clk_hw *parent; + + dai_clk_hw = &rt5682->dai_clks_hw[i]; + +@@ -2807,17 +2855,17 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) + case RT5682_DAI_WCLK_IDX: + /* Make MCLK the parent of WCLK */ + if (rt5682->mclk) { +- init.parent_data = &(struct clk_parent_data){ ++ parent_data = (struct clk_parent_data){ + .fw_name = "mclk", + }; ++ init.parent_data = &parent_data; + init.num_parents = 1; + } + break; + case RT5682_DAI_BCLK_IDX: + /* Make WCLK the parent of BCLK */ +- init.parent_hws = &(const struct clk_hw *){ +- &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX] +- }; ++ parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]; ++ init.parent_hws = &parent; + init.num_parents = 1; + break; + default: +diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h +index b59221048ebf9..8e3244a62c160 100644 +--- a/sound/soc/codecs/rt5682.h ++++ b/sound/soc/codecs/rt5682.h +@@ -375,6 +375,14 @@ + #define RT5682_R_VOL_MASK (0x3f) + #define RT5682_R_VOL_SFT 0 + ++/* Headphone Amp Control 2 (0x0003) */ ++#define RT5682_HP_C2_DAC_AMP_MUTE_SFT 15 ++#define RT5682_HP_C2_DAC_AMP_MUTE (0x1 << 15) ++#define RT5682_HP_C2_DAC_L_EN_SFT 14 ++#define RT5682_HP_C2_DAC_L_EN (0x1 << 14) ++#define RT5682_HP_C2_DAC_R_EN_SFT 13 ++#define RT5682_HP_C2_DAC_R_EN (0x1 << 13) ++ + /*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/ + #define RT5682_G_HP (0xf << 8) + #define RT5682_G_HP_SFT 8 +@@ -1265,6 +1273,10 @@ + #define RT5682_HPA_CP_BIAS_6UA (0x3 << 2) + + /* Charge Pump Internal Register1 (0x0125) */ ++#define RT5682_CP_SW_SIZE_MASK (0x7 << 8) ++#define RT5682_CP_SW_SIZE_L (0x4 << 8) ++#define RT5682_CP_SW_SIZE_M (0x2 << 8) ++#define RT5682_CP_SW_SIZE_S (0x1 << 8) + #define RT5682_CP_CLK_HP_MASK (0x3 << 4) + #define RT5682_CP_CLK_HP_100KHZ (0x0 << 4) + #define RT5682_CP_CLK_HP_200KHZ (0x1 << 4) +@@ -1315,6 +1327,14 @@ + #define RT5682_DEB_STO_DAC_MASK (0x7 << 4) + #define RT5682_DEB_80_MS (0x0 << 4) + ++/* HP Behavior Logic Control 2 (0x01db) */ ++#define RT5682_HP_LC2_SIG_SOUR2_MASK (0x1 << 4) ++#define RT5682_HP_LC2_SIG_SOUR2_REG (0x1 << 4) ++#define RT5682_HP_LC2_SIG_SOUR2_DC_CAL (0x0 << 4) ++#define RT5682_HP_LC2_SIG_SOUR1_MASK (0x7) ++#define RT5682_HP_LC2_SIG_SOUR1_1BIT (0x7) ++#define RT5682_HP_LC2_SIG_SOUR1_LEGA (0x2) ++ + /* SAR ADC Inline Command Control 1 (0x0210) */ + #define RT5682_SAR_BUTT_DET_MASK (0x1 << 15) + #define RT5682_SAR_BUTT_DET_EN (0x1 << 15) +diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c +index 172e79cbe0daf..c5ea3b115966b 100644 +--- a/sound/soc/codecs/tas2770.c ++++ b/sound/soc/codecs/tas2770.c +@@ -38,10 +38,12 @@ static void tas2770_reset(struct tas2770_priv *tas2770) + gpiod_set_value_cansleep(tas2770->reset_gpio, 0); + msleep(20); + gpiod_set_value_cansleep(tas2770->reset_gpio, 1); ++ usleep_range(1000, 2000); + } + + snd_soc_component_write(tas2770->component, TAS2770_SW_RST, + TAS2770_RST); ++ usleep_range(1000, 2000); + } + + static int tas2770_set_bias_level(struct snd_soc_component *component, +@@ -110,6 +112,7 @@ static int tas2770_codec_resume(struct snd_soc_component *component) + + if (tas2770->sdz_gpio) { + gpiod_set_value_cansleep(tas2770->sdz_gpio, 1); ++ usleep_range(1000, 2000); + } else { + ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL, + TAS2770_PWR_CTRL_MASK, +@@ -291,11 +294,11 @@ static int tas2770_set_samplerate(struct tas2770_priv *tas2770, int samplerate) + ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ | + TAS2770_TDM_CFG_REG0_31_88_2_96KHZ; + break; +- case 19200: ++ case 192000: + ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ | + TAS2770_TDM_CFG_REG0_31_176_4_192KHZ; + break; +- case 17640: ++ case 176400: + ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ | + TAS2770_TDM_CFG_REG0_31_176_4_192KHZ; + break; +@@ -510,8 +513,10 @@ static int tas2770_codec_probe(struct snd_soc_component *component) + + tas2770->component = component; + +- if (tas2770->sdz_gpio) ++ if (tas2770->sdz_gpio) { + gpiod_set_value_cansleep(tas2770->sdz_gpio, 1); ++ usleep_range(1000, 2000); ++ } + + tas2770_reset(tas2770); + +diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c +index d885ced34f606..bc5d68c53e5ab 100644 +--- a/sound/soc/codecs/wcd9335.c ++++ b/sound/soc/codecs/wcd9335.c +@@ -4859,7 +4859,7 @@ static int wcd9335_codec_probe(struct snd_soc_component *component) + + snd_soc_component_init_regmap(component, wcd->regmap); + /* Class-H Init*/ +- wcd->clsh_ctrl = wcd_clsh_ctrl_alloc(component, wcd->version); ++ wcd->clsh_ctrl = wcd_clsh_ctrl_alloc(component, WCD9335); + if (IS_ERR(wcd->clsh_ctrl)) + return PTR_ERR(wcd->clsh_ctrl); + +diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c +index c496b359f2f40..e63c6b723d76c 100644 +--- a/sound/soc/codecs/wcd934x.c ++++ b/sound/soc/codecs/wcd934x.c +@@ -1896,9 +1896,8 @@ static int wcd934x_hw_params(struct snd_pcm_substream *substream, + } + + wcd->dai[dai->id].sconfig.rate = params_rate(params); +- wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); + +- return 0; ++ return wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream); + } + + static int wcd934x_hw_free(struct snd_pcm_substream *substream, +@@ -3257,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, + int value = ucontrol->value.integer.value[0]; + int sel; + ++ if (wcd->comp_enabled[comp] == value) ++ return 0; ++ + wcd->comp_enabled[comp] = value; + sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER : + WCD934X_HPH_GAIN_SRC_SEL_REGISTER; +@@ -3280,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, + case COMPANDER_8: + break; + default: +- break; ++ return 0; + } + +- return 0; ++ return 1; + } + + static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc, +@@ -3327,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc, + return 0; + } + ++static int slim_rx_mux_to_dai_id(int mux) ++{ ++ int aif_id; ++ ++ switch (mux) { ++ case 1: ++ aif_id = AIF1_PB; ++ break; ++ case 2: ++ aif_id = AIF2_PB; ++ break; ++ case 3: ++ aif_id = AIF3_PB; ++ break; ++ case 4: ++ aif_id = AIF4_PB; ++ break; ++ default: ++ aif_id = -1; ++ break; ++ } ++ ++ return aif_id; ++} ++ + static int slim_rx_mux_put(struct snd_kcontrol *kc, + struct snd_ctl_elem_value *ucontrol) + { +@@ -3334,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, + struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev); + struct soc_enum *e = (struct soc_enum *)kc->private_value; + struct snd_soc_dapm_update *update = NULL; ++ struct wcd934x_slim_ch *ch, *c; + u32 port_id = w->shift; ++ bool found = false; ++ int mux_idx; ++ int prev_mux_idx = wcd->rx_port_value[port_id]; ++ int aif_id; + +- if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) +- return 0; ++ mux_idx = ucontrol->value.enumerated.item[0]; + +- wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; ++ if (mux_idx == prev_mux_idx) ++ return 0; + +- switch (wcd->rx_port_value[port_id]) { ++ switch(mux_idx) { + case 0: +- list_del_init(&wcd->rx_chs[port_id].list); +- break; +- case 1: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF1_PB].slim_ch_list); +- break; +- case 2: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF2_PB].slim_ch_list); +- break; +- case 3: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF3_PB].slim_ch_list); ++ aif_id = slim_rx_mux_to_dai_id(prev_mux_idx); ++ if (aif_id < 0) ++ return 0; ++ ++ list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) { ++ if (ch->port == port_id + WCD934X_RX_START) { ++ found = true; ++ list_del_init(&ch->list); ++ break; ++ } ++ } ++ if (!found) ++ return 0; ++ + break; +- case 4: +- list_add_tail(&wcd->rx_chs[port_id].list, +- &wcd->dai[AIF4_PB].slim_ch_list); ++ case 1 ... 4: ++ aif_id = slim_rx_mux_to_dai_id(mux_idx); ++ if (aif_id < 0) ++ return 0; ++ ++ if (list_empty(&wcd->rx_chs[port_id].list)) { ++ list_add_tail(&wcd->rx_chs[port_id].list, ++ &wcd->dai[aif_id].slim_ch_list); ++ } else { ++ dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id); ++ return 0; ++ } + break; ++ + default: +- dev_err(wcd->dev, "Unknown AIF %d\n", +- wcd->rx_port_value[port_id]); ++ dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx); + goto err; + } + ++ wcd->rx_port_value[port_id] = mux_idx; + snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id], + e, update); + +- return 0; ++ return 1; + err: + return -EINVAL; + } +@@ -3816,6 +3859,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, + struct soc_mixer_control *mixer = + (struct soc_mixer_control *)kc->private_value; + int enable = ucontrol->value.integer.value[0]; ++ struct wcd934x_slim_ch *ch, *c; + int dai_id = widget->shift; + int port_id = mixer->shift; + +@@ -3823,17 +3867,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, + if (enable == wcd->tx_port_value[port_id]) + return 0; + +- wcd->tx_port_value[port_id] = enable; +- +- if (enable) +- list_add_tail(&wcd->tx_chs[port_id].list, +- &wcd->dai[dai_id].slim_ch_list); +- else +- list_del_init(&wcd->tx_chs[port_id].list); ++ if (enable) { ++ if (list_empty(&wcd->tx_chs[port_id].list)) { ++ list_add_tail(&wcd->tx_chs[port_id].list, ++ &wcd->dai[dai_id].slim_ch_list); ++ } else { ++ dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id); ++ return 0; ++ } ++ } else { ++ bool found = false; ++ ++ list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) { ++ if (ch->port == port_id) { ++ found = true; ++ list_del_init(&wcd->tx_chs[port_id].list); ++ break; ++ } ++ } ++ if (!found) ++ return 0; ++ } + ++ wcd->tx_port_value[port_id] = enable; + snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update); + +- return 0; ++ return 1; + } + + static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = { +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index 52de7d14b1398..bbc261ab2025b 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -1174,6 +1174,9 @@ static bool wcd938x_readonly_register(struct device *dev, unsigned int reg) + case WCD938X_DIGITAL_INTR_STATUS_0: + case WCD938X_DIGITAL_INTR_STATUS_1: + case WCD938X_DIGITAL_INTR_STATUS_2: ++ case WCD938X_DIGITAL_INTR_CLEAR_0: ++ case WCD938X_DIGITAL_INTR_CLEAR_1: ++ case WCD938X_DIGITAL_INTR_CLEAR_2: + case WCD938X_DIGITAL_SWR_HM_TEST_0: + case WCD938X_DIGITAL_SWR_HM_TEST_1: + case WCD938X_DIGITAL_EFUSE_T_DATA_0: +@@ -1429,14 +1432,10 @@ static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info, + return 0; + } + +-static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 ch_id, u8 enable) ++static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 port_num, u8 ch_id, u8 enable) + { +- u8 port_num; +- +- port_num = wcd->ch_info[ch_id].port_num; +- + return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id], +- &wcd->port_config[port_num], ++ &wcd->port_config[port_num - 1], + enable); + } + +@@ -2560,7 +2559,7 @@ static int wcd938x_ear_pa_put_gain(struct snd_kcontrol *kcontrol, + WCD938X_EAR_GAIN_MASK, + ucontrol->value.integer.value[0]); + +- return 0; ++ return 1; + } + + static int wcd938x_get_compander(struct snd_kcontrol *kcontrol, +@@ -2590,6 +2589,7 @@ static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + struct wcd938x_sdw_priv *wcd; + int value = ucontrol->value.integer.value[0]; ++ int portidx; + struct soc_mixer_control *mc; + bool hphr; + +@@ -2603,12 +2603,14 @@ static int wcd938x_set_compander(struct snd_kcontrol *kcontrol, + else + wcd938x->comp1_enable = value; + ++ portidx = wcd->ch_info[mc->reg].port_num; ++ + if (value) +- wcd938x_connect_port(wcd, mc->reg, true); ++ wcd938x_connect_port(wcd, portidx, mc->reg, true); + else +- wcd938x_connect_port(wcd, mc->reg, false); ++ wcd938x_connect_port(wcd, portidx, mc->reg, false); + +- return 0; ++ return 1; + } + + static int wcd938x_ldoh_get(struct snd_kcontrol *kcontrol, +@@ -2879,9 +2881,11 @@ static int wcd938x_get_swr_port(struct snd_kcontrol *kcontrol, + struct wcd938x_sdw_priv *wcd; + struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; + int dai_id = mixer->shift; +- int portidx = mixer->reg; ++ int portidx, ch_idx = mixer->reg; ++ + + wcd = wcd938x->sdw_priv[dai_id]; ++ portidx = wcd->ch_info[ch_idx].port_num; + + ucontrol->value.integer.value[0] = wcd->port_enable[portidx]; + +@@ -2896,12 +2900,14 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, + struct wcd938x_sdw_priv *wcd; + struct soc_mixer_control *mixer = + (struct soc_mixer_control *)kcontrol->private_value; +- int portidx = mixer->reg; ++ int ch_idx = mixer->reg; ++ int portidx; + int dai_id = mixer->shift; + bool enable; + + wcd = wcd938x->sdw_priv[dai_id]; + ++ portidx = wcd->ch_info[ch_idx].port_num; + if (ucontrol->value.integer.value[0]) + enable = true; + else +@@ -2909,9 +2915,9 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, + + wcd->port_enable[portidx] = enable; + +- wcd938x_connect_port(wcd, portidx, enable); ++ wcd938x_connect_port(wcd, portidx, ch_idx, enable); + +- return 0; ++ return 1; + + } + +diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c +index 2da4a5fa7a18d..564b78f3cdd0a 100644 +--- a/sound/soc/codecs/wsa881x.c ++++ b/sound/soc/codecs/wsa881x.c +@@ -772,7 +772,8 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc, + + usleep_range(1000, 1010); + } +- return 0; ++ ++ return 1; + } + + static int wsa881x_get_port(struct snd_kcontrol *kcontrol, +@@ -816,15 +817,22 @@ static int wsa881x_set_port(struct snd_kcontrol *kcontrol, + (struct soc_mixer_control *)kcontrol->private_value; + int portidx = mixer->reg; + +- if (ucontrol->value.integer.value[0]) ++ if (ucontrol->value.integer.value[0]) { ++ if (data->port_enable[portidx]) ++ return 0; ++ + data->port_enable[portidx] = true; +- else ++ } else { ++ if (!data->port_enable[portidx]) ++ return 0; ++ + data->port_enable[portidx] = false; ++ } + + if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */ + wsa881x_boost_ctrl(comp, data->port_enable[portidx]); + +- return 0; ++ return 1; + } + + static const char * const smart_boost_lvl_text[] = { +diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c +index 24b41881a68f8..d7d1536a4f377 100644 +--- a/sound/soc/fsl/fsl_asrc.c ++++ b/sound/soc/fsl/fsl_asrc.c +@@ -19,6 +19,7 @@ + #include "fsl_asrc.h" + + #define IDEAL_RATIO_DECIMAL_DEPTH 26 ++#define DIVIDER_NUM 64 + + #define pair_err(fmt, ...) \ + dev_err(&asrc->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) +@@ -101,6 +102,55 @@ static unsigned char clk_map_imx8qxp[2][ASRC_CLK_MAP_LEN] = { + }, + }; + ++/* ++ * According to RM, the divider range is 1 ~ 8, ++ * prescaler is power of 2 from 1 ~ 128. ++ */ ++static int asrc_clk_divider[DIVIDER_NUM] = { ++ 1, 2, 4, 8, 16, 32, 64, 128, /* divider = 1 */ ++ 2, 4, 8, 16, 32, 64, 128, 256, /* divider = 2 */ ++ 3, 6, 12, 24, 48, 96, 192, 384, /* divider = 3 */ ++ 4, 8, 16, 32, 64, 128, 256, 512, /* divider = 4 */ ++ 5, 10, 20, 40, 80, 160, 320, 640, /* divider = 5 */ ++ 6, 12, 24, 48, 96, 192, 384, 768, /* divider = 6 */ ++ 7, 14, 28, 56, 112, 224, 448, 896, /* divider = 7 */ ++ 8, 16, 32, 64, 128, 256, 512, 1024, /* divider = 8 */ ++}; ++ ++/* ++ * Check if the divider is available for internal ratio mode ++ */ ++static bool fsl_asrc_divider_avail(int clk_rate, int rate, int *div) ++{ ++ u32 rem, i; ++ u64 n; ++ ++ if (div) ++ *div = 0; ++ ++ if (clk_rate == 0 || rate == 0) ++ return false; ++ ++ n = clk_rate; ++ rem = do_div(n, rate); ++ ++ if (div) ++ *div = n; ++ ++ if (rem != 0) ++ return false; ++ ++ for (i = 0; i < DIVIDER_NUM; i++) { ++ if (n == asrc_clk_divider[i]) ++ break; ++ } ++ ++ if (i == DIVIDER_NUM) ++ return false; ++ ++ return true; ++} ++ + /** + * fsl_asrc_sel_proc - Select the pre-processing and post-processing options + * @inrate: input sample rate +@@ -330,12 +380,12 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) + enum asrc_word_width input_word_width; + enum asrc_word_width output_word_width; + u32 inrate, outrate, indiv, outdiv; +- u32 clk_index[2], div[2], rem[2]; ++ u32 clk_index[2], div[2]; + u64 clk_rate; + int in, out, channels; + int pre_proc, post_proc; + struct clk *clk; +- bool ideal; ++ bool ideal, div_avail; + + if (!config) { + pair_err("invalid pair config\n"); +@@ -415,8 +465,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) + clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]]; + + clk_rate = clk_get_rate(clk); +- rem[IN] = do_div(clk_rate, inrate); +- div[IN] = (u32)clk_rate; ++ div_avail = fsl_asrc_divider_avail(clk_rate, inrate, &div[IN]); + + /* + * The divider range is [1, 1024], defined by the hardware. For non- +@@ -425,7 +474,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) + * only result in different converting speeds. So remainder does not + * matter, as long as we keep the divider within its valid range. + */ +- if (div[IN] == 0 || (!ideal && (div[IN] > 1024 || rem[IN] != 0))) { ++ if (div[IN] == 0 || (!ideal && !div_avail)) { + pair_err("failed to support input sample rate %dHz by asrck_%x\n", + inrate, clk_index[ideal ? OUT : IN]); + return -EINVAL; +@@ -436,13 +485,12 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate) + clk = asrc_priv->asrck_clk[clk_index[OUT]]; + clk_rate = clk_get_rate(clk); + if (ideal && use_ideal_rate) +- rem[OUT] = do_div(clk_rate, IDEAL_RATIO_RATE); ++ div_avail = fsl_asrc_divider_avail(clk_rate, IDEAL_RATIO_RATE, &div[OUT]); + else +- rem[OUT] = do_div(clk_rate, outrate); +- div[OUT] = clk_rate; ++ div_avail = fsl_asrc_divider_avail(clk_rate, outrate, &div[OUT]); + + /* Output divider has the same limitation as the input one */ +- if (div[OUT] == 0 || (!ideal && (div[OUT] > 1024 || rem[OUT] != 0))) { ++ if (div[OUT] == 0 || (!ideal && !div_avail)) { + pair_err("failed to support output sample rate %dHz by asrck_%x\n", + outrate, clk_index[OUT]); + return -EINVAL; +@@ -621,8 +669,7 @@ static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv, + clk_index = asrc_priv->clk_map[j][i]; + clk_rate = clk_get_rate(asrc_priv->asrck_clk[clk_index]); + /* Only match a perfect clock source with no remainder */ +- if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 && +- (clk_rate % rate[j]) == 0) ++ if (fsl_asrc_divider_avail(clk_rate, rate[j], NULL)) + break; + } + +diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c +index 69aeb0e71844d..0d4efbed41dab 100644 +--- a/sound/soc/fsl/fsl_mqs.c ++++ b/sound/soc/fsl/fsl_mqs.c +@@ -337,4 +337,4 @@ module_platform_driver(fsl_mqs_driver); + MODULE_AUTHOR("Shengjiu Wang <Shengjiu.Wang@nxp.com>"); + MODULE_DESCRIPTION("MQS codec driver"); + MODULE_LICENSE("GPL v2"); +-MODULE_ALIAS("platform: fsl-mqs"); ++MODULE_ALIAS("platform:fsl-mqs"); +diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c +index 58fd0639a0698..db947180617a6 100644 +--- a/sound/soc/fsl/imx-card.c ++++ b/sound/soc/fsl/imx-card.c +@@ -120,7 +120,7 @@ struct imx_card_data { + + static struct imx_akcodec_fs_mul ak4458_fs_mul[] = { + /* Normal, < 32kHz */ +- { .rmin = 8000, .rmax = 24000, .wmin = 1024, .wmax = 1024, }, ++ { .rmin = 8000, .rmax = 24000, .wmin = 256, .wmax = 1024, }, + /* Normal, 32kHz */ + { .rmin = 32000, .rmax = 32000, .wmin = 256, .wmax = 1024, }, + /* Normal */ +@@ -151,8 +151,8 @@ static struct imx_akcodec_fs_mul ak4497_fs_mul[] = { + * Table 7 - mapping multiplier and speed mode + * Tables 8 & 9 - mapping speed mode and LRCK fs + */ +- { .rmin = 8000, .rmax = 32000, .wmin = 1024, .wmax = 1024, }, /* Normal, <= 32kHz */ +- { .rmin = 44100, .rmax = 48000, .wmin = 512, .wmax = 512, }, /* Normal */ ++ { .rmin = 8000, .rmax = 32000, .wmin = 256, .wmax = 1024, }, /* Normal, <= 32kHz */ ++ { .rmin = 44100, .rmax = 48000, .wmin = 256, .wmax = 512, }, /* Normal */ + { .rmin = 88200, .rmax = 96000, .wmin = 256, .wmax = 256, }, /* Double */ + { .rmin = 176400, .rmax = 192000, .wmin = 128, .wmax = 128, }, /* Quad */ + { .rmin = 352800, .rmax = 384000, .wmin = 128, .wmax = 128, }, /* Oct */ +@@ -164,7 +164,7 @@ static struct imx_akcodec_fs_mul ak4497_fs_mul[] = { + * (Table 4 from datasheet) + */ + static struct imx_akcodec_fs_mul ak5558_fs_mul[] = { +- { .rmin = 8000, .rmax = 32000, .wmin = 1024, .wmax = 1024, }, ++ { .rmin = 8000, .rmax = 32000, .wmin = 512, .wmax = 1024, }, + { .rmin = 44100, .rmax = 48000, .wmin = 512, .wmax = 512, }, + { .rmin = 88200, .rmax = 96000, .wmin = 256, .wmax = 256, }, + { .rmin = 176400, .rmax = 192000, .wmin = 128, .wmax = 128, }, +@@ -247,13 +247,14 @@ static bool codec_is_akcodec(unsigned int type) + } + + static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params) ++ struct snd_pcm_hw_params *params, ++ int slots, int slot_width) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card); + const struct imx_card_plat_data *plat_data = data->plat_data; + struct dai_link_data *link_data = &data->link_data[rtd->num]; +- unsigned int width = link_data->slots * link_data->slot_width; ++ unsigned int width = slots * slot_width; + unsigned int rate = params_rate(params); + int i; + +@@ -349,7 +350,7 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, + + /* Set MCLK freq */ + if (codec_is_akcodec(plat_data->type)) +- mclk_freq = akcodec_get_mclk_rate(substream, params); ++ mclk_freq = akcodec_get_mclk_rate(substream, params, slots, slot_width); + else + mclk_freq = params_rate(params) * slots * slot_width; + /* Use the maximum freq from DSD512 (512*44100 = 22579200) */ +@@ -553,8 +554,23 @@ static int imx_card_parse_of(struct imx_card_data *data) + link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1; + + /* sai may support mclk/bclk = 1 */ +- if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) ++ if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) { + link_data->one2one_ratio = true; ++ } else { ++ int i; ++ ++ /* ++ * i.MX8MQ don't support one2one ratio, then ++ * with ak4497 only 16bit case is supported. ++ */ ++ for (i = 0; i < ARRAY_SIZE(ak4497_fs_mul); i++) { ++ if (ak4497_fs_mul[i].rmin == 705600 && ++ ak4497_fs_mul[i].rmax == 768000) { ++ ak4497_fs_mul[i].wmin = 32; ++ ak4497_fs_mul[i].wmax = 32; ++ } ++ } ++ } + } + + link->cpus->of_node = args.np; +diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c +index 34a0dceae6216..ef8d7a65ebc61 100644 +--- a/sound/soc/fsl/imx-hdmi.c ++++ b/sound/soc/fsl/imx-hdmi.c +@@ -145,6 +145,8 @@ static int imx_hdmi_probe(struct platform_device *pdev) + data->dai.capture_only = false; + data->dai.init = imx_hdmi_init; + ++ put_device(&cpu_pdev->dev); ++ + if (of_node_name_eq(cpu_np, "sai")) { + data->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1; + data->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1; +diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c +index af3c3b90c0aca..83b4a22bf15ac 100644 +--- a/sound/soc/fsl/pcm030-audio-fabric.c ++++ b/sound/soc/fsl/pcm030-audio-fabric.c +@@ -93,16 +93,21 @@ static int pcm030_fabric_probe(struct platform_device *op) + dev_err(&op->dev, "platform_device_alloc() failed\n"); + + ret = platform_device_add(pdata->codec_device); +- if (ret) ++ if (ret) { + dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); ++ platform_device_put(pdata->codec_device); ++ } + + ret = snd_soc_register_card(card); +- if (ret) ++ if (ret) { + dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); ++ platform_device_del(pdata->codec_device); ++ platform_device_put(pdata->codec_device); ++ } + + platform_set_drvdata(op, pdata); +- + return ret; ++ + } + + static int pcm030_fabric_remove(struct platform_device *op) +diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c +index a3a7990b5cb66..bc3e24c6a28a8 100644 +--- a/sound/soc/generic/simple-card.c ++++ b/sound/soc/generic/simple-card.c +@@ -28,6 +28,30 @@ static const struct snd_soc_ops simple_ops = { + .hw_params = asoc_simple_hw_params, + }; + ++static int asoc_simple_parse_platform(struct device_node *node, ++ struct snd_soc_dai_link_component *dlc) ++{ ++ struct of_phandle_args args; ++ int ret; ++ ++ if (!node) ++ return 0; ++ ++ /* ++ * Get node via "sound-dai = <&phandle port>" ++ * it will be used as xxx_of_node on soc_bind_dai_link() ++ */ ++ ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args); ++ if (ret) ++ return ret; ++ ++ /* dai_name is not required and may not exist for plat component */ ++ ++ dlc->of_node = args.np; ++ ++ return 0; ++} ++ + static int asoc_simple_parse_dai(struct device_node *node, + struct snd_soc_dai_link_component *dlc, + int *is_single_link) +@@ -289,7 +313,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, + if (ret < 0) + goto dai_link_of_err; + +- ret = asoc_simple_parse_dai(plat, platforms, NULL); ++ ret = asoc_simple_parse_platform(plat, platforms); + if (ret < 0) + goto dai_link_of_err; + +diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c +index 6b06248a9327a..76759b2099064 100644 +--- a/sound/soc/intel/boards/sof_sdw.c ++++ b/sound/soc/intel/boards/sof_sdw.c +@@ -188,7 +188,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | +- RT711_JD2), ++ RT711_JD1), + }, + { + /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */ +@@ -213,6 +213,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), + }, ++ { ++ .callback = sof_sdw_quirk_cb, ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45") ++ }, ++ .driver_data = (void *)(SOF_SDW_TGL_HDMI | ++ RT711_JD2 | ++ SOF_RT715_DAI_ID_FIX), ++ }, + /* AlderLake devices */ + { + .callback = sof_sdw_quirk_cb, +diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c +index 9c5fd18f2600f..346bec0003066 100644 +--- a/sound/soc/intel/catpt/dsp.c ++++ b/sound/soc/intel/catpt/dsp.c +@@ -65,6 +65,7 @@ static int catpt_dma_memcpy(struct catpt_dev *cdev, struct dma_chan *chan, + { + struct dma_async_tx_descriptor *desc; + enum dma_status status; ++ int ret; + + desc = dmaengine_prep_dma_memcpy(chan, dst_addr, src_addr, size, + DMA_CTRL_ACK); +@@ -77,13 +78,22 @@ static int catpt_dma_memcpy(struct catpt_dev *cdev, struct dma_chan *chan, + catpt_updatel_shim(cdev, HMDC, + CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id), + CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id)); +- dmaengine_submit(desc); ++ ++ ret = dma_submit_error(dmaengine_submit(desc)); ++ if (ret) { ++ dev_err(cdev->dev, "submit tx failed: %d\n", ret); ++ goto clear_hdda; ++ } ++ + status = dma_wait_for_async_tx(desc); ++ ret = (status == DMA_COMPLETE) ? 0 : -EPROTO; ++ ++clear_hdda: + /* regardless of status, disable access to HOST memory in demand mode */ + catpt_updatel_shim(cdev, HMDC, + CATPT_HMDC_HDDA(CATPT_DMA_DEVID, chan->chan_id), 0); + +- return (status == DMA_COMPLETE) ? 0 : -EPROTO; ++ return ret; + } + + int catpt_dma_memcpy_todsp(struct catpt_dev *cdev, struct dma_chan *chan, +diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +index 785d5f5f8a9c9..11801b905ecc2 100644 +--- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c ++++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +@@ -156,6 +156,15 @@ static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + } + }; + ++static const struct snd_soc_acpi_adr_device rt1316_1_single_adr[] = { ++ { ++ .adr = 0x000131025D131601ull, ++ .num_endpoints = 1, ++ .endpoints = &single_endpoint, ++ .name_prefix = "rt1316-1" ++ } ++}; ++ + static const struct snd_soc_acpi_adr_device rt1316_1_group1_adr[] = { + { + .adr = 0x000131025D131601ull, /* unique ID is set for some reason */ +@@ -320,6 +329,25 @@ static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca[] = { + {} + }; + ++static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca_mono[] = { ++ { ++ .mask = BIT(0), ++ .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), ++ .adr_d = rt711_sdca_0_adr, ++ }, ++ { ++ .mask = BIT(1), ++ .num_adr = ARRAY_SIZE(rt1316_1_single_adr), ++ .adr_d = rt1316_1_single_adr, ++ }, ++ { ++ .mask = BIT(3), ++ .num_adr = ARRAY_SIZE(rt714_3_adr), ++ .adr_d = rt714_3_adr, ++ }, ++ {} ++}; ++ + static const struct snd_soc_acpi_codecs tgl_max98373_amp = { + .num_codecs = 1, + .codecs = {"MX98373"} +@@ -412,6 +440,19 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg", + }, ++ { ++ /* ++ * link_mask should be 0xB, but all links are enabled by BIOS. ++ * This entry will be selected if there is no rt1316 amplifier exposed ++ * on link2 since it will fail to match the above entry. ++ */ ++ ++ .link_mask = 0xF, /* 4 active links required */ ++ .links = tgl_3_in_1_sdca_mono, ++ .drv_name = "sof_sdw", ++ .sof_tplg_filename = "sof-tgl-rt711-l0-rt1316-l1-mono-rt714-l3.tplg", ++ }, ++ + { + .link_mask = 0x3, /* rt711 on link 0 and 1 rt1308 on link 1 */ + .links = tgl_hp, +diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c +index 9ecaf6a1e8475..e4aa366d356eb 100644 +--- a/sound/soc/intel/skylake/skl-pcm.c ++++ b/sound/soc/intel/skylake/skl-pcm.c +@@ -1251,7 +1251,6 @@ static int skl_platform_soc_get_time_info( + snd_pcm_gettime(substream->runtime, system_ts); + + nsec = timecounter_read(&hstr->tc); +- nsec = div_u64(nsec, 3); /* can be optimized */ + if (audio_tstamp_config->report_delay) + nsec = skl_adjust_codec_delay(substream, nsec); + +diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c +index fc94314bfc02f..3bdd4931316cd 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-max98090.c ++++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c +@@ -180,6 +180,9 @@ static int mt8173_max98090_dev_probe(struct platform_device *pdev) + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); ++ ++ of_node_put(codec_node); ++ of_node_put(platform_node); + return ret; + } + +diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +index 0f28dc2217c09..390da5bf727eb 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c ++++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c +@@ -218,6 +218,8 @@ static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); ++ ++ of_node_put(platform_node); + return ret; + } + +diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +index 077c6ee067806..c8e4e85e10575 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c ++++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +@@ -285,6 +285,8 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); ++ ++ of_node_put(platform_node); + return ret; + } + +diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c +index c28ebf891cb05..e168d31f44459 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c ++++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c +@@ -323,6 +323,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); ++ ++ of_node_put(platform_node); + return ret; + } + +diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +index a4d26a6fc8492..bda103211e0bd 100644 +--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c ++++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +@@ -781,7 +781,11 @@ static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev) + return ret; + } + +- return devm_snd_soc_register_card(&pdev->dev, card); ++ ret = devm_snd_soc_register_card(&pdev->dev, card); ++ ++ of_node_put(platform_node); ++ of_node_put(hdmi_codec); ++ return ret; + } + + #ifdef CONFIG_OF +diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +index 94dcbd36c8697..c7b10c48c6c22 100644 +--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c ++++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +@@ -780,7 +780,12 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) + __func__, ret); + } + +- return devm_snd_soc_register_card(&pdev->dev, card); ++ ret = devm_snd_soc_register_card(&pdev->dev, card); ++ ++ of_node_put(platform_node); ++ of_node_put(ec_codec); ++ of_node_put(hdmi_codec); ++ return ret; + } + + #ifdef CONFIG_OF +diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +index a606133951b70..24a5d0adec1ba 100644 +--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c ++++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +@@ -1172,7 +1172,11 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) + return ret; + } + +- return devm_snd_soc_register_card(&pdev->dev, card); ++ ret = devm_snd_soc_register_card(&pdev->dev, card); ++ ++ of_node_put(platform_node); ++ of_node_put(hdmi_codec); ++ return ret; + } + + #ifdef CONFIG_OF +diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +index 6635c3f72eccc..2edb40fe27ccb 100644 +--- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c ++++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +@@ -3028,7 +3028,7 @@ static const struct reg_sequence mt8195_afe_reg_defaults[] = { + + static const struct reg_sequence mt8195_cg_patch[] = { + { AUDIO_TOP_CON0, 0xfffffffb }, +- { AUDIO_TOP_CON1, 0xfffffffa }, ++ { AUDIO_TOP_CON1, 0xfffffff8 }, + }; + + static int mt8195_afe_init_registers(struct mtk_base_afe *afe) +diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +index 5d10d2c4c991c..151914c873acd 100644 +--- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c ++++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +@@ -80,8 +80,15 @@ static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { + mtk_dai_pcm_o001_mix, + ARRAY_SIZE(mtk_dai_pcm_o001_mix)), + ++ SND_SOC_DAPM_SUPPLY("PCM_EN", PCM_INTF_CON1, ++ PCM_INTF_CON1_PCM_EN_SHIFT, 0, NULL, 0), ++ + SND_SOC_DAPM_INPUT("PCM1_INPUT"), + SND_SOC_DAPM_OUTPUT("PCM1_OUTPUT"), ++ ++ SND_SOC_DAPM_CLOCK_SUPPLY("aud_asrc11"), ++ SND_SOC_DAPM_CLOCK_SUPPLY("aud_asrc12"), ++ SND_SOC_DAPM_CLOCK_SUPPLY("aud_pcmif"), + }; + + static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { +@@ -97,22 +104,18 @@ static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { + {"PCM1 Playback", NULL, "O000"}, + {"PCM1 Playback", NULL, "O001"}, + ++ {"PCM1 Playback", NULL, "PCM_EN"}, ++ {"PCM1 Playback", NULL, "aud_asrc12"}, ++ {"PCM1 Playback", NULL, "aud_pcmif"}, ++ ++ {"PCM1 Capture", NULL, "PCM_EN"}, ++ {"PCM1 Capture", NULL, "aud_asrc11"}, ++ {"PCM1 Capture", NULL, "aud_pcmif"}, ++ + {"PCM1_OUTPUT", NULL, "PCM1 Playback"}, + {"PCM1 Capture", NULL, "PCM1_INPUT"}, + }; + +-static void mtk_dai_pcm_enable(struct mtk_base_afe *afe) +-{ +- regmap_update_bits(afe->regmap, PCM_INTF_CON1, +- PCM_INTF_CON1_PCM_EN, PCM_INTF_CON1_PCM_EN); +-} +- +-static void mtk_dai_pcm_disable(struct mtk_base_afe *afe) +-{ +- regmap_update_bits(afe->regmap, PCM_INTF_CON1, +- PCM_INTF_CON1_PCM_EN, 0x0); +-} +- + static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { +@@ -207,54 +210,22 @@ static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, + } + + /* dai ops */ +-static int mtk_dai_pcm_startup(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai) +-{ +- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); +- struct mt8195_afe_private *afe_priv = afe->platform_priv; +- +- if (dai->component->active) +- return 0; +- +- mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]); +- mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]); +- mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]); +- +- return 0; +-} +- +-static void mtk_dai_pcm_shutdown(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai) +-{ +- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); +- struct mt8195_afe_private *afe_priv = afe->platform_priv; +- +- if (dai->component->active) +- return; +- +- mtk_dai_pcm_disable(afe); +- +- mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]); +- mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]); +- mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]); +-} +- + static int mtk_dai_pcm_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { +- struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); +- int ret = 0; ++ int ret; + +- if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) && +- snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) ++ dev_dbg(dai->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n", ++ __func__, dai->id, substream->stream, ++ dai->playback_widget->active, dai->capture_widget->active); ++ ++ if (dai->playback_widget->active || dai->capture_widget->active) + return 0; + + ret = mtk_dai_pcm_configure(substream, dai); + if (ret) + return ret; + +- mtk_dai_pcm_enable(afe); +- + return 0; + } + +@@ -316,8 +287,6 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) + } + + static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { +- .startup = mtk_dai_pcm_startup, +- .shutdown = mtk_dai_pcm_shutdown, + .prepare = mtk_dai_pcm_prepare, + .set_fmt = mtk_dai_pcm_set_fmt, + }; +diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c +index de09f67c04502..a3fa8efc8f81c 100644 +--- a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c ++++ b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c +@@ -1040,8 +1040,10 @@ static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev) + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) ++ if (!priv) { ++ of_node_put(platform_node); + return -ENOMEM; ++ } + + snd_soc_card_set_drvdata(card, priv); + +@@ -1049,6 +1051,8 @@ static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev) + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); ++ ++ of_node_put(platform_node); + return ret; + } + +diff --git a/sound/soc/mediatek/mt8195/mt8195-reg.h b/sound/soc/mediatek/mt8195/mt8195-reg.h +index d06f9cf85a4ec..d3871353db415 100644 +--- a/sound/soc/mediatek/mt8195/mt8195-reg.h ++++ b/sound/soc/mediatek/mt8195/mt8195-reg.h +@@ -2550,6 +2550,7 @@ + #define PCM_INTF_CON1_PCM_FMT(x) (((x) & 0x3) << 1) + #define PCM_INTF_CON1_PCM_FMT_MASK (0x3 << 1) + #define PCM_INTF_CON1_PCM_EN BIT(0) ++#define PCM_INTF_CON1_PCM_EN_SHIFT 0 + + /* PCM_INTF_CON2 */ + #define PCM_INTF_CON2_CLK_DOMAIN_SEL(x) (((x) & 0x3) << 23) +diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c +index 9322245521463..67729de41a73e 100644 +--- a/sound/soc/meson/aiu-encoder-i2s.c ++++ b/sound/soc/meson/aiu-encoder-i2s.c +@@ -18,7 +18,6 @@ + #define AIU_RST_SOFT_I2S_FAST BIT(0) + + #define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2) +-#define AIU_I2S_MISC_HOLD_EN BIT(2) + #define AIU_CLK_CTRL_I2S_DIV_EN BIT(0) + #define AIU_CLK_CTRL_I2S_DIV GENMASK(3, 2) + #define AIU_CLK_CTRL_AOCLK_INVERT BIT(6) +@@ -36,37 +35,6 @@ static void aiu_encoder_i2s_divider_enable(struct snd_soc_component *component, + enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0); + } + +-static void aiu_encoder_i2s_hold(struct snd_soc_component *component, +- bool enable) +-{ +- snd_soc_component_update_bits(component, AIU_I2S_MISC, +- AIU_I2S_MISC_HOLD_EN, +- enable ? AIU_I2S_MISC_HOLD_EN : 0); +-} +- +-static int aiu_encoder_i2s_trigger(struct snd_pcm_substream *substream, int cmd, +- struct snd_soc_dai *dai) +-{ +- struct snd_soc_component *component = dai->component; +- +- switch (cmd) { +- case SNDRV_PCM_TRIGGER_START: +- case SNDRV_PCM_TRIGGER_RESUME: +- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- aiu_encoder_i2s_hold(component, false); +- return 0; +- +- case SNDRV_PCM_TRIGGER_STOP: +- case SNDRV_PCM_TRIGGER_SUSPEND: +- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- aiu_encoder_i2s_hold(component, true); +- return 0; +- +- default: +- return -EINVAL; +- } +-} +- + static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component, + struct snd_pcm_hw_params *params) + { +@@ -353,7 +321,6 @@ static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream, + } + + const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = { +- .trigger = aiu_encoder_i2s_trigger, + .hw_params = aiu_encoder_i2s_hw_params, + .hw_free = aiu_encoder_i2s_hw_free, + .set_fmt = aiu_encoder_i2s_set_fmt, +diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c +index 2388a2d0b3a6c..57e6e7160d2f2 100644 +--- a/sound/soc/meson/aiu-fifo-i2s.c ++++ b/sound/soc/meson/aiu-fifo-i2s.c +@@ -20,6 +20,8 @@ + #define AIU_MEM_I2S_CONTROL_MODE_16BIT BIT(6) + #define AIU_MEM_I2S_BUF_CNTL_INIT BIT(0) + #define AIU_RST_SOFT_I2S_FAST BIT(0) ++#define AIU_I2S_MISC_HOLD_EN BIT(2) ++#define AIU_I2S_MISC_FORCE_LEFT_RIGHT BIT(4) + + #define AIU_FIFO_I2S_BLOCK 256 + +@@ -90,6 +92,10 @@ static int aiu_fifo_i2s_hw_params(struct snd_pcm_substream *substream, + unsigned int val; + int ret; + ++ snd_soc_component_update_bits(component, AIU_I2S_MISC, ++ AIU_I2S_MISC_HOLD_EN, ++ AIU_I2S_MISC_HOLD_EN); ++ + ret = aiu_fifo_hw_params(substream, params, dai); + if (ret) + return ret; +@@ -117,6 +123,19 @@ static int aiu_fifo_i2s_hw_params(struct snd_pcm_substream *substream, + snd_soc_component_update_bits(component, AIU_MEM_I2S_MASKS, + AIU_MEM_I2S_MASKS_IRQ_BLOCK, val); + ++ /* ++ * Most (all?) supported SoCs have this bit set by default. The vendor ++ * driver however sets it manually (depending on the version either ++ * while un-setting AIU_I2S_MISC_HOLD_EN or right before that). Follow ++ * the same approach for consistency with the vendor driver. ++ */ ++ snd_soc_component_update_bits(component, AIU_I2S_MISC, ++ AIU_I2S_MISC_FORCE_LEFT_RIGHT, ++ AIU_I2S_MISC_FORCE_LEFT_RIGHT); ++ ++ snd_soc_component_update_bits(component, AIU_I2S_MISC, ++ AIU_I2S_MISC_HOLD_EN, 0); ++ + return 0; + } + +diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c +index 4ad23267cace5..d67ff4cdabd5a 100644 +--- a/sound/soc/meson/aiu-fifo.c ++++ b/sound/soc/meson/aiu-fifo.c +@@ -5,6 +5,7 @@ + + #include <linux/bitfield.h> + #include <linux/clk.h> ++#include <linux/dma-mapping.h> + #include <sound/pcm_params.h> + #include <sound/soc.h> + #include <sound/soc-dai.h> +@@ -179,6 +180,11 @@ int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, + struct snd_card *card = rtd->card->snd_card; + struct aiu_fifo *fifo = dai->playback_dma_data; + size_t size = fifo->pcm->buffer_bytes_max; ++ int ret; ++ ++ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); ++ if (ret) ++ return ret; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); +diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c +index a59e9d20cb46b..4b1773c1fb95f 100644 +--- a/sound/soc/qcom/lpass-platform.c ++++ b/sound/soc/qcom/lpass-platform.c +@@ -524,7 +524,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, + return -EINVAL; + } + +- ret = regmap_update_bits(map, reg_irqclr, val_irqclr, val_irqclr); ++ ret = regmap_write_bits(map, reg_irqclr, val_irqclr, val_irqclr); + if (ret) { + dev_err(soc_runtime->dev, "error writing to irqclear reg: %d\n", ret); + return ret; +@@ -665,7 +665,7 @@ static irqreturn_t lpass_dma_interrupt_handler( + return -EINVAL; + } + if (interrupts & LPAIF_IRQ_PER(chan)) { +- rv = regmap_update_bits(map, reg, mask, (LPAIF_IRQ_PER(chan) | val)); ++ rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_PER(chan) | val)); + if (rv) { + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", rv); +@@ -676,7 +676,7 @@ static irqreturn_t lpass_dma_interrupt_handler( + } + + if (interrupts & LPAIF_IRQ_XRUN(chan)) { +- rv = regmap_update_bits(map, reg, mask, (LPAIF_IRQ_XRUN(chan) | val)); ++ rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_XRUN(chan) | val)); + if (rv) { + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", rv); +@@ -688,7 +688,7 @@ static irqreturn_t lpass_dma_interrupt_handler( + } + + if (interrupts & LPAIF_IRQ_ERR(chan)) { +- rv = regmap_update_bits(map, reg, mask, (LPAIF_IRQ_ERR(chan) | val)); ++ rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_ERR(chan) | val)); + if (rv) { + dev_err(soc_runtime->dev, + "error writing to irqclear reg: %d\n", rv); +diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c +index 46f365528d501..b74b67720ef43 100644 +--- a/sound/soc/qcom/qdsp6/q6asm-dai.c ++++ b/sound/soc/qcom/qdsp6/q6asm-dai.c +@@ -269,9 +269,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, + + if (ret < 0) { + dev_err(dev, "%s: q6asm_open_write failed\n", __func__); +- q6asm_audio_client_free(prtd->audio_client); +- prtd->audio_client = NULL; +- return -ENOMEM; ++ goto open_err; + } + + prtd->session_id = q6asm_get_session_id(prtd->audio_client); +@@ -279,7 +277,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, + prtd->session_id, substream->stream); + if (ret) { + dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret); +- return ret; ++ goto routing_err; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +@@ -301,10 +299,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, + } + if (ret < 0) + dev_info(dev, "%s: CMD Format block failed\n", __func__); ++ else ++ prtd->state = Q6ASM_STREAM_RUNNING; + +- prtd->state = Q6ASM_STREAM_RUNNING; ++ return ret; + +- return 0; ++routing_err: ++ q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); ++open_err: ++ q6asm_unmap_memory_regions(substream->stream, prtd->audio_client); ++ q6asm_audio_client_free(prtd->audio_client); ++ prtd->audio_client = NULL; ++ ++ return ret; + } + + static int q6asm_dai_trigger(struct snd_soc_component *component, +diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c +index 3390ebef9549d..18c90bb4922be 100644 +--- a/sound/soc/qcom/qdsp6/q6routing.c ++++ b/sound/soc/qcom/qdsp6/q6routing.c +@@ -492,9 +492,15 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, + struct session_data *session = &data->sessions[session_id]; + + if (ucontrol->value.integer.value[0]) { ++ if (session->port_id == be_id) ++ return 0; ++ + session->port_id = be_id; + snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update); + } else { ++ if (session->port_id == -1 || session->port_id != be_id) ++ return 0; ++ + session->port_id = -1; + snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update); + } +diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c +index 66bcc2f97544b..c3f1b054e2389 100644 +--- a/sound/soc/samsung/idma.c ++++ b/sound/soc/samsung/idma.c +@@ -360,6 +360,8 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream) + buf->addr = idma.lp_tx_addr; + buf->bytes = idma_hardware.buffer_bytes_max; + buf->area = (unsigned char * __force)ioremap(buf->addr, buf->bytes); ++ if (!buf->area) ++ return -ENOMEM; + + return 0; + } +diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c +index 978bd0406729a..6a8fe0da7670b 100644 +--- a/sound/soc/sh/rcar/core.c ++++ b/sound/soc/sh/rcar/core.c +@@ -1225,6 +1225,7 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name + if (i < 0) { + dev_err(dev, "strange node numbering (%s)", + of_node_full_name(node)); ++ of_node_put(np); + return 0; + } + i++; +diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c +index 16c6e0265749b..03e0d4eca7815 100644 +--- a/sound/soc/sh/rcar/dma.c ++++ b/sound/soc/sh/rcar/dma.c +@@ -102,7 +102,7 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, + struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); + + if (dmaen->chan) +- dmaengine_terminate_sync(dmaen->chan); ++ dmaengine_terminate_async(dmaen->chan); + + return 0; + } +diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c +index 59d07648a7e7f..0479bb0005abd 100644 +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -2557,8 +2557,13 @@ static struct snd_soc_dapm_widget *dapm_find_widget( + return NULL; + } + +-static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, +- const char *pin, int status) ++/* ++ * set the DAPM pin status: ++ * returns 1 when the value has been updated, 0 when unchanged, or a negative ++ * error code; called from kcontrol put callback ++ */ ++static int __snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, ++ const char *pin, int status) + { + struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true); + int ret = 0; +@@ -2584,6 +2589,18 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, + return ret; + } + ++/* ++ * similar as __snd_soc_dapm_set_pin(), but returns 0 when successful; ++ * called from several API functions below ++ */ ++static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm, ++ const char *pin, int status) ++{ ++ int ret = __snd_soc_dapm_set_pin(dapm, pin, status); ++ ++ return ret < 0 ? ret : 0; ++} ++ + /** + * snd_soc_dapm_sync_unlocked - scan and power dapm paths + * @dapm: DAPM context +@@ -3587,10 +3604,10 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, + const char *pin = (const char *)kcontrol->private_value; + int ret; + +- if (ucontrol->value.integer.value[0]) +- ret = snd_soc_dapm_enable_pin(&card->dapm, pin); +- else +- ret = snd_soc_dapm_disable_pin(&card->dapm, pin); ++ mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); ++ ret = __snd_soc_dapm_set_pin(&card->dapm, pin, ++ !!ucontrol->value.integer.value[0]); ++ mutex_unlock(&card->dapm_mutex); + + snd_soc_dapm_sync(&card->dapm); + return ret; +diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c +index 08eaa9ddf191e..ee3782ecd7e3a 100644 +--- a/sound/soc/soc-ops.c ++++ b/sound/soc/soc-ops.c +@@ -308,7 +308,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, + unsigned int sign_bit = mc->sign_bit; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; +- int err; ++ int err, ret; + bool type_2r = false; + unsigned int val2 = 0; + unsigned int val, val_mask; +@@ -316,13 +316,27 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + +- val = ((ucontrol->value.integer.value[0] + min) & mask); ++ val = ucontrol->value.integer.value[0]; ++ if (mc->platform_max && ((int)val + min) > mc->platform_max) ++ return -EINVAL; ++ if (val > max - min) ++ return -EINVAL; ++ if (val < 0) ++ return -EINVAL; ++ val = (val + min) & mask; + if (invert) + val = max - val; + val_mask = mask << shift; + val = val << shift; + if (snd_soc_volsw_is_stereo(mc)) { +- val2 = ((ucontrol->value.integer.value[1] + min) & mask); ++ val2 = ucontrol->value.integer.value[1]; ++ if (mc->platform_max && ((int)val2 + min) > mc->platform_max) ++ return -EINVAL; ++ if (val2 > max - min) ++ return -EINVAL; ++ if (val2 < 0) ++ return -EINVAL; ++ val2 = (val2 + min) & mask; + if (invert) + val2 = max - val2; + if (reg == reg2) { +@@ -336,12 +350,18 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, + err = snd_soc_component_update_bits(component, reg, val_mask, val); + if (err < 0) + return err; ++ ret = err; + +- if (type_2r) ++ if (type_2r) { + err = snd_soc_component_update_bits(component, reg2, val_mask, +- val2); ++ val2); ++ /* Don't discard any error code or drop change flag */ ++ if (ret == 0 || err < 0) { ++ ret = err; ++ } ++ } + +- return err; ++ return ret; + } + EXPORT_SYMBOL_GPL(snd_soc_put_volsw); + +@@ -407,15 +427,24 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, + int min = mc->min; + unsigned int mask = (1U << (fls(min + max) - 1)) - 1; + int err = 0; ++ int ret; + unsigned int val, val_mask; + ++ val = ucontrol->value.integer.value[0]; ++ if (mc->platform_max && val > mc->platform_max) ++ return -EINVAL; ++ if (val > max - min) ++ return -EINVAL; ++ if (val < 0) ++ return -EINVAL; + val_mask = mask << shift; +- val = (ucontrol->value.integer.value[0] + min) & mask; ++ val = (val + min) & mask; + val = val << shift; + + err = snd_soc_component_update_bits(component, reg, val_mask, val); + if (err < 0) + return err; ++ ret = err; + + if (snd_soc_volsw_is_stereo(mc)) { + unsigned int val2; +@@ -426,6 +455,11 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, + + err = snd_soc_component_update_bits(component, reg2, val_mask, + val2); ++ ++ /* Don't discard any error code or drop change flag */ ++ if (ret == 0 || err < 0) { ++ ret = err; ++ } + } + return err; + } +@@ -485,7 +519,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val, val_mask; +- int ret; ++ int err, ret; + + if (invert) + val = (max - ucontrol->value.integer.value[0]) & mask; +@@ -494,9 +528,10 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, + val_mask = mask << shift; + val = val << shift; + +- ret = snd_soc_component_update_bits(component, reg, val_mask, val); +- if (ret < 0) +- return ret; ++ err = snd_soc_component_update_bits(component, reg, val_mask, val); ++ if (err < 0) ++ return err; ++ ret = err; + + if (snd_soc_volsw_is_stereo(mc)) { + if (invert) +@@ -506,8 +541,12 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, + val_mask = mask << shift; + val = val << shift; + +- ret = snd_soc_component_update_bits(component, rreg, val_mask, ++ err = snd_soc_component_update_bits(component, rreg, val_mask, + val); ++ /* Don't discard any error code or drop change flag */ ++ if (ret == 0 || err < 0) { ++ ret = err; ++ } + } + + return ret; +@@ -856,8 +895,11 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, + unsigned long mask = (1UL<<mc->nbits)-1; + long max = mc->max; + long val = ucontrol->value.integer.value[0]; ++ int ret = 0; + unsigned int i; + ++ if (val < mc->min || val > mc->max) ++ return -EINVAL; + if (invert) + val = max - val; + val &= mask; +@@ -868,9 +910,11 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, + regmask, regval); + if (err < 0) + return err; ++ if (err > 0) ++ ret = err; + } + +- return 0; ++ return ret; + } + EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); + +diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c +index f6e5ac3e03140..7459956d62b99 100644 +--- a/sound/soc/soc-topology.c ++++ b/sound/soc/soc-topology.c +@@ -2674,6 +2674,7 @@ EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load); + /* remove dynamic controls from the component driver */ + int snd_soc_tplg_component_remove(struct snd_soc_component *comp) + { ++ struct snd_card *card = comp->card->snd_card; + struct snd_soc_dobj *dobj, *next_dobj; + int pass = SOC_TPLG_PASS_END; + +@@ -2681,6 +2682,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp) + while (pass >= SOC_TPLG_PASS_START) { + + /* remove mixer controls */ ++ down_write(&card->controls_rwsem); + list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, + list) { + +@@ -2719,6 +2721,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp) + break; + } + } ++ up_write(&card->controls_rwsem); + pass--; + } + +diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c +index 30025d3c16b6e..0862ff8b66273 100644 +--- a/sound/soc/sof/intel/hda-bus.c ++++ b/sound/soc/sof/intel/hda-bus.c +@@ -10,6 +10,8 @@ + #include <linux/io.h> + #include <sound/hdaudio.h> + #include <sound/hda_i915.h> ++#include <sound/hda_codec.h> ++#include <sound/hda_register.h> + #include "../sof-priv.h" + #include "hda.h" + +@@ -21,6 +23,18 @@ + #endif + + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) ++static void update_codec_wake_enable(struct hdac_bus *bus, unsigned int addr, bool link_power) ++{ ++ unsigned int mask = snd_hdac_chip_readw(bus, WAKEEN); ++ ++ if (link_power) ++ mask &= ~BIT(addr); ++ else ++ mask |= BIT(addr); ++ ++ snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask); ++} ++ + static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable) + { + struct hdac_bus *bus = codec->bus; +@@ -41,6 +55,9 @@ static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable) + */ + if (codec->addr == HDA_IDISP_ADDR && !enable) + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); ++ ++ /* WAKEEN needs to be set for disabled links */ ++ update_codec_wake_enable(bus, codec->addr, enable); + } + + static const struct hdac_bus_ops bus_core_ops = { +diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c +index c1f9f0f584647..6704dbcd101cd 100644 +--- a/sound/soc/sof/intel/hda-dai.c ++++ b/sound/soc/sof/intel/hda-dai.c +@@ -68,6 +68,7 @@ static struct hdac_ext_stream * + return NULL; + } + ++ spin_lock_irq(&bus->reg_lock); + list_for_each_entry(stream, &bus->stream_list, list) { + struct hdac_ext_stream *hstream = + stream_to_hdac_ext_stream(stream); +@@ -107,12 +108,12 @@ static struct hdac_ext_stream * + * is updated in snd_hdac_ext_stream_decouple(). + */ + if (!res->decoupled) +- snd_hdac_ext_stream_decouple(bus, res, true); +- spin_lock_irq(&bus->reg_lock); ++ snd_hdac_ext_stream_decouple_locked(bus, res, true); ++ + res->link_locked = 1; + res->link_substream = substream; +- spin_unlock_irq(&bus->reg_lock); + } ++ spin_unlock_irq(&bus->reg_lock); + + return res; + } +diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c +index 623cf291e2074..262a70791a8f8 100644 +--- a/sound/soc/sof/intel/hda-dsp.c ++++ b/sound/soc/sof/intel/hda-dsp.c +@@ -623,8 +623,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) + hda_dsp_ipc_int_disable(sdev); + + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +- if (runtime_suspend) +- hda_codec_jack_wake_enable(sdev, true); ++ hda_codec_jack_wake_enable(sdev, runtime_suspend); + + /* power down all hda link */ + snd_hdac_ext_bus_link_power_down_all(bus); +diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c +index f60e2c57d3d0c..ef92cca7ae01e 100644 +--- a/sound/soc/sof/intel/hda.c ++++ b/sound/soc/sof/intel/hda.c +@@ -696,6 +696,20 @@ skip_soundwire: + return 0; + } + ++static void hda_check_for_state_change(struct snd_sof_dev *sdev) ++{ ++#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) ++ struct hdac_bus *bus = sof_to_bus(sdev); ++ unsigned int codec_mask; ++ ++ codec_mask = snd_hdac_chip_readw(bus, STATESTS); ++ if (codec_mask) { ++ hda_codec_jack_check(sdev); ++ snd_hdac_chip_writew(bus, STATESTS, codec_mask); ++ } ++#endif ++} ++ + static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context) + { + struct snd_sof_dev *sdev = context; +@@ -737,6 +751,8 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) + if (hda_sdw_check_wakeen_irq(sdev)) + hda_sdw_process_wakeen(sdev); + ++ hda_check_for_state_change(sdev); ++ + /* enable GIE interrupt */ + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_INTCTL, +diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c +index d04ce84fe7cc2..beb2fb3cd0141 100644 +--- a/sound/soc/sof/intel/pci-tgl.c ++++ b/sound/soc/sof/intel/pci-tgl.c +@@ -117,8 +117,12 @@ static const struct pci_device_id sof_pci_ids[] = { + .driver_data = (unsigned long)&adls_desc}, + { PCI_DEVICE(0x8086, 0x51c8), /* ADL-P */ + .driver_data = (unsigned long)&adl_desc}, ++ { PCI_DEVICE(0x8086, 0x51cd), /* ADL-P */ ++ .driver_data = (unsigned long)&adl_desc}, + { PCI_DEVICE(0x8086, 0x51cc), /* ADL-M */ + .driver_data = (unsigned long)&adl_desc}, ++ { PCI_DEVICE(0x8086, 0x54c8), /* ADL-N */ ++ .driver_data = (unsigned long)&adl_desc}, + { 0, } + }; + MODULE_DEVICE_TABLE(pci, sof_pci_ids); +diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c +index cc9585bfa4e9f..1bb2dcf37ffe9 100644 +--- a/sound/soc/sof/topology.c ++++ b/sound/soc/sof/topology.c +@@ -2598,6 +2598,15 @@ static int sof_widget_unload(struct snd_soc_component *scomp, + + /* power down the pipeline schedule core */ + pipeline = swidget->private; ++ ++ /* ++ * Runtime PM should still function normally if topology loading fails and ++ * it's components are unloaded. Do not power down the primary core so that the ++ * CTX_SAVE IPC can succeed during runtime suspend. ++ */ ++ if (pipeline->core == SOF_DSP_PRIMARY_CORE) ++ break; ++ + ret = snd_sof_dsp_core_power_down(sdev, 1 << pipeline->core); + if (ret < 0) + dev_err(scomp->dev, "error: powering down pipeline schedule core %d\n", +diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c +index 6254bacad6eb7..717f45a83445c 100644 +--- a/sound/soc/stm/stm32_i2s.c ++++ b/sound/soc/stm/stm32_i2s.c +@@ -700,7 +700,7 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, + if (ret < 0) + return ret; + +- nb_bits = frame_len * ((cgfr & I2S_CGFR_CHLEN) + 1); ++ nb_bits = frame_len * (FIELD_GET(I2S_CGFR_CHLEN, cgfr) + 1); + ret = stm32_i2s_calc_clk_div(i2s, i2s_clock_rate, + (nb_bits * rate)); + if (ret) +diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c +index 8ee9a77bd83d3..a74c980ee7753 100644 +--- a/sound/soc/tegra/tegra186_dspk.c ++++ b/sound/soc/tegra/tegra186_dspk.c +@@ -26,51 +26,162 @@ static const struct reg_default tegra186_dspk_reg_defaults[] = { + { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, + }; + +-static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol, ++static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); + +- if (strstr(kcontrol->id.name, "FIFO Threshold")) +- ucontrol->value.integer.value[0] = dspk->rx_fifo_th; +- else if (strstr(kcontrol->id.name, "OSR Value")) +- ucontrol->value.integer.value[0] = dspk->osr_val; +- else if (strstr(kcontrol->id.name, "LR Polarity Select")) +- ucontrol->value.integer.value[0] = dspk->lrsel; +- else if (strstr(kcontrol->id.name, "Channel Select")) +- ucontrol->value.integer.value[0] = dspk->ch_sel; +- else if (strstr(kcontrol->id.name, "Mono To Stereo")) +- ucontrol->value.integer.value[0] = dspk->mono_to_stereo; +- else if (strstr(kcontrol->id.name, "Stereo To Mono")) +- ucontrol->value.integer.value[0] = dspk->stereo_to_mono; ++ ucontrol->value.integer.value[0] = dspk->rx_fifo_th; + + return 0; + } + +-static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, ++static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); +- int val = ucontrol->value.integer.value[0]; +- +- if (strstr(kcontrol->id.name, "FIFO Threshold")) +- dspk->rx_fifo_th = val; +- else if (strstr(kcontrol->id.name, "OSR Value")) +- dspk->osr_val = val; +- else if (strstr(kcontrol->id.name, "LR Polarity Select")) +- dspk->lrsel = val; +- else if (strstr(kcontrol->id.name, "Channel Select")) +- dspk->ch_sel = val; +- else if (strstr(kcontrol->id.name, "Mono To Stereo")) +- dspk->mono_to_stereo = val; +- else if (strstr(kcontrol->id.name, "Stereo To Mono")) +- dspk->stereo_to_mono = val; ++ int value = ucontrol->value.integer.value[0]; ++ ++ if (value == dspk->rx_fifo_th) ++ return 0; ++ ++ dspk->rx_fifo_th = value; ++ ++ return 1; ++} ++ ++static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ ++ ucontrol->value.enumerated.item[0] = dspk->osr_val; + + return 0; + } + ++static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dspk->osr_val) ++ return 0; ++ ++ dspk->osr_val = value; ++ ++ return 1; ++} ++ ++static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ ++ ucontrol->value.enumerated.item[0] = dspk->lrsel; ++ ++ return 0; ++} ++ ++static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dspk->lrsel) ++ return 0; ++ ++ dspk->lrsel = value; ++ ++ return 1; ++} ++ ++static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ ++ ucontrol->value.enumerated.item[0] = dspk->ch_sel; ++ ++ return 0; ++} ++ ++static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dspk->ch_sel) ++ return 0; ++ ++ dspk->ch_sel = value; ++ ++ return 1; ++} ++ ++static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ ++ ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo; ++ ++ return 0; ++} ++ ++static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dspk->mono_to_stereo) ++ return 0; ++ ++ dspk->mono_to_stereo = value; ++ ++ return 1; ++} ++ ++static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ ++ ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono; ++ ++ return 0; ++} ++ ++static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); ++ struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dspk->stereo_to_mono) ++ return 0; ++ ++ dspk->stereo_to_mono = value; ++ ++ return 1; ++} ++ + static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) + { + struct tegra186_dspk *dspk = dev_get_drvdata(dev); +@@ -279,17 +390,19 @@ static const struct soc_enum tegra186_dspk_lrsel_enum = + static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { + SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, + TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, +- tegra186_dspk_get_control, tegra186_dspk_put_control), ++ tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th), + SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, +- tegra186_dspk_get_control, tegra186_dspk_put_control), ++ tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val), + SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, +- tegra186_dspk_get_control, tegra186_dspk_put_control), ++ tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel), + SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, +- tegra186_dspk_get_control, tegra186_dspk_put_control), ++ tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel), + SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, +- tegra186_dspk_get_control, tegra186_dspk_put_control), ++ tegra186_dspk_get_mono_to_stereo, ++ tegra186_dspk_put_mono_to_stereo), + SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, +- tegra186_dspk_get_control, tegra186_dspk_put_control), ++ tegra186_dspk_get_stereo_to_mono, ++ tegra186_dspk_put_stereo_to_mono), + }; + + static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { +diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c +index bcccdf3ddc528..1a2e868a62209 100644 +--- a/sound/soc/tegra/tegra210_admaif.c ++++ b/sound/soc/tegra/tegra210_admaif.c +@@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { + .trigger = tegra_admaif_trigger, + }; + +-static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) ++static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); ++ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; ++ ++ ucontrol->value.enumerated.item[0] = ++ admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; ++ ++ return 0; ++} ++ ++static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); ++ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]) ++ return 0; ++ ++ admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; ++ ++ return 1; ++} ++ ++static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); ++ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; ++ ++ ucontrol->value.enumerated.item[0] = ++ admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; ++ ++ return 0; ++} ++ ++static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]) ++ return 0; ++ ++ admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; ++ ++ return 1; ++} ++ ++static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); +- long *uctl_val = &ucontrol->value.integer.value[0]; ++ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + +- if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) +- *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; +- else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) +- *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; +- else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) +- *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; +- else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) +- *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; ++ ucontrol->value.enumerated.item[0] = ++ admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; + + return 0; + } + +-static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) ++static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]) ++ return 0; ++ ++ admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; ++ ++ return 1; ++} ++ ++static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); +- int value = ucontrol->value.integer.value[0]; ++ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; + +- if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) +- admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; +- else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) +- admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; +- else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) +- admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; +- else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) +- admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; ++ ucontrol->value.enumerated.item[0] = ++ admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; + + return 0; + } + ++static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); ++ struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]) ++ return 0; ++ ++ admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; ++ ++ return 1; ++} ++ + static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) + { + struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); +@@ -559,17 +635,21 @@ static const char * const tegra_admaif_mono_conv_text[] = { + } + + #define TEGRA_ADMAIF_CIF_CTRL(reg) \ +- NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ +- tegra_admaif_get_control, tegra_admaif_put_control, \ ++ NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \ ++ tegra210_admaif_pget_mono_to_stereo, \ ++ tegra210_admaif_pput_mono_to_stereo, \ + tegra_admaif_mono_conv_text), \ +- NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ +- tegra_admaif_get_control, tegra_admaif_put_control, \ ++ NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \ ++ tegra210_admaif_pget_stereo_to_mono, \ ++ tegra210_admaif_pput_stereo_to_mono, \ + tegra_admaif_stereo_conv_text), \ +- NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ +- tegra_admaif_get_control, tegra_admaif_put_control, \ ++ NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ ++ tegra210_admaif_cget_mono_to_stereo, \ ++ tegra210_admaif_cput_mono_to_stereo, \ + tegra_admaif_mono_conv_text), \ +- NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ +- tegra_admaif_get_control, tegra_admaif_put_control, \ ++ NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ ++ tegra210_admaif_cget_stereo_to_mono, \ ++ tegra210_admaif_cput_stereo_to_mono, \ + tegra_admaif_stereo_conv_text) + + static struct snd_kcontrol_new tegra210_admaif_controls[] = { +diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c +index 66287a7c9865d..1b2f7cb8c6adc 100644 +--- a/sound/soc/tegra/tegra210_ahub.c ++++ b/sound/soc/tegra/tegra210_ahub.c +@@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, + unsigned int *item = uctl->value.enumerated.item; + unsigned int value = e->values[item[0]]; + unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; ++ int change = 0; + + if (item[0] >= e->items) + return -EINVAL; +@@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, + + /* Update widget power if state has changed */ + if (snd_soc_component_test_bits(cmpnt, update[i].reg, +- update[i].mask, update[i].val)) +- snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, +- &update[i]); ++ update[i].mask, ++ update[i].val)) ++ change |= snd_soc_dapm_mux_update_power(dapm, kctl, ++ item[0], e, ++ &update[i]); + } + +- return 0; ++ return change; + } + + static struct snd_soc_dai_driver tegra210_ahub_dais[] = { +diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c +index b096478cd2ef0..db95794530f46 100644 +--- a/sound/soc/tegra/tegra210_dmic.c ++++ b/sound/soc/tegra/tegra210_dmic.c +@@ -156,51 +156,162 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, + return 0; + } + +-static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, ++static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ ++ ucontrol->value.integer.value[0] = dmic->boost_gain; ++ ++ return 0; ++} ++ ++static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ int value = ucontrol->value.integer.value[0]; ++ ++ if (value == dmic->boost_gain) ++ return 0; ++ ++ dmic->boost_gain = value; ++ ++ return 1; ++} ++ ++static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ ++ ucontrol->value.enumerated.item[0] = dmic->ch_select; ++ ++ return 0; ++} ++ ++static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dmic->ch_select) ++ return 0; ++ ++ dmic->ch_select = value; ++ ++ return 1; ++} ++ ++static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ ++ ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo; ++ ++ return 0; ++} ++ ++static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dmic->mono_to_stereo) ++ return 0; ++ ++ dmic->mono_to_stereo = value; ++ ++ return 1; ++} ++ ++static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ ++ ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono; ++ ++ return 0; ++} ++ ++static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dmic->stereo_to_mono) ++ return 0; ++ ++ dmic->stereo_to_mono = value; ++ ++ return 1; ++} ++ ++static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); + +- if (strstr(kcontrol->id.name, "Boost Gain Volume")) +- ucontrol->value.integer.value[0] = dmic->boost_gain; +- else if (strstr(kcontrol->id.name, "Channel Select")) +- ucontrol->value.integer.value[0] = dmic->ch_select; +- else if (strstr(kcontrol->id.name, "Mono To Stereo")) +- ucontrol->value.integer.value[0] = dmic->mono_to_stereo; +- else if (strstr(kcontrol->id.name, "Stereo To Mono")) +- ucontrol->value.integer.value[0] = dmic->stereo_to_mono; +- else if (strstr(kcontrol->id.name, "OSR Value")) +- ucontrol->value.integer.value[0] = dmic->osr_val; +- else if (strstr(kcontrol->id.name, "LR Polarity Select")) +- ucontrol->value.integer.value[0] = dmic->lrsel; ++ ucontrol->value.enumerated.item[0] = dmic->osr_val; + + return 0; + } + +-static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, ++static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); +- int value = ucontrol->value.integer.value[0]; ++ unsigned int value = ucontrol->value.enumerated.item[0]; + +- if (strstr(kcontrol->id.name, "Boost Gain Volume")) +- dmic->boost_gain = value; +- else if (strstr(kcontrol->id.name, "Channel Select")) +- dmic->ch_select = ucontrol->value.integer.value[0]; +- else if (strstr(kcontrol->id.name, "Mono To Stereo")) +- dmic->mono_to_stereo = value; +- else if (strstr(kcontrol->id.name, "Stereo To Mono")) +- dmic->stereo_to_mono = value; +- else if (strstr(kcontrol->id.name, "OSR Value")) +- dmic->osr_val = value; +- else if (strstr(kcontrol->id.name, "LR Polarity Select")) +- dmic->lrsel = value; ++ if (value == dmic->osr_val) ++ return 0; ++ ++ dmic->osr_val = value; ++ ++ return 1; ++} ++ ++static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ ++ ucontrol->value.enumerated.item[0] = dmic->lrsel; + + return 0; + } + ++static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == dmic->lrsel) ++ return 0; ++ ++ dmic->lrsel = value; ++ ++ return 1; ++} ++ + static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { + .hw_params = tegra210_dmic_hw_params, + }; +@@ -287,19 +398,22 @@ static const struct soc_enum tegra210_dmic_lrsel_enum = + + static const struct snd_kcontrol_new tegra210_dmic_controls[] = { + SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, +- tegra210_dmic_get_control, tegra210_dmic_put_control), ++ tegra210_dmic_get_boost_gain, ++ tegra210_dmic_put_boost_gain), + SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, +- tegra210_dmic_get_control, tegra210_dmic_put_control), ++ tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select), + SOC_ENUM_EXT("Mono To Stereo", +- tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, +- tegra210_dmic_put_control), ++ tegra210_dmic_mono_conv_enum, ++ tegra210_dmic_get_mono_to_stereo, ++ tegra210_dmic_put_mono_to_stereo), + SOC_ENUM_EXT("Stereo To Mono", +- tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, +- tegra210_dmic_put_control), ++ tegra210_dmic_stereo_conv_enum, ++ tegra210_dmic_get_stereo_to_mono, ++ tegra210_dmic_put_stereo_to_mono), + SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, +- tegra210_dmic_get_control, tegra210_dmic_put_control), ++ tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val), + SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, +- tegra210_dmic_get_control, tegra210_dmic_put_control), ++ tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel), + }; + + static const struct snd_soc_component_driver tegra210_dmic_compnt = { +diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c +index 45f31ccb49d89..9552bbb939dd1 100644 +--- a/sound/soc/tegra/tegra210_i2s.c ++++ b/sound/soc/tegra/tegra210_i2s.c +@@ -302,85 +302,235 @@ static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai, + return 0; + } + +-static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, +- unsigned int ratio) ++static int tegra210_i2s_get_loopback(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); + +- i2s->bclk_ratio = ratio; ++ ucontrol->value.integer.value[0] = i2s->loopback; + + return 0; + } + +-static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) ++static int tegra210_i2s_put_loopback(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ int value = ucontrol->value.integer.value[0]; ++ ++ if (value == i2s->loopback) ++ return 0; ++ ++ i2s->loopback = value; ++ ++ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK, ++ i2s->loopback << I2S_CTRL_LPBK_SHIFT); ++ ++ return 1; ++} ++ ++static int tegra210_i2s_get_fsync_width(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); +- long *uctl_val = &ucontrol->value.integer.value[0]; +- +- if (strstr(kcontrol->id.name, "Loopback")) +- *uctl_val = i2s->loopback; +- else if (strstr(kcontrol->id.name, "FSYNC Width")) +- *uctl_val = i2s->fsync_width; +- else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) +- *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH]; +- else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) +- *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH]; +- else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) +- *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH]; +- else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) +- *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH]; +- else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) +- *uctl_val = i2s->rx_fifo_th; +- else if (strstr(kcontrol->id.name, "BCLK Ratio")) +- *uctl_val = i2s->bclk_ratio; ++ ++ ucontrol->value.integer.value[0] = i2s->fsync_width; + + return 0; + } + +-static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) ++static int tegra210_i2s_put_fsync_width(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); + int value = ucontrol->value.integer.value[0]; + +- if (strstr(kcontrol->id.name, "Loopback")) { +- i2s->loopback = value; ++ if (value == i2s->fsync_width) ++ return 0; + +- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, +- I2S_CTRL_LPBK_MASK, +- i2s->loopback << I2S_CTRL_LPBK_SHIFT); ++ i2s->fsync_width = value; + +- } else if (strstr(kcontrol->id.name, "FSYNC Width")) { +- /* +- * Frame sync width is used only for FSYNC modes and not +- * applicable for LRCK modes. Reset value for this field is "0", +- * which means the width is one bit clock wide. +- * The width requirement may depend on the codec and in such +- * cases mixer control is used to update custom values. A value +- * of "N" here means, width is "N + 1" bit clock wide. +- */ +- i2s->fsync_width = value; +- +- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, +- I2S_CTRL_FSYNC_WIDTH_MASK, +- i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); +- +- } else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) { +- i2s->stereo_to_mono[I2S_TX_PATH] = value; +- } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) { +- i2s->mono_to_stereo[I2S_TX_PATH] = value; +- } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) { +- i2s->stereo_to_mono[I2S_RX_PATH] = value; +- } else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) { +- i2s->mono_to_stereo[I2S_RX_PATH] = value; +- } else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) { +- i2s->rx_fifo_th = value; +- } else if (strstr(kcontrol->id.name, "BCLK Ratio")) { +- i2s->bclk_ratio = value; +- } ++ /* ++ * Frame sync width is used only for FSYNC modes and not ++ * applicable for LRCK modes. Reset value for this field is "0", ++ * which means the width is one bit clock wide. ++ * The width requirement may depend on the codec and in such ++ * cases mixer control is used to update custom values. A value ++ * of "N" here means, width is "N + 1" bit clock wide. ++ */ ++ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, ++ I2S_CTRL_FSYNC_WIDTH_MASK, ++ i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); ++ ++ return 1; ++} ++ ++static int tegra210_i2s_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ ++ ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_TX_PATH]; ++ ++ return 0; ++} ++ ++static int tegra210_i2s_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == i2s->stereo_to_mono[I2S_TX_PATH]) ++ return 0; ++ ++ i2s->stereo_to_mono[I2S_TX_PATH] = value; ++ ++ return 1; ++} ++ ++static int tegra210_i2s_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ ++ ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_TX_PATH]; ++ ++ return 0; ++} ++ ++static int tegra210_i2s_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == i2s->mono_to_stereo[I2S_TX_PATH]) ++ return 0; ++ ++ i2s->mono_to_stereo[I2S_TX_PATH] = value; ++ ++ return 1; ++} ++ ++static int tegra210_i2s_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ ++ ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_RX_PATH]; ++ ++ return 0; ++} ++ ++static int tegra210_i2s_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == i2s->stereo_to_mono[I2S_RX_PATH]) ++ return 0; ++ ++ i2s->stereo_to_mono[I2S_RX_PATH] = value; ++ ++ return 1; ++} ++ ++static int tegra210_i2s_pget_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ ++ ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_RX_PATH]; ++ ++ return 0; ++} ++ ++static int tegra210_i2s_pput_mono_to_stereo(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ unsigned int value = ucontrol->value.enumerated.item[0]; ++ ++ if (value == i2s->mono_to_stereo[I2S_RX_PATH]) ++ return 0; ++ ++ i2s->mono_to_stereo[I2S_RX_PATH] = value; ++ ++ return 1; ++} ++ ++static int tegra210_i2s_pget_fifo_th(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ ++ ucontrol->value.integer.value[0] = i2s->rx_fifo_th; ++ ++ return 0; ++} ++ ++static int tegra210_i2s_pput_fifo_th(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ int value = ucontrol->value.integer.value[0]; ++ ++ if (value == i2s->rx_fifo_th) ++ return 0; ++ ++ i2s->rx_fifo_th = value; ++ ++ return 1; ++} ++ ++static int tegra210_i2s_get_bclk_ratio(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ ++ ucontrol->value.integer.value[0] = i2s->bclk_ratio; ++ ++ return 0; ++} ++ ++static int tegra210_i2s_put_bclk_ratio(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); ++ struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); ++ int value = ucontrol->value.integer.value[0]; ++ ++ if (value == i2s->bclk_ratio) ++ return 0; ++ ++ i2s->bclk_ratio = value; ++ ++ return 1; ++} ++ ++static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, ++ unsigned int ratio) ++{ ++ struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ i2s->bclk_ratio = ratio; + + return 0; + } +@@ -598,22 +748,28 @@ static const struct soc_enum tegra210_i2s_stereo_conv_enum = + tegra210_i2s_stereo_conv_text); + + static const struct snd_kcontrol_new tegra210_i2s_controls[] = { +- SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control, +- tegra210_i2s_put_control), +- SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control, +- tegra210_i2s_put_control), ++ SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_loopback, ++ tegra210_i2s_put_loopback), ++ SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, ++ tegra210_i2s_get_fsync_width, ++ tegra210_i2s_put_fsync_width), + SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum, +- tegra210_i2s_get_control, tegra210_i2s_put_control), ++ tegra210_i2s_cget_stereo_to_mono, ++ tegra210_i2s_cput_stereo_to_mono), + SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum, +- tegra210_i2s_get_control, tegra210_i2s_put_control), ++ tegra210_i2s_cget_mono_to_stereo, ++ tegra210_i2s_cput_mono_to_stereo), + SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum, +- tegra210_i2s_get_control, tegra210_i2s_put_control), ++ tegra210_i2s_pget_mono_to_stereo, ++ tegra210_i2s_pput_mono_to_stereo), + SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum, +- tegra210_i2s_get_control, tegra210_i2s_put_control), ++ tegra210_i2s_pget_stereo_to_mono, ++ tegra210_i2s_pput_stereo_to_mono), + SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1, +- 0, tegra210_i2s_get_control, tegra210_i2s_put_control), +- SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control, +- tegra210_i2s_put_control), ++ 0, tegra210_i2s_pget_fifo_th, tegra210_i2s_pput_fifo_th), ++ SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, ++ tegra210_i2s_get_bclk_ratio, ++ tegra210_i2s_put_bclk_ratio), + }; + + static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = { +diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c +index 735909310a262..2e549b69061ca 100644 +--- a/sound/soc/tegra/tegra_asoc_machine.c ++++ b/sound/soc/tegra/tegra_asoc_machine.c +@@ -116,16 +116,24 @@ static const struct snd_kcontrol_new tegra_machine_controls[] = { + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Internal Mic 1"), + SOC_DAPM_PIN_SWITCH("Internal Mic 2"), ++ SOC_DAPM_PIN_SWITCH("Headphones"), ++ SOC_DAPM_PIN_SWITCH("Mic Jack"), + }; + + int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd) + { + struct snd_soc_card *card = rtd->card; + struct tegra_machine *machine = snd_soc_card_get_drvdata(card); ++ const char *jack_name; + int err; + + if (machine->gpiod_hp_det && machine->asoc->add_hp_jack) { +- err = snd_soc_card_jack_new(card, "Headphones Jack", ++ if (machine->asoc->hp_jack_name) ++ jack_name = machine->asoc->hp_jack_name; ++ else ++ jack_name = "Headphones Jack"; ++ ++ err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_HEADPHONE, + &tegra_machine_hp_jack, + tegra_machine_hp_jack_pins, +@@ -341,9 +349,34 @@ tegra_machine_parse_phandle(struct device *dev, const char *name) + return np; + } + ++static void tegra_machine_unregister_codec(void *pdev) ++{ ++ platform_device_unregister(pdev); ++} ++ ++static int tegra_machine_register_codec(struct device *dev, const char *name) ++{ ++ struct platform_device *pdev; ++ int err; ++ ++ if (!name) ++ return 0; ++ ++ pdev = platform_device_register_simple(name, -1, NULL, 0); ++ if (IS_ERR(pdev)) ++ return PTR_ERR(pdev); ++ ++ err = devm_add_action_or_reset(dev, tegra_machine_unregister_codec, ++ pdev); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ + int tegra_asoc_machine_probe(struct platform_device *pdev) + { +- struct device_node *np_codec, *np_i2s; ++ struct device_node *np_codec, *np_i2s, *np_ac97; + const struct tegra_asoc_data *asoc; + struct device *dev = &pdev->dev; + struct tegra_machine *machine; +@@ -404,17 +437,30 @@ int tegra_asoc_machine_probe(struct platform_device *pdev) + return err; + } + +- np_codec = tegra_machine_parse_phandle(dev, "nvidia,audio-codec"); +- if (IS_ERR(np_codec)) +- return PTR_ERR(np_codec); ++ if (asoc->set_ac97) { ++ err = tegra_machine_register_codec(dev, asoc->codec_dev_name); ++ if (err) ++ return err; ++ ++ np_ac97 = tegra_machine_parse_phandle(dev, "nvidia,ac97-controller"); ++ if (IS_ERR(np_ac97)) ++ return PTR_ERR(np_ac97); + +- np_i2s = tegra_machine_parse_phandle(dev, "nvidia,i2s-controller"); +- if (IS_ERR(np_i2s)) +- return PTR_ERR(np_i2s); ++ card->dai_link->cpus->of_node = np_ac97; ++ card->dai_link->platforms->of_node = np_ac97; ++ } else { ++ np_codec = tegra_machine_parse_phandle(dev, "nvidia,audio-codec"); ++ if (IS_ERR(np_codec)) ++ return PTR_ERR(np_codec); + +- card->dai_link->cpus->of_node = np_i2s; +- card->dai_link->codecs->of_node = np_codec; +- card->dai_link->platforms->of_node = np_i2s; ++ np_i2s = tegra_machine_parse_phandle(dev, "nvidia,i2s-controller"); ++ if (IS_ERR(np_i2s)) ++ return PTR_ERR(np_i2s); ++ ++ card->dai_link->cpus->of_node = np_i2s; ++ card->dai_link->codecs->of_node = np_codec; ++ card->dai_link->platforms->of_node = np_i2s; ++ } + + if (asoc->add_common_controls) { + card->controls = tegra_machine_controls; +@@ -589,6 +635,7 @@ static struct snd_soc_card snd_soc_tegra_wm9712 = { + static const struct tegra_asoc_data tegra_wm9712_data = { + .card = &snd_soc_tegra_wm9712, + .add_common_dapm_widgets = true, ++ .codec_dev_name = "wm9712-codec", + .set_ac97 = true, + }; + +@@ -619,6 +666,7 @@ static struct snd_soc_card snd_soc_tegra_max98090 = { + static const struct tegra_asoc_data tegra_max98090_data = { + .mclk_rate = tegra_machine_mclk_rate_12mhz, + .card = &snd_soc_tegra_max98090, ++ .hp_jack_name = "Headphones", + .add_common_dapm_widgets = true, + .add_common_controls = true, + .add_common_snd_ops = true, +@@ -686,6 +734,7 @@ static struct snd_soc_dai_link tegra_tlv320aic23_dai = { + }; + + static struct snd_soc_card snd_soc_tegra_trimslice = { ++ .name = "tegra-trimslice", + .components = "codec:tlv320aic23", + .dai_link = &tegra_tlv320aic23_dai, + .num_links = 1, +diff --git a/sound/soc/tegra/tegra_asoc_machine.h b/sound/soc/tegra/tegra_asoc_machine.h +index 8ee0ec814f67c..6f795d7dff7c1 100644 +--- a/sound/soc/tegra/tegra_asoc_machine.h ++++ b/sound/soc/tegra/tegra_asoc_machine.h +@@ -13,6 +13,8 @@ struct snd_soc_pcm_runtime; + + struct tegra_asoc_data { + unsigned int (*mclk_rate)(unsigned int srate); ++ const char *codec_dev_name; ++ const char *hp_jack_name; + struct snd_soc_card *card; + unsigned int mclk_id; + bool hp_jack_gpio_active_low; +diff --git a/sound/soc/uniphier/Kconfig b/sound/soc/uniphier/Kconfig +index aa3592ee1358b..ddfa6424c656b 100644 +--- a/sound/soc/uniphier/Kconfig ++++ b/sound/soc/uniphier/Kconfig +@@ -23,7 +23,6 @@ config SND_SOC_UNIPHIER_LD11 + tristate "UniPhier LD11/LD20 Device Driver" + depends on SND_SOC_UNIPHIER + select SND_SOC_UNIPHIER_AIO +- select SND_SOC_UNIPHIER_AIO_DMA + help + This adds ASoC driver for Socionext UniPhier LD11/LD20 + input and output that can be used with other codecs. +@@ -34,7 +33,6 @@ config SND_SOC_UNIPHIER_PXS2 + tristate "UniPhier PXs2 Device Driver" + depends on SND_SOC_UNIPHIER + select SND_SOC_UNIPHIER_AIO +- select SND_SOC_UNIPHIER_AIO_DMA + help + This adds ASoC driver for Socionext UniPhier PXs2 + input and output that can be used with other codecs. +diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c +index 91afea9d5de67..ce19a6058b279 100644 +--- a/sound/soc/xilinx/xlnx_formatter_pcm.c ++++ b/sound/soc/xilinx/xlnx_formatter_pcm.c +@@ -37,6 +37,7 @@ + #define XLNX_AUD_XFER_COUNT 0x28 + #define XLNX_AUD_CH_STS_START 0x2C + #define XLNX_BYTES_PER_CH 0x44 ++#define XLNX_AUD_ALIGN_BYTES 64 + + #define AUD_STS_IOC_IRQ_MASK BIT(31) + #define AUD_STS_CH_STS_MASK BIT(29) +@@ -368,12 +369,32 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component, + snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); + runtime->private_data = stream_data; + +- /* Resize the period size divisible by 64 */ ++ /* Resize the period bytes as divisible by 64 */ + err = snd_pcm_hw_constraint_step(runtime, 0, +- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); ++ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, ++ XLNX_AUD_ALIGN_BYTES); + if (err) { + dev_err(component->dev, +- "unable to set constraint on period bytes\n"); ++ "Unable to set constraint on period bytes\n"); ++ return err; ++ } ++ ++ /* Resize the buffer bytes as divisible by 64 */ ++ err = snd_pcm_hw_constraint_step(runtime, 0, ++ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, ++ XLNX_AUD_ALIGN_BYTES); ++ if (err) { ++ dev_err(component->dev, ++ "Unable to set constraint on buffer bytes\n"); ++ return err; ++ } ++ ++ /* Set periods as integer multiple */ ++ err = snd_pcm_hw_constraint_integer(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS); ++ if (err < 0) { ++ dev_err(component->dev, ++ "Unable to set constraint on periods to be integer\n"); + return err; + } + +diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c +index 49d1976a132c0..5ed8e36d2e043 100644 +--- a/sound/synth/emux/emux.c ++++ b/sound/synth/emux/emux.c +@@ -88,7 +88,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch + emu->name = kstrdup(name, GFP_KERNEL); + emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice), + GFP_KERNEL); +- if (emu->voices == NULL) ++ if (emu->name == NULL || emu->voices == NULL) + return -ENOMEM; + + /* create soundfont list */ +diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c +index 43a2a62d66f7e..49629d4bb327a 100644 +--- a/sound/usb/6fire/comm.c ++++ b/sound/usb/6fire/comm.c +@@ -95,7 +95,7 @@ static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev) + int actual_len; + + ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP), +- buffer, buffer[1] + 2, &actual_len, HZ); ++ buffer, buffer[1] + 2, &actual_len, 1000); + if (ret < 0) + return ret; + else if (actual_len != buffer[1] + 2) +diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c +index 8981e61f2da4a..c51abc54d2f84 100644 +--- a/sound/usb/6fire/firmware.c ++++ b/sound/usb/6fire/firmware.c +@@ -160,7 +160,7 @@ static int usb6fire_fw_ezusb_write(struct usb_device *device, + { + return usb_control_msg_send(device, 0, type, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- value, 0, data, len, HZ, GFP_KERNEL); ++ value, 0, data, len, 1000, GFP_KERNEL); + } + + static int usb6fire_fw_ezusb_read(struct usb_device *device, +@@ -168,7 +168,7 @@ static int usb6fire_fw_ezusb_read(struct usb_device *device, + { + return usb_control_msg_recv(device, 0, type, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, +- value, 0, data, len, HZ, GFP_KERNEL); ++ value, 0, data, len, 1000, GFP_KERNEL); + } + + static int usb6fire_fw_fpga_write(struct usb_device *device, +@@ -178,7 +178,7 @@ static int usb6fire_fw_fpga_write(struct usb_device *device, + int ret; + + ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len, +- &actual_len, HZ); ++ &actual_len, 1000); + if (ret < 0) + return ret; + else if (actual_len != len) +diff --git a/sound/usb/card.h b/sound/usb/card.h +index 5b19901f305a3..87f042d06ce08 100644 +--- a/sound/usb/card.h ++++ b/sound/usb/card.h +@@ -74,8 +74,9 @@ struct snd_usb_endpoint { + + atomic_t state; /* running state */ + +- void (*prepare_data_urb) (struct snd_usb_substream *subs, +- struct urb *urb); ++ int (*prepare_data_urb) (struct snd_usb_substream *subs, ++ struct urb *urb, ++ bool in_stream_lock); + void (*retire_data_urb) (struct snd_usb_substream *subs, + struct urb *urb); + +@@ -94,9 +95,9 @@ struct snd_usb_endpoint { + struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */ + + unsigned int nurbs; /* # urbs */ +- unsigned int nominal_queue_size; /* total buffer sizes in URBs */ + unsigned long active_mask; /* bitmask of active urbs */ + unsigned long unlink_mask; /* bitmask of unlinked urbs */ ++ atomic_t submitted_urbs; /* currently submitted urbs */ + char *syncbuf; /* sync buffer for all sync URBs */ + dma_addr_t sync_dma; /* DMA address of syncbuf */ + +@@ -125,6 +126,7 @@ struct snd_usb_endpoint { + int skip_packets; /* quirks for devices to ignore the first n packets + in a stream */ + bool implicit_fb_sync; /* syncs with implicit feedback */ ++ bool lowlatency_playback; /* low-latency playback mode */ + bool need_setup; /* (re-)need for configure? */ + + /* for hw constraints */ +@@ -136,6 +138,7 @@ struct snd_usb_endpoint { + unsigned int cur_period_frames; + unsigned int cur_period_bytes; + unsigned int cur_buffer_periods; ++ unsigned char cur_clock; + + spinlock_t lock; + struct list_head list; +@@ -188,7 +191,7 @@ struct snd_usb_substream { + } dsd_dop; + + bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */ +- bool early_playback_start; /* early start needed for playback? */ ++ bool lowlatency_playback; /* low-latency playback mode */ + struct media_ctl *media_ctl; + }; + +diff --git a/sound/usb/clock.c b/sound/usb/clock.c +index 81d5ce07d548b..98345a695dccb 100644 +--- a/sound/usb/clock.c ++++ b/sound/usb/clock.c +@@ -496,6 +496,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, + union uac23_clock_source_desc *cs_desc; + + cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol); ++ ++ if (!cs_desc) ++ return 0; ++ + if (fmt->protocol == UAC_VERSION_3) + bmControls = le32_to_cpu(cs_desc->v3.bmControls); + else +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 533919a28856f..743b8287cfcdd 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -148,18 +148,23 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep) + * This won't be used for implicit feedback which takes the packet size + * returned from the sync source + */ +-static int slave_next_packet_size(struct snd_usb_endpoint *ep) ++static int slave_next_packet_size(struct snd_usb_endpoint *ep, ++ unsigned int avail) + { + unsigned long flags; ++ unsigned int phase; + int ret; + + if (ep->fill_max) + return ep->maxframesize; + + spin_lock_irqsave(&ep->lock, flags); +- ep->phase = (ep->phase & 0xffff) +- + (ep->freqm << ep->datainterval); +- ret = min(ep->phase >> 16, ep->maxframesize); ++ phase = (ep->phase & 0xffff) + (ep->freqm << ep->datainterval); ++ ret = min(phase >> 16, ep->maxframesize); ++ if (avail && ret >= avail) ++ ret = -EAGAIN; ++ else ++ ep->phase = phase; + spin_unlock_irqrestore(&ep->lock, flags); + + return ret; +@@ -169,20 +174,25 @@ static int slave_next_packet_size(struct snd_usb_endpoint *ep) + * Return the number of samples to be sent in the next packet + * for adaptive and synchronous endpoints + */ +-static int next_packet_size(struct snd_usb_endpoint *ep) ++static int next_packet_size(struct snd_usb_endpoint *ep, unsigned int avail) + { ++ unsigned int sample_accum; + int ret; + + if (ep->fill_max) + return ep->maxframesize; + +- ep->sample_accum += ep->sample_rem; +- if (ep->sample_accum >= ep->pps) { +- ep->sample_accum -= ep->pps; ++ sample_accum = ep->sample_accum + ep->sample_rem; ++ if (sample_accum >= ep->pps) { ++ sample_accum -= ep->pps; + ret = ep->packsize[1]; + } else { + ret = ep->packsize[0]; + } ++ if (avail && ret >= avail) ++ ret = -EAGAIN; ++ else ++ ep->sample_accum = sample_accum; + + return ret; + } +@@ -190,16 +200,27 @@ static int next_packet_size(struct snd_usb_endpoint *ep) + /* + * snd_usb_endpoint_next_packet_size: Return the number of samples to be sent + * in the next packet ++ * ++ * If the size is equal or exceeds @avail, don't proceed but return -EAGAIN ++ * Exception: @avail = 0 for skipping the check. + */ + int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, +- struct snd_urb_ctx *ctx, int idx) ++ struct snd_urb_ctx *ctx, int idx, ++ unsigned int avail) + { +- if (ctx->packet_size[idx]) +- return ctx->packet_size[idx]; +- else if (ep->sync_source) +- return slave_next_packet_size(ep); ++ unsigned int packet; ++ ++ packet = ctx->packet_size[idx]; ++ if (packet) { ++ if (avail && packet >= avail) ++ return -EAGAIN; ++ return packet; ++ } ++ ++ if (ep->sync_source) ++ return slave_next_packet_size(ep, avail); + else +- return next_packet_size(ep); ++ return next_packet_size(ep, avail); + } + + static void call_retire_callback(struct snd_usb_endpoint *ep, +@@ -263,7 +284,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, + unsigned int length; + int counts; + +- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); ++ counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, 0); + length = counts * ep->stride; /* number of silent bytes */ + offset = offs * ep->stride + extra * i; + urb->iso_frame_desc[i].offset = offset; +@@ -286,8 +307,9 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, + /* + * Prepare a PLAYBACK urb for submission to the bus. + */ +-static void prepare_outbound_urb(struct snd_usb_endpoint *ep, +- struct snd_urb_ctx *ctx) ++static int prepare_outbound_urb(struct snd_usb_endpoint *ep, ++ struct snd_urb_ctx *ctx, ++ bool in_stream_lock) + { + struct urb *urb = ctx->urb; + unsigned char *cp = urb->transfer_buffer; +@@ -299,9 +321,9 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, + case SND_USB_ENDPOINT_TYPE_DATA: + data_subs = READ_ONCE(ep->data_subs); + if (data_subs && ep->prepare_data_urb) +- ep->prepare_data_urb(data_subs, urb); +- else /* no data provider, so send silence */ +- prepare_silent_urb(ep, ctx); ++ return ep->prepare_data_urb(data_subs, urb, in_stream_lock); ++ /* no data provider, so send silence */ ++ prepare_silent_urb(ep, ctx); + break; + + case SND_USB_ENDPOINT_TYPE_SYNC: +@@ -330,13 +352,14 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep, + + break; + } ++ return 0; + } + + /* + * Prepare a CAPTURE or SYNC urb for submission to the bus. + */ +-static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep, +- struct snd_urb_ctx *urb_ctx) ++static int prepare_inbound_urb(struct snd_usb_endpoint *ep, ++ struct snd_urb_ctx *urb_ctx) + { + int i, offs; + struct urb *urb = urb_ctx->urb; +@@ -361,6 +384,7 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep, + urb->iso_frame_desc[0].offset = 0; + break; + } ++ return 0; + } + + /* notify an error as XRUN to the assigned PCM data substream */ +@@ -396,6 +420,16 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) + return p; + } + ++static void push_back_to_ready_list(struct snd_usb_endpoint *ep, ++ struct snd_urb_ctx *ctx) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ep->lock, flags); ++ list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); ++ spin_unlock_irqrestore(&ep->lock, flags); ++} ++ + /* + * Send output urbs that have been prepared previously. URBs are dequeued + * from ep->ready_playback_urbs and in case there aren't any available +@@ -406,12 +440,14 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep) + * is that host controllers don't guarantee the order in which they return + * inbound and outbound packets to their submitters. + * +- * This function is only used for implicit feedback endpoints. For endpoints +- * driven by dedicated sync endpoints, URBs are immediately re-submitted +- * from their completion handler. ++ * This function is used both for implicit feedback endpoints and in low- ++ * latency playback mode. + */ +-static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) ++void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, ++ bool in_stream_lock) + { ++ bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep); ++ + while (ep_state_running(ep)) { + + unsigned long flags; +@@ -420,14 +456,14 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) + int err, i; + + spin_lock_irqsave(&ep->lock, flags); +- if (ep->next_packet_queued > 0 && ++ if ((!implicit_fb || ep->next_packet_queued > 0) && + !list_empty(&ep->ready_playback_urbs)) { + /* take URB out of FIFO */ + ctx = list_first_entry(&ep->ready_playback_urbs, + struct snd_urb_ctx, ready_list); + list_del_init(&ctx->ready_list); +- +- packet = next_packet_fifo_dequeue(ep); ++ if (implicit_fb) ++ packet = next_packet_fifo_dequeue(ep); + } + spin_unlock_irqrestore(&ep->lock, flags); + +@@ -435,11 +471,24 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) + return; + + /* copy over the length information */ +- for (i = 0; i < packet->packets; i++) +- ctx->packet_size[i] = packet->packet_size[i]; ++ if (implicit_fb) { ++ for (i = 0; i < packet->packets; i++) ++ ctx->packet_size[i] = packet->packet_size[i]; ++ } + + /* call the data handler to fill in playback data */ +- prepare_outbound_urb(ep, ctx); ++ err = prepare_outbound_urb(ep, ctx, in_stream_lock); ++ /* can be stopped during prepare callback */ ++ if (unlikely(!ep_state_running(ep))) ++ break; ++ if (err < 0) { ++ /* push back to ready list again for -EAGAIN */ ++ if (err == -EAGAIN) ++ push_back_to_ready_list(ep, ctx); ++ else ++ notify_xrun(ep); ++ return; ++ } + + err = usb_submit_urb(ctx->urb, GFP_ATOMIC); + if (err < 0) { +@@ -451,6 +500,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep) + } + + set_bit(ctx->index, &ep->active_mask); ++ atomic_inc(&ep->submitted_urbs); + } + } + +@@ -461,7 +511,6 @@ static void snd_complete_urb(struct urb *urb) + { + struct snd_urb_ctx *ctx = urb->context; + struct snd_usb_endpoint *ep = ctx->ep; +- unsigned long flags; + int err; + + if (unlikely(urb->status == -ENOENT || /* unlinked */ +@@ -482,16 +531,20 @@ static void snd_complete_urb(struct urb *urb) + if (unlikely(!ep_state_running(ep))) + goto exit_clear; + +- if (snd_usb_endpoint_implicit_feedback_sink(ep)) { +- spin_lock_irqsave(&ep->lock, flags); +- list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); ++ /* in low-latency and implicit-feedback modes, push back the ++ * URB to ready list at first, then process as much as possible ++ */ ++ if (ep->lowlatency_playback || ++ snd_usb_endpoint_implicit_feedback_sink(ep)) { ++ push_back_to_ready_list(ep, ctx); + clear_bit(ctx->index, &ep->active_mask); +- spin_unlock_irqrestore(&ep->lock, flags); +- queue_pending_output_urbs(ep); ++ snd_usb_queue_pending_output_urbs(ep, false); ++ atomic_dec(&ep->submitted_urbs); /* decrement at last */ + return; + } + +- prepare_outbound_urb(ep, ctx); ++ /* in non-lowlatency mode, no error handling for prepare */ ++ prepare_outbound_urb(ep, ctx, false); + /* can be stopped during prepare callback */ + if (unlikely(!ep_state_running(ep))) + goto exit_clear; +@@ -513,6 +566,7 @@ static void snd_complete_urb(struct urb *urb) + + exit_clear: + clear_bit(ctx->index, &ep->active_mask); ++ atomic_dec(&ep->submitted_urbs); + } + + /* +@@ -596,6 +650,7 @@ int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type) + ep->type = type; + ep->ep_num = ep_num; + INIT_LIST_HEAD(&ep->ready_playback_urbs); ++ atomic_set(&ep->submitted_urbs, 0); + + is_playback = ((ep_num & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); + ep_num &= USB_ENDPOINT_NUMBER_MASK; +@@ -722,6 +777,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, + ep->cur_period_frames = params_period_size(params); + ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes; + ep->cur_buffer_periods = params_periods(params); ++ ep->cur_clock = fp->clock; + + if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) + endpoint_set_syncinterval(chip, ep); +@@ -781,14 +837,19 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, + * Pass NULL to deactivate each callback. + */ + void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, +- void (*prepare)(struct snd_usb_substream *subs, +- struct urb *urb), ++ int (*prepare)(struct snd_usb_substream *subs, ++ struct urb *urb, ++ bool in_stream_lock), + void (*retire)(struct snd_usb_substream *subs, + struct urb *urb), + struct snd_usb_substream *data_subs) + { + ep->prepare_data_urb = prepare; + ep->retire_data_urb = retire; ++ if (data_subs) ++ ep->lowlatency_playback = data_subs->lowlatency_playback; ++ else ++ ep->lowlatency_playback = false; + WRITE_ONCE(ep->data_subs, data_subs); + } + +@@ -833,6 +894,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, + ep->altsetting = 0; + ep->cur_audiofmt = NULL; + ep->cur_rate = 0; ++ ep->cur_clock = 0; + ep->iface_ref = NULL; + usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num); + } +@@ -859,7 +921,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) + return 0; + + do { +- alive = bitmap_weight(&ep->active_mask, ep->nurbs); ++ alive = atomic_read(&ep->submitted_urbs); + if (!alive) + break; + +@@ -893,9 +955,10 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) + * + * This function moves the EP to STOPPING state if it's being RUNNING. + */ +-static int stop_urbs(struct snd_usb_endpoint *ep, bool force) ++static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending) + { + unsigned int i; ++ unsigned long flags; + + if (!force && atomic_read(&ep->running)) + return -EBUSY; +@@ -903,9 +966,14 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force) + if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING)) + return 0; + ++ spin_lock_irqsave(&ep->lock, flags); + INIT_LIST_HEAD(&ep->ready_playback_urbs); + ep->next_packet_head = 0; + ep->next_packet_queued = 0; ++ spin_unlock_irqrestore(&ep->lock, flags); ++ ++ if (keep_pending) ++ return 0; + + for (i = 0; i < ep->nurbs; i++) { + if (test_bit(i, &ep->active_mask)) { +@@ -930,7 +998,7 @@ static int release_urbs(struct snd_usb_endpoint *ep, bool force) + snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL); + + /* stop and unlink urbs */ +- err = stop_urbs(ep, force); ++ err = stop_urbs(ep, force, false); + if (err) + return err; + +@@ -1132,10 +1200,6 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep) + INIT_LIST_HEAD(&u->ready_list); + } + +- /* total buffer bytes of all URBs plus the next queue; +- * referred in pcm.c +- */ +- ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1); + return 0; + + out_of_memory: +@@ -1340,6 +1404,25 @@ unlock: + return err; + } + ++/* get the current rate set to the given clock by any endpoint */ ++int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock) ++{ ++ struct snd_usb_endpoint *ep; ++ int rate = 0; ++ ++ if (!clock) ++ return 0; ++ mutex_lock(&chip->mutex); ++ list_for_each_entry(ep, &chip->ep_list, list) { ++ if (ep->cur_clock == clock && ep->cur_rate) { ++ rate = ep->cur_rate; ++ break; ++ } ++ } ++ mutex_unlock(&chip->mutex); ++ return rate; ++} ++ + /** + * snd_usb_endpoint_start: start an snd_usb_endpoint + * +@@ -1355,6 +1438,7 @@ unlock: + */ + int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) + { ++ bool is_playback = usb_pipeout(ep->pipe); + int err; + unsigned int i; + +@@ -1391,13 +1475,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) + + if (snd_usb_endpoint_implicit_feedback_sink(ep) && + !(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) { +- for (i = 0; i < ep->nurbs; i++) { +- struct snd_urb_ctx *ctx = ep->urb + i; +- list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); +- } +- + usb_audio_dbg(ep->chip, "No URB submission due to implicit fb sync\n"); +- return 0; ++ i = 0; ++ goto fill_rest; + } + + for (i = 0; i < ep->nurbs; i++) { +@@ -1406,10 +1486,18 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) + if (snd_BUG_ON(!urb)) + goto __error; + +- if (usb_pipeout(ep->pipe)) { +- prepare_outbound_urb(ep, urb->context); +- } else { +- prepare_inbound_urb(ep, urb->context); ++ if (is_playback) ++ err = prepare_outbound_urb(ep, urb->context, true); ++ else ++ err = prepare_inbound_urb(ep, urb->context); ++ if (err < 0) { ++ /* stop filling at applptr */ ++ if (err == -EAGAIN) ++ break; ++ usb_audio_dbg(ep->chip, ++ "EP 0x%x: failed to prepare urb: %d\n", ++ ep->ep_num, err); ++ goto __error; + } + + err = usb_submit_urb(urb, GFP_ATOMIC); +@@ -1420,14 +1508,29 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) + goto __error; + } + set_bit(i, &ep->active_mask); ++ atomic_inc(&ep->submitted_urbs); ++ } ++ ++ if (!i) { ++ usb_audio_dbg(ep->chip, "XRUN at starting EP 0x%x\n", ++ ep->ep_num); ++ goto __error; + } + + usb_audio_dbg(ep->chip, "%d URBs submitted for EP 0x%x\n", +- ep->nurbs, ep->ep_num); ++ i, ep->ep_num); ++ ++ fill_rest: ++ /* put the remaining URBs to ready list */ ++ if (is_playback) { ++ for (; i < ep->nurbs; i++) ++ push_back_to_ready_list(ep, ep->urb + i); ++ } ++ + return 0; + + __error: +- snd_usb_endpoint_stop(ep); ++ snd_usb_endpoint_stop(ep, false); + return -EPIPE; + } + +@@ -1435,6 +1538,7 @@ __error: + * snd_usb_endpoint_stop: stop an snd_usb_endpoint + * + * @ep: the endpoint to stop (may be NULL) ++ * @keep_pending: keep in-flight URBs + * + * A call to this function will decrement the running count of the endpoint. + * In case the last user has requested the endpoint stop, the URBs will +@@ -1445,7 +1549,7 @@ __error: + * The caller needs to synchronize the pending stop operation via + * snd_usb_endpoint_sync_pending_stop(). + */ +-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) ++void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending) + { + if (!ep) + return; +@@ -1460,7 +1564,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) + if (!atomic_dec_return(&ep->running)) { + if (ep->sync_source) + WRITE_ONCE(ep->sync_source->sync_sink, NULL); +- stop_urbs(ep, false); ++ stop_urbs(ep, false, keep_pending); + } + } + +@@ -1575,7 +1679,7 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, + } + + spin_unlock_irqrestore(&ep->lock, flags); +- queue_pending_output_urbs(ep); ++ snd_usb_queue_pending_output_urbs(ep, false); + + return; + } +diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h +index a668f675b52b0..6a9af04cf175a 100644 +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -19,6 +19,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); + int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); ++int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock); + + bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep, +@@ -29,14 +30,15 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip, + struct snd_usb_endpoint *data_ep, + struct snd_usb_endpoint *sync_ep); + void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep, +- void (*prepare)(struct snd_usb_substream *subs, +- struct urb *urb), ++ int (*prepare)(struct snd_usb_substream *subs, ++ struct urb *urb, ++ bool in_stream_lock), + void (*retire)(struct snd_usb_substream *subs, + struct urb *urb), + struct snd_usb_substream *data_subs); + + int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); +-void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); ++void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending); + void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); + void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); +@@ -45,6 +47,9 @@ void snd_usb_endpoint_free_all(struct snd_usb_audio *chip); + + int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep); + int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep, +- struct snd_urb_ctx *ctx, int idx); ++ struct snd_urb_ctx *ctx, int idx, ++ unsigned int avail); ++void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep, ++ bool in_stream_lock); + + #endif /* __USBAUDIO_ENDPOINT_H */ +diff --git a/sound/usb/format.c b/sound/usb/format.c +index 50efccbffb8a7..405dc0bf6678c 100644 +--- a/sound/usb/format.c ++++ b/sound/usb/format.c +@@ -375,7 +375,7 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, + for (rate = min; rate <= max; rate += res) { + + /* Filter out invalid rates on Presonus Studio 1810c */ +- if (chip->usb_id == USB_ID(0x0194f, 0x010c) && ++ if (chip->usb_id == USB_ID(0x194f, 0x010c) && + !s1810c_valid_sample_rate(fp, rate)) + goto skip_rate; + +@@ -414,6 +414,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, + case USB_ID(0x0e41, 0x4242): /* Line6 Helix Rack */ + case USB_ID(0x0e41, 0x4244): /* Line6 Helix LT */ + case USB_ID(0x0e41, 0x4246): /* Line6 HX-Stomp */ ++ case USB_ID(0x0e41, 0x4253): /* Line6 HX-Stomp XL */ + case USB_ID(0x0e41, 0x4247): /* Line6 Pod Go */ + case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */ + case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */ +diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c +index 23767a14d1266..2d444ec742029 100644 +--- a/sound/usb/implicit.c ++++ b/sound/usb/implicit.c +@@ -47,15 +47,13 @@ struct snd_usb_implicit_fb_match { + static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { + /* Generic matching */ + IMPLICIT_FB_GENERIC_DEV(0x0499, 0x1509), /* Steinberg UR22 */ +- IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2080), /* M-Audio FastTrack Ultra */ +- IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2081), /* M-Audio FastTrack Ultra */ + IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2030), /* M-Audio Fast Track C400 */ + IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2031), /* M-Audio Fast Track C600 */ + + /* Fixed EP */ + /* FIXME: check the availability of generic matching */ +- IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */ +- IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */ ++ IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */ ++ IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */ + IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */ + IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */ + IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */ +diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c +index 9602929b7de90..59faa5a9a7141 100644 +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -113,12 +113,12 @@ int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w), + (char *)frag_buf, frag_size, +- &partial, LINE6_TIMEOUT * HZ); ++ &partial, LINE6_TIMEOUT); + } else { + retval = usb_bulk_msg(line6->usbdev, + usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w), + (char *)frag_buf, frag_size, +- &partial, LINE6_TIMEOUT * HZ); ++ &partial, LINE6_TIMEOUT); + } + + if (retval) { +@@ -347,7 +347,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + ret = usb_control_msg_send(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + (datalen << 8) | 0x21, address, NULL, 0, +- LINE6_TIMEOUT * HZ, GFP_KERNEL); ++ LINE6_TIMEOUT, GFP_KERNEL); + if (ret) { + dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); + goto exit; +@@ -360,7 +360,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + ret = usb_control_msg_recv(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x0012, 0x0000, &len, 1, +- LINE6_TIMEOUT * HZ, GFP_KERNEL); ++ LINE6_TIMEOUT, GFP_KERNEL); + if (ret) { + dev_err(line6->ifcdev, + "receive length failed (error %d)\n", ret); +@@ -387,7 +387,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, + /* receive the result: */ + ret = usb_control_msg_recv(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- 0x0013, 0x0000, data, datalen, LINE6_TIMEOUT * HZ, ++ 0x0013, 0x0000, data, datalen, LINE6_TIMEOUT, + GFP_KERNEL); + if (ret) + dev_err(line6->ifcdev, "read failed (error %d)\n", ret); +@@ -417,7 +417,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, + + ret = usb_control_msg_send(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +- 0x0022, address, data, datalen, LINE6_TIMEOUT * HZ, ++ 0x0022, address, data, datalen, LINE6_TIMEOUT, + GFP_KERNEL); + if (ret) { + dev_err(line6->ifcdev, +@@ -430,7 +430,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, + + ret = usb_control_msg_recv(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, +- 0x0012, 0x0000, status, 1, LINE6_TIMEOUT * HZ, ++ 0x0012, 0x0000, status, 1, LINE6_TIMEOUT, + GFP_KERNEL); + if (ret) { + dev_err(line6->ifcdev, +diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h +index 71d3da1db8c81..ecf3a2b39c7eb 100644 +--- a/sound/usb/line6/driver.h ++++ b/sound/usb/line6/driver.h +@@ -27,7 +27,7 @@ + #define LINE6_FALLBACK_INTERVAL 10 + #define LINE6_FALLBACK_MAXPACKETSIZE 16 + +-#define LINE6_TIMEOUT 1 ++#define LINE6_TIMEOUT 1000 + #define LINE6_BUFSIZE_LISTEN 64 + #define LINE6_MIDI_MESSAGE_MAXLEN 256 + +diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c +index 28794a35949d4..b24bc82f89e37 100644 +--- a/sound/usb/line6/podhd.c ++++ b/sound/usb/line6/podhd.c +@@ -190,7 +190,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) + ret = usb_control_msg_send(usbdev, 0, + 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x11, 0, +- NULL, 0, LINE6_TIMEOUT * HZ, GFP_KERNEL); ++ NULL, 0, LINE6_TIMEOUT, GFP_KERNEL); + if (ret) { + dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); + goto exit; +@@ -200,7 +200,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) + ret = usb_control_msg_recv(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x11, 0x0, +- init_bytes, 3, LINE6_TIMEOUT * HZ, GFP_KERNEL); ++ init_bytes, 3, LINE6_TIMEOUT, GFP_KERNEL); + if (ret) { + dev_err(pod->line6.ifcdev, + "receive length failed (error %d)\n", ret); +@@ -220,7 +220,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) + USB_REQ_SET_FEATURE, + USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, + 1, 0, +- NULL, 0, LINE6_TIMEOUT * HZ, GFP_KERNEL); ++ NULL, 0, LINE6_TIMEOUT, GFP_KERNEL); + exit: + return ret; + } +diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c +index 4e5693c97aa42..e33df58740a91 100644 +--- a/sound/usb/line6/toneport.c ++++ b/sound/usb/line6/toneport.c +@@ -128,7 +128,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) + + ret = usb_control_msg_send(usbdev, 0, 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +- cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ, ++ cmd1, cmd2, NULL, 0, LINE6_TIMEOUT, + GFP_KERNEL); + + if (ret) { +diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c +index 5834d1dc317ef..4f6b20ed29dd7 100644 +--- a/sound/usb/misc/ua101.c ++++ b/sound/usb/misc/ua101.c +@@ -1000,7 +1000,7 @@ static int detect_usb_format(struct ua101 *ua) + fmt_playback->bSubframeSize * ua->playback.channels; + + epd = &ua->intf[INTF_CAPTURE]->altsetting[1].endpoint[0].desc; +- if (!usb_endpoint_is_isoc_in(epd)) { ++ if (!usb_endpoint_is_isoc_in(epd) || usb_endpoint_maxp(epd) == 0) { + dev_err(&ua->dev->dev, "invalid capture endpoint\n"); + return -ENXIO; + } +@@ -1008,7 +1008,7 @@ static int detect_usb_format(struct ua101 *ua) + ua->capture.max_packet_bytes = usb_endpoint_maxp(epd); + + epd = &ua->intf[INTF_PLAYBACK]->altsetting[1].endpoint[0].desc; +- if (!usb_endpoint_is_isoc_out(epd)) { ++ if (!usb_endpoint_is_isoc_out(epd) || usb_endpoint_maxp(epd) == 0) { + dev_err(&ua->dev->dev, "invalid playback endpoint\n"); + return -ENXIO; + } +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 8e030b1c061ab..567514832b0df 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1496,6 +1496,10 @@ error: + usb_audio_err(chip, + "cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", + UAC_GET_CUR, validx, idx, cval->val_type); ++ ++ if (val) ++ *val = 0; ++ + return filter_error(cval, ret); + } + +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 46082dc57be09..d48729e6a3b0a 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -2795,6 +2795,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) + #define SND_DJM_750_IDX 0x1 + #define SND_DJM_850_IDX 0x2 + #define SND_DJM_900NXS2_IDX 0x3 ++#define SND_DJM_750MK2_IDX 0x4 + + + #define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ +@@ -2984,12 +2985,42 @@ static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = { + SND_DJM_CTL("Ch5 Input", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP) + }; + ++// DJM-750MK2 ++static const u16 snd_djm_opts_750mk2_cap1[] = { ++ 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a }; ++static const u16 snd_djm_opts_750mk2_cap2[] = { ++ 0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a }; ++static const u16 snd_djm_opts_750mk2_cap3[] = { ++ 0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a }; ++static const u16 snd_djm_opts_750mk2_cap4[] = { ++ 0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a }; ++static const u16 snd_djm_opts_750mk2_cap5[] = { ++ 0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 }; ++ ++static const u16 snd_djm_opts_750mk2_pb1[] = { 0x0100, 0x0101, 0x0104 }; ++static const u16 snd_djm_opts_750mk2_pb2[] = { 0x0200, 0x0201, 0x0204 }; ++static const u16 snd_djm_opts_750mk2_pb3[] = { 0x0300, 0x0301, 0x0304 }; ++ ++ ++static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = { ++ SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), ++ SND_DJM_CTL("Ch1 Input", 750mk2_cap1, 2, SND_DJM_WINDEX_CAP), ++ SND_DJM_CTL("Ch2 Input", 750mk2_cap2, 2, SND_DJM_WINDEX_CAP), ++ SND_DJM_CTL("Ch3 Input", 750mk2_cap3, 2, SND_DJM_WINDEX_CAP), ++ SND_DJM_CTL("Ch4 Input", 750mk2_cap4, 2, SND_DJM_WINDEX_CAP), ++ SND_DJM_CTL("Ch5 Input", 750mk2_cap5, 3, SND_DJM_WINDEX_CAP), ++ SND_DJM_CTL("Ch1 Output", 750mk2_pb1, 0, SND_DJM_WINDEX_PB), ++ SND_DJM_CTL("Ch2 Output", 750mk2_pb2, 1, SND_DJM_WINDEX_PB), ++ SND_DJM_CTL("Ch3 Output", 750mk2_pb3, 2, SND_DJM_WINDEX_PB) ++}; ++ + + static const struct snd_djm_device snd_djm_devices[] = { +- SND_DJM_DEVICE(250mk2), +- SND_DJM_DEVICE(750), +- SND_DJM_DEVICE(850), +- SND_DJM_DEVICE(900nxs2) ++ [SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2), ++ [SND_DJM_750_IDX] = SND_DJM_DEVICE(750), ++ [SND_DJM_850_IDX] = SND_DJM_DEVICE(850), ++ [SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2), ++ [SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2), + }; + + +@@ -3223,7 +3254,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) + err = snd_rme_controls_create(mixer); + break; + +- case USB_ID(0x0194f, 0x010c): /* Presonus Studio 1810c */ ++ case USB_ID(0x194f, 0x010c): /* Presonus Studio 1810c */ + err = snd_sc1810_init_mixer(mixer); + break; + case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */ +@@ -3235,6 +3266,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) + case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ + err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); + break; ++ case USB_ID(0x2b73, 0x001b): /* Pioneer DJ DJM-750MK2 */ ++ err = snd_djm_controls_create(mixer, SND_DJM_750MK2_IDX); ++ break; + case USB_ID(0x08e4, 0x0163): /* Pioneer DJ DJM-850 */ + err = snd_djm_controls_create(mixer, SND_DJM_850_IDX); + break; +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 5dc9266180e37..2e51fb031ae01 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -219,16 +219,16 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, + return 0; + } + +-static bool stop_endpoints(struct snd_usb_substream *subs) ++static bool stop_endpoints(struct snd_usb_substream *subs, bool keep_pending) + { + bool stopped = 0; + + if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) { +- snd_usb_endpoint_stop(subs->sync_endpoint); ++ snd_usb_endpoint_stop(subs->sync_endpoint, keep_pending); + stopped = true; + } + if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) { +- snd_usb_endpoint_stop(subs->data_endpoint); ++ snd_usb_endpoint_stop(subs->data_endpoint, keep_pending); + stopped = true; + } + return stopped; +@@ -261,7 +261,7 @@ static int start_endpoints(struct snd_usb_substream *subs) + return 0; + + error: +- stop_endpoints(subs); ++ stop_endpoints(subs, false); + return err; + } + +@@ -437,7 +437,7 @@ static int configure_endpoints(struct snd_usb_audio *chip, + + if (subs->data_endpoint->need_setup) { + /* stop any running stream beforehand */ +- if (stop_endpoints(subs)) ++ if (stop_endpoints(subs, false)) + sync_pending_stops(subs); + err = snd_usb_endpoint_configure(chip, subs->data_endpoint); + if (err < 0) +@@ -572,7 +572,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) + subs->cur_audiofmt = NULL; + mutex_unlock(&chip->mutex); + if (!snd_usb_lock_shutdown(chip)) { +- if (stop_endpoints(subs)) ++ if (stop_endpoints(subs, false)) + sync_pending_stops(subs); + close_endpoints(chip, subs); + snd_usb_unlock_shutdown(chip); +@@ -581,6 +581,31 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) + return 0; + } + ++/* free-wheeling mode? (e.g. dmix) */ ++static int in_free_wheeling_mode(struct snd_pcm_runtime *runtime) ++{ ++ return runtime->stop_threshold > runtime->buffer_size; ++} ++ ++/* check whether early start is needed for playback stream */ ++static int lowlatency_playback_available(struct snd_pcm_runtime *runtime, ++ struct snd_usb_substream *subs) ++{ ++ struct snd_usb_audio *chip = subs->stream->chip; ++ ++ if (subs->direction == SNDRV_PCM_STREAM_CAPTURE) ++ return false; ++ /* disabled via module option? */ ++ if (!chip->lowlatency) ++ return false; ++ if (in_free_wheeling_mode(runtime)) ++ return false; ++ /* implicit feedback mode has own operation mode */ ++ if (snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) ++ return false; ++ return true; ++} ++ + /* + * prepare callback + * +@@ -614,13 +639,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + subs->period_elapsed_pending = 0; + runtime->delay = 0; + +- /* check whether early start is needed for playback stream */ +- subs->early_playback_start = +- subs->direction == SNDRV_PCM_STREAM_PLAYBACK && +- (!chip->lowlatency || +- (subs->data_endpoint->nominal_queue_size >= subs->buffer_bytes)); +- +- if (subs->early_playback_start) ++ subs->lowlatency_playback = lowlatency_playback_available(runtime, subs); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && ++ !subs->lowlatency_playback) + ret = start_endpoints(subs); + + unlock: +@@ -734,6 +755,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) + { + struct snd_usb_substream *subs = rule->private; ++ struct snd_usb_audio *chip = subs->stream->chip; + const struct audioformat *fp; + struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + unsigned int rmin, rmax, r; +@@ -745,6 +767,14 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params, + list_for_each_entry(fp, &subs->fmt_list, list) { + if (!hw_check_valid_format(subs, params, fp)) + continue; ++ r = snd_usb_endpoint_get_clock_rate(chip, fp->clock); ++ if (r > 0) { ++ if (!snd_interval_test(it, r)) ++ continue; ++ rmin = min(rmin, r); ++ rmax = max(rmax, r); ++ continue; ++ } + if (fp->rate_table && fp->nr_rates) { + for (i = 0; i < fp->nr_rates; i++) { + r = fp->rate_table[i]; +@@ -1068,6 +1098,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) + int ret; + + runtime->hw = snd_usb_hardware; ++ /* need an explicit sync to catch applptr update in low-latency mode */ ++ if (direction == SNDRV_PCM_STREAM_PLAYBACK && ++ as->chip->lowlatency) ++ runtime->hw.info |= SNDRV_PCM_INFO_SYNC_APPLPTR; + runtime->private_data = subs; + subs->pcm_substream = substream; + /* runtime PM is also done there */ +@@ -1320,44 +1354,66 @@ static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs, + return bytes; + } + +-static void prepare_playback_urb(struct snd_usb_substream *subs, +- struct urb *urb) ++static int prepare_playback_urb(struct snd_usb_substream *subs, ++ struct urb *urb, ++ bool in_stream_lock) + { + struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; + struct snd_usb_endpoint *ep = subs->data_endpoint; + struct snd_urb_ctx *ctx = urb->context; +- unsigned int counts, frames, bytes; ++ unsigned int frames, bytes; ++ int counts; ++ unsigned int transfer_done, frame_limit, avail = 0; + int i, stride, period_elapsed = 0; + unsigned long flags; ++ int err = 0; + + stride = ep->stride; + + frames = 0; + ctx->queued = 0; + urb->number_of_packets = 0; ++ + spin_lock_irqsave(&subs->lock, flags); +- subs->frame_limit += ep->max_urb_frames; ++ frame_limit = subs->frame_limit + ep->max_urb_frames; ++ transfer_done = subs->transfer_done; ++ ++ if (subs->lowlatency_playback && ++ runtime->status->state != SNDRV_PCM_STATE_DRAINING) { ++ unsigned int hwptr = subs->hwptr_done / stride; ++ ++ /* calculate the byte offset-in-buffer of the appl_ptr */ ++ avail = (runtime->control->appl_ptr - runtime->hw_ptr_base) ++ % runtime->buffer_size; ++ if (avail <= hwptr) ++ avail += runtime->buffer_size; ++ avail -= hwptr; ++ } ++ + for (i = 0; i < ctx->packets; i++) { +- counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); ++ counts = snd_usb_endpoint_next_packet_size(ep, ctx, i, avail); ++ if (counts < 0) ++ break; + /* set up descriptor */ + urb->iso_frame_desc[i].offset = frames * stride; + urb->iso_frame_desc[i].length = counts * stride; + frames += counts; ++ avail -= counts; + urb->number_of_packets++; +- subs->transfer_done += counts; +- if (subs->transfer_done >= runtime->period_size) { +- subs->transfer_done -= runtime->period_size; +- subs->frame_limit = 0; ++ transfer_done += counts; ++ if (transfer_done >= runtime->period_size) { ++ transfer_done -= runtime->period_size; ++ frame_limit = 0; + period_elapsed = 1; + if (subs->fmt_type == UAC_FORMAT_TYPE_II) { +- if (subs->transfer_done > 0) { ++ if (transfer_done > 0) { + /* FIXME: fill-max mode is not + * supported yet */ +- frames -= subs->transfer_done; +- counts -= subs->transfer_done; ++ frames -= transfer_done; ++ counts -= transfer_done; + urb->iso_frame_desc[i].length = + counts * stride; +- subs->transfer_done = 0; ++ transfer_done = 0; + } + i++; + if (i < ctx->packets) { +@@ -1371,13 +1427,19 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, + } + } + /* finish at the period boundary or after enough frames */ +- if ((period_elapsed || +- subs->transfer_done >= subs->frame_limit) && ++ if ((period_elapsed || transfer_done >= frame_limit) && + !snd_usb_endpoint_implicit_feedback_sink(ep)) + break; + } +- bytes = frames * stride; + ++ if (!frames) { ++ err = -EAGAIN; ++ goto unlock; ++ } ++ ++ bytes = frames * stride; ++ subs->transfer_done = transfer_done; ++ subs->frame_limit = frame_limit; + if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && + subs->cur_audiofmt->dsd_dop)) { + fill_playback_urb_dsd_dop(subs, urb, bytes); +@@ -1403,14 +1465,23 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, + subs->trigger_tstamp_pending_update = false; + } + +- if (period_elapsed && !subs->running && !subs->early_playback_start) { ++ if (period_elapsed && !subs->running && subs->lowlatency_playback) { + subs->period_elapsed_pending = 1; + period_elapsed = 0; + } ++ ++ unlock: + spin_unlock_irqrestore(&subs->lock, flags); ++ if (err < 0) ++ return err; + urb->transfer_buffer_length = bytes; +- if (period_elapsed) +- snd_pcm_period_elapsed(subs->pcm_substream); ++ if (period_elapsed) { ++ if (in_stream_lock) ++ snd_pcm_period_elapsed_under_stream_lock(subs->pcm_substream); ++ else ++ snd_pcm_period_elapsed(subs->pcm_substream); ++ } ++ return 0; + } + + /* +@@ -1442,6 +1513,27 @@ static void retire_playback_urb(struct snd_usb_substream *subs, + snd_pcm_period_elapsed(subs->pcm_substream); + } + ++/* PCM ack callback for the playback stream; ++ * this plays a role only when the stream is running in low-latency mode. ++ */ ++static int snd_usb_pcm_playback_ack(struct snd_pcm_substream *substream) ++{ ++ struct snd_usb_substream *subs = substream->runtime->private_data; ++ struct snd_usb_endpoint *ep; ++ ++ if (!subs->lowlatency_playback || !subs->running) ++ return 0; ++ ep = subs->data_endpoint; ++ if (!ep) ++ return 0; ++ /* When no more in-flight URBs available, try to process the pending ++ * outputs here ++ */ ++ if (!ep->active_mask) ++ snd_usb_queue_pending_output_urbs(ep, true); ++ return 0; ++} ++ + static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, + int cmd) + { +@@ -1457,8 +1549,10 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea + prepare_playback_urb, + retire_playback_urb, + subs); +- if (!subs->early_playback_start && ++ if (subs->lowlatency_playback && + cmd == SNDRV_PCM_TRIGGER_START) { ++ if (in_free_wheeling_mode(substream->runtime)) ++ subs->lowlatency_playback = false; + err = start_endpoints(subs); + if (err < 0) { + snd_usb_endpoint_set_callback(subs->data_endpoint, +@@ -1473,7 +1567,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea + return 0; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: +- stop_endpoints(subs); ++ stop_endpoints(subs, substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING); + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, NULL, NULL); + subs->running = 0; +@@ -1521,7 +1615,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream + return 0; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: +- stop_endpoints(subs); ++ stop_endpoints(subs, false); + fallthrough; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + snd_usb_endpoint_set_callback(subs->data_endpoint, +@@ -1545,6 +1639,7 @@ static const struct snd_pcm_ops snd_usb_playback_ops = { + .trigger = snd_usb_substream_playback_trigger, + .sync_stop = snd_usb_pcm_sync_stop, + .pointer = snd_usb_pcm_pointer, ++ .ack = snd_usb_pcm_playback_ack, + }; + + static const struct snd_pcm_ops snd_usb_capture_ops = { +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 2af8c68fac275..0ea39565e6232 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -84,7 +84,7 @@ + * combination. + */ + { +- USB_DEVICE(0x041e, 0x4095), ++ USB_AUDIO_DEVICE(0x041e, 0x4095), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, +@@ -3892,6 +3892,64 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + } + }, ++{ ++ /* ++ * Pioneer DJ DJM-750MK2 ++ * 10 channels playback & 12 channels capture @ 48kHz S24LE ++ */ ++ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001b), ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .channels = 10, ++ .iface = 0, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .endpoint = 0x01, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC| ++ USB_ENDPOINT_SYNC_ASYNC, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .nr_rates = 1, ++ .rate_table = (unsigned int[]) { ++ 48000 ++ } ++ } ++ }, ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .channels = 12, ++ .iface = 0, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .endpoint = 0x82, ++ .ep_idx = 1, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC| ++ USB_ENDPOINT_SYNC_ASYNC| ++ USB_ENDPOINT_USAGE_IMPLICIT_FB, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .nr_rates = 1, ++ .rate_table = (unsigned int[]) { 48000 } ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, + { + /* + * Pioneer DJ DJM-850 +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 8929d9abe8aa8..ab9f3da49941f 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1290,7 +1290,7 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, + if (chip->usb_id == USB_ID(0x0763, 0x2012)) + return fasttrackpro_skip_setting_quirk(chip, iface, altno); + /* presonus studio 1810c: skip altsets incompatible with device_setup */ +- if (chip->usb_id == USB_ID(0x0194f, 0x010c)) ++ if (chip->usb_id == USB_ID(0x194f, 0x010c)) + return s1810c_skip_setting_quirk(chip, iface, altno); + + +@@ -1749,6 +1749,7 @@ static const struct registration_quirk registration_quirks[] = { + REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ + REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */ + REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */ ++ REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */ + REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */ + REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */ + REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */ +@@ -1887,6 +1888,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), + DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */ + QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */ ++ QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ +diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c +index 378826312abe6..7aa9472749002 100644 +--- a/sound/x86/intel_hdmi_audio.c ++++ b/sound/x86/intel_hdmi_audio.c +@@ -1261,7 +1261,7 @@ static int had_pcm_mmap(struct snd_pcm_substream *substream, + { + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return remap_pfn_range(vma, vma->vm_start, +- substream->dma_buffer.addr >> PAGE_SHIFT, ++ substream->runtime->dma_addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + } + +diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h +index d0ce5cfd3ac14..63d30dde20f94 100644 +--- a/tools/arch/x86/include/asm/cpufeatures.h ++++ b/tools/arch/x86/include/asm/cpufeatures.h +@@ -204,7 +204,7 @@ + /* FREE! ( 7*32+10) */ + #define X86_FEATURE_PTI ( 7*32+11) /* Kernel Page Table Isolation enabled */ + #define X86_FEATURE_RETPOLINE ( 7*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */ +-#define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */ ++#define X86_FEATURE_RETPOLINE_LFENCE ( 7*32+13) /* "" Use LFENCEs for Spectre variant 2 */ + #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ + #define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */ + #define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */ +diff --git a/tools/arch/x86/lib/insn.c b/tools/arch/x86/lib/insn.c +index 797699462cd8e..8fd63a067308a 100644 +--- a/tools/arch/x86/lib/insn.c ++++ b/tools/arch/x86/lib/insn.c +@@ -13,6 +13,7 @@ + #endif + #include "../include/asm/inat.h" /* __ignore_sync_check__ */ + #include "../include/asm/insn.h" /* __ignore_sync_check__ */ ++#include "../include/asm-generic/unaligned.h" /* __ignore_sync_check__ */ + + #include <linux/errno.h> + #include <linux/kconfig.h> +@@ -37,10 +38,10 @@ + ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr) + + #define __get_next(t, insn) \ +- ({ t r; memcpy(&r, insn->next_byte, sizeof(t)); insn->next_byte += sizeof(t); leXX_to_cpu(t, r); }) ++ ({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); }) + + #define __peek_nbyte_next(t, insn, n) \ +- ({ t r; memcpy(&r, (insn)->next_byte + n, sizeof(t)); leXX_to_cpu(t, r); }) ++ ({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); }) + + #define get_next(t, insn) \ + ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); }) +diff --git a/tools/bpf/bpftool/Documentation/Makefile b/tools/bpf/bpftool/Documentation/Makefile +index c49487905cebe..f89929c7038d5 100644 +--- a/tools/bpf/bpftool/Documentation/Makefile ++++ b/tools/bpf/bpftool/Documentation/Makefile +@@ -1,6 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only + include ../../../scripts/Makefile.include +-include ../../../scripts/utilities.mak + + INSTALL ?= install + RM ?= rm -f +diff --git a/tools/bpf/bpftool/Documentation/bpftool-btf.rst b/tools/bpf/bpftool/Documentation/bpftool-btf.rst +index 88b28aa7431f6..4425d942dd39a 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool-btf.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool-btf.rst +@@ -13,7 +13,7 @@ SYNOPSIS + **bpftool** [*OPTIONS*] **btf** *COMMAND* + + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | {**-d** | **--debug** } | +- { **-B** | **--base-btf** } } ++ { **-B** | **--base-btf** } } + + *COMMANDS* := { **dump** | **help** } + +diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst +index 3e4395eede4f7..13a217a2503d8 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst +@@ -13,7 +13,7 @@ SYNOPSIS + **bpftool** [*OPTIONS*] **cgroup** *COMMAND* + + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } | +- { **-f** | **--bpffs** } } ++ { **-f** | **--bpffs** } } + + *COMMANDS* := + { **show** | **list** | **tree** | **attach** | **detach** | **help** } +diff --git a/tools/bpf/bpftool/Documentation/bpftool-gen.rst b/tools/bpf/bpftool/Documentation/bpftool-gen.rst +index 2ef2f2df02799..2a137f8a4cea0 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool-gen.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool-gen.rst +@@ -13,7 +13,7 @@ SYNOPSIS + **bpftool** [*OPTIONS*] **gen** *COMMAND* + + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } | +- { **-L** | **--use-loader** } } ++ { **-L** | **--use-loader** } } + + *COMMAND* := { **object** | **skeleton** | **help** } + +diff --git a/tools/bpf/bpftool/Documentation/bpftool-link.rst b/tools/bpf/bpftool/Documentation/bpftool-link.rst +index 0de90f086238c..9434349636a5e 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool-link.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool-link.rst +@@ -13,7 +13,7 @@ SYNOPSIS + **bpftool** [*OPTIONS*] **link** *COMMAND* + + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } | +- { **-f** | **--bpffs** } | { **-n** | **--nomount** } } ++ { **-f** | **--bpffs** } | { **-n** | **--nomount** } } + + *COMMANDS* := { **show** | **list** | **pin** | **help** } + +diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst +index d0c4abe08abab..1445cadc15d4c 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool-map.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst +@@ -13,11 +13,11 @@ SYNOPSIS + **bpftool** [*OPTIONS*] **map** *COMMAND* + + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } | +- { **-f** | **--bpffs** } | { **-n** | **--nomount** } } ++ { **-f** | **--bpffs** } | { **-n** | **--nomount** } } + + *COMMANDS* := +- { **show** | **list** | **create** | **dump** | **update** | **lookup** | **getnext** +- | **delete** | **pin** | **help** } ++ { **show** | **list** | **create** | **dump** | **update** | **lookup** | **getnext** | ++ **delete** | **pin** | **help** } + + MAP COMMANDS + ============= +diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst +index 91608cb7e44a0..f27265bd589b4 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst +@@ -13,12 +13,12 @@ SYNOPSIS + **bpftool** [*OPTIONS*] **prog** *COMMAND* + + *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } | +- { **-f** | **--bpffs** } | { **-m** | **--mapcompat** } | { **-n** | **--nomount** } | +- { **-L** | **--use-loader** } } ++ { **-f** | **--bpffs** } | { **-m** | **--mapcompat** } | { **-n** | **--nomount** } | ++ { **-L** | **--use-loader** } } + + *COMMANDS* := +- { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** +- | **loadall** | **help** } ++ { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** | ++ **loadall** | **help** } + + PROG COMMANDS + ============= +diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst +index bb23f55bb05ad..8ac86565c501e 100644 +--- a/tools/bpf/bpftool/Documentation/bpftool.rst ++++ b/tools/bpf/bpftool/Documentation/bpftool.rst +@@ -19,14 +19,14 @@ SYNOPSIS + *OBJECT* := { **map** | **program** | **cgroup** | **perf** | **net** | **feature** } + + *OPTIONS* := { { **-V** | **--version** } | +- { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } } ++ { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-d** | **--debug** } } + + *MAP-COMMANDS* := + { **show** | **list** | **create** | **dump** | **update** | **lookup** | **getnext** | +- **delete** | **pin** | **event_pipe** | **help** } ++ **delete** | **pin** | **event_pipe** | **help** } + + *PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin** | +- **load** | **attach** | **detach** | **help** } ++ **load** | **attach** | **detach** | **help** } + + *CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** } + +diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile +index d73232be1e991..cce52df3be064 100644 +--- a/tools/bpf/bpftool/Makefile ++++ b/tools/bpf/bpftool/Makefile +@@ -1,6 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only + include ../../scripts/Makefile.include +-include ../../scripts/utilities.mak + + ifeq ($(srctree),) + srctree := $(patsubst %/,%,$(dir $(CURDIR))) +diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c +index 02eaaf065f651..d27ec4f852bbb 100644 +--- a/tools/bpf/bpftool/main.c ++++ b/tools/bpf/bpftool/main.c +@@ -402,6 +402,8 @@ int main(int argc, char **argv) + }; + int opt, ret; + ++ setlinebuf(stdout); ++ + last_do_help = do_help; + pretty_output = false; + json_output = false; +diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c +index 9c3e343b7d872..f8755beb3d9eb 100644 +--- a/tools/bpf/bpftool/prog.c ++++ b/tools/bpf/bpftool/prog.c +@@ -308,18 +308,12 @@ static void show_prog_metadata(int fd, __u32 num_maps) + if (printed_header) + jsonw_end_object(json_wtr); + } else { +- json_writer_t *btf_wtr = jsonw_new(stdout); ++ json_writer_t *btf_wtr; + struct btf_dumper d = { + .btf = btf, +- .jw = btf_wtr, + .is_plain_text = true, + }; + +- if (!btf_wtr) { +- p_err("jsonw alloc failed"); +- goto out_free; +- } +- + for (i = 0; i < vlen; i++, vsi++) { + t_var = btf__type_by_id(btf, vsi->type); + name = btf__name_by_offset(btf, t_var->name_off); +@@ -329,6 +323,14 @@ static void show_prog_metadata(int fd, __u32 num_maps) + + if (!printed_header) { + printf("\tmetadata:"); ++ ++ btf_wtr = jsonw_new(stdout); ++ if (!btf_wtr) { ++ p_err("jsonw alloc failed"); ++ goto out_free; ++ } ++ d.jw = btf_wtr, ++ + printed_header = true; + } + +@@ -627,8 +629,8 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + char func_sig[1024]; + unsigned char *buf; + __u32 member_len; ++ int fd, err = -1; + ssize_t n; +- int fd; + + if (mode == DUMP_JITED) { + if (info->jited_prog_len == 0 || !info->jited_prog_insns) { +@@ -667,7 +669,7 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + if (fd < 0) { + p_err("can't open file %s: %s", filepath, + strerror(errno)); +- return -1; ++ goto exit_free; + } + + n = write(fd, buf, member_len); +@@ -675,7 +677,7 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + if (n != (ssize_t)member_len) { + p_err("error writing output file: %s", + n < 0 ? strerror(errno) : "short write"); +- return -1; ++ goto exit_free; + } + + if (json_output) +@@ -689,7 +691,7 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + info->netns_ino, + &disasm_opt); + if (!name) +- return -1; ++ goto exit_free; + } + + if (info->nr_jited_func_lens && info->jited_func_lens) { +@@ -784,9 +786,12 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode, + kernel_syms_destroy(&dd); + } + +- btf__free(btf); ++ err = 0; + +- return 0; ++exit_free: ++ btf__free(btf); ++ bpf_prog_linfo__free(prog_linfo); ++ return err; + } + + static int do_dump(int argc, char **argv) +diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile +index bb9fa8de7e625..af9f9d3534c96 100644 +--- a/tools/bpf/resolve_btfids/Makefile ++++ b/tools/bpf/resolve_btfids/Makefile +@@ -9,7 +9,11 @@ ifeq ($(V),1) + msg = + else + Q = @ +- msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; ++ ifeq ($(silent),1) ++ msg = ++ else ++ msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; ++ endif + MAKEFLAGS=--no-print-directory + endif + +diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c +index de6365b53c9ca..45e0d640618ac 100644 +--- a/tools/bpf/resolve_btfids/main.c ++++ b/tools/bpf/resolve_btfids/main.c +@@ -166,7 +166,7 @@ static struct btf_id *btf_id__find(struct rb_root *root, const char *name) + return NULL; + } + +-static struct btf_id* ++static struct btf_id * + btf_id__add(struct rb_root *root, char *name, bool unique) + { + struct rb_node **p = &root->rb_node; +@@ -720,7 +720,8 @@ int main(int argc, const char **argv) + if (no_fail) + return 0; + pr_err("FAILED to find needed sections\n"); +- return -1; ++ err = 0; ++ goto out; + } + + if (symbols_collect(&obj)) +diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature +index 3dd2f68366f95..88dd7db55d385 100644 +--- a/tools/build/Makefile.feature ++++ b/tools/build/Makefile.feature +@@ -48,7 +48,6 @@ FEATURE_TESTS_BASIC := \ + numa_num_possible_cpus \ + libperl \ + libpython \ +- libpython-version \ + libslang \ + libslang-include-subdir \ + libtraceevent \ +diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile +index eff55d287db1f..e1e670014bd0c 100644 +--- a/tools/build/feature/Makefile ++++ b/tools/build/feature/Makefile +@@ -32,7 +32,6 @@ FILES= \ + test-numa_num_possible_cpus.bin \ + test-libperl.bin \ + test-libpython.bin \ +- test-libpython-version.bin \ + test-libslang.bin \ + test-libslang-include-subdir.bin \ + test-libtraceevent.bin \ +@@ -223,9 +222,6 @@ $(OUTPUT)test-libperl.bin: + $(OUTPUT)test-libpython.bin: + $(BUILD) $(FLAGS_PYTHON_EMBED) + +-$(OUTPUT)test-libpython-version.bin: +- $(BUILD) +- + $(OUTPUT)test-libbfd.bin: + $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl + +diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c +index 9204395272912..5ffafb967b6e4 100644 +--- a/tools/build/feature/test-all.c ++++ b/tools/build/feature/test-all.c +@@ -14,10 +14,6 @@ + # include "test-libpython.c" + #undef main + +-#define main main_test_libpython_version +-# include "test-libpython-version.c" +-#undef main +- + #define main main_test_libperl + # include "test-libperl.c" + #undef main +@@ -177,7 +173,6 @@ + int main(int argc, char *argv[]) + { + main_test_libpython(); +- main_test_libpython_version(); + main_test_libperl(); + main_test_hello(); + main_test_libelf(); +@@ -200,7 +195,6 @@ int main(int argc, char *argv[]) + main_test_timerfd(); + main_test_stackprotector_all(); + main_test_libdw_dwarf_unwind(); +- main_test_sync_compare_and_swap(argc, argv); + main_test_zlib(); + main_test_pthread_attr_setaffinity_np(); + main_test_pthread_barrier(); +diff --git a/tools/build/feature/test-libpython-version.c b/tools/build/feature/test-libpython-version.c +deleted file mode 100644 +index 47714b942d4d3..0000000000000 +--- a/tools/build/feature/test-libpython-version.c ++++ /dev/null +@@ -1,11 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-#include <Python.h> +- +-#if PY_VERSION_HEX >= 0x03000000 +- #error +-#endif +- +-int main(void) +-{ +- return 0; +-} +diff --git a/tools/include/asm-generic/unaligned.h b/tools/include/asm-generic/unaligned.h +new file mode 100644 +index 0000000000000..47387c607035e +--- /dev/null ++++ b/tools/include/asm-generic/unaligned.h +@@ -0,0 +1,23 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copied from the kernel sources to tools/perf/: ++ */ ++ ++#ifndef __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H ++#define __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H ++ ++#define __get_unaligned_t(type, ptr) ({ \ ++ const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ ++ __pptr->x; \ ++}) ++ ++#define __put_unaligned_t(type, val, ptr) do { \ ++ struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ ++ __pptr->x = (val); \ ++} while (0) ++ ++#define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) ++#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr)) ++ ++#endif /* __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H */ ++ +diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h +index 3430667b0d241..3e2c6f2ed587f 100644 +--- a/tools/include/nolibc/nolibc.h ++++ b/tools/include/nolibc/nolibc.h +@@ -399,16 +399,22 @@ struct stat { + }) + + /* startup code */ ++/* ++ * x86-64 System V ABI mandates: ++ * 1) %rsp must be 16-byte aligned right before the function call. ++ * 2) The deepest stack frame should be zero (the %rbp). ++ * ++ */ + asm(".section .text\n" + ".global _start\n" + "_start:\n" + "pop %rdi\n" // argc (first arg, %rdi) + "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) + "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) +- "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned when +- "sub $8, %rsp\n" // entering the callee ++ "xor %ebp, %ebp\n" // zero the stack frame ++ "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned before call + "call main\n" // main() returns the status code, we'll exit with it. +- "movzb %al, %rdi\n" // retrieve exit code from 8 lower bits ++ "mov %eax, %edi\n" // retrieve exit code (32 bit) + "mov $60, %rax\n" // NR_exit == 60 + "syscall\n" // really exit + "hlt\n" // ensure it does not return +@@ -577,20 +583,28 @@ struct sys_stat_struct { + }) + + /* startup code */ ++/* ++ * i386 System V ABI mandates: ++ * 1) last pushed argument must be 16-byte aligned. ++ * 2) The deepest stack frame should be set to zero ++ * ++ */ + asm(".section .text\n" + ".global _start\n" + "_start:\n" + "pop %eax\n" // argc (first arg, %eax) + "mov %esp, %ebx\n" // argv[] (second arg, %ebx) + "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) +- "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned when ++ "xor %ebp, %ebp\n" // zero the stack frame ++ "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before ++ "sub $4, %esp\n" // the call instruction (args are aligned) + "push %ecx\n" // push all registers on the stack so that we + "push %ebx\n" // support both regparm and plain stack modes + "push %eax\n" + "call main\n" // main() returns the status code in %eax +- "movzbl %al, %ebx\n" // retrieve exit code from lower 8 bits +- "movl $1, %eax\n" // NR_exit == 1 +- "int $0x80\n" // exit now ++ "mov %eax, %ebx\n" // retrieve exit code (32-bit int) ++ "movl $1, %eax\n" // NR_exit == 1 ++ "int $0x80\n" // exit now + "hlt\n" // ensure it does not + ""); + +@@ -774,7 +788,6 @@ asm(".section .text\n" + "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the + "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc) + "bl main\n" // main() returns the status code, we'll exit with it. +- "and %r0, %r0, $0xff\n" // limit exit code to 8 bits + "movs r7, $1\n" // NR_exit == 1 + "svc $0x00\n" + ""); +@@ -971,7 +984,6 @@ asm(".section .text\n" + "add x2, x2, x1\n" // + argv + "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee + "bl main\n" // main() returns the status code, we'll exit with it. +- "and x0, x0, 0xff\n" // limit exit code to 8 bits + "mov x8, 93\n" // NR_exit == 93 + "svc #0\n" + ""); +@@ -1176,7 +1188,7 @@ asm(".section .text\n" + "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there! + "jal main\n" // main() returns the status code, we'll exit with it. + "nop\n" // delayed slot +- "and $a0, $v0, 0xff\n" // limit exit code to 8 bits ++ "move $a0, $v0\n" // retrieve 32-bit exit code from v0 + "li $v0, 4001\n" // NR_exit == 4001 + "syscall\n" + ".end __start\n" +@@ -1374,7 +1386,6 @@ asm(".section .text\n" + "add a2,a2,a1\n" // + argv + "andi sp,a1,-16\n" // sp must be 16-byte aligned + "call main\n" // main() returns the status code, we'll exit with it. +- "andi a0, a0, 0xff\n" // limit exit code to 8 bits + "li a7, 93\n" // NR_exit == 93 + "ecall\n" + ""); +diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h +index 5859ca0a1439b..93e40f91bd49a 100644 +--- a/tools/include/uapi/sound/asound.h ++++ b/tools/include/uapi/sound/asound.h +@@ -56,8 +56,10 @@ + * * + ****************************************************************************/ + ++#define AES_IEC958_STATUS_SIZE 24 ++ + struct snd_aes_iec958 { +- unsigned char status[24]; /* AES/IEC958 channel status bits */ ++ unsigned char status[AES_IEC958_STATUS_SIZE]; /* AES/IEC958 channel status bits */ + unsigned char subcode[147]; /* AES/IEC958 subcode bits */ + unsigned char pad; /* nothing */ + unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ +diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c +index 2401fad090c52..bfd1ce9fe2110 100644 +--- a/tools/lib/bpf/bpf.c ++++ b/tools/lib/bpf/bpf.c +@@ -480,6 +480,7 @@ int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value) + int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags) + { + union bpf_attr attr; ++ int ret; + + memset(&attr, 0, sizeof(attr)); + attr.map_fd = fd; +@@ -487,7 +488,8 @@ int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, _ + attr.value = ptr_to_u64(value); + attr.flags = flags; + +- return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); ++ ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr)); ++ return libbpf_err_errno(ret); + } + + int bpf_map_delete_elem(int fd, const void *key) +diff --git a/tools/lib/bpf/bpf_core_read.h b/tools/lib/bpf/bpf_core_read.h +index 09ebe3db5f2f8..e4aa9996a5501 100644 +--- a/tools/lib/bpf/bpf_core_read.h ++++ b/tools/lib/bpf/bpf_core_read.h +@@ -40,7 +40,7 @@ enum bpf_enum_value_kind { + #define __CORE_RELO(src, field, info) \ + __builtin_preserve_field_info((src)->field, BPF_FIELD_##info) + +-#if __BYTE_ORDER == __LITTLE_ENDIAN ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define __CORE_BITFIELD_PROBE_READ(dst, src, fld) \ + bpf_probe_read_kernel( \ + (void *)dst, \ +diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c +index 77dc24d58302d..5f3d20ae66d56 100644 +--- a/tools/lib/bpf/btf.c ++++ b/tools/lib/bpf/btf.c +@@ -231,17 +231,23 @@ static int btf_parse_hdr(struct btf *btf) + } + btf_bswap_hdr(hdr); + } else if (hdr->magic != BTF_MAGIC) { +- pr_debug("Invalid BTF magic:%x\n", hdr->magic); ++ pr_debug("Invalid BTF magic: %x\n", hdr->magic); + return -EINVAL; + } + +- meta_left = btf->raw_size - sizeof(*hdr); +- if (meta_left < hdr->str_off + hdr->str_len) { +- pr_debug("Invalid BTF total size:%u\n", btf->raw_size); ++ if (btf->raw_size < hdr->hdr_len) { ++ pr_debug("BTF header len %u larger than data size %u\n", ++ hdr->hdr_len, btf->raw_size); + return -EINVAL; + } + +- if (hdr->type_off + hdr->type_len > hdr->str_off) { ++ meta_left = btf->raw_size - hdr->hdr_len; ++ if (meta_left < (long long)hdr->str_off + hdr->str_len) { ++ pr_debug("Invalid BTF total size: %u\n", btf->raw_size); ++ return -EINVAL; ++ } ++ ++ if ((long long)hdr->type_off + hdr->type_len > hdr->str_off) { + pr_debug("Invalid BTF data sections layout: type data at %u + %u, strings data at %u + %u\n", + hdr->type_off, hdr->type_len, hdr->str_off, hdr->str_len); + return -EINVAL; +@@ -2620,15 +2626,11 @@ void btf_ext__free(struct btf_ext *btf_ext) + free(btf_ext); + } + +-struct btf_ext *btf_ext__new(__u8 *data, __u32 size) ++struct btf_ext *btf_ext__new(const __u8 *data, __u32 size) + { + struct btf_ext *btf_ext; + int err; + +- err = btf_ext_parse_hdr(data, size); +- if (err) +- return libbpf_err_ptr(err); +- + btf_ext = calloc(1, sizeof(struct btf_ext)); + if (!btf_ext) + return libbpf_err_ptr(-ENOMEM); +@@ -2641,6 +2643,10 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) + } + memcpy(btf_ext->data, data, size); + ++ err = btf_ext_parse_hdr(btf_ext->data, size); ++ if (err) ++ goto done; ++ + if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, line_info_len)) { + err = -EINVAL; + goto done; +@@ -2914,8 +2920,10 @@ int btf__dedup(struct btf *btf, struct btf_ext *btf_ext, + return libbpf_err(-EINVAL); + } + +- if (btf_ensure_modifiable(btf)) +- return libbpf_err(-ENOMEM); ++ if (btf_ensure_modifiable(btf)) { ++ err = -ENOMEM; ++ goto done; ++ } + + err = btf_dedup_prep(d); + if (err) { +@@ -3350,8 +3358,8 @@ static long btf_hash_struct(struct btf_type *t) + } + + /* +- * Check structural compatibility of two FUNC_PROTOs, ignoring referenced type +- * IDs. This check is performed during type graph equivalence check and ++ * Check structural compatibility of two STRUCTs/UNIONs, ignoring referenced ++ * type IDs. This check is performed during type graph equivalence check and + * referenced types equivalence is checked separately. + */ + static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2) +@@ -3722,6 +3730,31 @@ static int btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2) + return btf_equal_array(t1, t2); + } + ++/* Check if given two types are identical STRUCT/UNION definitions */ ++static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id2) ++{ ++ const struct btf_member *m1, *m2; ++ struct btf_type *t1, *t2; ++ int n, i; ++ ++ t1 = btf_type_by_id(d->btf, id1); ++ t2 = btf_type_by_id(d->btf, id2); ++ ++ if (!btf_is_composite(t1) || btf_kind(t1) != btf_kind(t2)) ++ return false; ++ ++ if (!btf_shallow_equal_struct(t1, t2)) ++ return false; ++ ++ m1 = btf_members(t1); ++ m2 = btf_members(t2); ++ for (i = 0, n = btf_vlen(t1); i < n; i++, m1++, m2++) { ++ if (m1->type != m2->type) ++ return false; ++ } ++ return true; ++} ++ + /* + * Check equivalence of BTF type graph formed by candidate struct/union (we'll + * call it "candidate graph" in this description for brevity) to a type graph +@@ -3833,6 +3866,8 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, + + hypot_type_id = d->hypot_map[canon_id]; + if (hypot_type_id <= BTF_MAX_NR_TYPES) { ++ if (hypot_type_id == cand_id) ++ return 1; + /* In some cases compiler will generate different DWARF types + * for *identical* array type definitions and use them for + * different fields within the *same* struct. This breaks type +@@ -3841,8 +3876,18 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, + * types within a single CU. So work around that by explicitly + * allowing identical array types here. + */ +- return hypot_type_id == cand_id || +- btf_dedup_identical_arrays(d, hypot_type_id, cand_id); ++ if (btf_dedup_identical_arrays(d, hypot_type_id, cand_id)) ++ return 1; ++ /* It turns out that similar situation can happen with ++ * struct/union sometimes, sigh... Handle the case where ++ * structs/unions are exactly the same, down to the referenced ++ * type IDs. Anything more complicated (e.g., if referenced ++ * types are different, but equivalent) is *way more* ++ * complicated and requires a many-to-many equivalence mapping. ++ */ ++ if (btf_dedup_identical_structs(d, hypot_type_id, cand_id)) ++ return 1; ++ return 0; + } + + if (btf_dedup_hypot_map_add(d, canon_id, cand_id)) +diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h +index 4a711f990904b..b0ee338a0cc87 100644 +--- a/tools/lib/bpf/btf.h ++++ b/tools/lib/bpf/btf.h +@@ -80,7 +80,7 @@ LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name, + __u32 expected_value_size, + __u32 *key_type_id, __u32 *value_type_id); + +-LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size); ++LIBBPF_API struct btf_ext *btf_ext__new(const __u8 *data, __u32 size); + LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext); + LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, + __u32 *size); +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index e4b483f15fb99..8c9325802793b 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -2186,7 +2186,7 @@ static int btf_dump_dump_type_data(struct btf_dump *d, + __u8 bits_offset, + __u8 bit_sz) + { +- int size, err; ++ int size, err = 0; + + size = btf_dump_type_data_check_overflow(d, t, id, data, bits_offset); + if (size < 0) +diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c +index 8df718a6b142d..33c19590ee434 100644 +--- a/tools/lib/bpf/gen_loader.c ++++ b/tools/lib/bpf/gen_loader.c +@@ -663,9 +663,11 @@ void bpf_gen__prog_load(struct bpf_gen *gen, + debug_ret(gen, "prog_load %s insn_cnt %d", attr.prog_name, attr.insn_cnt); + /* successful or not, close btf module FDs used in extern ksyms and attach_btf_obj_fd */ + cleanup_relos(gen, insns); +- if (gen->attach_kind) ++ if (gen->attach_kind) { + emit_sys_close_blob(gen, + attr_field(prog_load_attr, attach_btf_obj_fd)); ++ gen->attach_kind = 0; ++ } + emit_check_err(gen); + /* remember prog_fd in the stack, if successful */ + emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7, +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index e4f83c304ec92..0ad29203cbfbf 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -2993,6 +2993,12 @@ static int bpf_object__elf_collect(struct bpf_object *obj) + } + } + ++ if (!obj->efile.symbols) { ++ pr_warn("elf: couldn't find symbol table in %s, stripped object file?\n", ++ obj->path); ++ return -ENOENT; ++ } ++ + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) { + idx++; +@@ -5132,7 +5138,7 @@ static int bpf_core_apply_relo(struct bpf_program *prog, + * relocated, so it's enough to just subtract in-section offset + */ + insn_idx = insn_idx - prog->sec_insn_off; +- if (insn_idx > prog->insns_cnt) ++ if (insn_idx >= prog->insns_cnt) + return -EINVAL; + insn = &prog->insns[insn_idx]; + +@@ -8670,7 +8676,10 @@ int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd) + pr_warn("error: inner_map_fd already specified\n"); + return libbpf_err(-EINVAL); + } +- zfree(&map->inner_map); ++ if (map->inner_map) { ++ bpf_map__destroy(map->inner_map); ++ zfree(&map->inner_map); ++ } + map->inner_map_fd = fd; + return 0; + } +diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c +index 2df880cefdaee..6b2f59ddb6918 100644 +--- a/tools/lib/bpf/linker.c ++++ b/tools/lib/bpf/linker.c +@@ -211,6 +211,7 @@ void bpf_linker__free(struct bpf_linker *linker) + } + free(linker->secs); + ++ free(linker->glob_syms); + free(linker); + } + +@@ -2000,7 +2001,7 @@ add_sym: + static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *obj) + { + struct src_sec *src_symtab = &obj->secs[obj->symtab_sec_idx]; +- struct dst_sec *dst_symtab = &linker->secs[linker->symtab_sec_idx]; ++ struct dst_sec *dst_symtab; + int i, err; + + for (i = 1; i < obj->sec_cnt; i++) { +@@ -2033,6 +2034,9 @@ static int linker_append_elf_relos(struct bpf_linker *linker, struct src_obj *ob + return -1; + } + ++ /* add_dst_sec() above could have invalidated linker->secs */ ++ dst_symtab = &linker->secs[linker->symtab_sec_idx]; ++ + /* shdr->sh_link points to SYMTAB */ + dst_sec->shdr->sh_link = linker->symtab_sec_idx; + +diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h +index b22b50c1b173e..9cf66702fa8dd 100644 +--- a/tools/lib/bpf/skel_internal.h ++++ b/tools/lib/bpf/skel_internal.h +@@ -105,10 +105,12 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) + err = skel_sys_bpf(BPF_PROG_RUN, &attr, sizeof(attr)); + if (err < 0 || (int)attr.test.retval < 0) { + opts->errstr = "failed to execute loader prog"; +- if (err < 0) ++ if (err < 0) { + err = -errno; +- else ++ } else { + err = (int)attr.test.retval; ++ errno = -err; ++ } + goto out; + } + err = 0; +diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h +index 794a375dad360..b2aec04fce8f6 100644 +--- a/tools/lib/subcmd/subcmd-util.h ++++ b/tools/lib/subcmd/subcmd-util.h +@@ -50,15 +50,8 @@ static NORETURN inline void die(const char *err, ...) + static inline void *xrealloc(void *ptr, size_t size) + { + void *ret = realloc(ptr, size); +- if (!ret && !size) +- ret = realloc(ptr, 1); +- if (!ret) { +- ret = realloc(ptr, size); +- if (!ret && !size) +- ret = realloc(ptr, 1); +- if (!ret) +- die("Out of memory, realloc failed"); +- } ++ if (!ret) ++ die("Out of memory, realloc failed"); + return ret; + } + +diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c +index 0893436cc09f8..77b51600e3e94 100644 +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -659,6 +659,26 @@ const char *arch_nop_insn(int len) + return nops[len-1]; + } + ++#define BYTE_RET 0xC3 ++ ++const char *arch_ret_insn(int len) ++{ ++ static const char ret[5][5] = { ++ { BYTE_RET }, ++ { BYTE_RET, BYTES_NOP1 }, ++ { BYTE_RET, BYTES_NOP2 }, ++ { BYTE_RET, BYTES_NOP3 }, ++ { BYTE_RET, BYTES_NOP4 }, ++ }; ++ ++ if (len < 1 || len > 5) { ++ WARN("invalid RET size: %d\n", len); ++ return NULL; ++ } ++ ++ return ret[len-1]; ++} ++ + /* asm/alternative.h ? */ + + #define ALTINSTR_FLAG_INV (1 << 15) +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 06b5c164ae931..81982948f981d 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -173,6 +173,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, + "rewind_stack_do_exit", + "kunit_try_catch_throw", + "xen_start_kernel", ++ "cpu_bringup_and_idle", + }; + + if (!func) +@@ -828,6 +829,79 @@ static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *i + return insn->reloc; + } + ++static void remove_insn_ops(struct instruction *insn) ++{ ++ struct stack_op *op, *tmp; ++ ++ list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { ++ list_del(&op->list); ++ free(op); ++ } ++} ++ ++static void add_call_dest(struct objtool_file *file, struct instruction *insn, ++ struct symbol *dest, bool sibling) ++{ ++ struct reloc *reloc = insn_reloc(file, insn); ++ ++ insn->call_dest = dest; ++ if (!dest) ++ return; ++ ++ if (insn->call_dest->static_call_tramp) { ++ list_add_tail(&insn->call_node, ++ &file->static_call_list); ++ } ++ ++ /* ++ * Many compilers cannot disable KCOV with a function attribute ++ * so they need a little help, NOP out any KCOV calls from noinstr ++ * text. ++ */ ++ if (insn->sec->noinstr && ++ !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) { ++ if (reloc) { ++ reloc->type = R_NONE; ++ elf_write_reloc(file->elf, reloc); ++ } ++ ++ elf_write_insn(file->elf, insn->sec, ++ insn->offset, insn->len, ++ sibling ? arch_ret_insn(insn->len) ++ : arch_nop_insn(insn->len)); ++ ++ insn->type = sibling ? INSN_RETURN : INSN_NOP; ++ } ++ ++ if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) { ++ if (sibling) ++ WARN_FUNC("Tail call to __fentry__ !?!?", insn->sec, insn->offset); ++ ++ if (reloc) { ++ reloc->type = R_NONE; ++ elf_write_reloc(file->elf, reloc); ++ } ++ ++ elf_write_insn(file->elf, insn->sec, ++ insn->offset, insn->len, ++ arch_nop_insn(insn->len)); ++ ++ insn->type = INSN_NOP; ++ ++ list_add_tail(&insn->mcount_loc_node, ++ &file->mcount_loc_list); ++ } ++ ++ /* ++ * Whatever stack impact regular CALLs have, should be undone ++ * by the RETURN of the called function. ++ * ++ * Annotated intra-function calls retain the stack_ops but ++ * are converted to JUMP, see read_intra_function_calls(). ++ */ ++ remove_insn_ops(insn); ++} ++ + /* + * Find the destination instructions for all jumps. + */ +@@ -866,11 +940,7 @@ static int add_jump_destinations(struct objtool_file *file) + continue; + } else if (insn->func) { + /* internal or external sibling call (with reloc) */ +- insn->call_dest = reloc->sym; +- if (insn->call_dest->static_call_tramp) { +- list_add_tail(&insn->call_node, +- &file->static_call_list); +- } ++ add_call_dest(file, insn, reloc->sym, true); + continue; + } else if (reloc->sym->sec->idx) { + dest_sec = reloc->sym->sec; +@@ -926,13 +996,8 @@ static int add_jump_destinations(struct objtool_file *file) + + } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && + insn->jump_dest->offset == insn->jump_dest->func->offset) { +- + /* internal sibling call (without reloc) */ +- insn->call_dest = insn->jump_dest->func; +- if (insn->call_dest->static_call_tramp) { +- list_add_tail(&insn->call_node, +- &file->static_call_list); +- } ++ add_call_dest(file, insn, insn->jump_dest->func, true); + } + } + } +@@ -940,16 +1005,6 @@ static int add_jump_destinations(struct objtool_file *file) + return 0; + } + +-static void remove_insn_ops(struct instruction *insn) +-{ +- struct stack_op *op, *tmp; +- +- list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { +- list_del(&op->list); +- free(op); +- } +-} +- + static struct symbol *find_call_destination(struct section *sec, unsigned long offset) + { + struct symbol *call_dest; +@@ -968,6 +1023,7 @@ static int add_call_destinations(struct objtool_file *file) + { + struct instruction *insn; + unsigned long dest_off; ++ struct symbol *dest; + struct reloc *reloc; + + for_each_insn(file, insn) { +@@ -977,7 +1033,9 @@ static int add_call_destinations(struct objtool_file *file) + reloc = insn_reloc(file, insn); + if (!reloc) { + dest_off = arch_jump_destination(insn); +- insn->call_dest = find_call_destination(insn->sec, dest_off); ++ dest = find_call_destination(insn->sec, dest_off); ++ ++ add_call_dest(file, insn, dest, false); + + if (insn->ignore) + continue; +@@ -995,9 +1053,8 @@ static int add_call_destinations(struct objtool_file *file) + + } else if (reloc->sym->type == STT_SECTION) { + dest_off = arch_dest_reloc_offset(reloc->addend); +- insn->call_dest = find_call_destination(reloc->sym->sec, +- dest_off); +- if (!insn->call_dest) { ++ dest = find_call_destination(reloc->sym->sec, dest_off); ++ if (!dest) { + WARN_FUNC("can't find call dest symbol at %s+0x%lx", + insn->sec, insn->offset, + reloc->sym->sec->name, +@@ -1005,6 +1062,8 @@ static int add_call_destinations(struct objtool_file *file) + return -1; + } + ++ add_call_dest(file, insn, dest, false); ++ + } else if (arch_is_retpoline(reloc->sym)) { + /* + * Retpoline calls are really dynamic calls in +@@ -1020,55 +1079,7 @@ static int add_call_destinations(struct objtool_file *file) + continue; + + } else +- insn->call_dest = reloc->sym; +- +- if (insn->call_dest && insn->call_dest->static_call_tramp) { +- list_add_tail(&insn->call_node, +- &file->static_call_list); +- } +- +- /* +- * Many compilers cannot disable KCOV with a function attribute +- * so they need a little help, NOP out any KCOV calls from noinstr +- * text. +- */ +- if (insn->sec->noinstr && +- !strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) { +- if (reloc) { +- reloc->type = R_NONE; +- elf_write_reloc(file->elf, reloc); +- } +- +- elf_write_insn(file->elf, insn->sec, +- insn->offset, insn->len, +- arch_nop_insn(insn->len)); +- insn->type = INSN_NOP; +- } +- +- if (mcount && !strcmp(insn->call_dest->name, "__fentry__")) { +- if (reloc) { +- reloc->type = R_NONE; +- elf_write_reloc(file->elf, reloc); +- } +- +- elf_write_insn(file->elf, insn->sec, +- insn->offset, insn->len, +- arch_nop_insn(insn->len)); +- +- insn->type = INSN_NOP; +- +- list_add_tail(&insn->mcount_loc_node, +- &file->mcount_loc_list); +- } +- +- /* +- * Whatever stack impact regular CALLs have, should be undone +- * by the RETURN of the called function. +- * +- * Annotated intra-function calls retain the stack_ops but +- * are converted to JUMP, see read_intra_function_calls(). +- */ +- remove_insn_ops(insn); ++ add_call_dest(file, insn, reloc->sym, false); + } + + return 0; +diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h +index 062bb6e9b8658..478e054fcdf71 100644 +--- a/tools/objtool/include/objtool/arch.h ++++ b/tools/objtool/include/objtool/arch.h +@@ -82,6 +82,7 @@ unsigned long arch_jump_destination(struct instruction *insn); + unsigned long arch_dest_reloc_offset(int addend); + + const char *arch_nop_insn(int len); ++const char *arch_ret_insn(int len); + + int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg); + +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index 14e3e8d702a02..71772b20ea737 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -143,7 +143,10 @@ FEATURE_CHECK_LDFLAGS-libcrypto = -lcrypto + ifdef CSINCLUDES + LIBOPENCSD_CFLAGS := -I$(CSINCLUDES) + endif +-OPENCSDLIBS := -lopencsd_c_api -lopencsd -lstdc++ ++OPENCSDLIBS := -lopencsd_c_api ++ifeq ($(findstring -static,${LDFLAGS}),-static) ++ OPENCSDLIBS += -lopencsd -lstdc++ ++endif + ifdef CSLIBS + LIBOPENCSD_LDFLAGS := -L$(CSLIBS) + endif +@@ -271,8 +274,6 @@ endif + + FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) + FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) +-FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) +-FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) + + FEATURE_CHECK_LDFLAGS-libaio = -lrt + +diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c +index 5d1fe9c35807a..137890f78e17a 100644 +--- a/tools/perf/bench/futex-lock-pi.c ++++ b/tools/perf/bench/futex-lock-pi.c +@@ -233,6 +233,7 @@ int bench_futex_lock_pi(int argc, const char **argv) + print_summary(); + + free(worker); ++ perf_cpu_map__put(cpu); + return ret; + err: + usage_with_options(bench_futex_lock_pi_usage, options); +diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c +index 97fe31fd3a236..f7a5ffebb9408 100644 +--- a/tools/perf/bench/futex-requeue.c ++++ b/tools/perf/bench/futex-requeue.c +@@ -294,6 +294,7 @@ int bench_futex_requeue(int argc, const char **argv) + print_summary(); + + free(worker); ++ perf_cpu_map__put(cpu); + return ret; + err: + usage_with_options(bench_futex_requeue_usage, options); +diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c +index e970e6b9ad535..0983f40b4b408 100644 +--- a/tools/perf/bench/futex-wake-parallel.c ++++ b/tools/perf/bench/futex-wake-parallel.c +@@ -329,6 +329,7 @@ int bench_futex_wake_parallel(int argc, const char **argv) + print_summary(); + + free(blocked_worker); ++ perf_cpu_map__put(cpu); + return ret; + } + #endif /* HAVE_PTHREAD_BARRIER */ +diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c +index 77f058a477903..2226a475e782b 100644 +--- a/tools/perf/bench/futex-wake.c ++++ b/tools/perf/bench/futex-wake.c +@@ -222,5 +222,6 @@ int bench_futex_wake(int argc, const char **argv) + print_summary(); + + free(worker); ++ perf_cpu_map__put(cpu); + return ret; + } +diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c +index 6ad191e731fc9..50c2e6892b3e9 100644 +--- a/tools/perf/builtin-inject.c ++++ b/tools/perf/builtin-inject.c +@@ -755,12 +755,16 @@ static int parse_vm_time_correlation(const struct option *opt, const char *str, + return inject->itrace_synth_opts.vm_tm_corr_args ? 0 : -ENOMEM; + } + ++static int output_fd(struct perf_inject *inject) ++{ ++ return inject->in_place_update ? -1 : perf_data__fd(&inject->output); ++} ++ + static int __cmd_inject(struct perf_inject *inject) + { + int ret = -EINVAL; + struct perf_session *session = inject->session; +- struct perf_data *data_out = &inject->output; +- int fd = inject->in_place_update ? -1 : perf_data__fd(data_out); ++ int fd = output_fd(inject); + u64 output_data_offset; + + signal(SIGINT, sig_handler); +@@ -819,7 +823,7 @@ static int __cmd_inject(struct perf_inject *inject) + inject->tool.ordered_events = true; + inject->tool.ordering_requires_timestamps = true; + /* Allow space in the header for new attributes */ +- output_data_offset = 4096; ++ output_data_offset = roundup(8192 + session->header.data_offset, 4096); + if (inject->strip) + strip_init(inject); + } +@@ -1006,7 +1010,7 @@ int cmd_inject(int argc, const char **argv) + } + + inject.session = __perf_session__new(&data, repipe, +- perf_data__fd(&inject.output), ++ output_fd(&inject), + &inject.tool); + if (IS_ERR(inject.session)) { + ret = PTR_ERR(inject.session); +@@ -1069,7 +1073,8 @@ out_delete: + zstd_fini(&(inject.session->zstd_data)); + perf_session__delete(inject.session); + out_close_output: +- perf_data__close(&inject.output); ++ if (!inject.in_place_update) ++ perf_data__close(&inject.output); + free(inject.itrace_synth_opts.vm_tm_corr_args); + return ret; + } +diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c +index a0316ce910db6..997e0a4b0902a 100644 +--- a/tools/perf/builtin-report.c ++++ b/tools/perf/builtin-report.c +@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep) + int ret; + struct perf_session *session = rep->session; + struct evlist *evlist = session->evlist; +- const char *help = perf_tip(system_path(TIPDIR)); ++ char *help = NULL, *path = NULL; + +- if (help == NULL) { ++ path = system_path(TIPDIR); ++ if (perf_tip(&help, path) || help == NULL) { + /* fallback for people who don't install perf ;-) */ +- help = perf_tip(DOCDIR); +- if (help == NULL) +- help = "Cannot load tips.txt file, please install perf!"; ++ free(path); ++ path = system_path(DOCDIR); ++ if (perf_tip(&help, path) || help == NULL) ++ help = strdup("Cannot load tips.txt file, please install perf!"); + } ++ free(path); + + switch (use_browser) { + case 1: +@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep) + ret = evlist__tty_browse_hists(evlist, rep, help); + break; + } +- ++ free(help); + return ret; + } + +diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c +index c32c2eb16d7df..18b56256bb6ff 100644 +--- a/tools/perf/builtin-script.c ++++ b/tools/perf/builtin-script.c +@@ -2463,7 +2463,7 @@ static int process_switch_event(struct perf_tool *tool, + if (perf_event__process_switch(tool, event, sample, machine) < 0) + return -1; + +- if (scripting_ops && scripting_ops->process_switch) ++ if (scripting_ops && scripting_ops->process_switch && !filter_cpu(sample)) + scripting_ops->process_switch(event, sample, machine); + + if (!script->show_switch_events) +diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py +index 1d3a189a9a547..66452a8ec3586 100644 +--- a/tools/perf/scripts/python/intel-pt-events.py ++++ b/tools/perf/scripts/python/intel-pt-events.py +@@ -32,8 +32,7 @@ try: + except: + broken_pipe_exception = IOError + +-glb_switch_str = None +-glb_switch_printed = True ++glb_switch_str = {} + glb_insn = False + glb_disassembler = None + glb_src = False +@@ -70,6 +69,7 @@ def trace_begin(): + ap = argparse.ArgumentParser(usage = "", add_help = False) + ap.add_argument("--insn-trace", action='store_true') + ap.add_argument("--src-trace", action='store_true') ++ ap.add_argument("--all-switch-events", action='store_true') + global glb_args + global glb_insn + global glb_src +@@ -256,10 +256,6 @@ def print_srccode(comm, param_dict, sample, symbol, dso, with_insn): + print(start_str, src_str) + + def do_process_event(param_dict): +- global glb_switch_printed +- if not glb_switch_printed: +- print(glb_switch_str) +- glb_switch_printed = True + event_attr = param_dict["attr"] + sample = param_dict["sample"] + raw_buf = param_dict["raw_buf"] +@@ -274,6 +270,11 @@ def do_process_event(param_dict): + dso = get_optional(param_dict, "dso") + symbol = get_optional(param_dict, "symbol") + ++ cpu = sample["cpu"] ++ if cpu in glb_switch_str: ++ print(glb_switch_str[cpu]) ++ del glb_switch_str[cpu] ++ + if name[0:12] == "instructions": + if glb_src: + print_srccode(comm, param_dict, sample, symbol, dso, True) +@@ -336,8 +337,6 @@ def auxtrace_error(typ, code, cpu, pid, tid, ip, ts, msg, cpumode, *x): + sys.exit(1) + + def context_switch(ts, cpu, pid, tid, np_pid, np_tid, machine_pid, out, out_preempt, *x): +- global glb_switch_printed +- global glb_switch_str + if out: + out_str = "Switch out " + else: +@@ -350,6 +349,10 @@ def context_switch(ts, cpu, pid, tid, np_pid, np_tid, machine_pid, out, out_pree + machine_str = "" + else: + machine_str = "machine PID %d" % machine_pid +- glb_switch_str = "%16s %5d/%-5d [%03u] %9u.%09u %5d/%-5d %s %s" % \ ++ switch_str = "%16s %5d/%-5d [%03u] %9u.%09u %5d/%-5d %s %s" % \ + (out_str, pid, tid, cpu, ts / 1000000000, ts %1000000000, np_pid, np_tid, machine_str, preempt_str) +- glb_switch_printed = False ++ if glb_args.all_switch_events: ++ print(switch_str); ++ else: ++ global glb_switch_str ++ glb_switch_str[cpu] = switch_str +diff --git a/tools/perf/tests/shell/record+zstd_comp_decomp.sh b/tools/perf/tests/shell/record+zstd_comp_decomp.sh +index 8a168cf8bacca..49bd875d51227 100755 +--- a/tools/perf/tests/shell/record+zstd_comp_decomp.sh ++++ b/tools/perf/tests/shell/record+zstd_comp_decomp.sh +@@ -12,7 +12,7 @@ skip_if_no_z_record() { + + collect_z_record() { + echo "Collecting compressed record file:" +- [[ "$(uname -m)" != s390x ]] && gflag='-g' ++ [ "$(uname -m)" != s390x ] && gflag='-g' + $perf_tool record -o $trace_file $gflag -z -F 5000 -- \ + dd count=500 if=/dev/urandom of=/dev/null + } +diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c +index e81c2493efdf9..44ba900828f6c 100644 +--- a/tools/perf/ui/browsers/annotate.c ++++ b/tools/perf/ui/browsers/annotate.c +@@ -966,6 +966,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, + .opts = opts, + }; + int ret = -1, err; ++ int not_annotated = list_empty(¬es->src->source); + + if (sym == NULL) + return -1; +@@ -973,13 +974,15 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, + if (ms->map->dso->annotate_warned) + return -1; + +- err = symbol__annotate2(ms, evsel, opts, &browser.arch); +- if (err) { +- char msg[BUFSIZ]; +- ms->map->dso->annotate_warned = true; +- symbol__strerror_disassemble(ms, err, msg, sizeof(msg)); +- ui__error("Couldn't annotate %s:\n%s", sym->name, msg); +- goto out_free_offsets; ++ if (not_annotated) { ++ err = symbol__annotate2(ms, evsel, opts, &browser.arch); ++ if (err) { ++ char msg[BUFSIZ]; ++ ms->map->dso->annotate_warned = true; ++ symbol__strerror_disassemble(ms, err, msg, sizeof(msg)); ++ ui__error("Couldn't annotate %s:\n%s", sym->name, msg); ++ goto out_free_offsets; ++ } + } + + ui_helpline__push("Press ESC to exit"); +@@ -994,9 +997,11 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, + + ret = annotate_browser__run(&browser, evsel, hbt); + +- annotated_source__purge(notes->src); ++ if(not_annotated) ++ annotated_source__purge(notes->src); + + out_free_offsets: +- zfree(¬es->offsets); ++ if(not_annotated) ++ zfree(¬es->offsets); + return ret; + } +diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c +index c1f24d0048527..5075ecead5f3d 100644 +--- a/tools/perf/ui/hist.c ++++ b/tools/perf/ui/hist.c +@@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = { + #undef __HPP_SORT_ACC_FN + #undef __HPP_SORT_RAW_FN + ++static void fmt_free(struct perf_hpp_fmt *fmt) ++{ ++ /* ++ * At this point fmt should be completely ++ * unhooked, if not it's a bug. ++ */ ++ BUG_ON(!list_empty(&fmt->list)); ++ BUG_ON(!list_empty(&fmt->sort_list)); ++ ++ if (fmt->free) ++ fmt->free(fmt); ++} + + void perf_hpp__init(void) + { +@@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, + list_add(&format->sort_list, &list->sorts); + } + +-void perf_hpp__column_unregister(struct perf_hpp_fmt *format) ++static void perf_hpp__column_unregister(struct perf_hpp_fmt *format) + { + list_del_init(&format->list); ++ fmt_free(format); + } + + void perf_hpp__cancel_cumulate(void) +@@ -672,19 +685,6 @@ next: + } + + +-static void fmt_free(struct perf_hpp_fmt *fmt) +-{ +- /* +- * At this point fmt should be completely +- * unhooked, if not it's a bug. +- */ +- BUG_ON(!list_empty(&fmt->list)); +- BUG_ON(!list_empty(&fmt->sort_list)); +- +- if (fmt->free) +- fmt->free(fmt); +-} +- + void perf_hpp__reset_output_field(struct perf_hpp_list *list) + { + struct perf_hpp_fmt *fmt, *tmp; +diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c +index 58b7069c5a5f8..7054f23150e1b 100644 +--- a/tools/perf/util/arm-spe.c ++++ b/tools/perf/util/arm-spe.c +@@ -51,6 +51,7 @@ struct arm_spe { + u8 timeless_decoding; + u8 data_queued; + ++ u64 sample_type; + u8 sample_flc; + u8 sample_llc; + u8 sample_tlb; +@@ -248,6 +249,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe, + event->sample.header.size = sizeof(struct perf_event_header); + } + ++static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type) ++{ ++ event->header.size = perf_event__sample_event_size(sample, type, 0); ++ return perf_event__synthesize_sample(event, type, 0, sample); ++} ++ + static inline int + arm_spe_deliver_synth_event(struct arm_spe *spe, + struct arm_spe_queue *speq __maybe_unused, +@@ -256,6 +263,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe, + { + int ret; + ++ if (spe->synth_opts.inject) { ++ ret = arm_spe__inject_event(event, sample, spe->sample_type); ++ if (ret) ++ return ret; ++ } ++ + ret = perf_session__deliver_synth_event(spe->session, event, sample); + if (ret) + pr_err("ARM SPE: failed to deliver event, error %d\n", ret); +@@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session) + else + attr.sample_type |= PERF_SAMPLE_TIME; + ++ spe->sample_type = attr.sample_type; ++ + attr.exclude_user = evsel->core.attr.exclude_user; + attr.exclude_kernel = evsel->core.attr.exclude_kernel; + attr.exclude_hv = evsel->core.attr.exclude_hv; +diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c +index 1a7112a87736a..16ad0e6e9e9c5 100644 +--- a/tools/perf/util/bpf-event.c ++++ b/tools/perf/util/bpf-event.c +@@ -120,7 +120,11 @@ static int perf_env__fetch_btf(struct perf_env *env, + node->data_size = data_size; + memcpy(node->data, data, data_size); + +- perf_env__insert_btf(env, node); ++ if (!perf_env__insert_btf(env, node)) { ++ /* Insertion failed because of a duplicate. */ ++ free(node); ++ return -1; ++ } + return 0; + } + +@@ -576,7 +580,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, + synthesize_bpf_prog_name(name, KSYM_NAME_LEN, info, btf, 0); + fprintf(fp, "# bpf_prog_info %u: %s addr 0x%llx size %u\n", + info->id, name, prog_addrs[0], prog_lens[0]); +- return; ++ goto out; + } + + fprintf(fp, "# bpf_prog_info %u:\n", info->id); +@@ -586,4 +590,6 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info, + fprintf(fp, "# \tsub_prog %u: %s addr 0x%llx size %u\n", + i, name, prog_addrs[i], prog_lens[i]); + } ++out: ++ btf__free(btf); + } +diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c +index fbb3c4057c302..71710a1da4472 100644 +--- a/tools/perf/util/bpf-loader.c ++++ b/tools/perf/util/bpf-loader.c +@@ -1214,9 +1214,10 @@ bpf__obj_config_map(struct bpf_object *obj, + pr_debug("ERROR: Invalid map config option '%s'\n", map_opt); + err = -BPF_LOADER_ERRNO__OBJCONF_MAP_OPT; + out: +- free(map_name); + if (!err) + *key_scan_pos += strlen(map_opt); ++ ++ free(map_name); + return err; + } + +diff --git a/tools/perf/util/bpf_skel/bperf.h b/tools/perf/util/bpf_skel/bperf.h +deleted file mode 100644 +index 186a5551ddb9d..0000000000000 +--- a/tools/perf/util/bpf_skel/bperf.h ++++ /dev/null +@@ -1,14 +0,0 @@ +-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +-// Copyright (c) 2021 Facebook +- +-#ifndef __BPERF_STAT_H +-#define __BPERF_STAT_H +- +-typedef struct { +- __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); +- __uint(key_size, sizeof(__u32)); +- __uint(value_size, sizeof(struct bpf_perf_event_value)); +- __uint(max_entries, 1); +-} reading_map; +- +-#endif /* __BPERF_STAT_H */ +diff --git a/tools/perf/util/bpf_skel/bperf_follower.bpf.c b/tools/perf/util/bpf_skel/bperf_follower.bpf.c +index b8fa3cb2da230..6d2ea67b161ac 100644 +--- a/tools/perf/util/bpf_skel/bperf_follower.bpf.c ++++ b/tools/perf/util/bpf_skel/bperf_follower.bpf.c +@@ -4,11 +4,21 @@ + #include <linux/perf_event.h> + #include <bpf/bpf_helpers.h> + #include <bpf/bpf_tracing.h> +-#include "bperf.h" + #include "bperf_u.h" + +-reading_map diff_readings SEC(".maps"); +-reading_map accum_readings SEC(".maps"); ++struct { ++ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); ++ __uint(key_size, sizeof(__u32)); ++ __uint(value_size, sizeof(struct bpf_perf_event_value)); ++ __uint(max_entries, 1); ++} diff_readings SEC(".maps"); ++ ++struct { ++ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); ++ __uint(key_size, sizeof(__u32)); ++ __uint(value_size, sizeof(struct bpf_perf_event_value)); ++ __uint(max_entries, 1); ++} accum_readings SEC(".maps"); + + struct { + __uint(type, BPF_MAP_TYPE_HASH); +diff --git a/tools/perf/util/bpf_skel/bperf_leader.bpf.c b/tools/perf/util/bpf_skel/bperf_leader.bpf.c +index 4f70d1459e86c..d82e1633a2e0a 100644 +--- a/tools/perf/util/bpf_skel/bperf_leader.bpf.c ++++ b/tools/perf/util/bpf_skel/bperf_leader.bpf.c +@@ -4,7 +4,6 @@ + #include <linux/perf_event.h> + #include <bpf/bpf_helpers.h> + #include <bpf/bpf_tracing.h> +-#include "bperf.h" + + struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); +@@ -13,8 +12,19 @@ struct { + __uint(map_flags, BPF_F_PRESERVE_ELEMS); + } events SEC(".maps"); + +-reading_map prev_readings SEC(".maps"); +-reading_map diff_readings SEC(".maps"); ++struct { ++ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); ++ __uint(key_size, sizeof(__u32)); ++ __uint(value_size, sizeof(struct bpf_perf_event_value)); ++ __uint(max_entries, 1); ++} prev_readings SEC(".maps"); ++ ++struct { ++ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); ++ __uint(key_size, sizeof(__u32)); ++ __uint(value_size, sizeof(struct bpf_perf_event_value)); ++ __uint(max_entries, 1); ++} diff_readings SEC(".maps"); + + SEC("raw_tp/sched_switch") + int BPF_PROG(on_switch) +diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c +index f5d260b1df4d1..15a4547d608ec 100644 +--- a/tools/perf/util/data.c ++++ b/tools/perf/util/data.c +@@ -44,10 +44,6 @@ int perf_data__create_dir(struct perf_data *data, int nr) + if (!files) + return -ENOMEM; + +- data->dir.version = PERF_DIR_VERSION; +- data->dir.files = files; +- data->dir.nr = nr; +- + for (i = 0; i < nr; i++) { + struct perf_data_file *file = &files[i]; + +@@ -62,6 +58,9 @@ int perf_data__create_dir(struct perf_data *data, int nr) + file->fd = ret; + } + ++ data->dir.version = PERF_DIR_VERSION; ++ data->dir.files = files; ++ data->dir.nr = nr; + return 0; + + out_err: +diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c +index 2c06abf6dcd26..65e6c22f38e4f 100644 +--- a/tools/perf/util/debug.c ++++ b/tools/perf/util/debug.c +@@ -179,7 +179,7 @@ static int trace_event_printer(enum binary_printer_ops op, + break; + case BINARY_PRINT_CHAR_DATA: + printed += color_fprintf(fp, color, "%c", +- isprint(ch) ? ch : '.'); ++ isprint(ch) && isascii(ch) ? ch : '.'); + break; + case BINARY_PRINT_CHAR_PAD: + printed += color_fprintf(fp, color, " "); +diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c +index cf773f0dec384..5b24eb010336c 100644 +--- a/tools/perf/util/env.c ++++ b/tools/perf/util/env.c +@@ -74,12 +74,13 @@ out: + return node; + } + +-void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) ++bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) + { + struct rb_node *parent = NULL; + __u32 btf_id = btf_node->id; + struct btf_node *node; + struct rb_node **p; ++ bool ret = true; + + down_write(&env->bpf_progs.lock); + p = &env->bpf_progs.btfs.rb_node; +@@ -93,6 +94,7 @@ void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) + p = &(*p)->rb_right; + } else { + pr_debug("duplicated btf %u\n", btf_id); ++ ret = false; + goto out; + } + } +@@ -102,6 +104,7 @@ void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node) + env->bpf_progs.btfs_cnt++; + out: + up_write(&env->bpf_progs.lock); ++ return ret; + } + + struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id) +diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h +index 1383876f72b37..163e5ec503a26 100644 +--- a/tools/perf/util/env.h ++++ b/tools/perf/util/env.h +@@ -167,7 +167,7 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env, + struct bpf_prog_info_node *info_node); + struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env, + __u32 prog_id); +-void perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); ++bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node); + struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id); + + int perf_env__numa_node(struct perf_env *env, int cpu); +diff --git a/tools/perf/util/evlist-hybrid.c b/tools/perf/util/evlist-hybrid.c +index 7c554234b43d4..f39c8ffc5a111 100644 +--- a/tools/perf/util/evlist-hybrid.c ++++ b/tools/perf/util/evlist-hybrid.c +@@ -153,8 +153,8 @@ int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list) + perf_cpu_map__put(matched_cpus); + perf_cpu_map__put(unmatched_cpus); + } +- +- ret = (unmatched_count == events_nr) ? -1 : 0; ++ if (events_nr) ++ ret = (unmatched_count == events_nr) ? -1 : 0; + out: + perf_cpu_map__put(cpus); + return ret; +diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c +index dbfeceb2546c6..c87f9974c0c10 100644 +--- a/tools/perf/util/evsel.c ++++ b/tools/perf/util/evsel.c +@@ -1047,6 +1047,17 @@ void __weak arch_evsel__set_sample_weight(struct evsel *evsel) + evsel__set_sample_bit(evsel, WEIGHT); + } + ++static void evsel__set_default_freq_period(struct record_opts *opts, ++ struct perf_event_attr *attr) ++{ ++ if (opts->freq) { ++ attr->freq = 1; ++ attr->sample_freq = opts->freq; ++ } else { ++ attr->sample_period = opts->default_interval; ++ } ++} ++ + /* + * The enable_on_exec/disabled value strategy: + * +@@ -1113,14 +1124,12 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts, + * We default some events to have a default interval. But keep + * it a weak assumption overridable by the user. + */ +- if (!attr->sample_period) { +- if (opts->freq) { +- attr->freq = 1; +- attr->sample_freq = opts->freq; +- } else { +- attr->sample_period = opts->default_interval; +- } +- } ++ if ((evsel->is_libpfm_event && !attr->sample_period) || ++ (!evsel->is_libpfm_event && (!attr->sample_period || ++ opts->user_freq != UINT_MAX || ++ opts->user_interval != ULLONG_MAX))) ++ evsel__set_default_freq_period(opts, attr); ++ + /* + * If attr->freq was set (here or earlier), ask for period + * to be sampled. +diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c +index 65fe65ba03c25..b776465e04ef3 100644 +--- a/tools/perf/util/hist.c ++++ b/tools/perf/util/hist.c +@@ -289,15 +289,10 @@ static long hist_time(unsigned long htime) + return htime; + } + +-static void he_stat__add_period(struct he_stat *he_stat, u64 period, +- u64 weight, u64 ins_lat, u64 p_stage_cyc) ++static void he_stat__add_period(struct he_stat *he_stat, u64 period) + { +- + he_stat->period += period; +- he_stat->weight += weight; + he_stat->nr_events += 1; +- he_stat->ins_lat += ins_lat; +- he_stat->p_stage_cyc += p_stage_cyc; + } + + static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) +@@ -308,9 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) + dest->period_guest_sys += src->period_guest_sys; + dest->period_guest_us += src->period_guest_us; + dest->nr_events += src->nr_events; +- dest->weight += src->weight; +- dest->ins_lat += src->ins_lat; +- dest->p_stage_cyc += src->p_stage_cyc; + } + + static void he_stat__decay(struct he_stat *he_stat) +@@ -598,9 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, + struct hist_entry *he; + int64_t cmp; + u64 period = entry->stat.period; +- u64 weight = entry->stat.weight; +- u64 ins_lat = entry->stat.ins_lat; +- u64 p_stage_cyc = entry->stat.p_stage_cyc; + bool leftmost = true; + + p = &hists->entries_in->rb_root.rb_node; +@@ -619,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, + + if (!cmp) { + if (sample_self) { +- he_stat__add_period(&he->stat, period, weight, ins_lat, p_stage_cyc); ++ he_stat__add_period(&he->stat, period); + hist_entry__add_callchain_period(he, period); + } + if (symbol_conf.cumulate_callchain) +- he_stat__add_period(he->stat_acc, period, weight, ins_lat, p_stage_cyc); ++ he_stat__add_period(he->stat_acc, period); + + /* + * This mem info was allocated from sample__resolve_mem +@@ -733,9 +722,6 @@ __hists__add_entry(struct hists *hists, + .stat = { + .nr_events = 1, + .period = sample->period, +- .weight = sample->weight, +- .ins_lat = sample->ins_lat, +- .p_stage_cyc = sample->p_stage_cyc, + }, + .parent = sym_parent, + .filtered = symbol__parent_filter(sym_parent) | al->filtered, +@@ -748,6 +734,9 @@ __hists__add_entry(struct hists *hists, + .raw_size = sample->raw_size, + .ops = ops, + .time = hist_time(sample->time), ++ .weight = sample->weight, ++ .ins_lat = sample->ins_lat, ++ .p_stage_cyc = sample->p_stage_cyc, + }, *he = hists__findnew_entry(hists, &entry, al, sample_self); + + if (!hists->has_callchains && he && he->callchain_size != 0) +diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h +index 5343b62476e60..621f35ae1efa5 100644 +--- a/tools/perf/util/hist.h ++++ b/tools/perf/util/hist.h +@@ -369,7 +369,6 @@ enum { + }; + + void perf_hpp__init(void); +-void perf_hpp__column_unregister(struct perf_hpp_fmt *format); + void perf_hpp__cancel_cumulate(void); + void perf_hpp__setup_output_field(struct perf_hpp_list *list); + void perf_hpp__reset_output_field(struct perf_hpp_list *list); +diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build +index bc629359826fb..b41c2e9c6f887 100644 +--- a/tools/perf/util/intel-pt-decoder/Build ++++ b/tools/perf/util/intel-pt-decoder/Build +@@ -18,3 +18,5 @@ CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder + ifeq ($(CC_NO_CLANG), 1) + CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init + endif ++ ++CFLAGS_intel-pt-insn-decoder.o += -Wno-packed +diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +index 5ab631702769b..b0034ee4bba50 100644 +--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c ++++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +@@ -1204,61 +1204,69 @@ out_no_progress: + + static bool intel_pt_fup_event(struct intel_pt_decoder *decoder) + { ++ enum intel_pt_sample_type type = decoder->state.type; + bool ret = false; + ++ decoder->state.type &= ~INTEL_PT_BRANCH; ++ + if (decoder->set_fup_tx_flags) { + decoder->set_fup_tx_flags = false; + decoder->tx_flags = decoder->fup_tx_flags; +- decoder->state.type = INTEL_PT_TRANSACTION; ++ decoder->state.type |= INTEL_PT_TRANSACTION; + if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX) + decoder->state.type |= INTEL_PT_BRANCH; +- decoder->state.from_ip = decoder->ip; +- decoder->state.to_ip = 0; + decoder->state.flags = decoder->fup_tx_flags; +- return true; ++ ret = true; + } + if (decoder->set_fup_ptw) { + decoder->set_fup_ptw = false; +- decoder->state.type = INTEL_PT_PTW; ++ decoder->state.type |= INTEL_PT_PTW; + decoder->state.flags |= INTEL_PT_FUP_IP; +- decoder->state.from_ip = decoder->ip; +- decoder->state.to_ip = 0; + decoder->state.ptw_payload = decoder->fup_ptw_payload; +- return true; ++ ret = true; + } + if (decoder->set_fup_mwait) { + decoder->set_fup_mwait = false; +- decoder->state.type = INTEL_PT_MWAIT_OP; +- decoder->state.from_ip = decoder->ip; +- decoder->state.to_ip = 0; ++ decoder->state.type |= INTEL_PT_MWAIT_OP; + decoder->state.mwait_payload = decoder->fup_mwait_payload; + ret = true; + } + if (decoder->set_fup_pwre) { + decoder->set_fup_pwre = false; + decoder->state.type |= INTEL_PT_PWR_ENTRY; +- decoder->state.type &= ~INTEL_PT_BRANCH; +- decoder->state.from_ip = decoder->ip; +- decoder->state.to_ip = 0; + decoder->state.pwre_payload = decoder->fup_pwre_payload; + ret = true; + } + if (decoder->set_fup_exstop) { + decoder->set_fup_exstop = false; + decoder->state.type |= INTEL_PT_EX_STOP; +- decoder->state.type &= ~INTEL_PT_BRANCH; + decoder->state.flags |= INTEL_PT_FUP_IP; +- decoder->state.from_ip = decoder->ip; +- decoder->state.to_ip = 0; + ret = true; + } + if (decoder->set_fup_bep) { + decoder->set_fup_bep = false; + decoder->state.type |= INTEL_PT_BLK_ITEMS; +- decoder->state.type &= ~INTEL_PT_BRANCH; ++ ret = true; ++ } ++ if (decoder->overflow) { ++ decoder->overflow = false; ++ if (!ret && !decoder->pge) { ++ if (decoder->hop) { ++ decoder->state.type = 0; ++ decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; ++ } ++ decoder->pge = true; ++ decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN; ++ decoder->state.from_ip = 0; ++ decoder->state.to_ip = decoder->ip; ++ return true; ++ } ++ } ++ if (ret) { + decoder->state.from_ip = decoder->ip; + decoder->state.to_ip = 0; +- ret = true; ++ } else { ++ decoder->state.type = type; + } + return ret; + } +@@ -1607,7 +1615,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) + intel_pt_clear_tx_flags(decoder); + intel_pt_set_nr(decoder); + decoder->timestamp_insn_cnt = 0; +- decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; ++ decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; ++ decoder->state.from_ip = decoder->ip; ++ decoder->ip = 0; ++ decoder->pge = false; ++ decoder->set_fup_tx_flags = false; ++ decoder->set_fup_ptw = false; ++ decoder->set_fup_mwait = false; ++ decoder->set_fup_pwre = false; ++ decoder->set_fup_exstop = false; ++ decoder->set_fup_bep = false; + decoder->overflow = true; + return -EOVERFLOW; + } +@@ -2665,6 +2682,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder); + /* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */ + static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err) + { ++ *err = 0; ++ + /* Leap from PSB to PSB, getting ip from FUP within PSB+ */ + if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) { + *err = intel_pt_scan_for_psb(decoder); +@@ -2677,6 +2696,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in + return HOP_IGNORE; + + case INTEL_PT_TIP_PGD: ++ decoder->pge = false; + if (!decoder->packet.count) { + intel_pt_set_nr(decoder); + return HOP_IGNORE; +@@ -2704,18 +2724,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in + if (!decoder->packet.count) + return HOP_IGNORE; + intel_pt_set_ip(decoder); +- if (intel_pt_fup_event(decoder)) +- return HOP_RETURN; +- if (!decoder->branch_enable) ++ if (decoder->set_fup_mwait || decoder->set_fup_pwre) ++ *no_tip = true; ++ if (!decoder->branch_enable || !decoder->pge) + *no_tip = true; + if (*no_tip) { + decoder->state.type = INTEL_PT_INSTRUCTION; + decoder->state.from_ip = decoder->ip; + decoder->state.to_ip = 0; ++ intel_pt_fup_event(decoder); + return HOP_RETURN; + } ++ intel_pt_fup_event(decoder); ++ decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH; + *err = intel_pt_walk_fup_tip(decoder); +- if (!*err) ++ if (!*err && decoder->state.to_ip) + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; + return HOP_RETURN; + +@@ -2896,7 +2919,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err) + { + struct intel_pt_psb_info data = { .fup = false }; + +- if (!decoder->branch_enable || !decoder->pge) ++ if (!decoder->branch_enable) + return false; + + intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data); +@@ -2923,6 +2946,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) + if (err) + return err; + next: ++ err = 0; + if (decoder->cyc_threshold) { + if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC) + decoder->sample_cyc = false; +@@ -2961,6 +2985,7 @@ next: + + case INTEL_PT_TIP_PGE: { + decoder->pge = true; ++ decoder->overflow = false; + intel_pt_mtc_cyc_cnt_pge(decoder); + intel_pt_set_nr(decoder); + if (decoder->packet.count == 0) { +@@ -2998,7 +3023,7 @@ next: + break; + } + intel_pt_set_last_ip(decoder); +- if (!decoder->branch_enable) { ++ if (!decoder->branch_enable || !decoder->pge) { + decoder->ip = decoder->last_ip; + if (intel_pt_fup_event(decoder)) + return 0; +@@ -3466,10 +3491,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) + decoder->set_fup_pwre = false; + decoder->set_fup_exstop = false; + decoder->set_fup_bep = false; ++ decoder->overflow = false; + + if (!decoder->branch_enable) { + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; +- decoder->overflow = false; + decoder->state.type = 0; /* Do not have a sample */ + return 0; + } +@@ -3484,7 +3509,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; + else + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; +- decoder->overflow = false; + + decoder->state.from_ip = 0; + decoder->state.to_ip = decoder->ip; +@@ -3606,7 +3630,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) + } + + decoder->have_last_ip = true; +- decoder->pkt_state = INTEL_PT_STATE_NO_IP; ++ decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; + + err = intel_pt_walk_psb(decoder); + if (err) +@@ -3703,7 +3727,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) + + if (err) { + decoder->state.err = intel_pt_ext_err(err); +- decoder->state.from_ip = decoder->ip; ++ if (err != -EOVERFLOW) ++ decoder->state.from_ip = decoder->ip; + intel_pt_update_sample_time(decoder); + decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; + intel_pt_set_nr(decoder); +diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c +index 6f852b305e92b..c3ceac1388106 100644 +--- a/tools/perf/util/intel-pt.c ++++ b/tools/perf/util/intel-pt.c +@@ -2510,6 +2510,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) + ptq->sync_switch = false; + intel_pt_next_tid(pt, ptq); + } ++ ptq->timestamp = state->est_timestamp; + if (pt->synth_opts.errors) { + err = intel_ptq_synth_error(ptq, state); + if (err) +@@ -3539,6 +3540,7 @@ static int intel_pt_parse_vm_tm_corr_arg(struct intel_pt *pt, char **args) + *args = p; + return 0; + } ++ p += 1; + while (1) { + vmcs = strtoull(p, &p, 0); + if (errno) +diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c +index b2a02c9ab8ea9..a834918a0a0d3 100644 +--- a/tools/perf/util/probe-event.c ++++ b/tools/perf/util/probe-event.c +@@ -3083,6 +3083,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, + for (j = 0; j < num_matched_functions; j++) { + sym = syms[j]; + ++ if (sym->type != STT_FUNC) ++ continue; ++ + /* There can be duplicated symbols in the map */ + for (i = 0; i < j; i++) + if (sym->start == syms[i]->start) { +diff --git a/tools/perf/util/smt.c b/tools/perf/util/smt.c +index 20bacd5972ade..34f1b1b1176c7 100644 +--- a/tools/perf/util/smt.c ++++ b/tools/perf/util/smt.c +@@ -15,7 +15,7 @@ int smt_on(void) + if (cached) + return cached_result; + +- if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) > 0) ++ if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) + goto done; + + ncpu = sysconf(_SC_NPROCESSORS_CONF); +diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c +index 568a88c001c6c..a111065b484ef 100644 +--- a/tools/perf/util/sort.c ++++ b/tools/perf/util/sort.c +@@ -1325,88 +1325,68 @@ struct sort_entry sort_mispredict = { + .se_width_idx = HISTC_MISPREDICT, + }; + +-static u64 he_weight(struct hist_entry *he) +-{ +- return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0; +-} +- + static int64_t +-sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) ++sort__weight_cmp(struct hist_entry *left, struct hist_entry *right) + { +- return he_weight(left) - he_weight(right); ++ return left->weight - right->weight; + } + + static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { +- return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); ++ return repsep_snprintf(bf, size, "%-*llu", width, he->weight); + } + + struct sort_entry sort_local_weight = { + .se_header = "Local Weight", +- .se_cmp = sort__local_weight_cmp, ++ .se_cmp = sort__weight_cmp, + .se_snprintf = hist_entry__local_weight_snprintf, + .se_width_idx = HISTC_LOCAL_WEIGHT, + }; + +-static int64_t +-sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right) +-{ +- return left->stat.weight - right->stat.weight; +-} +- + static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { +- return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); ++ return repsep_snprintf(bf, size, "%-*llu", width, ++ he->weight * he->stat.nr_events); + } + + struct sort_entry sort_global_weight = { + .se_header = "Weight", +- .se_cmp = sort__global_weight_cmp, ++ .se_cmp = sort__weight_cmp, + .se_snprintf = hist_entry__global_weight_snprintf, + .se_width_idx = HISTC_GLOBAL_WEIGHT, + }; + +-static u64 he_ins_lat(struct hist_entry *he) +-{ +- return he->stat.nr_events ? he->stat.ins_lat / he->stat.nr_events : 0; +-} +- + static int64_t +-sort__local_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) ++sort__ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) + { +- return he_ins_lat(left) - he_ins_lat(right); ++ return left->ins_lat - right->ins_lat; + } + + static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { +- return repsep_snprintf(bf, size, "%-*u", width, he_ins_lat(he)); ++ return repsep_snprintf(bf, size, "%-*u", width, he->ins_lat); + } + + struct sort_entry sort_local_ins_lat = { + .se_header = "Local INSTR Latency", +- .se_cmp = sort__local_ins_lat_cmp, ++ .se_cmp = sort__ins_lat_cmp, + .se_snprintf = hist_entry__local_ins_lat_snprintf, + .se_width_idx = HISTC_LOCAL_INS_LAT, + }; + +-static int64_t +-sort__global_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) +-{ +- return left->stat.ins_lat - right->stat.ins_lat; +-} +- + static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { +- return repsep_snprintf(bf, size, "%-*u", width, he->stat.ins_lat); ++ return repsep_snprintf(bf, size, "%-*u", width, ++ he->ins_lat * he->stat.nr_events); + } + + struct sort_entry sort_global_ins_lat = { + .se_header = "INSTR Latency", +- .se_cmp = sort__global_ins_lat_cmp, ++ .se_cmp = sort__ins_lat_cmp, + .se_snprintf = hist_entry__global_ins_lat_snprintf, + .se_width_idx = HISTC_GLOBAL_INS_LAT, + }; +@@ -1414,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = { + static int64_t + sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right) + { +- return left->stat.p_stage_cyc - right->stat.p_stage_cyc; ++ return left->p_stage_cyc - right->p_stage_cyc; + } + + static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf, + size_t size, unsigned int width) + { +- return repsep_snprintf(bf, size, "%-*u", width, he->stat.p_stage_cyc); ++ return repsep_snprintf(bf, size, "%-*u", width, he->p_stage_cyc); + } + + struct sort_entry sort_p_stage_cyc = { +diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h +index b67c469aba795..7b7145501933f 100644 +--- a/tools/perf/util/sort.h ++++ b/tools/perf/util/sort.h +@@ -49,9 +49,6 @@ struct he_stat { + u64 period_us; + u64 period_guest_sys; + u64 period_guest_us; +- u64 weight; +- u64 ins_lat; +- u64 p_stage_cyc; + u32 nr_events; + }; + +@@ -109,6 +106,9 @@ struct hist_entry { + s32 socket; + s32 cpu; + u64 code_page_size; ++ u64 weight; ++ u64 ins_lat; ++ u64 p_stage_cyc; + u8 cpumode; + u8 depth; + +diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c +index 588601000f3f9..db00ca6a67deb 100644 +--- a/tools/perf/util/stat-display.c ++++ b/tools/perf/util/stat-display.c +@@ -584,15 +584,16 @@ static void collect_all_aliases(struct perf_stat_config *config, struct evsel *c + + alias = list_prepare_entry(counter, &(evlist->core.entries), core.node); + list_for_each_entry_continue (alias, &evlist->core.entries, core.node) { +- if (strcmp(evsel__name(alias), evsel__name(counter)) || +- alias->scale != counter->scale || +- alias->cgrp != counter->cgrp || +- strcmp(alias->unit, counter->unit) || +- evsel__is_clock(alias) != evsel__is_clock(counter) || +- !strcmp(alias->pmu_name, counter->pmu_name)) +- break; +- alias->merged_stat = true; +- cb(config, alias, data, false); ++ /* Merge events with the same name, etc. but on different PMUs. */ ++ if (!strcmp(evsel__name(alias), evsel__name(counter)) && ++ alias->scale == counter->scale && ++ alias->cgrp == counter->cgrp && ++ !strcmp(alias->unit, counter->unit) && ++ evsel__is_clock(alias) == evsel__is_clock(counter) && ++ strcmp(alias->pmu_name, counter->pmu_name)) { ++ alias->merged_stat = true; ++ cb(config, alias, data, false); ++ } + } + } + +diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c +index 37a9492edb3eb..df3c4671be72a 100644 +--- a/tools/perf/util/util.c ++++ b/tools/perf/util/util.c +@@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str, + return 0; + } + +-const char *perf_tip(const char *dirpath) ++int perf_tip(char **strp, const char *dirpath) + { + struct strlist *tips; + struct str_node *node; +- char *tip = NULL; + struct strlist_config conf = { + .dirname = dirpath, + .file_only = true, + }; ++ int ret = 0; + ++ *strp = NULL; + tips = strlist__new("tips.txt", &conf); + if (tips == NULL) +- return errno == ENOENT ? NULL : +- "Tip: check path of tips.txt or get more memory! ;-p"; ++ return -errno; + + if (strlist__nr_entries(tips) == 0) + goto out; + + node = strlist__entry(tips, random() % strlist__nr_entries(tips)); +- if (asprintf(&tip, "Tip: %s", node->s) < 0) +- tip = (char *)"Tip: get more memory! ;-)"; ++ if (asprintf(strp, "Tip: %s", node->s) < 0) ++ ret = -ENOMEM; + + out: + strlist__delete(tips); + +- return tip; ++ return ret; + } + + char *perf_exe(char *buf, int len) +diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h +index ad737052e5977..9f0d36ba77f2d 100644 +--- a/tools/perf/util/util.h ++++ b/tools/perf/util/util.h +@@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint, + #define KVER_FMT "%d.%d.%d" + #define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) + +-const char *perf_tip(const char *dirpath); ++int perf_tip(char **strp, const char *dirpath); + + #ifndef HAVE_SCHED_GETCPU_SUPPORT + int sched_getcpu(void); +diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py +index 2c6f916ccbafa..0874e512d109b 100644 +--- a/tools/testing/kunit/kunit_kernel.py ++++ b/tools/testing/kunit/kunit_kernel.py +@@ -6,6 +6,7 @@ + # Author: Felix Guo <felixguoxiuping@gmail.com> + # Author: Brendan Higgins <brendanhiggins@google.com> + ++import importlib.abc + import importlib.util + import logging + import subprocess +diff --git a/tools/testing/selftests/bpf/btf_helpers.c b/tools/testing/selftests/bpf/btf_helpers.c +index b692e6ead9b55..0a4ad7cb2c200 100644 +--- a/tools/testing/selftests/bpf/btf_helpers.c ++++ b/tools/testing/selftests/bpf/btf_helpers.c +@@ -246,18 +246,23 @@ const char *btf_type_c_dump(const struct btf *btf) + d = btf_dump__new(btf, NULL, &opts, btf_dump_printf); + if (libbpf_get_error(d)) { + fprintf(stderr, "Failed to create btf_dump instance: %ld\n", libbpf_get_error(d)); +- return NULL; ++ goto err_out; + } + + for (i = 1; i <= btf__get_nr_types(btf); i++) { + err = btf_dump__dump_type(d, i); + if (err) { + fprintf(stderr, "Failed to dump type [%d]: %d\n", i, err); +- return NULL; ++ goto err_out; + } + } + ++ btf_dump__free(d); + fflush(buf_file); + fclose(buf_file); + return buf; ++err_out: ++ btf_dump__free(d); ++ fclose(buf_file); ++ return NULL; + } +diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c +index 77ac24b191d4c..dc18e5ae0febc 100644 +--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c ++++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c +@@ -1208,13 +1208,14 @@ static void test_task_vma(void) + goto out; + + /* Read CMP_BUFFER_SIZE (1kB) from bpf_iter. Read in small chunks +- * to trigger seq_file corner cases. The expected output is much +- * longer than 1kB, so the while loop will terminate. ++ * to trigger seq_file corner cases. + */ + len = 0; + while (len < CMP_BUFFER_SIZE) { + err = read_fd_into_buffer(iter_fd, task_vma_output + len, + min(read_size, CMP_BUFFER_SIZE - len)); ++ if (!err) ++ break; + if (CHECK(err < 0, "read_iter_fd", "read_iter_fd failed\n")) + goto out; + len += err; +diff --git a/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c b/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c +index 762f6a9da8b5e..664ffc0364f4f 100644 +--- a/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c ++++ b/tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c +@@ -90,7 +90,7 @@ static void print_err_line(void) + + static void test_conn(void) + { +- int listen_fd = -1, cli_fd = -1, err; ++ int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; + socklen_t addrlen = sizeof(srv_sa6); + int srv_port; + +@@ -112,6 +112,10 @@ static void test_conn(void) + if (CHECK_FAIL(cli_fd == -1)) + goto done; + ++ srv_fd = accept(listen_fd, NULL, NULL); ++ if (CHECK_FAIL(srv_fd == -1)) ++ goto done; ++ + if (CHECK(skel->bss->listen_tp_sport != srv_port || + skel->bss->req_sk_sport != srv_port, + "Unexpected sk src port", +@@ -134,11 +138,13 @@ done: + close(listen_fd); + if (cli_fd != -1) + close(cli_fd); ++ if (srv_fd != -1) ++ close(srv_fd); + } + + static void test_syncookie(void) + { +- int listen_fd = -1, cli_fd = -1, err; ++ int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; + socklen_t addrlen = sizeof(srv_sa6); + int srv_port; + +@@ -161,6 +167,10 @@ static void test_syncookie(void) + if (CHECK_FAIL(cli_fd == -1)) + goto done; + ++ srv_fd = accept(listen_fd, NULL, NULL); ++ if (CHECK_FAIL(srv_fd == -1)) ++ goto done; ++ + if (CHECK(skel->bss->listen_tp_sport != srv_port, + "Unexpected tp src port", + "listen_tp_sport:%u expected:%u\n", +@@ -188,6 +198,8 @@ done: + close(listen_fd); + if (cli_fd != -1) + close(cli_fd); ++ if (srv_fd != -1) ++ close(srv_fd); + } + + struct test { +diff --git a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c +index 59adb4715394f..3c85247f96f95 100644 +--- a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c ++++ b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c +@@ -204,8 +204,8 @@ static int pass_ack(struct migrate_reuseport_test_case *test_case) + { + int err; + +- err = bpf_link__detach(test_case->link); +- if (!ASSERT_OK(err, "bpf_link__detach")) ++ err = bpf_link__destroy(test_case->link); ++ if (!ASSERT_OK(err, "bpf_link__destroy")) + return -1; + + test_case->link = NULL; +diff --git a/tools/testing/selftests/bpf/prog_tests/perf_buffer.c b/tools/testing/selftests/bpf/prog_tests/perf_buffer.c +index 6490e9673002f..7daaaab13681b 100644 +--- a/tools/testing/selftests/bpf/prog_tests/perf_buffer.c ++++ b/tools/testing/selftests/bpf/prog_tests/perf_buffer.c +@@ -107,8 +107,8 @@ void test_perf_buffer(void) + "expect %d, seen %d\n", nr_on_cpus, CPU_COUNT(&cpu_seen))) + goto out_free_pb; + +- if (CHECK(perf_buffer__buffer_cnt(pb) != nr_cpus, "buf_cnt", +- "got %zu, expected %d\n", perf_buffer__buffer_cnt(pb), nr_cpus)) ++ if (CHECK(perf_buffer__buffer_cnt(pb) != nr_on_cpus, "buf_cnt", ++ "got %zu, expected %d\n", perf_buffer__buffer_cnt(pb), nr_on_cpus)) + goto out_close; + + for (i = 0; i < nr_cpus; i++) { +diff --git a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +index aee41547e7f45..6db07401bc493 100644 +--- a/tools/testing/selftests/bpf/prog_tests/sk_lookup.c ++++ b/tools/testing/selftests/bpf/prog_tests/sk_lookup.c +@@ -598,7 +598,7 @@ close: + + static void run_lookup_prog(const struct test *t) + { +- int server_fds[MAX_SERVERS] = { -1 }; ++ int server_fds[] = { [0 ... MAX_SERVERS - 1] = -1 }; + int client_fd, reuse_conn_fd = -1; + struct bpf_link *lookup_link; + int i, err; +@@ -1053,7 +1053,7 @@ static void run_sk_assign(struct test_sk_lookup *skel, + struct bpf_program *lookup_prog, + const char *remote_ip, const char *local_ip) + { +- int server_fds[MAX_SERVERS] = { -1 }; ++ int server_fds[] = { [0 ... MAX_SERVERS - 1] = -1 }; + struct bpf_sk_lookup ctx; + __u64 server_cookie; + int i, err; +diff --git a/tools/testing/selftests/bpf/prog_tests/skb_ctx.c b/tools/testing/selftests/bpf/prog_tests/skb_ctx.c +index fafeddaad6a99..23915be6172d6 100644 +--- a/tools/testing/selftests/bpf/prog_tests/skb_ctx.c ++++ b/tools/testing/selftests/bpf/prog_tests/skb_ctx.c +@@ -105,4 +105,6 @@ void test_skb_ctx(void) + "ctx_out_mark", + "skb->mark == %u, expected %d\n", + skb.mark, 10); ++ ++ bpf_object__close(obj); + } +diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c +index e7201ba29ccd6..47e3159729d21 100644 +--- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c ++++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c +@@ -105,6 +105,13 @@ static int setns_by_fd(int nsfd) + if (!ASSERT_OK(err, "unshare")) + return err; + ++ /* Make our /sys mount private, so the following umount won't ++ * trigger the global umount in case it's shared. ++ */ ++ err = mount("none", "/sys", NULL, MS_PRIVATE, NULL); ++ if (!ASSERT_OK(err, "remount private /sys")) ++ return err; ++ + err = umount2("/sys", MNT_DETACH); + if (!ASSERT_OK(err, "umount2 /sys")) + return err; +diff --git a/tools/testing/selftests/bpf/prog_tests/test_ima.c b/tools/testing/selftests/bpf/prog_tests/test_ima.c +index 0252f61d611a9..97d8a6f84f4ab 100644 +--- a/tools/testing/selftests/bpf/prog_tests/test_ima.c ++++ b/tools/testing/selftests/bpf/prog_tests/test_ima.c +@@ -43,7 +43,7 @@ static int process_sample(void *ctx, void *data, size_t len) + void test_test_ima(void) + { + char measured_dir_template[] = "/tmp/ima_measuredXXXXXX"; +- struct ring_buffer *ringbuf; ++ struct ring_buffer *ringbuf = NULL; + const char *measured_dir; + char cmd[256]; + +@@ -85,5 +85,6 @@ close_clean: + err = system(cmd); + CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno); + close_prog: ++ ring_buffer__free(ringbuf); + ima__destroy(skel); + } +diff --git a/tools/testing/selftests/bpf/progs/strobemeta.h b/tools/testing/selftests/bpf/progs/strobemeta.h +index 7de534f38c3f1..60c93aee2f4ad 100644 +--- a/tools/testing/selftests/bpf/progs/strobemeta.h ++++ b/tools/testing/selftests/bpf/progs/strobemeta.h +@@ -358,7 +358,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg, + void *payload) + { + void *location; +- uint32_t len; ++ uint64_t len; + + data->str_lens[idx] = 0; + location = calc_location(&cfg->str_locs[idx], tls_base); +@@ -390,7 +390,7 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, + struct strobe_map_descr* descr = &data->map_descrs[idx]; + struct strobe_map_raw map; + void *location; +- uint32_t len; ++ uint64_t len; + int i; + + descr->tag_len = 0; /* presume no tag is set */ +diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_kern.h b/tools/testing/selftests/bpf/progs/test_sockmap_kern.h +index 1858435de7aaf..5cb90ca292186 100644 +--- a/tools/testing/selftests/bpf/progs/test_sockmap_kern.h ++++ b/tools/testing/selftests/bpf/progs/test_sockmap_kern.h +@@ -235,7 +235,7 @@ SEC("sk_msg1") + int bpf_prog4(struct sk_msg_md *msg) + { + int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5; +- int *start, *end, *start_push, *end_push, *start_pop, *pop; ++ int *start, *end, *start_push, *end_push, *start_pop, *pop, err = 0; + + bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); + if (bytes) +@@ -249,8 +249,11 @@ int bpf_prog4(struct sk_msg_md *msg) + bpf_msg_pull_data(msg, *start, *end, 0); + start_push = bpf_map_lookup_elem(&sock_bytes, &two); + end_push = bpf_map_lookup_elem(&sock_bytes, &three); +- if (start_push && end_push) +- bpf_msg_push_data(msg, *start_push, *end_push, 0); ++ if (start_push && end_push) { ++ err = bpf_msg_push_data(msg, *start_push, *end_push, 0); ++ if (err) ++ return SK_DROP; ++ } + start_pop = bpf_map_lookup_elem(&sock_bytes, &four); + pop = bpf_map_lookup_elem(&sock_bytes, &five); + if (start_pop && pop) +@@ -263,6 +266,7 @@ int bpf_prog6(struct sk_msg_md *msg) + { + int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0; + int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f; ++ int err = 0; + __u64 flags = 0; + + bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); +@@ -279,8 +283,11 @@ int bpf_prog6(struct sk_msg_md *msg) + + start_push = bpf_map_lookup_elem(&sock_bytes, &two); + end_push = bpf_map_lookup_elem(&sock_bytes, &three); +- if (start_push && end_push) +- bpf_msg_push_data(msg, *start_push, *end_push, 0); ++ if (start_push && end_push) { ++ err = bpf_msg_push_data(msg, *start_push, *end_push, 0); ++ if (err) ++ return SK_DROP; ++ } + + start_pop = bpf_map_lookup_elem(&sock_bytes, &four); + pop = bpf_map_lookup_elem(&sock_bytes, &five); +@@ -338,7 +345,7 @@ SEC("sk_msg5") + int bpf_prog10(struct sk_msg_md *msg) + { + int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop; +- int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5; ++ int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, err = 0; + + bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero); + if (bytes) +@@ -352,8 +359,11 @@ int bpf_prog10(struct sk_msg_md *msg) + bpf_msg_pull_data(msg, *start, *end, 0); + start_push = bpf_map_lookup_elem(&sock_bytes, &two); + end_push = bpf_map_lookup_elem(&sock_bytes, &three); +- if (start_push && end_push) +- bpf_msg_push_data(msg, *start_push, *end_push, 0); ++ if (start_push && end_push) { ++ err = bpf_msg_push_data(msg, *start_push, *end_push, 0); ++ if (err) ++ return SK_PASS; ++ } + start_pop = bpf_map_lookup_elem(&sock_bytes, &four); + pop = bpf_map_lookup_elem(&sock_bytes, &five); + if (start_pop && pop) +diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c +index cc1cd240445d2..e3fea6f281e4b 100644 +--- a/tools/testing/selftests/bpf/test_progs.c ++++ b/tools/testing/selftests/bpf/test_progs.c +@@ -370,7 +370,7 @@ int extract_build_id(char *build_id, size_t size) + + if (getline(&line, &len, fp) == -1) + goto err; +- fclose(fp); ++ pclose(fp); + + if (len > size) + len = size; +@@ -379,7 +379,7 @@ int extract_build_id(char *build_id, size_t size) + free(line); + return 0; + err: +- fclose(fp); ++ pclose(fp); + return -1; + } + +diff --git a/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh b/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh +index 1538373157e3c..bedff7aa7023f 100755 +--- a/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh ++++ b/tools/testing/selftests/bpf/test_xdp_redirect_multi.sh +@@ -2,11 +2,11 @@ + # SPDX-License-Identifier: GPL-2.0 + # + # Test topology: +-# - - - - - - - - - - - - - - - - - - - - - - - - - +-# | veth1 veth2 veth3 | ... init net ++# - - - - - - - - - - - - - - - - - - - ++# | veth1 veth2 veth3 | ns0 + # - -| - - - - - - | - - - - - - | - - + # --------- --------- --------- +-# | veth0 | | veth0 | | veth0 | ... ++# | veth0 | | veth0 | | veth0 | + # --------- --------- --------- + # ns1 ns2 ns3 + # +@@ -31,6 +31,7 @@ IFACES="" + DRV_MODE="xdpgeneric xdpdrv xdpegress" + PASS=0 + FAIL=0 ++LOG_DIR=$(mktemp -d) + + test_pass() + { +@@ -50,6 +51,7 @@ clean_up() + ip link del veth$i 2> /dev/null + ip netns del ns$i 2> /dev/null + done ++ ip netns del ns0 2> /dev/null + } + + # Kselftest framework requirement - SKIP code is 4. +@@ -77,10 +79,12 @@ setup_ns() + mode="xdpdrv" + fi + ++ ip netns add ns0 + for i in $(seq $NUM); do + ip netns add ns$i +- ip link add veth$i type veth peer name veth0 netns ns$i +- ip link set veth$i up ++ ip -n ns$i link add veth0 index 2 type veth \ ++ peer name veth$i netns ns0 index $((1 + $i)) ++ ip -n ns0 link set veth$i up + ip -n ns$i link set veth0 up + + ip -n ns$i addr add 192.0.2.$i/24 dev veth0 +@@ -91,7 +95,7 @@ setup_ns() + xdp_dummy.o sec xdp_dummy &> /dev/null || \ + { test_fail "Unable to load dummy xdp" && exit 1; } + IFACES="$IFACES veth$i" +- veth_mac[$i]=$(ip link show veth$i | awk '/link\/ether/ {print $2}') ++ veth_mac[$i]=$(ip -n ns0 link show veth$i | awk '/link\/ether/ {print $2}') + done + } + +@@ -100,17 +104,17 @@ do_egress_tests() + local mode=$1 + + # mac test +- ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-2_${mode}.log & +- ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-3_${mode}.log & ++ ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-2_${mode}.log & ++ ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-3_${mode}.log & + sleep 0.5 + ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null + sleep 0.5 +- pkill -9 tcpdump ++ pkill tcpdump + + # mac check +- grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" mac_ns1-2_${mode}.log && \ ++ grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-2_${mode}.log && \ + test_pass "$mode mac ns1-2" || test_fail "$mode mac ns1-2" +- grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" mac_ns1-3_${mode}.log && \ ++ grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-3_${mode}.log && \ + test_pass "$mode mac ns1-3" || test_fail "$mode mac ns1-3" + } + +@@ -121,46 +125,46 @@ do_ping_tests() + # ping6 test: echo request should be redirect back to itself, not others + ip netns exec ns1 ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02 + +- ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ns1-1_${mode}.log & +- ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ns1-2_${mode}.log & +- ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ns1-3_${mode}.log & ++ ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-1_${mode}.log & ++ ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-2_${mode}.log & ++ ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-3_${mode}.log & + sleep 0.5 + # ARP test +- ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null ++ ip netns exec ns1 arping -q -c 2 -I veth0 192.0.2.254 + # IPv4 test + ip netns exec ns1 ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null + # IPv6 test + ip netns exec ns1 ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null + sleep 0.5 +- pkill -9 tcpdump ++ pkill tcpdump + + # All netns should receive the redirect arp requests +- [ $(grep -c "who-has 192.0.2.254" ns1-1_${mode}.log) -gt 4 ] && \ ++ [ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \ + test_pass "$mode arp(F_BROADCAST) ns1-1" || \ + test_fail "$mode arp(F_BROADCAST) ns1-1" +- [ $(grep -c "who-has 192.0.2.254" ns1-2_${mode}.log) -le 4 ] && \ ++ [ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-2_${mode}.log) -eq 2 ] && \ + test_pass "$mode arp(F_BROADCAST) ns1-2" || \ + test_fail "$mode arp(F_BROADCAST) ns1-2" +- [ $(grep -c "who-has 192.0.2.254" ns1-3_${mode}.log) -le 4 ] && \ ++ [ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-3_${mode}.log) -eq 2 ] && \ + test_pass "$mode arp(F_BROADCAST) ns1-3" || \ + test_fail "$mode arp(F_BROADCAST) ns1-3" + + # ns1 should not receive the redirect echo request, others should +- [ $(grep -c "ICMP echo request" ns1-1_${mode}.log) -eq 4 ] && \ ++ [ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \ + test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1" || \ + test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1" +- [ $(grep -c "ICMP echo request" ns1-2_${mode}.log) -eq 4 ] && \ ++ [ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 4 ] && \ + test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2" || \ + test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2" +- [ $(grep -c "ICMP echo request" ns1-3_${mode}.log) -eq 4 ] && \ ++ [ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-3_${mode}.log) -eq 4 ] && \ + test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3" || \ + test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3" + + # ns1 should receive the echo request, ns2 should not +- [ $(grep -c "ICMP6, echo request" ns1-1_${mode}.log) -eq 4 ] && \ ++ [ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \ + test_pass "$mode IPv6 (no flags) ns1-1" || \ + test_fail "$mode IPv6 (no flags) ns1-1" +- [ $(grep -c "ICMP6, echo request" ns1-2_${mode}.log) -eq 0 ] && \ ++ [ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 0 ] && \ + test_pass "$mode IPv6 (no flags) ns1-2" || \ + test_fail "$mode IPv6 (no flags) ns1-2" + } +@@ -176,9 +180,13 @@ do_tests() + xdpgeneric) drv_p="-S";; + esac + +- ./xdp_redirect_multi $drv_p $IFACES &> xdp_redirect_${mode}.log & ++ ip netns exec ns0 ./xdp_redirect_multi $drv_p $IFACES &> ${LOG_DIR}/xdp_redirect_${mode}.log & + xdp_pid=$! + sleep 1 ++ if ! ps -p $xdp_pid > /dev/null; then ++ test_fail "$mode xdp_redirect_multi start failed" ++ return 1 ++ fi + + if [ "$mode" = "xdpegress" ]; then + do_egress_tests $mode +@@ -189,16 +197,16 @@ do_tests() + kill $xdp_pid + } + +-trap clean_up 0 2 3 6 9 ++trap clean_up EXIT + + check_env +-rm -f xdp_redirect_*.log ns*.log mac_ns*.log + + for mode in ${DRV_MODE}; do + setup_ns $mode + do_tests $mode + clean_up + done ++rm -rf ${LOG_DIR} + + echo "Summary: PASS $PASS, FAIL $FAIL" + [ $FAIL -eq 0 ] && exit 0 || exit 1 +diff --git a/tools/testing/selftests/bpf/verifier/array_access.c b/tools/testing/selftests/bpf/verifier/array_access.c +index 1b1c798e92489..1b138cd2b187d 100644 +--- a/tools/testing/selftests/bpf/verifier/array_access.c ++++ b/tools/testing/selftests/bpf/verifier/array_access.c +@@ -186,7 +186,7 @@ + }, + .fixup_map_hash_48b = { 3 }, + .errstr_unpriv = "R0 leaks addr", +- .errstr = "R0 unbounded memory access", ++ .errstr = "invalid access to map value, value_size=48 off=44 size=8", + .result_unpriv = REJECT, + .result = REJECT, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, +diff --git a/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c b/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c +index 6e52dfc644153..6fb52d8cfd889 100644 +--- a/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c ++++ b/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c +@@ -71,6 +71,8 @@ + BPF_EXIT_INSN(), + }, + .result = ACCEPT, ++ .result_unpriv = REJECT, ++ .errstr_unpriv = "R0 leaks addr into mem", + }, + { + "Can't use cmpxchg on uninit src reg", +@@ -118,4 +120,88 @@ + BPF_EXIT_INSN(), + }, + .result = ACCEPT, ++ .result_unpriv = REJECT, ++ .errstr_unpriv = "R0 leaks addr into mem", ++}, ++{ ++ "Dest pointer in r0 - succeed, check 2", ++ .insns = { ++ /* r0 = &val */ ++ BPF_MOV64_REG(BPF_REG_0, BPF_REG_10), ++ /* val = r0; */ ++ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), ++ /* r5 = &val */ ++ BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), ++ /* r0 = atomic_cmpxchg(&val, r0, r5); */ ++ BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), ++ /* r1 = *r0 */ ++ BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8), ++ /* exit(0); */ ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .result_unpriv = REJECT, ++ .errstr_unpriv = "R0 leaks addr into mem", ++}, ++{ ++ "Dest pointer in r0 - succeed, check 3", ++ .insns = { ++ /* r0 = &val */ ++ BPF_MOV64_REG(BPF_REG_0, BPF_REG_10), ++ /* val = r0; */ ++ BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), ++ /* r5 = &val */ ++ BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), ++ /* r0 = atomic_cmpxchg(&val, r0, r5); */ ++ BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), ++ /* exit(0); */ ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = REJECT, ++ .errstr = "invalid size of register fill", ++ .errstr_unpriv = "R0 leaks addr into mem", ++}, ++{ ++ "Dest pointer in r0 - succeed, check 4", ++ .insns = { ++ /* r0 = &val */ ++ BPF_MOV32_REG(BPF_REG_0, BPF_REG_10), ++ /* val = r0; */ ++ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8), ++ /* r5 = &val */ ++ BPF_MOV32_REG(BPF_REG_5, BPF_REG_10), ++ /* r0 = atomic_cmpxchg(&val, r0, r5); */ ++ BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), ++ /* r1 = *r10 */ ++ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -8), ++ /* exit(0); */ ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .result_unpriv = REJECT, ++ .errstr_unpriv = "R10 partial copy of pointer", ++}, ++{ ++ "Dest pointer in r0 - succeed, check 5", ++ .insns = { ++ /* r0 = &val */ ++ BPF_MOV32_REG(BPF_REG_0, BPF_REG_10), ++ /* val = r0; */ ++ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8), ++ /* r5 = &val */ ++ BPF_MOV32_REG(BPF_REG_5, BPF_REG_10), ++ /* r0 = atomic_cmpxchg(&val, r0, r5); */ ++ BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8), ++ /* r1 = *r0 */ ++ BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -8), ++ /* exit(0); */ ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = REJECT, ++ .errstr = "R0 invalid mem access", ++ .errstr_unpriv = "R10 partial copy of pointer", + }, +diff --git a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c +index 2debba4e8a3a8..4d347bc53aa28 100644 +--- a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c ++++ b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c +@@ -1077,6 +1077,29 @@ + .errstr = "R0 invalid mem access 'inv'", + .errstr_unpriv = "R0 pointer -= pointer prohibited", + }, ++{ ++ "map access: trying to leak tained dst reg", ++ .insns = { ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), ++ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), ++ BPF_LD_MAP_FD(BPF_REG_1, 0), ++ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), ++ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), ++ BPF_EXIT_INSN(), ++ BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), ++ BPF_MOV32_IMM(BPF_REG_1, 0xFFFFFFFF), ++ BPF_MOV32_REG(BPF_REG_1, BPF_REG_1), ++ BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1), ++ BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 0), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .fixup_map_array_48b = { 4 }, ++ .result = REJECT, ++ .errstr = "math between map_value pointer and 4294967295 is not allowed", ++}, + { + "32bit pkt_ptr -= scalar", + .insns = { +diff --git a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c +index bfb97383e6b5a..b4ec228eb95d0 100644 +--- a/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c ++++ b/tools/testing/selftests/bpf/verifier/xdp_direct_packet_access.c +@@ -35,7 +35,7 @@ + .prog_type = BPF_PROG_TYPE_XDP, + }, + { +- "XDP pkt read, pkt_data' > pkt_end, good access", ++ "XDP pkt read, pkt_data' > pkt_end, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -87,6 +87,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data' > pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' > pkt_end, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_end > pkt_data', good access", + .insns = { +@@ -106,16 +141,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end > pkt_data', bad access 1", ++ "XDP pkt read, pkt_end > pkt_data', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -142,6 +177,42 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_end > pkt_data', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end > pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data' < pkt_end, good access", + .insns = { +@@ -161,16 +232,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data' < pkt_end, bad access 1", ++ "XDP pkt read, pkt_data' < pkt_end, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -198,7 +269,43 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end < pkt_data', good access", ++ "XDP pkt read, pkt_data' < pkt_end, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' < pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end < pkt_data', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -250,6 +357,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_end < pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end < pkt_data', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data' >= pkt_end, good access", + .insns = { +@@ -268,15 +410,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data' >= pkt_end, bad access 1", ++ "XDP pkt read, pkt_data' >= pkt_end, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -304,7 +446,41 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end >= pkt_data', good access", ++ "XDP pkt read, pkt_data' >= pkt_end, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' >= pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end >= pkt_data', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -359,7 +535,44 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data' <= pkt_end, good access", ++ "XDP pkt read, pkt_end >= pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end >= pkt_data', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' <= pkt_end, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, +@@ -413,6 +626,43 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data' <= pkt_end, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data' <= pkt_end, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_end <= pkt_data', good access", + .insns = { +@@ -431,15 +681,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_end <= pkt_data', bad access 1", ++ "XDP pkt read, pkt_end <= pkt_data', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct xdp_md, data_end)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -467,7 +717,41 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' > pkt_data, good access", ++ "XDP pkt read, pkt_end <= pkt_data', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_end <= pkt_data', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, ++ offsetof(struct xdp_md, data_end)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' > pkt_data, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -519,6 +803,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_meta' > pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' > pkt_data, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data > pkt_meta', good access", + .insns = { +@@ -538,16 +857,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data > pkt_meta', bad access 1", ++ "XDP pkt read, pkt_data > pkt_meta', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -574,6 +893,42 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data > pkt_meta', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data > pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_meta' < pkt_data, good access", + .insns = { +@@ -593,16 +948,16 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' < pkt_data, bad access 1", ++ "XDP pkt read, pkt_meta' < pkt_data, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), + BPF_JMP_IMM(BPF_JA, 0, 0, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -630,7 +985,43 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data < pkt_meta', good access", ++ "XDP pkt read, pkt_meta' < pkt_data, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' < pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data < pkt_meta', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -682,6 +1073,41 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data < pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data < pkt_meta', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_meta' >= pkt_data, good access", + .insns = { +@@ -700,15 +1126,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' >= pkt_data, bad access 1", ++ "XDP pkt read, pkt_meta' >= pkt_data, corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -736,7 +1162,41 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data >= pkt_meta', good access", ++ "XDP pkt read, pkt_meta' >= pkt_data, corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' >= pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data >= pkt_meta', corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -791,7 +1251,44 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_meta' <= pkt_data, good access", ++ "XDP pkt read, pkt_data >= pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data >= pkt_meta', corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' <= pkt_data, corner case, good access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), +@@ -845,6 +1342,43 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_meta' <= pkt_data, corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_meta' <= pkt_data, corner case -1, bad access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), ++ BPF_JMP_IMM(BPF_JA, 0, 0, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .errstr = "R1 offset is outside of the packet", ++ .result = REJECT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, + { + "XDP pkt read, pkt_data <= pkt_meta', good access", + .insns = { +@@ -863,15 +1397,15 @@ + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { +- "XDP pkt read, pkt_data <= pkt_meta', bad access 1", ++ "XDP pkt read, pkt_data <= pkt_meta', corner case -1, bad access", + .insns = { + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct xdp_md, data_meta)), + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), +- BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), +- BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, +@@ -898,3 +1432,37 @@ + .prog_type = BPF_PROG_TYPE_XDP, + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, ++{ ++ "XDP pkt read, pkt_data <= pkt_meta', corner case, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, ++{ ++ "XDP pkt read, pkt_data <= pkt_meta', corner case +1, good access", ++ .insns = { ++ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, ++ offsetof(struct xdp_md, data_meta)), ++ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), ++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), ++ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), ++ BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), ++ BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), ++ BPF_MOV64_IMM(BPF_REG_0, 0), ++ BPF_EXIT_INSN(), ++ }, ++ .result = ACCEPT, ++ .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, ++}, +diff --git a/tools/testing/selftests/bpf/xdp_redirect_multi.c b/tools/testing/selftests/bpf/xdp_redirect_multi.c +index 3696a8f32c235..f5ffba341c174 100644 +--- a/tools/testing/selftests/bpf/xdp_redirect_multi.c ++++ b/tools/testing/selftests/bpf/xdp_redirect_multi.c +@@ -129,7 +129,7 @@ int main(int argc, char **argv) + goto err_out; + } + +- printf("Get interfaces"); ++ printf("Get interfaces:"); + for (i = 0; i < MAX_IFACE_NUM && argv[optind + i]; i++) { + ifaces[i] = if_nametoindex(argv[optind + i]); + if (!ifaces[i]) +@@ -139,7 +139,7 @@ int main(int argc, char **argv) + goto err_out; + } + if (ifaces[i] > MAX_INDEX_NUM) { +- printf("Interface index to large\n"); ++ printf(" interface index too large\n"); + goto err_out; + } + printf(" %d", ifaces[i]); +diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c +index 42be3b9258301..cd4582129c7d6 100644 +--- a/tools/testing/selftests/clone3/clone3.c ++++ b/tools/testing/selftests/clone3/clone3.c +@@ -52,6 +52,12 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) + size = sizeof(struct __clone_args); + + switch (test_mode) { ++ case CLONE3_ARGS_NO_TEST: ++ /* ++ * Uses default 'flags' and 'SIGCHLD' ++ * assignment. ++ */ ++ break; + case CLONE3_ARGS_ALL_0: + args.flags = 0; + args.exit_signal = 0; +@@ -120,8 +126,6 @@ static void test_clone3(uint64_t flags, size_t size, int expected, + + int main(int argc, char *argv[]) + { +- pid_t pid; +- + uid_t uid = getuid(); + + ksft_print_header(); +diff --git a/tools/testing/selftests/core/close_range_test.c b/tools/testing/selftests/core/close_range_test.c +index 73eb29c916d1b..aa7d13d91963f 100644 +--- a/tools/testing/selftests/core/close_range_test.c ++++ b/tools/testing/selftests/core/close_range_test.c +@@ -54,7 +54,7 @@ static inline int sys_close_range(unsigned int fd, unsigned int max_fd, + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + #endif + +-TEST(close_range) ++TEST(core_close_range) + { + int i, ret; + int open_fds[101]; +diff --git a/tools/testing/selftests/damon/.gitignore b/tools/testing/selftests/damon/.gitignore +new file mode 100644 +index 0000000000000..c6c2965a66075 +--- /dev/null ++++ b/tools/testing/selftests/damon/.gitignore +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++huge_count_read_write +diff --git a/tools/testing/selftests/damon/Makefile b/tools/testing/selftests/damon/Makefile +index 8a3f2cd9fec0c..f0aa954b5d135 100644 +--- a/tools/testing/selftests/damon/Makefile ++++ b/tools/testing/selftests/damon/Makefile +@@ -1,6 +1,8 @@ + # SPDX-License-Identifier: GPL-2.0 + # Makefile for damon selftests + ++TEST_GEN_FILES += huge_count_read_write ++ + TEST_FILES = _chk_dependency.sh + TEST_PROGS = debugfs_attrs.sh + +diff --git a/tools/testing/selftests/damon/debugfs_attrs.sh b/tools/testing/selftests/damon/debugfs_attrs.sh +index bfabb19dc0d3d..ecda972e87775 100644 +--- a/tools/testing/selftests/damon/debugfs_attrs.sh ++++ b/tools/testing/selftests/damon/debugfs_attrs.sh +@@ -72,4 +72,22 @@ test_write_succ "$file" "" "$orig_content" "empty input" + test_content "$file" "$orig_content" "" "empty input written" + echo "$orig_content" > "$file" + ++# Test huge count read write ++# ========================== ++ ++dmesg -C ++ ++for file in "$DBGFS/"* ++do ++ ./huge_count_read_write "$file" ++done ++ ++if dmesg | grep -q WARNING ++then ++ dmesg ++ exit 1 ++else ++ exit 0 ++fi ++ + echo "PASS" +diff --git a/tools/testing/selftests/damon/huge_count_read_write.c b/tools/testing/selftests/damon/huge_count_read_write.c +new file mode 100644 +index 0000000000000..ad7a6b4cf3387 +--- /dev/null ++++ b/tools/testing/selftests/damon/huge_count_read_write.c +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Author: SeongJae Park <sj@kernel.org> ++ */ ++ ++#include <fcntl.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <stdio.h> ++ ++void write_read_with_huge_count(char *file) ++{ ++ int filedesc = open(file, O_RDWR); ++ char buf[25]; ++ int ret; ++ ++ printf("%s %s\n", __func__, file); ++ if (filedesc < 0) { ++ fprintf(stderr, "failed opening %s\n", file); ++ exit(1); ++ } ++ ++ write(filedesc, "", 0xfffffffful); ++ perror("after write: "); ++ ret = read(filedesc, buf, 0xfffffffful); ++ perror("after read: "); ++ close(filedesc); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ if (argc != 2) { ++ fprintf(stderr, "Usage: %s <file>\n", argv[0]); ++ exit(1); ++ } ++ write_read_with_huge_count(argv[1]); ++ ++ return 0; ++} +diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh +index 685dfb3478b3e..b9b8274643de1 100755 +--- a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh +@@ -50,8 +50,8 @@ for current_test in ${TESTS:-$ALL_TESTS}; do + else + log_test "'$current_test' [$profile] overflow $target" + fi ++ RET_FIN=$(( RET_FIN || RET )) + done +- RET_FIN=$(( RET_FIN || RET )) + done + done + current_test="" +diff --git a/tools/testing/selftests/drivers/net/mlxsw/tc_police_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/tc_police_scale.sh +index 3e3e06ea5703c..86e787895f78b 100644 +--- a/tools/testing/selftests/drivers/net/mlxsw/tc_police_scale.sh ++++ b/tools/testing/selftests/drivers/net/mlxsw/tc_police_scale.sh +@@ -60,7 +60,8 @@ __tc_police_test() + + tc_police_rules_create $count $should_fail + +- offload_count=$(tc filter show dev $swp1 ingress | grep in_hw | wc -l) ++ offload_count=$(tc -j filter show dev $swp1 ingress | ++ jq "[.[] | select(.options.in_hw == true)] | length") + ((offload_count == count)) + check_err_fail $should_fail $? "tc police offload count" + } +diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile +index dd61118df66ed..2d7fca446c7f7 100644 +--- a/tools/testing/selftests/exec/Makefile ++++ b/tools/testing/selftests/exec/Makefile +@@ -3,9 +3,9 @@ CFLAGS = -Wall + CFLAGS += -Wno-nonnull + CFLAGS += -D_GNU_SOURCE + +-TEST_PROGS := binfmt_script non-regular +-TEST_GEN_PROGS := execveat load_address_4096 load_address_2097152 load_address_16777216 +-TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir pipe ++TEST_PROGS := binfmt_script ++TEST_GEN_PROGS := execveat load_address_4096 load_address_2097152 load_address_16777216 non-regular ++TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir + # Makefile is a run-time dependency, since it's accessed by the execveat test + TEST_FILES := Makefile + +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 e96e279e0533a..25432b8cd5bd2 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,7 @@ fail() { # mesg + + FILTER=set_ftrace_filter + FUNC1="schedule" +-FUNC2="do_softirq" ++FUNC2="scheduler_tick" + + ALL_FUNCS="#### all functions enabled ####" + +diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/profile.tc b/tools/testing/selftests/ftrace/test.d/kprobe/profile.tc +index 98166fa3eb91c..34fb89b0c61fa 100644 +--- a/tools/testing/selftests/ftrace/test.d/kprobe/profile.tc ++++ b/tools/testing/selftests/ftrace/test.d/kprobe/profile.tc +@@ -1,6 +1,6 @@ + #!/bin/sh + # SPDX-License-Identifier: GPL-2.0 +-# description: Kprobe dynamic event - adding and removing ++# description: Kprobe profile + # requires: kprobe_events + + ! grep -q 'myevent' kprobe_profile +diff --git a/tools/testing/selftests/futex/Makefile b/tools/testing/selftests/futex/Makefile +index 12631f0076a10..11e157d7533b8 100644 +--- a/tools/testing/selftests/futex/Makefile ++++ b/tools/testing/selftests/futex/Makefile +@@ -11,7 +11,7 @@ all: + @for DIR in $(SUBDIRS); do \ + BUILD_TARGET=$(OUTPUT)/$$DIR; \ + mkdir $$BUILD_TARGET -p; \ +- make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ ++ $(MAKE) OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ + if [ -e $$DIR/$(TEST_PROGS) ]; then \ + rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/; \ + fi \ +@@ -32,6 +32,6 @@ override define CLEAN + @for DIR in $(SUBDIRS); do \ + BUILD_TARGET=$(OUTPUT)/$$DIR; \ + mkdir $$BUILD_TARGET -p; \ +- make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ ++ $(MAKE) OUTPUT=$$BUILD_TARGET -C $$DIR $@;\ + done + endef +diff --git a/tools/testing/selftests/gpio/Makefile b/tools/testing/selftests/gpio/Makefile +index 39f2bbe8dd3df..42ea7d2aa8440 100644 +--- a/tools/testing/selftests/gpio/Makefile ++++ b/tools/testing/selftests/gpio/Makefile +@@ -3,5 +3,6 @@ + TEST_PROGS := gpio-mockup.sh + TEST_FILES := gpio-mockup-sysfs.sh + TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev ++CFLAGS += -I../../../../usr/include + + include ../lib.mk +diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h +index ae0f0f33b2a6e..78e59620d28de 100644 +--- a/tools/testing/selftests/kselftest_harness.h ++++ b/tools/testing/selftests/kselftest_harness.h +@@ -875,7 +875,8 @@ static void __timeout_handler(int sig, siginfo_t *info, void *ucontext) + } + + t->timed_out = true; +- kill(t->pid, SIGKILL); ++ // signal process group ++ kill(-(t->pid), SIGKILL); + } + + void __wait_for_test(struct __test_metadata *t) +@@ -969,7 +970,7 @@ void __run_test(struct __fixture_metadata *f, + t->passed = 1; + t->skip = 0; + t->trigger = 0; +- t->step = 0; ++ t->step = 1; + t->no_print = 0; + memset(t->results->reason, 0, sizeof(t->results->reason)); + +@@ -985,6 +986,7 @@ void __run_test(struct __fixture_metadata *f, + ksft_print_msg("ERROR SPAWNING TEST CHILD\n"); + t->passed = 0; + } else if (t->pid == 0) { ++ setpgrp(); + t->fn(t, variant); + if (t->skip) + _exit(255); +diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h +index 010b59b139176..1876d148ea0ae 100644 +--- a/tools/testing/selftests/kvm/include/kvm_util.h ++++ b/tools/testing/selftests/kvm/include/kvm_util.h +@@ -309,6 +309,7 @@ bool vm_is_unrestricted_guest(struct kvm_vm *vm); + + unsigned int vm_get_page_size(struct kvm_vm *vm); + unsigned int vm_get_page_shift(struct kvm_vm *vm); ++unsigned long vm_compute_max_gfn(struct kvm_vm *vm); + uint64_t vm_get_max_gfn(struct kvm_vm *vm); + int vm_get_fd(struct kvm_vm *vm); + +diff --git a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c b/tools/testing/selftests/kvm/kvm_create_max_vcpus.c +index 0299cd81b8ba2..aa3795cd7bd3d 100644 +--- a/tools/testing/selftests/kvm/kvm_create_max_vcpus.c ++++ b/tools/testing/selftests/kvm/kvm_create_max_vcpus.c +@@ -12,6 +12,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <sys/resource.h> + + #include "test_util.h" + +@@ -40,10 +41,39 @@ int main(int argc, char *argv[]) + { + int kvm_max_vcpu_id = kvm_check_cap(KVM_CAP_MAX_VCPU_ID); + int kvm_max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); ++ /* ++ * Number of file descriptors reqired, KVM_CAP_MAX_VCPUS for vCPU fds + ++ * an arbitrary number for everything else. ++ */ ++ int nr_fds_wanted = kvm_max_vcpus + 100; ++ struct rlimit rl; + + pr_info("KVM_CAP_MAX_VCPU_ID: %d\n", kvm_max_vcpu_id); + pr_info("KVM_CAP_MAX_VCPUS: %d\n", kvm_max_vcpus); + ++ /* ++ * Check that we're allowed to open nr_fds_wanted file descriptors and ++ * try raising the limits if needed. ++ */ ++ TEST_ASSERT(!getrlimit(RLIMIT_NOFILE, &rl), "getrlimit() failed!"); ++ ++ if (rl.rlim_cur < nr_fds_wanted) { ++ rl.rlim_cur = nr_fds_wanted; ++ if (rl.rlim_max < nr_fds_wanted) { ++ int old_rlim_max = rl.rlim_max; ++ rl.rlim_max = nr_fds_wanted; ++ ++ int r = setrlimit(RLIMIT_NOFILE, &rl); ++ if (r < 0) { ++ printf("RLIMIT_NOFILE hard limit is too low (%d, wanted %d)\n", ++ old_rlim_max, nr_fds_wanted); ++ exit(KSFT_SKIP); ++ } ++ } else { ++ TEST_ASSERT(!setrlimit(RLIMIT_NOFILE, &rl), "setrlimit() failed!"); ++ } ++ } ++ + /* + * Upstream KVM prior to 4.8 does not support KVM_CAP_MAX_VCPU_ID. + * Userspace is supposed to use KVM_CAP_MAX_VCPUS as the maximum ID +diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c +index 10a8ed691c669..e9d0ab9567fbf 100644 +--- a/tools/testing/selftests/kvm/lib/kvm_util.c ++++ b/tools/testing/selftests/kvm/lib/kvm_util.c +@@ -307,7 +307,7 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) + (1ULL << (vm->va_bits - 1)) >> vm->page_shift); + + /* Limit physical addresses to PA-bits. */ +- vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1; ++ vm->max_gfn = vm_compute_max_gfn(vm); + + /* Allocate and setup memory for guest. */ + vm->vpages_mapped = sparsebit_alloc(); +@@ -2282,6 +2282,11 @@ unsigned int vm_get_page_shift(struct kvm_vm *vm) + return vm->page_shift; + } + ++unsigned long __attribute__((weak)) vm_compute_max_gfn(struct kvm_vm *vm) ++{ ++ return ((1ULL << vm->pa_bits) >> vm->page_shift) - 1; ++} ++ + uint64_t vm_get_max_gfn(struct kvm_vm *vm) + { + return vm->max_gfn; +diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c +index 28cb881f440d0..da73b97e1e6dc 100644 +--- a/tools/testing/selftests/kvm/lib/x86_64/processor.c ++++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c +@@ -1433,3 +1433,71 @@ struct kvm_cpuid2 *vcpu_get_supported_hv_cpuid(struct kvm_vm *vm, uint32_t vcpui + + return cpuid; + } ++ ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 ++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 ++ ++static inline unsigned x86_family(unsigned int eax) ++{ ++ unsigned int x86; ++ ++ x86 = (eax >> 8) & 0xf; ++ ++ if (x86 == 0xf) ++ x86 += (eax >> 20) & 0xff; ++ ++ return x86; ++} ++ ++unsigned long vm_compute_max_gfn(struct kvm_vm *vm) ++{ ++ const unsigned long num_ht_pages = 12 << (30 - vm->page_shift); /* 12 GiB */ ++ unsigned long ht_gfn, max_gfn, max_pfn; ++ uint32_t eax, ebx, ecx, edx, max_ext_leaf; ++ ++ max_gfn = (1ULL << (vm->pa_bits - vm->page_shift)) - 1; ++ ++ /* Avoid reserved HyperTransport region on AMD processors. */ ++ eax = ecx = 0; ++ cpuid(&eax, &ebx, &ecx, &edx); ++ if (ebx != X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx || ++ ecx != X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx || ++ edx != X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) ++ return max_gfn; ++ ++ /* On parts with <40 physical address bits, the area is fully hidden */ ++ if (vm->pa_bits < 40) ++ return max_gfn; ++ ++ /* Before family 17h, the HyperTransport area is just below 1T. */ ++ ht_gfn = (1 << 28) - num_ht_pages; ++ eax = 1; ++ cpuid(&eax, &ebx, &ecx, &edx); ++ if (x86_family(eax) < 0x17) ++ goto done; ++ ++ /* ++ * Otherwise it's at the top of the physical address space, possibly ++ * reduced due to SME by bits 11:6 of CPUID[0x8000001f].EBX. Use ++ * the old conservative value if MAXPHYADDR is not enumerated. ++ */ ++ eax = 0x80000000; ++ cpuid(&eax, &ebx, &ecx, &edx); ++ max_ext_leaf = eax; ++ if (max_ext_leaf < 0x80000008) ++ goto done; ++ ++ eax = 0x80000008; ++ cpuid(&eax, &ebx, &ecx, &edx); ++ max_pfn = (1ULL << ((eax & 0xff) - vm->page_shift)) - 1; ++ if (max_ext_leaf >= 0x8000001f) { ++ eax = 0x8000001f; ++ cpuid(&eax, &ebx, &ecx, &edx); ++ max_pfn >>= (ebx >> 6) & 0x3f; ++ } ++ ++ ht_gfn = max_pfn - num_ht_pages; ++done: ++ return min(max_gfn, ht_gfn - 1); ++} +diff --git a/tools/testing/selftests/kvm/lib/x86_64/svm.c b/tools/testing/selftests/kvm/lib/x86_64/svm.c +index 2ac98d70d02bd..161eba7cd1289 100644 +--- a/tools/testing/selftests/kvm/lib/x86_64/svm.c ++++ b/tools/testing/selftests/kvm/lib/x86_64/svm.c +@@ -54,6 +54,18 @@ static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector, + seg->base = base; + } + ++/* ++ * Avoid using memset to clear the vmcb, since libc may not be ++ * available in L1 (and, even if it is, features that libc memset may ++ * want to use, like AVX, may not be enabled). ++ */ ++static void clear_vmcb(struct vmcb *vmcb) ++{ ++ int n = sizeof(*vmcb) / sizeof(u32); ++ ++ asm volatile ("rep stosl" : "+c"(n), "+D"(vmcb) : "a"(0) : "memory"); ++} ++ + void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp) + { + struct vmcb *vmcb = svm->vmcb; +@@ -70,7 +82,7 @@ void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_r + wrmsr(MSR_EFER, efer | EFER_SVME); + wrmsr(MSR_VM_HSAVE_PA, svm->save_area_gpa); + +- memset(vmcb, 0, sizeof(*vmcb)); ++ clear_vmcb(vmcb); + asm volatile ("vmsave %0\n\t" : : "a" (vmcb_gpa) : "memory"); + vmcb_set_seg(&save->es, get_es(), 0, -1U, data_seg_attr); + vmcb_set_seg(&save->cs, get_cs(), 0, -1U, code_seg_attr); +diff --git a/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c b/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c +index 8039e1eff9388..9f55ccd169a13 100644 +--- a/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c ++++ b/tools/testing/selftests/kvm/x86_64/mmio_warning_test.c +@@ -84,7 +84,7 @@ int get_warnings_count(void) + f = popen("dmesg | grep \"WARNING:\" | wc -l", "r"); + if (fscanf(f, "%d", &warnings) < 1) + warnings = 0; +- fclose(f); ++ pclose(f); + + return warnings; + } +diff --git a/tools/testing/selftests/kvm/x86_64/smm_test.c b/tools/testing/selftests/kvm/x86_64/smm_test.c +index d0fe2fdce58c4..db2a17559c3d5 100644 +--- a/tools/testing/selftests/kvm/x86_64/smm_test.c ++++ b/tools/testing/selftests/kvm/x86_64/smm_test.c +@@ -105,7 +105,6 @@ static void guest_code(void *arg) + + if (cpu_has_svm()) { + run_guest(svm->vmcb, svm->vmcb_gpa); +- svm->vmcb->save.rip += 3; + run_guest(svm->vmcb, svm->vmcb_gpa); + } else { + vmlaunch(); +diff --git a/tools/testing/selftests/mincore/mincore_selftest.c b/tools/testing/selftests/mincore/mincore_selftest.c +index e54106643337b..4c88238fc8f05 100644 +--- a/tools/testing/selftests/mincore/mincore_selftest.c ++++ b/tools/testing/selftests/mincore/mincore_selftest.c +@@ -207,15 +207,21 @@ TEST(check_file_mmap) + + errno = 0; + fd = open(".", O_TMPFILE | O_RDWR, 0600); +- ASSERT_NE(-1, fd) { +- TH_LOG("Can't create temporary file: %s", +- strerror(errno)); ++ if (fd < 0) { ++ ASSERT_EQ(errno, EOPNOTSUPP) { ++ TH_LOG("Can't create temporary file: %s", ++ strerror(errno)); ++ } ++ SKIP(goto out_free, "O_TMPFILE not supported by filesystem."); + } + errno = 0; + retval = fallocate(fd, 0, 0, FILE_SIZE); +- ASSERT_EQ(0, retval) { +- TH_LOG("Error allocating space for the temporary file: %s", +- strerror(errno)); ++ if (retval) { ++ ASSERT_EQ(errno, EOPNOTSUPP) { ++ TH_LOG("Error allocating space for the temporary file: %s", ++ strerror(errno)); ++ } ++ SKIP(goto out_close, "fallocate not supported by filesystem."); + } + + /* +@@ -271,7 +277,9 @@ TEST(check_file_mmap) + } + + munmap(addr, FILE_SIZE); ++out_close: + close(fd); ++out_free: + free(vec); + } + +diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c +index f31205f04ee05..8c5fea68ae677 100644 +--- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c ++++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c +@@ -1236,7 +1236,7 @@ static int get_userns_fd(unsigned long nsid, unsigned long hostid, unsigned long + } + + /** +- * Validate that an attached mount in our mount namespace can be idmapped. ++ * Validate that an attached mount in our mount namespace cannot be idmapped. + * (The kernel enforces that the mount's mount namespace and the caller's mount + * namespace match.) + */ +@@ -1259,7 +1259,7 @@ TEST_F(mount_setattr_idmapped, attached_mount_inside_current_mount_namespace) + + attr.userns_fd = get_userns_fd(0, 10000, 10000); + ASSERT_GE(attr.userns_fd, 0); +- ASSERT_EQ(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); ++ ASSERT_NE(sys_mount_setattr(open_tree_fd, "", AT_EMPTY_PATH, &attr, sizeof(attr)), 0); + ASSERT_EQ(close(attr.userns_fd), 0); + ASSERT_EQ(close(open_tree_fd), 0); + } +diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile +index 492b273743b4e..6a953ec793ced 100644 +--- a/tools/testing/selftests/net/Makefile ++++ b/tools/testing/selftests/net/Makefile +@@ -12,7 +12,7 @@ TEST_PROGS += udpgro_bench.sh udpgro.sh test_vxlan_under_vrf.sh reuseport_addr_a + TEST_PROGS += test_vxlan_fdb_changelink.sh so_txtime.sh ipv6_flowlabel.sh + TEST_PROGS += tcp_fastopen_backup_key.sh fcnal-test.sh l2tp.sh traceroute.sh + TEST_PROGS += fin_ack_lat.sh fib_nexthop_multiprefix.sh fib_nexthops.sh +-TEST_PROGS += altnames.sh icmp_redirect.sh ip6_gre_headroom.sh ++TEST_PROGS += altnames.sh icmp.sh icmp_redirect.sh ip6_gre_headroom.sh + TEST_PROGS += route_localnet.sh + TEST_PROGS += reuseaddr_ports_exhausted.sh + TEST_PROGS += txtimestamp.sh +@@ -28,7 +28,12 @@ TEST_PROGS += veth.sh + TEST_PROGS += ioam6.sh + TEST_PROGS += gro.sh + TEST_PROGS += gre_gso.sh +-TEST_PROGS_EXTENDED := in_netns.sh ++TEST_PROGS += srv6_end_dt46_l3vpn_test.sh ++TEST_PROGS += srv6_end_dt4_l3vpn_test.sh ++TEST_PROGS += srv6_end_dt6_l3vpn_test.sh ++TEST_PROGS += vrf_strict_mode_test.sh ++TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh ++TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh + TEST_GEN_FILES = socket nettest + TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any + TEST_GEN_FILES += tcp_mmap tcp_inq psock_snd txring_overwrite +diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh +index 3313566ce9062..aec9e784d0b46 100755 +--- a/tools/testing/selftests/net/fcnal-test.sh ++++ b/tools/testing/selftests/net/fcnal-test.sh +@@ -455,6 +455,22 @@ cleanup() + ip netns del ${NSC} >/dev/null 2>&1 + } + ++cleanup_vrf_dup() ++{ ++ ip link del ${NSA_DEV2} >/dev/null 2>&1 ++ ip netns pids ${NSC} | xargs kill 2>/dev/null ++ ip netns del ${NSC} >/dev/null 2>&1 ++} ++ ++setup_vrf_dup() ++{ ++ # some VRF tests use ns-C which has the same config as ++ # ns-B but for a device NOT in the VRF ++ create_ns ${NSC} "-" "-" ++ connect_ns ${NSA} ${NSA_DEV2} ${NSA_IP}/24 ${NSA_IP6}/64 \ ++ ${NSC} ${NSC_DEV} ${NSB_IP}/24 ${NSB_IP6}/64 ++} ++ + setup() + { + local with_vrf=${1} +@@ -484,12 +500,6 @@ setup() + + ip -netns ${NSB} ro add ${VRF_IP}/32 via ${NSA_IP} dev ${NSB_DEV} + ip -netns ${NSB} -6 ro add ${VRF_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV} +- +- # some VRF tests use ns-C which has the same config as +- # ns-B but for a device NOT in the VRF +- create_ns ${NSC} "-" "-" +- connect_ns ${NSA} ${NSA_DEV2} ${NSA_IP}/24 ${NSA_IP6}/64 \ +- ${NSC} ${NSC_DEV} ${NSB_IP}/24 ${NSB_IP6}/64 + else + ip -netns ${NSA} ro add ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV} + ip -netns ${NSA} ro add ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV} +@@ -1240,7 +1250,9 @@ ipv4_tcp_vrf() + log_test_addr ${a} $? 1 "Global server, local connection" + + # run MD5 tests ++ setup_vrf_dup + ipv4_tcp_md5 ++ cleanup_vrf_dup + + # + # enable VRF global server +@@ -1798,8 +1810,9 @@ ipv4_addr_bind_vrf() + for a in ${NSA_IP} ${VRF_IP} + do + log_start ++ show_hint "Socket not bound to VRF, but address is in VRF" + run_cmd nettest -s -R -P icmp -l ${a} -b +- log_test_addr ${a} $? 0 "Raw socket bind to local address" ++ log_test_addr ${a} $? 1 "Raw socket bind to local address" + + log_start + run_cmd nettest -s -R -P icmp -l ${a} -I ${NSA_DEV} -b +@@ -2191,7 +2204,7 @@ ipv6_ping_vrf() + log_start + show_hint "Fails since VRF device does not support linklocal or multicast" + run_cmd ${ping6} -c1 -w1 ${a} +- log_test_addr ${a} $? 2 "ping out, VRF bind" ++ log_test_addr ${a} $? 1 "ping out, VRF bind" + done + + for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} +@@ -2719,7 +2732,9 @@ ipv6_tcp_vrf() + log_test_addr ${a} $? 1 "Global server, local connection" + + # run MD5 tests ++ setup_vrf_dup + ipv6_tcp_md5 ++ cleanup_vrf_dup + + # + # enable VRF global server +@@ -3414,11 +3429,14 @@ ipv6_addr_bind_novrf() + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" + ++ # Sadly, the kernel allows binding a socket to a device and then ++ # binding to an address not on the device. So this test passes ++ # when it really should not + a=${NSA_LO_IP6} + log_start +- show_hint "Should fail with 'Cannot assign requested address'" ++ show_hint "Tecnically should fail since address is not on device but kernel allows" + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b +- log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" ++ log_test_addr ${a} $? 0 "TCP socket bind to out of scope local address" + } + + ipv6_addr_bind_vrf() +@@ -3459,10 +3477,15 @@ ipv6_addr_bind_vrf() + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b + log_test_addr ${a} $? 0 "TCP socket bind to local address with device bind" + ++ # Sadly, the kernel allows binding a socket to a device and then ++ # binding to an address not on the device. The only restriction ++ # is that the address is valid in the L3 domain. So this test ++ # passes when it really should not + a=${VRF_IP6} + log_start ++ show_hint "Tecnically should fail since address is not on device but kernel allows" + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b +- log_test_addr ${a} $? 1 "TCP socket bind to VRF address with device bind" ++ log_test_addr ${a} $? 0 "TCP socket bind to VRF address with device bind" + + a=${NSA_LO_IP6} + log_start +@@ -4002,8 +4025,8 @@ EOF + ################################################################################ + # main + +-TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" +-TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime ipv6_netfilter" ++TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_bind ipv4_runtime ipv4_netfilter" ++TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_bind ipv6_runtime ipv6_netfilter" + TESTS_OTHER="use_cases" + + PAUSE_ON_FAIL=no +diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh +index 0d293391e9a44..b5a69ad191b07 100755 +--- a/tools/testing/selftests/net/fib_nexthops.sh ++++ b/tools/testing/selftests/net/fib_nexthops.sh +@@ -2078,6 +2078,7 @@ basic_res() + "id 101 index 0 nhid 2 id 101 index 1 nhid 2 id 101 index 2 nhid 1 id 101 index 3 nhid 1" + log_test $? 0 "Dump all nexthop buckets in a group" + ++ sleep 0.1 + (( $($IP -j nexthop bucket list id 101 | + jq '[.[] | select(.bucket.idle_time > 0 and + .bucket.idle_time < 2)] | length') == 4 )) +diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh +index 5abe92d55b696..996af1ae3d3dd 100755 +--- a/tools/testing/selftests/net/fib_tests.sh ++++ b/tools/testing/selftests/net/fib_tests.sh +@@ -444,24 +444,63 @@ fib_rp_filter_test() + setup + + set -e ++ ip netns add ns2 ++ ip netns set ns2 auto ++ ++ ip -netns ns2 link set dev lo up ++ ++ $IP link add name veth1 type veth peer name veth2 ++ $IP link set dev veth2 netns ns2 ++ $IP address add 192.0.2.1/24 dev veth1 ++ ip -netns ns2 address add 192.0.2.1/24 dev veth2 ++ $IP link set dev veth1 up ++ ip -netns ns2 link set dev veth2 up ++ + $IP link set dev lo address 52:54:00:6a:c7:5e +- $IP link set dummy0 address 52:54:00:6a:c7:5e +- $IP link add dummy1 type dummy +- $IP link set dummy1 address 52:54:00:6a:c7:5e +- $IP link set dev dummy1 up ++ $IP link set dev veth1 address 52:54:00:6a:c7:5e ++ ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e ++ ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e ++ ++ # 1. (ns2) redirect lo's egress to veth2's egress ++ ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel ++ ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \ ++ action mirred egress redirect dev veth2 ++ ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \ ++ action mirred egress redirect dev veth2 ++ ++ # 2. (ns1) redirect veth1's ingress to lo's ingress ++ $NS_EXEC tc qdisc add dev veth1 ingress ++ $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \ ++ action mirred ingress redirect dev lo ++ $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \ ++ action mirred ingress redirect dev lo ++ ++ # 3. (ns1) redirect lo's egress to veth1's egress ++ $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel ++ $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \ ++ action mirred egress redirect dev veth1 ++ $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \ ++ action mirred egress redirect dev veth1 ++ ++ # 4. (ns2) redirect veth2's ingress to lo's ingress ++ ip netns exec ns2 tc qdisc add dev veth2 ingress ++ ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \ ++ action mirred ingress redirect dev lo ++ ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \ ++ action mirred ingress redirect dev lo ++ + $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1 + $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1 + $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1 +- +- $NS_EXEC tc qd add dev dummy1 parent root handle 1: fq_codel +- $NS_EXEC tc filter add dev dummy1 parent 1: protocol arp basic action mirred egress redirect dev lo +- $NS_EXEC tc filter add dev dummy1 parent 1: protocol ip basic action mirred egress redirect dev lo ++ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1 ++ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1 ++ ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1 + set +e + +- run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 198.51.100.1" ++ run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1" + log_test $? 0 "rp_filter passes local packets" + +- run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 127.0.0.1" ++ run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1" + log_test $? 0 "rp_filter passes loopback packets" + + cleanup +diff --git a/tools/testing/selftests/net/forwarding/bridge_igmp.sh b/tools/testing/selftests/net/forwarding/bridge_igmp.sh +index 675eff45b0371..1162836f8f329 100755 +--- a/tools/testing/selftests/net/forwarding/bridge_igmp.sh ++++ b/tools/testing/selftests/net/forwarding/bridge_igmp.sh +@@ -482,10 +482,15 @@ v3exc_timeout_test() + local X=("192.0.2.20" "192.0.2.30") + + # GMI should be 3 seconds +- ip link set dev br0 type bridge mcast_query_interval 100 mcast_query_response_interval 100 ++ ip link set dev br0 type bridge mcast_query_interval 100 \ ++ mcast_query_response_interval 100 \ ++ mcast_membership_interval 300 + + v3exclude_prepare $h1 $ALL_MAC $ALL_GROUP +- ip link set dev br0 type bridge mcast_query_interval 500 mcast_query_response_interval 500 ++ ip link set dev br0 type bridge mcast_query_interval 500 \ ++ mcast_query_response_interval 500 \ ++ mcast_membership_interval 1500 ++ + $MZ $h1 -c 1 -b $ALL_MAC -B $ALL_GROUP -t ip "proto=2,p=$MZPKT_ALLOW2" -q + sleep 3 + bridge -j -d -s mdb show dev br0 \ +@@ -517,7 +522,8 @@ v3exc_timeout_test() + log_test "IGMPv3 group $TEST_GROUP exclude timeout" + + ip link set dev br0 type bridge mcast_query_interval 12500 \ +- mcast_query_response_interval 1000 ++ mcast_query_response_interval 1000 \ ++ mcast_membership_interval 26000 + + v3cleanup $swp1 $TEST_GROUP + } +diff --git a/tools/testing/selftests/net/forwarding/bridge_mld.sh b/tools/testing/selftests/net/forwarding/bridge_mld.sh +index ffdcfa87ca2ba..e2b9ff773c6b6 100755 +--- a/tools/testing/selftests/net/forwarding/bridge_mld.sh ++++ b/tools/testing/selftests/net/forwarding/bridge_mld.sh +@@ -479,10 +479,15 @@ mldv2exc_timeout_test() + local X=("2001:db8:1::20" "2001:db8:1::30") + + # GMI should be 3 seconds +- ip link set dev br0 type bridge mcast_query_interval 100 mcast_query_response_interval 100 ++ ip link set dev br0 type bridge mcast_query_interval 100 \ ++ mcast_query_response_interval 100 \ ++ mcast_membership_interval 300 + + mldv2exclude_prepare $h1 +- ip link set dev br0 type bridge mcast_query_interval 500 mcast_query_response_interval 500 ++ ip link set dev br0 type bridge mcast_query_interval 500 \ ++ mcast_query_response_interval 500 \ ++ mcast_membership_interval 1500 ++ + $MZ $h1 -c 1 $MZPKT_ALLOW2 -q + sleep 3 + bridge -j -d -s mdb show dev br0 \ +@@ -514,7 +519,8 @@ mldv2exc_timeout_test() + log_test "MLDv2 group $TEST_GROUP exclude timeout" + + ip link set dev br0 type bridge mcast_query_interval 12500 \ +- mcast_query_response_interval 1000 ++ mcast_query_response_interval 1000 \ ++ mcast_membership_interval 26000 + + mldv2cleanup $swp1 + } +diff --git a/tools/testing/selftests/net/forwarding/forwarding.config.sample b/tools/testing/selftests/net/forwarding/forwarding.config.sample +index e5e2fbeca22ec..e51def39fd801 100644 +--- a/tools/testing/selftests/net/forwarding/forwarding.config.sample ++++ b/tools/testing/selftests/net/forwarding/forwarding.config.sample +@@ -13,6 +13,8 @@ NETIFS[p5]=veth4 + NETIFS[p6]=veth5 + NETIFS[p7]=veth6 + NETIFS[p8]=veth7 ++NETIFS[p9]=veth8 ++NETIFS[p10]=veth9 + + # Port that does not have a cable connected. + NETIF_NO_CABLE=eth8 +diff --git a/tools/testing/selftests/net/gre_gso.sh b/tools/testing/selftests/net/gre_gso.sh +index facbb0c804439..3224651db97b8 100755 +--- a/tools/testing/selftests/net/gre_gso.sh ++++ b/tools/testing/selftests/net/gre_gso.sh +@@ -116,17 +116,20 @@ gre_gst_test_checks() + { + local name=$1 + local addr=$2 ++ local proto=$3 + +- $NS_EXEC nc -kl $port >/dev/null & ++ [ "$proto" == 6 ] && addr="[$addr]" ++ ++ $NS_EXEC socat - tcp${proto}-listen:$port,reuseaddr,fork >/dev/null & + PID=$! + while ! $NS_EXEC ss -ltn | grep -q $port; do ((i++)); sleep 0.01; done + +- cat $TMPFILE | timeout 1 nc $addr $port ++ cat $TMPFILE | timeout 1 socat -u STDIN TCP:$addr:$port + log_test $? 0 "$name - copy file w/ TSO" + + ethtool -K veth0 tso off + +- cat $TMPFILE | timeout 1 nc $addr $port ++ cat $TMPFILE | timeout 1 socat -u STDIN TCP:$addr:$port + log_test $? 0 "$name - copy file w/ GSO" + + ethtool -K veth0 tso on +@@ -154,8 +157,8 @@ gre6_gso_test() + + sleep 2 + +- gre_gst_test_checks GREv6/v4 172.16.2.2 +- gre_gst_test_checks GREv6/v6 2001:db8:1::2 ++ gre_gst_test_checks GREv6/v4 172.16.2.2 4 ++ gre_gst_test_checks GREv6/v6 2001:db8:1::2 6 + + cleanup + } +@@ -211,8 +214,8 @@ if [ ! -x "$(command -v ip)" ]; then + exit $ksft_skip + fi + +-if [ ! -x "$(command -v nc)" ]; then +- echo "SKIP: Could not run test without nc tool" ++if [ ! -x "$(command -v socat)" ]; then ++ echo "SKIP: Could not run test without socat tool" + exit $ksft_skip + fi + +diff --git a/tools/testing/selftests/net/icmp_redirect.sh b/tools/testing/selftests/net/icmp_redirect.sh +index ecbf57f264ed9..7b9d6e31b8e7d 100755 +--- a/tools/testing/selftests/net/icmp_redirect.sh ++++ b/tools/testing/selftests/net/icmp_redirect.sh +@@ -311,7 +311,7 @@ check_exception() + ip -netns h1 ro get ${H1_VRF_ARG} ${H2_N2_IP} | \ + grep -E -v 'mtu|redirected' | grep -q "cache" + fi +- log_test $? 0 "IPv4: ${desc}" ++ log_test $? 0 "IPv4: ${desc}" 0 + + # No PMTU info for test "redirect" and "mtu exception plus redirect" + if [ "$with_redirect" = "yes" ] && [ "$desc" != "redirect exception plus mtu" ]; then +diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh +index 2674ba20d5249..ff821025d3096 100755 +--- a/tools/testing/selftests/net/mptcp/diag.sh ++++ b/tools/testing/selftests/net/mptcp/diag.sh +@@ -71,6 +71,36 @@ chk_msk_remote_key_nr() + __chk_nr "grep -c remote_key" $* + } + ++# $1: ns, $2: port ++wait_local_port_listen() ++{ ++ local listener_ns="${1}" ++ local port="${2}" ++ ++ local port_hex i ++ ++ port_hex="$(printf "%04X" "${port}")" ++ for i in $(seq 10); do ++ ip netns exec "${listener_ns}" cat /proc/net/tcp | \ ++ awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && ++ break ++ sleep 0.1 ++ done ++} ++ ++wait_connected() ++{ ++ local listener_ns="${1}" ++ local port="${2}" ++ ++ local port_hex i ++ ++ port_hex="$(printf "%04X" "${port}")" ++ for i in $(seq 10); do ++ ip netns exec ${listener_ns} grep -q " 0100007F:${port_hex} " /proc/net/tcp && break ++ sleep 0.1 ++ done ++} + + trap cleanup EXIT + ip netns add $ns +@@ -81,15 +111,15 @@ echo "a" | \ + ip netns exec $ns \ + ./mptcp_connect -p 10000 -l -t ${timeout_poll} \ + 0.0.0.0 >/dev/null & +-sleep 0.1 ++wait_local_port_listen $ns 10000 + chk_msk_nr 0 "no msk on netns creation" + + echo "b" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ +- ./mptcp_connect -p 10000 -j -t ${timeout_poll} \ ++ ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} \ + 127.0.0.1 >/dev/null & +-sleep 0.1 ++wait_connected $ns 10000 + chk_msk_nr 2 "after MPC handshake " + chk_msk_remote_key_nr 2 "....chk remote_key" + chk_msk_fallback_nr 0 "....chk no fallback" +@@ -101,13 +131,13 @@ echo "a" | \ + ip netns exec $ns \ + ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} \ + 0.0.0.0 >/dev/null & +-sleep 0.1 ++wait_local_port_listen $ns 10001 + echo "b" | \ + timeout ${timeout_test} \ + ip netns exec $ns \ +- ./mptcp_connect -p 10001 -j -t ${timeout_poll} \ ++ ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} \ + 127.0.0.1 >/dev/null & +-sleep 0.1 ++wait_connected $ns 10001 + chk_msk_fallback_nr 1 "check fallback" + flush_pids + +@@ -119,7 +149,7 @@ for I in `seq 1 $NR_CLIENTS`; do + ./mptcp_connect -p $((I+10001)) -l -w 10 \ + -t ${timeout_poll} 0.0.0.0 >/dev/null & + done +-sleep 0.1 ++wait_local_port_listen $ns $((NR_CLIENTS + 10001)) + + for I in `seq 1 $NR_CLIENTS`; do + echo "b" | \ +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index 255793c5ac4ff..3be615ab1588b 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -75,6 +75,7 @@ init() + + # let $ns2 reach any $ns1 address from any interface + ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i ++ ip -net "$ns2" route add default via dead:beef:$i::1 dev ns2eth$i metric 10$i + done + } + +@@ -297,7 +298,7 @@ do_transfer() + if [ "$test_link_fail" -eq 2 ];then + timeout ${timeout_test} \ + ip netns exec ${listener_ns} \ +- $mptcp_connect -t ${timeout_poll} -l -p $port -s ${cl_proto} \ ++ $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ + ${local_addr} < "$sinfail" > "$sout" & + else + timeout ${timeout_test} \ +@@ -623,6 +624,7 @@ chk_join_nr() + local ack_nr=$4 + local count + local dump_stats ++ local with_cookie + + printf "%02u %-36s %s" "$TEST_COUNT" "$msg" "syn" + count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}'` +@@ -636,12 +638,20 @@ chk_join_nr() + fi + + echo -n " - synack" ++ with_cookie=`ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies` + count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}'` + [ -z "$count" ] && count=0 + if [ "$count" != "$syn_ack_nr" ]; then +- echo "[fail] got $count JOIN[s] synack expected $syn_ack_nr" +- ret=1 +- dump_stats=1 ++ # simult connections exceeding the limit with cookie enabled could go up to ++ # synack validation as the conn limit can be enforced reliably only after ++ # the subflow creation ++ if [ "$with_cookie" = 2 ] && [ "$count" -gt "$syn_ack_nr" ] && [ "$count" -le "$syn_nr" ]; then ++ echo -n "[ ok ]" ++ else ++ echo "[fail] got $count JOIN[s] synack expected $syn_ack_nr" ++ ret=1 ++ dump_stats=1 ++ fi + else + echo -n "[ ok ]" + fi +@@ -1383,7 +1393,7 @@ ipv6_tests() + reset + ip netns exec $ns1 ./pm_nl_ctl limits 0 1 + ip netns exec $ns2 ./pm_nl_ctl limits 0 1 +- ip netns exec $ns2 ./pm_nl_ctl add dead:beef:3::2 flags subflow ++ ip netns exec $ns2 ./pm_nl_ctl add dead:beef:3::2 dev ns2eth3 flags subflow + run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow + chk_join_nr "single subflow IPv6" 1 1 1 + +@@ -1418,7 +1428,7 @@ ipv6_tests() + ip netns exec $ns1 ./pm_nl_ctl limits 0 2 + ip netns exec $ns1 ./pm_nl_ctl add dead:beef:2::1 flags signal + ip netns exec $ns2 ./pm_nl_ctl limits 1 2 +- ip netns exec $ns2 ./pm_nl_ctl add dead:beef:3::2 flags subflow ++ ip netns exec $ns2 ./pm_nl_ctl add dead:beef:3::2 dev ns2eth3 flags subflow + run_tests $ns1 $ns2 dead:beef:1::1 0 -1 -1 slow + chk_join_nr "remove subflow and signal IPv6" 2 2 2 + chk_add_nr 1 1 +diff --git a/tools/testing/selftests/net/toeplitz.c b/tools/testing/selftests/net/toeplitz.c +index 710ac956bdb33..c5489341cfb80 100644 +--- a/tools/testing/selftests/net/toeplitz.c ++++ b/tools/testing/selftests/net/toeplitz.c +@@ -498,7 +498,7 @@ static void parse_opts(int argc, char **argv) + bool have_toeplitz = false; + int index, c; + +- while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:u:v", long_options, &index)) != -1) { ++ while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:uv", long_options, &index)) != -1) { + switch (c) { + case '4': + cfg_family = AF_INET; +diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh +index 7f26591f236b9..6f05e06f67613 100755 +--- a/tools/testing/selftests/net/udpgro_fwd.sh ++++ b/tools/testing/selftests/net/udpgro_fwd.sh +@@ -132,7 +132,7 @@ run_test() { + local rcv=`ip netns exec $NS_DST $ipt"-save" -c | grep 'dport 8000' | \ + sed -e 's/\[//' -e 's/:.*//'` + if [ $rcv != $pkts ]; then +- echo " fail - received $rvs packets, expected $pkts" ++ echo " fail - received $rcv packets, expected $pkts" + ret=1 + return + fi +@@ -185,6 +185,7 @@ for family in 4 6; do + IPT=iptables + SUFFIX=24 + VXDEV=vxlan ++ PING=ping + + if [ $family = 6 ]; then + BM_NET=$BM_NET_V6 +@@ -192,6 +193,8 @@ for family in 4 6; do + SUFFIX="64 nodad" + VXDEV=vxlan6 + IPT=ip6tables ++ # Use ping6 on systems where ping doesn't handle IPv6 ++ ping -w 1 -c 1 ::1 > /dev/null 2>&1 || PING="ping6" + fi + + echo "IPv$family" +@@ -237,7 +240,7 @@ for family in 4 6; do + + # load arp cache before running the test to reduce the amount of + # stray traffic on top of the UDP tunnel +- ip netns exec $NS_SRC ping -q -c 1 $OL_NET$DST_NAT >/dev/null ++ ip netns exec $NS_SRC $PING -q -c 1 $OL_NET$DST_NAT >/dev/null + run_test "GRO fwd over UDP tunnel" $OL_NET$DST_NAT 1 1 $OL_NET$DST + cleanup + +diff --git a/tools/testing/selftests/net/udpgso.c b/tools/testing/selftests/net/udpgso.c +index c66da6ffd6d8d..7badaf215de28 100644 +--- a/tools/testing/selftests/net/udpgso.c ++++ b/tools/testing/selftests/net/udpgso.c +@@ -156,13 +156,13 @@ struct testcase testcases_v4[] = { + }, + { + /* send max number of min sized segments */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V4, ++ .tlen = UDP_MAX_SEGMENTS, + .gso_len = 1, +- .r_num_mss = UDP_MAX_SEGMENTS - CONST_HDRLEN_V4, ++ .r_num_mss = UDP_MAX_SEGMENTS, + }, + { + /* send max number + 1 of min sized segments: fail */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V4 + 1, ++ .tlen = UDP_MAX_SEGMENTS + 1, + .gso_len = 1, + .tfail = true, + }, +@@ -259,13 +259,13 @@ struct testcase testcases_v6[] = { + }, + { + /* send max number of min sized segments */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V6, ++ .tlen = UDP_MAX_SEGMENTS, + .gso_len = 1, +- .r_num_mss = UDP_MAX_SEGMENTS - CONST_HDRLEN_V6, ++ .r_num_mss = UDP_MAX_SEGMENTS, + }, + { + /* send max number + 1 of min sized segments: fail */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V6 + 1, ++ .tlen = UDP_MAX_SEGMENTS + 1, + .gso_len = 1, + .tfail = true, + }, +diff --git a/tools/testing/selftests/net/udpgso_bench_rx.c b/tools/testing/selftests/net/udpgso_bench_rx.c +index 76a24052f4b47..6a193425c367f 100644 +--- a/tools/testing/selftests/net/udpgso_bench_rx.c ++++ b/tools/testing/selftests/net/udpgso_bench_rx.c +@@ -293,19 +293,17 @@ static void usage(const char *filepath) + + static void parse_opts(int argc, char **argv) + { ++ const char *bind_addr = NULL; + int c; + +- /* bind to any by default */ +- setup_sockaddr(PF_INET6, "::", &cfg_bind_addr); + while ((c = getopt(argc, argv, "4b:C:Gl:n:p:rR:S:tv")) != -1) { + switch (c) { + case '4': + cfg_family = PF_INET; + cfg_alen = sizeof(struct sockaddr_in); +- setup_sockaddr(PF_INET, "0.0.0.0", &cfg_bind_addr); + break; + case 'b': +- setup_sockaddr(cfg_family, optarg, &cfg_bind_addr); ++ bind_addr = optarg; + break; + case 'C': + cfg_connect_timeout_ms = strtoul(optarg, NULL, 0); +@@ -341,6 +339,11 @@ static void parse_opts(int argc, char **argv) + } + } + ++ if (!bind_addr) ++ bind_addr = cfg_family == PF_INET6 ? "::" : "0.0.0.0"; ++ ++ setup_sockaddr(cfg_family, bind_addr, &cfg_bind_addr); ++ + if (optind != argc) + usage(argv[0]); + +diff --git a/tools/testing/selftests/net/udpgso_bench_tx.c b/tools/testing/selftests/net/udpgso_bench_tx.c +index 17512a43885e7..f1fdaa2702913 100644 +--- a/tools/testing/selftests/net/udpgso_bench_tx.c ++++ b/tools/testing/selftests/net/udpgso_bench_tx.c +@@ -419,6 +419,7 @@ static void usage(const char *filepath) + + static void parse_opts(int argc, char **argv) + { ++ const char *bind_addr = NULL; + int max_len, hdrlen; + int c; + +@@ -446,7 +447,7 @@ static void parse_opts(int argc, char **argv) + cfg_cpu = strtol(optarg, NULL, 0); + break; + case 'D': +- setup_sockaddr(cfg_family, optarg, &cfg_dst_addr); ++ bind_addr = optarg; + break; + case 'l': + cfg_runtime_ms = strtoul(optarg, NULL, 10) * 1000; +@@ -492,6 +493,11 @@ static void parse_opts(int argc, char **argv) + } + } + ++ if (!bind_addr) ++ bind_addr = cfg_family == PF_INET6 ? "::" : "0.0.0.0"; ++ ++ setup_sockaddr(cfg_family, bind_addr, &cfg_dst_addr); ++ + if (optind != argc) + usage(argv[0]); + +diff --git a/tools/testing/selftests/netfilter/Makefile b/tools/testing/selftests/netfilter/Makefile +index 8748199ac1098..ffca314897c4c 100644 +--- a/tools/testing/selftests/netfilter/Makefile ++++ b/tools/testing/selftests/netfilter/Makefile +@@ -5,7 +5,8 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \ + conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \ + nft_concat_range.sh nft_conntrack_helper.sh \ + nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ +- ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh ++ ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ ++ conntrack_vrf.sh + + LDLIBS = -lmnl + TEST_GEN_FILES = nf-queue +diff --git a/tools/testing/selftests/netfilter/conntrack_vrf.sh b/tools/testing/selftests/netfilter/conntrack_vrf.sh +new file mode 100755 +index 0000000000000..8b5ea92345882 +--- /dev/null ++++ b/tools/testing/selftests/netfilter/conntrack_vrf.sh +@@ -0,0 +1,241 @@ ++#!/bin/sh ++ ++# This script demonstrates interaction of conntrack and vrf. ++# The vrf driver calls the netfilter hooks again, with oif/iif ++# pointing at the VRF device. ++# ++# For ingress, this means first iteration has iifname of lower/real ++# device. In this script, thats veth0. ++# Second iteration is iifname set to vrf device, tvrf in this script. ++# ++# For egress, this is reversed: first iteration has the vrf device, ++# second iteration is done with the lower/real/veth0 device. ++# ++# test_ct_zone_in demonstrates unexpected change of nftables ++# behavior # caused by commit 09e856d54bda5f28 "vrf: Reset skb conntrack ++# connection on VRF rcv" ++# ++# It was possible to assign conntrack zone to a packet (or mark it for ++# `notracking`) in the prerouting chain before conntrack, based on real iif. ++# ++# After the change, the zone assignment is lost and the zone is assigned based ++# on the VRF master interface (in case such a rule exists). ++# assignment is lost. Instead, assignment based on the `iif` matching ++# Thus it is impossible to distinguish packets based on the original ++# interface. ++# ++# test_masquerade_vrf and test_masquerade_veth0 demonstrate the problem ++# that was supposed to be fixed by the commit mentioned above to make sure ++# that any fix to test case 1 won't break masquerade again. ++ ++ksft_skip=4 ++ ++IP0=172.30.30.1 ++IP1=172.30.30.2 ++PFXL=30 ++ret=0 ++ ++sfx=$(mktemp -u "XXXXXXXX") ++ns0="ns0-$sfx" ++ns1="ns1-$sfx" ++ ++cleanup() ++{ ++ ip netns pids $ns0 | xargs kill 2>/dev/null ++ ip netns pids $ns1 | xargs kill 2>/dev/null ++ ++ ip netns del $ns0 $ns1 ++} ++ ++nft --version > /dev/null 2>&1 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not run test without nft tool" ++ exit $ksft_skip ++fi ++ ++ip -Version > /dev/null 2>&1 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not run test without ip tool" ++ exit $ksft_skip ++fi ++ ++ip netns add "$ns0" ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not create net namespace $ns0" ++ exit $ksft_skip ++fi ++ip netns add "$ns1" ++ ++trap cleanup EXIT ++ ++ip netns exec $ns0 sysctl -q -w net.ipv4.conf.default.rp_filter=0 ++ip netns exec $ns0 sysctl -q -w net.ipv4.conf.all.rp_filter=0 ++ip netns exec $ns0 sysctl -q -w net.ipv4.conf.all.rp_filter=0 ++ ++ip link add veth0 netns "$ns0" type veth peer name veth0 netns "$ns1" > /dev/null 2>&1 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not add veth device" ++ exit $ksft_skip ++fi ++ ++ip -net $ns0 li add tvrf type vrf table 9876 ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not add vrf device" ++ exit $ksft_skip ++fi ++ ++ip -net $ns0 li set lo up ++ ++ip -net $ns0 li set veth0 master tvrf ++ip -net $ns0 li set tvrf up ++ip -net $ns0 li set veth0 up ++ip -net $ns1 li set veth0 up ++ ++ip -net $ns0 addr add $IP0/$PFXL dev veth0 ++ip -net $ns1 addr add $IP1/$PFXL dev veth0 ++ ++ip netns exec $ns1 iperf3 -s > /dev/null 2>&1& ++if [ $? -ne 0 ];then ++ echo "SKIP: Could not start iperf3" ++ exit $ksft_skip ++fi ++ ++# test vrf ingress handling. ++# The incoming connection should be placed in conntrack zone 1, ++# as decided by the first iteration of the ruleset. ++test_ct_zone_in() ++{ ++ip netns exec $ns0 nft -f - <<EOF ++table testct { ++ chain rawpre { ++ type filter hook prerouting priority raw; ++ ++ iif { veth0, tvrf } counter meta nftrace set 1 ++ iif veth0 counter ct zone set 1 counter return ++ iif tvrf counter ct zone set 2 counter return ++ ip protocol icmp counter ++ notrack counter ++ } ++ ++ chain rawout { ++ type filter hook output priority raw; ++ ++ oif veth0 counter ct zone set 1 counter return ++ oif tvrf counter ct zone set 2 counter return ++ notrack counter ++ } ++} ++EOF ++ ip netns exec $ns1 ping -W 1 -c 1 -I veth0 $IP0 > /dev/null ++ ++ # should be in zone 1, not zone 2 ++ count=$(ip netns exec $ns0 conntrack -L -s $IP1 -d $IP0 -p icmp --zone 1 2>/dev/null | wc -l) ++ if [ $count -eq 1 ]; then ++ echo "PASS: entry found in conntrack zone 1" ++ else ++ echo "FAIL: entry not found in conntrack zone 1" ++ count=$(ip netns exec $ns0 conntrack -L -s $IP1 -d $IP0 -p icmp --zone 2 2> /dev/null | wc -l) ++ if [ $count -eq 1 ]; then ++ echo "FAIL: entry found in zone 2 instead" ++ else ++ echo "FAIL: entry not in zone 1 or 2, dumping table" ++ ip netns exec $ns0 conntrack -L ++ ip netns exec $ns0 nft list ruleset ++ fi ++ fi ++} ++ ++# add masq rule that gets evaluated w. outif set to vrf device. ++# This tests the first iteration of the packet through conntrack, ++# oifname is the vrf device. ++test_masquerade_vrf() ++{ ++ local qdisc=$1 ++ ++ if [ "$qdisc" != "default" ]; then ++ tc -net $ns0 qdisc add dev tvrf root $qdisc ++ fi ++ ++ ip netns exec $ns0 conntrack -F 2>/dev/null ++ ++ip netns exec $ns0 nft -f - <<EOF ++flush ruleset ++table ip nat { ++ chain rawout { ++ type filter hook output priority raw; ++ ++ oif tvrf ct state untracked counter ++ } ++ chain postrouting2 { ++ type filter hook postrouting priority mangle; ++ ++ oif tvrf ct state untracked counter ++ } ++ chain postrouting { ++ type nat hook postrouting priority 0; ++ # NB: masquerade should always be combined with 'oif(name) bla', ++ # lack of this is intentional here, we want to exercise double-snat. ++ ip saddr 172.30.30.0/30 counter masquerade random ++ } ++} ++EOF ++ ip netns exec $ns0 ip vrf exec tvrf iperf3 -t 1 -c $IP1 >/dev/null ++ if [ $? -ne 0 ]; then ++ echo "FAIL: iperf3 connect failure with masquerade + sport rewrite on vrf device" ++ ret=1 ++ return ++ fi ++ ++ # must also check that nat table was evaluated on second (lower device) iteration. ++ ip netns exec $ns0 nft list table ip nat |grep -q 'counter packets 2' && ++ ip netns exec $ns0 nft list table ip nat |grep -q 'untracked counter packets [1-9]' ++ if [ $? -eq 0 ]; then ++ echo "PASS: iperf3 connect with masquerade + sport rewrite on vrf device ($qdisc qdisc)" ++ else ++ echo "FAIL: vrf rules have unexpected counter value" ++ ret=1 ++ fi ++ ++ if [ "$qdisc" != "default" ]; then ++ tc -net $ns0 qdisc del dev tvrf root ++ fi ++} ++ ++# add masq rule that gets evaluated w. outif set to veth device. ++# This tests the 2nd iteration of the packet through conntrack, ++# oifname is the lower device (veth0 in this case). ++test_masquerade_veth() ++{ ++ ip netns exec $ns0 conntrack -F 2>/dev/null ++ip netns exec $ns0 nft -f - <<EOF ++flush ruleset ++table ip nat { ++ chain postrouting { ++ type nat hook postrouting priority 0; ++ meta oif veth0 ip saddr 172.30.30.0/30 counter masquerade random ++ } ++} ++EOF ++ ip netns exec $ns0 ip vrf exec tvrf iperf3 -t 1 -c $IP1 > /dev/null ++ if [ $? -ne 0 ]; then ++ echo "FAIL: iperf3 connect failure with masquerade + sport rewrite on veth device" ++ ret=1 ++ return ++ fi ++ ++ # must also check that nat table was evaluated on second (lower device) iteration. ++ ip netns exec $ns0 nft list table ip nat |grep -q 'counter packets 2' ++ if [ $? -eq 0 ]; then ++ echo "PASS: iperf3 connect with masquerade + sport rewrite on veth device" ++ else ++ echo "FAIL: vrf masq rule has unexpected counter value" ++ ret=1 ++ fi ++} ++ ++test_ct_zone_in ++test_masquerade_vrf "default" ++test_masquerade_vrf "pfifo" ++test_masquerade_veth ++ ++exit $ret +diff --git a/tools/testing/selftests/netfilter/nft_concat_range.sh b/tools/testing/selftests/netfilter/nft_concat_range.sh +index 5a4938d6dcf25..b5eef5ffb58e5 100755 +--- a/tools/testing/selftests/netfilter/nft_concat_range.sh ++++ b/tools/testing/selftests/netfilter/nft_concat_range.sh +@@ -27,7 +27,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto + net_port_mac_proto_net" + + # Reported bugs, also described by TYPE_ variables below +-BUGS="flush_remove_add" ++BUGS="flush_remove_add reload" + + # List of possible paths to pktgen script from kernel tree for performance tests + PKTGEN_SCRIPT_PATHS=" +@@ -337,6 +337,23 @@ TYPE_flush_remove_add=" + display Add two elements, flush, re-add + " + ++TYPE_reload=" ++display net,mac with reload ++type_spec ipv4_addr . ether_addr ++chain_spec ip daddr . ether saddr ++dst addr4 ++src mac ++start 1 ++count 1 ++src_delta 2000 ++tools sendip nc bash ++proto udp ++ ++race_repeat 0 ++ ++perf_duration 0 ++" ++ + # Set template for all tests, types and rules are filled in depending on test + set_template=' + flush ruleset +@@ -1455,6 +1472,59 @@ test_bug_flush_remove_add() { + nft flush ruleset + } + ++# - add ranged element, check that packets match it ++# - reload the set, check packets still match ++test_bug_reload() { ++ setup veth send_"${proto}" set || return ${KSELFTEST_SKIP} ++ rstart=${start} ++ ++ range_size=1 ++ for i in $(seq "${start}" $((start + count))); do ++ end=$((start + range_size)) ++ ++ # Avoid negative or zero-sized port ranges ++ if [ $((end / 65534)) -gt $((start / 65534)) ]; then ++ start=${end} ++ end=$((end + 1)) ++ fi ++ srcstart=$((start + src_delta)) ++ srcend=$((end + src_delta)) ++ ++ add "$(format)" || return 1 ++ range_size=$((range_size + 1)) ++ start=$((end + range_size)) ++ done ++ ++ # check kernel does allocate pcpu sctrach map ++ # for reload with no elemet add/delete ++ ( echo flush set inet filter test ; ++ nft list set inet filter test ) | nft -f - ++ ++ start=${rstart} ++ range_size=1 ++ ++ for i in $(seq "${start}" $((start + count))); do ++ end=$((start + range_size)) ++ ++ # Avoid negative or zero-sized port ranges ++ if [ $((end / 65534)) -gt $((start / 65534)) ]; then ++ start=${end} ++ end=$((end + 1)) ++ fi ++ srcstart=$((start + src_delta)) ++ srcend=$((end + src_delta)) ++ ++ for j in $(seq ${start} $((range_size / 2 + 1)) ${end}); do ++ send_match "${j}" $((j + src_delta)) || return 1 ++ done ++ ++ range_size=$((range_size + 1)) ++ start=$((end + range_size)) ++ done ++ ++ nft flush ruleset ++} ++ + test_reported_issues() { + eval test_bug_"${subtest}" + } +@@ -1513,4 +1583,4 @@ for name in ${TESTS}; do + done + done + +-[ ${passed} -eq 0 ] && exit ${KSELFTEST_SKIP} ++[ ${passed} -eq 0 ] && exit ${KSELFTEST_SKIP} || exit 0 +diff --git a/tools/testing/selftests/netfilter/nft_fib.sh b/tools/testing/selftests/netfilter/nft_fib.sh +index 6caf6ac8c285f..695a1958723f5 100755 +--- a/tools/testing/selftests/netfilter/nft_fib.sh ++++ b/tools/testing/selftests/netfilter/nft_fib.sh +@@ -174,6 +174,7 @@ test_ping() { + ip netns exec ${nsrouter} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null + ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null + ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null ++ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.rp_filter=0 > /dev/null + + sleep 3 + +diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh +index da1c1e4b6c86b..781fa2d9ea9d5 100755 +--- a/tools/testing/selftests/netfilter/nft_nat.sh ++++ b/tools/testing/selftests/netfilter/nft_nat.sh +@@ -885,6 +885,144 @@ EOF + ip netns exec "$ns0" nft delete table $family nat + } + ++test_stateless_nat_ip() ++{ ++ local lret=0 ++ ++ ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null ++ ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null ++ ++ ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ++ if [ $? -ne 0 ] ; then ++ echo "ERROR: cannot ping $ns1 from $ns2 before loading stateless rules" ++ return 1 ++ fi ++ ++ip netns exec "$ns0" nft -f /dev/stdin <<EOF ++table ip stateless { ++ map xlate_in { ++ typeof meta iifname . ip saddr . ip daddr : ip daddr ++ elements = { ++ "veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2, ++ } ++ } ++ map xlate_out { ++ typeof meta iifname . ip saddr . ip daddr : ip daddr ++ elements = { ++ "veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99 ++ } ++ } ++ ++ chain prerouting { ++ type filter hook prerouting priority -400; policy accept; ++ ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in ++ ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out ++ } ++} ++EOF ++ if [ $? -ne 0 ]; then ++ echo "SKIP: Could not add ip statless rules" ++ return $ksft_skip ++ fi ++ ++ reset_counters ++ ++ ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 ++ if [ $? -ne 0 ] ; then ++ echo "ERROR: cannot ping $ns1 from $ns2 with stateless rules" ++ lret=1 ++ fi ++ ++ # ns1 should have seen packets from .2.2, due to stateless rewrite. ++ expect="packets 1 bytes 84" ++ cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect") ++ if [ $? -ne 0 ]; then ++ bad_counter "$ns1" ns0insl "$expect" "test_stateless 1" ++ lret=1 ++ fi ++ ++ for dir in "in" "out" ; do ++ cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") ++ if [ $? -ne 0 ]; then ++ bad_counter "$ns2" ns1$dir "$expect" "test_stateless 2" ++ lret=1 ++ fi ++ done ++ ++ # ns1 should not have seen packets from ns2, due to masquerade ++ expect="packets 0 bytes 0" ++ for dir in "in" "out" ; do ++ cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") ++ if [ $? -ne 0 ]; then ++ bad_counter "$ns1" ns0$dir "$expect" "test_stateless 3" ++ lret=1 ++ fi ++ ++ cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") ++ if [ $? -ne 0 ]; then ++ bad_counter "$ns0" ns1$dir "$expect" "test_stateless 4" ++ lret=1 ++ fi ++ done ++ ++ reset_counters ++ ++ socat -h > /dev/null 2>&1 ++ if [ $? -ne 0 ];then ++ echo "SKIP: Could not run stateless nat frag test without socat tool" ++ if [ $lret -eq 0 ]; then ++ return $ksft_skip ++ fi ++ ++ ip netns exec "$ns0" nft delete table ip stateless ++ return $lret ++ fi ++ ++ local tmpfile=$(mktemp) ++ dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2>/dev/null ++ ++ local outfile=$(mktemp) ++ ip netns exec "$ns1" timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null & ++ sc_r=$! ++ ++ sleep 1 ++ # re-do with large ping -> ip fragmentation ++ ip netns exec "$ns2" timeout 3 socat - UDP4-SENDTO:"10.0.1.99:4233" < "$tmpfile" > /dev/null ++ if [ $? -ne 0 ] ; then ++ echo "ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2 ++ lret=1 ++ fi ++ ++ wait ++ ++ cmp "$tmpfile" "$outfile" ++ if [ $? -ne 0 ]; then ++ ls -l "$tmpfile" "$outfile" ++ echo "ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2 ++ lret=1 ++ fi ++ ++ rm -f "$tmpfile" "$outfile" ++ ++ # ns1 should have seen packets from 2.2, due to stateless rewrite. ++ expect="packets 3 bytes 4164" ++ cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0insl | grep -q "$expect") ++ if [ $? -ne 0 ]; then ++ bad_counter "$ns1" ns0insl "$expect" "test_stateless 5" ++ lret=1 ++ fi ++ ++ ip netns exec "$ns0" nft delete table ip stateless ++ if [ $? -ne 0 ]; then ++ echo "ERROR: Could not delete table ip stateless" 1>&2 ++ lret=1 ++ fi ++ ++ test $lret -eq 0 && echo "PASS: IP statless for $ns2" ++ ++ return $lret ++} ++ + # ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 + for i in 0 1 2; do + ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF +@@ -951,6 +1089,19 @@ table inet filter { + EOF + done + ++# special case for stateless nat check, counter needs to ++# be done before (input) ip defragmentation ++ip netns exec ns1-$sfx nft -f /dev/stdin <<EOF ++table inet filter { ++ counter ns0insl {} ++ ++ chain pre { ++ type filter hook prerouting priority -400; policy accept; ++ ip saddr 10.0.2.2 counter name "ns0insl" ++ } ++} ++EOF ++ + sleep 3 + # test basic connectivity + for i in 1 2; do +@@ -1005,6 +1156,7 @@ $test_inet_nat && test_redirect inet + $test_inet_nat && test_redirect6 inet + + test_port_shadowing ++test_stateless_nat_ip + + if [ $ret -ne 0 ];then + echo -n "FAIL: " +diff --git a/tools/testing/selftests/openat2/Makefile b/tools/testing/selftests/openat2/Makefile +index 4b93b1417b862..843ba56d8e49e 100644 +--- a/tools/testing/selftests/openat2/Makefile ++++ b/tools/testing/selftests/openat2/Makefile +@@ -5,4 +5,4 @@ TEST_GEN_PROGS := openat2_test resolve_test rename_attack_test + + include ../lib.mk + +-$(TEST_GEN_PROGS): helpers.c ++$(TEST_GEN_PROGS): helpers.c helpers.h +diff --git a/tools/testing/selftests/openat2/helpers.h b/tools/testing/selftests/openat2/helpers.h +index a6ea27344db2d..7056340b9339e 100644 +--- a/tools/testing/selftests/openat2/helpers.h ++++ b/tools/testing/selftests/openat2/helpers.h +@@ -9,6 +9,7 @@ + + #define _GNU_SOURCE + #include <stdint.h> ++#include <stdbool.h> + #include <errno.h> + #include <linux/types.h> + #include "../kselftest.h" +@@ -62,11 +63,12 @@ bool needs_openat2(const struct open_how *how); + (similar to chroot(2)). */ + #endif /* RESOLVE_IN_ROOT */ + +-#define E_func(func, ...) \ +- do { \ +- if (func(__VA_ARGS__) < 0) \ +- ksft_exit_fail_msg("%s:%d %s failed\n", \ +- __FILE__, __LINE__, #func);\ ++#define E_func(func, ...) \ ++ do { \ ++ errno = 0; \ ++ if (func(__VA_ARGS__) < 0) \ ++ ksft_exit_fail_msg("%s:%d %s failed - errno:%d\n", \ ++ __FILE__, __LINE__, #func, errno); \ + } while (0) + + #define E_asprintf(...) E_func(asprintf, __VA_ARGS__) +diff --git a/tools/testing/selftests/openat2/openat2_test.c b/tools/testing/selftests/openat2/openat2_test.c +index 1bddbe934204c..7fb902099de45 100644 +--- a/tools/testing/selftests/openat2/openat2_test.c ++++ b/tools/testing/selftests/openat2/openat2_test.c +@@ -259,6 +259,16 @@ void test_openat2_flags(void) + unlink(path); + + fd = sys_openat2(AT_FDCWD, path, &test->how); ++ if (fd < 0 && fd == -EOPNOTSUPP) { ++ /* ++ * Skip the testcase if it failed because not supported ++ * by FS. (e.g. a valid O_TMPFILE combination on NFS) ++ */ ++ ksft_test_result_skip("openat2 with %s fails with %d (%s)\n", ++ test->name, fd, strerror(-fd)); ++ goto next; ++ } ++ + if (test->err >= 0) + failed = (fd < 0); + else +@@ -303,7 +313,7 @@ skip: + else + resultfn("openat2 with %s fails with %d (%s)\n", + test->name, test->err, strerror(-test->err)); +- ++next: + free(fdpath); + fflush(stdout); + } +diff --git a/tools/testing/selftests/pidfd/pidfd.h b/tools/testing/selftests/pidfd/pidfd.h +index 01f8d3c0cf2cb..6922d6417e1cf 100644 +--- a/tools/testing/selftests/pidfd/pidfd.h ++++ b/tools/testing/selftests/pidfd/pidfd.h +@@ -68,7 +68,7 @@ + #define PIDFD_SKIP 3 + #define PIDFD_XFAIL 4 + +-int wait_for_pid(pid_t pid) ++static inline int wait_for_pid(pid_t pid) + { + int status, ret; + +@@ -78,13 +78,20 @@ again: + if (errno == EINTR) + goto again; + ++ ksft_print_msg("waitpid returned -1, errno=%d\n", errno); + return -1; + } + +- if (!WIFEXITED(status)) ++ if (!WIFEXITED(status)) { ++ ksft_print_msg( ++ "waitpid !WIFEXITED, WIFSIGNALED=%d, WTERMSIG=%d\n", ++ WIFSIGNALED(status), WTERMSIG(status)); + return -1; ++ } + +- return WEXITSTATUS(status); ++ ret = WEXITSTATUS(status); ++ ksft_print_msg("waitpid WEXITSTATUS=%d\n", ret); ++ return ret; + } + + static inline int sys_pidfd_open(pid_t pid, unsigned int flags) +diff --git a/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c b/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c +index 22558524f71c3..3fd8e903118f5 100644 +--- a/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c ++++ b/tools/testing/selftests/pidfd/pidfd_fdinfo_test.c +@@ -12,6 +12,7 @@ + #include <string.h> + #include <syscall.h> + #include <sys/wait.h> ++#include <sys/mman.h> + + #include "pidfd.h" + #include "../kselftest.h" +@@ -80,7 +81,10 @@ static inline int error_check(struct error *err, const char *test_name) + return err->code; + } + ++#define CHILD_STACK_SIZE 8192 ++ + struct child { ++ char *stack; + pid_t pid; + int fd; + }; +@@ -89,17 +93,22 @@ static struct child clone_newns(int (*fn)(void *), void *args, + struct error *err) + { + static int flags = CLONE_PIDFD | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD; +- size_t stack_size = 1024; +- char *stack[1024] = { 0 }; + struct child ret; + + if (!(flags & CLONE_NEWUSER) && geteuid() != 0) + flags |= CLONE_NEWUSER; + ++ ret.stack = mmap(NULL, CHILD_STACK_SIZE, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); ++ if (ret.stack == MAP_FAILED) { ++ error_set(err, -1, "mmap of stack failed (errno %d)", errno); ++ return ret; ++ } ++ + #ifdef __ia64__ +- ret.pid = __clone2(fn, stack, stack_size, flags, args, &ret.fd); ++ ret.pid = __clone2(fn, ret.stack, CHILD_STACK_SIZE, flags, args, &ret.fd); + #else +- ret.pid = clone(fn, stack + stack_size, flags, args, &ret.fd); ++ ret.pid = clone(fn, ret.stack + CHILD_STACK_SIZE, flags, args, &ret.fd); + #endif + + if (ret.pid < 0) { +@@ -129,6 +138,11 @@ static inline int child_join(struct child *child, struct error *err) + else if (r > 0) + error_set(err, r, "child %d reported: %d", child->pid, r); + ++ if (munmap(child->stack, CHILD_STACK_SIZE)) { ++ error_set(err, -1, "munmap of child stack failed (errno %d)", errno); ++ r = -1; ++ } ++ + return r; + } + +diff --git a/tools/testing/selftests/pidfd/pidfd_test.c b/tools/testing/selftests/pidfd/pidfd_test.c +index 529eb700ac26a..9a2d64901d591 100644 +--- a/tools/testing/selftests/pidfd/pidfd_test.c ++++ b/tools/testing/selftests/pidfd/pidfd_test.c +@@ -441,7 +441,6 @@ static void test_pidfd_poll_exec(int use_waitpid) + { + int pid, pidfd = 0; + int status, ret; +- pthread_t t1; + time_t prog_start = time(NULL); + const char *test_name = "pidfd_poll check for premature notification on child thread exec"; + +@@ -500,13 +499,14 @@ static int child_poll_leader_exit_test(void *args) + */ + *child_exit_secs = time(NULL); + syscall(SYS_exit, 0); ++ /* Never reached, but appeases compiler thinking we should return. */ ++ exit(0); + } + + static void test_pidfd_poll_leader_exit(int use_waitpid) + { + int pid, pidfd = 0; +- int status, ret; +- time_t prog_start = time(NULL); ++ int status, ret = 0; + const char *test_name = "pidfd_poll check for premature notification on non-empty" + "group leader exit"; + +diff --git a/tools/testing/selftests/pidfd/pidfd_wait.c b/tools/testing/selftests/pidfd/pidfd_wait.c +index be2943f072f60..17999e082aa71 100644 +--- a/tools/testing/selftests/pidfd/pidfd_wait.c ++++ b/tools/testing/selftests/pidfd/pidfd_wait.c +@@ -39,7 +39,7 @@ static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options, + + TEST(wait_simple) + { +- int pidfd = -1, status = 0; ++ int pidfd = -1; + pid_t parent_tid = -1; + struct clone_args args = { + .parent_tid = ptr_to_u64(&parent_tid), +@@ -47,7 +47,6 @@ TEST(wait_simple) + .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, + .exit_signal = SIGCHLD, + }; +- int ret; + pid_t pid; + siginfo_t info = { + .si_signo = 0, +@@ -88,7 +87,7 @@ TEST(wait_simple) + + TEST(wait_states) + { +- int pidfd = -1, status = 0; ++ int pidfd = -1; + pid_t parent_tid = -1; + struct clone_args args = { + .parent_tid = ptr_to_u64(&parent_tid), +diff --git a/tools/testing/selftests/powerpc/security/spectre_v2.c b/tools/testing/selftests/powerpc/security/spectre_v2.c +index adc2b7294e5fd..83647b8277e7d 100644 +--- a/tools/testing/selftests/powerpc/security/spectre_v2.c ++++ b/tools/testing/selftests/powerpc/security/spectre_v2.c +@@ -193,7 +193,7 @@ int spectre_v2_test(void) + * We are not vulnerable and reporting otherwise, so + * missing such a mismatch is safe. + */ +- if (state == VULNERABLE) ++ if (miss_percent > 95) + return 4; + + return 1; +diff --git a/tools/testing/selftests/powerpc/signal/.gitignore b/tools/testing/selftests/powerpc/signal/.gitignore +index ce3375cd8e73e..8f6c816099a48 100644 +--- a/tools/testing/selftests/powerpc/signal/.gitignore ++++ b/tools/testing/selftests/powerpc/signal/.gitignore +@@ -4,3 +4,4 @@ signal_tm + sigfuz + sigreturn_vdso + sig_sc_double_restart ++sigreturn_kernel +diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile +index d6ae54663aed7..84e201572466d 100644 +--- a/tools/testing/selftests/powerpc/signal/Makefile ++++ b/tools/testing/selftests/powerpc/signal/Makefile +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + TEST_GEN_PROGS := signal signal_tm sigfuz sigreturn_vdso sig_sc_double_restart ++TEST_GEN_PROGS += sigreturn_kernel + + CFLAGS += -maltivec + $(OUTPUT)/signal_tm: CFLAGS += -mhtm +diff --git a/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c b/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c +new file mode 100644 +index 0000000000000..0a1b6e591eeed +--- /dev/null ++++ b/tools/testing/selftests/powerpc/signal/sigreturn_kernel.c +@@ -0,0 +1,132 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Test that we can't sigreturn to kernel addresses, or to kernel mode. ++ */ ++ ++#define _GNU_SOURCE ++ ++#include <stdio.h> ++#include <signal.h> ++#include <stdlib.h> ++#include <sys/types.h> ++#include <sys/wait.h> ++#include <unistd.h> ++ ++#include "utils.h" ++ ++#define MSR_PR (1ul << 14) ++ ++static volatile unsigned long long sigreturn_addr; ++static volatile unsigned long long sigreturn_msr_mask; ++ ++static void sigusr1_handler(int signo, siginfo_t *si, void *uc_ptr) ++{ ++ ucontext_t *uc = (ucontext_t *)uc_ptr; ++ ++ if (sigreturn_addr) ++ UCONTEXT_NIA(uc) = sigreturn_addr; ++ ++ if (sigreturn_msr_mask) ++ UCONTEXT_MSR(uc) &= sigreturn_msr_mask; ++} ++ ++static pid_t fork_child(void) ++{ ++ pid_t pid; ++ ++ pid = fork(); ++ if (pid == 0) { ++ raise(SIGUSR1); ++ exit(0); ++ } ++ ++ return pid; ++} ++ ++static int expect_segv(pid_t pid) ++{ ++ int child_ret; ++ ++ waitpid(pid, &child_ret, 0); ++ FAIL_IF(WIFEXITED(child_ret)); ++ FAIL_IF(!WIFSIGNALED(child_ret)); ++ FAIL_IF(WTERMSIG(child_ret) != 11); ++ ++ return 0; ++} ++ ++int test_sigreturn_kernel(void) ++{ ++ struct sigaction act; ++ int child_ret, i; ++ pid_t pid; ++ ++ act.sa_sigaction = sigusr1_handler; ++ act.sa_flags = SA_SIGINFO; ++ sigemptyset(&act.sa_mask); ++ ++ FAIL_IF(sigaction(SIGUSR1, &act, NULL)); ++ ++ for (i = 0; i < 2; i++) { ++ // Return to kernel ++ sigreturn_addr = 0xcull << 60; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return to kernel virtual ++ sigreturn_addr = 0xc008ull << 48; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return out of range ++ sigreturn_addr = 0xc010ull << 48; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return to no-man's land, just below PAGE_OFFSET ++ sigreturn_addr = (0xcull << 60) - (64 * 1024); ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return to no-man's land, above TASK_SIZE_4PB ++ sigreturn_addr = 0x1ull << 52; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return to 0xd space ++ sigreturn_addr = 0xdull << 60; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return to 0xe space ++ sigreturn_addr = 0xeull << 60; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Return to 0xf space ++ sigreturn_addr = 0xfull << 60; ++ pid = fork_child(); ++ expect_segv(pid); ++ ++ // Attempt to set PR=0 for 2nd loop (should be blocked by kernel) ++ sigreturn_msr_mask = ~MSR_PR; ++ } ++ ++ printf("All children killed as expected\n"); ++ ++ // Don't change address, just MSR, should return to user as normal ++ sigreturn_addr = 0; ++ sigreturn_msr_mask = ~MSR_PR; ++ pid = fork_child(); ++ waitpid(pid, &child_ret, 0); ++ FAIL_IF(!WIFEXITED(child_ret)); ++ FAIL_IF(WIFSIGNALED(child_ret)); ++ FAIL_IF(WEXITSTATUS(child_ret) != 0); ++ ++ return 0; ++} ++ ++int main(void) ++{ ++ return test_harness(test_sigreturn_kernel, "sigreturn_kernel"); ++} +diff --git a/tools/testing/selftests/rtc/settings b/tools/testing/selftests/rtc/settings +index ba4d85f74cd6b..a953c96aa16e1 100644 +--- a/tools/testing/selftests/rtc/settings ++++ b/tools/testing/selftests/rtc/settings +@@ -1 +1 @@ +-timeout=90 ++timeout=180 +diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c +index 7db9cf822dc75..8109b17dc764c 100644 +--- a/tools/testing/selftests/sched/cs_prctl_test.c ++++ b/tools/testing/selftests/sched/cs_prctl_test.c +@@ -62,6 +62,17 @@ enum pid_type {PIDTYPE_PID = 0, PIDTYPE_TGID, PIDTYPE_PGID}; + + const int THREAD_CLONE_FLAGS = CLONE_THREAD | CLONE_SIGHAND | CLONE_FS | CLONE_VM | CLONE_FILES; + ++struct child_args { ++ int num_threads; ++ int pfd[2]; ++ int cpid; ++ int thr_tids[MAX_THREADS]; ++}; ++ ++static struct child_args procs[MAX_PROCESSES]; ++static int num_processes = 2; ++static int need_cleanup = 0; ++ + static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, + unsigned long arg5) + { +@@ -78,8 +89,14 @@ static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned l + #define handle_error(msg) __handle_error(__FILE__, __LINE__, msg) + static void __handle_error(char *fn, int ln, char *msg) + { ++ int pidx; + printf("(%s:%d) - ", fn, ln); + perror(msg); ++ if (need_cleanup) { ++ for (pidx = 0; pidx < num_processes; ++pidx) ++ kill(procs[pidx].cpid, 15); ++ need_cleanup = 0; ++ } + exit(EXIT_FAILURE); + } + +@@ -106,13 +123,6 @@ static unsigned long get_cs_cookie(int pid) + return cookie; + } + +-struct child_args { +- int num_threads; +- int pfd[2]; +- int cpid; +- int thr_tids[MAX_THREADS]; +-}; +- + static int child_func_thread(void __attribute__((unused))*arg) + { + while (1) +@@ -212,10 +222,7 @@ void _validate(int line, int val, char *msg) + + int main(int argc, char *argv[]) + { +- struct child_args procs[MAX_PROCESSES]; +- + int keypress = 0; +- int num_processes = 2; + int num_threads = 3; + int delay = 0; + int res = 0; +@@ -262,6 +269,7 @@ int main(int argc, char *argv[]) + + printf("\n## Create a thread/process/process group hiearchy\n"); + create_processes(num_processes, num_threads, procs); ++ need_cleanup = 1; + disp_processes(num_processes, procs); + validate(get_cs_cookie(0) == 0); + +diff --git a/tools/testing/selftests/seccomp/Makefile b/tools/testing/selftests/seccomp/Makefile +index 0ebfe8b0e147f..585f7a0c10cbe 100644 +--- a/tools/testing/selftests/seccomp/Makefile ++++ b/tools/testing/selftests/seccomp/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-CFLAGS += -Wl,-no-as-needed -Wall ++CFLAGS += -Wl,-no-as-needed -Wall -isystem ../../../../usr/include/ + LDFLAGS += -lpthread + + TEST_GEN_PROGS := seccomp_bpf seccomp_benchmark +diff --git a/tools/testing/selftests/vDSO/vdso_test_abi.c b/tools/testing/selftests/vDSO/vdso_test_abi.c +index 3d603f1394af4..883ca85424bc5 100644 +--- a/tools/testing/selftests/vDSO/vdso_test_abi.c ++++ b/tools/testing/selftests/vDSO/vdso_test_abi.c +@@ -33,110 +33,114 @@ typedef long (*vdso_clock_gettime_t)(clockid_t clk_id, struct timespec *ts); + typedef long (*vdso_clock_getres_t)(clockid_t clk_id, struct timespec *ts); + typedef time_t (*vdso_time_t)(time_t *t); + +-static int vdso_test_gettimeofday(void) ++#define VDSO_TEST_PASS_MSG() "\n%s(): PASS\n", __func__ ++#define VDSO_TEST_FAIL_MSG(x) "\n%s(): %s FAIL\n", __func__, x ++#define VDSO_TEST_SKIP_MSG(x) "\n%s(): SKIP: Could not find %s\n", __func__, x ++ ++static void vdso_test_gettimeofday(void) + { + /* Find gettimeofday. */ + vdso_gettimeofday_t vdso_gettimeofday = + (vdso_gettimeofday_t)vdso_sym(version, name[0]); + + if (!vdso_gettimeofday) { +- printf("Could not find %s\n", name[0]); +- return KSFT_SKIP; ++ ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[0])); ++ return; + } + + struct timeval tv; + long ret = vdso_gettimeofday(&tv, 0); + + if (ret == 0) { +- printf("The time is %lld.%06lld\n", +- (long long)tv.tv_sec, (long long)tv.tv_usec); ++ ksft_print_msg("The time is %lld.%06lld\n", ++ (long long)tv.tv_sec, (long long)tv.tv_usec); ++ ksft_test_result_pass(VDSO_TEST_PASS_MSG()); + } else { +- printf("%s failed\n", name[0]); +- return KSFT_FAIL; ++ ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[0])); + } +- +- return KSFT_PASS; + } + +-static int vdso_test_clock_gettime(clockid_t clk_id) ++static void vdso_test_clock_gettime(clockid_t clk_id) + { + /* Find clock_gettime. */ + vdso_clock_gettime_t vdso_clock_gettime = + (vdso_clock_gettime_t)vdso_sym(version, name[1]); + + if (!vdso_clock_gettime) { +- printf("Could not find %s\n", name[1]); +- return KSFT_SKIP; ++ ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[1])); ++ return; + } + + struct timespec ts; + long ret = vdso_clock_gettime(clk_id, &ts); + + if (ret == 0) { +- printf("The time is %lld.%06lld\n", +- (long long)ts.tv_sec, (long long)ts.tv_nsec); ++ ksft_print_msg("The time is %lld.%06lld\n", ++ (long long)ts.tv_sec, (long long)ts.tv_nsec); ++ ksft_test_result_pass(VDSO_TEST_PASS_MSG()); + } else { +- printf("%s failed\n", name[1]); +- return KSFT_FAIL; ++ ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[1])); + } +- +- return KSFT_PASS; + } + +-static int vdso_test_time(void) ++static void vdso_test_time(void) + { + /* Find time. */ + vdso_time_t vdso_time = + (vdso_time_t)vdso_sym(version, name[2]); + + if (!vdso_time) { +- printf("Could not find %s\n", name[2]); +- return KSFT_SKIP; ++ ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[2])); ++ return; + } + + long ret = vdso_time(NULL); + + if (ret > 0) { +- printf("The time in hours since January 1, 1970 is %lld\n", ++ ksft_print_msg("The time in hours since January 1, 1970 is %lld\n", + (long long)(ret / 3600)); ++ ksft_test_result_pass(VDSO_TEST_PASS_MSG()); + } else { +- printf("%s failed\n", name[2]); +- return KSFT_FAIL; ++ ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[2])); + } +- +- return KSFT_PASS; + } + +-static int vdso_test_clock_getres(clockid_t clk_id) ++static void vdso_test_clock_getres(clockid_t clk_id) + { ++ int clock_getres_fail = 0; ++ + /* Find clock_getres. */ + vdso_clock_getres_t vdso_clock_getres = + (vdso_clock_getres_t)vdso_sym(version, name[3]); + + if (!vdso_clock_getres) { +- printf("Could not find %s\n", name[3]); +- return KSFT_SKIP; ++ ksft_test_result_skip(VDSO_TEST_SKIP_MSG(name[3])); ++ return; + } + + struct timespec ts, sys_ts; + long ret = vdso_clock_getres(clk_id, &ts); + + if (ret == 0) { +- printf("The resolution is %lld %lld\n", +- (long long)ts.tv_sec, (long long)ts.tv_nsec); ++ ksft_print_msg("The vdso resolution is %lld %lld\n", ++ (long long)ts.tv_sec, (long long)ts.tv_nsec); + } else { +- printf("%s failed\n", name[3]); +- return KSFT_FAIL; ++ clock_getres_fail++; + } + + ret = syscall(SYS_clock_getres, clk_id, &sys_ts); + +- if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec)) { +- printf("%s failed\n", name[3]); +- return KSFT_FAIL; +- } ++ ksft_print_msg("The syscall resolution is %lld %lld\n", ++ (long long)sys_ts.tv_sec, (long long)sys_ts.tv_nsec); + +- return KSFT_PASS; ++ if ((sys_ts.tv_sec != ts.tv_sec) || (sys_ts.tv_nsec != ts.tv_nsec)) ++ clock_getres_fail++; ++ ++ if (clock_getres_fail > 0) { ++ ksft_test_result_fail(VDSO_TEST_FAIL_MSG(name[3])); ++ } else { ++ ksft_test_result_pass(VDSO_TEST_PASS_MSG()); ++ } + } + + const char *vdso_clock_name[12] = { +@@ -158,36 +162,23 @@ const char *vdso_clock_name[12] = { + * This function calls vdso_test_clock_gettime and vdso_test_clock_getres + * with different values for clock_id. + */ +-static inline int vdso_test_clock(clockid_t clock_id) ++static inline void vdso_test_clock(clockid_t clock_id) + { +- int ret0, ret1; +- +- ret0 = vdso_test_clock_gettime(clock_id); +- /* A skipped test is considered passed */ +- if (ret0 == KSFT_SKIP) +- ret0 = KSFT_PASS; +- +- ret1 = vdso_test_clock_getres(clock_id); +- /* A skipped test is considered passed */ +- if (ret1 == KSFT_SKIP) +- ret1 = KSFT_PASS; ++ ksft_print_msg("\nclock_id: %s\n", vdso_clock_name[clock_id]); + +- ret0 += ret1; ++ vdso_test_clock_gettime(clock_id); + +- printf("clock_id: %s", vdso_clock_name[clock_id]); +- +- if (ret0 > 0) +- printf(" [FAIL]\n"); +- else +- printf(" [PASS]\n"); +- +- return ret0; ++ vdso_test_clock_getres(clock_id); + } + ++#define VDSO_TEST_PLAN 16 ++ + int main(int argc, char **argv) + { + unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); +- int ret; ++ ++ ksft_print_header(); ++ ksft_set_plan(VDSO_TEST_PLAN); + + if (!sysinfo_ehdr) { + printf("AT_SYSINFO_EHDR is not present!\n"); +@@ -201,44 +192,42 @@ int main(int argc, char **argv) + + vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR)); + +- ret = vdso_test_gettimeofday(); ++ vdso_test_gettimeofday(); + + #if _POSIX_TIMERS > 0 + + #ifdef CLOCK_REALTIME +- ret += vdso_test_clock(CLOCK_REALTIME); ++ vdso_test_clock(CLOCK_REALTIME); + #endif + + #ifdef CLOCK_BOOTTIME +- ret += vdso_test_clock(CLOCK_BOOTTIME); ++ vdso_test_clock(CLOCK_BOOTTIME); + #endif + + #ifdef CLOCK_TAI +- ret += vdso_test_clock(CLOCK_TAI); ++ vdso_test_clock(CLOCK_TAI); + #endif + + #ifdef CLOCK_REALTIME_COARSE +- ret += vdso_test_clock(CLOCK_REALTIME_COARSE); ++ vdso_test_clock(CLOCK_REALTIME_COARSE); + #endif + + #ifdef CLOCK_MONOTONIC +- ret += vdso_test_clock(CLOCK_MONOTONIC); ++ vdso_test_clock(CLOCK_MONOTONIC); + #endif + + #ifdef CLOCK_MONOTONIC_RAW +- ret += vdso_test_clock(CLOCK_MONOTONIC_RAW); ++ vdso_test_clock(CLOCK_MONOTONIC_RAW); + #endif + + #ifdef CLOCK_MONOTONIC_COARSE +- ret += vdso_test_clock(CLOCK_MONOTONIC_COARSE); ++ vdso_test_clock(CLOCK_MONOTONIC_COARSE); + #endif + + #endif + +- ret += vdso_test_time(); +- +- if (ret > 0) +- return KSFT_FAIL; ++ vdso_test_time(); + +- return KSFT_PASS; ++ ksft_print_cnts(); ++ return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL; + } +diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh +index fe8fcfb334e06..a5cb4b09a46c4 100644 +--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh ++++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh +@@ -24,19 +24,23 @@ if [[ "$1" == "-cgroup-v2" ]]; then + reservation_usage_file=rsvd.current + fi + +-cgroup_path=/dev/cgroup/memory +-if [[ ! -e $cgroup_path ]]; then +- mkdir -p $cgroup_path +- if [[ $cgroup2 ]]; then ++if [[ $cgroup2 ]]; then ++ cgroup_path=$(mount -t cgroup2 | head -1 | awk -e '{print $3}') ++ if [[ -z "$cgroup_path" ]]; then ++ cgroup_path=/dev/cgroup/memory + mount -t cgroup2 none $cgroup_path +- else ++ do_umount=1 ++ fi ++ echo "+hugetlb" >$cgroup_path/cgroup.subtree_control ++else ++ cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}') ++ if [[ -z "$cgroup_path" ]]; then ++ cgroup_path=/dev/cgroup/memory + mount -t cgroup memory,hugetlb $cgroup_path ++ do_umount=1 + fi + fi +- +-if [[ $cgroup2 ]]; then +- echo "+hugetlb" >/dev/cgroup/memory/cgroup.subtree_control +-fi ++export cgroup_path + + function cleanup() { + if [[ $cgroup2 ]]; then +@@ -108,7 +112,7 @@ function setup_cgroup() { + + function wait_for_hugetlb_memory_to_get_depleted() { + local cgroup="$1" +- local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" ++ local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" + # Wait for hugetlbfs memory to get depleted. + while [ $(cat $path) != 0 ]; do + echo Waiting for hugetlb memory to get depleted. +@@ -121,7 +125,7 @@ function wait_for_hugetlb_memory_to_get_reserved() { + local cgroup="$1" + local size="$2" + +- local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" ++ local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" + # Wait for hugetlbfs memory to get written. + while [ $(cat $path) != $size ]; do + echo Waiting for hugetlb memory reservation to reach size $size. +@@ -134,7 +138,7 @@ function wait_for_hugetlb_memory_to_get_written() { + local cgroup="$1" + local size="$2" + +- local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$fault_usage_file" ++ local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file" + # Wait for hugetlbfs memory to get written. + while [ $(cat $path) != $size ]; do + echo Waiting for hugetlb memory to reach size $size. +@@ -574,5 +578,7 @@ for populate in "" "-o"; do + done # populate + done # method + +-umount $cgroup_path +-rmdir $cgroup_path ++if [[ $do_umount ]]; then ++ umount $cgroup_path ++ rmdir $cgroup_path ++fi +diff --git a/tools/testing/selftests/vm/hmm-tests.c b/tools/testing/selftests/vm/hmm-tests.c +index 864f126ffd78f..203323967b507 100644 +--- a/tools/testing/selftests/vm/hmm-tests.c ++++ b/tools/testing/selftests/vm/hmm-tests.c +@@ -1248,6 +1248,48 @@ TEST_F(hmm, anon_teardown) + } + } + ++/* ++ * Test memory snapshot without faulting in pages accessed by the device. ++ */ ++TEST_F(hmm, mixedmap) ++{ ++ struct hmm_buffer *buffer; ++ unsigned long npages; ++ unsigned long size; ++ unsigned char *m; ++ int ret; ++ ++ npages = 1; ++ size = npages << self->page_shift; ++ ++ buffer = malloc(sizeof(*buffer)); ++ ASSERT_NE(buffer, NULL); ++ ++ buffer->fd = -1; ++ buffer->size = size; ++ buffer->mirror = malloc(npages); ++ ASSERT_NE(buffer->mirror, NULL); ++ ++ ++ /* Reserve a range of addresses. */ ++ buffer->ptr = mmap(NULL, size, ++ PROT_READ | PROT_WRITE, ++ MAP_PRIVATE, ++ self->fd, 0); ++ ASSERT_NE(buffer->ptr, MAP_FAILED); ++ ++ /* Simulate a device snapshotting CPU pagetables. */ ++ ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages); ++ ASSERT_EQ(ret, 0); ++ ASSERT_EQ(buffer->cpages, npages); ++ ++ /* Check what the device saw. */ ++ m = buffer->mirror; ++ ASSERT_EQ(m[0], HMM_DMIRROR_PROT_READ); ++ ++ hmm_buffer_free(buffer); ++} ++ + /* + * Test memory snapshot without faulting in pages accessed by the device. + */ +diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh +index 4a9a3afe9fd4d..bf2d2a684edfd 100644 +--- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh ++++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh +@@ -18,19 +18,24 @@ if [[ "$1" == "-cgroup-v2" ]]; then + usage_file=current + fi + +-CGROUP_ROOT='/dev/cgroup/memory' +-MNT='/mnt/huge/' + +-if [[ ! -e $CGROUP_ROOT ]]; then +- mkdir -p $CGROUP_ROOT +- if [[ $cgroup2 ]]; then ++if [[ $cgroup2 ]]; then ++ CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk -e '{print $3}') ++ if [[ -z "$CGROUP_ROOT" ]]; then ++ CGROUP_ROOT=/dev/cgroup/memory + mount -t cgroup2 none $CGROUP_ROOT +- sleep 1 +- echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control +- else ++ do_umount=1 ++ fi ++ echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control ++else ++ CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}') ++ if [[ -z "$CGROUP_ROOT" ]]; then ++ CGROUP_ROOT=/dev/cgroup/memory + mount -t cgroup memory,hugetlb $CGROUP_ROOT ++ do_umount=1 + fi + fi ++MNT='/mnt/huge/' + + function get_machine_hugepage_size() { + hpz=$(grep -i hugepagesize /proc/meminfo) +diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c +index 60aa1a4fc69b6..81690f1737c80 100644 +--- a/tools/testing/selftests/vm/userfaultfd.c ++++ b/tools/testing/selftests/vm/userfaultfd.c +@@ -86,7 +86,7 @@ static bool test_uffdio_minor = false; + + static bool map_shared; + static int shm_fd; +-static int huge_fd; ++static int huge_fd = -1; /* only used for hugetlb_shared test */ + static char *huge_fd_off0; + static unsigned long long *count_verify; + static int uffd = -1; +@@ -222,6 +222,9 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset) + + static void hugetlb_release_pages(char *rel_area) + { ++ if (huge_fd == -1) ++ return; ++ + if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + rel_area == huge_fd_off0 ? 0 : nr_pages * page_size, + nr_pages * page_size)) +@@ -234,16 +237,17 @@ static void hugetlb_allocate_area(void **alloc_area) + char **alloc_area_alias; + + *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, +- (map_shared ? MAP_SHARED : MAP_PRIVATE) | +- MAP_HUGETLB, +- huge_fd, *alloc_area == area_src ? 0 : +- nr_pages * page_size); ++ map_shared ? MAP_SHARED : ++ MAP_PRIVATE | MAP_HUGETLB | ++ (*alloc_area == area_src ? 0 : MAP_NORESERVE), ++ huge_fd, ++ *alloc_area == area_src ? 0 : nr_pages * page_size); + if (*alloc_area == MAP_FAILED) + err("mmap of hugetlbfs file failed"); + + if (map_shared) { + area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE, +- MAP_SHARED | MAP_HUGETLB, ++ MAP_SHARED, + huge_fd, *alloc_area == area_src ? 0 : + nr_pages * page_size); + if (area_alias == MAP_FAILED) +diff --git a/tools/testing/selftests/vm/write_hugetlb_memory.sh b/tools/testing/selftests/vm/write_hugetlb_memory.sh +index d3d0d108924d4..70a02301f4c27 100644 +--- a/tools/testing/selftests/vm/write_hugetlb_memory.sh ++++ b/tools/testing/selftests/vm/write_hugetlb_memory.sh +@@ -14,7 +14,7 @@ want_sleep=$8 + reserve=$9 + + echo "Putting task in cgroup '$cgroup'" +-echo $$ > /dev/cgroup/memory/"$cgroup"/cgroup.procs ++echo $$ > ${cgroup_path:-/dev/cgroup/memory}/"$cgroup"/cgroup.procs + + echo "Method is $method" + +diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh +index ebc4ee0fe179f..8a9461aa0878a 100755 +--- a/tools/testing/selftests/wireguard/netns.sh ++++ b/tools/testing/selftests/wireguard/netns.sh +@@ -276,7 +276,11 @@ n0 ping -W 1 -c 1 192.168.241.2 + n1 wg set wg0 peer "$pub2" endpoint 192.168.241.2:7 + ip2 link del wg0 + ip2 link del wg1 +-! n0 ping -W 1 -c 10 -f 192.168.241.2 || false # Should not crash kernel ++read _ _ tx_bytes_before < <(n0 wg show wg1 transfer) ++! n0 ping -W 1 -c 10 -f 192.168.241.2 || false ++sleep 1 ++read _ _ tx_bytes_after < <(n0 wg show wg1 transfer) ++(( tx_bytes_after - tx_bytes_before < 70000 )) + + ip0 link del wg1 + ip1 link del wg0 +@@ -609,6 +613,28 @@ ip0 link set wg0 up + kill $ncat_pid + ip0 link del wg0 + ++# Ensure that dst_cache references don't outlive netns lifetime ++ip1 link add dev wg0 type wireguard ++ip2 link add dev wg0 type wireguard ++configure_peers ++ip1 link add veth1 type veth peer name veth2 ++ip1 link set veth2 netns $netns2 ++ip1 addr add fd00:aa::1/64 dev veth1 ++ip2 addr add fd00:aa::2/64 dev veth2 ++ip1 link set veth1 up ++ip2 link set veth2 up ++waitiface $netns1 veth1 ++waitiface $netns2 veth2 ++ip1 -6 route add default dev veth1 via fd00:aa::2 ++ip2 -6 route add default dev veth2 via fd00:aa::1 ++n1 wg set wg0 peer "$pub2" endpoint [fd00:aa::2]:2 ++n2 wg set wg0 peer "$pub1" endpoint [fd00:aa::1]:1 ++n1 ping6 -c 1 fd00::2 ++pp ip netns delete $netns1 ++pp ip netns delete $netns2 ++pp ip netns add $netns1 ++pp ip netns add $netns2 ++ + # Ensure there aren't circular reference loops + ip1 link add wg1 type wireguard + ip2 link add wg2 type wireguard +@@ -627,7 +653,7 @@ while read -t 0.1 -r line 2>/dev/null || [[ $? -ne 142 ]]; do + done < /dev/kmsg + alldeleted=1 + for object in "${!objects[@]}"; do +- if [[ ${objects["$object"]} != *createddestroyed ]]; then ++ if [[ ${objects["$object"]} != *createddestroyed && ${objects["$object"]} != *createdcreateddestroyeddestroyed ]]; then + echo "Error: $object: merely ${objects["$object"]}" >&3 + alldeleted=0 + fi +diff --git a/tools/testing/selftests/wireguard/qemu/debug.config b/tools/testing/selftests/wireguard/qemu/debug.config +index fe07d97df9fa8..2b321b8a96cf3 100644 +--- a/tools/testing/selftests/wireguard/qemu/debug.config ++++ b/tools/testing/selftests/wireguard/qemu/debug.config +@@ -47,7 +47,7 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y + CONFIG_TRACE_IRQFLAGS=y + CONFIG_DEBUG_BUGVERBOSE=y + CONFIG_DEBUG_LIST=y +-CONFIG_DEBUG_PI_LIST=y ++CONFIG_DEBUG_PLIST=y + CONFIG_PROVE_RCU=y + CONFIG_SPARSE_RCU_POINTER=y + CONFIG_RCU_CPU_STALL_TIMEOUT=21 +diff --git a/tools/testing/selftests/wireguard/qemu/kernel.config b/tools/testing/selftests/wireguard/qemu/kernel.config +index 74db83a0aedd8..a9b5a520a1d22 100644 +--- a/tools/testing/selftests/wireguard/qemu/kernel.config ++++ b/tools/testing/selftests/wireguard/qemu/kernel.config +@@ -66,6 +66,7 @@ CONFIG_PROC_SYSCTL=y + CONFIG_SYSFS=y + CONFIG_TMPFS=y + CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 ++CONFIG_LOG_BUF_SHIFT=18 + CONFIG_PRINTK_TIME=y + CONFIG_BLK_DEV_INITRD=y + CONFIG_LEGACY_VSYSCALL_NONE=y +diff --git a/tools/testing/selftests/x86/iopl.c b/tools/testing/selftests/x86/iopl.c +index bab2f6e06b63d..7e3e09c1abac6 100644 +--- a/tools/testing/selftests/x86/iopl.c ++++ b/tools/testing/selftests/x86/iopl.c +@@ -85,48 +85,88 @@ static void expect_gp_outb(unsigned short port) + printf("[OK]\toutb to 0x%02hx failed\n", port); + } + +-static bool try_cli(void) ++#define RET_FAULTED 0 ++#define RET_FAIL 1 ++#define RET_EMUL 2 ++ ++static int try_cli(void) + { ++ unsigned long flags; ++ + sethandler(SIGSEGV, sigsegv, SA_RESETHAND); + if (sigsetjmp(jmpbuf, 1) != 0) { +- return false; ++ return RET_FAULTED; + } else { +- asm volatile ("cli"); +- return true; ++ asm volatile("cli; pushf; pop %[flags]" ++ : [flags] "=rm" (flags)); ++ ++ /* X86_FLAGS_IF */ ++ if (!(flags & (1 << 9))) ++ return RET_FAIL; ++ else ++ return RET_EMUL; + } + clearhandler(SIGSEGV); + } + +-static bool try_sti(void) ++static int try_sti(bool irqs_off) + { ++ unsigned long flags; ++ + sethandler(SIGSEGV, sigsegv, SA_RESETHAND); + if (sigsetjmp(jmpbuf, 1) != 0) { +- return false; ++ return RET_FAULTED; + } else { +- asm volatile ("sti"); +- return true; ++ asm volatile("sti; pushf; pop %[flags]" ++ : [flags] "=rm" (flags)); ++ ++ /* X86_FLAGS_IF */ ++ if (irqs_off && (flags & (1 << 9))) ++ return RET_FAIL; ++ else ++ return RET_EMUL; + } + clearhandler(SIGSEGV); + } + +-static void expect_gp_sti(void) ++static void expect_gp_sti(bool irqs_off) + { +- if (try_sti()) { ++ int ret = try_sti(irqs_off); ++ ++ switch (ret) { ++ case RET_FAULTED: ++ printf("[OK]\tSTI faulted\n"); ++ break; ++ case RET_EMUL: ++ printf("[OK]\tSTI NOPped\n"); ++ break; ++ default: + printf("[FAIL]\tSTI worked\n"); + nerrs++; +- } else { +- printf("[OK]\tSTI faulted\n"); + } + } + +-static void expect_gp_cli(void) ++/* ++ * Returns whether it managed to disable interrupts. ++ */ ++static bool test_cli(void) + { +- if (try_cli()) { ++ int ret = try_cli(); ++ ++ switch (ret) { ++ case RET_FAULTED: ++ printf("[OK]\tCLI faulted\n"); ++ break; ++ case RET_EMUL: ++ printf("[OK]\tCLI NOPped\n"); ++ break; ++ default: + printf("[FAIL]\tCLI worked\n"); + nerrs++; +- } else { +- printf("[OK]\tCLI faulted\n"); ++ return true; + } ++ ++ return false; + } + + int main(void) +@@ -152,8 +192,7 @@ int main(void) + } + + /* Make sure that CLI/STI are blocked even with IOPL level 3 */ +- expect_gp_cli(); +- expect_gp_sti(); ++ expect_gp_sti(test_cli()); + expect_ok_outb(0x80); + + /* Establish an I/O bitmap to test the restore */ +@@ -204,8 +243,7 @@ int main(void) + printf("[RUN]\tparent: write to 0x80 (should fail)\n"); + + expect_gp_outb(0x80); +- expect_gp_cli(); +- expect_gp_sti(); ++ expect_gp_sti(test_cli()); + + /* Test the capability checks. */ + printf("\tiopl(3)\n"); +diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c +index 65c141ebfbbde..5b45e6986aeab 100644 +--- a/tools/testing/selftests/x86/test_vsyscall.c ++++ b/tools/testing/selftests/x86/test_vsyscall.c +@@ -497,7 +497,7 @@ static int test_process_vm_readv(void) + } + + if (vsyscall_map_r) { +- if (!memcmp(buf, (const void *)0xffffffffff600000, 4096)) { ++ if (!memcmp(buf, remote.iov_base, sizeof(buf))) { + printf("[OK]\tIt worked and read correct data\n"); + } else { + printf("[FAIL]\tIt worked but returned incorrect data\n"); +diff --git a/tools/testing/selftests/zram/zram.sh b/tools/testing/selftests/zram/zram.sh +index 232e958ec4547..b0b91d9b0dc21 100755 +--- a/tools/testing/selftests/zram/zram.sh ++++ b/tools/testing/selftests/zram/zram.sh +@@ -2,9 +2,6 @@ + # SPDX-License-Identifier: GPL-2.0 + TCID="zram.sh" + +-# Kselftest framework requirement - SKIP code is 4. +-ksft_skip=4 +- + . ./zram_lib.sh + + run_zram () { +@@ -18,14 +15,4 @@ echo "" + + check_prereqs + +-# check zram module exists +-MODULE_PATH=/lib/modules/`uname -r`/kernel/drivers/block/zram/zram.ko +-if [ -f $MODULE_PATH ]; then +- run_zram +-elif [ -b /dev/zram0 ]; then +- run_zram +-else +- echo "$TCID : No zram.ko module or /dev/zram0 device file not found" +- echo "$TCID : CONFIG_ZRAM is not set" +- exit $ksft_skip +-fi ++run_zram +diff --git a/tools/testing/selftests/zram/zram01.sh b/tools/testing/selftests/zram/zram01.sh +index 114863d9fb876..8f4affe34f3e4 100755 +--- a/tools/testing/selftests/zram/zram01.sh ++++ b/tools/testing/selftests/zram/zram01.sh +@@ -33,9 +33,7 @@ zram_algs="lzo" + + zram_fill_fs() + { +- local mem_free0=$(free -m | awk 'NR==2 {print $4}') +- +- for i in $(seq 0 $(($dev_num - 1))); do ++ for i in $(seq $dev_start $dev_end); do + echo "fill zram$i..." + local b=0 + while [ true ]; do +@@ -45,29 +43,17 @@ zram_fill_fs() + b=$(($b + 1)) + done + echo "zram$i can be filled with '$b' KB" +- done + +- local mem_free1=$(free -m | awk 'NR==2 {print $4}') +- local used_mem=$(($mem_free0 - $mem_free1)) ++ local mem_used_total=`awk '{print $3}' "/sys/block/zram$i/mm_stat"` ++ local v=$((100 * 1024 * $b / $mem_used_total)) ++ if [ "$v" -lt 100 ]; then ++ echo "FAIL compression ratio: 0.$v:1" ++ ERR_CODE=-1 ++ return ++ fi + +- local total_size=0 +- for sm in $zram_sizes; do +- local s=$(echo $sm | sed 's/M//') +- total_size=$(($total_size + $s)) ++ echo "zram compression ratio: $(echo "scale=2; $v / 100 " | bc):1: OK" + done +- +- echo "zram used ${used_mem}M, zram disk sizes ${total_size}M" +- +- local v=$((100 * $total_size / $used_mem)) +- +- if [ "$v" -lt 100 ]; then +- echo "FAIL compression ratio: 0.$v:1" +- ERR_CODE=-1 +- zram_cleanup +- return +- fi +- +- echo "zram compression ratio: $(echo "scale=2; $v / 100 " | bc):1: OK" + } + + check_prereqs +@@ -81,7 +67,6 @@ zram_mount + + zram_fill_fs + zram_cleanup +-zram_unload + + if [ $ERR_CODE -ne 0 ]; then + echo "$TCID : [FAIL]" +diff --git a/tools/testing/selftests/zram/zram02.sh b/tools/testing/selftests/zram/zram02.sh +index e83b404807c09..2418b0c4ed136 100755 +--- a/tools/testing/selftests/zram/zram02.sh ++++ b/tools/testing/selftests/zram/zram02.sh +@@ -36,7 +36,6 @@ zram_set_memlimit + zram_makeswap + zram_swapoff + zram_cleanup +-zram_unload + + if [ $ERR_CODE -ne 0 ]; then + echo "$TCID : [FAIL]" +diff --git a/tools/testing/selftests/zram/zram_lib.sh b/tools/testing/selftests/zram/zram_lib.sh +index 6f872f266fd11..21ec1966de76c 100755 +--- a/tools/testing/selftests/zram/zram_lib.sh ++++ b/tools/testing/selftests/zram/zram_lib.sh +@@ -5,12 +5,17 @@ + # Author: Alexey Kodanev <alexey.kodanev@oracle.com> + # Modified: Naresh Kamboju <naresh.kamboju@linaro.org> + +-MODULE=0 + dev_makeswap=-1 + dev_mounted=-1 +- ++dev_start=0 ++dev_end=-1 ++module_load=-1 ++sys_control=-1 + # Kselftest framework requirement - SKIP code is 4. + ksft_skip=4 ++kernel_version=`uname -r | cut -d'.' -f1,2` ++kernel_major=${kernel_version%.*} ++kernel_minor=${kernel_version#*.} + + trap INT + +@@ -25,68 +30,104 @@ check_prereqs() + fi + } + ++kernel_gte() ++{ ++ major=${1%.*} ++ minor=${1#*.} ++ ++ if [ $kernel_major -gt $major ]; then ++ return 0 ++ elif [[ $kernel_major -eq $major && $kernel_minor -ge $minor ]]; then ++ return 0 ++ fi ++ ++ return 1 ++} ++ + zram_cleanup() + { + echo "zram cleanup" + local i= +- for i in $(seq 0 $dev_makeswap); do ++ for i in $(seq $dev_start $dev_makeswap); do + swapoff /dev/zram$i + done + +- for i in $(seq 0 $dev_mounted); do ++ for i in $(seq $dev_start $dev_mounted); do + umount /dev/zram$i + done + +- for i in $(seq 0 $(($dev_num - 1))); do ++ for i in $(seq $dev_start $dev_end); do + echo 1 > /sys/block/zram${i}/reset + rm -rf zram$i + done + +-} ++ if [ $sys_control -eq 1 ]; then ++ for i in $(seq $dev_start $dev_end); do ++ echo $i > /sys/class/zram-control/hot_remove ++ done ++ fi + +-zram_unload() +-{ +- if [ $MODULE -ne 0 ] ; then +- echo "zram rmmod zram" ++ if [ $module_load -eq 1 ]; then + rmmod zram > /dev/null 2>&1 + fi + } + + zram_load() + { +- # check zram module exists +- MODULE_PATH=/lib/modules/`uname -r`/kernel/drivers/block/zram/zram.ko +- if [ -f $MODULE_PATH ]; then +- MODULE=1 +- echo "create '$dev_num' zram device(s)" +- modprobe zram num_devices=$dev_num +- if [ $? -ne 0 ]; then +- echo "failed to insert zram module" +- exit 1 +- fi +- +- dev_num_created=$(ls /dev/zram* | wc -w) ++ echo "create '$dev_num' zram device(s)" ++ ++ # zram module loaded, new kernel ++ if [ -d "/sys/class/zram-control" ]; then ++ echo "zram modules already loaded, kernel supports" \ ++ "zram-control interface" ++ dev_start=$(ls /dev/zram* | wc -w) ++ dev_end=$(($dev_start + $dev_num - 1)) ++ sys_control=1 ++ ++ for i in $(seq $dev_start $dev_end); do ++ cat /sys/class/zram-control/hot_add > /dev/null ++ done ++ ++ echo "all zram devices (/dev/zram$dev_start~$dev_end" \ ++ "successfully created" ++ return 0 ++ fi + +- if [ "$dev_num_created" -ne "$dev_num" ]; then +- echo "unexpected num of devices: $dev_num_created" +- ERR_CODE=-1 ++ # detect old kernel or built-in ++ modprobe zram num_devices=$dev_num ++ if [ ! -d "/sys/class/zram-control" ]; then ++ if grep -q '^zram' /proc/modules; then ++ rmmod zram > /dev/null 2>&1 ++ if [ $? -ne 0 ]; then ++ echo "zram module is being used on old kernel" \ ++ "without zram-control interface" ++ exit $ksft_skip ++ fi + else +- echo "zram load module successful" ++ echo "test needs CONFIG_ZRAM=m on old kernel without" \ ++ "zram-control interface" ++ exit $ksft_skip + fi +- elif [ -b /dev/zram0 ]; then +- echo "/dev/zram0 device file found: OK" +- else +- echo "ERROR: No zram.ko module or no /dev/zram0 device found" +- echo "$TCID : CONFIG_ZRAM is not set" +- exit 1 ++ modprobe zram num_devices=$dev_num + fi ++ ++ module_load=1 ++ dev_end=$(($dev_num - 1)) ++ echo "all zram devices (/dev/zram0~$dev_end) successfully created" + } + + zram_max_streams() + { + echo "set max_comp_streams to zram device(s)" + +- local i=0 ++ kernel_gte 4.7 ++ if [ $? -eq 0 ]; then ++ echo "The device attribute max_comp_streams was"\ ++ "deprecated in 4.7" ++ return 0 ++ fi ++ ++ local i=$dev_start + for max_s in $zram_max_streams; do + local sys_path="/sys/block/zram${i}/max_comp_streams" + echo $max_s > $sys_path || \ +@@ -98,7 +139,7 @@ zram_max_streams() + echo "FAIL can't set max_streams '$max_s', get $max_stream" + + i=$(($i + 1)) +- echo "$sys_path = '$max_streams' ($i/$dev_num)" ++ echo "$sys_path = '$max_streams'" + done + + echo "zram max streams: OK" +@@ -108,15 +149,16 @@ zram_compress_alg() + { + echo "test that we can set compression algorithm" + +- local algs=$(cat /sys/block/zram0/comp_algorithm) ++ local i=$dev_start ++ local algs=$(cat /sys/block/zram${i}/comp_algorithm) + echo "supported algs: $algs" +- local i=0 ++ + for alg in $zram_algs; do + local sys_path="/sys/block/zram${i}/comp_algorithm" + echo "$alg" > $sys_path || \ + echo "FAIL can't set '$alg' to $sys_path" + i=$(($i + 1)) +- echo "$sys_path = '$alg' ($i/$dev_num)" ++ echo "$sys_path = '$alg'" + done + + echo "zram set compression algorithm: OK" +@@ -125,14 +167,14 @@ zram_compress_alg() + zram_set_disksizes() + { + echo "set disk size to zram device(s)" +- local i=0 ++ local i=$dev_start + for ds in $zram_sizes; do + local sys_path="/sys/block/zram${i}/disksize" + echo "$ds" > $sys_path || \ + echo "FAIL can't set '$ds' to $sys_path" + + i=$(($i + 1)) +- echo "$sys_path = '$ds' ($i/$dev_num)" ++ echo "$sys_path = '$ds'" + done + + echo "zram set disksizes: OK" +@@ -142,14 +184,14 @@ zram_set_memlimit() + { + echo "set memory limit to zram device(s)" + +- local i=0 ++ local i=$dev_start + for ds in $zram_mem_limits; do + local sys_path="/sys/block/zram${i}/mem_limit" + echo "$ds" > $sys_path || \ + echo "FAIL can't set '$ds' to $sys_path" + + i=$(($i + 1)) +- echo "$sys_path = '$ds' ($i/$dev_num)" ++ echo "$sys_path = '$ds'" + done + + echo "zram set memory limit: OK" +@@ -158,8 +200,8 @@ zram_set_memlimit() + zram_makeswap() + { + echo "make swap with zram device(s)" +- local i=0 +- for i in $(seq 0 $(($dev_num - 1))); do ++ local i=$dev_start ++ for i in $(seq $dev_start $dev_end); do + mkswap /dev/zram$i > err.log 2>&1 + if [ $? -ne 0 ]; then + cat err.log +@@ -182,7 +224,7 @@ zram_makeswap() + zram_swapoff() + { + local i= +- for i in $(seq 0 $dev_makeswap); do ++ for i in $(seq $dev_start $dev_end); do + swapoff /dev/zram$i > err.log 2>&1 + if [ $? -ne 0 ]; then + cat err.log +@@ -196,7 +238,7 @@ zram_swapoff() + + zram_makefs() + { +- local i=0 ++ local i=$dev_start + for fs in $zram_filesystems; do + # if requested fs not supported default it to ext2 + which mkfs.$fs > /dev/null 2>&1 || fs=ext2 +@@ -215,7 +257,7 @@ zram_makefs() + zram_mount() + { + local i=0 +- for i in $(seq 0 $(($dev_num - 1))); do ++ for i in $(seq $dev_start $dev_end); do + echo "mount /dev/zram$i" + mkdir zram$i + mount /dev/zram$i zram$i > /dev/null || \ +diff --git a/tools/tracing/latency/latency-collector.c b/tools/tracing/latency/latency-collector.c +index 3a2e6bb781a8c..59a7f2346eab4 100644 +--- a/tools/tracing/latency/latency-collector.c ++++ b/tools/tracing/latency/latency-collector.c +@@ -1538,7 +1538,7 @@ static void tracing_loop(void) + mutex_lock(&print_mtx); + check_signals(); + write_or_die(fd_stdout, queue_full_warning, +- sizeof(queue_full_warning)); ++ strlen(queue_full_warning)); + mutex_unlock(&print_mtx); + } + modified--; +diff --git a/usr/include/Makefile b/usr/include/Makefile +index 1c2ae1368079d..adc6cb2587369 100644 +--- a/usr/include/Makefile ++++ b/usr/include/Makefile +@@ -28,13 +28,13 @@ no-header-test += linux/am437x-vpfe.h + no-header-test += linux/android/binder.h + no-header-test += linux/android/binderfs.h + no-header-test += linux/coda.h ++no-header-test += linux/cyclades.h + no-header-test += linux/errqueue.h + no-header-test += linux/fsmap.h + no-header-test += linux/hdlc/ioctl.h + no-header-test += linux/ivtv.h + no-header-test += linux/kexec.h + no-header-test += linux/matroxfb.h +-no-header-test += linux/nfc.h + no-header-test += linux/omap3isp.h + no-header-test += linux/omapfb.h + no-header-test += linux/patchkey.h +diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c +index e996989cd580e..5b874e7ba36fd 100644 +--- a/virt/kvm/eventfd.c ++++ b/virt/kvm/eventfd.c +@@ -456,8 +456,8 @@ bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) + idx = srcu_read_lock(&kvm->irq_srcu); + gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); + if (gsi != -1) +- hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, +- link) ++ hlist_for_each_entry_srcu(kian, &kvm->irq_ack_notifier_list, ++ link, srcu_read_lock_held(&kvm->irq_srcu)) + if (kian->gsi == gsi) { + srcu_read_unlock(&kvm->irq_srcu, idx); + return true; +@@ -473,8 +473,8 @@ void kvm_notify_acked_gsi(struct kvm *kvm, int gsi) + { + struct kvm_irq_ack_notifier *kian; + +- hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, +- link) ++ hlist_for_each_entry_srcu(kian, &kvm->irq_ack_notifier_list, ++ link, srcu_read_lock_held(&kvm->irq_srcu)) + if (kian->gsi == gsi) + kian->irq_acked(kian); + } +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 7851f3a1b5f7c..f8b42e19bc775 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1523,11 +1523,10 @@ static struct kvm_memslots *kvm_dup_memslots(struct kvm_memslots *old, + + static int kvm_set_memslot(struct kvm *kvm, + const struct kvm_userspace_memory_region *mem, +- struct kvm_memory_slot *old, + struct kvm_memory_slot *new, int as_id, + enum kvm_mr_change change) + { +- struct kvm_memory_slot *slot; ++ struct kvm_memory_slot *slot, old; + struct kvm_memslots *slots; + int r; + +@@ -1558,7 +1557,7 @@ static int kvm_set_memslot(struct kvm *kvm, + * Note, the INVALID flag needs to be in the appropriate entry + * in the freshly allocated memslots, not in @old or @new. + */ +- slot = id_to_memslot(slots, old->id); ++ slot = id_to_memslot(slots, new->id); + slot->flags |= KVM_MEMSLOT_INVALID; + + /* +@@ -1589,6 +1588,26 @@ static int kvm_set_memslot(struct kvm *kvm, + kvm_copy_memslots(slots, __kvm_memslots(kvm, as_id)); + } + ++ /* ++ * Make a full copy of the old memslot, the pointer will become stale ++ * when the memslots are re-sorted by update_memslots(), and the old ++ * memslot needs to be referenced after calling update_memslots(), e.g. ++ * to free its resources and for arch specific behavior. This needs to ++ * happen *after* (re)acquiring slots_arch_lock. ++ */ ++ slot = id_to_memslot(slots, new->id); ++ if (slot) { ++ old = *slot; ++ } else { ++ WARN_ON_ONCE(change != KVM_MR_CREATE); ++ memset(&old, 0, sizeof(old)); ++ old.id = new->id; ++ old.as_id = as_id; ++ } ++ ++ /* Copy the arch-specific data, again after (re)acquiring slots_arch_lock. */ ++ memcpy(&new->arch, &old.arch, sizeof(old.arch)); ++ + r = kvm_arch_prepare_memory_region(kvm, new, mem, change); + if (r) + goto out_slots; +@@ -1596,14 +1615,18 @@ static int kvm_set_memslot(struct kvm *kvm, + update_memslots(slots, new, change); + slots = install_new_memslots(kvm, as_id, slots); + +- kvm_arch_commit_memory_region(kvm, mem, old, new, change); ++ kvm_arch_commit_memory_region(kvm, mem, &old, new, change); ++ ++ /* Free the old memslot's metadata. Note, this is the full copy!!! */ ++ if (change == KVM_MR_DELETE) ++ kvm_free_memslot(kvm, &old); + + kvfree(slots); + return 0; + + out_slots: + if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) { +- slot = id_to_memslot(slots, old->id); ++ slot = id_to_memslot(slots, new->id); + slot->flags &= ~KVM_MEMSLOT_INVALID; + slots = install_new_memslots(kvm, as_id, slots); + } else { +@@ -1618,7 +1641,6 @@ static int kvm_delete_memslot(struct kvm *kvm, + struct kvm_memory_slot *old, int as_id) + { + struct kvm_memory_slot new; +- int r; + + if (!old->npages) + return -EINVAL; +@@ -1631,12 +1653,7 @@ static int kvm_delete_memslot(struct kvm *kvm, + */ + new.as_id = as_id; + +- r = kvm_set_memslot(kvm, mem, old, &new, as_id, KVM_MR_DELETE); +- if (r) +- return r; +- +- kvm_free_memslot(kvm, old); +- return 0; ++ return kvm_set_memslot(kvm, mem, &new, as_id, KVM_MR_DELETE); + } + + /* +@@ -1664,7 +1681,8 @@ int __kvm_set_memory_region(struct kvm *kvm, + id = (u16)mem->slot; + + /* General sanity checks */ +- if (mem->memory_size & (PAGE_SIZE - 1)) ++ if ((mem->memory_size & (PAGE_SIZE - 1)) || ++ (mem->memory_size != (unsigned long)mem->memory_size)) + return -EINVAL; + if (mem->guest_phys_addr & (PAGE_SIZE - 1)) + return -EINVAL; +@@ -1710,7 +1728,6 @@ int __kvm_set_memory_region(struct kvm *kvm, + if (!old.npages) { + change = KVM_MR_CREATE; + new.dirty_bitmap = NULL; +- memset(&new.arch, 0, sizeof(new.arch)); + } else { /* Modify an existing slot. */ + if ((new.userspace_addr != old.userspace_addr) || + (new.npages != old.npages) || +@@ -1724,9 +1741,8 @@ int __kvm_set_memory_region(struct kvm *kvm, + else /* Nothing to change. */ + return 0; + +- /* Copy dirty_bitmap and arch from the current memslot. */ ++ /* Copy dirty_bitmap from the current memslot. */ + new.dirty_bitmap = old.dirty_bitmap; +- memcpy(&new.arch, &old.arch, sizeof(new.arch)); + } + + if ((change == KVM_MR_CREATE) || (change == KVM_MR_MOVE)) { +@@ -1752,7 +1768,7 @@ int __kvm_set_memory_region(struct kvm *kvm, + bitmap_set(new.dirty_bitmap, 0, new.npages); + } + +- r = kvm_set_memslot(kvm, mem, &old, &new, as_id, change); ++ r = kvm_set_memslot(kvm, mem, &new, as_id, change); + if (r) + goto out_bitmap; + +@@ -2088,7 +2104,6 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn + + return NULL; + } +-EXPORT_SYMBOL_GPL(kvm_vcpu_gfn_to_memslot); + + bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) + { +@@ -2985,7 +3000,8 @@ int kvm_write_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, + int r; + gpa_t gpa = ghc->gpa + offset; + +- BUG_ON(len + offset > ghc->len); ++ if (WARN_ON_ONCE(len + offset > ghc->len)) ++ return -EINVAL; + + if (slots->generation != ghc->generation) { + if (__kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len)) +@@ -3022,7 +3038,8 @@ int kvm_read_guest_offset_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, + int r; + gpa_t gpa = ghc->gpa + offset; + +- BUG_ON(len + offset > ghc->len); ++ if (WARN_ON_ONCE(len + offset > ghc->len)) ++ return -EINVAL; + + if (slots->generation != ghc->generation) { + if (__kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len)) +@@ -3205,6 +3222,7 @@ update_halt_poll_stats(struct kvm_vcpu *vcpu, u64 poll_ns, bool waited) + */ + void kvm_vcpu_block(struct kvm_vcpu *vcpu) + { ++ bool halt_poll_allowed = !kvm_arch_no_poll(vcpu); + ktime_t start, cur, poll_end; + bool waited = false; + u64 block_ns; +@@ -3212,7 +3230,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) + kvm_arch_vcpu_blocking(vcpu); + + start = cur = poll_end = ktime_get(); +- if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) { ++ if (vcpu->halt_poll_ns && halt_poll_allowed) { + ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns); + + ++vcpu->stat.generic.halt_attempted_poll; +@@ -3267,7 +3285,7 @@ out: + update_halt_poll_stats( + vcpu, ktime_to_ns(ktime_sub(poll_end, start)), waited); + +- if (!kvm_arch_no_poll(vcpu)) { ++ if (halt_poll_allowed) { + if (!vcpu_valid_wakeup(vcpu)) { + shrink_halt_poll_ns(vcpu); + } else if (vcpu->kvm->max_halt_poll_ns) { diff --git a/system/easy-kernel/0200-x86-compile.patch b/system/easy-kernel/0200-x86-compile.patch new file mode 100644 index 000000000..1d2d7d4ad --- /dev/null +++ b/system/easy-kernel/0200-x86-compile.patch @@ -0,0 +1,11 @@ +--- linux-5.15.8.old/arch/x86/Kconfig ++++ linux-5.15.8/arch/x86/Kconfig +@@ -237,7 +237,7 @@ + select HAVE_FUNCTION_ARG_ACCESS_API + select HAVE_SOFTIRQ_ON_OWN_STACK + select HAVE_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR +- select HAVE_STACK_VALIDATION if X86_64 ++# select HAVE_STACK_VALIDATION if X86_64 + select HAVE_STATIC_CALL + select HAVE_STATIC_CALL_INLINE if HAVE_STACK_VALIDATION + select HAVE_PREEMPT_DYNAMIC diff --git a/system/easy-kernel/0250-projectc-5.15-r1.patch b/system/easy-kernel/0250-projectc-5.15-r1.patch index 3a3bf7420..c67c2c9fc 100644 --- a/system/easy-kernel/0250-projectc-5.15-r1.patch +++ b/system/easy-kernel/0250-projectc-5.15-r1.patch @@ -9157,7 +9157,7 @@ diff -urN linux-5.15.3/kernel/sched/cputime.c linux-prjc-v5.15-prjc-r1/kernel/sc /* Add guest time to cpustat. */ - if (task_nice(p) > 0) { + if (task_running_nice(p)) { - cpustat[CPUTIME_NICE] += cputime; + task_group_account_field(p, CPUTIME_NICE, cputime); cpustat[CPUTIME_GUEST_NICE] += cputime; } else { @@ -270,7 +270,7 @@ diff --git a/system/easy-kernel/1000-version.patch b/system/easy-kernel/1000-version.patch index 18de49341..4ac6ecdca 100644 --- a/system/easy-kernel/1000-version.patch +++ b/system/easy-kernel/1000-version.patch @@ -4,7 +4,7 @@ diff -Naur linux-5.15-stock/Makefile linux-5.15-branded/Makefile @@ -2,8 +2,8 @@ VERSION = 5 PATCHLEVEL = 15 - SUBLEVEL = 11 + SUBLEVEL = 28 -EXTRAVERSION = -NAME = Trick or Treat +EXTRAVERSION = -mc1 diff --git a/system/easy-kernel/APKBUILD b/system/easy-kernel/APKBUILD index cc2ff00d7..0c8c8a859 100644 --- a/system/easy-kernel/APKBUILD +++ b/system/easy-kernel/APKBUILD @@ -4,7 +4,7 @@ _kflavour="" _patchver=1 # must match 1000-version.patch ??? _pkgname=easy-kernel$_kflavour -pkgver=5.15.11 +pkgver=5.15.28 pkgrel=0 pkgname=$_pkgname-$pkgver-mc$_patchver pkgdesc="The Linux kernel, packaged for your convenience" @@ -30,12 +30,13 @@ source="https://cdn.kernel.org/pub/linux/kernel/v${_pkgmajver}.x/linux-${_pkgmin config-sparc64 config-x86_64 - 0100-linux-5.15.11.patch + 0100-linux-5.15.28.patch 0120-XATTR_USER_PREFIX.patch 0122-link-security-restrictions.patch 0124-bluetooth-keysize-check.patch 0126-sign-file-libressl.patch 0130-lrng.patch + 0200-x86-compile.patch 0250-projectc-5.15-r1.patch 0255-ultra-ksm.patch 0260-reduce-swappiness.patch @@ -134,22 +135,23 @@ sha512sums="d25ad40b5bcd6a4c6042fd0fd84e196e7a58024734c3e9a484fd0d5d54a0c1d87db8 93ca6d54fc377db12dfa7cf230d362f82d635cd05166815389ef4fb2b065f8b2bba1a78d234bd6a7445dd9b475f2c0ca01e3d4528881cfd2c10040dab174cf6a config-m68k 5945f918daf441e1f92012b608d560b693f09d8fa36eb6c7ecb9935dec6163c5e64e04d7345b3b9c958a15d62878f33ac88a4e24d5fcc60381455842636bd1c7 config-pmmx 3f9ac256e11b9e469086cbc0d3ec84e7bed4ec79fe40111418eb70786c9d62e8ef8d208472fa65f91b883b959112e40ace18d98314dfa9eeaace6aa821834f8b config-ppc -6a79665fbfbbb720d619c88d4145cb75b47b690aa5c341617651ebec3ece35f0bd5a53c7ea62b9be92e83f1cc43c781b3fac4c91ea860e725a2ab4ac0911a834 config-ppc64 +c6b7f7cb0c6a155465b2db849187a95ff1a31dd157699019a3f3f44e522c62c6e6ec29532b1b1b0c508142e32200a5611e3be3d44d6ea750883808ac6578401c config-ppc64 f43ae12574c81f6e0161c547eff93d70ff4686e6ec1654edbdea10447e424218a33b81c664828f82617e4ef522128f2e0460da0c9523538724048174b53a7313 config-sparc64 19e35f80a23ed08613d61d2a5df78257664c66f4fee84d9464ab8587b9e0845596e428bfb770c9b4254aef4bc33cbde8e9fb4a2fa7f591cfca083733717948e2 config-x86_64 -508045b7150e025dbf3682528b62ee6162e3bd1acf4ff4b53c3b395f14bff0bb4769c4d8e4ea30604785a79ebb66953c4576574e15d1a5ade1c482d4c191fdf8 0100-linux-5.15.11.patch +aa22c4a18ae302356010cac4f375feeb9ce1b6a13eeb7a5c98b3c2bebee7249154cfb747aa138440b60bc1b62a4329bd08c151e55cd318c788a267ef51cbb752 0100-linux-5.15.28.patch 3ed100909f9aed72836a3c712e45e0116cd3c4331961a76a27b867a7098d0df9458387b656c9ea01385c3c37585436e48168ac35666b0e46dca7da05e5e38a61 0120-XATTR_USER_PREFIX.patch c97a3799a2d5e4da9c9dfe129756da629fba8183479b02ca82f9b6d9993f17a165a96bd35ac50eb25fb293785b9b529a95165b1a2eb79c05134bee8ccf22a5d3 0122-link-security-restrictions.patch dc47b18749d95a456f8bc47fd6a0618c286b646b38466c3d950dfbeb25adf3fc1a794e95552e4da1abb58e49f0bd841f7222e71c4d04cb0264ca23476ca9caef 0124-bluetooth-keysize-check.patch 79eaf814d76402a445efc961666a7c7c74207e552b0cb32d93d5cb828da580f7dbe93509dc9f53321c7844663205a8dce4e518ba047e4c57fc55f5c3498088ec 0126-sign-file-libressl.patch 27b0a76966f5ea36217a1686e9504e5cf34a319d7036f856c94ddc22f5e737b3c49bf8cc50508c20f476c4b24607eba194305d7073c50faad00046b0d72350a1 0130-lrng.patch -c7760c874532a3268353bfc87977cfe8a58ae7dde85809c6dae2190a458c752401f8faf4119723b5583fb4f1834b34c278826b23c29c03412f7db431e6f2b20e 0250-projectc-5.15-r1.patch +16b8b8333fe89a68bc7f9a49b1bae263ab830692c12981640ac3dd9a0fb687f90b53783be05d47e5b38759ace4d99e82b59edd537a85a7ee27e21e65bbfa40a6 0200-x86-compile.patch +3cc9156e321f6b20d8adcc7c3baeb27f1f4b2d91b514b241244b93ea69b5b54e2055fe0365f25db17033bdae38dddbb029378b40032992fda6534004893a1b31 0250-projectc-5.15-r1.patch 4c901fe38e197b0397702ec46329fac6cdd5b7ff6e2601f76f0cbabcf452581936c58028c3a93471782541ad3045b10d1030fad4b25121f35d091495d17fd308 0255-ultra-ksm.patch 5f74e6a72876d3cf3b3188a43b999b981b6ea0ca401ad72b3c7d5cc65bf505f50e7ee17d435ec95b7a012dc92e6540aea1bdb501f48690c242705c47d2403513 0260-reduce-swappiness.patch 4e637935c2f37cc18f347293e3c94b18f90e2caccca726304a95c4891257a5b2bb3093aee7a97571038b29c0c987cc60a9a80aefd0d4c9a063b33d102f03579e 0300-tmp513-regression-fix.patch a43fd7004715f4efd545fe27abad46cc6f8c4c5f3ba9ab27c74a004e74bd5e4106beaecd54ca785fee03a0b466021acfdba0afa07e9ee2965493334a24403ffc 0500-print-fw-info.patch f0e532539e93d19fc65b417b4a0663e3757823340b968f63bd3a2665f99524feebb843ecf88ccf6909f93a8e7e9290721677c8f43bc3a2a37d99a51c1281a469 0502-gcc9-kcflags.patch -e48fdbae750c83aa64523e5f1e97f1969ec565946672ceff271ae12f099347556e421f6520ffab6d98363b11c46363de9707896197e792cf2b65a50bbb122503 1000-version.patch +dbf38da48cd5ddf287201c5537019e80a50ff5cef497c474324c634e140dc0106c394c5166747010914b11fc462e508a4ddda9b5b103de1f9a1d995fc9aafa4e 1000-version.patch 03a73db9eda84a52315499cb511f730946939d2de1b3aa52c60f9bd3a364377a65ddf2b62f505689a84d3e2f0fc7da5ca90429629d93d9909360ee0c3c599bbe no-require-gnu-tar.patch aadf8a3cc46a08e3a396ebd45656aee235103db7a2155cc6980df20b750151a9938b8b73c9319c6cd1b5f8aba6ce707f857a47dabf69df8d91dd93d440cffcb5 no-require-lilo.patch 7bb07eb22002cc48caf0cd55d17ce4097aa583e0ca4048c11c92e1519761b2ae982ffe98311543d4b0dfc991c8bc411b2e1c7be9488b6c6f19ffaa08e69e2f47 no-autoload-fb.conf" diff --git a/system/easy-kernel/config-ppc64 b/system/easy-kernel/config-ppc64 index d57e298cf..4a867ab81 100644 --- a/system/easy-kernel/config-ppc64 +++ b/system/easy-kernel/config-ppc64 @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/powerpc 5.15.11-mc1 Kernel Configuration +# Linux/powerpc 5.15.28-mc1 Kernel Configuration # CONFIG_CC_VERSION_TEXT="gcc (Adelie 8.3.0) 8.3.0" CONFIG_CC_IS_GCC=y @@ -1867,7 +1867,6 @@ CONFIG_OF_KOBJ=y CONFIG_OF_DYNAMIC=y CONFIG_OF_ADDRESS=y CONFIG_OF_IRQ=y -CONFIG_OF_NET=y CONFIG_OF_RESERVED_MEM=y # CONFIG_OF_OVERLAY is not set CONFIG_OF_DMA_DEFAULT_COHERENT=y @@ -4406,6 +4405,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y # CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set |